Repository navigation
feat(codemode): return logs and calls when a run is stopped - #59978
rekram1-node wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
The change works. I drove the TUI with the simulated model against both checkouts, running an execute (one console.log, then a fetch that never returns) alongside a foreground shell that prints two lines and then sleeps, and interrupted both.
- Base: both tool results in the next model request had
"content":[]. - This PR: the
executeresult carriesTool calls:\n- fetch: interrupted\n\nLogs:\nchecked the cache, and theshellresult carries the two printed lines plusInterrupted before completion. The error message is stillTool execution interrupted, and the TUI's execute row now shows the recorded content.
The core tests for execute, shell and session-runner pass. The new tests fail on the base, as they should. typecheck:tsc is clean in both packages.
Public API: @opencode/codemode gets an optional "execution.interrupted" hook on Hooks and a new exported InterruptedExecution type. The session.tool.failed event's existing optional content field is now filled in when an interrupted execute or shell call produced output. Both are additive and backwards compatible.
No blocking concerns.
Fixes #39565
There was a problem hiding this comment.
The only new commit raises the wait in the shell interrupt test helper from 10s to 20s for slow PowerShell starts on Windows. That still fits within the core test runner's 30s per-test timeout. Source code is unchanged, so my earlier verification and API notes still apply. No new concerns.
56ee1be to
692dc6b
Compare
There was a problem hiding this comment.
The reworked approach works for execute. I ran an execute in the TUI with the simulated model and interrupted it while a fetch was hanging. On the base the next model request carries content: []. With this PR it carries Execution was interrupted., the program's log line and the call list (fetch: interrupted), and the error is still Tool execution interrupted. The core session-runner, tool-execute and codemode tests and the codemode package tests pass, and typecheck:tsc is clean in both packages.
Public API (@opencode/codemode is published):
Runtime.execute(code, bindings?)→Runtime.execute(code, options?: RunOptions). This is not backwards compatible: callers that pass bindings as the second argument must switch to{ bindings }(see inline comment).- New: the
RunOptionstype (bindings,stop),stoponExecuteOptions, and theInterruptedvalue inDiagnosticKind(code that handles every kind may need a new case). session.tool.failednow fills its existing optionalcontentfield for interruptedexecutecalls, which is backwards compatible.
Since the shell part was dropped, an interrupted shell still loses its output. #39565 is no longer fixed by this PR, so the Fixes #39565 my first review added no longer applies.
packages/codemode/src/codemode.ts:148: This changes the publishedRuntime.executesignature from(code, bindings?)to(code, options?). TypeScript callers that pass bindings positionally will stop compiling, and JS callers will silently lose their bindings because the record is read asRunOptions. If that break isn't intended,stopcould go in a third argument (or both shapes could be accepted) so existing callers keep working. Otherwise it's worth calling out as a breaking change for the package.
692dc6b to
5ea1245
Compare
There was a problem hiding this comment.
My earlier point on the Runtime.execute signature is addressed: stop now goes in a new optional third argument, so execute(code, bindings) callers are unaffected. The stop signal works as described. The new codemode tests pass, and the two stop result tests fail on the base. Core's execute and codemode tests pass, and typecheck:tsc is clean in both packages.
Public API (@opencode/codemode), all additions and backwards compatible:
Runtime.execute(code, bindings?)→execute(code, bindings?, options?: RunOptions).- New
RunOptionstype withstop?: Effect<void>, also accepted byExecuteOptions. - New
"Interrupted"value inDiagnosticKind. Code that handles every kind may need a new case; nothing in this repository does.
No new concerns.




Part of #54222
Problem
When a Code Mode run is interrupted, the Effect just ends interrupted and returns nothing. The logs and the calls the program already made are thrown away, so a host has no way to show what ran before the stop.
Change
I added an optional
stopsignal. When it completes, the program is stopped the same way an interrupt stops it (running calls are interrupted and theirafterhooks seeinterrupted), and then the run returns its normalResultinstead of being interrupted:stopgoes in a new optional third argument (RunOptions), soruntime.execute(code, bindings)keeps its signature and existing callers don't change. Core compiles untouched.Interruptedis a newDiagnosticKind.maxOutputByteslike any other failure.stop, or a call that interrupts itself, still ends the run interrupted exactly as before.interpreter/execute.ts(araceFirstwithstop). The evaluator is untouched.I skipped the Visual section since this is a package API with nothing user-facing yet.
Out of scope
executetool tostopso the model sees the logs and calls after an interrupt. That's the follow-up.shelloutput on interrupt.Verification
From
packages/codemode:bun run script/sync-test262.ts ~/development/test262bun run typecheck: no type errorsbun run typecheck:tsc: cleanbun test: 14832 pass, 1678 skip, 0 failFrom
packages/core(no changes there):bun run typecheck: no type errorsbun run typecheck:tsc: cleanbun run script/test.ts test/tool-execute.test.ts test/codemode: 35 pass, 0 failFrom the repo root:
bun run checkpasses.New tests:
stopmid-program returnsInterruptedwith the log and both calls and the blocked call'safterhook seesinterrupted; logs of a stopped run are bounded; an outside interrupt or a self-interrupting call still ends interrupted withstopset; a program that finishes first returns its normal result. The twostopresult tests fail without the change.Added by the opencode bot (AI-generated).
Fixes #39565
Related: #54222, #39565
Public API: @opencode/codemode: adds optional
stop(RunOptions, third argument of Runtime.execute and on ExecuteOptions) and theInterrupteddiagnostic kind (backwards compatible)