惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Blog — PlanetScale
Blog — PlanetScale
小众软件
小众软件
F
Fortinet All Blogs
博客园 - 叶小钗
博客园_首页
D
DataBreaches.Net
Apple Machine Learning Research
Apple Machine Learning Research
U
Unit 42
爱范儿
爱范儿
aimingoo的专栏
aimingoo的专栏
博客园 - Franky
Martin Fowler
Martin Fowler
酷 壳 – CoolShell
酷 壳 – CoolShell
The Cloudflare Blog
A
About on SuperTechFans
Google DeepMind News
Google DeepMind News
Microsoft Security Blog
Microsoft Security Blog
IT之家
IT之家
M
MIT News - Artificial intelligence
有赞技术团队
有赞技术团队
博客园 - 【当耐特】
S
SegmentFault 最新的问题
Hugging Face - Blog
Hugging Face - Blog

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix: avoid idle Codex hook relay subprocesses · openclaw/...
evgyur · 2026-05-17 · via Recent Commits to openclaw:main
Original file line numberDiff line numberDiff line change

@@ -20,6 +20,7 @@ Docs: https://docs.openclaw.ai

2020

- Agents/memory: explain that memory-triggered compaction exposes only `read` and append-only `write` when configured core tools are unavailable in `tools.allow` warnings. Fixes #82941. Thanks @galiniliev.

2121

- Agents/OpenAI: preserve deterministic tool payload ordering for prompt-cache reuse across OpenAI Responses and chat completions calls. (#82940) Thanks @galiniliev.

2222

- Agents/skills: apply the full effective tool policy pipeline to inline `command-dispatch: tool` skill dispatch before owner-only filtering, preserving configured allow, deny, sandbox, sender, group, and subagent restrictions. (#78525)

23+

- Codex: avoid spawning native hook relay subprocesses for post-tool/finalize events with no registered hook handlers while preserving pre-tool safety and approval relays. Fixes #76552. (#78004) Thanks @evgyur.

2324

- Channel accounts: keep top-level default channel accounts visible when named accounts are added alongside default credential material, so mixed legacy/new account configs keep resolving `default` instead of silently dropping it.

2425

- Codex/Telegram: synthesize native Codex tool progress from final turn snapshots so Telegram `/verbose` stays visible when command events arrive only at completion.

2526

- Mac app: make Channels settings open faster by deferring config-schema work, avoiding startup channel probes, caching decoded channel status rows, and showing only compact quick settings instead of the full generated channel schema.

Original file line numberDiff line numberDiff line change

@@ -146,6 +146,43 @@ describe("Codex native hook relay config", () => {

146146

});

147147

});

148148
149+

it("clears requested hook events when the relay reports no local work", () => {

150+

expect(

151+

buildCodexNativeHookRelayConfig({

152+

relay: createRelay({ inactiveEvents: ["post_tool_use", "before_agent_finalize"] }),

153+

events: ["pre_tool_use", "post_tool_use", "before_agent_finalize"],

154+

}),

155+

).toEqual({

156+

"features.hooks": true,

157+

"hooks.PreToolUse": [

158+

{

159+

hooks: [

160+

{

161+

type: "command",

162+

command:

163+

"openclaw hooks relay --provider codex --relay-id relay-1 --event pre_tool_use",

164+

timeout: 5,

165+

async: false,

166+

statusMessage: "OpenClaw native hook relay",

167+

},

168+

],

169+

},

170+

],

171+

"hooks.PostToolUse": [],

172+

"hooks.Stop": [],

173+

"hooks.state": {

174+

"/<session-flags>/config.toml:pre_tool_use:0:0": {

175+

enabled: true,

176+

trusted_hash: expect.stringMatching(/^sha256:[a-f0-9]{64}$/),

177+

},

178+

"<session-flags>/config.toml:pre_tool_use:0:0": {

179+

enabled: true,

180+

trusted_hash: expect.stringMatching(/^sha256:[a-f0-9]{64}$/),

181+

},

182+

},

183+

});

184+

});

185+
149186

it("omits matchers so Codex MCP tool names reach the relay with a stable trust hash", () => {

150187

const config = buildCodexNativeHookRelayConfig({

151188

relay: createRelay(),

@@ -171,7 +208,10 @@ describe("Codex native hook relay config", () => {

171208

});

172209

});

173210
174-

function createRelay(): NativeHookRelayRegistrationHandle {

211+

function createRelay(options?: {

212+

inactiveEvents?: readonly NativeHookRelayRegistrationHandle["allowedEvents"][number][];

213+

}): NativeHookRelayRegistrationHandle {

214+

const inactiveEvents = new Set(options?.inactiveEvents ?? []);

175215

return {

176216

relayId: "relay-1",

177217

provider: "codex",

@@ -180,6 +220,7 @@ function createRelay(): NativeHookRelayRegistrationHandle {

180220

runId: "run-1",

181221

allowedEvents: ["pre_tool_use", "post_tool_use", "permission_request", "before_agent_finalize"],

182222

expiresAtMs: Date.now() + 1000,

223+

shouldRelayEvent: (event) => !inactiveEvents.has(event),

183224

commandForEvent: (event) =>

184225

`openclaw hooks relay --provider codex --relay-id relay-1 --event ${event}`,

185226

renew: () => undefined,

Original file line numberDiff line numberDiff line change

@@ -45,6 +45,10 @@ export function buildCodexNativeHookRelayConfig(params: {

4545

const hookState: JsonObject = {};

4646

for (const event of events) {

4747

const codexEvent = CODEX_HOOK_EVENT_BY_NATIVE_EVENT[event];

48+

if (!params.relay.shouldRelayEvent(event)) {

49+

config[`hooks.${codexEvent}`] = [] satisfies JsonValue;

50+

continue;

51+

}

4852

const command = params.relay.commandForEvent(event);

4953

const timeout = normalizeHookTimeoutSec(params.hookTimeoutSec);

5054

config[`hooks.${codexEvent}`] = [

Original file line numberDiff line numberDiff line change

@@ -3928,8 +3928,8 @@ describe("runCodexAppServerAttempt", () => {

39283928

?.config;

39293929

expect(startConfig?.["features.hooks"]).toBe(true);

39303930

expect(Array.isArray(startConfig?.["hooks.PreToolUse"])).toBe(true);

3931-

expect(Array.isArray(startConfig?.["hooks.PostToolUse"])).toBe(true);

3932-

expect(Array.isArray(startConfig?.["hooks.Stop"])).toBe(true);

3931+

expect(startConfig?.["hooks.PostToolUse"]).toEqual([]);

3932+

expect(startConfig?.["hooks.Stop"]).toEqual([]);

39333933

expect(startConfig).not.toHaveProperty("hooks.PermissionRequest");

39343934

const relayId = extractRelayIdFromThreadRequest(startRequest?.params);

39353935

expect(

Original file line numberDiff line numberDiff line change

@@ -2062,7 +2062,8 @@ export async function runCodexAppServerAttempt(

20622062

});

20632063

projector = new CodexAppServerEventProjector(params, thread.threadId, activeTurnId, {

20642064

nativePostToolUseRelayEnabled:

2065-

nativeHookRelay?.allowedEvents.includes("post_tool_use") === true,

2065+

nativeHookRelay?.allowedEvents.includes("post_tool_use") === true &&

2066+

nativeHookRelay.shouldRelayEvent("post_tool_use"),

20662067

trajectoryRecorder,

20672068

});

20682069

if (

Original file line numberDiff line numberDiff line change

@@ -114,6 +114,70 @@ describe("native hook relay registry", () => {

114114

);

115115

});

116116
117+

it("preserves safety relays while marking hook-only events without handlers inactive", () => {

118+

const relay = registerNativeHookRelay({

119+

provider: "codex",

120+

sessionId: "session-1",

121+

runId: "run-1",

122+

command: {

123+

executable: "/opt/Open Claw/openclaw.mjs",

124+

nodeExecutable: "/usr/local/bin/node",

125+

timeoutMs: 1234,

126+

},

127+

});

128+
129+

expect(relay.shouldRelayEvent("pre_tool_use")).toBe(true);

130+

expect(relay.shouldRelayEvent("post_tool_use")).toBe(false);

131+

expect(relay.shouldRelayEvent("before_agent_finalize")).toBe(false);

132+

expect(relay.shouldRelayEvent("permission_request")).toBe(true);

133+

});

134+
135+

it("builds relay commands only for native events with matching local hooks", () => {

136+

initializeGlobalHookRunner(

137+

createMockPluginRegistry([{ hookName: "after_tool_call", handler: vi.fn() }]),

138+

);

139+

const relay = registerNativeHookRelay({

140+

provider: "codex",

141+

sessionId: "session-1",

142+

runId: "run-1",

143+

command: {

144+

executable: "/opt/Open Claw/openclaw.mjs",

145+

nodeExecutable: "/usr/local/bin/node",

146+

timeoutMs: 1234,

147+

},

148+

});

149+
150+

expect(relay.shouldRelayEvent("pre_tool_use")).toBe(true);

151+

expect(relay.shouldRelayEvent("post_tool_use")).toBe(true);

152+

expect(relay.shouldRelayEvent("before_agent_finalize")).toBe(false);

153+

expect(relay.commandForEvent("post_tool_use")).toBe(

154+

"/usr/local/bin/node '/opt/Open Claw/openclaw.mjs' hooks relay --provider codex --relay-id " +

155+

`${relay.relayId} --event post_tool_use --timeout 1234`,

156+

);

157+

});

158+
159+

it("builds relay commands for before-agent-finalize hooks", () => {

160+

initializeGlobalHookRunner(

161+

createMockPluginRegistry([{ hookName: "before_agent_finalize", handler: vi.fn() }]),

162+

);

163+

const relay = registerNativeHookRelay({

164+

provider: "codex",

165+

sessionId: "session-1",

166+

runId: "run-1",

167+

command: {

168+

executable: "/opt/Open Claw/openclaw.mjs",

169+

nodeExecutable: "/usr/local/bin/node",

170+

timeoutMs: 1234,

171+

},

172+

});

173+
174+

expect(relay.shouldRelayEvent("before_agent_finalize")).toBe(true);

175+

expect(relay.commandForEvent("before_agent_finalize")).toBe(

176+

"/usr/local/bin/node '/opt/Open Claw/openclaw.mjs' hooks relay --provider codex --relay-id " +

177+

`${relay.relayId} --event before_agent_finalize --timeout 1234`,

178+

);

179+

});

180+
117181

it("allows callers to replace a relay at a stable id", () => {

118182

const first = registerNativeHookRelay({

119183

provider: "codex",

Original file line numberDiff line numberDiff line change

@@ -13,6 +13,7 @@ import type { OpenClawConfig } from "../../config/types.openclaw.js";

1313

import { resolveOpenClawPackageRootSync } from "../../infra/openclaw-root.js";

1414

import { privateFileStoreSync } from "../../infra/private-file-store.js";

1515

import { createSubsystemLogger } from "../../logging/subsystem.js";

16+

import { hasGlobalHooks } from "../../plugins/hook-runner-global.js";

1617

import { PluginApprovalResolutions } from "../../plugins/types.js";

1718

import { runBeforeToolCallHook } from "../pi-tools.before-tool-call.js";

1819

import { normalizeToolName } from "../tool-policy.js";

@@ -82,6 +83,7 @@ export type NativeHookRelayRegistration = {

8283

};

8384
8485

export type NativeHookRelayRegistrationHandle = NativeHookRelayRegistration & {

86+

shouldRelayEvent: (event: NativeHookRelayEvent) => boolean;

8587

commandForEvent: (event: NativeHookRelayEvent) => string;

8688

renew: (ttlMs?: number) => void;

8789

unregister: () => void;

@@ -312,6 +314,7 @@ export function registerNativeHookRelay(

312314

registerNativeHookRelayBridge(registration);

313315

const handle: NativeHookRelayRegistrationHandle = {

314316

...registration,

317+

shouldRelayEvent: nativeHookRelayEventHasLocalWork,

315318

commandForEvent: (event) =>

316319

buildNativeHookRelayCommand({

317320

provider: params.provider,

@@ -386,6 +389,19 @@ export function buildNativeHookRelayCommand(params: {

386389

]);

387390

}

388391
392+

function nativeHookRelayEventHasLocalWork(event: NativeHookRelayEvent): boolean {

393+

if (event === "pre_tool_use") {

394+

return true;

395+

}

396+

if (event === "post_tool_use") {

397+

return hasGlobalHooks("after_tool_call");

398+

}

399+

if (event === "before_agent_finalize") {

400+

return hasGlobalHooks("before_agent_finalize");

401+

}

402+

return true;

403+

}

404+
389405

export async function invokeNativeHookRelay(

390406

params: InvokeNativeHookRelayParams,

391407

): Promise<NativeHookRelayProcessResponse> {