From 441f5767c4fe4eebbec6ebe9bb4a57f430871eba Mon Sep 17 00:00:00 2001 From: David Brailovsky Date: Mon, 12 Oct 2026 16:06:29 +0200 Subject: [PATCH] fix(coding-agent): warn and exit non-zero in print mode on truncated response Print mode now writes a warning to stderr and exits 1 when the final response stopped at the model's output token limit. The partial text is still written to stdout. fixes #10799 --- packages/coding-agent/CHANGELOG.md | 1 + packages/coding-agent/docs/cli-integration.md | 2 +- packages/coding-agent/src/modes/print-mode.ts | 4 ++++ packages/coding-agent/test/print-mode.test.ts | 13 +++++++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index cfe30b837..82345c81f 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -30,6 +30,7 @@ - Fixed the code mode tool description claiming every failed tool call rejects; a tool that declares an output schema resolves with its value on failure too (e.g. `bash` with a nonzero exit) - Fixed runs started by `pi.sendMessage(..., { triggerTurn: true })` removing system prompt sections added in `before_agent_start` after their first tool call, which changed the prompt mid-run and broke the provider prompt cache twice per run ([#10267](https://github.com/earendil-works/pi/issues/10267)) - Fixed codemode blocking the process for seconds to minutes after scripts with many `text()` calls; joining the output items was quadratic ([#10678](https://github.com/earendil-works/pi/issues/10678)) +- Fixed print mode (`-p`) exiting 0 without a warning when the final response was cut off at the model's output token limit; it now prints the partial text, writes a warning to stderr, and exits 1 ([#10799](https://github.com/earendil-works/pi/issues/10799)) - Fixed `pi mcp login --help` and the CLI docs describing `--timeout` as only the wait for the browser; it limits the whole sign-in ([#10636](https://github.com/earendil-works/pi/issues/10636)) - Fixed `~` not being expanded in `!pattern`, `+path`, and `-path` entries of the `extensions`, `skills`, `prompts`, and `themes` settings, so entries like `!~/skills/pdf` matched nothing ([#10765](https://github.com/earendil-works/pi/issues/10765)) - Fixed MCP servers with resources registering no tools until every resource was listed; Pi no longer lists resources when connecting, so `/mcp` and `pi mcp list` show that a server offers resources instead of counting them ([#10526](https://github.com/earendil-works/pi/issues/10526)) diff --git a/packages/coding-agent/docs/cli-integration.md b/packages/coding-agent/docs/cli-integration.md index c01772b96..e0ab57f01 100644 --- a/packages/coding-agent/docs/cli-integration.md +++ b/packages/coding-agent/docs/cli-integration.md @@ -27,7 +27,7 @@ pi --print "Summarize the changes in this repository" Use print mode when only the final text is needed, including command substitution, pipelines, and one-shot jobs. Intermediate events are not exposed. -Print mode writes errors to stderr. A final assistant response with an `error` or `aborted` stop reason produces a nonzero exit status. +Print mode writes errors to stderr. A final assistant response with an `error` or `aborted` stop reason produces a nonzero exit status. A response cut off at the model's output token limit (`length` stop reason) still prints its partial text to stdout, writes a warning to stderr, and produces a nonzero exit status. When no mode is selected explicitly, non-TTY stdin or stdout also selects print mode. This allows piped input and output without adding `--print`. diff --git a/packages/coding-agent/src/modes/print-mode.ts b/packages/coding-agent/src/modes/print-mode.ts index 3f677eef6..6b932ac25 100644 --- a/packages/coding-agent/src/modes/print-mode.ts +++ b/packages/coding-agent/src/modes/print-mode.ts @@ -151,6 +151,10 @@ export async function runPrintMode(runtimeHost: AgentSessionRuntime, options: Pr writeRawStdout(`${content.text}\n`); } } + if (assistantMsg.stopReason === "length") { + console.error("Response was truncated: the model reached its output token limit."); + exitCode = 1; + } } } } diff --git a/packages/coding-agent/test/print-mode.test.ts b/packages/coding-agent/test/print-mode.test.ts index 32cec8e87..be41adb8f 100644 --- a/packages/coding-agent/test/print-mode.test.ts +++ b/packages/coding-agent/test/print-mode.test.ts @@ -139,4 +139,17 @@ describe("runPrintMode", () => { expect(session.extensionRunner.emit).toHaveBeenCalledTimes(1); expect(session.extensionRunner.emit).toHaveBeenCalledWith({ type: "session_shutdown", reason: "quit" }); }); + + // #10799 + it("warns on stderr and returns non-zero when the response was truncated", async () => { + const runtimeHost = createRuntimeHost(createAssistantMessage({ stopReason: "length" })); + const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); + + const exitCode = await runPrintMode(runtimeHost as unknown as Parameters[0], { + mode: "text", + }); + + expect(exitCode).toBe(1); + expect(errorSpy).toHaveBeenCalled(); + }); });