Skip to content

Migrate crates/zeph-acp to agent-client-protocol 2.0.0 #6655

Description

@bug-ops

Description

The agent-client-protocol Rust SDK (https://github.com/agentclientprotocol/rust-sdk) released crate major version 2.0.0 on 2026-07-23. Zeph currently pins agent-client-protocol = "1.2.0" / agent-client-protocol-schema = "=1.4.0" in the root Cargo.toml. This issue tracks migrating crates/zeph-acp to the 2.0.0 line.

Important scope clarification (verified during spec research, see below): "ACP v2" here means the crate's major version 2.0.0 — an in-process Rust API redesign — not a wire-protocol v2. The wire protocol Zeph speaks stays at V1 throughout this migration; existing IDE hosts negotiate identically before and after. This is a dependency-major migration, not a protocol renegotiation. (A distinct, still-gated unstable_protocol_v2 wire-level draft exists upstream and is tracked separately in the spec's "Future/v2 Tracking" section — out of scope here.)

Spec

Full migration plan, invariants, and acceptance criteria: specs/013-acp/spec.md (v1.10, merged via PR #6654):

  • New "Breaking Changes Resolution (SDK 1.2.0 → 2.0.0)" table
  • "Protocol Version" section — crate-major-vs-wire-protocol-version invariant + compile-enforcement argument
  • "Feature Flags" section — pin notes, confirms unstable_protocol_v2 is deliberately not forwarded
  • Addendum "Version Upgrade Note (1.2.0 → 2.0.0)" — the authoritative step-by-step migration procedure
  • Implementation Gap Tracker entry I23

Related/superseded tracking issue: #4461 (speculative wire-v2 tracking issue predating this release; its specific predictions did not materialize — see comment there).

Scope — contained entirely in crates/zeph-acp/

Grep-confirmed: the root binary (src/acp.rs) only uses zeph_acp::* wrappers, never SDK types directly. All affected usage sites are inside crates/zeph-acp/src/ (agent/, client/, custom.rs, error.rs, fs.rs, lsp/, mcp_bridge.rs, permission.rs, terminal.rs, transport/).

Breaking changes in 2.0.0 relevant to Zeph

Renamed/removed (grep-confirmed zero current usage of any of these in crates/zeph-acp/src — no action needed, listed for completeness):

  • ResponseRouter::respond_*route_*
  • Builder::with_responderwith_runner
  • MatchDispatch::if_messageif_dispatch
  • run_indefinitelydetach
  • Removed: TypeNotification, send_error_notification, respond_with_error, DynamicHandler*, attach_session, util::both, process_stream_concurrently

Added (not adopted in this migration — deferred):

  • AcpAgent/AcpAgentConfig, TransportFrame/batch framing, DynamicHandlerGuard
  • Native unstable_mcp_over_acp (McpServer::Acp, mcp/connect) — replaces removed SDK-local McpAcpTransport/McpConnect* types. Zeph's mcp_bridge.rs already has a _ => warn!+None catch-all, so a McpServer::Acp variant from a host falls through cleanly; Zeph does not enable this feature, so hosts shouldn't send it anyway.

Named compiler-verify points (need confirmation at bump time, not assumed clean):

  • ActiveSession::connection() now returns &ConnectionTo<_> (used at client/driver.rs:149/204/259 via .connection().send_notification)
  • Option<&T> borrow-return changes on modes/meta/id accessors
  • Dispatch<Req,Notif> new Notif: JsonRpcNotification bound (agent/handlers/dispatch.rs:39)

Behavioral changes (live-test-only, not caught by unit tests):

  • Ordered-response-callback barrier now enforced in 2.0 (historically the class of issue behind the feat(llm): Claude server-side compaction API (compact-2026-01-12 beta) #1696 cascade — Zeph registers no on_receiving_result callbacks and its block_task calls sit inside request handlers, so expected-fine, but must be verified live)
  • Standard transports now accept JSON-RPC batches (Zeph gets this for free; verify streaming stays intact)
  • Dropping a Responder for one request now emits an Internal-Error fallback after dispatch (benign for Zeph — prompt.rs:34/dispatch.rs:28 always call responder.respond(...) on every handled path — but verify no unexpected Internal-Error frames appear in the live test)

Migration steps (from spec Addendum)

  1. Bump root Cargo.toml: agent-client-protocol = "2.0.0"; run cargo update + cargo tree to determine which schema version (1.5.0 or 1.6.0 line) 2.0.0 actually resolves, and =-pin to that exact version.
  2. PRE-MERGE WIRE GATE (blocking) — confirm ProtocolVersion::LATEST.as_u16() == 1 under the resolved schema with Zeph's feature set (unstable_protocol_v2 OFF). Add a local literal assert_eq!(ProtocolVersion::LATEST.as_u16(), 1) regression guard. If this resolves to 2, STOP — re-classify as a wire-breaking change requiring dual-version/negotiation handling, not a mechanical bump, and return to the architecture stage.
  3. cargo check -p zeph-acp --features full — triage and fix the three named compiler-verify points above mechanically.
  4. Build zeph-acp under each unstable feature individually, plus acp-http — cfg-gated code is invisible to the default build (a previously-documented trap from the 1.4.0 migration).
  5. Full CI suite: cargo +nightly fmt --check, cargo clippy --profile ci --workspace --all-targets --features "desktop,ide,server,chat,pdf,scheduler,testing" -- -D warnings, cargo nextest run --config-file .github/nextest.toml --workspace --features "desktop,ide,server,chat,pdf,scheduler" --lib --bins, rustdoc gate.
  6. Mandatory live round-trip gate (LLM-serialization gate, per .claude/rules/branching.md — this touches the ACP request/response path): initializeprompt → tool call exercising AcpPermissionGate.block_taskset_config_option{model}set_modeforkresumesession/deletelogout. Assert: no 400/422 errors, no deadlock, streaming intact, both stdio and (if enabled) http/ws transports. Explicitly assert /agent.json and /.well-known/acp.json emit literal protocol_version: 1 — not just "no error".
  7. Update specs/013-acp/spec.md Implementation Gap Tracker entry I23 to reflect completion, and CHANGELOG.md.

Open questions (need a decision during implementation, not blocking spec merge)

  1. Adopt native unstable_mcp_over_acp now, or keep passthrough behavior and defer? Recommendation: defer — matches the existing spec's MCP-over-ACP deferral stance.
  2. Exact schema pin: =1.5.0 (built-against) vs =1.6.0 (latest, also confirmed wire-V1-safe)? Recommendation: pin to whatever cargo tree shows agent-client-protocol 2.0.0 actually resolves.
  3. Pure mechanical bump vs. adopting new 2.x surface (batch framing, unstable_protocol_v2 draft) in the same pass? Recommendation: mechanical only — matches the clean-bump precedent set by the prior 0.14.0 and 1.0.1 migrations; adopting new surface is a separate follow-up.

Risks

  • Compile: LOW — migration surface is barely touched; only the three named compiler-verify points need confirmation.
  • Behavioral: MEDIUM — the three behavioral changes above are live-test-only; not caught by the unit/integration suite.
  • Pin exactness — if 2.0.0 resolves via a caret range, cargo update could later pull a newer schema than tested; the = pin must match exactly what was tested.
  • Interop/rollout: LOW, conditional on the wire gate passing — no wire-schema break is expected (verified via upstream agent-client-protocol-schema source: ProtocolVersion::LATEST is cfg-gated to V1 and is not even a valid symbol when unstable_protocol_v2 is enabled, so Zeph cannot accidentally advertise wire v2). This is why a big-bang cutover (no dual-version support) is the recommended approach — but step 2's gate must still be run and pass before merge.

Environment

  • Current: agent-client-protocol = "1.2.0", agent-client-protocol-schema = "=1.4.0" (root Cargo.toml:21-22)
  • Target: agent-client-protocol = "2.0.0", schema pin TBD (=1.5.0 or =1.6.0, resolved via cargo tree at implementation time)
  • Affected crate: zeph-acp (feature flags: unstable-session-fork, unstable-session-usage, unstable-elicitation, unstable-llm-providers, unstable-auth-methods)

Suggested next step

Run /rust-agents:team-develop with the refactoring chain (dependency-major migration, no architect needed — this issue and specs/013-acp/spec.md already contain the full plan) on this issue. The developer should start from the spec's Addendum "Version Upgrade Note (1.2.0 → 2.0.0)" step list.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2High value, medium complexityenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions