What's new in 0.9.0
The headline: opencode and any OpenAI-compatible client now get full session continuity with zero config. Before 0.9.0, every chat-completions request created a new amplifier session with a random sid; one opencode conversation fragmented into N session dirs. With 0.9.0, the amplifier session_id is derived from the client's session header (sent automatically by Vercel AI SDK), so one opencode conversation = one amplifier session — unified audit trail, persistent hook state across turns, append-mode events.jsonl.
Added
-
Chat-completions session resume via
X-Client-Session-Id/X-Session-Id. Server now uses a deterministichttp-<client_sid>as the amplifier session_id, auto-detects first-turn vs continuation by checking if the session state dir exists on disk, and passesis_resumedto the kernel resume mechanism (same primitiveamplifier-agent run --resumeuses). One client conversation = one amplifier session. (#71) -
X-Session-Idheader fallback — opencode and other Vercel AI SDK-based clients send this header automatically. amplifier-agent now recognizes it as a fallback forX-Client-Session-Id, so session-resume works out of the box for opencode with zero client config.X-Client-Session-Id(our amplifier-native convention) remains authoritative when both are present. (#72) -
Client-authoritative transcript reconciliation in
_reconciler.py. The chat-completions wire is stateless — clients send full history every turn. On divergence between stored and incoming, the client wins by fiat: we persist their view over ours without any rewind ceremony. (#71)
Changed
-
reconcile_client_historynow runs foundation's transcript-repair pass before persisting. Catches broken chat-completions clients (orphanedtool_usewithout pairedtool_result, ordering violations, incomplete assistant turns) that would otherwise cause Anthropic to reject the next LLM call with HTTP 400. Mirrors_runtime.py:_repair_loaded_transcript_if_neededfrom the CLI face. Healthy transcripts pass through unchanged (<10ms diagnostic). (#73) -
Workspace name is no longer suffixed with the client session id. Previously,
X-Client-Session-Id: abcwould route requests intoworkspaces/<base>-abc/. Now the workspace stays at<base>and per-client distinction is purely at the session_id level (workspaces/<base>/sessions/http-abc/). This keeps workspace-level hook state shared across all sessions of the same server process, where it belongs. (#72)
Wire protocol
Unchanged at 0.3.0. No wrapper bump. TypeScript wrapper stays at 0.7.0.
Backward compatibility
- Clients NOT sending
X-Client-Session-IdorX-Session-Id: behavior unchanged — random sid per turn, no resume. - Clients sending only
X-Client-Session-Id: behavior unchanged from PR #71. - Clients sending only
X-Session-Id(opencode default): NEW — gets full session continuity. - Clients sending both:
X-Client-Session-Idwins.
The wire format (request body, response body, headers) is unchanged. The only observable difference for existing clients is the on-disk workspace dir layout — workspace name is no longer suffixed with the client session id.
See CHANGELOG.md [0.9.0] for full details, including the [0.8.0] section which still applies.