@agentdocumentformat/cli 0.7.2

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 (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +45 -0
  3. package/dist/adf.mjs +162 -0
  4. package/dist/chunks/APEv2Parser-2CNNHMXV.mjs +22 -0
  5. package/dist/chunks/AiffParser-7BR4RL6G.mjs +162 -0
  6. package/dist/chunks/App-L5L37JI5.mjs +16747 -0
  7. package/dist/chunks/AsfParser-VVRSLFOM.mjs +538 -0
  8. package/dist/chunks/DsdiffParser-CMD4AX7A.mjs +156 -0
  9. package/dist/chunks/DsfParser-UOGZDS2M.mjs +94 -0
  10. package/dist/chunks/FlacParser-HB3T3CD4.mjs +23 -0
  11. package/dist/chunks/MP4Parser-66HBRUSX.mjs +973 -0
  12. package/dist/chunks/MatroskaParser-J3HUIMEW.mjs +579 -0
  13. package/dist/chunks/MpegParser-YW6LIUEW.mjs +442 -0
  14. package/dist/chunks/MusepackParser-PAUSXP7D.mjs +252 -0
  15. package/dist/chunks/OggParser-NUBV3GWC.mjs +359 -0
  16. package/dist/chunks/WavPackParser-WQAGT7TC.mjs +171 -0
  17. package/dist/chunks/WaveParser-EWLQVDX4.mjs +238 -0
  18. package/dist/chunks/adf-schema-JRU2BTOG.mjs +62 -0
  19. package/dist/chunks/build-QF5W473T.mjs +60 -0
  20. package/dist/chunks/chatgpt-subscription-BQGWYZXE.mjs +23 -0
  21. package/dist/chunks/chunk-2DIECGFL.mjs +6 -0
  22. package/dist/chunks/chunk-2NAP2ZF7.mjs +60 -0
  23. package/dist/chunks/chunk-3AT7IIP7.mjs +25696 -0
  24. package/dist/chunks/chunk-3GNIDM53.mjs +35 -0
  25. package/dist/chunks/chunk-3M4ZPOA3.mjs +1477 -0
  26. package/dist/chunks/chunk-4MQPTCXY.mjs +510 -0
  27. package/dist/chunks/chunk-5PO5PKRV.mjs +366 -0
  28. package/dist/chunks/chunk-5QU5VY7N.mjs +52 -0
  29. package/dist/chunks/chunk-5W7KES6P.mjs +436 -0
  30. package/dist/chunks/chunk-62NE4LG4.mjs +61 -0
  31. package/dist/chunks/chunk-64OKE4X3.mjs +45 -0
  32. package/dist/chunks/chunk-6GJ4QHRI.mjs +1278 -0
  33. package/dist/chunks/chunk-6VQEXLE2.mjs +144 -0
  34. package/dist/chunks/chunk-6XUV6EK6.mjs +41 -0
  35. package/dist/chunks/chunk-776TSXEP.mjs +43 -0
  36. package/dist/chunks/chunk-7CV2SA3H.mjs +285 -0
  37. package/dist/chunks/chunk-7MTRVW2U.mjs +3103 -0
  38. package/dist/chunks/chunk-7N2R2VCG.mjs +1434 -0
  39. package/dist/chunks/chunk-7T2YMTWL.mjs +374 -0
  40. package/dist/chunks/chunk-7XYNI52E.mjs +149 -0
  41. package/dist/chunks/chunk-APHX6HSV.mjs +7731 -0
  42. package/dist/chunks/chunk-APRU6PHC.mjs +40 -0
  43. package/dist/chunks/chunk-AUYKRQPJ.mjs +499 -0
  44. package/dist/chunks/chunk-DXWDD5XJ.mjs +136 -0
  45. package/dist/chunks/chunk-EWL5FG4I.mjs +39 -0
  46. package/dist/chunks/chunk-EYX2YLJW.mjs +117 -0
  47. package/dist/chunks/chunk-F5ELW46V.mjs +27 -0
  48. package/dist/chunks/chunk-G426FACA.mjs +49 -0
  49. package/dist/chunks/chunk-GEKSJHIV.mjs +2472 -0
  50. package/dist/chunks/chunk-HBUENVQL.mjs +570 -0
  51. package/dist/chunks/chunk-HPVFJYXR.mjs +112 -0
  52. package/dist/chunks/chunk-HWLWPXQ7.mjs +721 -0
  53. package/dist/chunks/chunk-I2HJYHFT.mjs +665 -0
  54. package/dist/chunks/chunk-I3UYSITV.mjs +68 -0
  55. package/dist/chunks/chunk-IC4JDZCI.mjs +3864 -0
  56. package/dist/chunks/chunk-IHDDCZBS.mjs +112 -0
  57. package/dist/chunks/chunk-IIGMZHQQ.mjs +10416 -0
  58. package/dist/chunks/chunk-KWFOS5WC.mjs +41 -0
  59. package/dist/chunks/chunk-LAZIXV2F.mjs +5290 -0
  60. package/dist/chunks/chunk-LFMB4PAA.mjs +10814 -0
  61. package/dist/chunks/chunk-M2RX3S2T.mjs +49 -0
  62. package/dist/chunks/chunk-M3WPIJYM.mjs +65 -0
  63. package/dist/chunks/chunk-NBTUWMGP.mjs +263 -0
  64. package/dist/chunks/chunk-NGK6PVSF.mjs +2676 -0
  65. package/dist/chunks/chunk-NZ7JTHEO.mjs +85 -0
  66. package/dist/chunks/chunk-OQN33RGQ.mjs +52 -0
  67. package/dist/chunks/chunk-RIX34QHC.mjs +2935 -0
  68. package/dist/chunks/chunk-SGUTYISF.mjs +16 -0
  69. package/dist/chunks/chunk-SLJ5L7PY.mjs +1473 -0
  70. package/dist/chunks/chunk-SLUKGXKH.mjs +68 -0
  71. package/dist/chunks/chunk-TMT32MXT.mjs +419 -0
  72. package/dist/chunks/chunk-UYY5M2PB.mjs +151 -0
  73. package/dist/chunks/chunk-VAUOM3IN.mjs +298 -0
  74. package/dist/chunks/chunk-VMHTYDH4.mjs +172 -0
  75. package/dist/chunks/chunk-VZS54AA5.mjs +200 -0
  76. package/dist/chunks/chunk-WFQUVXML.mjs +295 -0
  77. package/dist/chunks/chunk-X34PDRUH.mjs +809 -0
  78. package/dist/chunks/chunk-XNPZBLYL.mjs +33 -0
  79. package/dist/chunks/chunk-XX7OSWTO.mjs +157 -0
  80. package/dist/chunks/chunk-XYTWGHFS.mjs +600 -0
  81. package/dist/chunks/chunk-XYV3VCIX.mjs +336 -0
  82. package/dist/chunks/chunk-Y5ZLKFLE.mjs +1469 -0
  83. package/dist/chunks/chunk-ZJKXHM4Q.mjs +230 -0
  84. package/dist/chunks/cli-TCMBNZF6.mjs +1030 -0
  85. package/dist/chunks/commands-DTEKM4ZL.mjs +20 -0
  86. package/dist/chunks/daemon-ZC3FZ2P4.mjs +112449 -0
  87. package/dist/chunks/daemon-control-WDX7PMTC.mjs +300 -0
  88. package/dist/chunks/daemon-token-WRSULP7G.mjs +23 -0
  89. package/dist/chunks/devtools-H7CI2ZVG.mjs +85 -0
  90. package/dist/chunks/discord-IWDQJA7A.mjs +70588 -0
  91. package/dist/chunks/dist-C57KYFS2.mjs +4952 -0
  92. package/dist/chunks/dist-I3XBAGDL.mjs +11 -0
  93. package/dist/chunks/email-V4Q4VJON.mjs +58679 -0
  94. package/dist/chunks/environment-NX277MQG.mjs +15 -0
  95. package/dist/chunks/grok-subscription-4PYX7TBF.mjs +19 -0
  96. package/dist/chunks/layout-EPJQNFAI.mjs +22 -0
  97. package/dist/chunks/lib-N7FCZWKH.mjs +4038 -0
  98. package/dist/chunks/open-OTQDGDH5.mjs +36 -0
  99. package/dist/chunks/parser-JVY2PWSM.mjs +19 -0
  100. package/dist/chunks/pipeline-executor-BHBSJX2K.mjs +19 -0
  101. package/dist/chunks/react-IUIDQ5LX.mjs +11 -0
  102. package/dist/chunks/screen-54BUTYCW.mjs +27 -0
  103. package/dist/chunks/slack-3L5QTDZX.mjs +8113 -0
  104. package/dist/chunks/store-WR7TZJZS.mjs +32 -0
  105. package/dist/chunks/telegram-5ISVFBV3.mjs +14918 -0
  106. package/dist/chunks/terminal-O5WO7C5U.mjs +48 -0
  107. package/dist/chunks/theme-NORU4J74.mjs +20 -0
  108. package/dist/chunks/themes-F2FKU7CP.mjs +23 -0
  109. package/dist/chunks/token-6G3HCMNX.mjs +54 -0
  110. package/dist/chunks/token-util-UXYSDQIW.mjs +12 -0
  111. package/dist/chunks/tui-ODVYUIMT.mjs +197 -0
  112. package/dist/chunks/welcome-XHXFV7SH.mjs +32 -0
  113. package/dist/chunks/whatsapp-XSAMNGPJ.mjs +85412 -0
  114. package/dist/chunks/xterm-headless-YF53XWXE.mjs +3353 -0
  115. package/package.json +53 -0
  116. package/resources/wasm/coreutils.LICENSE +18 -0
  117. package/resources/wasm/coreutils.wasm +0 -0
@@ -0,0 +1,1477 @@
1
+ import { createRequire as __adfCreateRequire } from 'node:module';
2
+ import { fileURLToPath as __adfFileURLToPath } from 'node:url';
3
+ import { dirname as __adfDirname } from 'node:path';
4
+ const require = __adfCreateRequire(import.meta.url);
5
+ const __filename = __adfFileURLToPath(import.meta.url);
6
+ const __dirname = __adfDirname(__filename);
7
+ import {
8
+ require_jsx_runtime
9
+ } from "./chunk-7CV2SA3H.mjs";
10
+ import {
11
+ DaemonError,
12
+ MAIN_LOOP
13
+ } from "./chunk-XNPZBLYL.mjs";
14
+ import {
15
+ cjs
16
+ } from "./chunk-SGUTYISF.mjs";
17
+ import {
18
+ loop_parser_exports
19
+ } from "./chunk-5PO5PKRV.mjs";
20
+ import {
21
+ require_react
22
+ } from "./chunk-6GJ4QHRI.mjs";
23
+ import {
24
+ __toESM
25
+ } from "./chunk-M2RX3S2T.mjs";
26
+
27
+ // src/main/tui/state/store.tsx
28
+ var import_react = __toESM(require_react(), 1);
29
+
30
+ // src/main/tui/state/tracked.ts
31
+ var TRACKED_PREFIX = "file:";
32
+ function trackedKey(filePath) {
33
+ return `${TRACKED_PREFIX}${filePath}`;
34
+ }
35
+ function isTrackedKey(id) {
36
+ return !!id && id.startsWith(TRACKED_PREFIX);
37
+ }
38
+ function trackedPath(key) {
39
+ return key.slice(TRACKED_PREFIX.length);
40
+ }
41
+ var FOLD_CASE = process.platform === "win32" || process.platform === "darwin";
42
+ function normPath(p) {
43
+ let n = p.replace(/\\/g, "/").replace(/\/+$/, "");
44
+ return FOLD_CASE ? n.toLowerCase() : n;
45
+ }
46
+ function samePath(a, b) {
47
+ return !!a && !!b && normPath(a) === normPath(b);
48
+ }
49
+ function relativeTo(folder, file) {
50
+ let f = file.replace(/\\/g, "/"), root = folder.replace(/\\/g, "/").replace(/\/+$/, "");
51
+ return normPath(f).startsWith(`${normPath(root)}/`) ? f.slice(root.length + 1) : f.slice(f.lastIndexOf("/") + 1);
52
+ }
53
+ function folderName(folder) {
54
+ let parts = folder.replace(/\\/g, "/").replace(/\/+$/, "").split("/");
55
+ return parts[parts.length - 1] || folder;
56
+ }
57
+ function stoppedLabel(entry, errors = {}) {
58
+ let a = entry.agent;
59
+ if (a.status === "unreadable") return "unreadable";
60
+ if (a.error || errors[a.filePath]) return "load error";
61
+ switch (a.status) {
62
+ case "needs_review":
63
+ return "needs review";
64
+ case "password_protected":
65
+ return "locked";
66
+ default:
67
+ return "stopped";
68
+ }
69
+ }
70
+ function stoppedError(entry, errors = {}) {
71
+ return errors[entry.agent.filePath] ?? entry.agent.error;
72
+ }
73
+ function buildTracked(list, loaded, previous) {
74
+ let loadedPaths = new Set(loaded.map((a) => a.filePath).filter((p) => !!p).map(normPath)), seen = /* @__PURE__ */ new Set(), stopped = [];
75
+ for (let folder of list.folders) {
76
+ let rows = [];
77
+ for (let agent of folder.agents) {
78
+ let n = normPath(agent.filePath);
79
+ agent.status === "loaded" || loadedPaths.has(n) || seen.has(n) || (seen.add(n), rows.push({ key: trackedKey(agent.filePath), folder: folder.path, relPath: relativeTo(folder.path, agent.filePath), agent }));
80
+ }
81
+ rows.sort((a, b) => a.relPath.localeCompare(b.relPath)), stopped.push(...rows);
82
+ }
83
+ let errors = {};
84
+ for (let [path, error] of Object.entries(previous?.errors ?? {})) seen.has(normPath(path)) && (errors[path] = error);
85
+ return {
86
+ folders: list.folders.map((f) => ({ path: f.path, exists: f.exists, agentCount: f.agentCount ?? f.agents.length, loadedCount: f.agentCount !== void 0 ? f.loadedCount : f.agents.filter((a) => a.status === "loaded").length })),
87
+ stopped,
88
+ errors,
89
+ busy: previous?.busy ?? {},
90
+ at: Date.now()
91
+ };
92
+ }
93
+ function pruneLoaded(tracked, loaded) {
94
+ let loadedPaths = new Set(loaded.map((a) => a.filePath).filter((p) => !!p).map(normPath)), stopped = tracked.stopped.filter((t) => !loadedPaths.has(normPath(t.agent.filePath)));
95
+ if (stopped.length === tracked.stopped.length) return tracked;
96
+ let errors = { ...tracked.errors };
97
+ for (let t of tracked.stopped) loadedPaths.has(normPath(t.agent.filePath)) && delete errors[t.agent.filePath];
98
+ return { ...tracked, stopped, errors };
99
+ }
100
+ function underTrackedFolder(tracked, file) {
101
+ if (!tracked) return !1;
102
+ let f = normPath(file);
103
+ return tracked.folders.some((folder) => f.startsWith(`${normPath(folder.path)}/`));
104
+ }
105
+ function findTracked(state, key) {
106
+ if (!(!key || !state.tracked))
107
+ return state.tracked.stopped.find((t) => t.key === key) ?? state.tracked.stopped.find((t) => samePath(t.agent.filePath, trackedPath(key)));
108
+ }
109
+ function loadedIdForPath(state, filePath) {
110
+ return state.agentOrder.find((id) => samePath(state.agents[id]?.summary.filePath, filePath));
111
+ }
112
+ function reconcileSelection(state, previousSummaries = {}, trackedFresh = !1) {
113
+ let selected = state.selectedAgentId;
114
+ if (selected && !isTrackedKey(selected)) {
115
+ if (state.agents[selected]) return selected;
116
+ let file = previousSummaries[selected]?.filePath;
117
+ if (file) {
118
+ let t = findTracked(state, trackedKey(file));
119
+ if (t) return t.key;
120
+ if (underTrackedFolder(state.tracked, file)) return trackedKey(file);
121
+ }
122
+ } else if (selected) {
123
+ let loadedId = loadedIdForPath(state, trackedPath(selected));
124
+ if (loadedId) return loadedId;
125
+ let t = findTracked(state, selected);
126
+ if (t) return t.key;
127
+ if (!trackedFresh && (!state.tracked || underTrackedFolder(state.tracked, trackedPath(selected)))) return selected;
128
+ }
129
+ return state.agentOrder[0] ?? state.tracked?.stopped[0]?.key ?? null;
130
+ }
131
+
132
+ // src/main/tui/state/transcript.ts
133
+ var MAX_TRANSCRIPT_ITEMS = 2e3, { parseLoopToDisplay } = cjs(loop_parser_exports), localCounter = 0;
134
+ function localId(prefix = "l") {
135
+ return localCounter += 1, `${prefix}:${Date.now().toString(36)}:${localCounter}`;
136
+ }
137
+ function emptyTranscript() {
138
+ return { items: [], loaded: !1, loading: !1, total: 0, oldestOffset: 0, live: !1 };
139
+ }
140
+ function isAsyncInput(input) {
141
+ if (!input || typeof input != "object" || Array.isArray(input)) return !1;
142
+ let flag = input._async;
143
+ return flag === !0 || flag === "true";
144
+ }
145
+ function isTaskRef(text) {
146
+ if (!text || !text.startsWith("{") || !text.includes("task_id")) return !1;
147
+ try {
148
+ let value = JSON.parse(text);
149
+ return typeof value.task_id == "string" && (value.status === "running" || value.status === "pending_approval");
150
+ } catch {
151
+ return !1;
152
+ }
153
+ }
154
+ function askQuestion(input) {
155
+ let q = input && typeof input == "object" ? input.question : void 0;
156
+ return typeof q == "string" ? q : "";
157
+ }
158
+ function historyToItems(entries) {
159
+ let items = [], toolsById = /* @__PURE__ */ new Map();
160
+ for (let entry of parseLoopToDisplay(entries)) {
161
+ let meta = entry.metadata ?? {}, base = { id: `h:${entry.id}`, at: entry.timestamp, seq: typeof meta.seq == "number" ? meta.seq : void 0 };
162
+ switch (entry.type) {
163
+ case "user":
164
+ items.push({ ...base, kind: "user", text: entry.content, origin: "owner" });
165
+ break;
166
+ case "trigger":
167
+ items.push({ ...base, kind: "user", text: entry.content, origin: "runtime" });
168
+ break;
169
+ case "context":
170
+ meta.category === "loop" && typeof meta.fromLoop == "string" ? items.push({ ...base, kind: "user", text: entry.content, origin: "loop", from: meta.fromLoop }) : items.push({ ...base, kind: "context", category: String(meta.category ?? "context"), text: entry.content });
171
+ break;
172
+ case "compaction":
173
+ items.push({ ...base, kind: "context", category: "compaction", text: entry.content });
174
+ break;
175
+ case "error":
176
+ items.push({ ...base, kind: "error", text: entry.content });
177
+ break;
178
+ case "text":
179
+ items.push({ ...base, kind: "assistant", text: entry.content, streaming: !1, model: typeof meta.model == "string" ? meta.model : void 0 });
180
+ break;
181
+ case "thinking":
182
+ items.push({ ...base, kind: "thinking", text: entry.content, streaming: !1 });
183
+ break;
184
+ case "tool_call": {
185
+ let tool = {
186
+ ...base,
187
+ kind: "tool",
188
+ toolUseId: typeof meta.tool_id == "string" ? meta.tool_id : void 0,
189
+ name: typeof meta.name == "string" ? meta.name : "tool",
190
+ input: meta.input,
191
+ status: "running",
192
+ ...isAsyncInput(meta.input) ? { async: !0 } : {}
193
+ };
194
+ tool.toolUseId && toolsById.set(tool.toolUseId, tool), items.push(tool);
195
+ break;
196
+ }
197
+ case "tool_result": {
198
+ let useId = typeof meta.tool_use_id == "string" ? meta.tool_use_id : void 0, call = useId ? toolsById.get(useId) : void 0, status = meta.isError ? "error" : "ok";
199
+ call ? (call.status = status, call.result = entry.content, call.completedAt = entry.timestamp, !meta.isError && isTaskRef(entry.content) && (call.async = !0, call.taskRef = entry.content)) : items.push({ ...base, kind: "tool", toolUseId: useId, name: typeof meta.name == "string" ? meta.name : "tool", input: void 0, status, result: entry.content, completedAt: entry.timestamp });
200
+ break;
201
+ }
202
+ }
203
+ }
204
+ return items;
205
+ }
206
+ function mergeHistory(existing, incoming) {
207
+ let finished = /* @__PURE__ */ new Map();
208
+ for (let item of existing)
209
+ item.kind === "tool" && item.toolUseId && item.status !== "running" && item.result !== void 0 && finished.set(item.toolUseId, item);
210
+ let history = incoming.map((item) => {
211
+ if (item.kind !== "tool" || item.taskRef === void 0 || !item.toolUseId) return item;
212
+ let live = finished.get(item.toolUseId);
213
+ return !live || live.result === item.taskRef ? item : { ...item, status: live.status, result: live.result, completedAt: live.completedAt };
214
+ }), historyTools = /* @__PURE__ */ new Set(), historyTexts = /* @__PURE__ */ new Map(), countText = (key) => historyTexts.set(key, (historyTexts.get(key) ?? 0) + 1);
215
+ for (let item of history)
216
+ item.kind === "tool" && item.toolUseId && historyTools.add(item.toolUseId), (item.kind === "user" || item.kind === "assistant" || item.kind === "thinking") && countText(`${item.kind}:${item.text.trim()}`), item.kind === "tool" && item.name === "ask" && countText(`ask:${askQuestion(item.input).trim()}`);
217
+ let consume = (key) => {
218
+ let n = historyTexts.get(key) ?? 0;
219
+ return n <= 0 ? !1 : (historyTexts.set(key, n - 1), !0);
220
+ }, keep = existing.filter((item) => {
221
+ if (!item.local) return !1;
222
+ switch (item.kind) {
223
+ case "tool":
224
+ return !(item.toolUseId && historyTools.has(item.toolUseId));
225
+ case "user":
226
+ case "assistant":
227
+ case "thinking":
228
+ return !consume(`${item.kind}:${item.text.trim()}`);
229
+ case "context":
230
+ return !1;
231
+ case "ask":
232
+ return !consume(`ask:${item.question.trim()}`);
233
+ default:
234
+ return !0;
235
+ }
236
+ });
237
+ return sortByTime([...history, ...keep]);
238
+ }
239
+ function prependHistory(existing, older) {
240
+ let ids = new Set(existing.map((item) => item.id)), orphans = /* @__PURE__ */ new Map();
241
+ for (let item of existing)
242
+ item.kind === "tool" && !item.local && item.toolUseId && item.status !== "running" && orphans.set(item.toolUseId, item);
243
+ let merged = /* @__PURE__ */ new Set();
244
+ return [...older.filter((item) => !ids.has(item.id)).map((item) => {
245
+ if (item.kind !== "tool" || item.status !== "running" || !item.toolUseId) return item;
246
+ let result = orphans.get(item.toolUseId);
247
+ return result ? (merged.add(result), { ...item, status: result.status, result: result.result, completedAt: result.completedAt }) : item;
248
+ }), ...merged.size ? existing.filter((item) => !merged.has(item)) : existing];
249
+ }
250
+ function sortByTime(items) {
251
+ return items.map((item, index) => ({ item, index })).sort((a, b) => a.item.at - b.item.at || a.index - b.index).map((entry) => entry.item);
252
+ }
253
+ function finalizeStreaming(items) {
254
+ let changed = !1, next = items.map((item) => (item.kind === "assistant" || item.kind === "thinking") && item.streaming ? (changed = !0, { ...item, streaming: !1 }) : item);
255
+ return changed ? next : items;
256
+ }
257
+ function cap(items) {
258
+ return items.length > MAX_TRANSCRIPT_ITEMS ? items.slice(items.length - MAX_TRANSCRIPT_ITEMS) : items;
259
+ }
260
+ function str(value) {
261
+ return typeof value == "string" ? value : void 0;
262
+ }
263
+ function resultText(value) {
264
+ if (typeof value == "string") return value;
265
+ if (value && typeof value == "object" && "content" in value) {
266
+ let content = value.content;
267
+ return typeof content == "string" ? content : content === void 0 ? void 0 : JSON.stringify(content);
268
+ }
269
+ return value === void 0 ? void 0 : JSON.stringify(value);
270
+ }
271
+ function applyEventToItems(items, event) {
272
+ let p = event.payload ?? {}, at = event.timestamp || Date.now();
273
+ switch (event.event_type) {
274
+ case "turn.delta": {
275
+ let kind = p.kind === "thinking" ? "thinking" : "assistant", text = str(p.text) ?? "";
276
+ if (!text) return items;
277
+ let last = items[items.length - 1];
278
+ if (last && last.kind === kind && last.streaming) {
279
+ let next = items.slice();
280
+ return next[next.length - 1] = { ...last, text: last.text + text }, next;
281
+ }
282
+ let closed = finalizeStreaming(items), item = kind === "thinking" ? { id: localId(), at, local: !0, kind: "thinking", text, streaming: !0 } : { id: localId(), at, local: !0, kind: "assistant", text, streaming: !0 };
283
+ return cap([...closed, item]);
284
+ }
285
+ case "tool.started": {
286
+ let toolUseId = str(p.id);
287
+ if (toolUseId && items.some((item) => item.kind === "tool" && item.toolUseId === toolUseId)) return items;
288
+ let tool = { id: localId(), at, local: !0, kind: "tool", toolUseId, name: str(p.name) ?? "tool", input: p.input, status: "running" };
289
+ if (tool.name === "ask") {
290
+ let question = askQuestion(p.input).trim(), card = -1;
291
+ for (let i = items.length - 1; i >= 0; i--) {
292
+ let item = items[i];
293
+ if (item.kind === "ask" && item.question.trim() === question) {
294
+ card = i;
295
+ break;
296
+ }
297
+ }
298
+ if (card >= 0) {
299
+ let next = items.slice();
300
+ return next[card] = { ...tool, id: items[card].id, at: items[card].at }, next;
301
+ }
302
+ }
303
+ return cap([...finalizeStreaming(items), tool]);
304
+ }
305
+ case "tool.completed":
306
+ case "tool.failed": {
307
+ let toolUseId = str(p.id), name = str(p.name), index = -1;
308
+ for (let i = items.length - 1; i >= 0; i--) {
309
+ let item = items[i];
310
+ if (item.kind === "tool" && (toolUseId ? item.toolUseId === toolUseId : item.status === "running" && item.name === name)) {
311
+ index = i;
312
+ break;
313
+ }
314
+ }
315
+ let patch = { status: event.event_type === "tool.failed" || p.isError === !0 ? "error" : "ok", result: resultText(p.result), completedAt: at };
316
+ if (index < 0)
317
+ return cap([...items, { id: localId(), at, local: !0, kind: "tool", toolUseId, name: name ?? "tool", input: p.input, ...patch }]);
318
+ let next = items.slice();
319
+ return next[index] = { ...next[index], ...patch }, next;
320
+ }
321
+ case "turn.completed": {
322
+ let closed = finalizeStreaming(items), content = str(p.content)?.trim();
323
+ if (!content) return closed;
324
+ let lastUser = -1;
325
+ for (let i = closed.length - 1; i >= 0; i--) if (closed[i].kind === "user") {
326
+ lastUser = i;
327
+ break;
328
+ }
329
+ return closed.slice(lastUser + 1).some((item) => item.kind === "assistant") ? closed : cap([...closed, { id: localId(), at, local: !0, kind: "assistant", text: content, streaming: !1 }]);
330
+ }
331
+ case "hil.requested": {
332
+ let taskId = str(p.task_id) ?? str(p.request_id);
333
+ return !taskId || items.some((item) => item.kind === "hil" && item.taskId === taskId) ? items : cap([...finalizeStreaming(items), { id: localId(), at, local: !0, kind: "hil", taskId, tool: str(p.tool) ?? "tool", input: p.input, reason: str(p.reason), status: "pending" }]);
334
+ }
335
+ case "hil.resolved": {
336
+ let taskId = str(p.task_id) ?? str(p.request_id), index = items.findIndex((item) => item.kind === "hil" && item.taskId === taskId), status = p.approved === !0 ? "approved" : "denied";
337
+ if (index < 0)
338
+ return cap([...items, { id: localId(), at, local: !0, kind: "notice", level: "info", event: event.event_type, text: `Approval ${taskId ?? ""} ${status}${p.timed_out ? " (timed out)" : ""}` }]);
339
+ let next = items.slice();
340
+ return next[index] = { ...next[index], status, feedback: str(p.feedback) }, next;
341
+ }
342
+ case "ask.requested": {
343
+ let requestId = str(p.request_id);
344
+ return !requestId || items.some((item) => item.kind === "ask" && item.requestId === requestId) ? items : cap([...finalizeStreaming(items), { id: localId(), at, local: !0, kind: "ask", requestId, question: str(p.question) ?? "", status: "pending" }]);
345
+ }
346
+ case "ask.resolved": {
347
+ let requestId = str(p.request_id), index = items.findIndex((item) => item.kind === "ask" && item.requestId === requestId);
348
+ if (index < 0) return items;
349
+ let next = items.slice();
350
+ return next[index] = { ...next[index], status: "answered", answer: str(p.preview) }, next;
351
+ }
352
+ case "agent.error": {
353
+ let text = describeAgentError(p);
354
+ return cap([...finalizeStreaming(items), { id: localId(), at, local: !0, kind: "error", text }]);
355
+ }
356
+ default: {
357
+ let notice = noticeFor(event);
358
+ return notice ? cap([...items, { id: localId(), at, local: !0, kind: "notice", event: event.event_type, ...notice }]) : items;
359
+ }
360
+ }
361
+ }
362
+ function noticeFor(event) {
363
+ let p = event.payload ?? {};
364
+ switch (event.event_type) {
365
+ case "agent.state.changed": {
366
+ let state = str(p.state);
367
+ return state === "suspended" || state === "error" || state === "stopped" || state === "off" || state === "hibernate" ? { text: `State \u2192 ${state}`, level: state === "error" ? "warn" : "info" } : null;
368
+ }
369
+ case "loop.compacted":
370
+ return { text: `Compacted${p.reason ? ` (${String(p.reason)})` : ""}${typeof p.new_token_count == "number" ? ` \u2192 ${p.new_token_count} tokens` : ""}`, level: "info" };
371
+ case "loop.compaction_failed":
372
+ return { text: `Compaction failed${p.reason ? `: ${String(p.reason)}` : ""} \u2014 history kept`, level: "warn" };
373
+ case "loop.compaction_superseded":
374
+ return { text: "Compaction superseded by a newer one", level: "info" };
375
+ case "loop.cleared":
376
+ return { text: `Loop ${p.method === "replace" ? "rewritten" : "cleared"}`, level: "info" };
377
+ case "loop.recovered":
378
+ return { text: `Recovered: ${String(p.reason ?? "checkpoint")}`, level: "warn" };
379
+ case "suspend.requested":
380
+ return { text: `Suspended${p.reason ? `: ${String(p.reason)}` : ""} \u2014 resume or shut down`, level: "warn" };
381
+ case "suspend.resolved":
382
+ return { text: p.resumed ? "Resumed" : `Shut down${p.timed_out ? " (suspend timed out)" : ""}`, level: "info" };
383
+ case "provider.retry_scheduled":
384
+ return { text: `Provider error \u2014 retrying${typeof p.delay_ms == "number" ? ` in ${Math.round(p.delay_ms / 1e3)}s` : ""}`, level: "warn" };
385
+ case "provider.retry_cancelled":
386
+ return { text: "Provider retry cancelled", level: "info" };
387
+ case "llm.failed":
388
+ return { text: `Model call failed${p.model ? ` (${String(p.model)})` : ""}`, level: "warn" };
389
+ case "error.recovery_suppressed":
390
+ return { text: "Error recovery suppressed \u2014 triggers are being dropped", level: "warn" };
391
+ default:
392
+ return null;
393
+ }
394
+ }
395
+ function describeAgentError(p) {
396
+ let inner = p.event, detail = inner?.payload?.error ?? inner?.payload?.message;
397
+ return typeof detail == "string" && detail ? detail : "Agent error";
398
+ }
399
+ function summarizeEvent(event) {
400
+ let p = event.payload ?? {};
401
+ switch (event.event_type) {
402
+ case "tool.started":
403
+ case "tool.completed":
404
+ case "tool.failed":
405
+ return `${event.event_type.slice(5)} ${str(p.name) ?? ""}`.trim();
406
+ case "agent.state.changed":
407
+ return `state ${str(p.state) ?? "?"}`;
408
+ case "llm.completed":
409
+ return `${str(p.model) ?? "model"} in ${p.input_tokens ?? "?"} out ${p.output_tokens ?? "?"}`;
410
+ case "turn.completed":
411
+ return "turn completed";
412
+ case "hil.requested":
413
+ return `approval requested: ${str(p.tool) ?? ""}`;
414
+ case "ask.requested":
415
+ return `ask: ${(str(p.question) ?? "").slice(0, 60)}`;
416
+ case "message.received":
417
+ return `inbox from ${str(p.from) ?? "?"}`;
418
+ case "message.sent":
419
+ return "message sent";
420
+ case "timer.fired":
421
+ return `timer ${String(p.timer_id ?? "")} fired`;
422
+ case "trigger.fired":
423
+ return `trigger ${str(p.trigger_type) ?? ""}`;
424
+ case "config.changed":
425
+ return `config changed: ${Array.isArray(p.changed_keys) ? p.changed_keys.join(", ") : ""}`;
426
+ case "file.written":
427
+ return `wrote ${str(p.path) ?? ""}`;
428
+ case "file.deleted":
429
+ return `deleted ${str(p.path) ?? ""}`;
430
+ default:
431
+ return noticeFor(event)?.text ?? event.event_type;
432
+ }
433
+ }
434
+
435
+ // src/main/tui/state/types.ts
436
+ function transcriptKey(agentId, loop) {
437
+ return `${agentId}\0${loop}`;
438
+ }
439
+
440
+ // src/main/tui/state/reducer.ts
441
+ var MAX_ACTIVITY = 500, MAX_LAST_EVENTS = 5e3;
442
+ function initialState(daemonUrl, activeView = "fleet") {
443
+ return {
444
+ daemonUrl,
445
+ connection: { state: "idle", attempt: 0 },
446
+ daemonReachable: null,
447
+ identity: null,
448
+ auth: null,
449
+ web: null,
450
+ tracked: null,
451
+ agents: {},
452
+ agentOrder: [],
453
+ selectedAgentId: null,
454
+ selectedLoop: {},
455
+ transcripts: {},
456
+ activeView,
457
+ // Launching into Chat starts in the composer.
458
+ focus: activeView === "chat" ? "input" : "main",
459
+ overlays: [],
460
+ toasts: [],
461
+ activity: [],
462
+ lastEvents: [],
463
+ viewState: {}
464
+ };
465
+ }
466
+ function newAgent(summary) {
467
+ return {
468
+ summary,
469
+ pendingTasks: [],
470
+ pendingAsks: [],
471
+ tokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
472
+ unreadInbox: 0
473
+ };
474
+ }
475
+ function patchAgent(state, agentId, patch) {
476
+ let agent = state.agents[agentId];
477
+ if (!agent) return state;
478
+ let next = patch(agent);
479
+ return next === agent ? state : { ...state, agents: { ...state.agents, [agentId]: next } };
480
+ }
481
+ function patchTranscript(state, key, patch) {
482
+ let current = state.transcripts[key] ?? emptyTranscript(), next = patch(current);
483
+ return next === current ? state : { ...state, transcripts: { ...state.transcripts, [key]: next } };
484
+ }
485
+ var RUNNING_STATES = /* @__PURE__ */ new Set(["thinking", "tool_use", "awaiting_approval", "awaiting_ask"]);
486
+ function isBusyState(state) {
487
+ return !!state && RUNNING_STATES.has(state);
488
+ }
489
+ function tuiReducer(state, action) {
490
+ switch (action.type) {
491
+ case "connection":
492
+ return { ...state, connection: action.info, daemonReachable: action.info.state === "open" ? !0 : state.daemonReachable };
493
+ case "daemon/switch":
494
+ return {
495
+ ...initialState(action.url, state.activeView),
496
+ focus: state.focus,
497
+ overlays: state.overlays,
498
+ toasts: state.toasts,
499
+ viewState: state.viewState
500
+ };
501
+ case "identity/set":
502
+ return { ...state, identity: action.identity };
503
+ case "auth/set":
504
+ return { ...state, auth: action.auth };
505
+ case "web/set":
506
+ return { ...state, web: action.web };
507
+ case "daemon/reachable":
508
+ return state.daemonReachable === action.reachable ? state : { ...state, daemonReachable: action.reachable };
509
+ case "agents/loaded": {
510
+ let agents = {};
511
+ for (let summary of action.agents) {
512
+ let existing = state.agents[summary.id];
513
+ agents[summary.id] = existing ? { ...existing, summary } : newAgent(summary);
514
+ }
515
+ let agentOrder = action.agents.map((agent) => agent.id), previous = Object.fromEntries(Object.entries(state.agents).map(([id, a]) => [id, a.summary])), tracked = state.tracked ? pruneLoaded(state.tracked, action.agents) : null, next = { ...state, agents, agentOrder, tracked };
516
+ return { ...next, selectedAgentId: reconcileSelection(next, previous) };
517
+ }
518
+ case "tracked/loaded": {
519
+ let summaries = state.agentOrder.map((id) => state.agents[id]?.summary).filter(Boolean), next = { ...state, tracked: buildTracked(action.list, summaries, state.tracked) };
520
+ return { ...next, selectedAgentId: reconcileSelection(next, {}, !0) };
521
+ }
522
+ case "tracked/error":
523
+ return state.tracked ? { ...state, tracked: { ...state.tracked, error: action.error } } : state;
524
+ case "tracked/file-error": {
525
+ let tracked = state.tracked;
526
+ if (!tracked) return state;
527
+ let errors = { ...tracked.errors };
528
+ return action.error === void 0 ? delete errors[action.filePath] : errors[action.filePath] = action.error, { ...state, tracked: { ...tracked, errors } };
529
+ }
530
+ case "tracked/busy": {
531
+ let tracked = state.tracked;
532
+ if (!tracked) return state;
533
+ let busy = { ...tracked.busy };
534
+ return action.busy === void 0 ? delete busy[action.filePath] : busy[action.filePath] = action.busy, { ...state, tracked: { ...tracked, busy } };
535
+ }
536
+ case "agent/status":
537
+ return patchAgent(state, action.agentId, (agent) => ({
538
+ ...agent,
539
+ status: action.status,
540
+ executorState: action.status.runtimeState,
541
+ error: void 0
542
+ }));
543
+ case "agent/config":
544
+ return patchAgent(state, action.agentId, (agent) => ({ ...agent, config: action.config }));
545
+ case "agent/error":
546
+ return patchAgent(state, action.agentId, (agent) => ({ ...agent, error: action.error }));
547
+ case "agent/removed": {
548
+ if (!state.agents[action.agentId]) return state;
549
+ let agents = { ...state.agents };
550
+ delete agents[action.agentId];
551
+ let agentOrder = state.agentOrder.filter((id) => id !== action.agentId);
552
+ return {
553
+ ...state,
554
+ agents,
555
+ agentOrder,
556
+ selectedAgentId: state.selectedAgentId === action.agentId ? agentOrder[0] ?? state.tracked?.stopped[0]?.key ?? null : state.selectedAgentId
557
+ };
558
+ }
559
+ case "loops/loaded": {
560
+ let next = patchAgent(state, action.agentId, (agent) => {
561
+ let previous = new Map((agent.loops ?? []).map((loop) => [loop.info.name, loop]));
562
+ return {
563
+ ...agent,
564
+ loopsError: void 0,
565
+ loops: action.loops.map((info) => ({ info, executorState: previous.get(info.name)?.executorState }))
566
+ };
567
+ }), selected = next.selectedLoop[action.agentId];
568
+ if (selected && !action.loops.some((loop) => loop.name === selected)) {
569
+ let selectedLoop = { ...next.selectedLoop };
570
+ return delete selectedLoop[action.agentId], { ...next, selectedLoop };
571
+ }
572
+ return next;
573
+ }
574
+ case "loops/error":
575
+ return patchAgent(state, action.agentId, (agent) => ({ ...agent, loopsError: action.error }));
576
+ case "hil/loaded":
577
+ return patchAgent(state, action.agentId, (agent) => ({
578
+ ...agent,
579
+ pendingTasks: action.tasks.filter((task) => task.status === "pending_approval"),
580
+ pendingAsks: action.asks
581
+ }));
582
+ case "select/agent":
583
+ return state.selectedAgentId === action.agentId ? state : { ...state, selectedAgentId: action.agentId };
584
+ case "select/loop": {
585
+ let selectedLoop = { ...state.selectedLoop };
586
+ return action.loop === MAIN_LOOP ? delete selectedLoop[action.agentId] : selectedLoop[action.agentId] = action.loop, { ...state, selectedLoop };
587
+ }
588
+ case "view/set":
589
+ return state.activeView === action.view ? state : { ...state, activeView: action.view };
590
+ case "focus/set":
591
+ return state.focus === action.focus ? state : { ...state, focus: action.focus };
592
+ case "overlay/push":
593
+ return { ...state, overlays: [...state.overlays.filter((o) => o.id !== action.overlay.id), action.overlay] };
594
+ case "overlay/pop": {
595
+ if (state.overlays.length === 0) return state;
596
+ let overlays = action.id ? state.overlays.filter((o) => o.id !== action.id) : state.overlays.slice(0, -1);
597
+ return { ...state, overlays };
598
+ }
599
+ case "toast/add":
600
+ return { ...state, toasts: [...state.toasts.slice(-4), action.toast] };
601
+ case "toast/dismiss":
602
+ return { ...state, toasts: state.toasts.filter((t) => t.id !== action.id) };
603
+ case "transcript/loading":
604
+ return patchTranscript(state, action.key, (t) => ({ ...t, loading: !0, error: void 0 }));
605
+ case "transcript/history":
606
+ return patchTranscript(state, action.key, (t) => {
607
+ let page = historyToItems(action.entries);
608
+ if (action.mode === "prepend")
609
+ return { ...t, loading: !1, loaded: !0, total: action.total, oldestOffset: action.offset, items: prependHistory(t.items, page) };
610
+ let firstSeq = action.entries[0]?.seq, older = firstSeq === void 0 ? [] : t.items.filter((item) => !item.local && item.seq !== void 0 && item.seq < firstSeq), oldestOffset = older.length > 0 ? Math.min(t.oldestOffset, action.offset) : action.offset;
611
+ return {
612
+ ...t,
613
+ loading: !1,
614
+ loaded: !0,
615
+ error: void 0,
616
+ total: action.total,
617
+ oldestOffset,
618
+ live: !1,
619
+ items: [...older, ...mergeHistory(t.items, page)]
620
+ };
621
+ });
622
+ case "transcript/error":
623
+ return patchTranscript(state, action.key, (t) => ({ ...t, loading: !1, error: action.error }));
624
+ case "transcript/append":
625
+ return patchTranscript(state, action.key, (t) => ({ ...t, items: [...t.items, action.item] }));
626
+ case "transcript/update":
627
+ return patchTranscript(state, action.key, (t) => {
628
+ let index = t.items.findIndex((item) => item.id === action.id);
629
+ if (index < 0) return t;
630
+ let items = t.items.slice();
631
+ return items[index] = { ...items[index], ...action.patch }, { ...t, items };
632
+ });
633
+ case "transcript/reset":
634
+ return patchTranscript(state, action.key, () => ({ ...emptyTranscript(), loaded: !0 }));
635
+ case "transcript/idle":
636
+ return patchTranscript(state, action.key, endLive);
637
+ case "event":
638
+ return applyEvent(state, action.frame.event);
639
+ case "events":
640
+ return action.frames.reduce((next, frame) => applyEvent(next, frame.event), state);
641
+ case "viewState/set":
642
+ return { ...state, viewState: { ...state.viewState, [action.view]: action.value } };
643
+ default:
644
+ return state;
645
+ }
646
+ }
647
+ function eventLoop(event) {
648
+ return typeof event.loop == "string" && event.loop ? event.loop : MAIN_LOOP;
649
+ }
650
+ var TRANSCRIPT_EVENTS = /* @__PURE__ */ new Set([
651
+ "turn.delta",
652
+ "tool.started",
653
+ "tool.completed",
654
+ "tool.failed",
655
+ "turn.completed",
656
+ "hil.requested",
657
+ "hil.resolved",
658
+ "ask.requested",
659
+ "ask.resolved",
660
+ "agent.error",
661
+ "agent.state.changed",
662
+ "loop.compacted",
663
+ "loop.compaction_failed",
664
+ "loop.compaction_superseded",
665
+ "loop.cleared",
666
+ "loop.recovered",
667
+ "suspend.requested",
668
+ "suspend.resolved",
669
+ "provider.retry_scheduled",
670
+ "provider.retry_cancelled",
671
+ "llm.failed",
672
+ "error.recovery_suppressed"
673
+ ]);
674
+ function applyEvent(state, event) {
675
+ let agentId = event.agent_id ?? null, loop = eventLoop(event), next = {
676
+ ...state,
677
+ activity: pushBounded(state.activity, {
678
+ id: localId("a"),
679
+ at: event.timestamp || Date.now(),
680
+ agentId,
681
+ loop,
682
+ type: event.event_type,
683
+ summary: summarizeEvent(event)
684
+ }, MAX_ACTIVITY),
685
+ lastEvents: pushBounded(state.lastEvents, event, MAX_LAST_EVENTS)
686
+ };
687
+ if (!agentId || !next.agents[agentId]) return next;
688
+ let p = event.payload ?? {};
689
+ switch (event.event_type) {
690
+ case "agent.state.changed": {
691
+ let executorState = typeof p.state == "string" ? p.state : void 0;
692
+ loop === MAIN_LOOP ? next = patchAgent(next, agentId, (agent) => ({ ...agent, executorState })) : next = patchLoop(next, agentId, loop, (info) => ({
693
+ ...info,
694
+ executorState,
695
+ info: { ...info.info, status: isBusyState(executorState) ? "running" : "idle" }
696
+ }));
697
+ break;
698
+ }
699
+ case "turn.completed":
700
+ loop !== MAIN_LOOP && (next = patchLoop(next, agentId, loop, (l) => ({ ...l, info: { ...l.info, status: "idle" } })));
701
+ break;
702
+ case "llm.completed":
703
+ next = patchAgent(next, agentId, (agent) => ({
704
+ ...agent,
705
+ lastModel: typeof p.model == "string" ? p.model : agent.lastModel,
706
+ tokens: {
707
+ input: agent.tokens.input + num(p.input_tokens),
708
+ output: agent.tokens.output + num(p.output_tokens),
709
+ cacheRead: agent.tokens.cacheRead + num(p.cache_read_tokens),
710
+ cacheWrite: agent.tokens.cacheWrite + num(p.cache_write_tokens)
711
+ }
712
+ }));
713
+ break;
714
+ case "hil.requested": {
715
+ let taskId = typeof p.task_id == "string" ? p.task_id : void 0;
716
+ taskId && (next = patchAgent(next, agentId, (agent) => agent.pendingTasks.some((t) => t.id === taskId) ? agent : {
717
+ ...agent,
718
+ pendingTasks: [...agent.pendingTasks, {
719
+ id: taskId,
720
+ tool: typeof p.tool == "string" ? p.tool : "tool",
721
+ args: JSON.stringify(p.input ?? {}),
722
+ status: "pending_approval",
723
+ created_at: event.timestamp,
724
+ origin: loop === MAIN_LOOP ? void 0 : `loop:${loop}`,
725
+ // "Always approve" is offered only when the daemon says so (never for protection overrides).
726
+ ...typeof p.can_always_approve == "boolean" ? { canAlwaysApprove: p.can_always_approve } : {},
727
+ ...typeof p.always_approve_blocked_reason == "string" ? { alwaysApproveBlockedReason: p.always_approve_blocked_reason } : {}
728
+ }]
729
+ }));
730
+ break;
731
+ }
732
+ case "hil.resolved": {
733
+ let taskId = typeof p.task_id == "string" ? p.task_id : p.request_id;
734
+ next = patchAgent(next, agentId, (agent) => ({ ...agent, pendingTasks: agent.pendingTasks.filter((t) => t.id !== taskId) }));
735
+ break;
736
+ }
737
+ // Ask ids are per executor (main and an inner loop can both hold ask_1),
738
+ // so an ask is identified by (loop, requestId).
739
+ case "ask.requested": {
740
+ let requestId = typeof p.request_id == "string" ? p.request_id : void 0;
741
+ requestId && (next = patchAgent(next, agentId, (agent) => agent.pendingAsks.some((a) => sameAsk(a, loop, requestId)) ? agent : {
742
+ ...agent,
743
+ pendingAsks: [...agent.pendingAsks, { requestId, question: typeof p.question == "string" ? p.question : "", loop }]
744
+ }));
745
+ break;
746
+ }
747
+ case "ask.resolved":
748
+ next = patchAgent(next, agentId, (agent) => ({ ...agent, pendingAsks: agent.pendingAsks.filter((a) => !sameAsk(a, loop, p.request_id)) }));
749
+ break;
750
+ case "message.received":
751
+ next = patchAgent(next, agentId, (agent) => ({ ...agent, unreadInbox: agent.unreadInbox + 1 }));
752
+ break;
753
+ }
754
+ if (TRANSCRIPT_EVENTS.has(event.event_type)) {
755
+ let key = transcriptKey(agentId, loop);
756
+ next = patchTranscript(next, key, (t) => {
757
+ let items = applyEventToItems(t.items, event);
758
+ if (event.event_type === "agent.state.changed" && turnOver(p.state)) return endLive(items === t.items ? t : { ...t, items });
759
+ let live = event.event_type === "turn.completed" || event.event_type === "agent.error" ? !1 : event.event_type === "turn.delta" || event.event_type === "tool.started" ? !0 : t.live;
760
+ return items === t.items && live === t.live ? t : { ...t, items, live };
761
+ });
762
+ }
763
+ return next;
764
+ }
765
+ function turnOver(value) {
766
+ return typeof value == "string" && !RUNNING_STATES.has(value) && value !== "suspended";
767
+ }
768
+ function endLive(t) {
769
+ let items = finalizeStreaming(t.items);
770
+ return !t.live && items === t.items ? t : { ...t, live: !1, items };
771
+ }
772
+ function sameAsk(ask, loop, requestId) {
773
+ return ask.requestId === requestId && (ask.loop ?? MAIN_LOOP) === loop;
774
+ }
775
+ function patchLoop(state, agentId, loop, patch) {
776
+ return patchAgent(state, agentId, (agent) => {
777
+ if (!agent.loops) return agent;
778
+ let index = agent.loops.findIndex((l) => l.info.name === loop);
779
+ if (index < 0) return agent;
780
+ let loops = agent.loops.slice();
781
+ return loops[index] = patch(loops[index]), { ...agent, loops };
782
+ });
783
+ }
784
+ function pushBounded(list, item, max) {
785
+ let next = list.length >= max ? list.slice(list.length - max + 1) : list.slice();
786
+ return next.push(item), next;
787
+ }
788
+ function num(value) {
789
+ return typeof value == "number" && Number.isFinite(value) ? value : 0;
790
+ }
791
+
792
+ // src/main/tui/web/model.ts
793
+ var isRecord = (v) => typeof v == "object" && v !== null && !Array.isArray(v);
794
+ function parseServer(raw) {
795
+ if (!isRecord(raw) || typeof raw.running != "boolean") return null;
796
+ let port = typeof raw.port == "number" && Number.isFinite(raw.port) ? raw.port : 7295;
797
+ return { running: raw.running, port, host: typeof raw.host == "string" && raw.host ? raw.host : "127.0.0.1" };
798
+ }
799
+ function parseMeshAgents(raw) {
800
+ let out = {};
801
+ if (!Array.isArray(raw)) return out;
802
+ for (let a of raw)
803
+ !isRecord(a) || typeof a.agentId != "string" || (out[a.agentId] = {
804
+ handle: typeof a.handle == "string" ? a.handle : void 0,
805
+ publicEnabled: a.publicEnabled === !0,
806
+ apiRoutes: typeof a.apiRouteCount == "number" ? a.apiRouteCount : 0,
807
+ sharedCount: typeof a.sharedCount == "number" ? a.sharedCount : 0,
808
+ ...typeof a.status == "string" && a.status.trim() ? { status: a.status.trim() } : {}
809
+ });
810
+ return out;
811
+ }
812
+ function parseLan(raw) {
813
+ let outer = isRecord(raw) ? raw.addresses : void 0;
814
+ return (Array.isArray(outer) ? outer : isRecord(outer) && Array.isArray(outer.addresses) ? outer.addresses : []).filter((a) => isRecord(a) && typeof a.address == "string" && a.family !== "IPv6" && !String(a.address).includes(":")).map((a) => String(a.address));
815
+ }
816
+ function bindsAll(host) {
817
+ return host === "0.0.0.0" || host === "::" || host === "";
818
+ }
819
+ function isLoopback(host) {
820
+ return host === "127.0.0.1" || host === "localhost" || host === "::1" || host.startsWith("127.");
821
+ }
822
+ function linkHost(serverHost, daemonUrl) {
823
+ let host = serverHost;
824
+ if (bindsAll(serverHost)) {
825
+ let daemonHost = "127.0.0.1";
826
+ try {
827
+ daemonHost = new URL(daemonUrl).hostname.replace(/^\[|\]$/g, "");
828
+ } catch {
829
+ }
830
+ host = isLoopback(daemonHost) ? "127.0.0.1" : daemonHost;
831
+ }
832
+ return host.includes(":") ? `[${host}]` : host;
833
+ }
834
+ function siteUrl(host, port, handle) {
835
+ return `http://${host}:${port}/agents/${encodeURIComponent(handle)}/`;
836
+ }
837
+ function siteOf(state, agentId) {
838
+ if (!agentId) return null;
839
+ let agent = state.agents[agentId];
840
+ if (!agent) return null;
841
+ let serving = agent.config?.serving, mesh = state.web?.agents[agentId], api = Array.isArray(serving?.api) ? serving.api : [], publicEnabled = mesh ? mesh.publicEnabled : serving?.public?.enabled === !0, apiRoutes = mesh ? mesh.apiRoutes : api.length, sharedCount = mesh ? mesh.sharedCount : serving?.shared?.enabled ? serving.shared.patterns?.length ?? 0 : 0;
842
+ if (!publicEnabled && apiRoutes === 0 && sharedCount === 0) return null;
843
+ let handle = agent.summary.handle || mesh?.handle || agent.config?.handle || agent.summary.name || agentId, server = state.web?.server ?? null, url = server?.running ? siteUrl(linkHost(server.host, state.daemonUrl), server.port, handle) : null, lanUrls = server?.running && bindsAll(server.host) ? (state.web?.lan ?? []).map((ip) => siteUrl(ip, server.port, handle)) : [];
844
+ return {
845
+ agentId,
846
+ handle,
847
+ publicEnabled,
848
+ index: serving?.public?.index || "index.html",
849
+ apiRoutes,
850
+ wsRoutes: api.filter((r) => r.method === "WS").length,
851
+ sharedCount,
852
+ server,
853
+ url,
854
+ lanUrls
855
+ };
856
+ }
857
+ function servedText(site) {
858
+ let parts = [];
859
+ return site.publicEnabled && parts.push(`public/ (${site.index})`), site.apiRoutes > 0 && parts.push(`${site.apiRoutes} API route${site.apiRoutes === 1 ? "" : "s"}${site.wsRoutes > 0 ? ` incl. ${site.wsRoutes} WS` : ""}`), site.sharedCount > 0 && parts.push(`${site.sharedCount} shared pattern${site.sharedCount === 1 ? "" : "s"}`), parts.join(" \xB7 ");
860
+ }
861
+ function siteKind(site) {
862
+ return site.publicEnabled ? "site" : site.apiRoutes > 0 ? "api" : "files";
863
+ }
864
+ function shortUrl(url) {
865
+ return url.replace(/^https?:\/\//, "");
866
+ }
867
+ var SERVER_STOPPED_TEXT = "web server stopped \u2014 start it";
868
+ function serverBadge(server) {
869
+ return server ? server.running ? { text: `web :${server.port}`, running: !0 } : { text: "web off", running: !1 } : null;
870
+ }
871
+ function serverText(server) {
872
+ return server ? server.running ? bindsAll(server.host) ? `running on all interfaces, port ${server.port} (LAN too)` : `running on ${server.host}:${server.port}${isLoopback(server.host) ? " (this machine only)" : ""}` : "stopped" : "unknown (the daemon does not report it)";
873
+ }
874
+
875
+ // src/main/tui/state/store.tsx
876
+ var import_jsx_runtime = __toESM(require_jsx_runtime(), 1), REFRESH_DEBOUNCE_MS = 120, WEB_EVENT_DEBOUNCE_MS = 900, WEB_POLL_MS = 2e4, TRACKED_POLL_MS = 15e3, FOLDER_OVERLAY = "fleet.track", PROMPT_PREFILL_KEY = "shell.prompt.prefill", CHAT_VIEW_ID = "chat";
877
+ function createTuiStore(options) {
878
+ let client = options.client, pageSize = options.pageSize ?? 100, state = initialState(client.baseUrl, options.initialView), listeners = /* @__PURE__ */ new Set(), confirmResolvers = /* @__PURE__ */ new Map(), toastTimers = /* @__PURE__ */ new Map(), debounced = /* @__PURE__ */ new Map(), stream = null, webTick = null, trackedTick = null, stopped = !1, needsResync = !1, getState = () => state, dispatch = (action) => {
879
+ let next = tuiReducer(state, action);
880
+ if (next !== state) {
881
+ state = next;
882
+ for (let listener of listeners) listener();
883
+ }
884
+ }, subscribe = (listener) => (listeners.add(listener), () => {
885
+ listeners.delete(listener);
886
+ }), debounce = (key, fn, ms = REFRESH_DEBOUNCE_MS) => {
887
+ let existing = debounced.get(key);
888
+ existing && clearTimeout(existing), debounced.set(key, setTimeout(() => {
889
+ debounced.delete(key), stopped || fn();
890
+ }, ms));
891
+ }, describe = (err) => err instanceof Error ? err.message : String(err), toast = (text, level = "info", ttlMs = level === "error" ? 8e3 : 4e3) => {
892
+ let id = localId("t");
893
+ dispatch({ type: "toast/add", toast: { id, level, text, at: Date.now(), ttlMs } }), ttlMs > 0 && toastTimers.set(id, setTimeout(() => {
894
+ toastTimers.delete(id), dispatch({ type: "toast/dismiss", id });
895
+ }, ttlMs));
896
+ }, run = async (label, fn) => {
897
+ try {
898
+ return await fn(client);
899
+ } catch (err) {
900
+ err instanceof DaemonError && err.unreachable && dispatch({ type: "daemon/reachable", reachable: !1 }), toast(`${label}: ${describe(err)}`, "error");
901
+ return;
902
+ }
903
+ }, selectedLoopOf = (agentId) => state.selectedLoop[agentId] ?? MAIN_LOOP, stale = (c) => c !== client, actions = {
904
+ async setDaemonUrl(url, token) {
905
+ let next = client.withBaseUrl(url, token);
906
+ if (next.baseUrl === client.baseUrl && token === void 0)
907
+ return toast(`Already connected to ${next.baseUrl}`, "info"), !0;
908
+ client.hasToken && !next.hasToken && toast(`Not sending this daemon's token to ${next.baseUrl}; use /url <url> --token <token> if it needs one`, "warn", 6e3), toast(`Checking ${next.baseUrl}\u2026`, "info", 2e3);
909
+ try {
910
+ await next.health();
911
+ } catch (err) {
912
+ return toast(`Not switching: ${next.baseUrl} is not answering (${describe(err)}). Still on ${client.baseUrl}.`, "error"), !1;
913
+ }
914
+ let previous = client.baseUrl;
915
+ stream?.close(), stream = null;
916
+ for (let timer of debounced.values()) clearTimeout(timer);
917
+ return debounced.clear(), client = next, dispatch({ type: "daemon/switch", url: next.baseUrl }), toast(`Switched from ${previous} to ${next.baseUrl} \u2014 agents on the old daemon keep running`, "success", 6e3), await start(), !0;
918
+ },
919
+ async refreshAgents() {
920
+ let c = client;
921
+ try {
922
+ let agents = await c.agents();
923
+ if (stale(c)) return;
924
+ dispatch({ type: "daemon/reachable", reachable: !0 }), dispatch({ type: "agents/loaded", agents }), await Promise.all(agents.map((agent) => actions.refreshAgent(agent.id)));
925
+ let selected = state.selectedAgentId;
926
+ selected && !isTrackedKey(selected) && await actions.ensureTranscript(selected, selectedLoopOf(selected));
927
+ } catch (err) {
928
+ if (stale(c)) return;
929
+ dispatch({ type: "daemon/reachable", reachable: !(err instanceof DaemonError && err.unreachable) }), toast(`Agents: ${describe(err)}`, "error");
930
+ }
931
+ },
932
+ async refreshAgent(agentId) {
933
+ let c = client;
934
+ await Promise.all([
935
+ c.status(agentId).then((status) => {
936
+ stale(c) || dispatch({ type: "agent/status", agentId, status });
937
+ }).catch((err) => {
938
+ stale(c) || dispatch({ type: "agent/error", agentId, error: describe(err) });
939
+ }),
940
+ actions.refreshLoops(agentId),
941
+ actions.refreshHil(agentId),
942
+ c.config(agentId).then((result) => {
943
+ stale(c) || dispatch({ type: "agent/config", agentId, config: result.config });
944
+ }).catch(() => {
945
+ })
946
+ ]);
947
+ },
948
+ async refreshLoops(agentId) {
949
+ let c = client;
950
+ try {
951
+ let result = await c.loops(agentId);
952
+ stale(c) || dispatch({ type: "loops/loaded", agentId, loops: result.loops });
953
+ } catch (err) {
954
+ stale(c) || dispatch({ type: "loops/error", agentId, error: describe(err) });
955
+ }
956
+ },
957
+ async refreshHil(agentId) {
958
+ let c = client;
959
+ try {
960
+ let [tasks, asks] = await Promise.all([
961
+ c.tasks(agentId, { status: "pending_approval" }),
962
+ c.asks(agentId)
963
+ ]);
964
+ if (stale(c)) return;
965
+ dispatch({ type: "hil/loaded", agentId, tasks: tasks.tasks, asks: asks.asks });
966
+ } catch {
967
+ }
968
+ },
969
+ async loadConfig(agentId) {
970
+ let c = client, result = await run("Config", (cl) => cl.config(agentId));
971
+ if (!stale(c))
972
+ return result && dispatch({ type: "agent/config", agentId, config: result.config }), result?.config;
973
+ },
974
+ async startAgent(agentId) {
975
+ let result = await run("Start", (c) => c.start(agentId));
976
+ result && toast(`Started ${agentLabel(agentId)}${result.startupTriggered ? " (startup turn running)" : ""}`, "success"), await actions.refreshAgent(agentId);
977
+ },
978
+ async stopAgent(agentId) {
979
+ await run("Stop", (c) => c.stop(agentId)) && toast(`Stopped ${agentLabel(agentId)}`, "success"), await actions.refreshAgents();
980
+ },
981
+ async interrupt(agentId, loop) {
982
+ let id = agentId ?? state.selectedAgentId;
983
+ if (!id) return;
984
+ let target = loop ?? selectedLoopOf(id), result = await run("Interrupt", (c) => c.interrupt(id, target));
985
+ if (!result) return;
986
+ let key = transcriptKey(id, target);
987
+ dispatch({ type: "transcript/idle", key }), result.interrupted === !1 ? toast(`Nothing running in ${target}`, "info", 2500) : dispatch({ type: "transcript/append", key, item: { id: localId(), at: Date.now(), local: !0, kind: "notice", level: "warn", text: "Turn interrupted by you \u2014 loop is idle" } }), debounce(`loops:${id}`, () => {
988
+ actions.refreshLoops(id);
989
+ });
990
+ },
991
+ async abort(agentId, loop) {
992
+ let id = agentId ?? state.selectedAgentId;
993
+ if (!id) return;
994
+ let target = loop ?? selectedLoopOf(id);
995
+ if (await run("Abort", (c) => c.abort(id, target))) {
996
+ let key = transcriptKey(id, target);
997
+ dispatch({ type: "transcript/idle", key }), dispatch({ type: "transcript/append", key, item: { id: localId(), at: Date.now(), local: !0, kind: "notice", level: "warn", text: "Turn aborted by you \u2014 loop stopped until the agent is reloaded" } });
998
+ }
999
+ },
1000
+ async setDisplayState(agentId, displayState) {
1001
+ await run("State", (c) => c.setState(agentId, displayState)) && toast(`${agentLabel(agentId)} \u2192 ${displayState}`, "success"), await actions.refreshAgent(agentId);
1002
+ },
1003
+ async loadAgentFile(filePath) {
1004
+ let ref = await run("Load", (c) => c.load(filePath));
1005
+ ref && (toast(`Loaded ${ref.config?.name ?? filePath}`, "success"), await actions.refreshAgents(), actions.selectAgent(ref.id));
1006
+ },
1007
+ async refreshTracked() {
1008
+ let c = client;
1009
+ try {
1010
+ let list = await c.trackedAgents();
1011
+ stale(c) || dispatch({ type: "tracked/loaded", list });
1012
+ } catch (err) {
1013
+ if (stale(c)) return;
1014
+ if (err instanceof DaemonError && (err.status === 404 || err.status === 503)) {
1015
+ state.tracked || dispatch({ type: "tracked/loaded", list: { maxDepth: 0, folders: [] } });
1016
+ return;
1017
+ }
1018
+ dispatch({ type: "tracked/error", error: describe(err) });
1019
+ }
1020
+ },
1021
+ async startTracked(key, options2 = {}) {
1022
+ let entry = findTracked(state, key);
1023
+ if (!entry) {
1024
+ let loadedId = isTrackedKey(key) ? loadedIdForPath(state, trackedPath(key)) : key;
1025
+ return loadedId && state.agents[loadedId] ? loadedId : (toast("That agent is no longer in a tracked folder (r refreshes)", "warn"), null);
1026
+ }
1027
+ let { agent, folder } = entry, filePath = agent.filePath;
1028
+ if (state.tracked?.busy[filePath]) return null;
1029
+ if (agent.status === "unreadable")
1030
+ return toast(`${agent.name}: ${agent.error ?? "not a readable .adf"}`, "error", 6e3), null;
1031
+ if (agent.status === "password_protected")
1032
+ return toast(`${agent.name}: its identity is password-protected. Load it with /load ${filePath} and unlock it`, "warn", 8e3), null;
1033
+ let review = () => (toast(`${agent.name} has not been reviewed on this daemon: review it first`, "warn", 5e3), actions.pushOverlay({ kind: FOLDER_OVERLAY, props: { folder, review: filePath } }), null);
1034
+ if (agent.status === "needs_review") return review();
1035
+ let start2 = options2.start ?? !0, c = client;
1036
+ dispatch({ type: "tracked/busy", filePath, busy: "loading" }), dispatch({ type: "tracked/file-error", filePath, error: void 0 });
1037
+ let ref;
1038
+ try {
1039
+ ref = await c.load(filePath, !0);
1040
+ } catch (err) {
1041
+ if (dispatch({ type: "tracked/busy", filePath, busy: void 0 }), err instanceof DaemonError && err.unreachable && dispatch({ type: "daemon/reachable", reachable: !1 }), err instanceof DaemonError && err.status === 403) return review();
1042
+ let error = describe(err);
1043
+ return dispatch({ type: "tracked/file-error", filePath, error }), toast(`Load ${agent.name}: ${error}`, "error", 8e3), null;
1044
+ }
1045
+ let name = ref.config?.handle || ref.config?.name || agent.name, started = "", level = "success";
1046
+ if (start2 || agent.autostart) {
1047
+ dispatch({ type: "tracked/busy", filePath, busy: "starting" });
1048
+ try {
1049
+ started = ` and started it${(await c.start(ref.id)).startupTriggered ? " (startup turn running)" : ""}`;
1050
+ } catch (err) {
1051
+ started = ` (start failed: ${describe(err)})`, level = "warn";
1052
+ }
1053
+ }
1054
+ if (dispatch({ type: "tracked/busy", filePath, busy: void 0 }), stale(c)) return null;
1055
+ let text = `Loaded ${name}${started}`;
1056
+ toast(text, level, 5e3);
1057
+ let wasSelected = state.selectedAgentId === key || state.selectedAgentId === entry.key;
1058
+ return await actions.refreshAgents(), actions.refreshTracked(), (wasSelected || !state.selectedAgentId || isTrackedKey(state.selectedAgentId)) && state.agents[ref.id] && actions.selectAgent(ref.id), actions.notice(ref.id, MAIN_LOOP, text, level === "success" ? "info" : "warn"), ref.id;
1059
+ },
1060
+ selectAgent(agentId) {
1061
+ dispatch({ type: "select/agent", agentId }), !isTrackedKey(agentId) && agentId && (actions.ensureTranscript(agentId, selectedLoopOf(agentId)), state.agents[agentId]?.config || actions.loadConfig(agentId));
1062
+ },
1063
+ selectLoop(agentId, loop) {
1064
+ dispatch({ type: "select/loop", agentId, loop }), actions.ensureTranscript(agentId, loop);
1065
+ },
1066
+ setView(view) {
1067
+ let changed = state.activeView !== view;
1068
+ dispatch({ type: "view/set", view }), changed && dispatch({ type: "focus/set", focus: view === CHAT_VIEW_ID ? "input" : "main" });
1069
+ },
1070
+ setFocus(focus) {
1071
+ dispatch({ type: "focus/set", focus });
1072
+ },
1073
+ pushOverlay(overlay) {
1074
+ let id = overlay.id ?? localId("o");
1075
+ return dispatch({ type: "overlay/push", overlay: { ...overlay, id } }), id;
1076
+ },
1077
+ popOverlay(id) {
1078
+ dispatch({ type: "overlay/pop", id });
1079
+ },
1080
+ confirm(confirmOptions) {
1081
+ return new Promise((resolve) => {
1082
+ let id = localId("confirm");
1083
+ confirmResolvers.set(id, resolve), dispatch({ type: "overlay/push", overlay: { id, kind: "confirm", props: { ...confirmOptions } } });
1084
+ });
1085
+ },
1086
+ toast,
1087
+ dismissToast(id) {
1088
+ let timer = toastTimers.get(id);
1089
+ timer && clearTimeout(timer), toastTimers.delete(id), dispatch({ type: "toast/dismiss", id });
1090
+ },
1091
+ setViewState(view, value) {
1092
+ dispatch({ type: "viewState/set", view, value });
1093
+ },
1094
+ prefillPrompt(text) {
1095
+ dispatch({ type: "viewState/set", view: PROMPT_PREFILL_KEY, value: { text, nonce: localId("p") } }), dispatch({ type: "focus/set", focus: "input" });
1096
+ },
1097
+ notice(agentId, loop, text, level = "info") {
1098
+ dispatch({ type: "transcript/append", key: transcriptKey(agentId, loop), item: { id: localId("n"), at: Date.now(), local: !0, kind: "notice", level, text } });
1099
+ },
1100
+ async ensureTranscript(agentId, loop) {
1101
+ if (isTrackedKey(agentId)) return;
1102
+ let t = state.transcripts[transcriptKey(agentId, loop)];
1103
+ t?.loaded || t?.loading || await actions.loadTranscript(agentId, loop);
1104
+ },
1105
+ async loadTranscript(agentId, loop) {
1106
+ let key = transcriptKey(agentId, loop), c = client;
1107
+ dispatch({ type: "transcript/loading", key });
1108
+ try {
1109
+ let page = await c.loopHistory(agentId, { loop, limit: pageSize });
1110
+ stale(c) || dispatch({ type: "transcript/history", key, entries: page.entries, total: page.total, offset: page.offset, mode: "replace" });
1111
+ } catch (err) {
1112
+ stale(c) || dispatch({ type: "transcript/error", key, error: describe(err) });
1113
+ }
1114
+ },
1115
+ async loadOlder(agentId, loop) {
1116
+ let key = transcriptKey(agentId, loop), t = state.transcripts[key];
1117
+ if (!t || t.loading || t.oldestOffset <= 0) return;
1118
+ let offset = Math.max(0, t.oldestOffset - pageSize), limit = t.oldestOffset - offset, c = client;
1119
+ dispatch({ type: "transcript/loading", key });
1120
+ try {
1121
+ let page = await c.loopHistory(agentId, { loop, limit, offset });
1122
+ stale(c) || dispatch({ type: "transcript/history", key, entries: page.entries, total: page.total, offset: page.offset, mode: "prepend" });
1123
+ } catch (err) {
1124
+ stale(c) || dispatch({ type: "transcript/error", key, error: describe(err) });
1125
+ }
1126
+ },
1127
+ async sendChat(text, target = {}) {
1128
+ let agentId = target.agentId ?? state.selectedAgentId, trimmed = text.trim();
1129
+ if (!agentId || !trimmed) return !1;
1130
+ if (isTrackedKey(agentId)) {
1131
+ let name = findTracked(state, agentId)?.agent.name ?? "the agent";
1132
+ toast(`${name} is stopped: starting it to deliver your message`, "info", 3e3);
1133
+ let started = await actions.startTracked(agentId);
1134
+ if (!started)
1135
+ return toast(`Not sent: ${name} did not start (Ctrl+Up recalls your message)`, "warn", 6e3), !1;
1136
+ agentId = started;
1137
+ }
1138
+ let loop = target.loop ?? selectedLoopOf(agentId), key = transcriptKey(agentId, loop), item = { id: localId(), at: Date.now(), local: !0, kind: "user", text: trimmed, origin: "owner", pending: !0 };
1139
+ dispatch({ type: "transcript/append", key, item });
1140
+ try {
1141
+ return await client.chat(agentId, trimmed, loop), dispatch({ type: "transcript/update", key, id: item.id, patch: { accepted: !0 } }), !0;
1142
+ } catch (err) {
1143
+ return dispatch({ type: "transcript/update", key, id: item.id, patch: { pending: !1 } }), dispatch({ type: "transcript/append", key, item: { id: localId(), at: Date.now(), local: !0, kind: "error", text: `Not sent: ${describe(err)}` } }), !1;
1144
+ }
1145
+ },
1146
+ async clearLoopHistory(agentId, loop) {
1147
+ await run("Clear", (c) => c.clearChat(agentId, loop)) && (dispatch({ type: "transcript/reset", key: transcriptKey(agentId, loop) }), toast(`Cleared ${loop} history`, "success"), await actions.refreshLoops(agentId));
1148
+ },
1149
+ async compactLoop(agentId, loop) {
1150
+ return await run(`Compact ${loop}`, (c) => c.compact(agentId, loop)) ? (toast(`Compacted ${loop} of ${agentLabel(agentId)}`, "success"), actions.notice(agentId, loop, "History compacted by you"), !0) : !1;
1151
+ },
1152
+ async createLoop(agentId, input) {
1153
+ let result = await run("Create loop", (c) => c.createLoop(agentId, input));
1154
+ if (result) {
1155
+ let excluded = result.excludedTools.length ? ` (not granted yet: ${result.excludedTools.join(", ")})` : "";
1156
+ toast(`Loop ${input.name} created${result.kickoff?.woke ? ", running first turn" : ""}${excluded}`, "success"), await actions.refreshLoops(agentId);
1157
+ }
1158
+ return result;
1159
+ },
1160
+ async updateLoop(agentId, name, patch) {
1161
+ let result = await run("Update loop", (c) => c.updateLoop(agentId, name, patch));
1162
+ return result && (toast(`Loop ${name} updated: ${result.updated.join(", ")}`, "success"), await actions.refreshLoops(agentId)), result;
1163
+ },
1164
+ async setLoopEnabled(agentId, name, enabled) {
1165
+ await run(enabled ? "Enable loop" : "Disable loop", (c) => c.setLoopEnabled(agentId, name, enabled)) && (toast(`Loop ${name} ${enabled ? "enabled" : "disabled"}`, "success"), await actions.refreshLoops(agentId));
1166
+ },
1167
+ async deleteLoop(agentId, name) {
1168
+ let result = await run("Delete loop", (c) => c.deleteLoop(agentId, name));
1169
+ return result && (toast(`Loop ${name} deleted \u2014 ${result.archivedEntries} entries archived${result.interruptedTurn ? ", running turn stopped" : ""}`, "success"), dispatch({ type: "transcript/reset", key: transcriptKey(agentId, name) }), selectedLoopOf(agentId) === name && dispatch({ type: "select/loop", agentId, loop: MAIN_LOOP }), await actions.refreshLoops(agentId)), result;
1170
+ },
1171
+ async scheduleLoop(agentId, input) {
1172
+ let result = await run("Schedule", (c) => c.createTimer(agentId, input));
1173
+ return result && toast(`Timer ${result.id} scheduled for ${input.loop ?? MAIN_LOOP}`, "success"), result?.id;
1174
+ },
1175
+ async resolveTask(agentId, taskId, action, reason) {
1176
+ await run(action === "approve" ? "Approve" : "Deny", (c) => c.resolveTask(agentId, taskId, { action, ...reason ? { reason } : {} })) && toast(`${action === "approve" ? "Approved" : action === "deny" ? reason ? "Rejected with feedback" : "Rejected" : "Updated"} ${taskId}`, "success"), await actions.refreshHil(agentId);
1177
+ },
1178
+ async alwaysApproveTask(agentId, taskId) {
1179
+ let result = await run("Always approve", (c) => c.alwaysApproveTask(agentId, taskId));
1180
+ return result && toast(`Always approving ${result.tool}: it will not ask again (Inspect \u203A Config \u203A tools to undo)`, "success", 5e3), await actions.refreshHil(agentId), !!result;
1181
+ },
1182
+ async approveAllTasks(agentId, loop) {
1183
+ let result = await run("Approve all", (c) => c.approveAllTasks(agentId, loop));
1184
+ if (result) {
1185
+ let skipped = result.skippedProtection ? ` \xB7 ${result.skippedProtection} protection override${result.skippedProtection === 1 ? "" : "s"} still need${result.skippedProtection === 1 ? "s" : ""} you one by one` : "";
1186
+ toast(`Approved ${result.approved} call${result.approved === 1 ? "" : "s"}${skipped}`, result.skippedProtection ? "warn" : "success", 5e3);
1187
+ }
1188
+ await actions.refreshHil(agentId);
1189
+ },
1190
+ async answerAsk(agentId, requestId, answer, loop) {
1191
+ let result = await run("Answer", (c) => c.answerAsk(agentId, requestId, answer, loop));
1192
+ result && toast(result.answered ? "Answer sent" : "Ask was no longer pending", result.answered ? "success" : "warn"), await actions.refreshHil(agentId);
1193
+ },
1194
+ async respondSuspend(agentId, resume) {
1195
+ await run("Suspend", (c) => c.respondSuspend(agentId, resume)) && toast(resume ? "Resumed" : "Shutting down", "success"), await actions.refreshAgent(agentId);
1196
+ },
1197
+ async refreshAuth() {
1198
+ let c = client;
1199
+ try {
1200
+ let auth = await c.authStatus();
1201
+ stale(c) || dispatch({ type: "auth/set", auth });
1202
+ } catch {
1203
+ }
1204
+ },
1205
+ async logoutSubscription(provider) {
1206
+ let label = provider === "chatgpt" ? "ChatGPT" : "Grok", result = await run(`Sign out of ${label}`, (c) => c.logoutSubscription(provider));
1207
+ return result && toast(`Signed the daemon out of ${label}`, "success"), await actions.refreshAuth(), !!result;
1208
+ },
1209
+ async refreshWeb() {
1210
+ let c = client, server = null, agents = {}, error;
1211
+ try {
1212
+ let mesh = await c.meshStatus();
1213
+ server = parseServer(mesh.meshServer), agents = parseMeshAgents(mesh.agents);
1214
+ } catch (err) {
1215
+ if (stale(c) || err instanceof DaemonError && err.unreachable) return state.web;
1216
+ error = describe(err);
1217
+ }
1218
+ if (!server)
1219
+ try {
1220
+ server = parseServer(await c.meshServer());
1221
+ } catch (err) {
1222
+ if (stale(c) || err instanceof DaemonError && err.unreachable) return state.web;
1223
+ error ??= describe(err);
1224
+ }
1225
+ let lan = [];
1226
+ if (server?.running && bindsAll(server.host) && (lan = parseLan(await c.lanAddresses().catch(() => null))), stale(c)) return state.web;
1227
+ let web = { server, lan, agents, ...server ? {} : { error }, at: Date.now() };
1228
+ return dispatch({ type: "web/set", web }), web;
1229
+ },
1230
+ async setWebServer(on) {
1231
+ let result = await run(on ? "Start web server" : "Stop web server", (c) => c.meshServerAction(on ? "start" : "stop")), web = await actions.refreshWeb();
1232
+ if (!result) return !1;
1233
+ let server = web?.server ?? parseServer(result), ok = !!server && server.running === on;
1234
+ return on ? toast(ok ? `Web server ${serverText(server)} \u2014 agent sites are up` : `Web server did not start${typeof result.error == "string" ? `: ${result.error}` : ""}`, ok ? "success" : "error") : toast(ok ? "Web server stopped \u2014 agent sites, APIs and mesh delivery are offline" : "Web server is still running", ok ? "success" : "warn"), ok;
1235
+ },
1236
+ async refreshIdentity() {
1237
+ let c = client;
1238
+ try {
1239
+ let identity = await c.identity();
1240
+ return stale(c) ? state.identity : (dispatch({ type: "identity/set", identity }), identity);
1241
+ } catch (err) {
1242
+ return stale(c) || err instanceof DaemonError && err.unreachable ? state.identity : (dispatch({ type: "identity/set", identity: null }), null);
1243
+ }
1244
+ },
1245
+ async createIdentity(passphrase) {
1246
+ let result = await attempt((c) => c.createIdentity(passphrase));
1247
+ return result.ok && (dispatch({ type: "identity/set", identity: result.value.identity }), toast("Owner identity created", "success")), result;
1248
+ },
1249
+ async restoreIdentity(mnemonic, passphrase) {
1250
+ let result = await attempt((c) => c.restoreIdentity(mnemonic, passphrase));
1251
+ return result.ok ? (dispatch({ type: "identity/set", identity: result.value.identity }), toast("Owner identity restored", "success"), { ok: !0, value: result.value.identity }) : result;
1252
+ },
1253
+ async unlockIdentity(passphrase) {
1254
+ let result = await attempt((c) => c.unlockIdentity(passphrase));
1255
+ return result.ok ? (dispatch({ type: "identity/set", identity: result.value.identity }), toast("Owner identity unlocked", "success"), { ok: !0, value: result.value.identity }) : result;
1256
+ },
1257
+ async lockIdentity() {
1258
+ let result = await attempt((c) => c.lockIdentity());
1259
+ return result.ok ? (dispatch({ type: "identity/set", identity: result.value.identity }), toast("Owner identity locked", "success"), { ok: !0, value: result.value.identity }) : (toast(`Lock: ${result.error}`, "error"), result);
1260
+ },
1261
+ async confirmIdentityBackup() {
1262
+ let result = await attempt((c) => c.confirmIdentityBackup());
1263
+ return result.ok ? (dispatch({ type: "identity/set", identity: result.value.identity }), toast("Seed phrase backup confirmed", "success"), { ok: !0, value: result.value.identity }) : (toast(`Backup: ${result.error}`, "error"), result);
1264
+ },
1265
+ async listTemplates() {
1266
+ return attempt((c) => c.templates());
1267
+ },
1268
+ async createAgent(input) {
1269
+ let result = await attempt((c) => c.createAgent(input));
1270
+ if (!result.ok) return result;
1271
+ let created = result.value;
1272
+ return toast(`Created ${created.name}${created.started ? " and started it" : ""}`, "success"), await actions.refreshAgents(), state.agents[created.agentId] && actions.selectAgent(created.agentId), result;
1273
+ },
1274
+ run
1275
+ };
1276
+ async function attempt(fn) {
1277
+ try {
1278
+ return { ok: !0, value: await fn(client) };
1279
+ } catch (err) {
1280
+ if (err instanceof DaemonError) {
1281
+ err.unreachable && dispatch({ type: "daemon/reachable", reachable: !1 });
1282
+ let body = err.body;
1283
+ return body && typeof body == "object" && body.identity && typeof body.identity == "object" && dispatch({ type: "identity/set", identity: body.identity }), { ok: !1, error: err.message, code: body && typeof body.code == "string" ? body.code : void 0, status: err.status, body: err.body };
1284
+ }
1285
+ return { ok: !1, error: describe(err), status: null };
1286
+ }
1287
+ }
1288
+ function agentLabel(agentId) {
1289
+ let agent = state.agents[agentId];
1290
+ return agent?.summary.handle ?? agent?.summary.name ?? agentId;
1291
+ }
1292
+ let pendingFrames = [], flushScheduled = !1, flushFrames = () => {
1293
+ flushScheduled = !1;
1294
+ let frames = pendingFrames;
1295
+ pendingFrames = [], frames.length === 1 ? dispatch({ type: "event", frame: frames[0] }) : frames.length > 1 && dispatch({ type: "events", frames });
1296
+ };
1297
+ function onFrame(frame) {
1298
+ pendingFrames.push(frame), flushScheduled || (flushScheduled = !0, setImmediate(flushFrames));
1299
+ let { event } = frame, agentId = event.agent_id;
1300
+ switch (event.event_type) {
1301
+ case "agent.loaded":
1302
+ case "agent.unloaded":
1303
+ debounce("agents", () => {
1304
+ actions.refreshAgents().then(() => actions.refreshTracked());
1305
+ }, 250), debounce("web", () => {
1306
+ actions.refreshWeb();
1307
+ }, WEB_EVENT_DEBOUNCE_MS);
1308
+ return;
1309
+ }
1310
+ if (event.event_type.startsWith("mesh.") && debounce("web", () => {
1311
+ actions.refreshWeb();
1312
+ }, WEB_EVENT_DEBOUNCE_MS), !agentId || !state.agents[agentId]) return;
1313
+ let loop = eventLoop(event), key = transcriptKey(agentId, loop);
1314
+ switch (event.event_type) {
1315
+ case "turn.completed":
1316
+ case "loop.cleared":
1317
+ case "loop.compacted":
1318
+ state.transcripts[key]?.loaded && debounce(`t:${key}`, () => {
1319
+ actions.loadTranscript(agentId, loop);
1320
+ }), debounce(`loops:${agentId}`, () => {
1321
+ actions.refreshLoops(agentId);
1322
+ }), debounce(`status:${agentId}`, () => {
1323
+ let c = client;
1324
+ c.status(agentId).then((status) => {
1325
+ stale(c) || dispatch({ type: "agent/status", agentId, status });
1326
+ }).catch(() => {
1327
+ });
1328
+ });
1329
+ break;
1330
+ case "config.changed": {
1331
+ let keys = Array.isArray(event.payload?.changed_keys) ? event.payload.changed_keys : [];
1332
+ (keys.length === 0 || keys.includes("loops")) && debounce(`loops:${agentId}`, () => {
1333
+ actions.refreshLoops(agentId);
1334
+ }), state.agents[agentId]?.config && debounce(`config:${agentId}`, () => {
1335
+ actions.loadConfig(agentId);
1336
+ }), (keys.length === 0 || keys.includes("serving") || keys.includes("messaging")) && debounce("web", () => {
1337
+ actions.refreshWeb();
1338
+ }, WEB_EVENT_DEBOUNCE_MS);
1339
+ break;
1340
+ }
1341
+ case "tool.completed":
1342
+ typeof event.payload?.name == "string" && /^sys_(set|delete)_meta$/.test(event.payload.name) && debounce("web", () => {
1343
+ actions.refreshWeb();
1344
+ }, 300);
1345
+ break;
1346
+ case "llm.failed":
1347
+ case "agent.error":
1348
+ debounce("auth", () => {
1349
+ actions.refreshAuth();
1350
+ }, 500);
1351
+ break;
1352
+ case "hil.requested":
1353
+ case "hil.resolved":
1354
+ case "ask.requested":
1355
+ case "ask.resolved":
1356
+ debounce(`hil:${agentId}`, () => {
1357
+ actions.refreshHil(agentId);
1358
+ }, 300);
1359
+ break;
1360
+ }
1361
+ }
1362
+ async function start() {
1363
+ stopped = !1;
1364
+ try {
1365
+ await client.health(), dispatch({ type: "daemon/reachable", reachable: !0 });
1366
+ } catch {
1367
+ dispatch({ type: "daemon/reachable", reachable: !1 });
1368
+ }
1369
+ options.live !== !1 && (stream = client.events({
1370
+ onEvent: onFrame,
1371
+ onState: (info) => {
1372
+ dispatch({ type: "connection", info }), info.state === "reconnecting" && (needsResync = !0, info.error && dispatch({ type: "daemon/reachable", reachable: !1 })), info.state === "open" && (info.resumed || needsResync) && (needsResync = !1, toast(info.resumed ? "Reconnected to daemon \u2014 resyncing" : "Connected to daemon", "info", 2500), resync());
1373
+ }
1374
+ }).start(), webTick && clearInterval(webTick), webTick = setInterval(() => {
1375
+ stopped || actions.refreshWeb();
1376
+ }, WEB_POLL_MS), trackedTick && clearInterval(trackedTick), trackedTick = setInterval(() => {
1377
+ !stopped && state.daemonReachable !== !1 && actions.refreshTracked();
1378
+ }, TRACKED_POLL_MS)), await Promise.all([actions.refreshIdentity(), actions.refreshAuth(), actions.refreshAgents(), actions.refreshWeb()]), await actions.refreshTracked();
1379
+ }
1380
+ async function resync() {
1381
+ await Promise.all([actions.refreshIdentity(), actions.refreshAuth(), actions.refreshAgents(), actions.refreshWeb()]), actions.refreshTracked();
1382
+ for (let key of Object.keys(state.transcripts)) {
1383
+ let at = key.indexOf("\0"), agentId = key.slice(0, at);
1384
+ state.agents[agentId] && state.transcripts[key].loaded && actions.loadTranscript(agentId, key.slice(at + 1));
1385
+ }
1386
+ }
1387
+ function stop() {
1388
+ stopped = !0, stream?.close(), stream = null, webTick && (clearInterval(webTick), webTick = null), trackedTick && (clearInterval(trackedTick), trackedTick = null), pendingFrames = [];
1389
+ for (let timer of toastTimers.values()) clearTimeout(timer);
1390
+ for (let timer of debounced.values()) clearTimeout(timer);
1391
+ toastTimers.clear(), debounced.clear();
1392
+ for (let resolve of confirmResolvers.values()) resolve(!1);
1393
+ confirmResolvers.clear();
1394
+ }
1395
+ function resolveConfirm(id, confirmed) {
1396
+ let resolve = confirmResolvers.get(id);
1397
+ confirmResolvers.delete(id), dispatch({ type: "overlay/pop", id }), resolve?.(confirmed);
1398
+ }
1399
+ return {
1400
+ get client() {
1401
+ return client;
1402
+ },
1403
+ actions,
1404
+ getState,
1405
+ dispatch,
1406
+ subscribe,
1407
+ start,
1408
+ stop,
1409
+ resolveConfirm
1410
+ };
1411
+ }
1412
+ var StoreContext = (0, import_react.createContext)(null);
1413
+ function StoreProvider({ store, children }) {
1414
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StoreContext.Provider, { value: store, children });
1415
+ }
1416
+ function useStore() {
1417
+ let store = (0, import_react.useContext)(StoreContext);
1418
+ if (!store) throw new Error("useStore must be used inside <StoreProvider>");
1419
+ return store;
1420
+ }
1421
+ function useActions() {
1422
+ return useStore().actions;
1423
+ }
1424
+ function useClient() {
1425
+ return useStore().client;
1426
+ }
1427
+ function useTuiSelector(selector, isEqual = Object.is) {
1428
+ let store = useStore(), cache = (0, import_react.useRef)(null), getSnapshot = () => {
1429
+ let current = store.getState(), cached = cache.current;
1430
+ if (cached && cached.state === current && cached.selector === selector) return cached.value;
1431
+ let value = selector(current);
1432
+ return cached && isEqual(cached.value, value) ? (cache.current = { state: current, selector, value: cached.value }, cached.value) : (cache.current = { state: current, selector, value }, value);
1433
+ };
1434
+ return (0, import_react.useSyncExternalStore)(store.subscribe, getSnapshot, getSnapshot);
1435
+ }
1436
+ function shallowEqual(a, b) {
1437
+ if (Object.is(a, b)) return !0;
1438
+ if (typeof a != "object" || typeof b != "object" || a === null || b === null) return !1;
1439
+ if (Array.isArray(a)) {
1440
+ if (!Array.isArray(b) || a.length !== b.length) return !1;
1441
+ for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return !1;
1442
+ return !0;
1443
+ }
1444
+ let ak = Object.keys(a), bk = Object.keys(b);
1445
+ if (ak.length !== bk.length) return !1;
1446
+ for (let k of ak) if (!Object.is(a[k], b[k])) return !1;
1447
+ return !0;
1448
+ }
1449
+
1450
+ export {
1451
+ emptyTranscript,
1452
+ isAsyncInput,
1453
+ askQuestion,
1454
+ isTrackedKey,
1455
+ folderName,
1456
+ stoppedLabel,
1457
+ stoppedError,
1458
+ findTracked,
1459
+ transcriptKey,
1460
+ isBusyState,
1461
+ parseServer,
1462
+ siteOf,
1463
+ servedText,
1464
+ siteKind,
1465
+ shortUrl,
1466
+ SERVER_STOPPED_TEXT,
1467
+ serverBadge,
1468
+ serverText,
1469
+ PROMPT_PREFILL_KEY,
1470
+ createTuiStore,
1471
+ StoreProvider,
1472
+ useStore,
1473
+ useActions,
1474
+ useClient,
1475
+ useTuiSelector,
1476
+ shallowEqual
1477
+ };