zcode-acp-server 0.11.8 → 0.14.1

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.
Files changed (120) hide show
  1. package/README.md +144 -32
  2. package/dist/backend/client.d.ts.map +1 -1
  3. package/dist/backend/client.js +10 -0
  4. package/dist/backend/client.js.map +1 -1
  5. package/dist/backend/listener.d.ts.map +1 -1
  6. package/dist/backend/listener.js +6 -5
  7. package/dist/backend/listener.js.map +1 -1
  8. package/dist/backend/resolve.d.ts.map +1 -1
  9. package/dist/backend/resolve.js +35 -1
  10. package/dist/backend/resolve.js.map +1 -1
  11. package/dist/bin/hub.d.ts +3 -3
  12. package/dist/bin/hub.d.ts.map +1 -1
  13. package/dist/bin/hub.js +22 -12
  14. package/dist/bin/hub.js.map +1 -1
  15. package/dist/bin/quota.d.ts +14 -6
  16. package/dist/bin/quota.d.ts.map +1 -1
  17. package/dist/bin/quota.js +27 -19
  18. package/dist/bin/quota.js.map +1 -1
  19. package/dist/cli.d.ts +38 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +129 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/config/runtime-model.d.ts +10 -10
  24. package/dist/config/runtime-model.js +10 -10
  25. package/dist/handlers/account.d.ts +1 -1
  26. package/dist/handlers/account.js +1 -1
  27. package/dist/handlers/dispatch.d.ts.map +1 -1
  28. package/dist/handlers/dispatch.js +42 -36
  29. package/dist/handlers/dispatch.js.map +1 -1
  30. package/dist/handlers/io.d.ts.map +1 -1
  31. package/dist/handlers/io.js +19 -13
  32. package/dist/handlers/io.js.map +1 -1
  33. package/dist/handlers/session.d.ts +58 -4
  34. package/dist/handlers/session.d.ts.map +1 -1
  35. package/dist/handlers/session.js +317 -87
  36. package/dist/handlers/session.js.map +1 -1
  37. package/dist/index.d.ts +4 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +27 -8
  40. package/dist/index.js.map +1 -1
  41. package/dist/interaction/adapter.d.ts +1 -0
  42. package/dist/interaction/adapter.d.ts.map +1 -1
  43. package/dist/interaction/adapter.js +5 -1
  44. package/dist/interaction/adapter.js.map +1 -1
  45. package/dist/quota/color.d.ts +4 -4
  46. package/dist/quota/color.d.ts.map +1 -1
  47. package/dist/quota/color.js +7 -5
  48. package/dist/quota/color.js.map +1 -1
  49. package/dist/quota/combined.d.ts +1 -1
  50. package/dist/quota/combined.js +4 -4
  51. package/dist/quota/combined.js.map +1 -1
  52. package/dist/quota/format.d.ts +1 -1
  53. package/dist/quota/opencode-go/format.d.ts.map +1 -1
  54. package/dist/quota/opencode-go/format.js +5 -1
  55. package/dist/quota/opencode-go/format.js.map +1 -1
  56. package/dist/quota/opencode-go/index.d.ts +1 -1
  57. package/dist/quota/opencode-go/index.js +1 -1
  58. package/dist/quota/opencode-go/types.d.ts +1 -1
  59. package/dist/quota/opencode-go/types.js +1 -1
  60. package/dist/quota/rounding.d.ts +8 -0
  61. package/dist/quota/rounding.d.ts.map +1 -0
  62. package/dist/quota/rounding.js +10 -0
  63. package/dist/quota/rounding.js.map +1 -0
  64. package/dist/remote/config.d.ts +1 -1
  65. package/dist/remote/config.d.ts.map +1 -1
  66. package/dist/remote/config.js +1 -1
  67. package/dist/remote/config.js.map +1 -1
  68. package/dist/remote/endpoint.d.ts +1 -1
  69. package/dist/remote/endpoint.d.ts.map +1 -1
  70. package/dist/remote/endpoint.js +6 -1
  71. package/dist/remote/endpoint.js.map +1 -1
  72. package/dist/remote/hub-server.d.ts +1 -1
  73. package/dist/remote/hub-server.d.ts.map +1 -1
  74. package/dist/remote/hub-server.js +13 -10
  75. package/dist/remote/hub-server.js.map +1 -1
  76. package/dist/remote/session-rename-endpoint.d.ts +20 -0
  77. package/dist/remote/session-rename-endpoint.d.ts.map +1 -0
  78. package/dist/remote/session-rename-endpoint.js +108 -0
  79. package/dist/remote/session-rename-endpoint.js.map +1 -0
  80. package/dist/repl/App.d.ts +108 -0
  81. package/dist/repl/App.d.ts.map +1 -0
  82. package/dist/repl/App.js +706 -0
  83. package/dist/repl/App.js.map +1 -0
  84. package/dist/repl/history.d.ts +25 -0
  85. package/dist/repl/history.d.ts.map +1 -0
  86. package/dist/repl/history.js +73 -0
  87. package/dist/repl/history.js.map +1 -0
  88. package/dist/repl/input-buffer.d.ts +77 -0
  89. package/dist/repl/input-buffer.d.ts.map +1 -0
  90. package/dist/repl/input-buffer.js +174 -0
  91. package/dist/repl/input-buffer.js.map +1 -0
  92. package/dist/repl/model.d.ts +275 -0
  93. package/dist/repl/model.d.ts.map +1 -0
  94. package/dist/repl/model.js +596 -0
  95. package/dist/repl/model.js.map +1 -0
  96. package/dist/repl/mouse.d.ts +49 -0
  97. package/dist/repl/mouse.d.ts.map +1 -0
  98. package/dist/repl/mouse.js +165 -0
  99. package/dist/repl/mouse.js.map +1 -0
  100. package/dist/repl/run.d.ts +12 -0
  101. package/dist/repl/run.d.ts.map +1 -0
  102. package/dist/repl/run.js +902 -0
  103. package/dist/repl/run.js.map +1 -0
  104. package/dist/server.d.ts +19 -1
  105. package/dist/server.d.ts.map +1 -1
  106. package/dist/server.js +32 -4
  107. package/dist/server.js.map +1 -1
  108. package/dist/tasks-index.d.ts +7 -0
  109. package/dist/tasks-index.d.ts.map +1 -1
  110. package/dist/tasks-index.js +50 -9
  111. package/dist/tasks-index.js.map +1 -1
  112. package/dist/translators/tool-helpers.d.ts.map +1 -1
  113. package/dist/translators/tool-helpers.js +3 -0
  114. package/dist/translators/tool-helpers.js.map +1 -1
  115. package/docs/ARCHITECTURE.md +1 -1
  116. package/docs/BACKLOG.md +40 -21
  117. package/docs/REMOTE-CLIENTS.md +37 -8
  118. package/docs/TROUBLESHOOTING.md +1 -1
  119. package/docs/adr/0007-unified-cli-entry-and-bin-pruning.md +40 -0
  120. package/package.json +9 -4
@@ -2,7 +2,7 @@
2
2
 
3
3
  How to attach any out-of-editor client — browser SPA, mobile app, CLI, desktop
4
4
  tool — to bridge sessions over the network. This document IS the contract:
5
- everything here is implemented by `zcode-acp-hub` and the bridge's remote
5
+ everything here is implemented by the hub daemon (`zcode-acp hub`) and the bridge's remote
6
6
  endpoint; anything not written here is not part of the contract.
7
7
 
8
8
  ACP method semantics are defined by the [ACP spec](https://agentclientprotocol.com);
@@ -52,6 +52,7 @@ ACP editor ────── stdio ──────────┘
52
52
  | `GET /api/instances` | required | Registered bridge instances. Add `?probe=1` to verify first. |
53
53
  | `GET /api/instances/{id}/status` | required | Real-time per-session running status of one bridge. |
54
54
  | `POST /api/instances/{id}/sessions/{sessionId}/close` | required | Retire a session from remote discovery — see [Closing a session](#closing-a-session). |
55
+ | `POST /api/instances/{id}/sessions/{sessionId}/rename` | required | Rename a session — see [Renaming a session](#renaming-a-session). |
55
56
  | `GET /api/quota` | required | Account-level usage stats — same payload as `account/usage_stats`, no ACP connection needed. |
56
57
  | `POST /api/upgrade` | required | Trigger the hub's own staleness check — see [Hub self-upgrade](#hub-self-upgrade). |
57
58
 
@@ -91,9 +92,12 @@ HTTP auth: `Authorization: Bearer <token>` or `?token=<token>`.
91
92
  `session/load` puts the remote client on the same notification stream as
92
93
  the editor tab: turns driven from either side stream live to both. A
93
94
  conversation with no editor placeholder is advertised under its backend
94
- id (`sess_…`), still loadable via pass-through resume. `title` comes from
95
- the backend session store once the backend has titled it; sessions whose
96
- first turn is still running carry the provisional prompt-derived title.
95
+ id (`sess_…`), still loadable via `session/load` pass-through resume. The
96
+ title is set exactly once by the bridge from the first line of the first
97
+ prompt (capped at 80 chars), the moment that prompt is sent — and never
98
+ changes automatically afterwards; a manual rename is the only later
99
+ modifier. Sessions born in a previous bridge lifetime get their title from
100
+ the session store on load/resume.
97
101
  - `sessions[].status` is a coarse `"running" | "idle"` indicator riding the
98
102
  heartbeat (up to ~10s stale; absent on older bridges — treat as unknown).
99
103
  For the live value poll [`/api/instances/{id}/status`](#session-running-status).
@@ -110,9 +114,9 @@ HTTP auth: `Authorization: Bearer <token>` or `?token=<token>`.
110
114
  **accessible** (every listed id resolves and resumes through that bridge).
111
115
  Retired conversations of the project are NOT listed even though the
112
116
  backend store still has them — the store only enriches live entries with
113
- the authoritative title and a cross-bridge `updatedAt`. Entries may carry
114
- a provisional title (first line of the first prompt, capped at 60 chars)
115
- until the backend's own auto-title lands.
117
+ the stored title and a cross-bridge `updatedAt`. The auto-title is set once
118
+ at the first prompt (first non-empty line, capped at 80 chars) and is never
119
+ revised by later turns.
116
120
  - Entries are **deduped across instances**: several bridges of the same
117
121
  project (e.g. a leaked old process plus the current one) can all hold the
118
122
  same live conversation under the same id; the hub keeps one copy per
@@ -178,7 +182,7 @@ pull-only request — callable any time after `initialize`, no session required.
178
182
  Fetch once after attach and on demand; quota changes are slow, there is no
179
183
  push.
180
184
 
181
- Both channels return the same payload, mirroring the `zcode-quota` CLI card's
185
+ Both channels return the same payload, mirroring the `zcode-acp quota` CLI card's
182
186
  data model — one GLM section plus one Opencode Go section — so clients can
183
187
  reproduce the CLI layout exactly:
184
188
 
@@ -292,6 +296,31 @@ Cross-instance note: if the same conversation is also registered by another
292
296
  bridge of the project, the hub's dedupe re-attaches it under that instance —
293
297
  close it there too.
294
298
 
299
+ ## Renaming a session
300
+
301
+ ```text
302
+ POST {hub}/api/instances/{id}/sessions/{sessionId}/rename
303
+ body: { "title": "new name" } → 200 { "ok": true, "title": "…" }
304
+ ```
305
+
306
+ The session title is set **once**, automatically, from the first prompt of a
307
+ freshly created session (first non-empty line, capped at 80 chars) — this
308
+ endpoint is the only later modifier. ACP has no client→agent rename channel,
309
+ and an editor-side rename lives in the editor's own storage forever, so the
310
+ remote side is where a rename enters the system.
311
+
312
+ The bridge applies the rename everywhere: its in-memory title pin (no later
313
+ automatic write can touch it), the discovery summary (live within one
314
+ heartbeat), the ZCode App's tasks-index (`title_overridden=1`, same marker the
315
+ App's own rename sets), and a `session_info_update` broadcast to every
316
+ attached client — the editor tab updates live. The title is normalized like
317
+ the auto-title: flattened to one line, trimmed, capped at 80 chars; an
318
+ all-whitespace title is rejected with `400`.
319
+
320
+ Errors: `400` missing/empty title or oversized body (>4 KB), `401` bad token,
321
+ `404` unknown session (or instance), `502` bridge unreachable. Renaming during
322
+ a running turn is allowed — titles are no longer turn-coupled.
323
+
295
324
  ## Hub self-upgrade
296
325
 
297
326
  ```text
@@ -341,7 +341,7 @@ http://127.0.0.1:<hub-port>/api/health` fails, or `/api/*` returns 401.
341
341
  1. 401 means a token mismatch — `ZCODE_ACP_REMOTE_TOKEN` must be identical in
342
342
  the bridge env, the hub env (if run manually), and the client request.
343
343
  2. A dead hub self-heals: the next bridge heartbeat (≤10s; worst ~1min under
344
- the spawn throttle) re-spawns `zcode-acp-hub`. Retry with backoff rather
344
+ the spawn throttle) re-spawns the hub daemon. Retry with backoff rather
345
345
  than restarting anything by hand.
346
346
  3. Confirm the ports match: the client must reach `ZCODE_ACP_HUB_PORT`
347
347
  (default 8377) through the tunnel, and the tunnel maps exactly that one
@@ -0,0 +1,40 @@
1
+ # Unified CLI entry and bin pruning
2
+
3
+ The package grew three separate bins (`zcode-acp-server`, `zcode-acp-hub`,
4
+ `zcode-quota`) plus a planned terminal chat surface. Installing four sibling
5
+ commands for one tool is noisy, and each new surface would add another. We
6
+ decided to ship one human-facing entry point — the Unified CLI, `zcode-acp` —
7
+ with every surface as a subcommand: `quota`, `hub`, and `server`. Bare
8
+ `zcode-acp` opens the interactive REPL: an Ink-rendered chat UI (the renderer
9
+ Claude Code and Gemini CLI use) speaking ACP to a spawned bridge over stdio,
10
+ with the update pump, permission picker, and turn state machine owned by this
11
+ package. The REPL is written in-house rather than borrowed — no embeddable
12
+ interactive ACP client library exists (acpx is headless-only; the interactive
13
+ clients Toad/Hydra/Nori are external tools or heavyweight daemons), and we
14
+ control both protocol ends already.
15
+
16
+ Bin declarations are pruned to `zcode-acp` and `zcode-acp-server`. The server
17
+ bin stays because it is the command name hardcoded in existing editor configs
18
+ (Zed, JetBrains) across ~2.5k monthly downloads — removing it would break every
19
+ current user at once; it is an editor contract, not a human alias. The
20
+ `zcode-acp-hub` and `zcode-quota` bins are removed in 0.12.0 with a README
21
+ migration note (`zcode-acp hub` / `zcode-acp quota`); the hub's own binary file
22
+ stays in `dist/bin/hub.js` because bridges spawn it by absolute path, not by
23
+ command name, so the remote feature is unaffected.
24
+
25
+ Bin-name detection is `basename(argv[1])`, which works through Unix symlinks
26
+ but not through Windows `.cmd` shims (they spawn `node ...\dist\cli.js`, so
27
+ the bin name never reaches argv). Bare invocation without a TTY therefore
28
+ falls back to the stdio server — the only sensible reading of a piped, no-TTY
29
+ launch, and exactly what a Windows editor spawn needs. The explicit
30
+ `zcode-acp repl` subcommand keeps a hard TTY check and errors instead.
31
+
32
+ We rejected keeping all old bins as silent aliases (five installed commands;
33
+ the redundancy was the original complaint), removing every old bin including
34
+ `zcode-acp-server` (breaks all existing editor configs at once; revisit at
35
+ 1.0), and bundling [acpx](https://github.com/openclaw/acpx) as a `chat`
36
+ passthrough subcommand (evaluated first: its engine is headless-only, so it
37
+ cannot host the interactive REPL that is the actual requirement, and keeping
38
+ it beside the in-house REPL would mean two terminal surfaces, a pre-1.0
39
+ dependency, and an extra Node engine bump for no remaining use — dropped
40
+ before release).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zcode-acp-server",
3
- "version": "0.11.8",
3
+ "version": "0.14.1",
4
4
  "description": "Agent Client Protocol (ACP) server bridging headless ZCode to editors like Zed and JetBrains.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -23,9 +23,8 @@
23
23
  "zcode"
24
24
  ],
25
25
  "bin": {
26
- "zcode-acp-server": "dist/index.js",
27
- "zcode-acp-hub": "dist/bin/hub.js",
28
- "zcode-quota": "dist/bin/quota.js"
26
+ "zcode-acp": "dist/cli.js",
27
+ "zcode-acp-server": "dist/cli.js"
29
28
  },
30
29
  "main": "dist/index.js",
31
30
  "types": "dist/index.d.ts",
@@ -37,6 +36,11 @@
37
36
  ],
38
37
  "dependencies": {
39
38
  "@agentclientprotocol/sdk": "^1.3.0",
39
+ "chalk": "^6.0.0",
40
+ "ink": "^7.1.1",
41
+ "ink-spinner": "^5.0.0",
42
+ "react": "^19.2.8",
43
+ "string-width": "^8.2.2",
40
44
  "ws": "^8.21.3"
41
45
  },
42
46
  "peerDependencies": {
@@ -45,6 +49,7 @@
45
49
  "devDependencies": {
46
50
  "@eslint/js": "^9.0.0",
47
51
  "@types/node": "^22.0.0",
52
+ "@types/react": "^19.2.18",
48
53
  "@types/ws": "^8.18.1",
49
54
  "@typescript-eslint/eslint-plugin": "^8.0.0",
50
55
  "@typescript-eslint/parser": "^8.0.0",