mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 06:04:43 +00:00
11 KiB
11 KiB
TypeScript Client Rewrite Spec (ACP HTTP Client + Sandbox Agent SDK)
Status
- Draft.
- Captures confirmed decisions and server-verified contracts before implementation.
Goals
- Split TypeScript clients into:
acp-http-client: protocol-pure ACP-over-HTTP transport/client.sandbox-agentSDK: Sandbox Agent wrapper that hides ACP terminology and applies Sandbox-specific metadata/extensions.
- Make the Sandbox Agent SDK API as simple as creating a client and connecting once.
- Remove ACP-facing API from
sandbox-agentpublic surface.
Confirmed Product Decisions
- Dedicated protocol package name:
acp-http-client. acp-http-clientmust implement ACP HTTP protocol "to the T" and include no Sandbox-specific metadata/extensions.- Sandbox SDK public constructor pattern:
new SandboxAgentClient(...). - Sandbox SDK auto-connects by default, but supports disabling auto-connect.
- ACP-related SDK calls must fail if
.connect()has not been called. - After
.disconnect(), ACP-related SDK calls must fail until reconnected. - A
SandboxAgentClientinstance can hold at most one active ACP connection. - No API for creating multiple ACP clients per wrapper instance.
- ACP terminology should not appear in Sandbox SDK public API/docs.
- Sandbox SDK should be a thin conversion layer on top of ACP protocol, mainly for metadata/event conversion.
- Existing ACP-facing methods in
sandbox-agentare removed (full rewrite). - Non-ACP HTTP helpers remain in
sandbox-agent(health/agents/install/fs/etc).
Server-Verified v1 ACP Contract
HTTP endpoints and headers
- Endpoints:
POST /v1/rpcGET /v1/rpc(SSE)DELETE /v1/rpc
- Headers:
- No connection-id header.
Last-Event-IDfor SSE replay.- Agent selection is in payload metadata:
params._meta["sandboxagent.dev"].agent.
- Sources:
server/packages/sandbox-agent/src/router.rs:862server/packages/sandbox-agent/src/router.rs:913server/packages/sandbox-agent/src/router.rs:948server/packages/sandbox-agent/src/acp_runtime/mod.rs:26server/packages/sandbox-agent/src/acp_runtime/mod.rs:27
Custom _sandboxagent/* methods/events currently implemented
- Request methods handled in runtime:
_sandboxagent/session/detach_sandboxagent/session/terminate_sandboxagent/session/list_models_sandboxagent/session/set_metadata
- Notification methods handled in runtime:
_sandboxagent/session/detach_sandboxagent/session/terminate_sandboxagent/session/set_metadata
- Runtime notifications:
_sandboxagent/session/ended_sandboxagent/agent/unparsed
- Sources:
server/packages/sandbox-agent/src/acp_runtime/ext_methods.rs:3server/packages/sandbox-agent/src/acp_runtime/ext_methods.rs:4server/packages/sandbox-agent/src/acp_runtime/ext_methods.rs:5server/packages/sandbox-agent/src/acp_runtime/ext_methods.rs:6server/packages/sandbox-agent/src/acp_runtime/ext_methods.rs:7server/packages/sandbox-agent/src/acp_runtime/ext_methods.rs:8server/packages/sandbox-agent/src/acp_runtime/ext_methods.rs:11server/packages/sandbox-agent/src/acp_runtime/ext_methods.rs:30server/packages/sandbox-agent/src/acp_runtime/mod.rs:1496server/packages/sandbox-agent/src/acp_runtime/backend.rs:95
Custom extension capability advertisement
- Injected into
initializeresponse at: result.agentCapabilities._meta["sandboxagent.dev"].extensions- Includes booleans and
methodsarray for extension availability. - Source:
server/packages/sandbox-agent/src/acp_runtime/ext_meta.rs:32server/packages/sandbox-agent/src/acp_runtime/ext_meta.rs:55server/packages/sandbox-agent/tests/v1_api/acp_extensions.rs:3
Server-Verified _meta["sandboxagent.dev"] Behavior
Namespace definition
- Canonical metadata namespace key:
sandboxagent.dev. - Source:
server/packages/sandbox-agent/src/acp_runtime/ext_meta.rs:4
Inbound metadata ingestion
session/newreads_meta["sandboxagent.dev"]as map and stores it.- Source:
server/packages/sandbox-agent/src/acp_runtime/mod.rs:610server/packages/sandbox-agent/src/acp_runtime/ext_meta.rs:21
Metadata mutation extension
_sandboxagent/session/set_metadataaccepts either:
params.metadataobject, orparams._meta["sandboxagent.dev"]object.
- Source:
server/packages/sandbox-agent/src/acp_runtime/ext_methods.rs:163server/packages/sandbox-agent/src/acp_runtime/ext_methods.rs:182
Keys with explicit runtime behavior
title:
- Updates
session.titleand stored sandbox metadata.
model:
- Updates model hint and stored sandbox metadata.
mode:
- Updates mode hint and stored sandbox metadata.
- Source:
server/packages/sandbox-agent/src/acp_runtime/mod.rs:1355server/packages/sandbox-agent/src/acp_runtime/mod.rs:1369server/packages/sandbox-agent/src/acp_runtime/mod.rs:1374server/packages/sandbox-agent/src/acp_runtime/mod.rs:1377
Keys injected/derived by runtime in session/list
- Runtime always injects these keys under
_meta["sandboxagent.dev"]:
agentcreatedAtupdatedAtendedeventCountmodel(if model hint exists)
- Source:
server/packages/sandbox-agent/src/acp_runtime/mod.rs:817
Known pass-through keys (stored and returned, not strongly typed in runtime)
- Observed in tests/docs as pass-through metadata:
variantrequestedSessionIdpermissionModeskillsagentVersionRequested
- Sources:
server/packages/sandbox-agent/tests/v1_api/acp_extensions.rs:145research/acp/v1-schema-to-acp-mapping.md:73research/acp/v1-schema-to-acp-mapping.md:80
Package Split
Package A: acp-http-client
- Scope:
- ACP JSON-RPC over streamable HTTP only (
/v1/rpc, headers, SSE replay, close). - Generic envelope send/receive and connection lifecycle.
- No
_sandboxagent/*helpers. - No
_meta["sandboxagent.dev"]helpers. - No Sandbox-specific type aliases.
- API intent:
- Low-level, minimal, protocol-faithful.
- Usable by any ACP-compatible server.
Package B: sandbox-agent (SandboxAgentClient)
- Scope:
- Control-plane and host APIs: health, agents, install, filesystem, etc.
- Single ACP-backed session client lifecycle hidden behind sandbox naming.
- Metadata conversion in/out of
_meta["sandboxagent.dev"]. - Sandbox extension conversion for
_sandboxagent/*methods/events.
- Lifecycle rules:
- Constructor:
new SandboxAgentClient(options). - Auto-connect by default (configurable opt-out).
.connect(...)creates/activates one ACP connection..connect(...)throws if already connected..disconnect(...)closes current ACP connection.- ACP-related methods throw a not-connected error when disconnected.
ACP-Shaped vs Sandbox API Names
ACP-shaped names are method names that mirror ACP primitives directly (or current SDK wrappers around them), such as initialize, newSession, prompt, extMethod.
Naming rule: for stable ACP methods, Sandbox Agent SDK method names stay ACP-aligned; only extension/unstable helpers may use Sandbox-specific naming.
| ACP-shaped name | ACP protocol message | Sandbox-facing name (candidate) | Notes |
|---|---|---|---|
initialize() |
{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{...}} |
connect() |
First request must include params._meta[\"sandboxagent.dev\"].agent when no connection id exists. |
newSession() |
{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"session/new\",\"params\":{...}} |
newSession() |
Stable ACP method name preserved. |
loadSession() |
{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"session/load\",\"params\":{\"sessionId\":\"...\",...}} |
loadSession() |
Stable ACP method name preserved. |
prompt() |
{\"jsonrpc\":\"2.0\",\"id\":4,\"method\":\"session/prompt\",\"params\":{...}} |
prompt() |
Stable ACP method name preserved. |
cancel() / session/cancel |
{\"jsonrpc\":\"2.0\",\"method\":\"session/cancel\",\"params\":{\"sessionId\":\"...\"}} |
cancel() |
Stable ACP method name preserved. |
setSessionMode() |
{\"jsonrpc\":\"2.0\",\"id\":5,\"method\":\"session/set_mode\",\"params\":{\"sessionId\":\"...\",\"modeId\":\"...\"}} |
setSessionMode() |
Stable ACP method name preserved. |
setSessionConfigOption() |
{\"jsonrpc\":\"2.0\",\"id\":6,\"method\":\"session/set_config_option\",\"params\":{...}} |
setSessionConfigOption() |
Stable ACP method name preserved. |
unstableListSessions() or session/list |
{\"jsonrpc\":\"2.0\",\"id\":7,\"method\":\"session/list\",\"params\":{...}} |
listSessions() |
Wrapper chooses best server method. |
unstableForkSession() |
{\"jsonrpc\":\"2.0\",\"id\":8,\"method\":\"session/fork\",\"params\":{...}} |
forkSession() |
Preserve capability if exposed. |
unstableResumeSession() |
{\"jsonrpc\":\"2.0\",\"id\":9,\"method\":\"session/resume\",\"params\":{...}} |
resumeSession() |
Preserve capability if exposed. |
unstableSetSessionModel() / session/set_model |
{\"jsonrpc\":\"2.0\",\"id\":10,\"method\":\"session/set_model\",\"params\":{\"sessionId\":\"...\",\"modelId\":\"...\"}} |
setSessionModel() |
ACP-aligned naming when exposed. |
extMethod(\"_sandboxagent/session/list_models\") |
{\"jsonrpc\":\"2.0\",\"id\":11,\"method\":\"_sandboxagent/session/list_models\",\"params\":{...}} |
listModels() |
Native wrapper method. |
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 /v1/rpc |
disconnect() |
Transport-level close, not a JSON-RPC envelope. |
Conversion Layer Requirements
- Request conversion (sandbox -> ACP):
- Map sandbox method names to ACP methods.
- Inject/merge
_meta["sandboxagent.dev"]where needed.
- Response/event conversion (ACP -> sandbox):
- Convert
_sandboxagent/session/endedto sandbox lifecycle event. - Convert
_sandboxagent/agent/unparsedto sandbox parse-error event. - Surface metadata fields from
_meta["sandboxagent.dev"]as first-class sandbox fields where appropriate.
Error Model
- Shared HTTP error type for non-2xx (
application/problem+json) remains in sandbox SDK. - Additional wrapper errors:
NotConnectedErrorfor ACP-related calls before.connect().AlreadyConnectedErrorwhen calling.connect()while connected.
Rewrite Impact (expected)
- Remove from
sandbox-agentpublic API:
createAcpClientpostAcpEnvelopecloseAcpClient- ACP type re-exports from
@agentclientprotocol/sdk - ACP-named classes (
SandboxAgentAcpClient)
- Replace with sandbox-facing API on
SandboxAgentClient.
Testing Requirements
- Continue integration tests against real server/runtime over real
/v1HTTP APIs. - Add integration coverage for:
- Auto-connect on constructor.
autoConnect: falsebehavior.- Not-connected error gates.
- Single-connection guard (
connect()twice). - Metadata injection/extraction parity.
- Extension event conversion parity (
_sandboxagent/session/ended,_sandboxagent/agent/unparsed).