Repository navigation
refactor(runtime): remove the opencode adapter and in-sandbox serve - #73
Open
FreshlyBrewedCode wants to merge 1 commit into
Open
FreshlyBrewedCode wants to merge 1 commit into
FreshlyBrewedCode wants to merge 1 commit into
Conversation
The ACP adapter is the only runtime now (ADR 0013 §1, §4, §6):
- delete `opencode-adapter.ts` (`opencode serve` in a local-process
sandbox, the free-port probe, `extractOpencodeSignal`) and
`lib/sandbox-config.ts` (the `opencode.json` write)
- drop `AgentAdapter.prepareWorkspace` and `StartRunOptions` /
`startTrackedRun`'s `prepareWorkspace`, with every caller
- drop `@tanstack/ai-opencode` and `-sandbox-local-process`; keep
`@tanstack/ai-sandbox`, which `@tanstack/ai-acp` imports at load time
- drop write-back's D16 stray-artifact cleanup (it also deleted any
top-level `data/`); `WriteBackFinished.cleanedArtifacts` becomes
optional for old logs, and the `.tanstack-projected-*` ignore goes
- the replay corpus is re-recorded through the ACP adapter for Claude
(haiku) and opencode (big-pickle) by `scripts/record-corpus.ts`;
lines are `{step, chunk, signal?}`, so replay yields the recorded
signals and knows no agent's event names
- `agent-step.ts`'s commentary describes the ACP cancel; it keeps
`abortableIterable`, which `return()` behind a pending `next()` still
needs
- a run yields once before its workflow, so the daemon's deferred
cancel of a reserved run lands before the first step; the
`prepareWorkspace` await used to provide that gap
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
FreshlyBrewedCode
added this pull request to stack #70
October 2, 2026 20:41
This was referenced Oct 2, 2026
This branch has not been deployed
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.
Removes the opencode-specific runtime, so the ACP adapter is the only runtime (ADR 0013 §1, §4, §6).
What changed
Removed
src/runtime/opencode-adapter.tsand its test:opencode servein alocalProcessSandbox, thefreePortprobe, andextractOpencodeSignal.src/lib/sandbox-config.tsand its test (writeHeadlessPermissions, theopencode.jsonwrite).AgentAdapter.prepareWorkspace,StartRunOptions.prepareWorkspaceandstartTrackedRun'sprepareWorkspace. Every caller goes with them: the CLI, the legacyPOST /api/runs{dir, clone}path, the no-op implementations in the ACP, replay and fake adapters, and the three tests that exercised preparation.@tanstack/ai-opencodeand@tanstack/ai-sandbox-local-process..tanstack-projected-and^data(/|$), so it also deleted any top-leveldata/the agent changed.WriteBackFinished.cleanedArtifactsbecomes optional so old logs still decode. New runs don't write it, and the SPA shows the "cleaned" row only when the list is non-empty. The.tanstack-projected-*gitignore entry is removed too. There was nodata/entry in.gitignore.Kept:
@tanstack/ai-sandbox.@tanstack/ai-acpdeclares it as a non-optional peer and needs it at runtime. Its rootindex.jsimportspermissions.js, which imports@tanstack/ai-sandbox, and the package exports nothing but.. Bun would auto-install the peer anyway, but it stays a direct dependency so that is visible.Replay corpus re-recorded through the ACP adapter
scripts/record-corpus.ts <agent> <model> <out>runse2e/implement-issue.ts(implement, fix, structured pr-metadata, write-back) for a fake issue ci(release): add GitHub Actions, semantic-release, and npm packaging #1, "add slugify". It runs against a throwaway clone of a local bare origin, with a fakeghonPATH. Each item the adapter yields goes through a newrecordingAdapter.{step, chunk}to{step, chunk, signal?}. Replay yields the recorded signal with its chunk, so it knows no agent's event names. Legacy lines carry nosignaland replay as chunks only.test/corpus/acp-claude-implement-issue.ndjson:claude/haiku, 385 lines, 195 KB. Signals: session id per step, usage, and pr-metadata's structured output (branchfactory/issue-1-add-slugify).test/corpus/acp-opencode-implement-issue.ndjson:opencode/opencode/big-pickle, 2113 lines, 765 KB. It is large mostly because of 1309 reasoning deltas. Branchfactory/issue-1-add-slugify-helper.replay/adapter.test.ts: block grouping, signal replay, and a record→load round trip.agent-step.usage.test.ts: the usage split, plus context/cost from a recorded step.e2e/implement-issue.test.ts: now runs once per agent.run-static-acp-replay, from the opencode recording, which has reasoning.events.test.ts: D3's evidence about opencode chunk shapes. Its verbatim-AgentChunkcheck now also covers the ACP files.web/lib/transcript.test.ts.agentStepContextTokens' legacy fallback test.run-static-corpus, used for the old-log fallback and runs ordering.agent-step.tssession/cancel, then a kill after a grace period and infinally.abortableIterablestays. The problem it solves is generic: an async generator'sreturn()queues behind a pendingnext(). The ACP adapter's generator waits on its incoming queue, so without the wrapper an interrupt would block until the agent's next session update. The abort that would release it fires only after that. The shutdown tests that use a never-yielding adapter also need it.AGENT_TEARDOWN_GRACE_MS(1 s) stays, unchanged. It boundssettledfor adapters that never tear down, which the shutdown tests use. Its comment is rewritten for ACP: teardown was measured at 13–70 ms, and an agent that ignores the cancel is killed by the adapter's own 2 s timer.Fix exposed by the removal. The daemon cancels a run that was still a reserved slot right after
startRunreturns. TheprepareWorkspaceawait used to give that cancel a moment to land before the workflow's first step. Without it,shutdown.test.tssaw anExecStartedbeforeRunCancelled.startRunnow yields once afterRunStartedand checkscancelledbefore callingworkflow.run.Also: the
sessionIddoc comment insrc/events.tsno longer mentionsopencode.session-id.Validation
bun run check: green, 451 tests.bun run test:e2e(vianix develop): 17/17 passed.docs/: no matches foropencode serve,freePort,ai-opencode,localProcessSandbox,writeHeadlessPermissions,opencode.jsonorprepareWorkspace..tanstack-projected-remains only in the historical event comment and fixture.factory serveon port 3066. It used a scratch project, a test db, and a local bare origin with HEAD onmain, and no write-back. Port 3005 was not touched.smokeworkflow, one run per agent, started concurrently withfactory start --agent … --watch. Both completed and editedmath.ts.M math.ts. There is noopencode.jsonand no.git/info/excludeentry.python3 -c 'time.sleep(90)'):cancelledand the runRunCancelled. 0 of 4 processes were alive 3 s later (claude-agent-acp, the claude binary, its shell, python).opencode acp, python).Deviations
data/pattern was the "data/ ignore", and it deleted real changes under a top-leveldata/.startRunyield-before-workflow fix described above.Closes #66
Part of #62
🤖 Generated with Claude Code