@hydra-acp/cli 0.1.51 → 0.1.53

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
@@ -71,6 +71,8 @@ Agents are sourced from the [ACP Registry](https://github.com/agentclientprotoco
71
71
 
72
72
  hydra-acp daemon ← daemon (the body)
73
73
 
74
+ T1 → T2 → … → Tn ← transformers (per-session middleware)
75
+
74
76
  ┌─────────────┼─────────────┐
75
77
  │ │ │
76
78
  ACP agent A ACP agent B ACP agent C ← agents (the feet)
@@ -93,62 +95,58 @@ Existing ACP clients are stdio-based: they `spawn(command)` a process and exchan
93
95
 
94
96
  Clients that adopt the streamable-http-websocket-transport RFD natively can connect to the daemon's `/acp` endpoint directly without the shim.
95
97
 
96
- ### Surviving daemon restarts (resurrection)
97
-
98
- The shim and daemon together implement a "resume hint" pattern that lets editor sessions survive a daemon restart without the editor noticing:
99
-
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`.
101
- 2. **The shim caches that namespaced data in a `SessionTracker`** as messages flow through, keyed by the hydra sessionId the editor knows.
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.
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`.
104
- 5. **If the daemon already knows the session** (e.g., the daemon never died, just a network blip), it ignores the resume hint and does a normal attach.
105
- 6. **If the daemon doesn't know the session**, it resurrects: spawns a fresh agent of `agentId` in `cwd`, runs `initialize`, calls ACP `session/load { sessionId: upstreamSessionId }` against the agent, and registers a new hydra `Session` *with the same hydra sessionId the shim claimed*. The editor sees nothing.
106
-
107
- The resurrection is serialized per hydra sessionId, so two shims racing to reattach to the same session don't both spawn fresh agents.
108
-
109
- **What this requires:** the underlying agent must support `loadSession` and persist its own session state to disk between processes (e.g., claude-code-acp does, in `~/.claude/sessions/`). For agents that don't support load, resurrection fails on the daemon side and the shim surfaces an error to the editor.
98
+ ### Cat mode
99
+
100
+ `hydra-acp cat` is a pipe-friendly headless verb: it feeds stdin to a fresh
101
+ session as the user prompt and streams the agent's text reply to stdout. No
102
+ TUI, no JSON-RPC for the caller, no terminal control sequences in the
103
+ output just text in, text out, exit code 0 on a clean turn. Hydra ends up
104
+ usable as a unix filter, with the agent as the program in the middle of the
105
+ pipeline.
106
+
107
+ A few properties keep it well-behaved:
108
+
109
+ - **Sandboxed cwd by default.** Piped invocations get a fresh empty tempdir as
110
+ the agent's `cwd`, and the permission handler rejects every tool call that
111
+ isn't one of the `hydra-acp-stdin` MCP tools (head / tail / grep / read on
112
+ the piped bytes). The agent has nothing to look at except the data you
113
+ piped in. Override with `--cwd <path>` when you want it poking at the
114
+ project (e.g. "find docs in the codebase that mention this error").
115
+ - **Smart about size.** Small inputs are inlined into the prompt. Large inputs
116
+ (default >1 MiB) get the daemon's in-memory `hydra-acp-stdin` MCP server:
117
+ bytes flow into a ring buffer and the agent pulls them on demand via
118
+ `head`, `tail`, `grep`, `read`, and `info`. A multi-gigabyte log isn't a
119
+ context-window problem; it's a fixed-size buffer the agent samples.
120
+ - **`--follow` for live streams.** Pipe `tail -f` into `--follow` and each quiet
121
+ burst on stdin is sent as a new turn. The standing prompt (`-p`) is sent
122
+ only on the first turn; later turns carry just the new bytes.
123
+ - **`--detach` to share the session.** By default the session lives as long as
124
+ the cat process; on stdin EOF it dies. With `--detach` it stays in the
125
+ daemon, `hydra-acp session` lists it, and the slack / browser / notifier
126
+ extensions can ride on it. Useful for kicking off a long-running watch
127
+ from a shell script and following it on your phone.
128
+
129
+ A few examples:
110
130
 
111
- **What gets lost across restart:** the daemon's in-memory streaming history and in-flight tool calls. The agent's persisted state — past completed turns, conversation context — is recovered via `session/load`. The agent will need to re-issue any tool call that was mid-stream when the daemon died.
112
-
113
- **In-flight permission prompts:** the shim tracks open `session/request_permission` requests it has forwarded to the editor. On any reconnect (which always implies the previous daemon-side promise is gone), the shim emits a `session/update` notification with `sessionUpdate: "permission_resolved"` toward the editor for each pending request, carrying the original `toolCallId` plus `outcome: { kind: "cancelled", reason: "daemon-disconnected" }` and `resolvedBy: { clientId: "hydra-acp" }`. Editors that handle `permission_resolved` per [RFD #533](https://github.com/agentclientprotocol/agent-client-protocol/pull/533) will dismiss their in-flight permission UI. Any response the editor still sends afterward is silently dropped by the new daemon (unknown request id).
131
+ ```sh
132
+ # One-shot question, no stdin.
133
+ hydra-acp -p "tools to convert a HEIC photo to JPEG on linux?"
114
134
 
115
- ### Wire shape of `_meta`
135
+ # Analyze a big log without copy-pasting it into a chat window.
136
+ journalctl -u nginx --since "1 hour ago" | hydra-acp cat -p "anything alarming?"
116
137
 
117
- A hydra `session/new` response looks like:
138
+ # Treat hydra as the filter in a unix pipeline — output is plain text,
139
+ # so tee / grep / jq downstream just work.
140
+ git log --since="last monday" --pretty=full | hydra-acp cat -p "draft release notes, one bullet per user-visible change, grouped by version" | tee RELEASE_NOTES.md
118
141
 
119
- ```json
120
- {
121
- "sessionId": "hydra_session_abc123",
122
- "_meta": {
123
- "agent-vendor": { "sequence": 7 },
124
- "hydra-acp": {
125
- "upstreamSessionId": "u_xyz",
126
- "agentId": "claude-code",
127
- "cwd": "/path/to/project"
128
- }
129
- }
130
- }
142
+ # Watch a live log and only speak up when something's wrong. --detach
143
+ # keeps the session in the daemon, so you can follow it on your phone
144
+ # via the slack extension after closing the shell.
145
+ tail -F /var/log/app.log | hydra-acp cat --follow --detach -p "if a line looks like an error or stack trace, summarize it. otherwise stay silent."
131
146
  ```
132
147
 
133
- The `agent-vendor` key (illustrative) is whatever the underlying agent put in *its* `_meta` block hydra forwards that through unchanged. Only the `hydra-acp` namespace is hydra's. The same shape applies to `session/attach` responses.
134
-
135
- For resurrection, the shim sends `session/attach` with a resume hint nested in the same namespace:
136
-
137
- ```json
138
- {
139
- "sessionId": "hydra_session_abc123",
140
- "historyPolicy": "pending_only",
141
- "_meta": {
142
- "hydra-acp": {
143
- "resume": {
144
- "upstreamSessionId": "u_xyz",
145
- "agentId": "claude-code",
146
- "cwd": "/path/to/project"
147
- }
148
- }
149
- }
150
- }
151
- ```
148
+ Sessions created by `cat` are normal hydra sessions, so `hydra-acp session`,
149
+ `session export`, `/hydra title`, and the rest of the surface all work on them.
152
150
 
153
151
  ## Install
154
152
 
@@ -401,8 +399,8 @@ Configure in `~/.hydra-acp/config.json`:
401
399
  {
402
400
  "extensions": {
403
401
  "hydra-acp-slack": {},
404
- "hydra-acp-web-ui": {
405
- "command": ["hydra-acp-web-ui"],
402
+ "hydra-acp-browser": {
403
+ "command": ["hydra-acp-browser"],
406
404
  "args": ["--port", "9999"],
407
405
  "env": { "UI_THEME": "dark" }
408
406
  }