From 5ba92577c593c78c68896afa67c57e5e85f1034d Mon Sep 17 00:00:00 2001 From: Adam Weidman Date: Tue, 17 Mar 2026 15:06:10 -0400 Subject: [PATCH] fix(cli): revert breaking stream crash on limits to restore bot compatibility --- package-lock.json | 9 ++++-- .../nonInteractiveCli.test.ts.snap | 5 +-- packages/cli/src/nonInteractiveCli.test.ts | 2 +- packages/cli/src/nonInteractiveCli.ts | 32 ++++++++++++------- packages/core/src/agent/event-translator.ts | 4 +-- 5 files changed, 33 insertions(+), 19 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3757403f78..d31c0544f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -486,7 +486,8 @@ "version": "2.11.0", "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.11.0.tgz", "integrity": "sha512-sBXGT13cpmPR5BMgHE6UEEfEaShh5Ror6rfN3yEK5si7QVrtZg8LEPQb0VVhiLRUslD2yLnXtnRzG035J/mZXQ==", - "license": "(Apache-2.0 AND BSD-3-Clause)" + "license": "(Apache-2.0 AND BSD-3-Clause)", + "peer": true }, "node_modules/@bundled-es-modules/cookie": { "version": "2.0.1", @@ -1489,6 +1490,7 @@ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.4.tgz", "integrity": "sha512-GsFaMXCkMqkKIvwCQjCrwH+GHbPKBjhwo/8ZuUkWHqbI73Kky9I+pQltrlT0+MWpedCoosda53lgjYfyEPgxBg==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@grpc/proto-loader": "^0.7.13", "@js-sdsl/ordered-map": "^4.4.2" @@ -7411,7 +7413,8 @@ "version": "0.0.1581282", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1581282.tgz", "integrity": "sha512-nv7iKtNZQshSW2hKzYNr46nM/Cfh5SEvE2oV0/SEGgc9XupIY5ggf84Cz8eJIkBce7S3bmTAauFD6aysMpnqsQ==", - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/dezalgo": { "version": "1.0.4", @@ -16247,7 +16250,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, "license": "0BSD", "peer": true }, @@ -17865,6 +17867,7 @@ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.3.tgz", "integrity": "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" diff --git a/packages/cli/src/__snapshots__/nonInteractiveCli.test.ts.snap b/packages/cli/src/__snapshots__/nonInteractiveCli.test.ts.snap index c12b66fc61..be8ff60d59 100644 --- a/packages/cli/src/__snapshots__/nonInteractiveCli.test.ts.snap +++ b/packages/cli/src/__snapshots__/nonInteractiveCli.test.ts.snap @@ -10,8 +10,9 @@ exports[`runNonInteractive > should emit appropriate error event in streaming JS exports[`runNonInteractive > should emit appropriate error event in streaming JSON mode: 'max session turns' 1`] = ` "{"type":"init","timestamp":"","session_id":"test-session-id","model":"test-model"} {"type":"message","timestamp":"","role":"user","content":"Max turns test"} -{"type":"result","timestamp":"","status":"error","error":{"type":"FatalTurnLimitedError","message":"Reached max session turns for this session. Increase the number of turns by specifying maxSessionTurns in settings.json."},"stats":{"total_tokens":0,"input_tokens":0,"output_tokens":0,"cached":0,"input":0,"duration_ms":,"tool_calls":0,"models":{}}} -{"type":"result","timestamp":"","status":"error","error":{"type":"Error","message":"[API Error: process.exit(53) called]"},"stats":{"total_tokens":0,"input_tokens":0,"output_tokens":0,"cached":0,"input":0,"duration_ms":,"tool_calls":0,"models":{}}} +{"type":"error","timestamp":"","severity":"error","message":"Maximum session turns exceeded"} +{"type":"result","timestamp":"","status":"success","stats":{"total_tokens":0,"input_tokens":0,"output_tokens":0,"cached":0,"input":0,"duration_ms":,"tool_calls":0,"models":{}}} +{"type":"result","timestamp":"","status":"success","stats":{"total_tokens":0,"input_tokens":0,"output_tokens":0,"cached":0,"input":0,"duration_ms":,"tool_calls":0,"models":{}}} " `; diff --git a/packages/cli/src/nonInteractiveCli.test.ts b/packages/cli/src/nonInteractiveCli.test.ts index bfed46fe98..ea44b79aaf 100644 --- a/packages/cli/src/nonInteractiveCli.test.ts +++ b/packages/cli/src/nonInteractiveCli.test.ts @@ -627,7 +627,7 @@ describe('runNonInteractive', () => { input: 'Trigger loop', prompt_id: 'prompt-id-6', }), - ).rejects.toThrow('process.exit(53) called'); + ).resolves.toBeUndefined(); }); it('should preprocess @include commands before sending to the model', async () => { diff --git a/packages/cli/src/nonInteractiveCli.ts b/packages/cli/src/nonInteractiveCli.ts index 8056896015..6e7b977aa7 100644 --- a/packages/cli/src/nonInteractiveCli.ts +++ b/packages/cli/src/nonInteractiveCli.ts @@ -41,7 +41,6 @@ import { handleError, handleToolError, handleCancellationError, - handleMaxTurnsExceededError, } from './utils/errors.js'; import { TextOutput } from './ui/utils/textOutput.js'; @@ -400,6 +399,14 @@ export async function runNonInteractive({ event.content?.[0]?.type === 'text' ? event.content[0].text : 'Tool error'; + + if (event.data?.['errorType'] === ToolErrorType.STOP_EXECUTION) { + const stopMessage = `Agent execution stopped: ${errorMsg}`; + if (config.getOutputFormat() === OutputFormat.TEXT) { + process.stderr.write(`${stopMessage}\n`); + } + } + handleToolError( event.name, new Error(errorMsg), @@ -410,15 +417,6 @@ export async function runNonInteractive({ displayText, ); } - if ( - event.isError && - event.data?.['errorType'] === ToolErrorType.STOP_EXECUTION - ) { - const stopMessage = `Agent execution stopped: ${errorMsg}`; - if (config.getOutputFormat() === OutputFormat.TEXT) { - process.stderr.write(`${stopMessage}\n`); - } - } break; } case 'error': { @@ -443,7 +441,19 @@ export async function runNonInteractive({ if (event.reason === 'aborted') { handleCancellationError(config); } else if (event.reason === 'max_turns') { - handleMaxTurnsExceededError(config); + if (config.getOutputFormat() === OutputFormat.TEXT) { + process.stderr.write( + `[WARNING] Maximum session turns exceeded\n`, + ); + } + if (streamFormatter) { + streamFormatter.emitEvent({ + type: JsonStreamEventType.ERROR, + timestamp: new Date().toISOString(), + severity: 'error', + message: 'Maximum session turns exceeded', + }); + } } // Emit final result if (streamFormatter) { diff --git a/packages/core/src/agent/event-translator.ts b/packages/core/src/agent/event-translator.ts index 5a31e565c2..50ae6f7c71 100644 --- a/packages/core/src/agent/event-translator.ts +++ b/packages/core/src/agent/event-translator.ts @@ -191,8 +191,8 @@ export function translateEvent( out.push( makeEvent('error', state, { status: 'INTERNAL', - message: 'Loop detected', - fatal: true, + message: 'Loop detected, stopping execution', + fatal: false, }), ); out.push(