zcode-acp-server 0.1.0 → 0.3.0

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 (223) hide show
  1. package/README.md +192 -9
  2. package/README.zh-CN.md +143 -8
  3. package/dist/backend/client.d.ts +12 -4
  4. package/dist/backend/client.d.ts.map +1 -1
  5. package/dist/backend/client.js +72 -7
  6. package/dist/backend/client.js.map +1 -1
  7. package/dist/backend/credentials.d.ts.map +1 -1
  8. package/dist/backend/credentials.js +2 -1
  9. package/dist/backend/credentials.js.map +1 -1
  10. package/dist/backend/listener.d.ts +12 -4
  11. package/dist/backend/listener.d.ts.map +1 -1
  12. package/dist/backend/listener.js +68 -12
  13. package/dist/backend/listener.js.map +1 -1
  14. package/dist/backend/types.d.ts +1 -1
  15. package/dist/backend/types.d.ts.map +1 -1
  16. package/dist/bin/hub.d.ts +16 -0
  17. package/dist/bin/hub.d.ts.map +1 -0
  18. package/dist/bin/hub.js +41 -0
  19. package/dist/bin/hub.js.map +1 -0
  20. package/dist/bin/quota.d.ts +54 -0
  21. package/dist/bin/quota.d.ts.map +1 -0
  22. package/dist/bin/quota.js +333 -0
  23. package/dist/bin/quota.js.map +1 -0
  24. package/dist/config/auto-compact.d.ts +23 -0
  25. package/dist/config/auto-compact.d.ts.map +1 -0
  26. package/dist/config/auto-compact.js +67 -0
  27. package/dist/config/auto-compact.js.map +1 -0
  28. package/dist/config/mcp-discovery.d.ts +34 -0
  29. package/dist/config/mcp-discovery.d.ts.map +1 -0
  30. package/dist/config/mcp-discovery.js +153 -0
  31. package/dist/config/mcp-discovery.js.map +1 -0
  32. package/dist/config/model-cache.d.ts +12 -1
  33. package/dist/config/model-cache.d.ts.map +1 -1
  34. package/dist/config/model-cache.js +30 -8
  35. package/dist/config/model-cache.js.map +1 -1
  36. package/dist/config/options.d.ts +87 -9
  37. package/dist/config/options.d.ts.map +1 -1
  38. package/dist/config/options.js +248 -45
  39. package/dist/config/options.js.map +1 -1
  40. package/dist/config/plugin-commands.d.ts +24 -0
  41. package/dist/config/plugin-commands.d.ts.map +1 -0
  42. package/dist/config/plugin-commands.js +107 -0
  43. package/dist/config/plugin-commands.js.map +1 -0
  44. package/dist/config/provider-registry.d.ts +60 -0
  45. package/dist/config/provider-registry.d.ts.map +1 -0
  46. package/dist/config/provider-registry.js +128 -0
  47. package/dist/config/provider-registry.js.map +1 -0
  48. package/dist/config/runtime-model.d.ts +54 -18
  49. package/dist/config/runtime-model.d.ts.map +1 -1
  50. package/dist/config/runtime-model.js +105 -61
  51. package/dist/config/runtime-model.js.map +1 -1
  52. package/dist/config/skill-discovery.d.ts +35 -0
  53. package/dist/config/skill-discovery.d.ts.map +1 -0
  54. package/dist/config/skill-discovery.js +188 -0
  55. package/dist/config/skill-discovery.js.map +1 -0
  56. package/dist/handlers/account.d.ts +43 -0
  57. package/dist/handlers/account.d.ts.map +1 -0
  58. package/dist/handlers/account.js +59 -0
  59. package/dist/handlers/account.js.map +1 -0
  60. package/dist/handlers/background-tasks.d.ts +72 -0
  61. package/dist/handlers/background-tasks.d.ts.map +1 -0
  62. package/dist/handlers/background-tasks.js +330 -0
  63. package/dist/handlers/background-tasks.js.map +1 -0
  64. package/dist/handlers/dispatch.d.ts.map +1 -1
  65. package/dist/handlers/dispatch.js +134 -22
  66. package/dist/handlers/dispatch.js.map +1 -1
  67. package/dist/handlers/extensions.d.ts +15 -0
  68. package/dist/handlers/extensions.d.ts.map +1 -1
  69. package/dist/handlers/extensions.js +43 -27
  70. package/dist/handlers/extensions.js.map +1 -1
  71. package/dist/handlers/io.d.ts +31 -3
  72. package/dist/handlers/io.d.ts.map +1 -1
  73. package/dist/handlers/io.js +108 -9
  74. package/dist/handlers/io.js.map +1 -1
  75. package/dist/handlers/replay.d.ts +79 -0
  76. package/dist/handlers/replay.d.ts.map +1 -0
  77. package/dist/handlers/replay.js +252 -0
  78. package/dist/handlers/replay.js.map +1 -0
  79. package/dist/handlers/server-requests.d.ts +20 -4
  80. package/dist/handlers/server-requests.d.ts.map +1 -1
  81. package/dist/handlers/server-requests.js +293 -63
  82. package/dist/handlers/server-requests.js.map +1 -1
  83. package/dist/handlers/session.d.ts +113 -10
  84. package/dist/handlers/session.d.ts.map +1 -1
  85. package/dist/handlers/session.js +932 -277
  86. package/dist/handlers/session.js.map +1 -1
  87. package/dist/handlers/slash.d.ts +37 -1
  88. package/dist/handlers/slash.d.ts.map +1 -1
  89. package/dist/handlers/slash.js +143 -8
  90. package/dist/handlers/slash.js.map +1 -1
  91. package/dist/index.js +76 -12
  92. package/dist/index.js.map +1 -1
  93. package/dist/interaction/adapter.d.ts +19 -33
  94. package/dist/interaction/adapter.d.ts.map +1 -1
  95. package/dist/interaction/adapter.js +80 -79
  96. package/dist/interaction/adapter.js.map +1 -1
  97. package/dist/lazy-sessions.d.ts +35 -0
  98. package/dist/lazy-sessions.d.ts.map +1 -0
  99. package/dist/lazy-sessions.js +98 -0
  100. package/dist/lazy-sessions.js.map +1 -0
  101. package/dist/quota/cache.d.ts +18 -0
  102. package/dist/quota/cache.d.ts.map +1 -0
  103. package/dist/quota/cache.js +32 -0
  104. package/dist/quota/cache.js.map +1 -0
  105. package/dist/quota/client.d.ts +30 -0
  106. package/dist/quota/client.d.ts.map +1 -0
  107. package/dist/quota/client.js +57 -0
  108. package/dist/quota/client.js.map +1 -0
  109. package/dist/quota/color.d.ts +58 -0
  110. package/dist/quota/color.d.ts.map +1 -0
  111. package/dist/quota/color.js +95 -0
  112. package/dist/quota/color.js.map +1 -0
  113. package/dist/quota/combined.d.ts +66 -0
  114. package/dist/quota/combined.d.ts.map +1 -0
  115. package/dist/quota/combined.js +179 -0
  116. package/dist/quota/combined.js.map +1 -0
  117. package/dist/quota/format.d.ts +105 -0
  118. package/dist/quota/format.d.ts.map +1 -0
  119. package/dist/quota/format.js +219 -0
  120. package/dist/quota/format.js.map +1 -0
  121. package/dist/quota/index.d.ts +23 -0
  122. package/dist/quota/index.d.ts.map +1 -0
  123. package/dist/quota/index.js +42 -0
  124. package/dist/quota/index.js.map +1 -0
  125. package/dist/quota/opencode-go/cache.d.ts +17 -0
  126. package/dist/quota/opencode-go/cache.d.ts.map +1 -0
  127. package/dist/quota/opencode-go/cache.js +31 -0
  128. package/dist/quota/opencode-go/cache.js.map +1 -0
  129. package/dist/quota/opencode-go/client.d.ts +28 -0
  130. package/dist/quota/opencode-go/client.d.ts.map +1 -0
  131. package/dist/quota/opencode-go/client.js +48 -0
  132. package/dist/quota/opencode-go/client.js.map +1 -0
  133. package/dist/quota/opencode-go/config.d.ts +37 -0
  134. package/dist/quota/opencode-go/config.d.ts.map +1 -0
  135. package/dist/quota/opencode-go/config.js +58 -0
  136. package/dist/quota/opencode-go/config.js.map +1 -0
  137. package/dist/quota/opencode-go/format.d.ts +36 -0
  138. package/dist/quota/opencode-go/format.d.ts.map +1 -0
  139. package/dist/quota/opencode-go/format.js +87 -0
  140. package/dist/quota/opencode-go/format.js.map +1 -0
  141. package/dist/quota/opencode-go/index.d.ts +30 -0
  142. package/dist/quota/opencode-go/index.d.ts.map +1 -0
  143. package/dist/quota/opencode-go/index.js +108 -0
  144. package/dist/quota/opencode-go/index.js.map +1 -0
  145. package/dist/quota/opencode-go/parse.d.ts +41 -0
  146. package/dist/quota/opencode-go/parse.d.ts.map +1 -0
  147. package/dist/quota/opencode-go/parse.js +75 -0
  148. package/dist/quota/opencode-go/parse.js.map +1 -0
  149. package/dist/quota/opencode-go/types.d.ts +48 -0
  150. package/dist/quota/opencode-go/types.d.ts.map +1 -0
  151. package/dist/quota/opencode-go/types.js +11 -0
  152. package/dist/quota/opencode-go/types.js.map +1 -0
  153. package/dist/quota/parse.d.ts +33 -0
  154. package/dist/quota/parse.d.ts.map +1 -0
  155. package/dist/quota/parse.js +200 -0
  156. package/dist/quota/parse.js.map +1 -0
  157. package/dist/quota/types.d.ts +72 -0
  158. package/dist/quota/types.d.ts.map +1 -0
  159. package/dist/quota/types.js +10 -0
  160. package/dist/quota/types.js.map +1 -0
  161. package/dist/remote/broadcast.d.ts +47 -0
  162. package/dist/remote/broadcast.d.ts.map +1 -0
  163. package/dist/remote/broadcast.js +121 -0
  164. package/dist/remote/broadcast.js.map +1 -0
  165. package/dist/remote/config.d.ts +32 -0
  166. package/dist/remote/config.d.ts.map +1 -0
  167. package/dist/remote/config.js +65 -0
  168. package/dist/remote/config.js.map +1 -0
  169. package/dist/remote/endpoint.d.ts +30 -0
  170. package/dist/remote/endpoint.d.ts.map +1 -0
  171. package/dist/remote/endpoint.js +213 -0
  172. package/dist/remote/endpoint.js.map +1 -0
  173. package/dist/remote/hub-server.d.ts +41 -0
  174. package/dist/remote/hub-server.d.ts.map +1 -0
  175. package/dist/remote/hub-server.js +346 -0
  176. package/dist/remote/hub-server.js.map +1 -0
  177. package/dist/server.d.ts +139 -1
  178. package/dist/server.d.ts.map +1 -1
  179. package/dist/server.js +179 -4
  180. package/dist/server.js.map +1 -1
  181. package/dist/tasks-index.d.ts +14 -4
  182. package/dist/tasks-index.d.ts.map +1 -1
  183. package/dist/tasks-index.js +145 -46
  184. package/dist/tasks-index.js.map +1 -1
  185. package/dist/translators/event-translator.d.ts +33 -0
  186. package/dist/translators/event-translator.d.ts.map +1 -1
  187. package/dist/translators/event-translator.js +101 -0
  188. package/dist/translators/event-translator.js.map +1 -1
  189. package/dist/translators/index.d.ts +1 -1
  190. package/dist/translators/index.d.ts.map +1 -1
  191. package/dist/translators/index.js +1 -1
  192. package/dist/translators/index.js.map +1 -1
  193. package/dist/translators/projection-differ.d.ts +8 -0
  194. package/dist/translators/projection-differ.d.ts.map +1 -1
  195. package/dist/translators/projection-differ.js +19 -9
  196. package/dist/translators/projection-differ.js.map +1 -1
  197. package/dist/translators/tool-helpers.d.ts +28 -0
  198. package/dist/translators/tool-helpers.d.ts.map +1 -1
  199. package/dist/translators/tool-helpers.js +104 -0
  200. package/dist/translators/tool-helpers.js.map +1 -1
  201. package/dist/translators/types.d.ts +38 -1
  202. package/dist/translators/types.d.ts.map +1 -1
  203. package/dist/translators/types.js.map +1 -1
  204. package/dist/utils.d.ts +36 -7
  205. package/dist/utils.d.ts.map +1 -1
  206. package/dist/utils.js +69 -5
  207. package/dist/utils.js.map +1 -1
  208. package/docs/ARCHITECTURE.md +130 -40
  209. package/docs/BACKLOG.md +59 -0
  210. package/docs/DEVELOPMENT.md +31 -0
  211. package/docs/PROTOCOL.md +328 -23
  212. package/docs/REMOTE-CLIENTS.md +260 -0
  213. package/docs/REPLAY-GUIDE.md +131 -0
  214. package/docs/TROUBLESHOOTING.md +131 -14
  215. package/docs/adr/0001-bridge-lifetime-follows-primary-client.md +14 -0
  216. package/docs/adr/0002-stateless-hub-over-per-bridge-acp-endpoints.md +23 -0
  217. package/docs/adr/0003-tail-replay-meta-and-cursor-pagination.md +40 -0
  218. package/docs/agents/domain.md +51 -0
  219. package/docs/agents/issue-tracker.md +22 -0
  220. package/docs/agents/triage-labels.md +15 -0
  221. package/docs/proposals/0001-tail-session-replay.md +136 -0
  222. package/docs/proposals/0002-plan-quota-usage.md +81 -0
  223. package/package.json +10 -6
package/dist/server.d.ts CHANGED
@@ -8,6 +8,8 @@
8
8
  */
9
9
  import type * as acp from "@agentclientprotocol/sdk";
10
10
  import { ZcodeBackend } from "./backend/index.js";
11
+ import { BackgroundTaskListener } from "./handlers/background-tasks.js";
12
+ import { ClientRegistry } from "./remote/broadcast.js";
11
13
  /** Client capabilities advertised in the initialize request. */
12
14
  export interface ClientCapabilities {
13
15
  fs?: {
@@ -26,12 +28,58 @@ export interface ClientCapabilities {
26
28
  export interface PendingTurn {
27
29
  zcodeSid: string;
28
30
  cancelled: boolean;
31
+ /** Set once session/stop has been fired for this turn, to avoid re-sending. */
32
+ stopSent?: boolean;
33
+ /**
34
+ * Set when the turn was ended by the stall-recovery heuristic (backend
35
+ * reported idle after a silence) rather than a real turn.completed event.
36
+ * prompt() skips auto-compact for such turns — the completion was inferred,
37
+ * and compressing an in-flight task's context would destroy the work.
38
+ */
39
+ stallRecovered?: boolean;
29
40
  }
30
41
  export declare class ZcodeAcpServer {
31
42
  /** The ZCode subprocess client (lazy — spawned on first use). */
32
43
  backend: ZcodeBackend | null;
33
44
  /** acp_sid → zcode session id (usually identical, but kept for clarity). */
34
45
  readonly sessionMap: Map<string, string>;
46
+ /**
47
+ * Reverse map: zcode session id → acp_sid. The background-task listener only
48
+ * knows the zcode sid (it comes from backend events), but ACP notifications
49
+ * must address the acp_sid the client knows. Usually the two are identical,
50
+ * but forked/loaded sessions can diverge, so we maintain an explicit reverse
51
+ * index rather than assuming equality.
52
+ */
53
+ readonly acpSidByZcodeSid: Map<string, string>;
54
+ /**
55
+ * Sessions returned by `session/new` whose backend session has not been
56
+ * created yet (acp_sid → { cwd }). session/new defers `session/create` until
57
+ * the session is first used, so an editor startup that never prompts leaves
58
+ * no empty session in the backend or the App's task index. `ensureRealSession`
59
+ * materializes these on first use; entries live only as long as the bridge
60
+ * process (a never-used placeholder vanishes with it).
61
+ *
62
+ * `creating` holds the in-flight materialization promise while a first-use
63
+ * create is running, so concurrent first-uses (e.g. a raced double prompt)
64
+ * share one `session/create` instead of creating two backend sessions.
65
+ */
66
+ readonly pendingSessions: Map<string, {
67
+ cwd: string;
68
+ creating?: Promise<string>;
69
+ /** Client-provided MCP servers from session/new, replayed verbatim into
70
+ * the backend's session/create when the lazy session materializes. The
71
+ * backend's mcpServers schema matches the ACP array shape (stdio entries
72
+ * carry command/args/env; remote entries carry type/url), so entries are
73
+ * passed through unchanged. */
74
+ mcpServers?: acp.McpServer[];
75
+ }>;
76
+ /**
77
+ * Session cwds (acp_sid → cwd), recorded at session/new and lazy-recovery.
78
+ * Unlike pendingSessions this survives materialization — the hub discovery
79
+ * payload needs a workspace label for live sessions, whose pending entries
80
+ * are deleted on first use.
81
+ */
82
+ readonly sessionCwds: Map<string, string>;
35
83
  /** Currently running turns, keyed by the ACP request id. */
36
84
  readonly pendingTurns: Map<number, PendingTurn>;
37
85
  /**
@@ -40,16 +88,66 @@ export declare class ZcodeAcpServer {
40
88
  * concurrent prompts from both missing each other and registering at once.
41
89
  */
42
90
  readonly preemptLocks: Map<string, Promise<void>>;
43
- /** Capabilities advertised by the connected client (Zed, JetBrains, ...). */
91
+ /** Capabilities advertised by connected clients (Zed, JetBrains, remote). */
44
92
  clientCapabilities: ClientCapabilities;
93
+ /**
94
+ * All connected ACP clients (the stdio editor plus any remote WebSocket
95
+ * clients). Handlers push notifications through `clients.broadcast()` so
96
+ * every attached client sees the same stream; the registry replaces the old
97
+ * single `acpClient` reference. Background listeners use it to push
98
+ * `session/update` notifications outside request handlers.
99
+ */
100
+ readonly clients: ClientRegistry;
101
+ /**
102
+ * Lightweight session summaries for the remote hub's discovery API
103
+ * (acp_sid → { title, updatedAt }). In-memory only — the hub holds no
104
+ * business state and the bridge dies with its editor, so persistence would
105
+ * buy nothing. Maintained by `touchSessionSummary` at session registration,
106
+ * title set, and turn completion.
107
+ */
108
+ readonly sessionSummaries: Map<string, {
109
+ title?: string;
110
+ updatedAt: number;
111
+ }>;
45
112
  /** Session titles already set, to enforce set-once (acp_sid → title). */
46
113
  readonly sessionTitles: Map<string, string>;
114
+ /**
115
+ * Sessions eligible for auto-title on first end_turn. Only `session/new`
116
+ * populates this — resumed/loaded sessions already carry a title, so their
117
+ * first post-load message must NOT overwrite it. (sessionTitles alone can't
118
+ * distinguish "freshly created" from "resumed but not yet titled in-process".)
119
+ */
120
+ readonly titleEligibleSessions: Set<string>;
47
121
  /** Last mode id advertised to the client (acp_sid → modeId), for change detection. */
48
122
  readonly lastMode: Map<string, string>;
123
+ /**
124
+ * Timestamp of the last cancel (user stop or preempt), keyed by zcodeSid.
125
+ * Set in cancel() and preemptInFlightTurn(); read in runEventTurn's stall
126
+ * reconciliation to fast-fail turns that collide with the backend's
127
+ * ~20s model-connection recovery window after a mid-stream abort.
128
+ */
129
+ readonly lastCancelledAt: Map<string, number>;
49
130
  /** Per-session ProjectionDiffers (persists across turns). */
50
131
  readonly differs: Map<string, import("./translators/projection-differ.js").ProjectionDiffer>;
51
132
  /** Per-session model cache for configOptions model dropdown. */
52
133
  readonly modelCache: Map<string, string>;
134
+ /**
135
+ * Per-session (zcodeSid) background-task listeners. Registered once when a
136
+ * session is created/resumed/loaded and lives across prompts, forwarding
137
+ * background task status + result notifications to the client outside of
138
+ * request handlers. The turn loop's own listener coexists with this one
139
+ * (backend.listeners is now a Set per session).
140
+ */
141
+ readonly backgroundListeners: Map<string, BackgroundTaskListener>;
142
+ /**
143
+ * Per-Bash-callId stdout snapshot already streamed via terminal_output. Used
144
+ * by dispatchTerminalUpdate for two dedup guards:
145
+ * - progress: diff cumulative stdoutTail snapshots, emit only the suffix.
146
+ * - result: if present, the output was already streamed → skip replay.
147
+ * Presence of a key also signals "progress fired for this call" (absent =
148
+ * short command with no progress, so the result emits output once).
149
+ */
150
+ readonly terminalSentData: Map<string, string>;
53
151
  /** Monotonic id counter; base 10_000_000 to avoid collisions with zcode-originated ids. */
54
152
  private msgCounter;
55
153
  /** Next JSON-RPC id for messages we send to zcode. */
@@ -58,6 +156,38 @@ export declare class ZcodeAcpServer {
58
156
  ensureBackend(): ZcodeBackend;
59
157
  /** Resolve the zcode session id for an ACP session id. */
60
158
  resolveSid(acpSid: string): string | undefined;
159
+ /**
160
+ * Register the acp_sid ↔ zcode_sid mapping both ways. Use this instead of
161
+ * `sessionMap.set(...)` directly so the reverse index stays in sync (the
162
+ * background-task listener needs the reverse lookup to address notifications).
163
+ */
164
+ registerSession(acpSid: string, zcodeSid: string): void;
165
+ /** Update a session's discovery summary (title sticky once set). */
166
+ touchSessionSummary(acpSid: string, title?: string): void;
167
+ /**
168
+ * Best-effort workspace label for the hub discovery payload: first known
169
+ * session cwd, else the bridge process cwd.
170
+ */
171
+ workspaceLabel(): string;
172
+ /**
173
+ * Ensure a background-task listener is registered for the session. Idempotent
174
+ * — returns the existing listener if already registered (covers resume/load
175
+ * after new, and fork). Lives for the whole session so background agents that
176
+ * finish AFTER `session/prompt` returns still get their status/result
177
+ * forwarded to the client. The turn loop's own listener coexists via the
178
+ * backend's per-session listener Set.
179
+ */
180
+ ensureBackgroundListener(zcodeSid: string): BackgroundTaskListener;
181
+ /** Resolve the ACP session id for a zcode session id (reverse of resolveSid). */
182
+ resolveAcpSid(zcodeSid: string): string | undefined;
183
+ /**
184
+ * Push a `session/update` notification to the client from OUTSIDE a request
185
+ * handler (used by the background-task listener). Resolves the acp_sid from
186
+ * the zcode_sid and no-ops (returning false) if the client or session is
187
+ * unknown. Never throws — callers run in the event loop and must not crash
188
+ * the bridge on a notification failure.
189
+ */
190
+ notifyByZcodeSid(zcodeSid: string, update: acp.SessionUpdate): Promise<boolean>;
61
191
  /** Whether the client declared `_meta.terminal_output` (Zed's Bash UI hook). */
62
192
  supportsTerminalOutput(): boolean;
63
193
  /**
@@ -67,6 +197,14 @@ export declare class ZcodeAcpServer {
67
197
  * `session/request_permission`.
68
198
  */
69
199
  supportsElicitationForm(): boolean;
200
+ /**
201
+ * OR-merge capabilities from a newly connected client. Each connection runs
202
+ * its own `initialize`; boolean capabilities are unioned across clients so a
203
+ * feature advertised by ANY attached client (Zed or a remote one) enables the
204
+ * richer interaction path, and `_meta` flags (e.g. terminal_output) merge
205
+ * shallowly. Idempotent for re-connecting clients with equal capabilities.
206
+ */
207
+ mergeClientCapabilities(caps: ClientCapabilities): void;
70
208
  /** Handle `initialize`: negotiate version + declare agent capabilities. */
71
209
  initialize(params: acp.InitializeRequest): Promise<acp.InitializeResponse>;
72
210
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAErD,OAAO,EAIL,YAAY,EACb,MAAM,oBAAoB,CAAC;AAG5B,gEAAgE;AAChE,MAAM,WAAW,kBAAkB;IACjC,EAAE,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACzD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,WAAW,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,6BAA6B;AAC7B,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,cAAc;IACzB,iEAAiE;IACjE,OAAO,EAAE,YAAY,GAAG,IAAI,CAAQ;IACpC,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,sBAA6B;IAChD,4DAA4D;IAC5D,QAAQ,CAAC,YAAY,2BAAkC;IACvD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,6BAAoC;IACzD,6EAA6E;IAC7E,kBAAkB,EAAE,kBAAkB,CAAM;IAC5C,yEAAyE;IACzE,QAAQ,CAAC,aAAa,sBAA6B;IACnD,sFAAsF;IACtF,QAAQ,CAAC,QAAQ,sBAA6B;IAC9C,6DAA6D;IAC7D,QAAQ,CAAC,OAAO,6EAGZ;IACJ,gEAAgE;IAChE,QAAQ,CAAC,UAAU,sBAA6B;IAChD,2FAA2F;IAC3F,OAAO,CAAC,UAAU,CAAc;IAEhC,sDAAsD;IACtD,MAAM,IAAI,MAAM;IAIhB,gFAAgF;IAChF,aAAa,IAAI,YAAY;IAQ7B,0DAA0D;IAC1D,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI9C,gFAAgF;IAChF,sBAAsB,IAAI,OAAO;IAKjC;;;;;OAKG;IACH,uBAAuB,IAAI,OAAO;IAIlC,2EAA2E;IACrE,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;CAgCjF"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -7,12 +7,43 @@
7
7
  * every handler layer can reach it without globals.
8
8
  */
9
9
  import { loadZcodeCredentials, mergeEnvWithCreds, resolveZcodeCommand, ZcodeBackend, } from "./backend/index.js";
10
+ import { BackgroundTaskListener } from "./handlers/background-tasks.js";
11
+ import { enqueueSessionSend } from "./handlers/io.js";
12
+ import { ClientRegistry } from "./remote/broadcast.js";
10
13
  import { AGENT_INFO, PROTOCOL_VERSION, log } from "./utils.js";
11
14
  export class ZcodeAcpServer {
12
15
  /** The ZCode subprocess client (lazy — spawned on first use). */
13
16
  backend = null;
14
17
  /** acp_sid → zcode session id (usually identical, but kept for clarity). */
15
18
  sessionMap = new Map();
19
+ /**
20
+ * Reverse map: zcode session id → acp_sid. The background-task listener only
21
+ * knows the zcode sid (it comes from backend events), but ACP notifications
22
+ * must address the acp_sid the client knows. Usually the two are identical,
23
+ * but forked/loaded sessions can diverge, so we maintain an explicit reverse
24
+ * index rather than assuming equality.
25
+ */
26
+ acpSidByZcodeSid = new Map();
27
+ /**
28
+ * Sessions returned by `session/new` whose backend session has not been
29
+ * created yet (acp_sid → { cwd }). session/new defers `session/create` until
30
+ * the session is first used, so an editor startup that never prompts leaves
31
+ * no empty session in the backend or the App's task index. `ensureRealSession`
32
+ * materializes these on first use; entries live only as long as the bridge
33
+ * process (a never-used placeholder vanishes with it).
34
+ *
35
+ * `creating` holds the in-flight materialization promise while a first-use
36
+ * create is running, so concurrent first-uses (e.g. a raced double prompt)
37
+ * share one `session/create` instead of creating two backend sessions.
38
+ */
39
+ pendingSessions = new Map();
40
+ /**
41
+ * Session cwds (acp_sid → cwd), recorded at session/new and lazy-recovery.
42
+ * Unlike pendingSessions this survives materialization — the hub discovery
43
+ * payload needs a workspace label for live sessions, whose pending entries
44
+ * are deleted on first use.
45
+ */
46
+ sessionCwds = new Map();
16
47
  /** Currently running turns, keyed by the ACP request id. */
17
48
  pendingTurns = new Map();
18
49
  /**
@@ -21,16 +52,63 @@ export class ZcodeAcpServer {
21
52
  * concurrent prompts from both missing each other and registering at once.
22
53
  */
23
54
  preemptLocks = new Map();
24
- /** Capabilities advertised by the connected client (Zed, JetBrains, ...). */
55
+ /** Capabilities advertised by connected clients (Zed, JetBrains, remote). */
25
56
  clientCapabilities = {};
57
+ /**
58
+ * All connected ACP clients (the stdio editor plus any remote WebSocket
59
+ * clients). Handlers push notifications through `clients.broadcast()` so
60
+ * every attached client sees the same stream; the registry replaces the old
61
+ * single `acpClient` reference. Background listeners use it to push
62
+ * `session/update` notifications outside request handlers.
63
+ */
64
+ clients = new ClientRegistry();
65
+ /**
66
+ * Lightweight session summaries for the remote hub's discovery API
67
+ * (acp_sid → { title, updatedAt }). In-memory only — the hub holds no
68
+ * business state and the bridge dies with its editor, so persistence would
69
+ * buy nothing. Maintained by `touchSessionSummary` at session registration,
70
+ * title set, and turn completion.
71
+ */
72
+ sessionSummaries = new Map();
26
73
  /** Session titles already set, to enforce set-once (acp_sid → title). */
27
74
  sessionTitles = new Map();
75
+ /**
76
+ * Sessions eligible for auto-title on first end_turn. Only `session/new`
77
+ * populates this — resumed/loaded sessions already carry a title, so their
78
+ * first post-load message must NOT overwrite it. (sessionTitles alone can't
79
+ * distinguish "freshly created" from "resumed but not yet titled in-process".)
80
+ */
81
+ titleEligibleSessions = new Set();
28
82
  /** Last mode id advertised to the client (acp_sid → modeId), for change detection. */
29
83
  lastMode = new Map();
84
+ /**
85
+ * Timestamp of the last cancel (user stop or preempt), keyed by zcodeSid.
86
+ * Set in cancel() and preemptInFlightTurn(); read in runEventTurn's stall
87
+ * reconciliation to fast-fail turns that collide with the backend's
88
+ * ~20s model-connection recovery window after a mid-stream abort.
89
+ */
90
+ lastCancelledAt = new Map();
30
91
  /** Per-session ProjectionDiffers (persists across turns). */
31
92
  differs = new Map();
32
93
  /** Per-session model cache for configOptions model dropdown. */
33
94
  modelCache = new Map();
95
+ /**
96
+ * Per-session (zcodeSid) background-task listeners. Registered once when a
97
+ * session is created/resumed/loaded and lives across prompts, forwarding
98
+ * background task status + result notifications to the client outside of
99
+ * request handlers. The turn loop's own listener coexists with this one
100
+ * (backend.listeners is now a Set per session).
101
+ */
102
+ backgroundListeners = new Map();
103
+ /**
104
+ * Per-Bash-callId stdout snapshot already streamed via terminal_output. Used
105
+ * by dispatchTerminalUpdate for two dedup guards:
106
+ * - progress: diff cumulative stdoutTail snapshots, emit only the suffix.
107
+ * - result: if present, the output was already streamed → skip replay.
108
+ * Presence of a key also signals "progress fired for this call" (absent =
109
+ * short command with no progress, so the result emits output once).
110
+ */
111
+ terminalSentData = new Map();
34
112
  /** Monotonic id counter; base 10_000_000 to avoid collisions with zcode-originated ids. */
35
113
  msgCounter = 10_000_000;
36
114
  /** Next JSON-RPC id for messages we send to zcode. */
@@ -50,6 +128,79 @@ export class ZcodeAcpServer {
50
128
  resolveSid(acpSid) {
51
129
  return this.sessionMap.get(acpSid);
52
130
  }
131
+ /**
132
+ * Register the acp_sid ↔ zcode_sid mapping both ways. Use this instead of
133
+ * `sessionMap.set(...)` directly so the reverse index stays in sync (the
134
+ * background-task listener needs the reverse lookup to address notifications).
135
+ */
136
+ registerSession(acpSid, zcodeSid) {
137
+ this.sessionMap.set(acpSid, zcodeSid);
138
+ this.acpSidByZcodeSid.set(zcodeSid, acpSid);
139
+ this.touchSessionSummary(acpSid);
140
+ }
141
+ /** Update a session's discovery summary (title sticky once set). */
142
+ touchSessionSummary(acpSid, title) {
143
+ const existing = this.sessionSummaries.get(acpSid);
144
+ this.sessionSummaries.set(acpSid, {
145
+ title: title ?? existing?.title,
146
+ updatedAt: Date.now(),
147
+ });
148
+ }
149
+ /**
150
+ * Best-effort workspace label for the hub discovery payload: first known
151
+ * session cwd, else the bridge process cwd.
152
+ */
153
+ workspaceLabel() {
154
+ return this.sessionCwds.values().next().value ?? process.cwd();
155
+ }
156
+ /**
157
+ * Ensure a background-task listener is registered for the session. Idempotent
158
+ * — returns the existing listener if already registered (covers resume/load
159
+ * after new, and fork). Lives for the whole session so background agents that
160
+ * finish AFTER `session/prompt` returns still get their status/result
161
+ * forwarded to the client. The turn loop's own listener coexists via the
162
+ * backend's per-session listener Set.
163
+ */
164
+ ensureBackgroundListener(zcodeSid) {
165
+ const existing = this.backgroundListeners.get(zcodeSid);
166
+ if (existing)
167
+ return existing;
168
+ const backend = this.ensureBackend();
169
+ const listener = new BackgroundTaskListener(this, zcodeSid);
170
+ this.backgroundListeners.set(zcodeSid, listener);
171
+ backend.registerEventListener(zcodeSid, listener);
172
+ log(` [bg] background listener registered for ${zcodeSid}`);
173
+ return listener;
174
+ }
175
+ /** Resolve the ACP session id for a zcode session id (reverse of resolveSid). */
176
+ resolveAcpSid(zcodeSid) {
177
+ return this.acpSidByZcodeSid.get(zcodeSid);
178
+ }
179
+ /**
180
+ * Push a `session/update` notification to the client from OUTSIDE a request
181
+ * handler (used by the background-task listener). Resolves the acp_sid from
182
+ * the zcode_sid and no-ops (returning false) if the client or session is
183
+ * unknown. Never throws — callers run in the event loop and must not crash
184
+ * the bridge on a notification failure.
185
+ */
186
+ async notifyByZcodeSid(zcodeSid, update) {
187
+ if (this.clients.size === 0)
188
+ return false;
189
+ const acpSid = this.resolveAcpSid(zcodeSid);
190
+ if (!acpSid)
191
+ return false;
192
+ try {
193
+ // Broadcast notify swallows per-client failures internally (warn only).
194
+ // Serialized through the replay guard so a background emission queues
195
+ // behind an in-flight replay batch for the same session.
196
+ await enqueueSessionSend(acpSid, () => this.clients.broadcast().notify("session/update", { sessionId: acpSid, update }));
197
+ return true;
198
+ }
199
+ catch (e) {
200
+ log(`notifyByZcodeSid: session/update failed: ${e instanceof Error ? e.message : String(e)}`);
201
+ return false;
202
+ }
203
+ }
53
204
  /** Whether the client declared `_meta.terminal_output` (Zed's Bash UI hook). */
54
205
  supportsTerminalOutput() {
55
206
  const meta = this.clientCapabilities._meta ?? {};
@@ -64,19 +215,43 @@ export class ZcodeAcpServer {
64
215
  supportsElicitationForm() {
65
216
  return this.clientCapabilities.elicitation?.form != null;
66
217
  }
218
+ /**
219
+ * OR-merge capabilities from a newly connected client. Each connection runs
220
+ * its own `initialize`; boolean capabilities are unioned across clients so a
221
+ * feature advertised by ANY attached client (Zed or a remote one) enables the
222
+ * richer interaction path, and `_meta` flags (e.g. terminal_output) merge
223
+ * shallowly. Idempotent for re-connecting clients with equal capabilities.
224
+ */
225
+ mergeClientCapabilities(caps) {
226
+ const cur = this.clientCapabilities;
227
+ const next = { ...cur, ...caps };
228
+ next.fs = {
229
+ readTextFile: cur.fs?.readTextFile || caps.fs?.readTextFile,
230
+ writeTextFile: cur.fs?.writeTextFile || caps.fs?.writeTextFile,
231
+ };
232
+ next.terminal = cur.terminal || caps.terminal;
233
+ next.elicitation = {
234
+ form: cur.elicitation?.form || caps.elicitation?.form,
235
+ url: cur.elicitation?.url || caps.elicitation?.url,
236
+ };
237
+ if (cur._meta || caps._meta)
238
+ next._meta = { ...cur._meta, ...caps._meta };
239
+ this.clientCapabilities = next;
240
+ }
67
241
  /** Handle `initialize`: negotiate version + declare agent capabilities. */
68
242
  async initialize(params) {
69
243
  const clientInfo = params.clientInfo ?? null;
70
- this.clientCapabilities = params.clientCapabilities ?? {};
244
+ this.mergeClientCapabilities(params.clientCapabilities ?? {});
71
245
  log(`initialize: client protocolVersion=${params.protocolVersion}` +
72
246
  `, client=${clientInfo?.name ?? "unknown"}` +
73
- `, version=${clientInfo?.version ?? "unknown"}`);
247
+ `, version=${clientInfo?.version ?? "unknown"}` +
248
+ `, elicitation.form=${this.clientCapabilities.elicitation?.form == null ? "no" : "yes"}`);
74
249
  return {
75
250
  protocolVersion: PROTOCOL_VERSION,
76
251
  agentInfo: { ...AGENT_INFO },
77
252
  agentCapabilities: {
78
253
  loadSession: true,
79
- promptCapabilities: { image: false, audio: false, embeddedContext: false },
254
+ promptCapabilities: { image: true, audio: false, embeddedContext: false },
80
255
  mcpCapabilities: { http: false, sse: false },
81
256
  sessionCapabilities: { list: {}, resume: {}, fork: {} },
82
257
  },
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -31,9 +31,19 @@ export declare function upsertSessionTask(opts: {
31
31
  status?: string;
32
32
  }): Promise<boolean>;
33
33
  /**
34
- * Update a session's title after the first turn. session/create leaves title
35
- * empty; once the first prompt completes, set a meaningful title. Respects
36
- * title_overridden: if the user already renamed in the App, their title wins.
34
+ * Update a session's title + searchable_text after the first turn.
35
+ *
36
+ * session/create leaves title empty; once the first prompt completes, set a
37
+ * meaningful title. Respects title_overridden: if the user already renamed in
38
+ * the App, their title wins (but searchable_text is still refreshed — it's not
39
+ * user-controlled).
40
+ *
41
+ * `searchableText` feeds the App's full-text search (the App builds it via
42
+ * `buildSearchableTextFromMessages`: each message's content trimmed + joined
43
+ * by newlines, capped at 200k chars). We pass the first user prompt here; the
44
+ * App later overwrites it with the full conversation when it reindexes, but
45
+ * having it non-empty from the start means the row shows up in search and
46
+ * matches the shape of App-created rows.
37
47
  */
38
- export declare function updateSessionTitle(taskId: string, title: string): Promise<boolean>;
48
+ export declare function updateSessionTitle(taskId: string, title: string, searchableText?: string): Promise<boolean>;
39
49
  //# sourceMappingURL=tasks-index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tasks-index.d.ts","sourceRoot":"","sources":["../src/tasks-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA6DH;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,OAAO,CAAC,CA0DnB;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA4BxF"}
1
+ {"version":3,"file":"tasks-index.d.ts","sourceRoot":"","sources":["../src/tasks-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA4HH;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,OAAO,CAAC,CA4DnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,OAAO,CAAC,CAoDlB"}