Conversation
…and OpenCode
- `CommandSpec::loopback_ports`: ports a provider process serves on loopback
that the SDK host must reach. `SshTransport` forwards each one with `ssh -L`
(and `ExitOnForwardFailure=yes`), so `OpenCode::serve()` runs on SSH targets.
Local execution ignores the field.
- Manual compaction for Codex (`thread/compact/start` on the app server) and
OpenCode (`/session/{id}/summarize` on `opencode serve`, which needs a pinned
model). Both report the manual compaction lifecycle like Claude.
- `TurnCapabilities::manual_compaction` states which adapters support it; the
retained driver's capability follows it instead of naming Claude alone.
- `is_manual_compaction_prompt` moves to `providers` so every adapter detects
the `/compact` invocation `CompactionInput` produces the same way.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
`thread/compact/start` answers with an empty result, so a retained connection had no turn id for the compaction and dropped every frame of it as uncorrelated: the invocation never finished. A manual compaction now adopts the turn id from `turn/started`. The fixture app server plays `thread/compact/start` exactly as codex app-server 0.159 does (empty result, `turn/started`, a `contextCompaction` item, `turn/completed`), with one-shot and retained coverage. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A compaction has no reply text by design; the empty-response warning only added noise to every /compact. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review follow-ups for SSH forwarding and native compaction: - Security: `opencode serve` runs with OPENCODE_SERVER_USERNAME/PASSWORD (password derived per process and port from a random SDK secret) and the HTTP bridge sends Basic credentials on every request, the readiness probe and the event stream. A forwarded or local loopback port no longer exposes an unauthenticated session API. - Codex: a manual compaction adopts `turn/started`'s turn id only from its own thread, ends when its `contextCompaction` item completes, and accepts the older `thread/compacted` for its own thread on a retained connection. - OpenCode: `session.compacted` ends a manual compaction successfully; an idle session that never confirmed it fails clearly instead of reporting "finished without producing a reply". - Compaction instructions: new `compaction_instructions` capability (Claude only). `RuntimeHandle::compact` and the Codex/OpenCode adapters refuse instructions instead of silently dropping them. - The empty-reply warning is skipped only for adapters that performed a native compaction; pi, Codex exec and OpenCode run still warn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Why
Temps Fleet is moving every turn — local, remote daemon and SSH, for every harness — onto this SDK so it can delete its own legacy drivers and Bun sidecar. Two gaps blocked that:
OpenCode::serve()could not run on anSshTransport: the client talks to the server on the SDK host's loopback, and the transport never forwarded the port.RuntimeHandle::compactonly worked for Claude, so Fleet still compacted Codex and OpenCode sessions through its legacy drivers.What
CommandSpec::loopback_ports— loopback ports a provider process serves that the SDK host must reach.SshTransport::spawnadds-L 127.0.0.1:<port>:127.0.0.1:<port>for each (withExitOnForwardFailure=yes, so a failed forward fails the connection instead of leaving the client unable to reach the server).opencode servedeclares its port. Local execution ignores the field./compactinvocation:thread/compact/startonce the thread is open instead ofturn/start, and finishes onthread/compacted(or thecontextCompactionitem /turn/completed)./session/{id}/summarizewith the pinned{providerID, modelID}instead of a message; the existing compaction-part /session.compacted/session.idlehandling reports the lifecycle. Without a pinned model the turn fails withInvalidRequest { field: "model" }.CompactionStarted/CompletedwithCompactionTrigger::Manual.TurnCapabilities::manual_compaction(serde-defaulted) — Claude, Codex app-server and OpenCode serve set it;RuntimeDriverCapabilities::manual_compactionfollows it instead ofprovider == Claude.is_manual_compaction_promptmoves from the Claude adapter toprovidersso all adapters detect the invocation the same way.Follow-up fixes on this branch
thread/compact/startanswers with an empty result, so a retained connection had no turn id for the compaction and dropped all of its frames as uncorrelated. A manual compaction now adopts the turn id fromturn/started.Testing
SshTransportforwards ports before the destination, only when requested.tests/codex_app_server.rs): the fixture app server now playsthread/compact/startexactly ascodex app-server0.159 does (captured from the real binary: empty result,turn/started,contextCompactionitem started/completed,turn/completed, nothread/compacted). Covered one-shot and on a retained connection after a normal turn — the retained case reproduced the hang before the fix.cargo fmt --check,cargo clippy --all-targets --all-features -D warnings,cargo test --locked --all-featuresall pass./compacton a Codex conversation with a retained app server completes and shrinks the context (7% → 2%); Claude turns run overSshTransportagainst a Docker sshd. OpenCode over SSH and OpenCode compaction are covered by unit tests only (no working OpenCode login on the test machine).🤖 Generated with Claude Code