Fix Codex image generation tool timeout (#84369)

Summary:
- The branch gives Codex `image_generate` dynamic-tool calls a 120s default watchdog in main and side-thread paths and updates docs, tests, and changelog.
- Reproducibility: yes. Source inspection on current main shows unconfigured Codex `image_generate` calls fall ... -tool default, and the linked source PR includes live Gateway before/after output for the timeout behavior.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): address review for automerge-openclaw-openclaw-8425…
- PR branch already contained follow-up commit before automerge: Fix Codex image generation tool timeout

Validation:
- ClawSweeper review passed for head 10c7f87023.
- Required merge gates passed before the squash merge.

Prepared head SHA: 10c7f87023
Review: https://github.com/openclaw/openclaw/pull/84369#issuecomment-4493288493

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: moritzmmayerhofer <254141390+moritzmmayerhofer@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
This commit is contained in:
clawsweeper[bot]
2026-05-20 02:29:49 +00:00
committed by GitHub
parent a002c416c7
commit eb814b0216
8 changed files with 48 additions and 7 deletions

View File

@@ -12,6 +12,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Agents/code mode: spell out the `exec` tool's JavaScript/TypeScript, no Node module, and catalog-bridge constraints in model-visible schema text so agents can use enabled tools without trial-and-error. (#84269) Thanks @Kaspre.
- Codex: give `image_generate` dynamic-tool calls a 120s default watchdog when no per-call or configured image timeout is set, so image generation no longer falls back to the generic 30s bridge timeout. (#84254) Thanks @moritzmmayerhofer.
- CLI/message: include a stable top-level `messageId` in `openclaw message --json` output when channel sends return one. (#84191) Thanks @100menotu001.
- Gateway/agents: use an agent's `identity.name` in Gateway agent summaries when `agents.list[].name` is unset, so configured agent labels remain visible in clients. (#84355; refs #57835) Thanks @luoyanglang.
- Plugins/hooks: apply a default 30-second timeout to `before_compaction` and `after_compaction` hooks so a hung plugin handler no longer blocks compaction completion. (#84153)

View File

@@ -256,6 +256,8 @@ available timeout in this order:
- A positive per-call `timeoutMs` argument.
- For `image_generate`, `agents.defaults.imageGenerationModel.timeoutMs`.
- For `image_generate` without a configured timeout, the 120 second
image-generation default.
- For the media-understanding `image` tool, `tools.media.image.timeoutSeconds`
converted to milliseconds, or the 60 second media default.
- The 30 second dynamic-tool default.

View File

@@ -532,9 +532,10 @@ Supported `appServer` fields:
OpenClaw-owned dynamic tool calls are bounded independently from
`appServer.requestTimeoutMs`: Codex `item/tool/call` requests use a 30 second
OpenClaw watchdog by default. A positive per-call `timeoutMs` argument extends
or shortens that specific tool budget. The `image_generate` tool also uses
or shortens that specific tool budget. The `image_generate` tool uses
`agents.defaults.imageGenerationModel.timeoutMs` when the tool call does not
provide its own timeout, and the media-understanding `image` tool uses
provide its own timeout, or a 120 second image-generation default otherwise.
The media-understanding `image` tool uses
`tools.media.image.timeoutSeconds` or its 60 second media default. Dynamic tool
budgets are capped at 600000 ms. On timeout, OpenClaw aborts the tool signal
where supported and returns a failed dynamic-tool response to Codex so the turn

View File

@@ -237,8 +237,9 @@ from each attempt.
backends. A per-call `timeoutMs` tool parameter overrides the configured
default. Google, OpenRouter, and xAI hosted image providers use 180 second
defaults; Azure OpenAI image generation uses 600 seconds. Codex dynamic-tool
calls honor the same timeout budget, bounded by OpenClaw's 600000 ms
dynamic-tool bridge maximum.
calls use a 120 second `image_generate` bridge default and honor the same
timeout budget when configured, bounded by OpenClaw's 600000 ms dynamic-tool
bridge maximum.
</Accordion>
<Accordion title="Inspect at runtime">
Use `action: "list"` to inspect the currently registered providers,

View File

@@ -1903,6 +1903,22 @@ describe("runCodexAppServerAttempt", () => {
).toBe(180_000);
});
it("uses a 120 second default for Codex image generation dynamic tool calls", () => {
expect(
testing.resolveDynamicToolCallTimeoutMs({
call: {
threadId: "thread-1",
turnId: "turn-1",
callId: "call-image-generate-default",
namespace: null,
tool: "image_generate",
arguments: { prompt: "cat" },
},
config: undefined,
}),
).toBe(120_000);
});
it("uses the media image timeout for Codex image dynamic tool calls", () => {
expect(
testing.resolveDynamicToolCallTimeoutMs({

View File

@@ -181,6 +181,7 @@ import { filterToolsForVisionInputs } from "./vision-tools.js";
const CODEX_DYNAMIC_TOOL_TIMEOUT_MS = 30_000;
const CODEX_DYNAMIC_TOOL_MAX_TIMEOUT_MS = 600_000;
const CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS = 120_000;
const CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS = 60_000;
const CODEX_APP_SERVER_STARTUP_CONNECTION_CLOSE_MAX_ATTEMPTS = 3;
const CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS = 100;
@@ -3020,9 +3021,12 @@ function readConfiguredDynamicToolTimeoutMs(
if (toolName === "image_generate") {
const imageGenerationModel = config?.agents?.defaults?.imageGenerationModel;
if (!imageGenerationModel || typeof imageGenerationModel !== "object") {
return undefined;
return CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS;
}
return readPositiveFiniteTimeoutMs(imageGenerationModel.timeoutMs);
return (
readPositiveFiniteTimeoutMs(imageGenerationModel.timeoutMs) ??
CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS
);
}
if (toolName === "image") {

View File

@@ -1072,6 +1072,20 @@ describe("runCodexAppServerSideQuestion", () => {
expect(timeoutMs).toBe(123_456);
});
it("uses a 120 second default for side-thread image_generate calls", () => {
const timeoutMs = testing.resolveSideDynamicToolCallTimeoutMs({
call: {
threadId: "side-thread",
turnId: "turn-1",
callId: "tool-1",
tool: "image_generate",
},
config: {} as never,
});
expect(timeoutMs).toBe(120_000);
});
it("cleans up notification handlers when side tool setup fails", async () => {
const client = createFakeClient();
createOpenClawCodingToolsMock.mockImplementation(() => {

View File

@@ -66,6 +66,7 @@ import { filterToolsForVisionInputs } from "./vision-tools.js";
const CODEX_SIDE_DYNAMIC_TOOL_TIMEOUT_MS = 30_000;
const CODEX_SIDE_DYNAMIC_TOOL_MAX_TIMEOUT_MS = 600_000;
const CODEX_SIDE_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS = 120_000;
const CODEX_SIDE_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS = 60_000;
const SIDE_QUESTION_COMPLETION_TIMEOUT_MS = 600_000;
const CODEX_SIDE_NATIVE_HOOK_RELAY_MIN_TTL_MS = 30 * 60_000;
@@ -671,7 +672,8 @@ function resolveSideDynamicToolCallTimeoutMs(params: {
const configured =
readSideDynamicToolCallTimeoutMs(params.call.arguments) ??
(params.call.tool === "image_generate"
? readSideImageGenerationModelTimeoutMs(params.config)
? (readSideImageGenerationModelTimeoutMs(params.config) ??
CODEX_SIDE_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS)
: undefined) ??
(params.call.tool === "image"
? (readSideTimeoutSecondsAsMs(params.config?.tools?.media?.image?.timeoutSeconds) ??