chore: fix bad merge

This commit is contained in:
Nathan Flurry 2026-02-11 07:52:48 -08:00
parent 1dd45908a3
commit 94353f7696
205 changed files with 19244 additions and 14866 deletions

View file

@ -1,6 +1,6 @@
# Delete Or Comment Out First
This is the initial, deliberate teardown list before building ACP-native v2.
This is the initial, deliberate teardown list before building ACP-native v1.
## Hard delete first (in-house protocol types and converters)
@ -39,7 +39,7 @@ This is the initial, deliberate teardown list before building ACP-native v2.
Rationale: this layer is based on current v1 session/event model. Comment it out/disable it during ACP core implementation to avoid coupling and drift.
Important: OpenCode <-> ACP support is still required, but it is explicitly reintroduced in Phase 7 after ACP v2 core transport/runtime are stable.
Important: OpenCode <-> ACP support is still required, but it is explicitly reintroduced in Phase 7 after ACP v1 core transport/runtime are stable.
## Tests to remove or disable with v1
@ -50,4 +50,4 @@ Important: OpenCode <-> ACP support is still required, but it is explicitly rein
- `server/packages/sandbox-agent/tests/sessions.rs`
- `server/packages/sandbox-agent/tests/agent_flows.rs`
Replace with ACP-native contract tests in v2.
Replace with ACP-native contract tests in v1.

View file

@ -1,13 +1,13 @@
# ACP Migration Research
This folder captures the v2 migration plan from the current in-house protocol to ACP-first architecture.
This folder captures the v1 migration plan from the current in-house protocol to ACP-first architecture.
## Files
- `research/acp/00-delete-first.md`: delete/comment-out-first inventory for the rewrite kickoff.
- `research/acp/acp-notes.md`: ACP protocol notes extracted from `~/misc/acp-docs`.
- `research/acp/acp-over-http-findings.md`: field research from ACP Zulip thread on real ACP-over-HTTP transport patterns and recommendations.
- `research/acp/spec.md`: proposed v2 protocol/transport spec (ACP over HTTP).
- `research/acp/spec.md`: proposed v1 protocol/transport spec (ACP over HTTP).
- `research/acp/v1-schema-to-acp-mapping.md`: exhaustive 1:1 mapping of all current v1 endpoints/events into ACP methods, notifications, responses, and `_meta` extensions.
- `research/acp/rfds-vs-extensions.md`: simple list of which gaps should be raised as ACP RFDs vs remain product-specific extensions.
- `research/acp/migration-steps.md`: concrete implementation phases and execution checklist.
@ -35,7 +35,7 @@ This folder captures the v2 migration plan from the current in-house protocol to
## Important context
- ACP stable transport is stdio; streamable HTTP is still draft in ACP docs.
- v2 in this repo is intentionally breaking and ACP-native.
- v1 is removed in v2 and returns HTTP 410 on `/v1/*`.
- v1 in this repo is intentionally breaking and ACP-native.
- v1 is removed in v1 and returns HTTP 410 on `/v1/*`.
- `/opencode/*` is disabled during ACP core phases and re-enabled in the dedicated bridge phase.
- Keep `research/acp/friction.md` current as issues/ambiguities are discovered.

View file

@ -63,4 +63,4 @@ From ACP docs agent list:
Gap to confirm for launch scope:
- Amp is not currently listed in ACP docs as a native ACP agent or published agent process.
- We need an explicit product decision: block Amp in v2 launch or provide/build an ACP agent process.
- We need an explicit product decision: block Amp in v1 launch or provide/build an ACP agent process.

View file

@ -53,14 +53,14 @@ Why it matters:
- Lower complexity for bidirectional ACP semantics.
- But less aligned with strict HTTP-only environments without additional gatewaying.
## Recommended options for our v2
## Recommended options for our v1
## Option A (recommended): Streamable HTTP as canonical v2 transport
## Option A (recommended): Streamable HTTP as canonical v1 transport
Implement ACP over:
- `POST /v2/rpc`
- `GET /v2/rpc` (SSE, optional but recommended)
- `DELETE /v2/rpc`
- `POST /v1/rpc`
- `GET /v1/rpc` (SSE, optional but recommended)
- `DELETE /v1/rpc`
Profile:
- Keep JSON-RPC payloads pure ACP.
@ -86,14 +86,14 @@ Pros:
- Potentially simpler core runtime behavior.
Cons:
- Less direct fit to your immediate "ACP over HTTP v2 API" objective.
- Less direct fit to your immediate "ACP over HTTP v1 API" objective.
- Requires and maintains a translation layer from day one.
## Recommendation
Choose Option A for v2 launch and keep Option B as a later optimization path if operational pain appears.
Choose Option A for v1 launch and keep Option B as a later optimization path if operational pain appears.
Rationale:
- It matches current product direction.
- It aligns with concrete ecosystem work already visible (Goose Streamable HTTP).
- It can still preserve a future WebSocket backend if needed later, without changing v2 public semantics.
- It can still preserve a future WebSocket backend if needed later, without changing v1 public semantics.

View file

@ -13,7 +13,7 @@ Primary references:
## 1) Status Matrix (Session-Centric)
| v1 capability (session-related) | ACP stable | ACP unstable | Status in v2 | Recommendation |
| v1 capability (session-related) | ACP stable | ACP unstable | Status in v1 | Recommendation |
|---|---|---|---|---|
| Create session | `session/new` | N/A | Covered | Use ACP standard only. |
| Load/replay prior session | `session/load` (capability-gated) | N/A | Covered when agent process supports `loadSession` | Keep standard behavior. |
@ -111,7 +111,7 @@ Advertise extension support in `initialize.result.agentCapabilities._meta["sandb
Clients must feature-detect and degrade gracefully.
## 4) Recommendation for Current v2
## 4) Recommendation for Current v1
Recommended implementation order:

View file

@ -21,8 +21,8 @@ Update this file continuously during the migration.
- Date: 2026-02-10
- Area: Agent process availability
- Issue: Amp does not have a confirmed official ACP agent process in current ACP docs/research.
- Impact: Blocks full parity if Amp is required in v2 launch scope.
- Proposed direction: Treat Amp as conditional for v2.0 and support via pinned fallback only if agent process source is validated.
- Impact: Blocks full parity if Amp is required in v1 launch scope.
- Proposed direction: Treat Amp as conditional for v1.0 and support via pinned fallback only if agent process source is validated.
- Decision: Open.
- Owner: Unassigned.
- Status: open
@ -30,7 +30,7 @@ Update this file continuously during the migration.
- Date: 2026-02-10
- Area: Transport
- Issue: ACP streamable HTTP is still draft upstream; v2 requires ACP over HTTP now.
- Issue: ACP streamable HTTP is still draft upstream; v1 requires ACP over HTTP now.
- Impact: Potential divergence from upstream HTTP semantics.
- Proposed direction: Use strict JSON-RPC mapping and keep transport shim minimal/documented for later alignment.
- Decision: Open.
@ -72,7 +72,7 @@ Update this file continuously during the migration.
- Area: ACP over HTTP standardization
- Issue: Community is actively piloting both Streamable HTTP and WebSocket; no final single transport profile has emerged yet.
- Impact: Risk of rework if we overfit to one draft behavior that later shifts.
- Proposed direction: Lock v2 public contract to Streamable HTTP with ACP JSON-RPC payloads, keep implementation modular so WebSocket can be added later without breaking v2 API.
- Proposed direction: Lock v1 public contract to Streamable HTTP with ACP JSON-RPC payloads, keep implementation modular so WebSocket can be added later without breaking v1 API.
- Decision: Accepted.
- Owner: Unassigned.
- Status: in_progress
@ -121,7 +121,7 @@ Update this file continuously during the migration.
- Date: 2026-02-10
- Area: TypeScript ACP-over-HTTP client support
- Issue: Official ACP client SDK does not currently provide the exact Streamable HTTP transport behavior required by this project.
- Impact: SDK cannot target `/v2/rpc` without additional transport implementation.
- Impact: SDK cannot target `/v1/rpc` without additional transport implementation.
- Proposed direction: Embed upstream ACP SDK types/lifecycle and implement a project transport agent process for ACP-over-HTTP.
- Decision: Accepted.
- Owner: Unassigned.
@ -156,7 +156,7 @@ Update this file continuously during the migration.
- Decision: Accepted and implemented.
- Owner: Unassigned.
- Status: resolved
- Links: `server/packages/agent-management/src/agents.rs`, `server/packages/sandbox-agent/tests/v2_api.rs`
- Links: `server/packages/agent-management/src/agents.rs`, `server/packages/sandbox-agent/tests/v1_api.rs`
- Date: 2026-02-10
- Area: Inspector E2E tooling
@ -179,9 +179,9 @@ Update this file continuously during the migration.
- Links: `research/acp/todo.md`
- Date: 2026-02-10
- Area: Inspector v1-to-v2 compatibility
- Issue: Restored inspector UI expects legacy `/v1` session/event contracts that no longer exist in ACP-native v2.
- Impact: Full parity would block migration; inspector would otherwise fail to run against v2.
- Area: Inspector v1-to-v1 compatibility
- Issue: Restored inspector UI expects legacy `/v1` session/event contracts that no longer exist in ACP-native v1.
- Impact: Full parity would block migration; inspector would otherwise fail to run against v1.
- Proposed direction: Keep the restored UI and bridge to ACP with a thin compatibility client (`src/lib/legacyClient.ts`), stubbing non-parity features with explicit `TDOO` markers.
- Decision: Accepted.
- Owner: Unassigned.
@ -196,7 +196,7 @@ Update this file continuously during the migration.
- Decision: Accepted and implemented.
- Owner: Unassigned.
- Status: resolved
- Links: `server/packages/sandbox-agent/src/acp_runtime/mod.rs`, `server/packages/sandbox-agent/src/acp_runtime/mock.rs`, `server/packages/sandbox-agent/tests/v2_api.rs`, `server/packages/sandbox-agent/tests/v2_agent_process_matrix.rs`
- Links: `server/packages/sandbox-agent/src/acp_runtime/mod.rs`, `server/packages/sandbox-agent/src/acp_runtime/mock.rs`, `server/packages/sandbox-agent/tests/v1_api.rs`, `server/packages/sandbox-agent/tests/v1_agent_process_matrix.rs`
- Date: 2026-02-10
- Area: TypeScript SDK package split and ACP lifecycle
@ -210,13 +210,13 @@ Update this file continuously during the migration.
- Date: 2026-02-10
- Area: Streamable HTTP transport contract
- Issue: Ambiguity over whether `/v2/rpc` should track MCP transport negotiation (`POST` accepting SSE responses, multi-stream fanout) versus Sandbox Agent's simpler JSON-only POST contract.
- Issue: Ambiguity over whether `/v1/rpc` should track MCP transport negotiation (`POST` accepting SSE responses, multi-stream fanout) versus Sandbox Agent's simpler JSON-only POST contract.
- Impact: Without an explicit contract, clients can assume incompatible Accept/media semantics and open duplicate GET streams that receive duplicate events.
- Proposed direction: Define Sandbox Agent transport profile explicitly: `POST /v2/rpc` is JSON-only (`Content-Type` and `Accept` for `application/json`), `GET /v2/rpc` is SSE-only (`Accept: text/event-stream`), and allow only one active SSE stream per ACP connection id.
- Proposed direction: Define Sandbox Agent transport profile explicitly: `POST /v1/rpc` is JSON-only (`Content-Type` and `Accept` for `application/json`), `GET /v1/rpc` is SSE-only (`Accept: text/event-stream`), and allow only one active SSE stream per ACP connection id.
- Decision: Accepted and implemented.
- Owner: Unassigned.
- Status: resolved
- Links: `server/packages/sandbox-agent/src/router.rs`, `server/packages/sandbox-agent/src/acp_runtime/mod.rs`, `server/packages/sandbox-agent/tests/v2_api/acp_transport.rs`, `docs/advanced/acp-http-client.mdx`
- Links: `server/packages/sandbox-agent/src/router.rs`, `server/packages/sandbox-agent/src/acp_runtime/mod.rs`, `server/packages/sandbox-agent/tests/v1_api/acp_transport.rs`, `docs/advanced/acp-http-client.mdx`
- Date: 2026-02-10
- Area: Agent selection contract for ACP bootstrap/session creation
@ -226,4 +226,24 @@ Update this file continuously during the migration.
- Decision: Accepted and implemented.
- Owner: Unassigned.
- Status: resolved
- Links: `server/packages/sandbox-agent/src/router.rs`, `server/packages/sandbox-agent/src/acp_runtime/helpers.rs`, `server/packages/sandbox-agent/src/acp_runtime/mod.rs`, `server/packages/sandbox-agent/src/acp_runtime/ext_meta.rs`, `server/packages/sandbox-agent/tests/v2_api/acp_transport.rs`
- Links: `server/packages/sandbox-agent/src/router.rs`, `server/packages/sandbox-agent/src/acp_runtime/helpers.rs`, `server/packages/sandbox-agent/src/acp_runtime/mod.rs`, `server/packages/sandbox-agent/src/acp_runtime/ext_meta.rs`, `server/packages/sandbox-agent/tests/v1_api/acp_transport.rs`
- Date: 2026-02-11
- Area: ACP server simplification
- Issue: Current `/v1/rpc` runtime includes server-managed metadata/session registry and `_sandboxagent/*` ACP extensions, while the new direction is a dumb stdio proxy keyed by client-provided ACP server id.
- Impact: Requires removing extension/metadata semantics and reshaping transport to `/v1/acp/{server_id}` with per-id subprocess lifecycle.
- Proposed direction: Replace `/v1/rpc` with `/v1/acp/{server_id}` (`POST`/`GET` SSE/`DELETE`), drop connection-id headers, keep replay by `server_id`, move non-ACP concerns to HTTP endpoints, and disable OpenCode routes.
- Decision: Accepted (spec drafted).
- Owner: Unassigned.
- Status: in_progress
- Links: `research/acp/simplify-server.md`
- Date: 2026-02-11
- Area: Directory-scoped config ownership
- Issue: MCP/skills config previously traveled with session initialization payloads; simplified server needs standalone HTTP config scoped by directory.
- Impact: Requires new HTTP APIs and clear naming for per-directory/per-entry operations without ACP extension transport.
- Proposed direction: Add directory-scoped query APIs: `/v1/config/mcp?directory=...&mcpName=...` and `/v1/config/skills?directory=...&skillName=...` (name required), using v1 payload shapes for MCP/skills config values.
- Decision: Accepted (spec updated).
- Owner: Unassigned.
- Status: in_progress
- Links: `research/acp/simplify-server.md`, `docs/mcp-config.mdx`, `docs/skills-config.mdx`

View file

@ -2,7 +2,7 @@
Updated: 2026-02-10
This tracks legacy inspector behaviors that do not yet have full parity on ACP v2.
This tracks legacy inspector behaviors that do not yet have full parity on ACP v1.
1. TDOO: Session `permissionMode` preconfiguration on create is not wired in ACP inspector compatibility.
2. TDOO: Session `variant` preconfiguration on create is not wired in ACP inspector compatibility.

View file

@ -1,57 +1,57 @@
# Proposal: Move Static v2 HTTP Endpoints into ACP Extensions
# Proposal: Move Static v1 HTTP Endpoints into ACP Extensions
## Goal
Keep `GET /v2/health` as the only static control endpoint, except for dedicated binary filesystem transfer endpoints.
Keep `GET /v1/health` as the only static control endpoint, except for dedicated binary filesystem transfer endpoints.
Move all other current static v2 HTTP routes to ACP JSON-RPC methods (Sandbox Agent extensions under `_sandboxagent/...`) on `/v2/rpc`.
Move all other current static v1 HTTP routes to ACP JSON-RPC methods (Sandbox Agent extensions under `_sandboxagent/...`) on `/v1/rpc`.
Retain these HTTP endpoints intentionally:
- `GET /v2/fs/file`
- `PUT /v2/fs/file`
- `POST /v2/fs/upload-batch`
- `GET /v1/fs/file`
- `PUT /v1/fs/file`
- `POST /v1/fs/upload-batch`
No implementation in this proposal. This is a migration plan.
## Current State (from `server/packages/sandbox-agent/src/router.rs`)
Static v2 endpoints today:
Static v1 endpoints today:
- `GET /v2/agents`
- `POST /v2/agents/:agent/install`
- `GET /v2/sessions`
- `GET /v2/sessions/:session_id`
- `GET /v2/fs/entries`
- `GET /v2/fs/file`
- `PUT /v2/fs/file`
- `DELETE /v2/fs/entry`
- `POST /v2/fs/mkdir`
- `POST /v2/fs/move`
- `GET /v2/fs/stat`
- `POST /v2/fs/upload-batch`
- `GET /v1/agents`
- `POST /v1/agents/:agent/install`
- `GET /v1/sessions`
- `GET /v1/sessions/:session_id`
- `GET /v1/fs/entries`
- `GET /v1/fs/file`
- `PUT /v1/fs/file`
- `DELETE /v1/fs/entry`
- `POST /v1/fs/mkdir`
- `POST /v1/fs/move`
- `GET /v1/fs/stat`
- `POST /v1/fs/upload-batch`
Non-static ACP transport endpoints (remain):
- `POST /v2/rpc`
- `GET /v2/rpc` (SSE)
- `DELETE /v2/rpc`
- `POST /v1/rpc`
- `GET /v1/rpc` (SSE)
- `DELETE /v1/rpc`
Health endpoint (remain):
- `GET /v2/health`
- `GET /v1/health`
## Proposed Target Surface
Keep:
- `GET /v2/health`
- `POST/GET/DELETE /v2/rpc`
- `GET /v2/fs/file`
- `PUT /v2/fs/file`
- `POST /v2/fs/upload-batch`
- `GET /v1/health`
- `POST/GET/DELETE /v1/rpc`
- `GET /v1/fs/file`
- `PUT /v1/fs/file`
- `POST /v1/fs/upload-batch`
Remove all other static v2 control/file routes after migration.
Remove all other static v1 control/file routes after migration.
Add ACP extension methods:
@ -68,24 +68,24 @@ Add ACP extension methods:
- `_sandboxagent/fs/stat`
- `_sandboxagent/fs/upload_batch` (parallel with HTTP)
Interpretation for clients: all agent/session operations and non-binary filesystem operations move to ACP extension calls over `/v2/rpc`. Binary file transfer has a dual surface: ACP equivalents exist in parallel, but HTTP remains the primary transport for large/streaming payloads.
Interpretation for clients: all agent/session operations and non-binary filesystem operations move to ACP extension calls over `/v1/rpc`. Binary file transfer has a dual surface: ACP equivalents exist in parallel, but HTTP remains the primary transport for large/streaming payloads.
## Endpoint-to-Method Mapping
| Existing HTTP | New ACP method | Notes |
| --- | --- | --- |
| `GET /v2/agents` | `_sandboxagent/agent/list` | Response keeps current `AgentListResponse` shape for low migration risk. |
| `POST /v2/agents/:agent/install` | `_sandboxagent/agent/install` | Params include `agent`, `reinstall`, `agentVersion`, `agentProcessVersion`. |
| `GET /v2/sessions` | `_sandboxagent/session/list` | Return current `SessionListResponse` shape (not ACP unstable list shape). |
| `GET /v2/sessions/:session_id` | `_sandboxagent/session/get` | Return current `SessionInfo` shape; error on missing session. |
| `GET /v2/fs/entries` | `_sandboxagent/fs/list_entries` | Preserve path + optional `sessionId` resolution semantics. |
| `GET /v2/fs/file` | keep HTTP + `_sandboxagent/fs/read_file` | HTTP is primary because responses may require large streaming reads; ACP variant exists for compatibility/smaller payloads. |
| `PUT /v2/fs/file` | keep HTTP + `_sandboxagent/fs/write_file` | HTTP is primary for large binary writes; ACP variant exists for compatibility/smaller payloads. |
| `DELETE /v2/fs/entry` | `_sandboxagent/fs/delete_entry` | Preserve recursive directory delete behavior. |
| `POST /v2/fs/mkdir` | `_sandboxagent/fs/mkdir` | Preserve create-dir behavior. |
| `POST /v2/fs/move` | `_sandboxagent/fs/move` | Preserve `overwrite` behavior. |
| `GET /v2/fs/stat` | `_sandboxagent/fs/stat` | Preserve `FsStat` shape. |
| `POST /v2/fs/upload-batch` | keep HTTP + `_sandboxagent/fs/upload_batch` | HTTP is primary for large tar uploads; ACP variant exists for compatibility/smaller payloads. |
| `GET /v1/agents` | `_sandboxagent/agent/list` | Response keeps current `AgentListResponse` shape for low migration risk. |
| `POST /v1/agents/:agent/install` | `_sandboxagent/agent/install` | Params include `agent`, `reinstall`, `agentVersion`, `agentProcessVersion`. |
| `GET /v1/sessions` | `_sandboxagent/session/list` | Return current `SessionListResponse` shape (not ACP unstable list shape). |
| `GET /v1/sessions/:session_id` | `_sandboxagent/session/get` | Return current `SessionInfo` shape; error on missing session. |
| `GET /v1/fs/entries` | `_sandboxagent/fs/list_entries` | Preserve path + optional `sessionId` resolution semantics. |
| `GET /v1/fs/file` | keep HTTP + `_sandboxagent/fs/read_file` | HTTP is primary because responses may require large streaming reads; ACP variant exists for compatibility/smaller payloads. |
| `PUT /v1/fs/file` | keep HTTP + `_sandboxagent/fs/write_file` | HTTP is primary for large binary writes; ACP variant exists for compatibility/smaller payloads. |
| `DELETE /v1/fs/entry` | `_sandboxagent/fs/delete_entry` | Preserve recursive directory delete behavior. |
| `POST /v1/fs/mkdir` | `_sandboxagent/fs/mkdir` | Preserve create-dir behavior. |
| `POST /v1/fs/move` | `_sandboxagent/fs/move` | Preserve `overwrite` behavior. |
| `GET /v1/fs/stat` | `_sandboxagent/fs/stat` | Preserve `FsStat` shape. |
| `POST /v1/fs/upload-batch` | keep HTTP + `_sandboxagent/fs/upload_batch` | HTTP is primary for large tar uploads; ACP variant exists for compatibility/smaller payloads. |
## ACP Contract Details
@ -99,14 +99,14 @@ Add keys for new extensions (`agentList`, `agentInstall`, `fsListEntries`, `fsSt
### Filesystem Exception (Intentional)
`GET/PUT /v2/fs/file` and `POST /v2/fs/upload-batch` stay as first-class Sandbox Agent HTTP APIs.
`GET/PUT /v1/fs/file` and `POST /v1/fs/upload-batch` stay as first-class Sandbox Agent HTTP APIs.
Reason:
- These operations are host/runtime capabilities implemented by Sandbox Agent, not agent-process behavior.
- Keeping them server-owned gives consistent behavior across agents.
- ACP envelopes are JSON-RPC payloads and are not suitable for streaming very large binary files efficiently.
- `GET /v2/fs/file` specifically needs efficient streamed responses for large reads.
- `GET /v1/fs/file` specifically needs efficient streamed responses for large reads.
ACP parity note:
@ -134,16 +134,16 @@ Required change for ACP-only behavior:
- Make ACP-backed helpers connection-scoped (same as ACP methods): they must throw `NotConnectedError` when disconnected.
- Keep direct HTTP helper calls only for:
- `getHealth()`
- `readFsFile()` (`GET /v2/fs/file`)
- `writeFsFile()` (`PUT /v2/fs/file`)
- `uploadFsBatch()` (`POST /v2/fs/upload-batch`)
- `readFsFile()` (`GET /v1/fs/file`)
- `writeFsFile()` (`PUT /v1/fs/file`)
- `uploadFsBatch()` (`POST /v1/fs/upload-batch`)
- Keep ACP variants available through low-level `extMethod(...)` for advanced/smaller-payload use cases, but do not make them the SDK default path.
Package boundary after migration:
- `acp-http-client` remains protocol-pure ACP transport and generic `extMethod`/`extNotification`.
- `sandbox-agent` remains the typed wrapper that maps convenience methods to `_sandboxagent/...` extension methods.
- No direct `/v2/agents*`, `/v2/sessions*`, or non-binary `/v2/fs/*` fetches in SDK runtime code.
- No direct `/v1/agents*`, `/v1/sessions*`, or non-binary `/v1/fs/*` fetches in SDK runtime code.
- Binary file transfer keeps direct HTTP fetches on the three endpoints listed above.
- SDK policy: prefer HTTP for `readFsFile`/`writeFsFile`/`uploadFsBatch` even if ACP extension variants exist.
@ -160,7 +160,7 @@ Integration test impact (`sdks/typescript/tests/integration.test.ts`):
## Bootstrap Model (Important)
Today, first call without `x-acp-connection-id` must be `initialize`, and requires `params._meta["sandboxagent.dev"].agent`.
Today, first call to a new ACP server id should be `initialize`, and requires `params._meta["sandboxagent.dev"].agent`.
Implication after migration:
@ -177,30 +177,30 @@ Alternative (optional): introduce a runtime-only control connection mode that do
- Reuse existing router/support mapping logic where possible to keep response parity.
- Keep binary file-transfer ACP methods in parallel with HTTP (`_sandboxagent/fs/read_file`, `_sandboxagent/fs/write_file`, `_sandboxagent/fs/upload_batch`) and route both surfaces through shared implementation code.
- Advertise new capabilities in `acp_runtime/ext_meta.rs`.
- Add ACP extension tests for each new method in `server/packages/sandbox-agent/tests/v2_api/acp_extensions.rs`.
- Add ACP extension tests for each new method in `server/packages/sandbox-agent/tests/v1_api/acp_extensions.rs`.
### Phase 2: Migrate Clients (No HTTP Route Removal Yet)
- TypeScript SDK (`sdks/typescript/src/client.ts`):
- Repoint `listAgents`, `installAgent`, `listSessions`, `getSession`, `listFsEntries`, `deleteFsEntry`, `mkdirFs`, `moveFs`, and `statFs` to ACP extension calls.
- Keep `readFsFile`, `writeFsFile`, and `uploadFsBatch` on HTTP endpoints.
- Remove direct runtime fetch usage for `/v2/agents*`, `/v2/sessions*`, and non-binary `/v2/fs/*`.
- Remove direct runtime fetch usage for `/v1/agents*`, `/v1/sessions*`, and non-binary `/v1/fs/*`.
- Keep method names stable for callers.
- Move these methods to connected-only semantics (`NotConnectedError` when disconnected).
- CLI (`server/packages/sandbox-agent/src/cli.rs`):
- Make `api agents list/install` call ACP extension methods (via ACP post flow), not direct `/v2/agents*` HTTP calls.
- Make `api agents list/install` call ACP extension methods (via ACP post flow), not direct `/v1/agents*` HTTP calls.
- Inspector flow/docs:
- Stop depending on `GET /v2/agents` in startup path; use ACP extension instead.
- Stop depending on `GET /v1/agents` in startup path; use ACP extension instead.
### Phase 3: Remove Static Endpoints (Except Health + Binary FS Transfer)
- Remove route registrations for `/v2/agents*`, `/v2/sessions*`, `/v2/fs/entries`, `/v2/fs/entry`, `/v2/fs/mkdir`, `/v2/fs/move`, `/v2/fs/stat` from `router.rs`.
- Keep `/v2/health`, `/v2/rpc`, `GET /v2/fs/file`, `PUT /v2/fs/file`, and `POST /v2/fs/upload-batch`.
- Remove route registrations for `/v1/agents*`, `/v1/sessions*`, `/v1/fs/entries`, `/v1/fs/entry`, `/v1/fs/mkdir`, `/v1/fs/move`, `/v1/fs/stat` from `router.rs`.
- Keep `/v1/health`, `/v1/rpc`, `GET /v1/fs/file`, `PUT /v1/fs/file`, and `POST /v1/fs/upload-batch`.
- Optional short deprecation period: convert removed routes to `410 Gone` with explicit extension method in `detail`.
### Phase 4: Docs/OpenAPI/Test Cleanup
- Regenerate `docs/openapi.json` (should now primarily describe `/v2/health`, `/v2/rpc`, and retained binary fs transfer endpoints).
- Regenerate `docs/openapi.json` (should now primarily describe `/v1/health`, `/v1/rpc`, and retained binary fs transfer endpoints).
- Update:
- `docs/cli.mdx`
- `docs/inspector.mdx`
@ -237,6 +237,6 @@ Inspector:
## Open Decisions
1. Should removed `/v2/agents*`, `/v2/sessions*`, and non-binary `/v2/fs/*` return `410` for one release or be dropped immediately?
1. Should removed `/v1/agents*`, `/v1/sessions*`, and non-binary `/v1/fs/*` return `410` for one release or be dropped immediately?
2. Do we keep a strict response-shape parity layer for session/file methods, or normalize to ACP-native shapes?
3. Should `/` service-root remain as informational HTTP, or be treated as out-of-scope for this “only health static + binary fs transfer” policy?

View file

@ -11,7 +11,7 @@
The migration test plan is intentionally collapsed to avoid duplicate coverage.
1. ACP protocol conformance
2. Transport contract (`/v2/rpc`)
2. Transport contract (`/v1/rpc`)
3. End-to-end agent process matrix (core flow + cancel + HITL + streaming)
4. Installer suite (explicit + lazy + registry/fallback provenance)
5. Security/auth isolation
@ -56,7 +56,7 @@ Validation gate:
2. Implement agent process process manager (spawn, supervise, reconnect policy).
3. Implement JSON-RPC bridge: HTTP POST/SSE <-> agent process stdio.
4. Add connection registry keyed by `X-ACP-Connection-Id`.
5. Include unstable ACP methods in the v2 profile (`session/list`, `session/fork`, `session/resume`, `session/set_model`, `$/cancel_request`).
5. Include unstable ACP methods in the v1 profile (`session/list`, `session/fork`, `session/resume`, `session/set_model`, `$/cancel_request`).
Exit criteria:
@ -64,11 +64,11 @@ Exit criteria:
Validation gate:
- End-to-end ACP flow test over `/v2/rpc` (request/response + streamed notifications).
- End-to-end ACP flow test over `/v1/rpc` (request/response + streamed notifications).
- Cancellation test (`session/cancel`) with proper terminal response behavior.
- HITL request/response round-trip test (`session/request_permission` path).
- SSE ordering and reconnection behavior test (`Last-Event-ID` replay path).
- Explicit close test (`DELETE /v2/rpc`) including idempotent double-close behavior.
- Explicit close test (`DELETE /v1/rpc`) including idempotent double-close behavior.
- Unstable ACP methods validation (`session/list`, `session/fork`, `session/resume`, `session/set_model`, `$/cancel_request`) for agent processes that advertise support.
## Phase 3: Installer Refactor
@ -79,7 +79,7 @@ Validation gate:
4. Add install verification command per agent process.
5. Add ACP registry integration for install metadata + fallback sources.
6. Generate install instructions from manifest and expose provenance (`registry` or `fallback`) in API/CLI.
7. Implement lazy install path on first `/v2/rpc` initialize (with per-agent install lock and idempotent results).
7. Implement lazy install path on first `/v1/rpc` initialize (with per-agent install lock and idempotent results).
8. Add config to disable lazy install for preprovisioned environments.
Exit criteria:
@ -92,39 +92,39 @@ Validation gate:
- Lazy install on first ACP `initialize` test.
- Reinstall/version/provenance assertions.
## Phase 4: v2 HTTP API
## Phase 4: v1 HTTP API
1. Mount `/v2/rpc` POST and SSE endpoints.
2. Add `/v2/health`, `/v2/agents`, `/v2/agents/{agent}/install`.
1. Mount `/v1/rpc` POST and SSE endpoints.
2. Add `/v1/health`, `/v1/agents`, `/v1/agents/{agent}/install`.
3. Add auth integration on connection lifecycle.
4. Keep `/ui/` inspector route and migrate inspector backend calls to ACP v2 transport.
4. Keep `/ui/` inspector route and migrate inspector backend calls to ACP v1 transport.
5. Remove v1 OpenAPI generation from default docs build.
Exit criteria:
- v2 endpoints documented and passing integration tests.
- v1 endpoints documented and passing integration tests.
Validation gate:
- Contract tests for all `/v2` endpoints (`/v2/rpc`, `/v2/health`, `/v2/agents`, install).
- Contract tests for all `/v1` endpoints (`/v1/rpc`, `/v1/health`, `/v1/agents`, install).
- Auth tests (valid, missing, invalid token).
- Error mapping tests (bad envelope, unknown connection, timeout paths).
- `/v1/*` removal contract test (HTTP 410 + stable payload).
- Inspector ACP `agent-browser` flow tests pass.
- `DELETE /v2/rpc` close contract tests pass.
- `DELETE /v1/rpc` close contract tests pass.
## Phase 5: SDK and CLI v2
## Phase 5: SDK and CLI v1
1. Add ACP transport client in `sdks/typescript` by embedding `@agentclientprotocol/sdk` (no in-house ACP reimplementation).
2. Implement custom ACP-over-HTTP transport agent process in our SDK (official ACP client SDK does not provide required Streamable HTTP behavior out of the box).
3. Add inspector frontend client wiring to use ACP-over-HTTP transport primitives.
4. Add CLI commands for sending raw ACP envelopes and streaming ACP messages.
5. Remove v1-only SDK/CLI methods (or hard-fail with "v1 removed").
6. Regenerate docs to v2 ACP contract.
6. Regenerate docs to v1 ACP contract.
Exit criteria:
- SDK can complete a full ACP prompt turn over `/v2/rpc`.
- SDK can complete a full ACP prompt turn over `/v1/rpc`.
Validation gate:
@ -136,9 +136,9 @@ Validation gate:
1. Replace v1 HTTP/session tests with ACP transport contract tests.
2. Add smoke tests per supported agent process.
Current deterministic matrix: `server/packages/sandbox-agent/tests/v2_agent_process_matrix.rs`.
Current deterministic matrix: `server/packages/sandbox-agent/tests/v1_agent_process_matrix.rs`.
3. Add canary rollout notes directly in `docs/quickstart.mdx`, `docs/cli.mdx`, and `docs/sdks/typescript.mdx`.
4. Update docs for v2 ACP, `/v1/*` removal, inspector ACP behavior, and SDK usage.
4. Update docs for v1 ACP, `/v1/*` removal, inspector ACP behavior, and SDK usage.
5. Keep v1 endpoints hard-removed (`410`) until/unless a separate compatibility project is approved.
Exit criteria:
@ -155,9 +155,9 @@ Validation gate:
## Phase 7: OpenCode <-> ACP Bridge (Dedicated Step)
1. Keep `/opencode/*` commented out/disabled through Phases 1-6.
2. Implement OpenCode <-> ACP bridge on top of v2 ACP runtime.
2. Implement OpenCode <-> ACP bridge on top of v1 ACP runtime.
3. Re-enable `server/packages/sandbox-agent/src/opencode_compat.rs` routes/tests at full capability.
4. Add dedicated integration tests that validate OpenCode SDK/TUI flows through ACP v2 internals.
4. Add dedicated integration tests that validate OpenCode SDK/TUI flows through ACP v1 internals.
Exit criteria:
@ -170,5 +170,5 @@ Validation gate:
## Compatibility Layer (optional future project)
1. No compatibility layer is in the current v2 scope.
1. No compatibility layer is in the current v1 scope.
2. If later approved, it should be a separate project with a dedicated spec and test matrix.

View file

@ -4,9 +4,9 @@
## Summary
v1 had a full question subsystem: agent requests a question from the user, client replies with an answer or rejection, and the system tracks question status. v2 has partial stub implementation in mock only.
v1 had a full question subsystem: agent requests a question from the user, client replies with an answer or rejection, and the system tracks question status. v1 has partial stub implementation in mock only.
## Current v2 State
## Current v1 State
- `_sandboxagent/session/request_question` is declared as a constant in `acp_runtime/mod.rs:33`
- Advertised in capability injection (`extensions.sessionRequestQuestion: true`)

View file

@ -4,13 +4,13 @@
## Summary
v1 had 8 filesystem endpoints. v2 has only ACP `fs/read_text_file` + `fs/write_text_file` (text-only, agent->client direction). The full filesystem API should be re-implemented as Sandbox Agent-specific HTTP contracts at `/v2/fs/*`.
v1 had 8 filesystem endpoints. v1 has only ACP `fs/read_text_file` + `fs/write_text_file` (text-only, agent->client direction). The full filesystem API should be re-implemented as Sandbox Agent-specific HTTP contracts at `/v1/fs/*`.
## Current v2 State
## Current v1 State
- ACP stable: `fs/read_text_file`, `fs/write_text_file` (client methods invoked by agents, text-only)
- No HTTP filesystem endpoints exist in current `router.rs`
- `rfds-vs-extensions.md` confirms: "Already extension (`/v2/fs/*` custom HTTP surface)"
- `rfds-vs-extensions.md` confirms: "Already extension (`/v1/fs/*` custom HTTP surface)"
- CLAUDE.md: "Filesystem and terminal APIs remain Sandbox Agent-specific HTTP contracts and are not ACP"
## v1 Reference (source commit)
@ -356,32 +356,32 @@ async fn fs_upload_batch(
## Implementation Plan
### New v2 Endpoints
### New v1 Endpoints
| Method | Path | Description |
|--------|------|-------------|
| GET | `/v2/fs/entries` | List directory entries |
| GET | `/v2/fs/file` | Read file raw bytes |
| PUT | `/v2/fs/file` | Write file raw bytes |
| DELETE | `/v2/fs/entry` | Delete file or directory |
| POST | `/v2/fs/mkdir` | Create directory |
| POST | `/v2/fs/move` | Move/rename |
| GET | `/v2/fs/stat` | File metadata |
| POST | `/v2/fs/upload-batch` | Upload tar archive |
| GET | `/v1/fs/entries` | List directory entries |
| GET | `/v1/fs/file` | Read file raw bytes |
| PUT | `/v1/fs/file` | Write file raw bytes |
| DELETE | `/v1/fs/entry` | Delete file or directory |
| POST | `/v1/fs/mkdir` | Create directory |
| POST | `/v1/fs/move` | Move/rename |
| GET | `/v1/fs/stat` | File metadata |
| POST | `/v1/fs/upload-batch` | Upload tar archive |
### Files to Modify
| File | Change |
|------|--------|
| `server/packages/sandbox-agent/src/router.rs` | Add all 8 `/v2/fs/*` endpoints with handlers (port from v1 with v2 path prefix) |
| `server/packages/sandbox-agent/src/router.rs` | Add all 8 `/v1/fs/*` endpoints with handlers (port from v1 with v1 path prefix) |
| `server/packages/sandbox-agent/src/cli.rs` | Add CLI `fs` subcommands (list, read, write, delete, mkdir, move, stat) |
| `sdks/typescript/src/client.ts` | Add filesystem methods to SDK |
| `server/packages/sandbox-agent/tests/v2_api.rs` | Add filesystem endpoint tests |
| `server/packages/sandbox-agent/tests/v1_api.rs` | Add filesystem endpoint tests |
### Docs to Update
| Doc | Change |
|-----|--------|
| `docs/openapi.json` | Add `/v2/fs/*` endpoint specs |
| `docs/openapi.json` | Add `/v1/fs/*` endpoint specs |
| `docs/cli.mdx` | Add `fs` subcommand documentation |
| `docs/sdks/typescript.mdx` | Document filesystem SDK methods |

View file

@ -1,12 +1,12 @@
# Feature 5: Health Endpoint
**Implementation approach:** Enhance existing `GET /v2/health`
**Implementation approach:** Enhance existing `GET /v1/health`
## Summary
v1 had a typed `HealthResponse` with detailed status. v2 `GET /v2/health` exists but returns only `{ status: "ok", api_version: "v2" }`. Needs enrichment.
v1 had a typed `HealthResponse` with detailed status. v1 `GET /v1/health` exists but returns only `{ status: "ok", api_version: "v1" }`. Needs enrichment.
## Current v2 State
## Current v1 State
From `router.rs:332-346`:
@ -17,10 +17,10 @@ pub struct HealthResponse {
pub api_version: String,
}
async fn get_v2_health() -> Json<HealthResponse> {
async fn get_v1_health() -> Json<HealthResponse> {
Json(HealthResponse {
status: "ok".to_string(),
api_version: "v2".to_string(),
api_version: "v1".to_string(),
})
}
```
@ -72,19 +72,19 @@ pub struct HealthResponse {
}
```
`GET /v2/health` should mirror v1 semantics and response shape (ported from commit `8ecd27bc24e62505d7aa4c50cbdd1c9dbb09f836`), while keeping the v2 route path.
`GET /v1/health` should mirror v1 semantics and response shape (ported from commit `8ecd27bc24e62505d7aa4c50cbdd1c9dbb09f836`), while keeping the v1 route path.
### Files to Modify
| File | Change |
|------|--------|
| `server/packages/sandbox-agent/src/router.rs` | Port v1 health response types/logic onto `GET /v2/health` |
| `server/packages/sandbox-agent/tests/v2_api.rs` | Update health endpoint test for full v1-parity payload |
| `server/packages/sandbox-agent/src/router.rs` | Port v1 health response types/logic onto `GET /v1/health` |
| `server/packages/sandbox-agent/tests/v1_api.rs` | Update health endpoint test for full v1-parity payload |
| `sdks/typescript/src/client.ts` | Update `HealthResponse` type |
### Docs to Update
| Doc | Change |
|-----|--------|
| `docs/openapi.json` | Update `/v2/health` response schema |
| `docs/openapi.json` | Update `/v1/health` response schema |
| `docs/sdks/typescript.mdx` | Document enriched health response |

View file

@ -1,14 +1,14 @@
# Feature 6: Server Status
**Implementation approach:** Extension fields on `GET /v2/agents` and `GET /v2/health`
**Implementation approach:** Extension fields on `GET /v1/agents` and `GET /v1/health`
## Summary
v1 had `ServerStatus` (Running/Stopped/Error) and `ServerStatusInfo` (baseUrl, lastError, restartCount, uptimeMs) per agent. v2 has none of this. Add server/agent process status tracking.
v1 had `ServerStatus` (Running/Stopped/Error) and `ServerStatusInfo` (baseUrl, lastError, restartCount, uptimeMs) per agent. v1 has none of this. Add server/agent process status tracking.
## Current v2 State
## Current v1 State
`GET /v2/agents` returns `AgentInfo` with install state only:
`GET /v1/agents` returns `AgentInfo` with install state only:
```rust
pub struct AgentInfo {
@ -132,13 +132,13 @@ Only include `server_status` for agents that use shared processes (Codex, OpenCo
| File | Change |
|------|--------|
| `server/packages/sandbox-agent/src/acp_runtime/mod.rs` | Track agent process lifecycle (start/stop/error/restart count) per `AgentId`; expose `status_snapshot()` method |
| `server/packages/sandbox-agent/src/router.rs` | Add `ServerStatus`, `ServerStatusInfo` types; add `server_status` to `AgentInfo`; query runtime for status in `get_v2_agents` |
| `server/packages/sandbox-agent/src/router.rs` | Add `ServerStatus`, `ServerStatusInfo` types; add `server_status` to `AgentInfo`; query runtime for status in `get_v1_agents` |
| `sdks/typescript/src/client.ts` | Update `AgentInfo` type with `serverStatus` |
| `server/packages/sandbox-agent/tests/v2_api.rs` | Test server status in agent listing |
| `server/packages/sandbox-agent/tests/v1_api.rs` | Test server status in agent listing |
### Docs to Update
| Doc | Change |
|-----|--------|
| `docs/openapi.json` | Update `/v2/agents` response with `server_status` |
| `docs/openapi.json` | Update `/v1/agents` response with `server_status` |
| `docs/sdks/typescript.mdx` | Document `serverStatus` field |

View file

@ -4,12 +4,12 @@
## Summary
v1 had explicit session termination (`POST /v1/sessions/{id}/terminate`). v2 only has `session/cancel` (turn cancellation, not session kill) and `DELETE /v2/rpc` (connection close, not session termination). Need explicit session destroy/terminate semantics.
v1 had explicit session termination (`POST /v1/sessions/{id}/terminate`). v1 only has `session/cancel` (turn cancellation, not session kill) and `DELETE /v1/rpc` (connection close, not session termination). Need explicit session destroy/terminate semantics.
## Current v2 State
## Current v1 State
- `session/cancel` — cancels an in-flight prompt turn only
- `DELETE /v2/rpc` — closes the HTTP connection, does **not** terminate the session
- `DELETE /v1/rpc` — closes the HTTP connection, does **not** terminate the session
- `_sandboxagent/session/detach` — detaches a session from a connection (multi-client visibility)
- No session termination/deletion exists
- `rfds-vs-extensions.md`: "Session Termination: Not covered by ACP. Only implement if product explicitly requires termination semantics beyond session/cancel"
@ -112,7 +112,7 @@ Response:
| `server/packages/sandbox-agent/src/acp_runtime/mod.rs` | Add `_sandboxagent/session/terminate` handler; add session removal from registry; add process kill logic |
| `server/packages/sandbox-agent/src/acp_runtime/mock.rs` | Add mock terminate support |
| `sdks/typescript/src/client.ts` | Add `terminateSession(sessionId)` method |
| `server/packages/sandbox-agent/tests/v2_api.rs` | Add session termination test |
| `server/packages/sandbox-agent/tests/v1_api.rs` | Add session termination test |
### Docs to Update

View file

@ -6,9 +6,9 @@
## Summary
v1 had `AgentModelInfo.variants`, `AgentModelInfo.defaultVariant`, and `CreateSessionRequest.variant`. v2 already has `_sandboxagent/session/list_models` but the variant fields need to be verified and the session-creation variant selection needs to work end-to-end.
v1 had `AgentModelInfo.variants`, `AgentModelInfo.defaultVariant`, and `CreateSessionRequest.variant`. v1 already has `_sandboxagent/session/list_models` but the variant fields need to be verified and the session-creation variant selection needs to work end-to-end.
## Current v2 State
## Current v1 State
From `acp_runtime/mod.rs`, `_sandboxagent/session/list_models` is implemented and returns:
- `availableModels[]` with `modelId`, `name`, `description`
@ -120,7 +120,7 @@ The runtime should forward this variant to the agent process (e.g., as a model p
| `server/packages/sandbox-agent/src/acp_runtime/mod.rs` | Verify `list_models` response includes `variants`/`defaultVariant`; extract and forward `variant` from `session/new` `_meta` |
| `server/packages/sandbox-agent/src/acp_runtime/mock.rs` | Add variant support to mock model listing |
| `sdks/typescript/src/client.ts` | Update `listModels` return type to include variants |
| `server/packages/sandbox-agent/tests/v2_api.rs` | Add model variants test |
| `server/packages/sandbox-agent/tests/v1_api.rs` | Add model variants test |
### Docs to Update

View file

@ -6,9 +6,9 @@
## Summary
v1 had an `include_raw` option that preserved the original agent JSON alongside normalized events. The `UniversalEvent.raw` field held the verbatim agent output. v2 has `_sandboxagent/agent/unparsed` for parse errors but no mechanism for clients to request raw agent payloads alongside normalized ACP events.
v1 had an `include_raw` option that preserved the original agent JSON alongside normalized events. The `UniversalEvent.raw` field held the verbatim agent output. v1 has `_sandboxagent/agent/unparsed` for parse errors but no mechanism for clients to request raw agent payloads alongside normalized ACP events.
## Current v2 State
## Current v1 State
- `_sandboxagent/agent/unparsed` — sends notifications when the runtime fails to parse agent output (error recovery only)
- No option for clients to request raw agent JSON alongside normal ACP events
@ -43,7 +43,7 @@ When `include_raw=true`, each `UniversalEvent` included the verbatim JSON the ag
### Extension Design
Since v2 agents speak ACP natively (JSON-RPC), the "raw" concept changes:
Since v1 agents speak ACP natively (JSON-RPC), the "raw" concept changes:
- For ACP-native agents: raw = the ACP JSON-RPC envelope itself (which clients already see)
- For non-native agents or runtime-synthesized events: raw = the original agent output before transformation

View file

@ -1,14 +1,14 @@
# Feature 12: Agent Listing (Typed Response)
**Implementation approach:** Enhance existing `GET /v2/agents`
**Implementation approach:** Enhance existing `GET /v1/agents`
## Summary
v1 `GET /v1/agents` returned a typed `AgentListResponse` with `installed`, `credentialsAvailable`, `path`, `capabilities`, `serverStatus`. v2 `GET /v2/agents` returns a basic `AgentInfo` with only install state. Needs enrichment.
v1 `GET /v1/agents` returned a typed `AgentListResponse` with `installed`, `credentialsAvailable`, `path`, `capabilities`, `serverStatus`. v1 `GET /v1/agents` returns a basic `AgentInfo` with only install state. Needs enrichment.
This feature also carries pre-session models/modes as optional fields when the agent is installed (Feature #13), rather than using separate model/mode endpoints.
## Current v2 State
## Current v1 State
From `router.rs:265-275`:
@ -183,19 +183,19 @@ fn agent_capabilities_for(agent: AgentId) -> AgentCapabilities {
### Enriched AgentInfo
Merge v2 install fields with v1 richness:
Merge v1 install fields with v1 richness:
```rust
pub struct AgentInfo {
pub id: String,
pub installed: bool, // convenience: is fully installed
pub credentials_available: bool, // from credential extraction
pub native_required: bool, // keep from v2
pub native_installed: bool, // keep from v2
pub native_version: Option<String>, // keep from v2
pub agent_process_installed: bool, // keep from v2
pub agent_process_source: Option<String>, // keep from v2
pub agent_process_version: Option<String>, // keep from v2
pub native_required: bool, // keep from v1
pub native_installed: bool, // keep from v1
pub native_version: Option<String>, // keep from v1
pub agent_process_installed: bool, // keep from v1
pub agent_process_source: Option<String>, // keep from v1
pub agent_process_version: Option<String>, // keep from v1
pub path: Option<String>, // from resolve_binary()
pub capabilities: AgentCapabilities, // full v1 capability set
pub server_status: Option<AgentServerStatus>, // from Feature #6
@ -212,11 +212,11 @@ pub struct AgentInfo {
| `server/packages/sandbox-agent/src/router.rs` | Enrich `AgentInfo` and `AgentCapabilities` structs; add `agent_capabilities_for()` static mapping; add credential check; add convenience `installed` field; add optional `models`/`modes` for installed agents |
| `server/packages/agent-management/src/agents.rs` | Expose credential availability check and `resolve_binary()` if not already present |
| `sdks/typescript/src/client.ts` | Update `AgentInfo` and `AgentCapabilities` types |
| `server/packages/sandbox-agent/tests/v2_api.rs` | Update agent listing test assertions |
| `server/packages/sandbox-agent/tests/v1_api.rs` | Update agent listing test assertions |
### Docs to Update
| Doc | Change |
|-----|--------|
| `docs/openapi.json` | Update `/v2/agents` response schema with full `AgentCapabilities` |
| `docs/openapi.json` | Update `/v1/agents` response schema with full `AgentCapabilities` |
| `docs/sdks/typescript.mdx` | Document enriched agent listing |

View file

@ -4,12 +4,12 @@
## Summary
v1 exposed pre-session model/mode discovery via separate endpoints. For v2, models and modes should be optional fields on the agent response payload (only when the agent is installed), with lazy population for dynamic agents.
v1 exposed pre-session model/mode discovery via separate endpoints. For v1, models and modes should be optional fields on the agent response payload (only when the agent is installed), with lazy population for dynamic agents.
## Current v2 State
## Current v1 State
- `_sandboxagent/session/list_models` works but requires an active ACP connection and session
- `GET /v2/agents` does not include pre-session model/mode metadata
- `GET /v1/agents` does not include pre-session model/mode metadata
- v1 had static per-agent mode definitions (`agent_modes_for()` in `router.rs`)
- v1 had dynamic model fetching (Claude/Codex/OpenCode), plus static model lists for Amp/Mock
@ -57,11 +57,11 @@ Model variants are explicitly out of scope for this implementation pass.
| `server/packages/sandbox-agent/src/router.rs` | Enrich agent response type/handlers to optionally include models + modes |
| `server/packages/sandbox-agent/src/acp_runtime/mod.rs` | Expose model query support for control-plane enrichment without requiring an active session |
| `sdks/typescript/src/client.ts` | Extend `AgentInfo` type with optional `models`, `defaultModel`, `modes` |
| `server/packages/sandbox-agent/tests/v2_api.rs` | Add assertions for installed vs non-installed agent response shapes |
| `server/packages/sandbox-agent/tests/v1_api.rs` | Add assertions for installed vs non-installed agent response shapes |
## Docs to Update
| Doc | Change |
|-----|--------|
| `docs/openapi.json` | Update `/v2/agents` (and agent detail endpoint if present) schema with optional `models`/`modes` |
| `docs/openapi.json` | Update `/v1/agents` (and agent detail endpoint if present) schema with optional `models`/`modes` |
| `docs/sdks/typescript.mdx` | Document optional model/mode fields on agent response |

View file

@ -4,9 +4,9 @@
## Summary
v1 `MessageRequest.attachments` allowed sending file attachments (path, mime, filename) with prompts. v2 ACP `embeddedContext` is only partial. Need to support file attachments in prompt messages.
v1 `MessageRequest.attachments` allowed sending file attachments (path, mime, filename) with prompts. v1 ACP `embeddedContext` is only partial. Need to support file attachments in prompt messages.
## Current v2 State
## Current v1 State
- ACP `session/prompt` accepts `params.content` as the prompt text
- No attachment mechanism in the current ACP prompt flow
@ -122,7 +122,7 @@ The runtime extracts attachments from `_meta` and transforms them per agent:
| `server/packages/sandbox-agent/src/acp_runtime/mod.rs` | Extract `attachments` from `session/prompt` `_meta`; transform per agent before forwarding |
| `server/packages/sandbox-agent/src/acp_runtime/mock.rs` | Add mock handling for attachments |
| `sdks/typescript/src/client.ts` | Add `attachments` option to prompt method |
| `server/packages/sandbox-agent/tests/v2_api.rs` | Add attachment prompt test |
| `server/packages/sandbox-agent/tests/v1_api.rs` | Add attachment prompt test |
### Docs to Update

View file

@ -4,13 +4,13 @@
## Summary
v1 `CreateSessionRequest` had `mcp` (full MCP server config with OAuth, env headers, bearer tokens), `skills` (sources with git refs), `agent_version`, `directory`. v2 needs to support these at session creation time.
v1 `CreateSessionRequest` had `mcp` (full MCP server config with OAuth, env headers, bearer tokens), `skills` (sources with git refs), `agent_version`, `directory`. v1 needs to support these at session creation time.
## Current v2 State — MOSTLY IMPLEMENTED
## Current v1 State — MOSTLY IMPLEMENTED
Investigation shows that **most of these are already supported** via `_meta.sandboxagent.dev` passthrough in `session/new`:
| Field | v1 | v2 Status | v2 Mechanism |
| Field | v1 | v1 Status | v1 Mechanism |
|-------|-----|-----------|-------------|
| `directory` | `CreateSessionRequest.directory` | **Implemented** | `cwd` parameter extracted from payload |
| `agent_version` | `CreateSessionRequest.agent_version` | **Implemented** | `_meta.sandboxagent.dev.agentVersionRequested` (stored, forwarded) |

View file

@ -1,12 +1,12 @@
# Feature 16: Session Info
**Implementation approach:** New HTTP endpoints (`GET /v2/sessions`, `GET /v2/sessions/{id}`)
**Implementation approach:** New HTTP endpoints (`GET /v1/sessions`, `GET /v1/sessions/{id}`)
## Summary
v1 `SessionInfo` tracked `event_count`, `created_at`, `updated_at`, and full `mcp` config. v2 has session data in the ACP runtime's `MetaSession` struct but no HTTP endpoints to query it. Add REST endpoints for session listing and detail.
v1 `SessionInfo` tracked `event_count`, `created_at`, `updated_at`, and full `mcp` config. v1 has session data in the ACP runtime's `MetaSession` struct but no HTTP endpoints to query it. Add REST endpoints for session listing and detail.
## Current v2 State
## Current v1 State
### Internal Session Tracking
@ -117,15 +117,15 @@ fn build_session_info(state: &SessionState) -> SessionInfo {
### New HTTP Endpoints
```
GET /v2/sessions -> SessionListResponse
GET /v2/sessions/{id} -> SessionInfo
GET /v1/sessions -> SessionListResponse
GET /v1/sessions/{id} -> SessionInfo
```
These are control-plane HTTP endpoints (not ACP), providing session visibility without requiring an active ACP connection.
### Response Types
The v2 `SessionInfo` should be a superset of v1 fields, adapted for ACP:
The v1 `SessionInfo` should be a superset of v1 fields, adapted for ACP:
```rust
#[derive(Debug, Serialize, JsonSchema, ToSchema)]
@ -156,15 +156,15 @@ Need to add:
| File | Change |
|------|--------|
| `server/packages/sandbox-agent/src/router.rs` | Add `GET /v2/sessions` and `GET /v2/sessions/{id}` handlers; add response types |
| `server/packages/sandbox-agent/src/router.rs` | Add `GET /v1/sessions` and `GET /v1/sessions/{id}` handlers; add response types |
| `server/packages/sandbox-agent/src/acp_runtime/mod.rs` | Add `created_at` to `MetaSession`; add `ended` tracking; expose `list_sessions()` and `get_session()` public methods |
| `sdks/typescript/src/client.ts` | Add `listSessions()` and `getSession(id)` methods |
| `server/packages/sandbox-agent/tests/v2_api.rs` | Add session listing and detail tests |
| `server/packages/sandbox-agent/tests/v1_api.rs` | Add session listing and detail tests |
### Docs to Update
| Doc | Change |
|-----|--------|
| `docs/openapi.json` | Add `/v2/sessions` and `/v2/sessions/{id}` endpoint specs |
| `docs/openapi.json` | Add `/v1/sessions` and `/v1/sessions/{id}` endpoint specs |
| `docs/cli.mdx` | Add CLI `sessions list` and `sessions info` commands |
| `docs/sdks/typescript.mdx` | Document session listing SDK methods |

View file

@ -4,9 +4,9 @@
## Summary
v1 captured `exit_code`, structured `StderrOutput` (head/tail/truncated) when a session ended due to error. v2 loses this metadata. Need to capture and expose process termination details.
v1 captured `exit_code`, structured `StderrOutput` (head/tail/truncated) when a session ended due to error. v1 loses this metadata. Need to capture and expose process termination details.
## Current v2 State
## Current v1 State
- Agent process lifecycle is managed in `acp_runtime/mod.rs`
- Process exit is detected but error metadata (exit code, stderr) is not captured or forwarded
@ -171,7 +171,7 @@ When an agent process terminates with an error:
### Session Info Integration
Termination metadata should be accessible via:
- `GET /v2/sessions/{id}` (Feature #16) — include `terminationInfo` in response when session has ended
- `GET /v1/sessions/{id}` (Feature #16) — include `terminationInfo` in response when session has ended
- `session/list` ACP response — include termination status in session entries
### Files to Modify
@ -181,7 +181,7 @@ Termination metadata should be accessible via:
| `server/packages/sandbox-agent/src/acp_runtime/mod.rs` | Add stderr capture (head/tail buffer) on agent process; capture exit code; emit `_sandboxagent/session/ended`; store v1-shaped termination info in `MetaSession` |
| `server/packages/sandbox-agent/src/acp_runtime/mock.rs` | Add mock error termination scenario (e.g., when prompt contains "crash") |
| `sdks/typescript/src/client.ts` | Add `TerminationInfo` type; expose on session events and session info |
| `server/packages/sandbox-agent/tests/v2_api.rs` | Add error termination metadata test |
| `server/packages/sandbox-agent/tests/v1_api.rs` | Add error termination metadata test |
### Docs to Update

View file

@ -1,8 +1,8 @@
# Missing Features Index
Features selected for implementation from the v1-to-v2 gap analysis.
Features selected for implementation from the v1-to-v1 gap analysis.
## Completely UNIMPLEMENTED in v2
## Completely UNIMPLEMENTED in v1
| # | Feature | Implementation notes |
|---|---------|---------------------|
@ -12,19 +12,19 @@ Features selected for implementation from the v1-to-v2 gap analysis.
| 4 | **Filesystem API** -- all 8 endpoints (list, read, write, delete, mkdir, move, stat, upload-batch). ACP only has text-only `fs/read_text_file` + `fs/write_text_file` (agent->client direction). | |
| 5 | **Health endpoint** -- typed `HealthResponse` with status. | |
| 6 | **Server status** -- `ServerStatus` (Running/Stopped/Error), `ServerStatusInfo` (baseUrl, lastError, restartCount, uptimeMs). | |
| 7 | **Session termination** -- v1 had full `terminate`. v2 only has `session/cancel` (turn cancellation, not session kill). No explicit close/delete. | See existing ACP RFD |
| 7 | **Session termination** -- v1 had full `terminate`. v1 only has `session/cancel` (turn cancellation, not session kill). No explicit close/delete. | See existing ACP RFD |
| 8 | ~~Model variants~~ -- deferred for now. | Out of scope |
| 9 | ~~Agent capability flags~~ | Not selected |
| 10 | ~~`include_raw`~~ -- deferred for now. | Out of scope |
## Downgraded / Partial in v2
## Downgraded / Partial in v1
| # | Feature | Implementation notes |
|---|---------|---------------------|
| 11 | ~~Permission reply granularity~~ | Not selected |
| 12 | **Agent listing** -- v1 `GET /v1/agents` returned typed `AgentListResponse` with `installed`, `credentialsAvailable`, `path`, `capabilities`, `serverStatus`. v2 returns generic JSON. | |
| 12 | **Agent listing** -- v1 `GET /v1/agents` returned typed `AgentListResponse` with `installed`, `credentialsAvailable`, `path`, `capabilities`, `serverStatus`. v1 returns generic JSON. | |
| 13 | **Models/modes listing** -- expose as optional `models`/`modes` fields on agent response payloads (installed agents only), lazily populated. | No separate `/models` or `/modes` endpoints |
| 14 | **Message attachments** -- v1 `MessageRequest.attachments` (path, mime, filename). v2 ACP `embeddedContext` is only partial. | |
| 14 | **Message attachments** -- v1 `MessageRequest.attachments` (path, mime, filename). v1 ACP `embeddedContext` is only partial. | |
| 15 | **Session creation richness** -- v1 `CreateSessionRequest` had `mcp` (full MCP server config with OAuth, env headers, bearer tokens), `skills` (sources with git refs), `agent_version`, `directory`. Most have no ACP equivalent. | Check with our extensions, do not implement if already done |
| 16 | **Session info** -- v1 `SessionInfo` tracked `event_count`, `created_at`, `updated_at`, full `mcp` config. Mostly lost. | Add as sessions HTTP endpoint |
| 17 | **Error termination metadata** -- v1 captured `exit_code`, structured `StderrOutput` (head/tail/truncated). Gone. | |

View file

@ -1,14 +1,14 @@
# Missing Features Implementation Plan
Features selected from the v1-to-v2 gap analysis, ordered for implementation.
Features selected from the v1-to-v1 gap analysis, ordered for implementation.
## Confirmed Decisions (Locked)
- Canonical extension naming is `_sandboxagent/...` and `_meta["sandboxagent.dev"]`; remove/ignore `_sandboxagent/*`.
- Control-plane discovery/status/session APIs are HTTP-only under `/v2/*` (no ACP control-plane equivalents).
- Control-plane discovery/status/session APIs are HTTP-only under `/v1/*` (no ACP control-plane equivalents).
- For Health, Filesystem, and Attachments, implementation should port behavior from v1 using commit `8ecd27bc24e62505d7aa4c50cbdd1c9dbb09f836`.
- Session termination via `_sandboxagent/session/terminate` is idempotent.
- `DELETE /v2/rpc` is transport detach only; it must not replace explicit termination semantics.
- `DELETE /v1/rpc` is transport detach only; it must not replace explicit termination semantics.
- Model variants (#8) are removed from current scope.
- `include_raw` (#10) is removed from current scope.
- Models/modes should be optional properties on agent response payloads (only when the agent is installed) and lazily populated.
@ -24,9 +24,9 @@ These features enrich existing endpoints and have no dependencies on each other.
| Order | Feature | Spec | Approach | Effort |
|:-----:|----------------------------------------------|:----:|--------------------------------------------|:------:|
| A1 | [Health Endpoint](./05-health-endpoint.md) | #5 | Port v1 health behavior to `GET /v2/health` | Small |
| A1 | [Health Endpoint](./05-health-endpoint.md) | #5 | Port v1 health behavior to `GET /v1/health` | Small |
| A2 | [Server Status](./06-server-status.md) | #6 | Add process tracking to ACP runtime | Medium |
| A3 | [Agent Listing](./12-agent-listing.md) | #12 | Enrich `GET /v2/agents` with v1-parity data | Medium |
| A3 | [Agent Listing](./12-agent-listing.md) | #12 | Enrich `GET /v1/agents` with v1-parity data | Medium |
**A2 blocks A3** — agent listing includes server status from Feature #6.
@ -36,7 +36,7 @@ Session-level features that build on Phase A runtime tracking.
| Order | Feature | Spec | Approach | Effort |
|:-----:|--------------------------------------------------------------|:----:|------------------------------------------------------|:------:|
| B1 | [Session Info](./16-session-info.md) | #16 | New `GET /v2/sessions` and `GET /v2/sessions/{id}` | Medium |
| B1 | [Session Info](./16-session-info.md) | #16 | New `GET /v1/sessions` and `GET /v1/sessions/{id}` | Medium |
| B2 | [Session Termination](./07-session-termination.md) | #7 | Idempotent `_sandboxagent/session/terminate` | Medium |
| B3 | [Error Termination Metadata](./17-error-termination-metadata.md) | #17 | Stderr capture + `_sandboxagent/session/ended` event | Medium |
@ -72,7 +72,7 @@ Standalone platform-level API.
| Order | Feature | Spec | Approach | Effort |
|:-----:|---------------------------------------|:----:|----------------------------------|:------:|
| E1 | [Filesystem API](./04-filesystem-api.md) | #4 | Port v1 behavior to `/v2/fs/*` | Large |
| E1 | [Filesystem API](./04-filesystem-api.md) | #4 | Port v1 behavior to `/v1/fs/*` | Large |
No dependencies on other features. Can be implemented at any time but is the largest single feature.
@ -97,7 +97,7 @@ E1 (Filesystem) [independent]
| # | Feature | Spec File | Status | Approach |
|:--:|---------------------------------|-------------------------------------------------------|---------------------------------|-------------------------------------------------|
| 1 | ~~Questions~~ | [01-questions.md](./01-questions.md) | Deferred ([#156](https://github.com/rivet-dev/sandbox-agent/issues/156)) | Agent process side |
| 4 | Filesystem API | [04-filesystem-api.md](./04-filesystem-api.md) | Not implemented | Port v1 behavior onto `/v2/fs/*` |
| 4 | Filesystem API | [04-filesystem-api.md](./04-filesystem-api.md) | Not implemented | Port v1 behavior onto `/v1/fs/*` |
| 5 | Health Endpoint | [05-health-endpoint.md](./05-health-endpoint.md) | Partial (basic only) | Port v1 health behavior |
| 6 | Server Status | [06-server-status.md](./06-server-status.md) | Not implemented | Runtime tracking |
| 7 | Session Termination | [07-session-termination.md](./07-session-termination.md) | Not implemented | Idempotent ACP extension |
@ -121,7 +121,7 @@ E1 (Filesystem) [independent]
| `sdks/typescript/src/client.ts` | All in-scope features |
| `docs/openapi.json` | #4, #5, #6, #12, #13, #16 |
| `docs/sdks/typescript.mdx` | All in-scope features |
| `server/packages/sandbox-agent/tests/v2_api.rs` | All in-scope features |
| `server/packages/sandbox-agent/tests/v1_api.rs` | All in-scope features |
### Docs update checklist

View file

@ -1,7 +1,7 @@
## Sources
- Old OpenAPI path: `docs/openapi.json` at git ref `8ecd27b`
- ACP v2 API path: `~/misc/acp-docs/schema/schema.json` (`~/misc/acp-docs/schema/schema.unstable.json` for unstable methods)
- ACP v1 API path: `~/misc/acp-docs/schema/schema.json` (`~/misc/acp-docs/schema/schema.unstable.json` for unstable methods)
| Path / Schema Property | ACP Equivalent |
| --- | --- |

View file

@ -11,11 +11,11 @@ Status date: 2026-02-10
| Stabilize `session/resume` | RFD | Use ACP unstable `session/resume` directly (no custom extension alias). | Currently unstable ACP method. |
| Stabilize `session/set_model` | RFD | Use ACP unstable `session/set_model` directly; fallback to `session/set_config_option` where available. | Currently unstable ACP method. |
| Standard session metadata-at-creation semantics (portable title/tags-style hints) | RFD | Use `session/new.params._meta["sandboxagent.dev"]` for create-time metadata; optional `_sandboxagent/session/set_metadata` for post-create updates. | Reduces custom `_meta` usage for common metadata. |
| Sandbox Agent robust HTTP filesystem API | Extension | Already extension (`/v2/fs/*` custom HTTP surface). | Separate custom HTTP API; not ACP core agent-session protocol. |
| Sandbox Agent robust HTTP filesystem API | Extension | Already extension (`/v1/fs/*` custom HTTP surface). | Separate custom HTTP API; not ACP core agent-session protocol. |
| `skills` payload and behavior | Extension | Already extension via `_meta["sandboxagent.dev"].skills` and optional `_sandboxagent/session/set_metadata`. | Product-specific behavior. |
| Client-requested session alias (`requestedSessionId`) behavior | Extension | Already extension via `_meta["sandboxagent.dev"].requestedSessionId`. | Product-specific metadata/ID behavior. |
| Agent version pin/hint behavior during bootstrap/session creation | Extension | Already extension via `_meta["sandboxagent.dev"].agentVersionRequested`. | Product-specific runtime selection behavior. |
| Agent control-plane inventory/install state (`list/install/credentialsAvailable/installed/path`) | Extension | Already extension as custom control-plane HTTP (`/v2/agents`, `/v2/agents/{agent}/install`). | Control-plane functionality outside ACP core. |
| Runtime daemon/process status and related capabilities (`serverStatus`, `sharedProcess`, `commandExecution`, `errorEvents`) | Extension | Already extension as control-plane fields (`/v2/agents`, `/v2/health`) and capability `_meta` hints. | Runtime/orchestrator-specific state. |
| Sandbox Agent control-plane APIs (`/v2/health`, `/v2/agents`, `/v2/agents/{agent}/install`) | Extension | Already extension (custom non-ACP API surface). | Custom non-ACP HTTP surface. |
| Agent control-plane inventory/install state (`list/install/credentialsAvailable/installed/path`) | Extension | Already extension as custom control-plane HTTP (`/v1/agents`, `/v1/agents/{agent}/install`). | Control-plane functionality outside ACP core. |
| Runtime daemon/process status and related capabilities (`serverStatus`, `sharedProcess`, `commandExecution`, `errorEvents`) | Extension | Already extension as control-plane fields (`/v1/agents`, `/v1/health`) and capability `_meta` hints. | Runtime/orchestrator-specific state. |
| Sandbox Agent control-plane APIs (`/v1/health`, `/v1/agents`, `/v1/agents/{agent}/install`) | Extension | Already extension (custom non-ACP API surface). | Custom non-ACP HTTP surface. |
| OpenCode compatibility bridging behavior (`/opencode/*`) | Extension | Already extension as product compatibility bridge layer. | Product compatibility layer, not ACP core protocol. |

View file

@ -0,0 +1,242 @@
# ACP Simplified Server Spec
## 1) Scope and Intent
This spec replaces the current ACP runtime model with a simple stdio proxy model:
- Sandbox Agent becomes a **dumb ACP HTTP <-> stdio proxy**.
- ACP transport moves from `/v1/rpc` to `/v1/acp/{server_id}`.
- `server_id` is client-provided and is the only ACP transport identity.
- No server-side ACP extensions and no custom metadata processing.
- Session metadata/state moves to clients.
- Non-ACP functionality is exposed as HTTP endpoints.
Backwards compatibility is explicitly out of scope.
## 2) Hard Breaking Changes
- Remove `/v1/rpc` (`POST`, `GET`, `DELETE`) completely.
- Remove ACP extension support (`_sandboxagent/*`) completely.
- Remove ACP metadata contract (`params._meta["sandboxagent.dev"]`) from runtime behavior.
- Disable OpenCode compatibility completely (`/opencode/*` not mounted).
- Remove server-side session registry semantics tied to ACP transport.
## 3) ACP Transport
### 3.1 Endpoints
For each client-defined `{server_id}`:
- `POST /v1/acp/{server_id}`
- `GET /v1/acp/{server_id}` (SSE)
- `DELETE /v1/acp/{server_id}`
Control-plane ACP transport endpoint:
- `GET /v1/acp` (list active ACP transport instances)
No connection-id header is used.
### 3.2 Bootstrap / Creation
A transport instance is created lazily on first `POST`.
- First `POST` to a new `{server_id}` **must include `agent`** as query parameter:
- `POST /v1/acp/{server_id}?agent=claude`
- Server behavior on first `POST`:
1. Validate agent id.
2. Lazy-install binaries if missing (current install policy retained).
3. Lazy-start one ACP stdio process for this `{server_id}`.
4. Forward JSON-RPC payload to that process.
Behavior for existing `{server_id}`:
- `agent` query param is optional.
- If provided and mismatched with existing bound agent, return `409 Conflict`.
If `{server_id}` does not exist and no `agent` is provided, return `400 Bad Request`.
### 3.3 Message Semantics
Sandbox Agent does not inspect ACP method semantics.
- `POST` accepts one JSON-RPC envelope.
- If envelope is request (`method` + `id`): wait for matching stdio response and return `200` + JSON body.
- If envelope is notification or response without `method`: forward and return `202` empty.
- `GET` streams agent->client messages as SSE.
- Replay semantics remain: `Last-Event-ID` supported using in-memory ring buffer per `{server_id}`.
- `DELETE` closes `{server_id}` transport instance and terminates subprocess.
### 3.4 SSE Framing
Same framing as current transport profile:
- `event: message`
- `id: <monotonic sequence per server_id>`
- `data: <single JSON-RPC object>`
- keepalive comment heartbeat every 15s
### 3.5 Process Model
- One ACP process per `{server_id}`.
- Multiple `{server_id}` can target the same agent type.
- Each `{server_id}` has isolated pending requests and replay buffer.
### 3.6 Error Mapping
- Invalid JSON envelope: `400 application/problem+json`
- Missing/invalid content type: `415`
- Unknown agent: `400`
- Unknown `{server_id}` for `GET`/`DELETE`/non-bootstrap `POST`: `404`
- Agent mismatch on existing `{server_id}`: `409`
- Timeout waiting for request response: `504`
- Subprocess spawn/write/read failures: `502`
- Successful `DELETE`: `204` (idempotent)
## 4) ACP Adapter Integration
Sandbox Agent reuses `acp-http-adapter` runtime internals for per-server stdio bridging.
- ACP stdio framing follows ACP docs (UTF-8, newline-delimited JSON-RPC).
- No synthetic `_sandboxagent/*` ACP messages are emitted.
- No transport-level metadata injection or translation.
- Sandbox Agent only performs HTTP routing/lifecycle and subprocess orchestration.
## 5) HTTP Endpoints for Non-ACP Features
These are the proposed HTTP surfaces to review.
### 5.1 Agents
- `GET /v1/agents`
- List known agents + install/runtime status.
- `POST /v1/agents/{agent}/install`
- Trigger install/reinstall with existing options.
### 5.2 Filesystem
All filesystem operations are HTTP-only (no ACP extension mirrors):
- `GET /v1/fs/entries`
- `GET /v1/fs/file`
- `PUT /v1/fs/file`
- `DELETE /v1/fs/entry`
- `POST /v1/fs/mkdir`
- `POST /v1/fs/move`
- `GET /v1/fs/stat`
- `POST /v1/fs/upload-batch`
### 5.3 MCP Config (HTTP)
Directory-scoped MCP config endpoints (copy v1 `mcp` config shape, but bind to `directory` instead of session init):
- `GET /v1/config/mcp?directory=<...>&mcpName=<name>`
- Returns one MCP entry by name.
- `PUT /v1/config/mcp?directory=<...>&mcpName=<name>`
- Upserts one MCP entry by name.
- `DELETE /v1/config/mcp?directory=<...>&mcpName=<name>`
- Deletes one MCP entry by name.
Notes:
- Entry payload schema is v1-compatible MCP server config:
- same as one value from legacy `CreateSessionRequest.mcp[<name>]`.
- supports both local (stdio) and remote (http/sse) server forms.
- `directory` is required on all MCP config operations.
- `mcpName` is required on all MCP config operations.
- Server stores/retrieves config only and does not inject ACP payload metadata.
### 5.4 Skills Config (HTTP)
Directory-scoped Skills config endpoints (copy v1 skills config shape, but bind to `directory` instead of session init):
- `GET /v1/config/skills?directory=<...>&skillName=<name>`
- Returns one skill entry by name.
- `PUT /v1/config/skills?directory=<...>&skillName=<name>`
- Upserts one skill entry by name.
- `DELETE /v1/config/skills?directory=<...>&skillName=<name>`
- Deletes one skill entry by name.
Notes:
- Entry payload schema is v1-compatible skills config:
- same source object semantics as legacy `CreateSessionRequest.skills`.
- includes `sources` behavior and compatible source options.
- `directory` is required on all skill config operations.
- `skillName` is required on all skill config operations.
- No ACP-side mutation/injection by server.
## 6) Session Metadata Ownership
Server no longer owns ACP session metadata.
- No `_sandboxagent/session/set_metadata`.
- No `_sandboxagent/session/list` / `_sandboxagent/session/get`.
- Client owns session indexing, labels, and metadata persistence.
- `GET /v1/acp`
- Required endpoint.
- Returns active `{server_id}` instances and process status only.
## 7) Security/Auth
- Existing bearer token auth remains for `/v1/*` when enabled.
- Auth is enforced at HTTP layer only.
- No extra principal scoping inside ACP runtime beyond route auth.
## 8) Testing Requirements
Minimum required coverage:
- ACP proxy e2e for request/response/notification/SSE replay on `/v1/acp/{server_id}`.
- Multi-instance isolation (`server-a`, `server-b`, same agent).
- Lazy install/start on first POST bootstrap.
- Idempotent `DELETE` + cleanup.
- Explicit regression test that `_sandboxagent/*` methods are not handled specially.
## 9) Implementation Checklist
1. Add new router surface `/v1/acp/{server_id}` and remove `/v1/rpc`.
2. Replace current ACP runtime method handling with per-server dumb proxy runtime.
3. Remove extension metadata advertisement/handlers.
4. Remove OpenCode router mount.
5. Keep/add HTTP endpoints listed in section 5.
6. Update OpenAPI/docs to reflect new transport and removed ACP extensions.
## 10) Final HTTP Endpoint Inventory
Expected HTTP endpoints after migration:
- `GET /`
- `GET /v1/health`
- `GET /v1/acp`
- `POST /v1/acp/{server_id}`
- `GET /v1/acp/{server_id}`
- `DELETE /v1/acp/{server_id}`
- `GET /v1/agents`
- `POST /v1/agents/{agent}/install`
- `GET /v1/fs/entries`
- `GET /v1/fs/file`
- `PUT /v1/fs/file`
- `DELETE /v1/fs/entry`
- `POST /v1/fs/mkdir`
- `POST /v1/fs/move`
- `GET /v1/fs/stat`
- `POST /v1/fs/upload-batch`
- `GET /v1/config/mcp?directory=...&mcpName=...`
- `PUT /v1/config/mcp?directory=...&mcpName=...`
- `DELETE /v1/config/mcp?directory=...&mcpName=...`
- `GET /v1/config/skills?directory=...&skillName=...`
- `PUT /v1/config/skills?directory=...&skillName=...`
- `DELETE /v1/config/skills?directory=...&skillName=...`
Removed/disabled surfaces:
- `/v1/rpc` removed.
- `/opencode/*` disabled/unmounted.
- No `_sandboxagent/*` ACP extension behavior.

View file

@ -1,8 +1,8 @@
# V2 Spec: ACP Over HTTP
# V1 Spec: ACP Over HTTP
## 0) Delete/Remove First
Before implementing v2, remove in-house protocol files and remove v1 API behavior as documented in:
Before implementing v1, remove in-house protocol files and remove v1 API behavior as documented in:
- `research/acp/00-delete-first.md`
- `research/acp/v1-schema-to-acp-mapping.md` (endpoint/event-by-event conversion target)
@ -11,16 +11,16 @@ This is mandatory to prevent dual-protocol drift.
## 1) Goals
- v2 is intentionally breaking and ACP-native.
- v1 is intentionally breaking and ACP-native.
- Internal runtime uses ACP end-to-end (no custom universal event schema).
- Existing agent managers are replaced with ACP agent process runtimes.
- v1 API is completely removed; all `/v1/*` requests return explicit removed errors.
- OpenCode <-> ACP support is preserved as a product requirement, but implemented in a separate step after ACP core is stable.
## 2) Non-goals for first v2 cut
## 2) Non-goals for first v1 cut
- No guarantee of v1 endpoint compatibility.
- No v1 compatibility layer in the initial v2 release.
- No v1 compatibility layer in the initial v1 release.
- No OpenCode compatibility during ACP core bring-up (`/opencode/*` is disabled until the dedicated bridge step).
- No in-house universal event format.
@ -40,7 +40,7 @@ Supported client methods (minimum):
- `session/request_permission`
Included unstable ACP methods for v2 profile:
Included unstable ACP methods for v1 profile:
- `session/list`
- `session/fork`
@ -69,9 +69,9 @@ ACP streamable HTTP is draft upstream, so this spec defines a concrete transport
### 4.1 Endpoints
- `POST /v2/rpc`
- `GET /v2/rpc` (SSE stream, `Accept: text/event-stream`)
- `DELETE /v2/rpc` (explicit connection close)
- `POST /v1/rpc`
- `GET /v1/rpc` (SSE stream, `Accept: text/event-stream`)
- `DELETE /v1/rpc` (explicit connection close)
### 4.2 Connection model
@ -81,15 +81,15 @@ ACP streamable HTTP is draft upstream, so this spec defines a concrete transport
- Connection identity is `X-ACP-Connection-Id` header.
- First `initialize` request may omit `X-ACP-Connection-Id` and must include `params._meta["sandboxagent.dev"].agent`.
- Server ensures backend exists for that agent, creates connection, returns `X-ACP-Connection-Id` in response headers.
- All subsequent `POST /v2/rpc` and `GET /v2/rpc` requests must include `X-ACP-Connection-Id`.
- `DELETE /v2/rpc` with `X-ACP-Connection-Id` detaches/closes only the transport connection and releases connection-scoped resources.
- `DELETE /v2/rpc` does not terminate the session or agent process. Session termination is explicit via `_sandboxagent/session/terminate`.
- All subsequent `POST /v1/rpc` and `GET /v1/rpc` requests must include `X-ACP-Connection-Id`.
- `DELETE /v1/rpc` with `X-ACP-Connection-Id` detaches/closes only the transport connection and releases connection-scoped resources.
- `DELETE /v1/rpc` does not terminate the session or agent process. Session termination is explicit via `_sandboxagent/session/terminate`.
### 4.3 Message routing
- Client -> agent requests/notifications: sent as JSON-RPC payloads to `POST /v2/rpc`.
- Agent -> client notifications/requests: delivered on `GET /v2/rpc` SSE stream as JSON-RPC envelopes.
- Client replies to agent-initiated requests by POSTing JSON-RPC responses to `POST /v2/rpc`.
- Client -> agent requests/notifications: sent as JSON-RPC payloads to `POST /v1/rpc`.
- Agent -> client notifications/requests: delivered on `GET /v1/rpc` SSE stream as JSON-RPC envelopes.
- Client replies to agent-initiated requests by POSTing JSON-RPC responses to `POST /v1/rpc`.
### 4.4 SSE framing
@ -112,9 +112,9 @@ Resume:
- Invalid envelope: HTTP 400 with `application/problem+json`.
- Unknown connection: HTTP 404 with `application/problem+json`.
- Server timeout waiting on agent process response: HTTP 504 with `application/problem+json`.
- Successful `DELETE /v2/rpc`: HTTP 204.
- Repeated `DELETE /v2/rpc` on an already-closed connection: HTTP 204 (idempotent close).
- All `/v1/*` endpoints: HTTP 410 with `application/problem+json` and message `v1 API removed; use /v2`.
- Successful `DELETE /v1/rpc`: HTTP 204.
- Repeated `DELETE /v1/rpc` on an already-closed connection: HTTP 204 (idempotent close).
- All `/v1/*` endpoints: HTTP 410 with `application/problem+json` and message `v1 API removed; use /v1`.
Note: ACP method-level failures still return JSON-RPC error objects inside 200 responses.
@ -127,7 +127,7 @@ Note: ACP method-level failures still return JSON-RPC error objects inside 200 r
### 4.7 Security
- Reuse existing bearer token auth middleware.
- Validate bearer auth at request time for `/v2/*` routes when configured.
- Validate bearer auth at request time for `/v1/*` routes when configured.
- ACP runtime connection ids are in-memory server ids and are not additionally principal-scoped inside runtime.
- Do not expose agent process stderr on stdout channel.
@ -141,8 +141,8 @@ Based on current ACP community implementations/discussion:
Decision for this repo:
- v2 public transport remains Streamable HTTP (`POST`/`GET` SSE over `/v2/rpc`) as the canonical contract.
- WebSocket transport is not part of initial v2 surface; consider later only if HTTP profile proves insufficient operationally.
- v1 public transport remains Streamable HTTP (`POST`/`GET` SSE over `/v1/rpc`) as the canonical contract.
- WebSocket transport is not part of initial v1 surface; consider later only if HTTP profile proves insufficient operationally.
Reference:
@ -160,7 +160,7 @@ Replace custom per-agent protocol parsers with one ACP agent process process con
## 5.2 Installers
Current auto-installer installs native CLIs. v2 installer must install:
Current auto-installer installs native CLIs. v1 installer must install:
- native agent binary (if needed by agent process)
- ACP agent process binary required for that agent
@ -170,13 +170,13 @@ Add a manifest-driven mapping (new file to create in implementation phase):
- `claude`: agent process `claude-code-acp`
- `codex`: agent process `codex-acp`
- `opencode`: native ACP mode (agent process optional)
- `amp`: pending decision (official agent process required or unsupported in v2 initial release)
- `amp`: pending decision (official agent process required or unsupported in v1 initial release)
## 5.3 ACP Registry install instructions
Yes, this must be handled.
V2 installer/docs must include install instructions sourced from ACP registry metadata where available, with explicit fallback for non-registry agent processes.
V1 installer/docs must include install instructions sourced from ACP registry metadata where available, with explicit fallback for non-registry agent processes.
Requirements:
@ -194,8 +194,8 @@ Requirements:
Output surfaces:
- `GET /v2/agents`: include agent process install source + verification status.
- `POST /v2/agents/{agent}/install`: return concrete installed artifacts and source provenance.
- `GET /v1/agents`: include agent process install source + verification status.
- `POST /v1/agents/{agent}/install`: return concrete installed artifacts and source provenance.
## 5.4 Install commands and lazy agent process install
@ -203,12 +203,12 @@ This must match current ergonomics where installs can be explicit or automatic.
Explicit install interfaces:
- API: `POST /v2/agents/{agent}/install`
- CLI (v2 surface): `sandbox-agent api v2 agents install <agent> [--reinstall] [--agent-version <v>] [--agent process-version <v>]`
- API: `POST /v1/agents/{agent}/install`
- CLI (v1 surface): `sandbox-agent api v1 agents install <agent> [--reinstall] [--agent-version <v>] [--agent process-version <v>]`
Lazy install behavior (default on):
- Trigger point: first ACP bootstrap request (`initialize`) on `/v2/rpc` with `params._meta["sandboxagent.dev"].agent`.
- Trigger point: first ACP bootstrap request (`initialize`) on `/v1/rpc` with `params._meta["sandboxagent.dev"].agent`.
- If required binaries are missing, server installs:
- ACP agent process
- native agent binary if agent process requires it
@ -221,28 +221,28 @@ Operational requirements:
- Clear provenance in result (`registry` vs `fallback`) plus concrete artifact versions.
- Config switch to disable lazy install (`require_preinstall=true`) for controlled environments.
## 6) Public v2 API shape
## 6) Public v1 API shape
Expose ACP directly, not custom session endpoints.
- `POST /v2/rpc`: transport write path
- `GET /v2/rpc`: transport read path (SSE)
- `POST /v1/rpc`: transport write path
- `GET /v1/rpc`: transport read path (SSE)
Non-ACP endpoints retained in v2:
Non-ACP endpoints retained in v1:
- `GET /v2/health`
- `GET /v2/agents` (capabilities + install status)
- `POST /v2/agents/{agent}/install`
- `GET /v2/sessions`
- `GET /v2/sessions/{id}`
- `GET /v2/fs/file`
- `PUT /v2/fs/file`
- `POST /v2/fs/upload-batch`
- `GET /v1/health`
- `GET /v1/agents` (capabilities + install status)
- `POST /v1/agents/{agent}/install`
- `GET /v1/sessions`
- `GET /v1/sessions/{id}`
- `GET /v1/fs/file`
- `PUT /v1/fs/file`
- `POST /v1/fs/upload-batch`
- `GET /ui/` (Inspector UI shell)
Agent discovery note:
- Do not add standalone `/v2/agents/{agent}/models` or `/v2/agents/{agent}/modes` endpoints.
- Do not add standalone `/v1/agents/{agent}/models` or `/v1/agents/{agent}/modes` endpoints.
- Expose optional `models`/`modes` properties on agent response payloads when the agent is installed.
Legacy endpoints retained only as removals:
@ -261,9 +261,9 @@ Rationale:
- ACP `fs/*` methods are agent-protocol capabilities and can vary by agent implementation.
- Sandbox Agent filesystem HTTP endpoints are host/runtime capabilities and should behave consistently across all agents.
- Large binary transfers (raw file read/write and tar upload) need streaming-friendly HTTP behavior; ACP JSON-RPC envelopes are not suitable for super-large binary payload transport.
- `GET /v2/fs/file` specifically benefits from HTTP response streaming for large reads.
- `GET /v1/fs/file` specifically benefits from HTTP response streaming for large reads.
For this reason, `GET /v2/fs/file`, `PUT /v2/fs/file`, and `POST /v2/fs/upload-batch` remain dedicated HTTP endpoints even as other static control APIs migrate to ACP extensions.
For this reason, `GET /v1/fs/file`, `PUT /v1/fs/file`, and `POST /v1/fs/upload-batch` remain dedicated HTTP endpoints even as other static control APIs migrate to ACP extensions.
Parallel ACP compatibility is still supported:
@ -289,7 +289,7 @@ Rules:
## 6.2 Inspector (mandatory)
The inspector must be ACP-native in v2.
The inspector must be ACP-native in v1.
- Replace v1 session/event calls in inspector with ACP-over-HTTP connection flow (`initialize`, `session/new`, `session/prompt`, streamed `session/update`).
- Add inspector support for rendering raw ACP envelopes and decoded session updates.
@ -310,12 +310,12 @@ Added:
- raw ACP JSON-RPC envelopes over HTTP
- explicit connection identity (`X-ACP-Connection-Id`)
## 8) Test contract for v2
## 8) Test contract for v1
Consolidated must-have suites (duplicates collapsed):
- ACP protocol conformance (JSON-RPC + ACP schema/semantics)
- Transport contract (`/v2/rpc` POST/SSE routing, ordering, replay, errors)
- Transport contract (`/v1/rpc` POST/SSE routing, ordering, replay, errors)
- End-to-end agent process matrix (includes core turn flow, cancel, HITL, streaming)
- Installer suite (explicit + lazy install, registry/fallback provenance)
- Security/auth isolation
@ -333,11 +333,11 @@ Minimum required `agent-browser` inspector coverage:
Current automation entrypoint:
- `frontend/packages/inspector/tests/agent-browser.e2e.sh`
- `server/packages/sandbox-agent/tests/v2_agent_process_matrix.rs` (deterministic agent process matrix smoke + JSON-RPC conformance checks)
- `server/packages/sandbox-agent/tests/v1_agent_process_matrix.rs` (deterministic agent process matrix smoke + JSON-RPC conformance checks)
## 9) Open questions to resolve before implementation lock
- Amp agent process availability and support level for v2 launch.
- Amp agent process availability and support level for v1 launch.
- Whether additional non-binary filesystem endpoints remain HTTP or migrate to ACP extensions after initial cut.
## 10) Deferred Dedicated Step: OpenCode <-> ACP
@ -359,8 +359,8 @@ Current automation entrypoint:
When implementing this spec, update docs in the same change set:
- API reference/openapi docs for v2 and `/v1/*` removal semantics
- `docs/cli.mdx` for v2 ACP and removed v1 commands
- API reference/openapi docs for v1 and `/v1/*` removal semantics
- `docs/cli.mdx` for v1 ACP and removed v1 commands
- `docs/inspector.mdx` for ACP-based inspector behavior
- SDK docs (`docs/sdks/typescript.mdx`) for ACP-over-HTTP transport usage
- Any OpenCode compatibility docs that reference `/opencode/*`

View file

@ -1,4 +1,4 @@
# ACP v2 Migration TODO
# ACP v1 Migration TODO
Source docs:
- `research/acp/spec.md`
@ -34,15 +34,15 @@ Implementation:
- [x] Implement agent process process manager (spawn/supervise baseline).
- [x] Implement JSON-RPC bridge (`POST`/SSE <-> agent process stdio).
- [x] Add connection registry keyed by `X-ACP-Connection-Id`.
- [x] Implement unstable methods in v2 profile: `session/list`, `session/fork`, `session/resume`, `session/set_model`, `$/cancel_request`.
- [x] Implement explicit close path: `DELETE /v2/rpc`.
- [x] Implement unstable methods in v1 profile: `session/list`, `session/fork`, `session/resume`, `session/set_model`, `$/cancel_request`.
- [x] Implement explicit close path: `DELETE /v1/rpc`.
Validation gate:
- [x] End-to-end ACP flow over `/v2/rpc` (request/response + streamed notifications).
- [x] End-to-end ACP flow over `/v1/rpc` (request/response + streamed notifications).
- [x] `session/cancel` behavior test passes.
- [x] HITL request/response round-trip test passes.
- [x] SSE ordering and `Last-Event-ID` replay test passes.
- [x] `DELETE /v2/rpc` idempotent double-close test passes.
- [x] `DELETE /v1/rpc` idempotent double-close test passes.
- [x] Unstable method tests pass for agent processes that advertise support (mock covered).
## Phase 3: Installer Refactor
@ -54,7 +54,7 @@ Implementation:
- [x] Add install verification command per agent process.
- [x] Integrate ACP registry metadata + fallback sources.
- [x] Expose install provenance (`registry` vs `fallback`) in API/CLI.
- [x] Implement lazy install on first `/v2/rpc` initialize.
- [x] Implement lazy install on first `/v1/rpc` initialize.
- [x] Add per-agent install lock + idempotent install results.
- [x] Add config switch to disable lazy install for preprovisioned envs (`SANDBOX_AGENT_REQUIRE_PREINSTALL`).
- [ ] Fill out installers for all ACP registry agents (expand `AgentId` + per-agent installer mappings).
@ -65,25 +65,25 @@ Validation gate:
- [x] Reinstall/version/provenance assertions pass.
- [ ] Add integration coverage that every ACP registry agent has a corresponding installer mapping in `agent-management`.
## Phase 4: v2 HTTP API
## Phase 4: v1 HTTP API
Implementation:
- [x] Mount `POST /v2/rpc` and `GET /v2/rpc` (SSE).
- [x] Mount `DELETE /v2/rpc` close endpoint.
- [x] Add `GET /v2/health`, `GET /v2/agents`, `POST /v2/agents/{agent}/install`.
- [x] Mount `POST /v1/rpc` and `GET /v1/rpc` (SSE).
- [x] Mount `DELETE /v1/rpc` close endpoint.
- [x] Add `GET /v1/health`, `GET /v1/agents`, `POST /v1/agents/{agent}/install`.
- [x] Integrate auth on ACP client lifecycle.
- [x] Keep `/ui/` and migrate inspector backend calls to ACP v2 transport.
- [x] Keep `/ui/` and migrate inspector backend calls to ACP v1 transport.
- [x] Remove v1 OpenAPI surface from generated docs contract.
Validation gate:
- [x] Contract tests for `/v2` endpoints pass.
- [x] Contract tests for `/v1` endpoints pass.
- [x] Auth tests pass (valid/missing/invalid token).
- [x] `/v1/*` removal contract test passes (HTTP 410 + stable payload).
- [x] Inspector ACP `agent-browser` flow test passes.
- [x] `DELETE /v2/rpc` close contract tests pass.
- [x] `DELETE /v1/rpc` close contract tests pass.
- [x] Error mapping tests are complete for every documented error path.
## Phase 5: SDK and CLI v2
## Phase 5: SDK and CLI v1
Implementation:
- [x] Embed `@agentclientprotocol/sdk` in `sdks/typescript`.
@ -91,7 +91,7 @@ Implementation:
- [x] Wire inspector frontend client to ACP-over-HTTP primitives.
- [x] Add CLI commands for raw ACP envelopes + streaming ACP messages.
- [x] Remove or hard-fail v1-only SDK/CLI methods (`v1 removed`).
- [x] Regenerate docs for v2 ACP contract.
- [x] Regenerate docs for v1 ACP contract.
Validation gate:
- [x] TypeScript SDK end-to-end tests pass in embedded mode.
@ -105,7 +105,7 @@ Implementation:
- [x] Replace v1 HTTP/session tests with ACP transport contract tests (core server + SDK).
- [x] Add smoke tests per supported agent process (claude/codex/opencode covered with deterministic ACP agent process stubs).
- [x] Add canary docs + migration notes.
- [x] Update docs for v2 ACP, `/v1/*` removal, inspector ACP behavior, and SDK usage.
- [x] Update docs for v1 ACP, `/v1/*` removal, inspector ACP behavior, and SDK usage.
- [x] Keep `/v1/*` hard-removed (HTTP 410).
Validation gate:
@ -122,9 +122,9 @@ Notes:
Implementation:
- [x] Keep `/opencode/*` disabled through Phases 1-6.
- [ ] Implement OpenCode <-> ACP bridge on top of v2 ACP runtime.
- [ ] Implement OpenCode <-> ACP bridge on top of v1 ACP runtime.
- [ ] Re-enable `server/packages/sandbox-agent/src/opencode_compat.rs` routes/tests.
- [ ] Add dedicated integration tests for OpenCode SDK/TUI flows through ACP v2 internals.
- [ ] Add dedicated integration tests for OpenCode SDK/TUI flows through ACP v1 internals.
Validation gate:
- [ ] OpenCode compatibility suite passes against ACP-backed implementation.
@ -133,7 +133,7 @@ Validation gate:
## Consolidated Test Suites (Must-Have)
- [x] ACP protocol conformance (beyond mock baseline).
- [x] `/v2/rpc` transport contract.
- [x] `/v1/rpc` transport contract.
- [x] End-to-end agent process matrix (core + cancel + HITL + streaming).
- [x] Installer suite (explicit + lazy + provenance).
- [x] Security/auth isolation.
@ -155,7 +155,7 @@ Validation gate:
- [x] Add dedicated regression for `Last-Event-ID` handling in CLI `api acp stream`.
- [x] Add explicit test for `SANDBOX_AGENT_REQUIRE_PREINSTALL=true` behavior.
- [x] Improve server build-script invalidation for inspector embedding (avoid manual touch workaround when `dist/` appears after initial build).
- [ ] Integrate agent server logs into v2 observability surfaces (agent process/process logs available via control-plane and inspector), with redaction and end-to-end tests.
- [ ] Integrate agent server logs into v1 observability surfaces (agent process/process logs available via control-plane and inspector), with redaction and end-to-end tests.
## Inspector Frontend Parity Follow-ups
@ -164,6 +164,7 @@ Validation gate:
- [ ] TODO: Implement session `skills` source configuration in inspector ACP flow.
- [ ] TODO: Implement question request/reply/reject flow in inspector ACP flow.
- [ ] TODO: Implement agent mode discovery before session creation (replace cached/empty fallback).
- [ ] TODO: Implement agent model discovery before session creation (replace cached/empty fallback).
- [ ] TODO: Dynamic Claude model loading — fetch models from Anthropic API (`GET https://api.anthropic.com/v1/models?beta=true`) using the user's credentials instead of hardcoded aliases (default/sonnet/opus/haiku). The old implementation cached results with coalesced in-flight requests and fell back to aliases for OAuth users. See commit `8ecd27b` for `fetch_claude_models()` and `agent_models()` cache logic. Current hardcoded fallback is in `router/support.rs::fallback_config_options()`.
- [ ] TODO: Dynamic Codex model loading — codex-acp (`github.com/zed-industries/codex-acp`) is installed and returns models via ACP `configOptions` in `session/new`. The config probe should pick these up automatically; investigate why the probe currently returns empty configOptions for Codex and fix. Once working, the hardcoded Codex fallbacks in `fallback_config_options()` become unused. See commit `8ecd27b` for old `fetch_codex_models()`.
- [ ] TODO: Replace inspector-local session list with server/global ACP-backed session inventory.
- [ ] TODO: Replace synthesized inspector event history with canonical ACP-backed history model.

View file

@ -25,15 +25,15 @@
- Existing ACP-facing methods in `sandbox-agent` are removed (full rewrite).
- Non-ACP HTTP helpers remain in `sandbox-agent` (health/agents/install/fs/etc).
## Server-Verified v2 ACP Contract
## Server-Verified v1 ACP Contract
### HTTP endpoints and headers
- Endpoints:
1. `POST /v2/rpc`
2. `GET /v2/rpc` (SSE)
3. `DELETE /v2/rpc`
1. `POST /v1/rpc`
2. `GET /v1/rpc` (SSE)
3. `DELETE /v1/rpc`
- Headers:
1. `x-acp-connection-id` for existing connection usage.
1. No connection-id header.
2. `Last-Event-ID` for SSE replay.
3. Agent selection is in payload metadata: `params._meta["sandboxagent.dev"].agent`.
- Sources:
@ -75,7 +75,7 @@
- Source:
1. `server/packages/sandbox-agent/src/acp_runtime/ext_meta.rs:32`
2. `server/packages/sandbox-agent/src/acp_runtime/ext_meta.rs:55`
3. `server/packages/sandbox-agent/tests/v2_api/acp_extensions.rs:3`
3. `server/packages/sandbox-agent/tests/v1_api/acp_extensions.rs:3`
## Server-Verified `_meta["sandboxagent.dev"]` Behavior
@ -130,7 +130,7 @@
4. `skills`
5. `agentVersionRequested`
- Sources:
1. `server/packages/sandbox-agent/tests/v2_api/acp_extensions.rs:145`
1. `server/packages/sandbox-agent/tests/v1_api/acp_extensions.rs:145`
2. `research/acp/v1-schema-to-acp-mapping.md:73`
3. `research/acp/v1-schema-to-acp-mapping.md:80`
@ -138,7 +138,7 @@
### Package A: `acp-http-client`
- Scope:
1. ACP JSON-RPC over streamable HTTP only (`/v2/rpc`, headers, SSE replay, close).
1. ACP JSON-RPC over streamable HTTP only (`/v1/rpc`, headers, SSE replay, close).
2. Generic envelope send/receive and connection lifecycle.
3. No `_sandboxagent/*` helpers.
4. No `_meta["sandboxagent.dev"]` helpers.
@ -184,7 +184,7 @@ Naming rule: for stable ACP methods, Sandbox Agent SDK method names stay ACP-ali
| `extMethod(\"_sandboxagent/session/set_metadata\")` | `{\"jsonrpc\":\"2.0\",\"id\":12,\"method\":\"_sandboxagent/session/set_metadata\",\"params\":{...}}` | `setMetadata()` | Native wrapper method. |
| `extMethod(\"_sandboxagent/session/detach\")` | `{\"jsonrpc\":\"2.0\",\"id\":13,\"method\":\"_sandboxagent/session/detach\",\"params\":{\"sessionId\":\"...\"}}` | `detachSession()` | Native wrapper method. |
| `extMethod(\"_sandboxagent/session/terminate\")` | `{\"jsonrpc\":\"2.0\",\"id\":14,\"method\":\"_sandboxagent/session/terminate\",\"params\":{\"sessionId\":\"...\"}}` | `terminateSession()` | Native wrapper method. |
| close ACP connection | `DELETE /v2/rpc` with header `x-acp-connection-id` | `disconnect()` | Transport-level close, not a JSON-RPC envelope. |
| close ACP connection | `DELETE /v1/rpc` | `disconnect()` | Transport-level close, not a JSON-RPC envelope. |
## Conversion Layer Requirements
- Request conversion (sandbox -> ACP):
@ -211,7 +211,7 @@ Naming rule: for stable ACP methods, Sandbox Agent SDK method names stay ACP-ali
- Replace with sandbox-facing API on `SandboxAgentClient`.
## Testing Requirements
- Continue integration tests against real server/runtime over real `/v2` HTTP APIs.
- Continue integration tests against real server/runtime over real `/v1` HTTP APIs.
- Add integration coverage for:
1. Auto-connect on constructor.
2. `autoConnect: false` behavior.

View file

@ -1,10 +1,10 @@
# V1 Schema to ACP v2 Mapping (1:1)
# V1 Schema to ACP v1 Mapping (1:1)
## 1) Scope
This document maps every current v1 HTTP endpoint and every universal event type to the v2 surface (ACP JSON-RPC for agent/session traffic, HTTP for control-plane/platform APIs).
This document maps every current v1 HTTP endpoint and every universal event type to the v1 surface (ACP JSON-RPC for agent/session traffic, HTTP for control-plane/platform APIs).
Important: this is a conversion reference only. Runtime `/v1/*` endpoints are removed in v2 and return HTTP 410.
Important: this is a conversion reference only. Runtime `/v1/*` endpoints are removed in v1 and return HTTP 410.
Source of truth used:
@ -17,7 +17,7 @@ Source of truth used:
Transport assumption:
- v2 uses ACP over Streamable HTTP (POST + SSE) as the canonical public transport.
- v1 uses ACP over Streamable HTTP (POST + SSE) as the canonical public transport.
- WebSocket can be added later without changing this mapping.
## 2) Mapping Rules
@ -25,7 +25,7 @@ Transport assumption:
1. Use ACP standard methods/events first.
2. If ACP stable has no equivalent, use either:
- ACP extension methods (must start with `_`) for agent/session protocol gaps, or
- HTTP `/v2/*` control-plane/platform endpoints for non-agent/session APIs.
- HTTP `/v1/*` control-plane/platform endpoints for non-agent/session APIs.
3. Preserve legacy-only data in `_meta` (namespaced), not as ad-hoc root fields.
4. Use `_meta` for correlation and legacy envelope carry-over.
@ -39,28 +39,28 @@ Extension namespace used in this spec:
## 3) Endpoint Mapping (All v1 Endpoints)
| v1 endpoint | v2 mapping | Mapping type | Notes |
| v1 endpoint | v1 mapping | Mapping type | Notes |
|---|---|---|---|
| `GET /v1/health` | `GET /v2/health` | HTTP control-plane | v1-parity payload on v2 route. |
| `GET /v1/agents` | `GET /v2/agents` | HTTP control-plane | Agent inventory, capabilities, server status, and optional models/modes for installed agents. |
| `POST /v1/agents/{agent}/install` | `POST /v2/agents/{agent}/install` | HTTP control-plane | Agent process + native agent install flow. |
| `GET /v1/agents/{agent}/models` | Folded into agent response `models` field (installed agents only) | HTTP control-plane | No standalone `/models` endpoint in v2. |
| `GET /v1/agents/{agent}/modes` | Folded into agent response `modes` field (installed agents only) | HTTP control-plane | No standalone `/modes` endpoint in v2. |
| `GET /v1/fs/entries` | `GET /v2/fs/entries` | HTTP platform API | Port v1 behavior. |
| `DELETE /v1/fs/entry` | `DELETE /v2/fs/entry` | HTTP platform API | Port v1 behavior, including `recursive`. |
| `GET /v1/fs/file` | `GET /v2/fs/file` | HTTP platform API | Raw bytes response (octet-stream), v1 parity. |
| `PUT /v1/fs/file` | `PUT /v2/fs/file` | HTTP platform API | Raw bytes write, v1 parity. |
| `POST /v1/fs/mkdir` | `POST /v2/fs/mkdir` | HTTP platform API | Port v1 behavior. |
| `POST /v1/fs/move` | `POST /v2/fs/move` | HTTP platform API | Port v1 behavior. |
| `GET /v1/fs/stat` | `GET /v2/fs/stat` | HTTP platform API | Port v1 behavior. |
| `POST /v1/fs/upload-batch` | `POST /v2/fs/upload-batch` | HTTP platform API | Tar upload/extract behavior from v1. |
| `GET /v1/sessions` | `GET /v2/sessions` | HTTP control-plane | Session inventory without ACP connection requirement. |
| `GET /v1/health` | `GET /v1/health` | HTTP control-plane | v1-parity payload on v1 route. |
| `GET /v1/agents` | `GET /v1/agents` | HTTP control-plane | Agent inventory, capabilities, server status, and optional models/modes for installed agents. |
| `POST /v1/agents/{agent}/install` | `POST /v1/agents/{agent}/install` | HTTP control-plane | Agent process + native agent install flow. |
| `GET /v1/agents/{agent}/models` | Folded into agent response `models` field (installed agents only) | HTTP control-plane | No standalone `/models` endpoint in v1. |
| `GET /v1/agents/{agent}/modes` | Folded into agent response `modes` field (installed agents only) | HTTP control-plane | No standalone `/modes` endpoint in v1. |
| `GET /v1/fs/entries` | `GET /v1/fs/entries` | HTTP platform API | Port v1 behavior. |
| `DELETE /v1/fs/entry` | `DELETE /v1/fs/entry` | HTTP platform API | Port v1 behavior, including `recursive`. |
| `GET /v1/fs/file` | `GET /v1/fs/file` | HTTP platform API | Raw bytes response (octet-stream), v1 parity. |
| `PUT /v1/fs/file` | `PUT /v1/fs/file` | HTTP platform API | Raw bytes write, v1 parity. |
| `POST /v1/fs/mkdir` | `POST /v1/fs/mkdir` | HTTP platform API | Port v1 behavior. |
| `POST /v1/fs/move` | `POST /v1/fs/move` | HTTP platform API | Port v1 behavior. |
| `GET /v1/fs/stat` | `GET /v1/fs/stat` | HTTP platform API | Port v1 behavior. |
| `POST /v1/fs/upload-batch` | `POST /v1/fs/upload-batch` | HTTP platform API | Tar upload/extract behavior from v1. |
| `GET /v1/sessions` | `GET /v1/sessions` | HTTP control-plane | Session inventory without ACP connection requirement. |
| `POST /v1/sessions/{session_id}` | `session/new` | Standard | Path `session_id` becomes alias in `_meta["sandboxagent.dev"].requestedSessionId`. |
| `POST /v1/sessions/{session_id}/messages` | `session/prompt` | Standard | Asynchronous behavior comes from transport (request + stream). |
| `POST /v1/sessions/{session_id}/messages/stream` | `session/prompt` + consume `session/update` on SSE | Standard | Streaming is transport-level, not a distinct ACP method. |
| `POST /v1/sessions/{session_id}/terminate` | `_sandboxagent/session/terminate` | Extension | Idempotent termination semantics distinct from `DELETE /v2/rpc`. |
| `GET /v1/sessions/{session_id}/events` | `_sandboxagent/session/events` (poll view over ACP stream) | Extension | Optional compatibility helper; canonical v2 is stream consumption. |
| `GET /v1/sessions/{session_id}/events/sse` | `GET /v2/rpc` SSE stream | Standard transport | Filter by sessionId client-side or via connection/session binding. |
| `POST /v1/sessions/{session_id}/terminate` | `_sandboxagent/session/terminate` | Extension | Idempotent termination semantics distinct from `DELETE /v1/rpc`. |
| `GET /v1/sessions/{session_id}/events` | `_sandboxagent/session/events` (poll view over ACP stream) | Extension | Optional compatibility helper; canonical v1 is stream consumption. |
| `GET /v1/sessions/{session_id}/events/sse` | `GET /v1/rpc` SSE stream | Standard transport | Filter by sessionId client-side or via connection/session binding. |
| `POST /v1/sessions/{session_id}/permissions/{permission_id}/reply` | JSON-RPC response to pending `session/request_permission` request id | Standard | Bridge `permission_id` to request `id` in transport state. |
| `POST /v1/sessions/{session_id}/questions/{question_id}/reply` | JSON-RPC response to pending `_sandboxagent/session/request_question` | Extension | ACP stable has no generic question/HITL request method. |
| `POST /v1/sessions/{session_id}/questions/{question_id}/reject` | JSON-RPC response to pending `_sandboxagent/session/request_question` | Extension | Encode rejection in response outcome. |