fix(execution): opencode serve protocol — object-shaped model post + settled terminal stream - #85
Merged
Conversation
…settled terminal stream Found by the pacphi#76 three-host live smoke, where every opencode worker failed and the CLI then crashed: 1. prompt_async 400s: the adapter posted the configured model as a bare string, but opencode serve's schema expects {providerID, modelID} or null ("Expected object | null, got \"opencode/kimi-k3\" at [\"model\"]" — verified against serve 1.18.8). provider/model strings are now split on the first slash into the schema object (model ids may contain slashes); a model with no provider prefix is omitted so the server's own configured default applies — never a guessed provider. 2. Process crash after the failure verdict: when the prompt post threw, launch() stopped the owned server but left the terminal SSE promise unconsumed; its socket-close rejection surfaced as an unhandled rejection (TypeError: terminated, UND_ERR_SOCKET) that killed node AFTER the run verdict had printed. A no-op second consumer is attached at creation — observe() still sees genuine terminal rejections. Regression tests: serve-shaped model posts (incl. slash-containing model ids and the bare-id omission), and a 400-prompt teardown asserting no unhandled rejection while the owned server still receives SIGTERM. Verified end-to-end: with this fix, the opencode leg of the pacphi#76 smoke completes — ak run feature with all four workers routed to opencode (kimi-k3) succeeded, produced the sandboxed repo mutation, and emitted normalized terminal evidence (observed model, provider, durations).
This was referenced Jul 29, 2026
This was referenced Jul 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two bugs in the opencode execution adapter, found by the #76 three-host live smoke where the opencode leg could not be exercised:
Every configured-model worker 400'd. The adapter posted
modelas a bare string toPOST /session/:id/prompt_async, but opencode serve's schema expects{providerID, modelID}ornull:provider/modelstrings are now split on the first slash into the schema object (model ids may contain slashes); a model with no provider prefix is omitted so the server's own configured default applies.The CLI crashed after printing the failure verdict. When the prompt post threw,
launch()stopped the owned server but left the terminal SSE promise unconsumed; its socket-close rejection surfaced as an unhandled rejection (TypeError: terminated,UND_ERR_SOCKET) and killed the process after the run verdict. A no-op second consumer is attached at creation —observe()still sees genuine terminal rejections; the owned server still gets SIGTERM.Verification
openrouter/z-ai/glm-5.2, and the bare-id omission), and a 400-prompt teardown asserting no unhandled rejection while the owned server still receives SIGTERM.pnpm run checkexit 0 (1049 kit + 222 cjs tests),pnpm run test:surfaceexit 0 (25).ak run featurewith all four workers routed to opencode (kimi-k3) succeeded end-to-end, produced the sandboxed repository mutation (hello.mjs+tests/), and emitted normalized terminal evidence (observed modelkimi-k3, provideropencode, per-worker durations). Smoke detail posted on feat: generalize host routing and add OpenCode as a routable execution host #76.Refs #76