@hydra-acp/cli 0.1.32 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -27,11 +27,11 @@
27
27
 
28
28
  ## What it is
29
29
 
30
- `hydra-acp` is a daemon + CLI shim that implements four open ACP RFDs as a single coherent surface, plus the official ACP Registry as its agent-distribution mechanism.
30
+ `hydra-acp` is a daemon + CLI shim that implements two open ACP RFDs as a single coherent surface, on top of the standard ACP protocol (including `session/list` for session discovery), plus the official ACP Registry as its agent-distribution mechanism.
31
31
 
32
32
  ### The standards it stitches together
33
33
 
34
- ACP itself is the [Agent Client Protocol](https://agentclientprotocol.com/) — a JSON-RPC 2.0 protocol between editors (clients) and AI coding agents. Today the protocol is canonically a 1:1 stdio relationship: one editor spawns one agent and owns its stdin/stdout. Four RFDs in the [`agentclientprotocol/agent-client-protocol`](https://github.com/agentclientprotocol/agent-client-protocol) repo extend that model. `hydra-acp` is one daemon that implements all four together so they can be used as a coherent system rather than four independent extensions.
34
+ ACP itself is the [Agent Client Protocol](https://agentclientprotocol.com/) — a JSON-RPC 2.0 protocol between editors (clients) and AI coding agents. Today the protocol is canonically a 1:1 stdio relationship: one editor spawns one agent and owns its stdin/stdout. Two RFDs in the [`agentclientprotocol/agent-client-protocol`](https://github.com/agentclientprotocol/agent-client-protocol) repo extend that model. `hydra-acp` is one daemon that implements both together so they can be used as a coherent system rather than two independent extensions.
35
35
 
36
36
  #### 1. Multi-Client Session Attach — [RFD #533](https://github.com/agentclientprotocol/agent-client-protocol/pull/533)
37
37
 
@@ -42,17 +42,15 @@ Adds two new methods that turn ACP from 1:1 into 1:N:
42
42
 
43
43
  Every event the agent emits is broadcast to every attached client; clients self-filter what they act on. Permission requests broadcast the same way: the first response wins, and the rest receive a `session/update` notification with `sessionUpdate: "permission_resolved"`. Capability is advertised in `initialize` under `agentCapabilities.sessionCapabilities.attach`.
44
44
 
45
- #### 2. Agent Extensions via ACP Proxies — [RFD: proxy-chains](https://agentclientprotocol.com/rfds/proxy-chains)
45
+ #### 2. Streamable HTTP & WebSocket Transport — [RFD: streamable-http-websocket-transport](https://agentclientprotocol.com/rfds/streamable-http-websocket-transport) (WebSocket profile only)
46
46
 
47
- Defines the proxy-chain pattern: a component that sits between an ACP client and an ACP agent and either passes traffic through or transforms it. Proxies use `proxy/initialize` (instead of `initialize`) so the conductor of the chain can tell terminal agents apart from intermediate proxies. Proxies "send messages to successor and receive messages from successor" without knowing what or where the successor is the conductor's job. `hydra-acp` operates as the conductor and as one such proxy: editors spawn it, and from their perspective it appears as a single ACP agent regardless of how many real agents the daemon is managing behind it.
47
+ Defines the network transport that lets ACP run between processes that aren't parent and child. The RFD specifies two profiles on one `/acp` endpoint: a Streamable HTTP profile (POST/GET-SSE/DELETE with `Acp-Connection-Id` and `Acp-Session-Id` headers, HTTP/2 required) and a WebSocket profile (GET with `Upgrade: websocket`). The RFD explicitly permits servers to support **only** the WebSocket profile, and that's the route `hydra-acp` takes the Streamable HTTP half isn't implemented. The RFD itself is still Draft as of April 2026, with the routing model rewritten twice in the six weeks before this writing, so deferring HTTP-transport work until the spec stabilizes is deliberate.
48
48
 
49
- #### 3. Session List [RFD: session-list](https://agentclientprotocol.com/rfds/session-list)
49
+ On the WebSocket side, `hydra-acp` exposes its WSS endpoint at `/acp`: a client sends `GET /acp` with `Upgrade: websocket`, receives a `101 Switching Protocols` response, and the connection becomes a bidirectional stream of JSON-RPC text frames (binary frames are ignored). The server negotiates the `acp.v1` subprotocol via the standard `Sec-WebSocket-Protocol` mechanism (echoed back in the 101 when advertised; absent otherwise). Authentication is layered on top — HTTP headers, query parameters, or WebSocket subprotocols — and is treated as orthogonal by the spec. `hydra-acp` authenticates via a bearer token carried in a `hydra-acp-token.<token>` subprotocol entry or a `?token=<token>` query parameter.
50
50
 
51
- Adds **`session/list { cwd?, cursor?, limit? }`** — an optional capability for enumerating live sessions on an agent (or, in this case, on the daemon). Each entry returns `{ sessionId, cwd, title, updatedAt, _meta }` plus a cursor for pagination. Capability is advertised as `agentCapabilities.sessionCapabilities.list: true`. This is what makes "list and attach" usable from any compliant client without a hydra-specific REST call.
51
+ ### Standard ACP it relies on
52
52
 
53
- #### 4. Streamable HTTP & WebSocket Transport [RFD: streamable-http-websocket-transport](https://agentclientprotocol.com/rfds/streamable-http-websocket-transport)
54
-
55
- Defines the network transport that lets ACP run between processes that aren't parent and child. The relevant half for `hydra-acp` is the WebSocket binding: a client sends `GET /acp` with `Upgrade: websocket`, receives a `101 Switching Protocols` response, and the connection becomes a bidirectional stream of JSON-RPC text frames (binary frames are ignored). Authentication is layered on top — HTTP headers, query parameters, or WebSocket subprotocols — and is treated as orthogonal by the spec. `hydra-acp` exposes its WSS endpoint at `/acp` and authenticates via a bearer token carried in a WebSocket subprotocol or a query parameter.
53
+ Beyond the bedrock of `initialize` / `session/new` / `session/prompt`, the daemon implements **`session/list`** ([Protocol: Session List](https://agentclientprotocol.com/protocol/session-list), stabilized 2026-03-09) so any compliant client can enumerate sessions known to the daemon and attach to one — `{ sessionId, cwd, title?, updatedAt?, _meta? }` per entry, with `cwd` filtering and `cursor`-based pagination. Hydra-specific fields ride under `_meta["hydra-acp"]` per the [Extensibility](https://agentclientprotocol.com/protocol/extensibility) convention.
56
54
 
57
55
  ### The registry it depends on
58
56
 
@@ -83,10 +81,10 @@ Agents are sourced from the [ACP Registry](https://github.com/agentclientprotoco
83
81
 
84
82
  1. **Editor spawns `hydra-acp`** as it would any ACP agent. The shim looks like a normal stdio agent.
85
83
  2. **Shim opens a WSS connection** to the daemon at `/acp`, authenticating via the bearer token.
86
- 3. **`session/new` from the editor** → daemon resolves the requested agent against the cached ACP Registry, downloads it on first use under `~/.hydra-acp/agents/`, spawns it as a child process, and creates an ACP session inside it (per RFD: proxy-chains).
84
+ 3. **`session/new` from the editor** → daemon resolves the requested agent against the cached ACP Registry, downloads it on first use under `~/.hydra-acp/agents/`, spawns it as a child process, and creates an ACP session inside it.
87
85
  4. **`session/attach` from a second client** → daemon adds the new client to the session's broadcast list and replays history per `historyPolicy` (per RFD #533).
88
86
  5. **Notifications** fan out to every attached client. **Prompts** are serialized through the daemon's per-session queue. **Permission requests** broadcast to every attached client; first response wins and the rest receive a `session/update` with `sessionUpdate: "permission_resolved"` carrying the resolving client's outcome.
89
- 6. **`session/list`** returns the daemon's active sessions, filterable by `cwd` (per RFD: session-list).
87
+ 6. **`session/list`** returns the daemon's sessions (live and cold), filterable by `cwd`.
90
88
  7. **`session/detach`** lets a client leave voluntarily; the session continues until the last client detaches (per RFD #533).
91
89
 
92
90
  ### Why a shim?
@@ -99,7 +97,7 @@ Clients that adopt the streamable-http-websocket-transport RFD natively can conn
99
97
 
100
98
  The shim and daemon together implement a "resume hint" pattern that lets editor sessions survive a daemon restart without the editor noticing:
101
99
 
102
- 1. **The daemon's `session/new` and `session/attach` responses include a `_meta` block**, with hydra-specific data namespaced under `_meta["hydra-acp"]` (per the [Session List RFD](https://agentclientprotocol.com/rfds/session-list)'s "agent-specific `_meta` fields" convention). The underlying agent's own `_meta` keys, if any, are passed through unchanged alongside `hydra-acp`.
100
+ 1. **The daemon's `session/new` and `session/attach` responses include a `_meta` block**, with hydra-specific data namespaced under `_meta["hydra-acp"]` (per the ACP [Extensibility](https://agentclientprotocol.com/protocol/extensibility) convention). The underlying agent's own `_meta` keys, if any, are passed through unchanged alongside `hydra-acp`.
103
101
  2. **The shim caches that namespaced data in a `SessionTracker`** as messages flow through, keyed by the hydra sessionId the editor knows.
104
102
  3. **The shim's WS connection is wrapped in a `ResilientWsStream`** that reconnects with exponential backoff (200ms → 5s, capped, max 60 attempts) and buffers outbound messages from the editor while disconnected.
105
103
  4. **After each successful reconnect, the shim replays a `session/attach`** for every cached session, including the resume hints under `_meta["hydra-acp"].resume`.
@@ -504,7 +502,7 @@ Logs are also fanned out to stderr while the daemon is running. To follow live:
504
502
 
505
503
  ## Wire protocol
506
504
 
507
- The daemon's WSS endpoint follows the [Streamable HTTP & WebSocket Transport RFD](https://agentclientprotocol.com/rfds/streamable-http-websocket-transport):
505
+ The daemon's WSS endpoint follows the WebSocket profile of the [Streamable HTTP & WebSocket Transport RFD](https://agentclientprotocol.com/rfds/streamable-http-websocket-transport) (the Streamable HTTP profile isn't implemented — see the transport section above):
508
506
 
509
507
  ```
510
508
  GET /acp HTTP/1.1
@@ -513,9 +511,9 @@ Upgrade: websocket
513
511
  Sec-WebSocket-Protocol: acp.v1, hydra-acp-token.<token>
514
512
  ```
515
513
 
516
- Frames are JSON-RPC 2.0 text frames; binary frames are ignored.
514
+ The server selects `acp.v1` and echoes it back in `Sec-WebSocket-Protocol` on the 101 response; the `hydra-acp-token.<token>` entry is consumed as auth and never echoed. Frames are JSON-RPC 2.0 text frames; binary frames are ignored.
517
515
 
518
- The first JSON-RPC message a client sends is `initialize` (per ACP), or `proxy/initialize` if the client wants the daemon to act as a proxy in the proxy-chain sense (per RFD: proxy-chains).
516
+ The first JSON-RPC message a client sends is `initialize` (per ACP).
519
517
 
520
518
  ### Methods implemented
521
519
 
@@ -525,13 +523,12 @@ Standard ACP:
525
523
  - `session/new` — create a new session, spawning the requested agent
526
524
  - `session/prompt`
527
525
  - `session/cancel`
526
+ - `session/list { cwd?, cursor? }` — enumerate sessions known to the daemon
528
527
 
529
528
  RFD additions:
530
529
 
531
530
  - `session/attach { sessionId, historyPolicy: "full"|"pending_only"|"none" }` — RFD #533
532
531
  - `session/detach { sessionId }` — RFD #533
533
- - `session/list { cwd?, cursor?, limit? }` — RFD: session-list
534
- - `proxy/initialize` — RFD: proxy-chains
535
532
 
536
533
  Capabilities advertised in the `initialize` response:
537
534
 
@@ -550,7 +547,7 @@ Capabilities advertised in the `initialize` response:
550
547
  "loadSession": false,
551
548
  "sessionCapabilities": {
552
549
  "attach": {},
553
- "list": true
550
+ "list": {}
554
551
  }
555
552
  }
556
553
  }