zcode-acp-server 0.1.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 (108) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +167 -0
  3. package/README.zh-CN.md +163 -0
  4. package/dist/backend/client.d.ts +103 -0
  5. package/dist/backend/client.d.ts.map +1 -0
  6. package/dist/backend/client.js +344 -0
  7. package/dist/backend/client.js.map +1 -0
  8. package/dist/backend/credentials.d.ts +31 -0
  9. package/dist/backend/credentials.d.ts.map +1 -0
  10. package/dist/backend/credentials.js +93 -0
  11. package/dist/backend/credentials.js.map +1 -0
  12. package/dist/backend/index.d.ts +7 -0
  13. package/dist/backend/index.d.ts.map +1 -0
  14. package/dist/backend/index.js +6 -0
  15. package/dist/backend/index.js.map +1 -0
  16. package/dist/backend/listener.d.ts +63 -0
  17. package/dist/backend/listener.d.ts.map +1 -0
  18. package/dist/backend/listener.js +138 -0
  19. package/dist/backend/listener.js.map +1 -0
  20. package/dist/backend/resolve.d.ts +11 -0
  21. package/dist/backend/resolve.d.ts.map +1 -0
  22. package/dist/backend/resolve.js +116 -0
  23. package/dist/backend/resolve.js.map +1 -0
  24. package/dist/backend/types.d.ts +164 -0
  25. package/dist/backend/types.d.ts.map +1 -0
  26. package/dist/backend/types.js +15 -0
  27. package/dist/backend/types.js.map +1 -0
  28. package/dist/config/model-cache.d.ts +20 -0
  29. package/dist/config/model-cache.d.ts.map +1 -0
  30. package/dist/config/model-cache.js +62 -0
  31. package/dist/config/model-cache.js.map +1 -0
  32. package/dist/config/options.d.ts +36 -0
  33. package/dist/config/options.d.ts.map +1 -0
  34. package/dist/config/options.js +171 -0
  35. package/dist/config/options.js.map +1 -0
  36. package/dist/config/runtime-model.d.ts +33 -0
  37. package/dist/config/runtime-model.d.ts.map +1 -0
  38. package/dist/config/runtime-model.js +96 -0
  39. package/dist/config/runtime-model.js.map +1 -0
  40. package/dist/handlers/dispatch.d.ts +15 -0
  41. package/dist/handlers/dispatch.d.ts.map +1 -0
  42. package/dist/handlers/dispatch.js +183 -0
  43. package/dist/handlers/dispatch.js.map +1 -0
  44. package/dist/handlers/extensions.d.ts +43 -0
  45. package/dist/handlers/extensions.d.ts.map +1 -0
  46. package/dist/handlers/extensions.js +310 -0
  47. package/dist/handlers/extensions.js.map +1 -0
  48. package/dist/handlers/io.d.ts +40 -0
  49. package/dist/handlers/io.d.ts.map +1 -0
  50. package/dist/handlers/io.js +55 -0
  51. package/dist/handlers/io.js.map +1 -0
  52. package/dist/handlers/server-requests.d.ts +34 -0
  53. package/dist/handlers/server-requests.d.ts.map +1 -0
  54. package/dist/handlers/server-requests.js +357 -0
  55. package/dist/handlers/server-requests.js.map +1 -0
  56. package/dist/handlers/session.d.ts +46 -0
  57. package/dist/handlers/session.d.ts.map +1 -0
  58. package/dist/handlers/session.js +738 -0
  59. package/dist/handlers/session.js.map +1 -0
  60. package/dist/handlers/slash.d.ts +16 -0
  61. package/dist/handlers/slash.d.ts.map +1 -0
  62. package/dist/handlers/slash.js +107 -0
  63. package/dist/handlers/slash.js.map +1 -0
  64. package/dist/index.d.ts +11 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +93 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/interaction/adapter.d.ts +136 -0
  69. package/dist/interaction/adapter.d.ts.map +1 -0
  70. package/dist/interaction/adapter.js +353 -0
  71. package/dist/interaction/adapter.js.map +1 -0
  72. package/dist/server.d.ts +73 -0
  73. package/dist/server.d.ts.map +1 -0
  74. package/dist/server.js +97 -0
  75. package/dist/server.js.map +1 -0
  76. package/dist/tasks-index.d.ts +39 -0
  77. package/dist/tasks-index.d.ts.map +1 -0
  78. package/dist/tasks-index.js +152 -0
  79. package/dist/tasks-index.js.map +1 -0
  80. package/dist/translators/event-translator.d.ts +40 -0
  81. package/dist/translators/event-translator.d.ts.map +1 -0
  82. package/dist/translators/event-translator.js +214 -0
  83. package/dist/translators/event-translator.js.map +1 -0
  84. package/dist/translators/index.d.ts +6 -0
  85. package/dist/translators/index.d.ts.map +1 -0
  86. package/dist/translators/index.js +5 -0
  87. package/dist/translators/index.js.map +1 -0
  88. package/dist/translators/projection-differ.d.ts +48 -0
  89. package/dist/translators/projection-differ.d.ts.map +1 -0
  90. package/dist/translators/projection-differ.js +239 -0
  91. package/dist/translators/projection-differ.js.map +1 -0
  92. package/dist/translators/tool-helpers.d.ts +60 -0
  93. package/dist/translators/tool-helpers.d.ts.map +1 -0
  94. package/dist/translators/tool-helpers.js +308 -0
  95. package/dist/translators/tool-helpers.js.map +1 -0
  96. package/dist/translators/types.d.ts +58 -0
  97. package/dist/translators/types.d.ts.map +1 -0
  98. package/dist/translators/types.js +27 -0
  99. package/dist/translators/types.js.map +1 -0
  100. package/dist/utils.d.ts +111 -0
  101. package/dist/utils.d.ts.map +1 -0
  102. package/dist/utils.js +110 -0
  103. package/dist/utils.js.map +1 -0
  104. package/docs/ARCHITECTURE.md +299 -0
  105. package/docs/DEVELOPMENT.md +193 -0
  106. package/docs/PROTOCOL.md +649 -0
  107. package/docs/TROUBLESHOOTING.md +251 -0
  108. package/package.json +66 -0
@@ -0,0 +1,152 @@
1
+ /**
2
+ * ZCode App tasks-index sync: let the App UI see ACP-created sessions.
3
+ *
4
+ * The ZCode App's session list reads from `~/.zcode/v2/tasks-index.sqlite`
5
+ * (the `tasks` table), NOT from the CLI's `~/.zcode/cli/db/db.sqlite`. These
6
+ * are independent stores — the App's Electron host maintains tasks-index; the
7
+ * headless app-server (which we drive) writes only to cli/db. As a result,
8
+ * every session created via ACP is invisible in the App's UI until the App
9
+ * happens to reindex.
10
+ *
11
+ * This module bridges that gap by writing a tasks-index row directly after
12
+ * session/create. The App picks it up on its next list refresh. INSERT OR
13
+ * IGNORE avoids clobbering rows the App already manages.
14
+ *
15
+ * Best-effort side-channel: failures (locked DB, schema drift) are logged and
16
+ * swallowed so they never break the session/create path.
17
+ */
18
+ import { existsSync, readFileSync } from "node:fs";
19
+ import path from "node:path";
20
+ import { log, ZCODE_CREDS_PATH } from "./utils.js";
21
+ /**
22
+ * Dynamically load `node:sqlite` (Node ≥ 22). On older Node the import fails;
23
+ * callers degrade gracefully (tasks-index sync is best-effort). We cache the
24
+ * loaded class so repeated calls don't re-import.
25
+ */
26
+ let DatabaseSyncCtor;
27
+ async function loadSqlite() {
28
+ if (DatabaseSyncCtor !== undefined)
29
+ return DatabaseSyncCtor;
30
+ try {
31
+ // node:sqlite ships with Node ≥ 22. Cast through unknown so this compiles
32
+ // even if @types/node lags behind the runtime module.
33
+ const mod = (await import("node:sqlite"));
34
+ DatabaseSyncCtor = mod.DatabaseSync;
35
+ }
36
+ catch {
37
+ DatabaseSyncCtor = null; // Node < 22 or sqlite unavailable
38
+ }
39
+ return DatabaseSyncCtor;
40
+ }
41
+ /** tasks-index.sqlite sits next to config.json under ~/.zcode/v2/. */
42
+ const TASKS_INDEX_PATH = path.join(path.dirname(ZCODE_CREDS_PATH), "tasks-index.sqlite");
43
+ /** Read provider id + model id from config.json (display-only fields). */
44
+ function resolveProviderModel() {
45
+ try {
46
+ const cfg = JSON.parse(readFileSync(ZCODE_CREDS_PATH, "utf8"));
47
+ for (const [, p] of Object.entries(cfg.provider ?? {})) {
48
+ if (p?.enabled) {
49
+ const models = p.models ?? {};
50
+ const modelId = Object.keys(models)[0] ?? "GLM-5.2";
51
+ return { providerId: "glm", modelRef: modelId };
52
+ }
53
+ }
54
+ }
55
+ catch {
56
+ // fall through to defaults
57
+ }
58
+ return { providerId: "glm", modelRef: "GLM-5.2" };
59
+ }
60
+ /**
61
+ * Insert (or refresh) a row in tasks-index.sqlite so the App UI shows it.
62
+ * Called after a successful session/create. Uses INSERT OR IGNORE so it never
63
+ * overwrites a row the App is actively managing (e.g. user-renamed titles).
64
+ *
65
+ * Returns true if written, false on failure (logged, never thrown).
66
+ */
67
+ export async function upsertSessionTask(opts) {
68
+ if (!existsSync(TASKS_INDEX_PATH))
69
+ return false; // App never installed → no index.
70
+ const DatabaseSync = await loadSqlite();
71
+ if (!DatabaseSync)
72
+ return false; // node:sqlite unavailable (Node < 22)
73
+ const nowMs = Date.now();
74
+ const { providerId, modelRef } = resolveProviderModel();
75
+ const model = opts.model ?? modelRef;
76
+ const status = opts.status ?? "completed";
77
+ const meta = {
78
+ taskId: opts.taskId,
79
+ traceId: opts.traceId ?? opts.taskId,
80
+ title: opts.title,
81
+ titleOverridden: false,
82
+ workspacePath: opts.workspaceKey,
83
+ createdAt: nowMs,
84
+ updatedAt: nowMs,
85
+ mode: "build",
86
+ model,
87
+ provider: providerId,
88
+ status,
89
+ target: null,
90
+ };
91
+ let metaJson;
92
+ try {
93
+ metaJson = JSON.stringify(meta);
94
+ }
95
+ catch {
96
+ return false;
97
+ }
98
+ try {
99
+ const con = DatabaseSync(TASKS_INDEX_PATH, { timeout: 5000 });
100
+ try {
101
+ con.run("INSERT OR IGNORE INTO tasks " +
102
+ "(workspace_key, workspace_path, workspace_identity, task_id, " +
103
+ " title, task_status, provider, mode, model, " +
104
+ " created_at, updated_at, unread_at, pinned, archived, deleted, " +
105
+ " title_overridden, meta_json, searchable_text) " +
106
+ "VALUES (?, ?, NULL, ?, ?, ?, ?, 'build', ?, ?, ?, NULL, 0, 0, 0, 0, ?, ?)", opts.workspaceKey, opts.workspaceKey, opts.taskId, opts.title, status, providerId, model, nowMs, nowMs, metaJson, opts.title);
107
+ }
108
+ finally {
109
+ con.close();
110
+ }
111
+ return true;
112
+ }
113
+ catch (e) {
114
+ log(`tasks-index sync skipped: ${e instanceof Error ? e.message : String(e)}`);
115
+ return false;
116
+ }
117
+ }
118
+ /**
119
+ * Update a session's title after the first turn. session/create leaves title
120
+ * empty; once the first prompt completes, set a meaningful title. Respects
121
+ * title_overridden: if the user already renamed in the App, their title wins.
122
+ */
123
+ export async function updateSessionTitle(taskId, title) {
124
+ if (!existsSync(TASKS_INDEX_PATH) || !title)
125
+ return false;
126
+ const DatabaseSync = await loadSqlite();
127
+ if (!DatabaseSync)
128
+ return false;
129
+ const trimmed = title.trim().slice(0, 80);
130
+ if (!trimmed)
131
+ return false;
132
+ try {
133
+ const con = DatabaseSync(TASKS_INDEX_PATH, { timeout: 5000 });
134
+ try {
135
+ const row = con.get("SELECT title_overridden FROM tasks WHERE task_id=?", taskId);
136
+ if (!row)
137
+ return false;
138
+ if (row.title_overridden === 1)
139
+ return true; // user overrode → respect it
140
+ con.run("UPDATE tasks SET title=?, updated_at=?, searchable_text=? WHERE task_id=? AND title_overridden=0", trimmed, Date.now(), trimmed, taskId);
141
+ }
142
+ finally {
143
+ con.close();
144
+ }
145
+ return true;
146
+ }
147
+ catch (e) {
148
+ log(`tasks-index title update skipped: ${e instanceof Error ? e.message : String(e)}`);
149
+ return false;
150
+ }
151
+ }
152
+ //# sourceMappingURL=tasks-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks-index.js","sourceRoot":"","sources":["../src/tasks-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * EventTranslator: turn zcode `session/event` pushes into internal event dicts.
3
+ *
4
+ * The output shape matches `ProjectionDiffer.diff()` (the `InternalEvent` union)
5
+ * so either can feed `dispatchEvent`. State held per-translator:
6
+ * - seenToolIds / toolNames / toolInputs / finalToolIds for tool lifecycle
7
+ * - turnStarted / turnDone / turnFailed / turnResultType / turnError for turn state
8
+ *
9
+ * A critical quirk: zcode streams tool input via `model.streaming tool_call`
10
+ * BEFORE the `tool.updated scheduled` event, whose `input` is then omitted
11
+ * (`inputOmitted:true`). So we cache input from `tool_call` and fall back to
12
+ * it when `scheduled` arrives without input.
13
+ */
14
+ import type { InternalEvent } from "./types.js";
15
+ interface ZcodeEventPayload {
16
+ type?: string;
17
+ payload?: Record<string, unknown>;
18
+ }
19
+ export declare class EventTranslator {
20
+ turnStarted: boolean;
21
+ turnDone: boolean;
22
+ turnFailed: boolean;
23
+ turnResultType: string | null;
24
+ turnError: Record<string, unknown> | null;
25
+ /** Tool call ids we've already emitted a ToolCallNew for. */
26
+ readonly seenToolIds: Set<string>;
27
+ /** call_id → tool_name (result/error events omit toolName). */
28
+ readonly toolNames: Map<string, string>;
29
+ /** call_id → input dict cached from model.streaming tool_call. */
30
+ readonly toolInputs: Map<string, unknown>;
31
+ /** Tool call ids that reached a terminal state (result/error). */
32
+ readonly finalToolIds: Set<string>;
33
+ /** Translate one zcode event into 0..n internal events. */
34
+ translate(event: ZcodeEventPayload): InternalEvent[];
35
+ private translateStreaming;
36
+ private translateTool;
37
+ private translateTurnDone;
38
+ }
39
+ export {};
40
+ //# sourceMappingURL=event-translator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-translator.d.ts","sourceRoot":"","sources":["../../src/translators/event-translator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAUH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,UAAU,iBAAiB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,qBAAa,eAAe;IAC1B,WAAW,UAAS;IACpB,QAAQ,UAAS;IACjB,UAAU,UAAS;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IACrC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAQ;IAEjD,6DAA6D;IAC7D,QAAQ,CAAC,WAAW,cAAqB;IACzC,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,sBAA6B;IAC/C,kEAAkE;IAClE,QAAQ,CAAC,UAAU,uBAA8B;IACjD,kEAAkE;IAClE,QAAQ,CAAC,YAAY,cAAqB;IAE1C,2DAA2D;IAC3D,SAAS,CAAC,KAAK,EAAE,iBAAiB,GAAG,aAAa,EAAE;IAmCpD,OAAO,CAAC,kBAAkB;IAoB1B,OAAO,CAAC,aAAa;IAsGrB,OAAO,CAAC,iBAAiB;CAS1B"}
@@ -0,0 +1,214 @@
1
+ /**
2
+ * EventTranslator: turn zcode `session/event` pushes into internal event dicts.
3
+ *
4
+ * The output shape matches `ProjectionDiffer.diff()` (the `InternalEvent` union)
5
+ * so either can feed `dispatchEvent`. State held per-translator:
6
+ * - seenToolIds / toolNames / toolInputs / finalToolIds for tool lifecycle
7
+ * - turnStarted / turnDone / turnFailed / turnResultType / turnError for turn state
8
+ *
9
+ * A critical quirk: zcode streams tool input via `model.streaming tool_call`
10
+ * BEFORE the `tool.updated scheduled` event, whose `input` is then omitted
11
+ * (`inputOmitted:true`). So we cache input from `tool_call` and fall back to
12
+ * it when `scheduled` arrives without input.
13
+ */
14
+ import { log, warn } from "../utils.js";
15
+ import { buildResultContent, extractLocations, renderToolOutput, summarizeToolInput, TOOL_KIND_MAP, } from "./tool-helpers.js";
16
+ export class EventTranslator {
17
+ turnStarted = false;
18
+ turnDone = false;
19
+ turnFailed = false;
20
+ turnResultType = null;
21
+ turnError = null;
22
+ /** Tool call ids we've already emitted a ToolCallNew for. */
23
+ seenToolIds = new Set();
24
+ /** call_id → tool_name (result/error events omit toolName). */
25
+ toolNames = new Map();
26
+ /** call_id → input dict cached from model.streaming tool_call. */
27
+ toolInputs = new Map();
28
+ /** Tool call ids that reached a terminal state (result/error). */
29
+ finalToolIds = new Set();
30
+ /** Translate one zcode event into 0..n internal events. */
31
+ translate(event) {
32
+ const etype = event.type ?? "";
33
+ const payload = event.payload ?? {};
34
+ const results = [];
35
+ if (etype === "turn.started") {
36
+ this.turnStarted = true;
37
+ log(" [event] turn.started");
38
+ }
39
+ else if (etype === "model.streaming") {
40
+ results.push(...this.translateStreaming(payload));
41
+ }
42
+ else if (etype === "tool.updated") {
43
+ results.push(...this.translateTool(payload));
44
+ }
45
+ else if (etype === "turn.completed") {
46
+ this.turnDone = true;
47
+ this.turnResultType = payload["resultType"] ?? "success";
48
+ results.push(...this.translateTurnDone(payload));
49
+ log(` [event] turn.completed (resultType=${this.turnResultType})`);
50
+ }
51
+ else if (etype === "session.updated") {
52
+ const usage = payload["usage"] ?? {};
53
+ const used = usage["inputTokens"];
54
+ const size = payload["contextWindow"] ?? 0;
55
+ if (typeof used === "number") {
56
+ results.push({ kind: "UsageDelta", used, size });
57
+ }
58
+ }
59
+ else if (etype === "turn.failed") {
60
+ this.turnDone = true;
61
+ this.turnFailed = true;
62
+ this.turnError = payload["error"] ?? {};
63
+ this.turnResultType = payload["resultType"] ?? "error";
64
+ const err = this.turnError;
65
+ warn(` [event] turn.failed (code=${err["code"] ?? err["type"] ?? "?"})`);
66
+ }
67
+ return results;
68
+ }
69
+ translateStreaming(payload) {
70
+ const results = [];
71
+ const kind = payload["kind"] ?? "";
72
+ const delta = payload["delta"] ?? "";
73
+ if (kind === "text_delta") {
74
+ if (delta)
75
+ results.push({ kind: "TextDelta", text: delta });
76
+ }
77
+ else if (kind === "reasoning_delta") {
78
+ if (delta)
79
+ results.push({ kind: "ReasoningDelta", text: delta });
80
+ }
81
+ else if (kind === "tool_call") {
82
+ // Cache input + toolName for the later scheduled event.
83
+ const callId = payload["toolCallId"] ?? "";
84
+ if (callId) {
85
+ if (payload["toolName"])
86
+ this.toolNames.set(callId, payload["toolName"]);
87
+ if (payload["input"] !== undefined)
88
+ this.toolInputs.set(callId, payload["input"]);
89
+ }
90
+ }
91
+ return results;
92
+ }
93
+ translateTool(payload) {
94
+ const results = [];
95
+ const tkind = payload["kind"] ?? "";
96
+ const callId = payload["toolCallId"] ?? "";
97
+ let toolName = payload["toolName"] ?? "";
98
+ if (tkind === "scheduled") {
99
+ if (callId && !this.seenToolIds.has(callId)) {
100
+ this.seenToolIds.add(callId);
101
+ if (toolName) {
102
+ this.toolNames.set(callId, toolName);
103
+ }
104
+ else {
105
+ toolName = this.toolNames.get(callId) ?? "unknown";
106
+ }
107
+ const acpKind = TOOL_KIND_MAP[toolName] ?? "execute";
108
+ // Input: scheduled payload first, fall back to cached tool_call input.
109
+ let inp = payload["input"];
110
+ if (inp === undefined)
111
+ inp = this.toolInputs.get(callId);
112
+ const summary = summarizeToolInput(toolName, inp);
113
+ const title = summary ? `${toolName}: ${summary}` : toolName;
114
+ const newEv = {
115
+ kind: "ToolCallNew",
116
+ callId,
117
+ tool: toolName,
118
+ acpKind,
119
+ status: "pending",
120
+ title,
121
+ };
122
+ if (inp !== undefined)
123
+ newEv.input = inp;
124
+ const locs = extractLocations(toolName, inp);
125
+ if (locs.length > 0)
126
+ newEv.locations = locs;
127
+ results.push(newEv);
128
+ }
129
+ }
130
+ else if (tkind === "started") {
131
+ if (callId) {
132
+ results.push({ kind: "ToolCallUpdate", callId, status: "in_progress" });
133
+ }
134
+ }
135
+ else if (tkind === "progress") {
136
+ if (callId) {
137
+ const output = payload["stdoutTail"] ?? payload["stderrTail"] ?? "";
138
+ const tn = (toolName || this.toolNames.get(callId)) ?? "";
139
+ results.push({
140
+ kind: "ToolCallUpdate",
141
+ callId,
142
+ tool: tn,
143
+ status: "in_progress",
144
+ output: renderToolOutput(output),
145
+ rawOutput: output,
146
+ });
147
+ }
148
+ }
149
+ else if (tkind === "result") {
150
+ if (callId) {
151
+ const resultPayload = payload["result"];
152
+ const tn = (toolName || this.toolNames.get(callId)) ?? "";
153
+ const ev = {
154
+ kind: "ToolCallUpdate",
155
+ callId,
156
+ tool: tn,
157
+ status: "completed",
158
+ output: renderToolOutput(resultPayload),
159
+ rawResult: resultPayload,
160
+ };
161
+ // Bash content handled by the terminal path in dispatch; skip here.
162
+ if (tn !== "Bash" && tn !== "bash") {
163
+ const content = buildResultContent(tn, resultPayload);
164
+ if (content.length > 0)
165
+ ev.content = content;
166
+ }
167
+ results.push(ev);
168
+ this.finalToolIds.add(callId);
169
+ }
170
+ }
171
+ else if (tkind === "error") {
172
+ if (callId) {
173
+ const tn = (toolName || this.toolNames.get(callId)) ?? "";
174
+ const errPayload = payload["error"];
175
+ const ev = {
176
+ kind: "ToolCallUpdate",
177
+ callId,
178
+ tool: tn,
179
+ status: "failed",
180
+ output: renderToolOutput(errPayload),
181
+ };
182
+ const content = buildResultContent(tn, errPayload, true);
183
+ if (content.length > 0)
184
+ ev.content = content;
185
+ results.push(ev);
186
+ this.finalToolIds.add(callId);
187
+ }
188
+ }
189
+ else if (tkind === "batch") {
190
+ // Multi-tool completion. Only backfill unseen or non-final ids, else a
191
+ // content-less `completed` would overwrite a prior result event.
192
+ const batchIds = payload["toolCallIds"] ?? [];
193
+ const errorCount = payload["errorCount"] ?? 0;
194
+ const finalStatus = errorCount > 0 ? "failed" : "completed";
195
+ for (const bid of batchIds) {
196
+ if (this.seenToolIds.has(bid) && !this.finalToolIds.has(bid)) {
197
+ results.push({ kind: "ToolCallUpdate", callId: bid, status: finalStatus });
198
+ this.finalToolIds.add(bid);
199
+ }
200
+ }
201
+ }
202
+ return results;
203
+ }
204
+ translateTurnDone(payload) {
205
+ const usage = payload["usage"] ?? {};
206
+ // Use || (not ??) to match Python's `or` semantics: a falsy totalTokens
207
+ // (0 / undefined) falls back to tokenCount, then to 0. With ?? a 0 would
208
+ // be kept as-is and never fall back, diverging from the Python reference.
209
+ const used = usage["totalTokens"] || payload["tokenCount"] || 0;
210
+ const size = usage["contextWindow"] || 0;
211
+ return [{ kind: "UsageDelta", used, size }];
212
+ }
213
+ }
214
+ //# sourceMappingURL=event-translator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-translator.js","sourceRoot":"","sources":["../../src/translators/event-translator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /** Translators barrel: internal event types + EventTranslator + ProjectionDiffer + helpers. */
2
+ export { EventTranslator } from "./event-translator.js";
3
+ export { ProjectionDiffer } from "./projection-differ.js";
4
+ export { TOOL_KIND_MAP, summarizeToolInput, renderToolOutput, extractExitCode, buildResultContent, buildDiffContent, extractLocations, formatTurnError, } from "./tool-helpers.js";
5
+ export type { InternalEvent, ToolCallNewEvent, ToolCallUpdateEvent, UsageDeltaEvent, TextDeltaEvent, ReasoningDeltaEvent, PlanUpdateEvent, FilesChangedEvent, } from "./types.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/translators/index.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAE/F,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** Translators barrel: internal event types + EventTranslator + ProjectionDiffer + helpers. */
2
+ export { EventTranslator } from "./event-translator.js";
3
+ export { ProjectionDiffer } from "./projection-differ.js";
4
+ export { TOOL_KIND_MAP, summarizeToolInput, renderToolOutput, extractExitCode, buildResultContent, buildDiffContent, extractLocations, formatTurnError, } from "./tool-helpers.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/translators/index.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAE/F,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,GAChB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * ProjectionDiffer: diff two `{projection, messages, todos}` snapshots into
3
+ * internal events.
4
+ *
5
+ * Used in three places:
6
+ * 1. Turn completion — emit the final PlanUpdate / usage (text/tools are
7
+ * already deduped by seenMessageIds).
8
+ * 2. Stall reconciliation — recover missed events from an authoritative
9
+ * `session/messages` snapshot.
10
+ * 3. session/load — replay an initial plan.
11
+ *
12
+ * Only NEW messages (by message id dedup) are processed, so multi-turn/resume
13
+ * history isn't re-emitted. The PlanUpdate fires whenever the todos signature
14
+ * changes (including clearing to empty — the initial `_lastPlanSig = "__none__"`
15
+ * makes the first empty list also emit).
16
+ */
17
+ import type { ZcodeMessage, ZcodeSnapshot } from "../backend/types.js";
18
+ import type { InternalEvent } from "./types.js";
19
+ export declare class ProjectionDiffer {
20
+ private readonly seenToolIds;
21
+ private readonly lastToolStatus;
22
+ private lastUsage;
23
+ private readonly seenMessageIds;
24
+ private lastPlanSig;
25
+ private readonly seenPatchHashes;
26
+ /** Whether any TextDelta fired this turn (used by fallback detection). */
27
+ emittedTextThisTurn: boolean;
28
+ /** Mark all given messages as seen (baseline so we don't re-emit history). */
29
+ markSeen(messages: ZcodeMessage[]): void;
30
+ /** Whether a message's dedup key has already been processed. */
31
+ hasSeenMessage(m: ZcodeMessage): boolean;
32
+ /**
33
+ * Mark a tool call id as seen + completed. Used to sync state from the
34
+ * EventTranslator so the next `diff()` won't re-emit a tool the event path
35
+ * already dispatched (which would clear Bash terminal output via a
36
+ * content-less ToolCallNew through the terminal path).
37
+ */
38
+ markToolSeen(callId: string): void;
39
+ /** Reset per-turn flags (does NOT reset seenMessageIds). */
40
+ resetTurn(): void;
41
+ /** Set the usage baseline so the next diff won't re-emit the same value. */
42
+ setLastUsage(used: number): void;
43
+ /** Diff two snapshots. Returns 0..n events. */
44
+ diff(curSnapshot: ZcodeSnapshot | null): InternalEvent[];
45
+ private diffToolPart;
46
+ private messageDedupKey;
47
+ }
48
+ //# sourceMappingURL=projection-differ.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projection-differ.d.ts","sourceRoot":"","sources":["../../src/translators/projection-differ.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EACV,YAAY,EAGZ,aAAa,EACd,MAAM,qBAAqB,CAAC;AAS7B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAUhD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;IACrD,0EAA0E;IAC1E,mBAAmB,UAAS;IAE5B,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI;IAOxC,gEAAgE;IAChE,cAAc,CAAC,CAAC,EAAE,YAAY,GAAG,OAAO;IAKxC;;;;;OAKG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKlC,4DAA4D;IAC5D,SAAS,IAAI,IAAI;IAIjB,4EAA4E;IAC5E,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIhC,+CAA+C;IAC/C,IAAI,CAAC,WAAW,EAAE,aAAa,GAAG,IAAI,GAAG,aAAa,EAAE;IA6DxD,OAAO,CAAC,YAAY;IAmEpB,OAAO,CAAC,eAAe;CAYxB"}