feat(http): session resume via X-Client-Session-Id; client-authoritative reconciliation#71
Merged
Merged
Conversation
…ive reconciliation When the chat-completions client sends X-Client-Session-Id, treat it as authoritative for the amplifier session_id (`http-<client_sid>`). Auto- detect first-turn vs continuation by state_dir.exists(). Pass is_resumed into the existing make_turn_handler — same primitive `amplifier-agent run --resume` uses. Add HTTP-face-private reconcile_client_history() that persists the client's full-history view as authoritative. No divergence detection, no new event types, no ceremony — client wins by fiat. Backward compatible: clients without the header get a random sid per turn as before. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
manojp99
added a commit
that referenced
this pull request
Jun 23, 2026
opencode sends X-Session-Id by default via Vercel AI SDK -- recognize it as a fallback for X-Client-Session-Id so PR #71's session-resume chain works for opencode with zero config. Also drop the workspace-suffix mechanism. Per-client distinction is at the session_id level; workspace stays at server-process scope so hook state (context-intelligence) shares cleanly across client sessions. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-authored-by: Manoj Prabhakar Paidiparthy <mpaidiparthy@microsoft.com> Co-authored-by: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
manojp99
added a commit
that referenced
this pull request
Jun 23, 2026
Cuts v0.9.0 release with chat-completions session resume, client-authoritative reconciliation, and zero-config opencode session continuity via X-Session-Id header. See CHANGELOG.md [0.9.0] for details: PR #71, #72, #73. Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-authored-by: Manoj Prabhakar Paidiparthy <mpaidiparthy@microsoft.com> Co-authored-by: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
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.
What this PR does
When the chat-completions client sends
X-Client-Session-Id, amplifier-agent now uses a deterministichttp-<client_sid>as the amplifier session_id, auto-detects whether this is the first turn or a continuation by checking if the session state dir exists on disk, and passesis_resumedto the existing kernel resume mechanism (same primitive the CLI face's--resumeflag uses). One opencode conversation = one amplifier session — unified audit trail, persistent hook state across turns, append-mode events.jsonl.Client-authoritative transcript reconciliation in
src/amplifier_agent_http/_reconciler.py. Since the chat-completions wire is stateless and the client sends full history every turn, on divergence between stored and incoming the client wins by fiat — we persist the client's view over our stored copy without any rewind ceremony. Sufficient for opencode and any well-behaved OpenAI-compatible client. No new event types introduced.Changes
src/amplifier_agent_http/_reconciler.pyreconcile_client_history(). Persists client messages toSessionStore, returns messages unchanged.src/amplifier_agent_http/routes/chat_completions.pyclient_session_id_cleanbefore the workspace block; adds sid + is_resumed determination; calls reconciler; passessession_id+is_resumedtorun_chat_turn.src/amplifier_agent_http/_session_runner.pyis_resumed: bool = Falsetorun_chat_turnsignature; threads it through toprepared.create_session().tests/http/test_reconciler.pyCHANGELOG.md[Unreleased] > Added.Backward compatibility
Clients that do not send
X-Client-Session-Idget a random sid per turn (viarun_chat_turn) andis_resumed=False— identical to current behavior.How to smoke test
amplifier-agent serve chat-completions --api-key testValidation
uv run pytest tests/http/— 24 passed (16 pre-existing + 8 new)uv run pytest tests/config/— 47 passeduv run pytest tests/cli/— 237 passed, 1 pre-existing env-var failure on main (unchanged)uv run ruff check src/ tests/— cleanuv run pyright src/— 1 pre-existing error insingle_turn.py(not in this PR's files)