diff --git a/CHANGELOG.md b/CHANGELOG.md index 02bd6a3d3ca..dfe9aada861 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Docs: https://docs.openclaw.ai ### Fixes - Gateway/models: move local-provider pricing opt-outs, OpenRouter/LiteLLM aliases, and proxy passthrough pricing lookup into plugin manifest metadata so core no longer carries extension-specific pricing tables. Thanks @codex. +- Agents/Claude CLI: force live-session launches to include `--output-format stream-json` whenever OpenClaw adds `--input-format stream-json`, so new Claude CLI sessions no longer fail immediately while reusable sessions keep working. Fixes #72206. Thanks @kwangwonkoh and @Xivi08. - CLI/plugins: accept ClawHub plugin API wildcard ranges such as `*` without rejecting compatible plugin installs, while still requiring a valid runtime API version. Fixes #56446; supersedes #56466. Thanks @darconada and @claygeo. - Agents/sessions: acquire the session write lock only after cold bootstrap, plugin, and tool setup so fallback runs are not blocked by stalled pre-model startup work. Thanks @codex. - Browser/plugins: auto-start the bundled browser plugin when root `browser` config is present, including restrictive plugin allowlists, and ignore stale persisted plugin registries whose package paths no longer exist. Thanks @codex. diff --git a/src/agents/cli-runner.spawn.test.ts b/src/agents/cli-runner.spawn.test.ts index d7facd9e57d..db147457fa6 100644 --- a/src/agents/cli-runner.spawn.test.ts +++ b/src/agents/cli-runner.spawn.test.ts @@ -786,14 +786,7 @@ describe("runCliAgent spawn path", () => { runId: "run-live-1", prompt: "first", backend: { - args: [ - "-p", - "--output-format", - "stream-json", - "--strict-mcp-config", - "--mcp-config", - "/tmp/mcp-one.json", - ], + args: ["-p", "--strict-mcp-config", "--mcp-config", "/tmp/mcp-one.json"], liveSession: "claude-stdio", }, mcpConfigHash: "same-mcp-config", @@ -806,14 +799,7 @@ describe("runCliAgent spawn path", () => { runId: "run-live-2", prompt: "second", backend: { - args: [ - "-p", - "--output-format", - "stream-json", - "--strict-mcp-config", - "--mcp-config", - "/tmp/mcp-two.json", - ], + args: ["-p", "--strict-mcp-config", "--mcp-config", "/tmp/mcp-two.json"], liveSession: "claude-stdio", }, mcpConfigHash: "same-mcp-config", @@ -829,6 +815,7 @@ describe("runCliAgent spawn path", () => { expect(supervisorSpawnMock).toHaveBeenCalledOnce(); expect(spawnInput.stdinMode).toBe("pipe-open"); expect(spawnInput.argv).toContain("--input-format"); + expect(spawnInput.argv).toContain("--output-format"); expect(spawnInput.argv).toContain("stream-json"); expect(spawnInput.argv).toContain("--replay-user-messages"); expect(spawnInput.argv).not.toContain("--session-id"); @@ -1214,6 +1201,36 @@ describe("runCliAgent spawn path", () => { expect(args).not.toContain("current prompt"); }); + it("adds Claude stream-json output format when building live session argv", () => { + const backend: PreparedCliRunContext["preparedBackend"]["backend"] = { + command: "claude", + args: ["-p"], + output: "jsonl", + input: "stdin", + sessionArg: "--session-id", + systemPromptArg: "--append-system-prompt", + systemPromptFileArg: "--append-system-prompt-file", + }; + + const args = buildClaudeLiveArgs({ + args: ["-p"], + backend, + systemPrompt: "current prompt", + useResume: false, + }); + + expect(args).toEqual( + expect.arrayContaining([ + "--input-format", + "stream-json", + "--output-format", + "stream-json", + "--permission-prompt-tool", + "stdio", + ]), + ); + }); + it("restarts Claude live sessions for env changes and fresh retries", async () => { const cancels: Array> = []; const turnResults = ["first-ok", "resume-ok", "env-ok", "fresh-ok"]; diff --git a/src/agents/cli-runner/claude-live-session.ts b/src/agents/cli-runner/claude-live-session.ts index c0975be3699..6b9fdfd0ded 100644 --- a/src/agents/cli-runner/claude-live-session.ts +++ b/src/agents/cli-runner/claude-live-session.ts @@ -147,8 +147,12 @@ export function buildClaudeLiveArgs(params: { return appendArg( upsertArgValue( upsertArgValue( - stripLiveProcessArgs(params.args, params.backend, params.useResume), - "--input-format", + upsertArgValue( + stripLiveProcessArgs(params.args, params.backend, params.useResume), + "--input-format", + "stream-json", + ), + "--output-format", "stream-json", ), "--permission-prompt-tool",