@agentdocumentformat/cli 0.7.7 → 0.8.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 (102) hide show
  1. package/README.md +1 -1
  2. package/dist/adf.mjs +59 -8
  3. package/dist/chunks/{APEv2Parser-2CNNHMXV.mjs → APEv2Parser-WIXRJLHB.mjs} +2 -2
  4. package/dist/chunks/{AiffParser-7BR4RL6G.mjs → AiffParser-ZC4QFOVJ.mjs} +5 -5
  5. package/dist/chunks/{App-5KXVPMBV.mjs → App-A5GUFCFJ.mjs} +279 -291
  6. package/dist/chunks/{DsdiffParser-CMD4AX7A.mjs → DsdiffParser-UAPAJHFX.mjs} +5 -5
  7. package/dist/chunks/{DsfParser-UOGZDS2M.mjs → DsfParser-NNYZK2QX.mjs} +6 -6
  8. package/dist/chunks/{FlacParser-HB3T3CD4.mjs → FlacParser-MW2W4LO3.mjs} +6 -6
  9. package/dist/chunks/{MP4Parser-66HBRUSX.mjs → MP4Parser-Z57SYOOQ.mjs} +4 -4
  10. package/dist/chunks/{MpegParser-YW6LIUEW.mjs → MpegParser-XIIPAZVM.mjs} +7 -7
  11. package/dist/chunks/{MusepackParser-PAUSXP7D.mjs → MusepackParser-QWNDEYHJ.mjs} +6 -6
  12. package/dist/chunks/{OggParser-NUBV3GWC.mjs → OggParser-WRX53F77.mjs} +9 -9
  13. package/dist/chunks/{WavPackParser-WQAGT7TC.mjs → WavPackParser-MJ7WCSJ5.mjs} +2 -2
  14. package/dist/chunks/{WaveParser-EWLQVDX4.mjs → WaveParser-RAVLHZ5S.mjs} +7 -7
  15. package/dist/chunks/{adf-schema-US4NFHMR.mjs → adf-schema-YJSGLMA4.mjs} +2 -2
  16. package/dist/chunks/auth-manager-AJ32FZWS.mjs +19 -0
  17. package/dist/chunks/auth-manager-C5OBEQK2.mjs +18 -0
  18. package/dist/chunks/auth-manager-TBNKCJ45.mjs +17 -0
  19. package/dist/chunks/{chatgpt-subscription-E4MXTIAT.mjs → chatgpt-subscription-MMGNW5KJ.mjs} +5 -2
  20. package/dist/chunks/chunk-3UGZFWIF.mjs +26 -0
  21. package/dist/chunks/{chunk-5PO5PKRV.mjs → chunk-4OGZFUKA.mjs} +126 -67
  22. package/dist/chunks/{chunk-VN7UH7I5.mjs → chunk-6XQZGYMK.mjs} +246 -67
  23. package/dist/chunks/{chunk-XNPZBLYL.mjs → chunk-75DC5EWN.mjs} +13 -2
  24. package/dist/chunks/chunk-AZYOXXVL.mjs +865 -0
  25. package/dist/chunks/{chunk-6VQEXLE2.mjs → chunk-BHY7QDCM.mjs} +41 -3
  26. package/dist/chunks/chunk-C2S64Y6F.mjs +203 -0
  27. package/dist/chunks/chunk-C4GA5SI4.mjs +12799 -0
  28. package/dist/chunks/chunk-DDTTSKGG.mjs +2443 -0
  29. package/dist/chunks/{chunk-VAUOM3IN.mjs → chunk-DLWCKKIO.mjs} +1 -1
  30. package/dist/chunks/{chunk-HPVFJYXR.mjs → chunk-ESP3VNMX.mjs} +1 -1
  31. package/dist/chunks/{chunk-QPLEAE6V.mjs → chunk-G6NBFYG5.mjs} +152 -824
  32. package/dist/chunks/{chunk-KXEF4F4E.mjs → chunk-GAZO6UMI.mjs} +1 -1
  33. package/dist/chunks/{chunk-XYTWGHFS.mjs → chunk-H3XLRWVE.mjs} +1 -1
  34. package/dist/chunks/{chunk-7T2YMTWL.mjs → chunk-H4C65MTP.mjs} +4 -4
  35. package/dist/chunks/chunk-HBOFZRUS.mjs +738 -0
  36. package/dist/chunks/chunk-JVPZIMXW.mjs +976 -0
  37. package/dist/chunks/{chunk-XYV3VCIX.mjs → chunk-JZFONJSL.mjs} +79 -20
  38. package/dist/chunks/chunk-KDDVQKCG.mjs +65 -0
  39. package/dist/chunks/chunk-KRPKWOMB.mjs +290 -0
  40. package/dist/chunks/{chunk-4N4ASPH6.mjs → chunk-LCMANRYY.mjs} +4 -254
  41. package/dist/chunks/{chunk-TPRZQ7Z4.mjs → chunk-LGL6ML37.mjs} +4 -4
  42. package/dist/chunks/chunk-LKFHERRV.mjs +145 -0
  43. package/dist/chunks/chunk-LTX74NU6.mjs +29 -0
  44. package/dist/chunks/chunk-M2F7C2UJ.mjs +425 -0
  45. package/dist/chunks/{chunk-62NE4LG4.mjs → chunk-MQAMI5BF.mjs} +5 -5
  46. package/dist/chunks/chunk-MZRXFWPQ.mjs +278 -0
  47. package/dist/chunks/{chunk-PRMGZZM5.mjs → chunk-NZLEPJ5M.mjs} +2 -0
  48. package/dist/chunks/{chunk-CD3ATSXE.mjs → chunk-NZO5O4VN.mjs} +1 -1
  49. package/dist/chunks/{chunk-I3UYSITV.mjs → chunk-O7XKQ6CH.mjs} +1 -1
  50. package/dist/chunks/chunk-P3RG5LQA.mjs +244 -0
  51. package/dist/chunks/chunk-PAK5JCO2.mjs +48 -0
  52. package/dist/chunks/chunk-PC63YFB7.mjs +34 -0
  53. package/dist/chunks/{daemon-control-HKFVSQTQ.mjs → chunk-PRPTKMQW.mjs} +67 -26
  54. package/dist/chunks/{chunk-LFMB4PAA.mjs → chunk-TKXIH27X.mjs} +974 -113
  55. package/dist/chunks/{chunk-5W7KES6P.mjs → chunk-UZPDETEU.mjs} +1 -1
  56. package/dist/chunks/chunk-V2T6NZX2.mjs +517 -0
  57. package/dist/chunks/chunk-V3MM6PCH.mjs +366 -0
  58. package/dist/chunks/chunk-WJGPNHGX.mjs +67 -0
  59. package/dist/chunks/chunk-WVTPPOKK.mjs +290 -0
  60. package/dist/chunks/{chunk-J74STFKE.mjs → chunk-WX6QCUWI.mjs} +272 -51
  61. package/dist/chunks/{chunk-Y5ZLKFLE.mjs → chunk-XNNJQCZP.mjs} +196 -165
  62. package/dist/chunks/{chunk-HDBPBORT.mjs → chunk-XT2BJUFC.mjs} +15 -6
  63. package/dist/chunks/chunk-YRMKSHW3.mjs +9076 -0
  64. package/dist/chunks/{chunk-BNXUAOO4.mjs → chunk-ZGXUOAWZ.mjs} +3186 -959
  65. package/dist/chunks/chunk-ZPB3HYM7.mjs +45 -0
  66. package/dist/chunks/claude-subscription-33BMZB6I.mjs +29 -0
  67. package/dist/chunks/{cli-AFHQ2XTN.mjs → cli-I47IFDHJ.mjs} +797 -56
  68. package/dist/chunks/{commands-XNJMCD5L.mjs → commands-E4EQUHE5.mjs} +5 -2
  69. package/dist/chunks/{daemon-CHZHTLGR.mjs → daemon-FQ5BV3AP.mjs} +84550 -70518
  70. package/dist/chunks/daemon-control-L3CLG63P.mjs +59 -0
  71. package/dist/chunks/{daemon-token-WRSULP7G.mjs → daemon-token-L5QKTHU5.mjs} +3 -1
  72. package/dist/chunks/{discord-DSP4HUWI.mjs → discord-IR62565M.mjs} +3 -52
  73. package/dist/chunks/{email-BRG7KUO2.mjs → email-KHHTJBDW.mjs} +4 -2
  74. package/dist/chunks/{environment-NX277MQG.mjs → environment-R47X44GM.mjs} +1 -1
  75. package/dist/chunks/{grok-subscription-4PYX7TBF.mjs → grok-subscription-E74FS5EG.mjs} +5 -2
  76. package/dist/chunks/{lib-N7FCZWKH.mjs → lib-L27L5PXM.mjs} +22 -22
  77. package/dist/chunks/{open-VAU7PXT6.mjs → open-TLGS2Z3Q.mjs} +4 -4
  78. package/dist/chunks/{parser-JVY2PWSM.mjs → parser-7GARNT5L.mjs} +1 -1
  79. package/dist/chunks/{pipeline-executor-U6IMCCP3.mjs → pipeline-executor-FD4FBWQA.mjs} +8 -5
  80. package/dist/chunks/prompt-RRHZX4YT.mjs +13 -0
  81. package/dist/chunks/remote-access-cli-XXAPQWH6.mjs +268 -0
  82. package/dist/chunks/remote-hello-UFWUBDQI.mjs +37 -0
  83. package/dist/chunks/sdk-5FD2ZP7N.mjs +28422 -0
  84. package/dist/chunks/{slack-OCNNF4DX.mjs → slack-IYC5RAB5.mjs} +3 -4
  85. package/dist/chunks/{store-HUVDJPYN.mjs → store-ZRN2WCFB.mjs} +6 -3
  86. package/dist/chunks/tailscale-WLJATFMB.mjs +25 -0
  87. package/dist/chunks/{theme-SFE3JMA2.mjs → theme-HLBDTF6F.mjs} +1 -1
  88. package/dist/chunks/{themes-YLXLOIJF.mjs → themes-BQ72P446.mjs} +2 -2
  89. package/dist/chunks/{token-6G3HCMNX.mjs → token-6D22WECM.mjs} +20 -16
  90. package/dist/chunks/{token-util-UXYSDQIW.mjs → token-util-YF3ZWBZ4.mjs} +1 -2
  91. package/dist/chunks/{tui-4ZWZKD4C.mjs → tui-SPSPDADM.mjs} +17 -14
  92. package/dist/chunks/{welcome-XHXFV7SH.mjs → welcome-J5JZZAM5.mjs} +1 -1
  93. package/dist/chunks/{whatsapp-AVKT3CTJ.mjs → whatsapp-YJFFVN4Q.mjs} +8 -8
  94. package/package.json +1 -1
  95. package/dist/chunks/chunk-GKKCMXIZ.mjs +0 -94
  96. package/dist/chunks/chunk-IHDDCZBS.mjs +0 -112
  97. package/dist/chunks/chunk-KWFOS5WC.mjs +0 -41
  98. package/dist/chunks/chunk-UEZR2CNS.mjs +0 -65
  99. package/dist/chunks/chunk-VMHTYDH4.mjs +0 -172
  100. package/dist/chunks/chunk-ZROSGV65.mjs +0 -3112
  101. package/dist/chunks/{chunk-NBTUWMGP.mjs → chunk-2MTE22CR.mjs} +3 -3
  102. package/dist/chunks/{telegram-YI2OHNTD.mjs → telegram-JYY2VDTI.mjs} +4 -4
@@ -4,22 +4,24 @@ import { dirname as __adfDirname } from 'node:path';
4
4
  const require = __adfCreateRequire(import.meta.url);
5
5
  const __filename = __adfFileURLToPath(import.meta.url);
6
6
  const __dirname = __adfDirname(__filename);
7
+ import {
8
+ types_exports
9
+ } from "./chunk-75DC5EWN.mjs";
7
10
  import {
8
11
  require_jsx_runtime
9
12
  } from "./chunk-7CV2SA3H.mjs";
10
- import {
11
- DaemonError,
12
- MAIN_LOOP
13
- } from "./chunk-XNPZBLYL.mjs";
14
13
  import {
15
14
  cjs
16
15
  } from "./chunk-SGUTYISF.mjs";
17
16
  import {
18
17
  loop_parser_exports
19
- } from "./chunk-5PO5PKRV.mjs";
18
+ } from "./chunk-4OGZFUKA.mjs";
20
19
  import {
21
20
  require_react
22
21
  } from "./chunk-6GJ4QHRI.mjs";
22
+ import {
23
+ file_ref_exports
24
+ } from "./chunk-LKFHERRV.mjs";
23
25
  import {
24
26
  __toESM
25
27
  } from "./chunk-M2RX3S2T.mjs";
@@ -27,6 +29,9 @@ import {
27
29
  // src/main/tui/state/store.tsx
28
30
  var import_react = __toESM(require_react(), 1);
29
31
 
32
+ // src/main/tui/api/types.ts
33
+ var shared = cjs(types_exports), MAIN_LOOP = shared.MAIN_LOOP, DaemonError = shared.DaemonError, isCredentialsLocked = shared.isCredentialsLocked, SUPPORTED_CLIENT_API_VERSION = shared.SUPPORTED_CLIENT_API_VERSION;
34
+
30
35
  // src/main/tui/state/tracked.ts
31
36
  var TRACKED_PREFIX = "file:";
32
37
  function trackedKey(filePath) {
@@ -130,7 +135,14 @@ function reconcileSelection(state, previousSummaries = {}, trackedFresh = !1) {
130
135
  }
131
136
 
132
137
  // src/main/tui/state/transcript.ts
133
- var MAX_TRANSCRIPT_ITEMS = 2e3, { parseLoopToDisplay } = cjs(loop_parser_exports), localCounter = 0;
138
+ var MAX_TRANSCRIPT_ITEMS = 2e3, { parseLoopToDisplay } = cjs(loop_parser_exports), { attachmentText } = cjs(file_ref_exports);
139
+ function withAttachments(text, attachments) {
140
+ if (!Array.isArray(attachments) || attachments.length === 0) return text;
141
+ let lines = attachments.map(attachmentText);
142
+ return [text, ...lines].filter(Boolean).join(`
143
+ `);
144
+ }
145
+ var localCounter = 0;
134
146
  function localId(prefix = "l") {
135
147
  return localCounter += 1, `${prefix}:${Date.now().toString(36)}:${localCounter}`;
136
148
  }
@@ -151,6 +163,19 @@ function isTaskRef(text) {
151
163
  return !1;
152
164
  }
153
165
  }
166
+ function taskRefId(text) {
167
+ if (isTaskRef(text))
168
+ return JSON.parse(text).task_id;
169
+ }
170
+ function unresolvedTasks(items) {
171
+ let out = [];
172
+ for (let item of items) {
173
+ if (item.kind !== "tool" || item.status !== "running" || !item.toolUseId) continue;
174
+ let taskId = taskRefId(item.taskRef);
175
+ taskId && out.push({ toolUseId: item.toolUseId, taskId });
176
+ }
177
+ return out;
178
+ }
154
179
  function askQuestion(input) {
155
180
  let q = input && typeof input == "object" ? input.question : void 0;
156
181
  return typeof q == "string" ? q : "";
@@ -161,13 +186,13 @@ function historyToItems(entries) {
161
186
  let meta = entry.metadata ?? {}, base = { id: `h:${entry.id}`, at: entry.timestamp, seq: typeof meta.seq == "number" ? meta.seq : void 0 };
162
187
  switch (entry.type) {
163
188
  case "user":
164
- items.push({ ...base, kind: "user", text: entry.content, origin: "owner" });
189
+ items.push({ ...base, kind: "user", text: withAttachments(entry.content, meta.attachments), origin: "owner" });
165
190
  break;
166
191
  case "trigger":
167
192
  items.push({ ...base, kind: "user", text: entry.content, origin: "runtime" });
168
193
  break;
169
194
  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 });
195
+ meta.category === "loop" && typeof meta.fromLoop == "string" ? items.push({ ...base, kind: "user", text: entry.content, origin: "loop", from: meta.fromLoop }) : meta.category === "runtime" ? items.push({ ...base, kind: "user", text: entry.content, origin: "runtime" }) : items.push({ ...base, kind: "context", category: String(meta.category ?? "context"), text: entry.content });
171
196
  break;
172
197
  case "compaction":
173
198
  items.push({ ...base, kind: "context", category: "compaction", text: entry.content });
@@ -176,7 +201,7 @@ function historyToItems(entries) {
176
201
  items.push({ ...base, kind: "error", text: entry.content });
177
202
  break;
178
203
  case "text":
179
- items.push({ ...base, kind: "assistant", text: entry.content, streaming: !1, model: typeof meta.model == "string" ? meta.model : void 0 });
204
+ items.push({ ...base, kind: "assistant", text: entry.content, streaming: !1, model: typeof meta.model == "string" ? meta.model : void 0, ...meta.interrupted === !0 ? { interrupted: !0 } : {} });
180
205
  break;
181
206
  case "thinking":
182
207
  items.push({ ...base, kind: "thinking", text: entry.content, streaming: !1 });
@@ -196,7 +221,14 @@ function historyToItems(entries) {
196
221
  }
197
222
  case "tool_result": {
198
223
  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 });
224
+ if (call) {
225
+ if (!meta.isError && isTaskRef(entry.content)) {
226
+ call.async = !0, call.taskRef = entry.content;
227
+ break;
228
+ }
229
+ call.status = status, call.result = withAttachments(entry.content, meta.attachments), call.completedAt = entry.timestamp;
230
+ } else
231
+ 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
232
  break;
201
233
  }
202
234
  }
@@ -210,7 +242,7 @@ function mergeHistory(existing, incoming) {
210
242
  let history = incoming.map((item) => {
211
243
  if (item.kind !== "tool" || item.taskRef === void 0 || !item.toolUseId) return item;
212
244
  let live = finished.get(item.toolUseId);
213
- return !live || live.result === item.taskRef ? item : { ...item, status: live.status, result: live.result, completedAt: live.completedAt };
245
+ return live ? { ...item, status: live.status, result: live.result, completedAt: live.completedAt } : item;
214
246
  }), historyTools = /* @__PURE__ */ new Set(), historyTexts = /* @__PURE__ */ new Map(), countText = (key) => historyTexts.set(key, (historyTexts.get(key) ?? 0) + 1);
215
247
  for (let item of history)
216
248
  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()}`);
@@ -254,6 +286,9 @@ function finalizeStreaming(items) {
254
286
  let changed = !1, next = items.map((item) => (item.kind === "assistant" || item.kind === "thinking") && item.streaming ? (changed = !0, { ...item, streaming: !1 }) : item);
255
287
  return changed ? next : items;
256
288
  }
289
+ function markInterrupted(items) {
290
+ return items.map((item) => item.kind === "assistant" && item.streaming ? { ...item, interrupted: !0 } : item);
291
+ }
257
292
  function cap(items) {
258
293
  return items.length > MAX_TRANSCRIPT_ITEMS ? items.slice(items.length - MAX_TRANSCRIPT_ITEMS) : items;
259
294
  }
@@ -332,7 +367,7 @@ function applyEventToItems(items, event) {
332
367
  return next[index] = { ...next[index], ...patch }, next;
333
368
  }
334
369
  case "turn.completed": {
335
- let closed = finalizeStreaming(items), content = str(p.content)?.trim();
370
+ let closed = finalizeStreaming(p.interrupted === !0 && p.partial === !0 ? markInterrupted(items) : items), content = str(p.content)?.trim();
336
371
  if (!content) return closed;
337
372
  let lastUser = -1;
338
373
  for (let i = closed.length - 1; i >= 0; i--) if (closed[i].kind === "user") {
@@ -346,7 +381,7 @@ function applyEventToItems(items, event) {
346
381
  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" }]);
347
382
  }
348
383
  case "hil.resolved": {
349
- 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";
384
+ let taskId = str(p.task_id) ?? str(p.request_id), index = items.findIndex((item) => item.kind === "hil" && item.taskId === taskId), status = p.settled === !0 ? "completed" : p.approved === !0 ? "approved" : "denied";
350
385
  if (index < 0)
351
386
  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)" : ""}` }]);
352
387
  let next = items.slice();
@@ -651,10 +686,31 @@ function tuiReducer(state, action) {
651
686
  return patchTranscript(state, action.key, () => ({ ...emptyTranscript(), loaded: !0 }));
652
687
  case "transcript/idle":
653
688
  return patchTranscript(state, action.key, endLive);
689
+ case "tool/result":
690
+ return patchTranscript(state, action.key, (t) => {
691
+ let index = t.items.findIndex((item2) => item2.kind === "tool" && item2.toolUseId === action.toolUseId), item = t.items[index];
692
+ if (!item || item.kind !== "tool" || item.result === action.result) return t;
693
+ let items = t.items.slice();
694
+ return !action.isError && isTaskRef(action.result) ? (items[index] = { ...item, async: !0, taskRef: action.result }, { ...t, items }) : (items[index] = { ...item, result: action.result, status: action.isError ? "error" : "ok", completedAt: item.completedAt ?? Date.now() }, { ...t, items });
695
+ });
696
+ case "tool/task":
697
+ return patchTranscript(state, action.key, (t) => {
698
+ let index = t.items.findIndex((item2) => item2.kind === "tool" && item2.toolUseId === action.toolUseId), item = t.items[index];
699
+ if (!item || item.kind !== "tool" || item.status !== "running") return t;
700
+ let task = action.task, patch;
701
+ if (!task) patch = { status: "ok", result: item.taskRef };
702
+ else if (task.status === "completed") patch = { status: "ok", result: task.result ?? "" };
703
+ else if (task.status === "failed" || task.status === "denied" || task.status === "cancelled") patch = { status: "error", result: task.error ?? task.result ?? task.status };
704
+ else return t;
705
+ let items = t.items.slice();
706
+ return items[index] = { ...item, ...patch, completedAt: task?.completed_at ?? item.at }, { ...t, items };
707
+ });
654
708
  case "event":
655
- return applyEvent(state, action.frame.event);
709
+ return applyEvent(state, action.frame.event, !isSynthetic(action.frame));
656
710
  case "events":
657
- return action.frames.reduce((next, frame) => applyEvent(next, frame.event), state);
711
+ return action.frames.reduce((next, frame) => applyEvent(next, frame.event, !isSynthetic(frame)), state);
712
+ case "activity/note":
713
+ return { ...state, activity: pushBounded(state.activity, { id: localId("a"), at: Date.now(), agentId: null, loop: MAIN_LOOP, type: action.kind, summary: action.text }, MAX_ACTIVITY) };
658
714
  case "viewState/set":
659
715
  return { ...state, viewState: { ...state.viewState, [action.view]: action.value } };
660
716
  default:
@@ -690,8 +746,11 @@ var TRANSCRIPT_EVENTS = /* @__PURE__ */ new Set([
690
746
  "chat.delivered",
691
747
  "chat.discarded"
692
748
  ]);
693
- function applyEvent(state, event) {
694
- let agentId = event.agent_id ?? null, loop = eventLoop(event), next = {
749
+ function isSynthetic(frame) {
750
+ return frame.synthetic === !0;
751
+ }
752
+ function applyEvent(state, event, log = !0) {
753
+ let agentId = event.agent_id ?? null, loop = eventLoop(event), next = log ? {
695
754
  ...state,
696
755
  activity: pushBounded(state.activity, {
697
756
  id: localId("a"),
@@ -702,7 +761,7 @@ function applyEvent(state, event) {
702
761
  summary: summarizeEvent(event)
703
762
  }, MAX_ACTIVITY),
704
763
  lastEvents: pushBounded(state.lastEvents, event, MAX_LAST_EVENTS)
705
- };
764
+ } : state;
706
765
  if (!agentId || !next.agents[agentId]) return next;
707
766
  let p = event.payload ?? {};
708
767
  switch (event.event_type) {
@@ -808,6 +867,49 @@ function num(value) {
808
867
  return typeof value == "number" && Number.isFinite(value) ? value : 0;
809
868
  }
810
869
 
870
+ // src/main/tui/state/client-stream.ts
871
+ var MAIN = "main", NONE = { frames: [] };
872
+ function clientFrameEffects(frame) {
873
+ if (frame.kind === "umbilical") return { frames: [{ cursor: frame.cursor, event: frame.event }] };
874
+ if (frame.kind === "push" && frame.topic === "daemon_orphan_hold") {
875
+ let payload2 = frame.payload;
876
+ return { frames: [], notice: payload2.holding ? { text: `The daemon stays up because this app is connected: ${payload2.reason}`, level: "warn" } : { text: "The daemon is no longer waiting for this app to close", level: "info" } };
877
+ }
878
+ if (frame.kind !== "executor") return NONE;
879
+ let { event, agentId } = frame, loop = frame.loop ?? event.loop ?? MAIN, payload = event.payload ?? {};
880
+ switch (event.type) {
881
+ case "text_delta":
882
+ case "text_delta_batch":
883
+ case "thinking_delta":
884
+ case "thinking_delta_batch": {
885
+ let text = deltaText(payload);
886
+ if (!text) return NONE;
887
+ let kind = event.type.startsWith("thinking") ? "thinking" : "text", delta = {
888
+ seq: frame.cursor,
889
+ event_type: "turn.delta",
890
+ timestamp: event.timestamp,
891
+ source: `agent:${agentId}`,
892
+ agent_id: agentId,
893
+ ...loop !== MAIN ? { loop } : {},
894
+ payload: { kind, text }
895
+ };
896
+ return { frames: [{ cursor: frame.cursor, event: delta, synthetic: !0 }] };
897
+ }
898
+ case "tool_call_result": {
899
+ if (frame.stripped) return NONE;
900
+ let id = typeof payload.id == "string" ? payload.id : void 0, result = payload.result;
901
+ return !id || typeof result?.content != "string" ? NONE : { frames: [], toolResult: { agentId, loop, toolUseId: id, result: result.content, isError: result.isError === !0 } };
902
+ }
903
+ case "chat_updated":
904
+ return { frames: [], reload: { agentId, loop } };
905
+ default:
906
+ return NONE;
907
+ }
908
+ }
909
+ function deltaText(payload) {
910
+ return Array.isArray(payload.deltas) ? payload.deltas.filter((d) => typeof d == "string").join("") : typeof payload.delta == "string" ? payload.delta : typeof payload.text == "string" ? payload.text : "";
911
+ }
912
+
811
913
  // src/main/tui/web/model.ts
812
914
  var isRecord = (v) => typeof v == "object" && v !== null && !Array.isArray(v);
813
915
  function parseServer(raw) {
@@ -892,13 +994,14 @@ function serverText(server) {
892
994
  }
893
995
 
894
996
  // src/main/tui/state/store.tsx
895
- var import_jsx_runtime = __toESM(require_jsx_runtime(), 1), REFRESH_DEBOUNCE_MS = 120, WEB_EVENT_DEBOUNCE_MS = 900, RESUME_VERDICT_MS = 1500, WEB_POLL_MS = 2e4, TRACKED_POLL_MS = 15e3, FOLDER_OVERLAY = "fleet.track", PROMPT_PREFILL_KEY = "shell.prompt.prefill", CHAT_VIEW_ID = "chat";
997
+ var import_jsx_runtime = __toESM(require_jsx_runtime(), 1), TUI_MIN_CLIENT_API_VERSION = 1, REFRESH_DEBOUNCE_MS = 120, WEB_EVENT_DEBOUNCE_MS = 900, RESUME_VERDICT_MS = 1500, WEB_POLL_MS = 2e4, TRACKED_POLL_MS = 15e3, FOLDER_OVERLAY = "fleet.track", PROMPT_PREFILL_KEY = "shell.prompt.prefill", CHAT_VIEW_ID = "chat";
896
998
  function createTuiStore(options) {
897
- 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, resumeFallback = null, getState = () => state, dispatch = (action) => {
999
+ let client = options.client, plain = options.client, current = new WeakSet([client]), pageSize = options.pageSize ?? 100, state = initialState(client.baseUrl, options.initialView), selectionRevision = 0, listeners = /* @__PURE__ */ new Set(), confirmResolvers = /* @__PURE__ */ new Map(), toastTimers = /* @__PURE__ */ new Map(), debounced = /* @__PURE__ */ new Map(), stream = null, sessionId = null, fallbackNoticed = !1, sessionRetry = !1, reopening = !1, focusSent, focusInFlight = !1, focusRetryAt = 0, lastResyncAt = 0, webTick = null, trackedTick = null, stopped = !1, needsResync = !1, resumeFallback = null, getState = () => state, dispatch = (action) => {
898
1000
  let next = tuiReducer(state, action);
899
1001
  if (next !== state) {
900
- state = next;
1002
+ action.type === "select/agent" && selectionRevision++, state = next;
901
1003
  for (let listener of listeners) listener();
1004
+ sessionId && desiredFocus() !== focusSent && syncFocus();
902
1005
  }
903
1006
  }, subscribe = (listener) => (listeners.add(listener), () => {
904
1007
  listeners.delete(listener);
@@ -919,9 +1022,21 @@ function createTuiStore(options) {
919
1022
  err instanceof DaemonError && err.unreachable && dispatch({ type: "daemon/reachable", reachable: !1 }), toast(`${label}: ${describe(err)}`, "error");
920
1023
  return;
921
1024
  }
922
- }, selectedLoopOf = (agentId) => state.selectedLoop[agentId] ?? MAIN_LOOP, stale = (c) => c !== client, actions = {
1025
+ }, selectedLoopOf = (agentId) => state.selectedLoop[agentId] ?? MAIN_LOOP, stale = (c) => !current.has(c), settleBackgroundTasks = (c, agentId, key) => {
1026
+ for (let { toolUseId, taskId } of unresolvedTasks(state.transcripts[key]?.items ?? []))
1027
+ c.task(agentId, taskId).then(
1028
+ (result) => {
1029
+ stale(c) || dispatch({ type: "tool/task", key, toolUseId, task: result.task });
1030
+ },
1031
+ (err) => {
1032
+ !stale(c) && err instanceof DaemonError && err.status === 404 && dispatch({ type: "tool/task", key, toolUseId, task: null });
1033
+ }
1034
+ );
1035
+ }, useSession = (id) => {
1036
+ client = id ? plain.withClientSession(id) : plain, current.add(client);
1037
+ }, actions = {
923
1038
  async setDaemonUrl(url, token) {
924
- let next = client.withBaseUrl(url, token);
1039
+ let next = plain.withBaseUrl(url, token);
925
1040
  if (next.baseUrl === client.baseUrl && token === void 0)
926
1041
  return toast(`Already connected to ${next.baseUrl}`, "info"), !0;
927
1042
  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);
@@ -931,9 +1046,9 @@ function createTuiStore(options) {
931
1046
  return toast(`Not switching: ${next.baseUrl} is not answering (${describe(err)}). Still on ${client.baseUrl}.`, "error"), !1;
932
1047
  }
933
1048
  let previous = client.baseUrl;
934
- stream?.close(), stream = null;
1049
+ stream?.close(), stream = null, endSession(client);
935
1050
  for (let timer of debounced.values()) clearTimeout(timer);
936
- 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;
1051
+ return debounced.clear(), client = next, plain = next, current = new WeakSet([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;
937
1052
  },
938
1053
  async refreshAgents() {
939
1054
  let c = client;
@@ -1051,7 +1166,7 @@ function createTuiStore(options) {
1051
1166
  return toast(`${agent.name}: its identity is password-protected. Load it with /load ${filePath} and unlock it`, "warn", 8e3), null;
1052
1167
  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);
1053
1168
  if (agent.status === "needs_review") return review();
1054
- let start2 = options2.start ?? !0, c = client;
1169
+ let start2 = options2.start ?? !0, selectionAtStart = selectionRevision, c = client;
1055
1170
  dispatch({ type: "tracked/busy", filePath, busy: "loading" }), dispatch({ type: "tracked/file-error", filePath, error: void 0 });
1056
1171
  let ref;
1057
1172
  try {
@@ -1073,8 +1188,10 @@ function createTuiStore(options) {
1073
1188
  if (dispatch({ type: "tracked/busy", filePath, busy: void 0 }), stale(c)) return null;
1074
1189
  let text = `Loaded ${name}${started}`;
1075
1190
  toast(text, level, 5e3);
1076
- let wasSelected = state.selectedAgentId === key || state.selectedAgentId === entry.key;
1077
- 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;
1191
+ let selectedBefore = state.selectedAgentId, wasSelected = selectedBefore === key || selectedBefore === entry.key;
1192
+ await actions.refreshAgents(), actions.refreshTracked();
1193
+ let current2 = state.selectedAgentId, untouched = current2 === selectedBefore || current2 === ref.id;
1194
+ return selectionRevision === selectionAtStart && untouched && (wasSelected || !selectedBefore || isTrackedKey(selectedBefore)) && state.agents[ref.id] && actions.selectAgent(ref.id), actions.notice(ref.id, MAIN_LOOP, text, level === "success" ? "info" : "warn"), ref.id;
1078
1195
  },
1079
1196
  selectAgent(agentId) {
1080
1197
  dispatch({ type: "select/agent", agentId }), !isTrackedKey(agentId) && agentId && (actions.ensureTranscript(agentId, selectedLoopOf(agentId)), state.agents[agentId]?.config || actions.loadConfig(agentId));
@@ -1126,7 +1243,8 @@ function createTuiStore(options) {
1126
1243
  dispatch({ type: "transcript/loading", key });
1127
1244
  try {
1128
1245
  let page = await c.loopHistory(agentId, { loop, limit: pageSize });
1129
- stale(c) || dispatch({ type: "transcript/history", key, entries: page.entries, total: page.total, offset: page.offset, mode: "replace" });
1246
+ if (stale(c)) return;
1247
+ dispatch({ type: "transcript/history", key, entries: page.entries, total: page.total, offset: page.offset, mode: "replace" }), settleBackgroundTasks(c, agentId, key);
1130
1248
  } catch (err) {
1131
1249
  stale(c) || dispatch({ type: "transcript/error", key, error: describe(err) });
1132
1250
  }
@@ -1138,7 +1256,8 @@ function createTuiStore(options) {
1138
1256
  dispatch({ type: "transcript/loading", key });
1139
1257
  try {
1140
1258
  let page = await c.loopHistory(agentId, { loop, limit, offset });
1141
- stale(c) || dispatch({ type: "transcript/history", key, entries: page.entries, total: page.total, offset: page.offset, mode: "prepend" });
1259
+ if (stale(c)) return;
1260
+ dispatch({ type: "transcript/history", key, entries: page.entries, total: page.total, offset: page.offset, mode: "prepend" }), settleBackgroundTasks(c, agentId, key);
1142
1261
  } catch (err) {
1143
1262
  stale(c) || dispatch({ type: "transcript/error", key, error: describe(err) });
1144
1263
  }
@@ -1223,7 +1342,7 @@ function createTuiStore(options) {
1223
1342
  }
1224
1343
  },
1225
1344
  async logoutSubscription(provider) {
1226
- let label = provider === "chatgpt" ? "ChatGPT" : "Grok", result = await run(`Sign out of ${label}`, (c) => c.logoutSubscription(provider));
1345
+ let label = { chatgpt: "ChatGPT", grok: "Grok", claude: "Claude" }[provider], result = await run(`Sign out of ${label}`, (c) => c.logoutSubscription(provider));
1227
1346
  return result && toast(`Signed the daemon out of ${label}`, "success"), await actions.refreshAuth(), !!result;
1228
1347
  },
1229
1348
  async refreshWeb() {
@@ -1386,40 +1505,132 @@ function createTuiStore(options) {
1386
1505
  } catch {
1387
1506
  dispatch({ type: "daemon/reachable", reachable: !1 });
1388
1507
  }
1389
- options.live !== !1 && (stream = client.events({
1390
- onEvent: onFrame,
1391
- onState: (info) => {
1392
- dispatch({ type: "connection", info }), info.state === "reconnecting" && (needsResync = !0, info.error && dispatch({ type: "daemon/reachable", reachable: !1 })), info.state === "open" && info.resumed ? (needsResync = !1, resumeFallback && clearTimeout(resumeFallback), resumeFallback = setTimeout(() => {
1393
- resumeFallback = null, toast("Reconnected to daemon \u2014 resyncing", "info", 2500), resync();
1394
- }, RESUME_VERDICT_MS)) : info.state === "open" && needsResync && (needsResync = !1, toast("Connected to daemon", "info", 2500), resync());
1395
- },
1396
- onResume: (info) => {
1397
- if (resumeFallback && (clearTimeout(resumeFallback), resumeFallback = null), info.exact) {
1398
- toast("Reconnected to daemon \u2014 no events missed", "info", 2500), Promise.all([actions.refreshIdentity(), actions.refreshAuth(), actions.refreshAgents(), actions.refreshWeb()]);
1399
- return;
1400
- }
1401
- toast(info.reason === "epoch_changed" ? "The daemon restarted \u2014 reloading" : "Events were missed while disconnected \u2014 reloading", "warn", 4e3), resync();
1402
- }
1403
- }).start(), webTick && clearInterval(webTick), webTick = setInterval(() => {
1508
+ let opening = Promise.resolve();
1509
+ options.live !== !1 && (opening = openStream(), webTick && clearInterval(webTick), webTick = setInterval(() => {
1404
1510
  stopped || actions.refreshWeb();
1405
1511
  }, WEB_POLL_MS), trackedTick && clearInterval(trackedTick), trackedTick = setInterval(() => {
1406
1512
  !stopped && state.daemonReachable !== !1 && actions.refreshTracked();
1407
- }, TRACKED_POLL_MS)), await Promise.all([actions.refreshIdentity(), actions.refreshAuth(), actions.refreshAgents(), actions.refreshWeb()]), await actions.refreshTracked();
1513
+ }, TRACKED_POLL_MS)), await Promise.all([opening, actions.refreshIdentity(), actions.refreshAuth(), actions.refreshAgents(), actions.refreshWeb()]), await actions.refreshTracked();
1514
+ }
1515
+ function onStreamState(info) {
1516
+ if (dispatch({ type: "connection", info }), info.state === "reconnecting" && (needsResync = !0, info.error && dispatch({ type: "daemon/reachable", reachable: !1 }), sessionId && info.error?.startsWith("HTTP 404") && reopenSession()), info.state === "open" && sessionRetry && !sessionId) {
1517
+ sessionRetry = !1, reopenSession();
1518
+ return;
1519
+ }
1520
+ info.state === "open" && info.resumed ? (needsResync = !1, resumeFallback && clearTimeout(resumeFallback), resumeFallback = setTimeout(() => {
1521
+ resumeFallback = null, toast("Reconnected to daemon \u2014 resyncing", "info", 2500), resync();
1522
+ }, RESUME_VERDICT_MS)) : info.state === "open" && needsResync && (needsResync = !1, toast("Connected to daemon", "info", 2500), resync());
1523
+ }
1524
+ function onStreamResume(info) {
1525
+ if (resumeFallback && (clearTimeout(resumeFallback), resumeFallback = null), info.exact) {
1526
+ toast("Reconnected to daemon \u2014 no events missed", "info", 2500), Promise.all([actions.refreshIdentity(), actions.refreshAuth(), actions.refreshAgents(), actions.refreshWeb()]);
1527
+ return;
1528
+ }
1529
+ toast(info.reason === "epoch_changed" ? "The daemon restarted \u2014 reloading" : "Events were missed while disconnected \u2014 reloading", "warn", 4e3), resync();
1530
+ }
1531
+ function onStreamGap(gap) {
1532
+ Date.now() - lastResyncAt < RESUME_VERDICT_MS || (toast(`${gap.dropped ? `${gap.dropped} live event${gap.dropped === 1 ? " was" : "s were"}` : "Live events were"} dropped \u2014 reloading`, "warn", 4e3), resync());
1533
+ }
1534
+ function onClientFrame(frame) {
1535
+ let effects = clientFrameEffects(frame);
1536
+ for (let envelope of effects.frames) onFrame(envelope);
1537
+ if (effects.toolResult) {
1538
+ flushFrames();
1539
+ let { agentId, loop, toolUseId, result, isError } = effects.toolResult;
1540
+ dispatch({ type: "tool/result", key: transcriptKey(agentId, loop), toolUseId, result, isError });
1541
+ }
1542
+ if (effects.notice && toast(effects.notice.text, effects.notice.level, effects.notice.level === "warn" ? 1e4 : 4e3), effects.reload) {
1543
+ let { agentId, loop } = effects.reload, key = transcriptKey(agentId, loop);
1544
+ state.transcripts[key]?.loaded && debounce(`t:${key}`, () => {
1545
+ actions.loadTranscript(agentId, loop);
1546
+ });
1547
+ }
1548
+ }
1549
+ function noticeFallback(reason) {
1550
+ fallbackNoticed || (fallbackNoticed = !0, dispatch({ type: "activity/note", kind: "client.fallback", text: `Live events over /events: ${reason}. Token streaming follows each agent's umbilical.stream_deltas.` }));
1551
+ }
1552
+ async function openSession(c) {
1553
+ try {
1554
+ let version = (await c.version()).clientApiVersion;
1555
+ if (typeof version != "number" || version < TUI_MIN_CLIENT_API_VERSION || version > SUPPORTED_CLIENT_API_VERSION)
1556
+ return noticeFallback(`the daemon speaks client API ${version}, this app ${TUI_MIN_CLIENT_API_VERSION}-${SUPPORTED_CLIENT_API_VERSION}`), null;
1557
+ } catch (err) {
1558
+ return err instanceof DaemonError && err.unreachable ? (sessionRetry = !0, null) : (noticeFallback(err instanceof DaemonError && err.status === 404 ? "the daemon has no client sessions (an older version)" : `GET /version failed (${describe(err)})`), null);
1559
+ }
1560
+ try {
1561
+ return (await c.createClientSession({ client: "tui", version: options.clientVersion ?? process.env.ADF_VERSION ?? "dev", umbilical: !0 })).sessionId;
1562
+ } catch (err) {
1563
+ return err instanceof DaemonError && err.unreachable ? (sessionRetry = !0, null) : (noticeFallback(err instanceof DaemonError && err.status === 404 ? "the daemon has no client sessions (an older version)" : `opening a client session failed (${describe(err)})`), null);
1564
+ }
1565
+ }
1566
+ async function openStream() {
1567
+ let c = plain, id = options.clientSessions === !1 ? null : await openSession(c);
1568
+ if (stale(c) || stopped) {
1569
+ id && c.endClientSession(id).catch(() => {
1570
+ });
1571
+ return;
1572
+ }
1573
+ sessionId = id, useSession(id), focusSent = void 0, id ? (stream = c.clientSessionEvents(id, { onEvent: onClientFrame, onState: onStreamState, onResume: onStreamResume, onGap: onStreamGap }).start(), syncFocus()) : stream = c.events({ onEvent: onFrame, onState: onStreamState, onResume: onStreamResume }).start();
1574
+ }
1575
+ async function reopenSession() {
1576
+ if (!(reopening || stopped)) {
1577
+ reopening = !0;
1578
+ try {
1579
+ let hadSession = sessionId !== null;
1580
+ if (stream?.close(), stream = null, sessionId = null, useSession(null), await openStream(), stopped) return;
1581
+ hadSession && toast("The daemon no longer had this app's client session \u2014 reopened, reloading", "warn", 4e3), await resync();
1582
+ } finally {
1583
+ reopening = !1;
1584
+ }
1585
+ }
1586
+ }
1587
+ function desiredFocus() {
1588
+ let id = state.selectedAgentId;
1589
+ return state.activeView === CHAT_VIEW_ID && id && !isTrackedKey(id) ? id : null;
1590
+ }
1591
+ async function syncFocus() {
1592
+ if (!sessionId || focusInFlight || Date.now() < focusRetryAt) return;
1593
+ let want = desiredFocus();
1594
+ if (want === focusSent) return;
1595
+ let id = sessionId, c = client;
1596
+ focusInFlight = !0;
1597
+ try {
1598
+ await c.setClientSessionFocus(id, want), sessionId === id && (focusSent = want);
1599
+ } catch {
1600
+ focusRetryAt = Date.now() + 2e3;
1601
+ } finally {
1602
+ focusInFlight = !1;
1603
+ }
1604
+ sessionId === id && desiredFocus() !== focusSent && syncFocus();
1605
+ }
1606
+ function endSession(c) {
1607
+ let id = sessionId;
1608
+ return sessionId = null, c === client && useSession(null), focusSent = void 0, id ? c.endClientSession(id).then(() => {
1609
+ }, () => {
1610
+ }) : Promise.resolve();
1408
1611
  }
1409
1612
  async function resync() {
1410
- await Promise.all([actions.refreshIdentity(), actions.refreshAuth(), actions.refreshAgents(), actions.refreshWeb()]), actions.refreshTracked();
1613
+ lastResyncAt = Date.now(), await Promise.all([actions.refreshIdentity(), actions.refreshAuth(), actions.refreshAgents(), actions.refreshWeb()]), actions.refreshTracked();
1411
1614
  for (let key of Object.keys(state.transcripts)) {
1412
1615
  let at = key.indexOf("\0"), agentId = key.slice(0, at);
1413
1616
  state.agents[agentId] && state.transcripts[key].loaded && actions.loadTranscript(agentId, key.slice(at + 1));
1414
1617
  }
1415
1618
  }
1416
1619
  function stop() {
1417
- stopped = !0, stream?.close(), stream = null, resumeFallback && (clearTimeout(resumeFallback), resumeFallback = null), webTick && (clearInterval(webTick), webTick = null), trackedTick && (clearInterval(trackedTick), trackedTick = null), pendingFrames = [];
1620
+ stopped = !0, stream?.close(), stream = null;
1621
+ let ended = endSession(client);
1622
+ resumeFallback && (clearTimeout(resumeFallback), resumeFallback = null), webTick && (clearInterval(webTick), webTick = null), trackedTick && (clearInterval(trackedTick), trackedTick = null), pendingFrames = [];
1418
1623
  for (let timer of toastTimers.values()) clearTimeout(timer);
1419
1624
  for (let timer of debounced.values()) clearTimeout(timer);
1420
1625
  toastTimers.clear(), debounced.clear();
1421
1626
  for (let resolve of confirmResolvers.values()) resolve(!1);
1422
- confirmResolvers.clear();
1627
+ return confirmResolvers.clear(), ended;
1628
+ }
1629
+ async function close() {
1630
+ let ended = stop(), timer;
1631
+ await Promise.race([ended, new Promise((resolve) => {
1632
+ timer = setTimeout(resolve, 1e3);
1633
+ })]), timer && clearTimeout(timer);
1423
1634
  }
1424
1635
  function resolveConfirm(id, confirmed) {
1425
1636
  let resolve = confirmResolvers.get(id);
@@ -1434,7 +1645,13 @@ function createTuiStore(options) {
1434
1645
  dispatch,
1435
1646
  subscribe,
1436
1647
  start,
1437
- stop,
1648
+ stop: () => {
1649
+ stop();
1650
+ },
1651
+ close,
1652
+ get liveMode() {
1653
+ return sessionId ? "session" : stream ? "events" : "none";
1654
+ },
1438
1655
  resolveConfirm
1439
1656
  };
1440
1657
  }
@@ -1477,6 +1694,9 @@ function shallowEqual(a, b) {
1477
1694
  }
1478
1695
 
1479
1696
  export {
1697
+ MAIN_LOOP,
1698
+ DaemonError,
1699
+ isCredentialsLocked,
1480
1700
  emptyTranscript,
1481
1701
  isAsyncInput,
1482
1702
  askQuestion,
@@ -1495,6 +1715,7 @@ export {
1495
1715
  SERVER_STOPPED_TEXT,
1496
1716
  serverBadge,
1497
1717
  serverText,
1718
+ TUI_MIN_CLIENT_API_VERSION,
1498
1719
  PROMPT_PREFILL_KEY,
1499
1720
  createTuiStore,
1500
1721
  StoreProvider,