@johnhenry/acp-query
v0.0.2
Published
Reactive session/turn store + permission broker for the Agent Client Protocol — embeddable ACP client state for web UIs, notebooks, and editors. On the official @agentclientprotocol/sdk.
Readme
@johnhenry/acp-query — acp-query
A reactive session/turn store + permission broker for the Agent Client Protocol.
The official @agentclientprotocol/sdk
gives you the wire: the fluent client() builder, typed handlers, stdio/HTTP/SSE/WebSocket
transports. acp-query adds the state stratum an embedding app needs — for web UIs, notebooks,
dashboards, and editors hosting coding agents:
- Reactive session store —
session/updatestreams fold into observable per-session state (messageText,toolCallswith live statuses,plan,availableCommands,currentMode, stop reasons, plus the raw update log).subscribe()isuseSyncExternalStore-ready, and@johnhenry/acp-query/reactships hooks (useSession,useToolCalls,usePermissions) built directly on it. - Permission broker — ACP's
session/request_permission(typedallow_once/always/reject_once/alwaysoptions) routes through the sharedInteractionBroker: trust policy auto-answers, "ask" queues for your approval UI (resolvewith anoptionId), every outcome audited. With no broker configured, requests fail safe (reject). - In-process mock agent (
@johnhenry/acp-query/testing) — the SDK's ownagent()builder wired straight to the client (connect(mockAcpAgent(...))): real protocol, no transport, withsay/toolCall/askPermissionturn helpers.
import { AcpQuery, InteractionBroker } from "@johnhenry/acp-query";
const broker = new InteractionBroker();
const q = new AcpQuery({ interactions: broker });
q.connect(myAgentStream); // ndJsonStream over stdio, WebSocket, ... or an AgentApp
const sid = await q.newSession("/workspace");
q.subscribe(sid, () => render(q.session(sid))); // live turn state
await q.prompt(sid, "refactor the auth module");
// broker.list() -> pending permission requests for your approval inboxAlso ships: React hooks (@johnhenry/acp-query/react — useSession,
useToolCalls, usePermissions, plus the re-exported core hooks and
<AgentQueryDevtools> panel), opt-in fs/terminal client capabilities
(config-supplied callbacks only, default OFF, writes gated through the broker
via gateWrites), a devtools wire tap (instrumentAcpStream — every
JSON-RPC message alongside the semantic event stream), session/list /
session/load / slash-command caching, and AcpSessionHandle
(attach() / newAttachedSession() — bound-session ergonomics with a
states() async-iterable over folded snapshots).
Install
npm install @johnhenry/acp-query@rcUse the rc dist-tag, not latest — latest is still pinned to acp-query's very
first publish (0.1.0-rc.1); every subsequent release, including the current
one, ships under rc until acp-query cuts a stable 1.0.0.
Supported protocol versions
acp-query supports ACP wire protocol v1 only. v2 (schema alpha as of this writing) is explicitly out of scope until it stabilizes — tracked in #5.
- Built on
@agentclientprotocol/[email protected], pinned exactly (bothdependencies/peerDependenciesand the dev pin) — not a caret range. The SDK's own semver (1.3.0) is independent of ACP's wire protocol version; acp-query tracks the SDK version, and the SDK reportsPROTOCOL_VERSION = 1. - The SDK package was renamed from
@zed-industries/agent-client-protocol(now deprecated on npm) to@agentclientprotocol/sdkas governance moved out of Zed Industries into its ownagentclientprotocolorg. acp-query depends on the new package only. - A
schema-v2.0.0-alphais in flight upstream with known breaking renames (semantic string types, diff patch → text, a terminal surface,cancelledvariants). acp-query deliberately does not track or support it — issue #5 stays open, watching for v2 to stabilize before any work starts.
Docs & examples
- API reference — every export, with an example each (including the permission decision → wire mapping and the mock agent's helpers).
- Design — why ACP is a stream-fold, not a cache; the
fold vocabulary; the full policy × options → outcome permission table; the
cancel contract; observability (status semantics, devtools events, why
prompt()is never retried); what the SDK provides vs what acp-query adds. examples/— eleven graded, runnable examples (in-process mock agent, no transport): basic turn → tool calls → permission inbox → policy rules → multi-session → cancel → devtools timeline → client capabilities → wire timeline → session list/load → attached session.npm run example:01…example:11(seeexamples/README.mdfor the full table).
Cancellation honors the ACP contract end to end: cancel(sessionId) sends
session/cancel and resolves that session's pending permission requests
with {outcome: "cancelled"}, so blocked turns finish with
stopReason: "cancelled" instead of hanging.
Status: release candidate (0.1.0-rc.4, on @agentclientprotocol/[email protected]
pinned, wire protocol v1). Part of the
agent-query family — shared engine
@johnhenry/agent-query-core; siblings @johnhenry/mcp-query (MCP) and @johnhenry/a2a-query (A2A).
MIT
