@agentdocumentformat/cli 0.7.8 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/adf.mjs +59 -8
- package/dist/chunks/{APEv2Parser-2CNNHMXV.mjs → APEv2Parser-WIXRJLHB.mjs} +2 -2
- package/dist/chunks/{AiffParser-7BR4RL6G.mjs → AiffParser-ZC4QFOVJ.mjs} +5 -5
- package/dist/chunks/{App-7RIIOHJJ.mjs → App-4AZZJNN2.mjs} +917 -826
- package/dist/chunks/{DsdiffParser-CMD4AX7A.mjs → DsdiffParser-UAPAJHFX.mjs} +5 -5
- package/dist/chunks/{DsfParser-UOGZDS2M.mjs → DsfParser-NNYZK2QX.mjs} +6 -6
- package/dist/chunks/{FlacParser-HB3T3CD4.mjs → FlacParser-MW2W4LO3.mjs} +6 -6
- package/dist/chunks/{MP4Parser-66HBRUSX.mjs → MP4Parser-Z57SYOOQ.mjs} +4 -4
- package/dist/chunks/{MpegParser-YW6LIUEW.mjs → MpegParser-XIIPAZVM.mjs} +7 -7
- package/dist/chunks/{MusepackParser-PAUSXP7D.mjs → MusepackParser-QWNDEYHJ.mjs} +6 -6
- package/dist/chunks/{OggParser-NUBV3GWC.mjs → OggParser-WRX53F77.mjs} +9 -9
- package/dist/chunks/{WavPackParser-WQAGT7TC.mjs → WavPackParser-MJ7WCSJ5.mjs} +2 -2
- package/dist/chunks/{WaveParser-EWLQVDX4.mjs → WaveParser-RAVLHZ5S.mjs} +7 -7
- package/dist/chunks/{adf-schema-US4NFHMR.mjs → adf-schema-AIPBQTR2.mjs} +9 -3
- package/dist/chunks/auth-manager-AJ32FZWS.mjs +19 -0
- package/dist/chunks/auth-manager-C5OBEQK2.mjs +18 -0
- package/dist/chunks/auth-manager-TBNKCJ45.mjs +17 -0
- package/dist/chunks/{chatgpt-subscription-E4MXTIAT.mjs → chatgpt-subscription-MMGNW5KJ.mjs} +5 -2
- package/dist/chunks/chunk-2Z7X3UUR.mjs +678 -0
- package/dist/chunks/chunk-3UGZFWIF.mjs +26 -0
- package/dist/chunks/{chunk-XNPZBLYL.mjs → chunk-75DC5EWN.mjs} +13 -2
- package/dist/chunks/{chunk-5PO5PKRV.mjs → chunk-7JZXMDDF.mjs} +158 -67
- package/dist/chunks/chunk-AEAJDCVK.mjs +517 -0
- package/dist/chunks/{chunk-6VQEXLE2.mjs → chunk-BHY7QDCM.mjs} +41 -3
- package/dist/chunks/{chunk-CD3ATSXE.mjs → chunk-BR3AD5QZ.mjs} +8 -2
- package/dist/chunks/chunk-BS3USVEA.mjs +301 -0
- package/dist/chunks/chunk-C2S64Y6F.mjs +203 -0
- package/dist/chunks/chunk-D7A77SNL.mjs +976 -0
- package/dist/chunks/chunk-DDTTSKGG.mjs +2443 -0
- package/dist/chunks/{chunk-VAUOM3IN.mjs → chunk-DLWCKKIO.mjs} +1 -1
- package/dist/chunks/{chunk-G6PH7RPW.mjs → chunk-E7LC6SHP.mjs} +3 -3
- package/dist/chunks/{chunk-ZESQMP66.mjs → chunk-F3WSCAJD.mjs} +3 -3
- package/dist/chunks/{chunk-KXEF4F4E.mjs → chunk-GAZO6UMI.mjs} +1 -1
- package/dist/chunks/{chunk-XYTWGHFS.mjs → chunk-H3XLRWVE.mjs} +1 -1
- package/dist/chunks/{chunk-7T2YMTWL.mjs → chunk-H4C65MTP.mjs} +4 -4
- package/dist/chunks/chunk-HBOFZRUS.mjs +738 -0
- package/dist/chunks/{chunk-VN7UH7I5.mjs → chunk-IMVMSU3A.mjs} +251 -68
- package/dist/chunks/{chunk-XYV3VCIX.mjs → chunk-JZFONJSL.mjs} +79 -20
- package/dist/chunks/chunk-KCIRFUZH.mjs +12799 -0
- package/dist/chunks/chunk-KDDVQKCG.mjs +65 -0
- package/dist/chunks/chunk-KRPKWOMB.mjs +290 -0
- package/dist/chunks/chunk-LKFHERRV.mjs +145 -0
- package/dist/chunks/chunk-LTX74NU6.mjs +29 -0
- package/dist/chunks/{chunk-HSBV6YFU.mjs → chunk-LVF2DRBR.mjs} +634 -99
- package/dist/chunks/chunk-M2F7C2UJ.mjs +425 -0
- package/dist/chunks/{chunk-62NE4LG4.mjs → chunk-MQAMI5BF.mjs} +5 -5
- package/dist/chunks/chunk-MZRXFWPQ.mjs +278 -0
- package/dist/chunks/{chunk-PRMGZZM5.mjs → chunk-NZLEPJ5M.mjs} +2 -0
- package/dist/chunks/{chunk-I3UYSITV.mjs → chunk-O7XKQ6CH.mjs} +1 -1
- package/dist/chunks/chunk-P3RG5LQA.mjs +244 -0
- package/dist/chunks/chunk-PAK5JCO2.mjs +48 -0
- package/dist/chunks/chunk-PC63YFB7.mjs +34 -0
- package/dist/chunks/{daemon-control-HKFVSQTQ.mjs → chunk-RHBGCOS3.mjs} +67 -26
- package/dist/chunks/{chunk-J74STFKE.mjs → chunk-RJDOVMM4.mjs} +362 -58
- package/dist/chunks/{chunk-QPLEAE6V.mjs → chunk-SOSPQPEN.mjs} +167 -650
- package/dist/chunks/{chunk-LFMB4PAA.mjs → chunk-TKXIH27X.mjs} +974 -113
- package/dist/chunks/{chunk-5W7KES6P.mjs → chunk-UZPDETEU.mjs} +1 -1
- package/dist/chunks/chunk-V3MM6PCH.mjs +366 -0
- package/dist/chunks/chunk-VENQBMOA.mjs +62 -0
- package/dist/chunks/chunk-WJGPNHGX.mjs +67 -0
- package/dist/chunks/{chunk-Y5ZLKFLE.mjs → chunk-XNNJQCZP.mjs} +196 -165
- package/dist/chunks/{chunk-HDBPBORT.mjs → chunk-YRBFIDLB.mjs} +46 -10
- package/dist/chunks/{chunk-BNXUAOO4.mjs → chunk-ZGXUOAWZ.mjs} +3186 -959
- package/dist/chunks/chunk-ZPB3HYM7.mjs +45 -0
- package/dist/chunks/claude-subscription-EB4LAAVV.mjs +29 -0
- package/dist/chunks/{cli-NMFIAR7Z.mjs → cli-PCVFB6B4.mjs} +797 -56
- package/dist/chunks/{commands-KPJWFRUE.mjs → commands-KOMPXJZS.mjs} +4 -3
- package/dist/chunks/{daemon-YDIK3AAM.mjs → daemon-BVDB565V.mjs} +83142 -64424
- package/dist/chunks/daemon-control-MKN7G5M3.mjs +59 -0
- package/dist/chunks/{daemon-token-WRSULP7G.mjs → daemon-token-L5QKTHU5.mjs} +3 -1
- package/dist/chunks/{discord-DSP4HUWI.mjs → discord-IR62565M.mjs} +3 -52
- package/dist/chunks/{email-BRG7KUO2.mjs → email-KHHTJBDW.mjs} +4 -2
- package/dist/chunks/{grok-subscription-4PYX7TBF.mjs → grok-subscription-E74FS5EG.mjs} +5 -2
- package/dist/chunks/{layout-EPJQNFAI.mjs → layout-ECWGJF6M.mjs} +2 -2
- package/dist/chunks/{lib-N7FCZWKH.mjs → lib-L27L5PXM.mjs} +22 -22
- package/dist/chunks/{open-VAU7PXT6.mjs → open-3OR6WT4T.mjs} +6 -6
- package/dist/chunks/{parser-JVY2PWSM.mjs → parser-7GARNT5L.mjs} +1 -1
- package/dist/chunks/{pipeline-executor-O77NTGLP.mjs → pipeline-executor-DRYEEFDR.mjs} +6 -5
- package/dist/chunks/prompt-RRHZX4YT.mjs +13 -0
- package/dist/chunks/remote-access-cli-GLEEP7DI.mjs +268 -0
- package/dist/chunks/remote-hello-UFWUBDQI.mjs +37 -0
- package/dist/chunks/sdk-OJOAF4DP.mjs +30014 -0
- package/dist/chunks/{slack-OCNNF4DX.mjs → slack-IYC5RAB5.mjs} +3 -4
- package/dist/chunks/{store-HUVDJPYN.mjs → store-55CQSAOX.mjs} +7 -3
- package/dist/chunks/tailscale-WLJATFMB.mjs +25 -0
- package/dist/chunks/{theme-SFE3JMA2.mjs → theme-HLBDTF6F.mjs} +1 -1
- package/dist/chunks/{themes-YLXLOIJF.mjs → themes-BQ72P446.mjs} +2 -2
- package/dist/chunks/{token-6G3HCMNX.mjs → token-6D22WECM.mjs} +20 -16
- package/dist/chunks/{token-util-UXYSDQIW.mjs → token-util-YF3ZWBZ4.mjs} +1 -2
- package/dist/chunks/{tui-UQJLK7XI.mjs → tui-RAUVFOYY.mjs} +21 -18
- package/dist/chunks/{welcome-XHXFV7SH.mjs → welcome-J5JZZAM5.mjs} +1 -1
- package/dist/chunks/{whatsapp-AJMRQBT7.mjs → whatsapp-YJFFVN4Q.mjs} +9 -9
- package/package.json +1 -1
- package/dist/chunks/chunk-GKKCMXIZ.mjs +0 -94
- package/dist/chunks/chunk-IHDDCZBS.mjs +0 -112
- package/dist/chunks/chunk-KWFOS5WC.mjs +0 -41
- package/dist/chunks/chunk-UEZR2CNS.mjs +0 -65
- package/dist/chunks/chunk-VMHTYDH4.mjs +0 -172
- package/dist/chunks/chunk-Y2QA53AN.mjs +0 -259
- package/dist/chunks/{chunk-NBTUWMGP.mjs → chunk-2MTE22CR.mjs} +3 -3
- package/dist/chunks/{chunk-APRU6PHC.mjs → chunk-JZ7AQNPM.mjs} +3 -3
- package/dist/chunks/{telegram-2EFGKIVK.mjs → telegram-JYY2VDTI.mjs} +5 -5
|
@@ -4,28 +4,38 @@ 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
|
-
loop_parser_exports
|
|
19
|
-
|
|
17
|
+
loop_parser_exports,
|
|
18
|
+
owner_command_row_exports
|
|
19
|
+
} from "./chunk-7JZXMDDF.mjs";
|
|
20
20
|
import {
|
|
21
21
|
require_react
|
|
22
22
|
} from "./chunk-6GJ4QHRI.mjs";
|
|
23
|
+
import {
|
|
24
|
+
file_ref_exports
|
|
25
|
+
} from "./chunk-LKFHERRV.mjs";
|
|
26
|
+
import {
|
|
27
|
+
agent_commands_exports
|
|
28
|
+
} from "./chunk-VENQBMOA.mjs";
|
|
23
29
|
import {
|
|
24
30
|
__toESM
|
|
25
31
|
} from "./chunk-M2RX3S2T.mjs";
|
|
26
32
|
|
|
27
33
|
// src/main/tui/state/store.tsx
|
|
28
34
|
var import_react = __toESM(require_react(), 1);
|
|
35
|
+
import { randomUUID } from "node:crypto";
|
|
36
|
+
|
|
37
|
+
// src/main/tui/api/types.ts
|
|
38
|
+
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;
|
|
29
39
|
|
|
30
40
|
// src/main/tui/state/tracked.ts
|
|
31
41
|
var TRACKED_PREFIX = "file:";
|
|
@@ -130,7 +140,14 @@ function reconcileSelection(state, previousSummaries = {}, trackedFresh = !1) {
|
|
|
130
140
|
}
|
|
131
141
|
|
|
132
142
|
// src/main/tui/state/transcript.ts
|
|
133
|
-
var MAX_TRANSCRIPT_ITEMS = 2e3, { parseLoopToDisplay } = cjs(loop_parser_exports),
|
|
143
|
+
var MAX_TRANSCRIPT_ITEMS = 2e3, { parseLoopToDisplay } = cjs(loop_parser_exports), { attachmentText } = cjs(file_ref_exports);
|
|
144
|
+
function withAttachments(text, attachments) {
|
|
145
|
+
if (!Array.isArray(attachments) || attachments.length === 0) return text;
|
|
146
|
+
let lines = attachments.map(attachmentText);
|
|
147
|
+
return [text, ...lines].filter(Boolean).join(`
|
|
148
|
+
`);
|
|
149
|
+
}
|
|
150
|
+
var localCounter = 0;
|
|
134
151
|
function localId(prefix = "l") {
|
|
135
152
|
return localCounter += 1, `${prefix}:${Date.now().toString(36)}:${localCounter}`;
|
|
136
153
|
}
|
|
@@ -151,6 +168,19 @@ function isTaskRef(text) {
|
|
|
151
168
|
return !1;
|
|
152
169
|
}
|
|
153
170
|
}
|
|
171
|
+
function taskRefId(text) {
|
|
172
|
+
if (isTaskRef(text))
|
|
173
|
+
return JSON.parse(text).task_id;
|
|
174
|
+
}
|
|
175
|
+
function unresolvedTasks(items) {
|
|
176
|
+
let out = [];
|
|
177
|
+
for (let item of items) {
|
|
178
|
+
if (item.kind !== "tool" || item.status !== "running" || !item.toolUseId) continue;
|
|
179
|
+
let taskId = taskRefId(item.taskRef);
|
|
180
|
+
taskId && out.push({ toolUseId: item.toolUseId, taskId });
|
|
181
|
+
}
|
|
182
|
+
return out;
|
|
183
|
+
}
|
|
154
184
|
function askQuestion(input) {
|
|
155
185
|
let q = input && typeof input == "object" ? input.question : void 0;
|
|
156
186
|
return typeof q == "string" ? q : "";
|
|
@@ -161,13 +191,19 @@ function historyToItems(entries) {
|
|
|
161
191
|
let meta = entry.metadata ?? {}, base = { id: `h:${entry.id}`, at: entry.timestamp, seq: typeof meta.seq == "number" ? meta.seq : void 0 };
|
|
162
192
|
switch (entry.type) {
|
|
163
193
|
case "user":
|
|
164
|
-
items.push({ ...base, kind: "user", text: entry.content, origin: "owner" });
|
|
194
|
+
items.push({ ...base, kind: "user", text: withAttachments(entry.content, meta.attachments), origin: "owner" });
|
|
165
195
|
break;
|
|
166
196
|
case "trigger":
|
|
167
197
|
items.push({ ...base, kind: "user", text: entry.content, origin: "runtime" });
|
|
168
198
|
break;
|
|
169
199
|
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: "
|
|
200
|
+
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({
|
|
201
|
+
...base,
|
|
202
|
+
kind: "context",
|
|
203
|
+
category: String(meta.category ?? "context"),
|
|
204
|
+
text: entry.content,
|
|
205
|
+
...meta.category === "owner_command" ? { ownerCommand: meta.ownerCommand } : {}
|
|
206
|
+
});
|
|
171
207
|
break;
|
|
172
208
|
case "compaction":
|
|
173
209
|
items.push({ ...base, kind: "context", category: "compaction", text: entry.content });
|
|
@@ -176,7 +212,7 @@ function historyToItems(entries) {
|
|
|
176
212
|
items.push({ ...base, kind: "error", text: entry.content });
|
|
177
213
|
break;
|
|
178
214
|
case "text":
|
|
179
|
-
items.push({ ...base, kind: "assistant", text: entry.content, streaming: !1, model: typeof meta.model == "string" ? meta.model : void 0 });
|
|
215
|
+
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
216
|
break;
|
|
181
217
|
case "thinking":
|
|
182
218
|
items.push({ ...base, kind: "thinking", text: entry.content, streaming: !1 });
|
|
@@ -196,7 +232,14 @@ function historyToItems(entries) {
|
|
|
196
232
|
}
|
|
197
233
|
case "tool_result": {
|
|
198
234
|
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
|
-
|
|
235
|
+
if (call) {
|
|
236
|
+
if (!meta.isError && isTaskRef(entry.content)) {
|
|
237
|
+
call.async = !0, call.taskRef = entry.content;
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
call.status = status, call.result = withAttachments(entry.content, meta.attachments), call.completedAt = entry.timestamp;
|
|
241
|
+
} else
|
|
242
|
+
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
243
|
break;
|
|
201
244
|
}
|
|
202
245
|
}
|
|
@@ -210,8 +253,8 @@ function mergeHistory(existing, incoming) {
|
|
|
210
253
|
let history = incoming.map((item) => {
|
|
211
254
|
if (item.kind !== "tool" || item.taskRef === void 0 || !item.toolUseId) return item;
|
|
212
255
|
let live = finished.get(item.toolUseId);
|
|
213
|
-
return
|
|
214
|
-
}), historyTools = /* @__PURE__ */ new Set(), historyTexts = /* @__PURE__ */ new Map(), countText = (key) => historyTexts.set(key, (historyTexts.get(key) ?? 0) + 1);
|
|
256
|
+
return live ? { ...item, status: live.status, result: live.result, completedAt: live.completedAt } : item;
|
|
257
|
+
}), historyTools = /* @__PURE__ */ new Set(), historyCommands = new Set(history.flatMap((item) => item.kind === "context" && item.ownerCommand ? [item.ownerCommand.id] : [])), historyTexts = /* @__PURE__ */ new Map(), countText = (key) => historyTexts.set(key, (historyTexts.get(key) ?? 0) + 1);
|
|
215
258
|
for (let item of history)
|
|
216
259
|
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
260
|
let consume = (key) => {
|
|
@@ -227,7 +270,7 @@ function mergeHistory(existing, incoming) {
|
|
|
227
270
|
case "thinking":
|
|
228
271
|
return !consume(`${item.kind}:${item.text.trim()}`);
|
|
229
272
|
case "context":
|
|
230
|
-
return !
|
|
273
|
+
return !!item.ownerCommand && !historyCommands.has(item.ownerCommand.id);
|
|
231
274
|
case "ask":
|
|
232
275
|
return !consume(`ask:${item.question.trim()}`);
|
|
233
276
|
default:
|
|
@@ -240,7 +283,9 @@ function prependHistory(existing, older) {
|
|
|
240
283
|
let ids = new Set(existing.map((item) => item.id)), orphans = /* @__PURE__ */ new Map();
|
|
241
284
|
for (let item of existing)
|
|
242
285
|
item.kind === "tool" && !item.local && item.toolUseId && item.status !== "running" && orphans.set(item.toolUseId, item);
|
|
243
|
-
let merged = /* @__PURE__ */ new Set();
|
|
286
|
+
let merged = /* @__PURE__ */ new Set(), commands = new Set(older.flatMap((item) => item.kind === "context" && item.ownerCommand ? [item.ownerCommand.id] : []));
|
|
287
|
+
for (let item of existing)
|
|
288
|
+
item.local && item.kind === "context" && item.ownerCommand && commands.has(item.ownerCommand.id) && (merged.add(item), ids.delete(item.id));
|
|
244
289
|
return [...older.filter((item) => !ids.has(item.id)).map((item) => {
|
|
245
290
|
if (item.kind !== "tool" || item.status !== "running" || !item.toolUseId) return item;
|
|
246
291
|
let result = orphans.get(item.toolUseId);
|
|
@@ -254,6 +299,9 @@ function finalizeStreaming(items) {
|
|
|
254
299
|
let changed = !1, next = items.map((item) => (item.kind === "assistant" || item.kind === "thinking") && item.streaming ? (changed = !0, { ...item, streaming: !1 }) : item);
|
|
255
300
|
return changed ? next : items;
|
|
256
301
|
}
|
|
302
|
+
function markInterrupted(items) {
|
|
303
|
+
return items.map((item) => item.kind === "assistant" && item.streaming ? { ...item, interrupted: !0 } : item);
|
|
304
|
+
}
|
|
257
305
|
function cap(items) {
|
|
258
306
|
return items.length > MAX_TRANSCRIPT_ITEMS ? items.slice(items.length - MAX_TRANSCRIPT_ITEMS) : items;
|
|
259
307
|
}
|
|
@@ -332,7 +380,7 @@ function applyEventToItems(items, event) {
|
|
|
332
380
|
return next[index] = { ...next[index], ...patch }, next;
|
|
333
381
|
}
|
|
334
382
|
case "turn.completed": {
|
|
335
|
-
let closed = finalizeStreaming(items), content = str(p.content)?.trim();
|
|
383
|
+
let closed = finalizeStreaming(p.interrupted === !0 && p.partial === !0 ? markInterrupted(items) : items), content = str(p.content)?.trim();
|
|
336
384
|
if (!content) return closed;
|
|
337
385
|
let lastUser = -1;
|
|
338
386
|
for (let i = closed.length - 1; i >= 0; i--) if (closed[i].kind === "user") {
|
|
@@ -346,7 +394,7 @@ function applyEventToItems(items, event) {
|
|
|
346
394
|
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
395
|
}
|
|
348
396
|
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";
|
|
397
|
+
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
398
|
if (index < 0)
|
|
351
399
|
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
400
|
let next = items.slice();
|
|
@@ -640,6 +688,13 @@ function tuiReducer(state, action) {
|
|
|
640
688
|
return patchTranscript(state, action.key, (t) => ({ ...t, loading: !1, error: action.error }));
|
|
641
689
|
case "transcript/append":
|
|
642
690
|
return patchTranscript(state, action.key, (t) => ({ ...t, items: [...t.items, action.item] }));
|
|
691
|
+
case "transcript/owner-command":
|
|
692
|
+
return patchTranscript(state, action.key, (t) => {
|
|
693
|
+
let matches = (item) => item.kind === "context" && item.ownerCommand?.id === action.item.ownerCommand?.id, existing = t.items.find(matches);
|
|
694
|
+
return existing?.seq !== void 0 && (action.item.seq === void 0 || existing.seq === action.item.seq) ? t : { ...t, items: [...t.items.filter((item) => !matches(item)), action.item] };
|
|
695
|
+
});
|
|
696
|
+
case "transcript/remove":
|
|
697
|
+
return patchTranscript(state, action.key, (t) => ({ ...t, items: t.items.filter((item) => item.id !== action.id || item.seq !== void 0) }));
|
|
643
698
|
case "transcript/update":
|
|
644
699
|
return patchTranscript(state, action.key, (t) => {
|
|
645
700
|
let index = t.items.findIndex((item) => item.id === action.id);
|
|
@@ -651,10 +706,31 @@ function tuiReducer(state, action) {
|
|
|
651
706
|
return patchTranscript(state, action.key, () => ({ ...emptyTranscript(), loaded: !0 }));
|
|
652
707
|
case "transcript/idle":
|
|
653
708
|
return patchTranscript(state, action.key, endLive);
|
|
709
|
+
case "tool/result":
|
|
710
|
+
return patchTranscript(state, action.key, (t) => {
|
|
711
|
+
let index = t.items.findIndex((item2) => item2.kind === "tool" && item2.toolUseId === action.toolUseId), item = t.items[index];
|
|
712
|
+
if (!item || item.kind !== "tool" || item.result === action.result) return t;
|
|
713
|
+
let items = t.items.slice();
|
|
714
|
+
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 });
|
|
715
|
+
});
|
|
716
|
+
case "tool/task":
|
|
717
|
+
return patchTranscript(state, action.key, (t) => {
|
|
718
|
+
let index = t.items.findIndex((item2) => item2.kind === "tool" && item2.toolUseId === action.toolUseId), item = t.items[index];
|
|
719
|
+
if (!item || item.kind !== "tool" || item.status !== "running") return t;
|
|
720
|
+
let task = action.task, patch;
|
|
721
|
+
if (!task) patch = { status: "ok", result: item.taskRef };
|
|
722
|
+
else if (task.status === "completed") patch = { status: "ok", result: task.result ?? "" };
|
|
723
|
+
else if (task.status === "failed" || task.status === "denied" || task.status === "cancelled") patch = { status: "error", result: task.error ?? task.result ?? task.status };
|
|
724
|
+
else return t;
|
|
725
|
+
let items = t.items.slice();
|
|
726
|
+
return items[index] = { ...item, ...patch, completedAt: task?.completed_at ?? item.at }, { ...t, items };
|
|
727
|
+
});
|
|
654
728
|
case "event":
|
|
655
|
-
return applyEvent(state, action.frame.event);
|
|
729
|
+
return applyEvent(state, action.frame.event, !isSynthetic(action.frame));
|
|
656
730
|
case "events":
|
|
657
|
-
return action.frames.reduce((next, frame) => applyEvent(next, frame.event), state);
|
|
731
|
+
return action.frames.reduce((next, frame) => applyEvent(next, frame.event, !isSynthetic(frame)), state);
|
|
732
|
+
case "activity/note":
|
|
733
|
+
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
734
|
case "viewState/set":
|
|
659
735
|
return { ...state, viewState: { ...state.viewState, [action.view]: action.value } };
|
|
660
736
|
default:
|
|
@@ -690,8 +766,11 @@ var TRANSCRIPT_EVENTS = /* @__PURE__ */ new Set([
|
|
|
690
766
|
"chat.delivered",
|
|
691
767
|
"chat.discarded"
|
|
692
768
|
]);
|
|
693
|
-
function
|
|
694
|
-
|
|
769
|
+
function isSynthetic(frame) {
|
|
770
|
+
return frame.synthetic === !0;
|
|
771
|
+
}
|
|
772
|
+
function applyEvent(state, event, log = !0) {
|
|
773
|
+
let agentId = event.agent_id ?? null, loop = eventLoop(event), next = log ? {
|
|
695
774
|
...state,
|
|
696
775
|
activity: pushBounded(state.activity, {
|
|
697
776
|
id: localId("a"),
|
|
@@ -702,7 +781,7 @@ function applyEvent(state, event) {
|
|
|
702
781
|
summary: summarizeEvent(event)
|
|
703
782
|
}, MAX_ACTIVITY),
|
|
704
783
|
lastEvents: pushBounded(state.lastEvents, event, MAX_LAST_EVENTS)
|
|
705
|
-
};
|
|
784
|
+
} : state;
|
|
706
785
|
if (!agentId || !next.agents[agentId]) return next;
|
|
707
786
|
let p = event.payload ?? {};
|
|
708
787
|
switch (event.event_type) {
|
|
@@ -808,6 +887,63 @@ function num(value) {
|
|
|
808
887
|
return typeof value == "number" && Number.isFinite(value) ? value : 0;
|
|
809
888
|
}
|
|
810
889
|
|
|
890
|
+
// src/main/tui/state/client-stream.ts
|
|
891
|
+
var { parseOwnerCommandRow } = cjs(owner_command_row_exports), TUI_CLIENT_NAME = "tui", MAIN = "main", NONE = { frames: [] };
|
|
892
|
+
function clientFrameEffects(frame) {
|
|
893
|
+
if (frame.kind === "umbilical") return { frames: [{ cursor: frame.cursor, event: frame.event }] };
|
|
894
|
+
if (frame.kind === "push" && frame.topic === "daemon_orphan_hold") {
|
|
895
|
+
let payload2 = frame.payload;
|
|
896
|
+
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" } };
|
|
897
|
+
}
|
|
898
|
+
if (frame.kind !== "executor") return NONE;
|
|
899
|
+
let { event, agentId } = frame, loop = frame.loop ?? event.loop ?? MAIN, payload = event.payload ?? {};
|
|
900
|
+
switch (event.type) {
|
|
901
|
+
case "context_injected": {
|
|
902
|
+
if (payload.category !== "owner_command") return NONE;
|
|
903
|
+
let record = typeof payload.content == "string" ? parseOwnerCommandRow(payload.content) : null;
|
|
904
|
+
return !record || typeof payload.seq != "number" ? { frames: [], reload: { agentId, loop } } : { frames: [], ownerCommand: { agentId, loop, item: {
|
|
905
|
+
id: `command:${record.header.id}`,
|
|
906
|
+
at: event.timestamp,
|
|
907
|
+
local: !0,
|
|
908
|
+
seq: payload.seq,
|
|
909
|
+
kind: "context",
|
|
910
|
+
category: "owner_command",
|
|
911
|
+
ownerCommand: record.header,
|
|
912
|
+
text: record.body
|
|
913
|
+
} } };
|
|
914
|
+
}
|
|
915
|
+
case "text_delta":
|
|
916
|
+
case "text_delta_batch":
|
|
917
|
+
case "thinking_delta":
|
|
918
|
+
case "thinking_delta_batch": {
|
|
919
|
+
let text = deltaText(payload);
|
|
920
|
+
if (!text) return NONE;
|
|
921
|
+
let kind = event.type.startsWith("thinking") ? "thinking" : "text", delta = {
|
|
922
|
+
seq: frame.cursor,
|
|
923
|
+
event_type: "turn.delta",
|
|
924
|
+
timestamp: event.timestamp,
|
|
925
|
+
source: `agent:${agentId}`,
|
|
926
|
+
agent_id: agentId,
|
|
927
|
+
...loop !== MAIN ? { loop } : {},
|
|
928
|
+
payload: { kind, text }
|
|
929
|
+
};
|
|
930
|
+
return { frames: [{ cursor: frame.cursor, event: delta, synthetic: !0 }] };
|
|
931
|
+
}
|
|
932
|
+
case "tool_call_result": {
|
|
933
|
+
if (frame.stripped) return NONE;
|
|
934
|
+
let id = typeof payload.id == "string" ? payload.id : void 0, result = payload.result;
|
|
935
|
+
return !id || typeof result?.content != "string" ? NONE : { frames: [], toolResult: { agentId, loop, toolUseId: id, result: result.content, isError: result.isError === !0 } };
|
|
936
|
+
}
|
|
937
|
+
case "chat_updated":
|
|
938
|
+
return { frames: [], reload: { agentId, loop } };
|
|
939
|
+
default:
|
|
940
|
+
return NONE;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
function deltaText(payload) {
|
|
944
|
+
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 : "";
|
|
945
|
+
}
|
|
946
|
+
|
|
811
947
|
// src/main/tui/web/model.ts
|
|
812
948
|
var isRecord = (v) => typeof v == "object" && v !== null && !Array.isArray(v);
|
|
813
949
|
function parseServer(raw) {
|
|
@@ -892,13 +1028,14 @@ function serverText(server) {
|
|
|
892
1028
|
}
|
|
893
1029
|
|
|
894
1030
|
// 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";
|
|
1031
|
+
var import_jsx_runtime = __toESM(require_jsx_runtime(), 1), { parseAuthorizeToken } = cjs(agent_commands_exports), 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
1032
|
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) => {
|
|
1033
|
+
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
1034
|
let next = tuiReducer(state, action);
|
|
899
1035
|
if (next !== state) {
|
|
900
|
-
state = next;
|
|
1036
|
+
action.type === "select/agent" && selectionRevision++, state = next;
|
|
901
1037
|
for (let listener of listeners) listener();
|
|
1038
|
+
sessionId && desiredFocus() !== focusSent && syncFocus();
|
|
902
1039
|
}
|
|
903
1040
|
}, subscribe = (listener) => (listeners.add(listener), () => {
|
|
904
1041
|
listeners.delete(listener);
|
|
@@ -919,9 +1056,21 @@ function createTuiStore(options) {
|
|
|
919
1056
|
err instanceof DaemonError && err.unreachable && dispatch({ type: "daemon/reachable", reachable: !1 }), toast(`${label}: ${describe(err)}`, "error");
|
|
920
1057
|
return;
|
|
921
1058
|
}
|
|
922
|
-
}, selectedLoopOf = (agentId) => state.selectedLoop[agentId] ?? MAIN_LOOP, stale = (c) => c
|
|
1059
|
+
}, selectedLoopOf = (agentId) => state.selectedLoop[agentId] ?? MAIN_LOOP, stale = (c) => !current.has(c), settleBackgroundTasks = (c, agentId, key) => {
|
|
1060
|
+
for (let { toolUseId, taskId } of unresolvedTasks(state.transcripts[key]?.items ?? []))
|
|
1061
|
+
c.task(agentId, taskId).then(
|
|
1062
|
+
(result) => {
|
|
1063
|
+
stale(c) || dispatch({ type: "tool/task", key, toolUseId, task: result.task });
|
|
1064
|
+
},
|
|
1065
|
+
(err) => {
|
|
1066
|
+
!stale(c) && err instanceof DaemonError && err.status === 404 && dispatch({ type: "tool/task", key, toolUseId, task: null });
|
|
1067
|
+
}
|
|
1068
|
+
);
|
|
1069
|
+
}, useSession = (id) => {
|
|
1070
|
+
client = id ? plain.withClientSession(id) : plain, current.add(client);
|
|
1071
|
+
}, actions = {
|
|
923
1072
|
async setDaemonUrl(url, token) {
|
|
924
|
-
let next =
|
|
1073
|
+
let next = plain.withBaseUrl(url, token);
|
|
925
1074
|
if (next.baseUrl === client.baseUrl && token === void 0)
|
|
926
1075
|
return toast(`Already connected to ${next.baseUrl}`, "info"), !0;
|
|
927
1076
|
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 +1080,9 @@ function createTuiStore(options) {
|
|
|
931
1080
|
return toast(`Not switching: ${next.baseUrl} is not answering (${describe(err)}). Still on ${client.baseUrl}.`, "error"), !1;
|
|
932
1081
|
}
|
|
933
1082
|
let previous = client.baseUrl;
|
|
934
|
-
stream?.close(), stream = null;
|
|
1083
|
+
stream?.close(), stream = null, endSession(client);
|
|
935
1084
|
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;
|
|
1085
|
+
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
1086
|
},
|
|
938
1087
|
async refreshAgents() {
|
|
939
1088
|
let c = client;
|
|
@@ -1051,7 +1200,7 @@ function createTuiStore(options) {
|
|
|
1051
1200
|
return toast(`${agent.name}: its identity is password-protected. Load it with /load ${filePath} and unlock it`, "warn", 8e3), null;
|
|
1052
1201
|
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
1202
|
if (agent.status === "needs_review") return review();
|
|
1054
|
-
let start2 = options2.start ?? !0, c = client;
|
|
1203
|
+
let start2 = options2.start ?? !0, selectionAtStart = selectionRevision, c = client;
|
|
1055
1204
|
dispatch({ type: "tracked/busy", filePath, busy: "loading" }), dispatch({ type: "tracked/file-error", filePath, error: void 0 });
|
|
1056
1205
|
let ref;
|
|
1057
1206
|
try {
|
|
@@ -1073,8 +1222,10 @@ function createTuiStore(options) {
|
|
|
1073
1222
|
if (dispatch({ type: "tracked/busy", filePath, busy: void 0 }), stale(c)) return null;
|
|
1074
1223
|
let text = `Loaded ${name}${started}`;
|
|
1075
1224
|
toast(text, level, 5e3);
|
|
1076
|
-
let
|
|
1077
|
-
|
|
1225
|
+
let selectedBefore = state.selectedAgentId, wasSelected = selectedBefore === key || selectedBefore === entry.key;
|
|
1226
|
+
await actions.refreshAgents(), actions.refreshTracked();
|
|
1227
|
+
let current2 = state.selectedAgentId, untouched = current2 === selectedBefore || current2 === ref.id;
|
|
1228
|
+
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
1229
|
},
|
|
1079
1230
|
selectAgent(agentId) {
|
|
1080
1231
|
dispatch({ type: "select/agent", agentId }), !isTrackedKey(agentId) && agentId && (actions.ensureTranscript(agentId, selectedLoopOf(agentId)), state.agents[agentId]?.config || actions.loadConfig(agentId));
|
|
@@ -1126,7 +1277,8 @@ function createTuiStore(options) {
|
|
|
1126
1277
|
dispatch({ type: "transcript/loading", key });
|
|
1127
1278
|
try {
|
|
1128
1279
|
let page = await c.loopHistory(agentId, { loop, limit: pageSize });
|
|
1129
|
-
stale(c)
|
|
1280
|
+
if (stale(c)) return;
|
|
1281
|
+
dispatch({ type: "transcript/history", key, entries: page.entries, total: page.total, offset: page.offset, mode: "replace" }), settleBackgroundTasks(c, agentId, key);
|
|
1130
1282
|
} catch (err) {
|
|
1131
1283
|
stale(c) || dispatch({ type: "transcript/error", key, error: describe(err) });
|
|
1132
1284
|
}
|
|
@@ -1138,7 +1290,8 @@ function createTuiStore(options) {
|
|
|
1138
1290
|
dispatch({ type: "transcript/loading", key });
|
|
1139
1291
|
try {
|
|
1140
1292
|
let page = await c.loopHistory(agentId, { loop, limit, offset });
|
|
1141
|
-
stale(c)
|
|
1293
|
+
if (stale(c)) return;
|
|
1294
|
+
dispatch({ type: "transcript/history", key, entries: page.entries, total: page.total, offset: page.offset, mode: "prepend" }), settleBackgroundTasks(c, agentId, key);
|
|
1142
1295
|
} catch (err) {
|
|
1143
1296
|
stale(c) || dispatch({ type: "transcript/error", key, error: describe(err) });
|
|
1144
1297
|
}
|
|
@@ -1163,6 +1316,45 @@ function createTuiStore(options) {
|
|
|
1163
1316
|
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;
|
|
1164
1317
|
}
|
|
1165
1318
|
},
|
|
1319
|
+
async runAgentCommand(agentId, loop, name, rawArgs) {
|
|
1320
|
+
let c = client;
|
|
1321
|
+
if (isTrackedKey(agentId)) {
|
|
1322
|
+
toast(`Agent is off. Start it, then run /${name} again.`, "warn");
|
|
1323
|
+
return;
|
|
1324
|
+
}
|
|
1325
|
+
if (rawArgs.includes(`
|
|
1326
|
+
`) || rawArgs.includes("\r") || rawArgs.length > 4096) {
|
|
1327
|
+
toast(`/${name}: arguments must be one line of at most 4096 characters.`, "warn");
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
let { args, authorize } = parseAuthorizeToken(rawArgs), requestId = randomUUID(), key = transcriptKey(agentId, loop), registered = state.agents[agentId]?.config?.commands, lambda = Array.isArray(registered) ? registered.find((command) => command?.name === name)?.lambda : void 0, item = {
|
|
1331
|
+
id: `command:${requestId}`,
|
|
1332
|
+
at: Date.now(),
|
|
1333
|
+
local: !0,
|
|
1334
|
+
kind: "context",
|
|
1335
|
+
category: "owner_command",
|
|
1336
|
+
text: "",
|
|
1337
|
+
ownerCommand: { v: 1, id: requestId, command: `/${name}${args ? ` ${args}` : ""}`, lambda: typeof lambda == "string" ? lambda : "", authorized: authorize, status: "running", duration_ms: 0 }
|
|
1338
|
+
};
|
|
1339
|
+
dispatch({ type: "transcript/owner-command", key, item });
|
|
1340
|
+
try {
|
|
1341
|
+
let result = await c.runCommand(agentId, name, { args, authorize, loop, requestId });
|
|
1342
|
+
if (stale(c) || stopped) return;
|
|
1343
|
+
dispatch({ type: "transcript/owner-command", key, item: {
|
|
1344
|
+
...item,
|
|
1345
|
+
seq: result.seq,
|
|
1346
|
+
text: result.result,
|
|
1347
|
+
deferred: result.deferred,
|
|
1348
|
+
unrecorded: !result.deferred && result.seq === void 0,
|
|
1349
|
+
ownerCommand: { ...item.ownerCommand, authorized: result.authorized, status: result.status, duration_ms: result.durationMs }
|
|
1350
|
+
} });
|
|
1351
|
+
let label = `${agentLabel(agentId)} /${name} (${loop})`;
|
|
1352
|
+
toast(`${label}: ${result.status === "denied" ? "permission denied; add !authorize for one authorized run" : result.status}${result.deferred ? " \u2014 recording after the current step" : ""}`, result.status === "ok" ? "success" : result.status === "denied" ? "warn" : "error");
|
|
1353
|
+
} catch (err) {
|
|
1354
|
+
if (stale(c) || stopped) return;
|
|
1355
|
+
dispatch({ type: "transcript/remove", key, id: item.id }), err instanceof DaemonError && err.unreachable && dispatch({ type: "daemon/reachable", reachable: !1 }), toast(`/${name}: ${describe(err)}`, "error");
|
|
1356
|
+
}
|
|
1357
|
+
},
|
|
1166
1358
|
async clearLoopHistory(agentId, loop) {
|
|
1167
1359
|
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));
|
|
1168
1360
|
},
|
|
@@ -1223,7 +1415,7 @@ function createTuiStore(options) {
|
|
|
1223
1415
|
}
|
|
1224
1416
|
},
|
|
1225
1417
|
async logoutSubscription(provider) {
|
|
1226
|
-
let label =
|
|
1418
|
+
let label = { chatgpt: "ChatGPT", grok: "Grok", claude: "Claude" }[provider], result = await run(`Sign out of ${label}`, (c) => c.logoutSubscription(provider));
|
|
1227
1419
|
return result && toast(`Signed the daemon out of ${label}`, "success"), await actions.refreshAuth(), !!result;
|
|
1228
1420
|
},
|
|
1229
1421
|
async refreshWeb() {
|
|
@@ -1332,6 +1524,11 @@ function createTuiStore(options) {
|
|
|
1332
1524
|
}, WEB_EVENT_DEBOUNCE_MS), !agentId || !state.agents[agentId]) return;
|
|
1333
1525
|
let loop = eventLoop(event), key = transcriptKey(agentId, loop);
|
|
1334
1526
|
switch (event.event_type) {
|
|
1527
|
+
case "context.injected":
|
|
1528
|
+
event.payload?.category === "owner_command" && debounce(`t:${key}`, () => {
|
|
1529
|
+
actions.loadTranscript(agentId, loop);
|
|
1530
|
+
});
|
|
1531
|
+
break;
|
|
1335
1532
|
case "turn.completed":
|
|
1336
1533
|
case "loop.cleared":
|
|
1337
1534
|
case "loop.compacted":
|
|
@@ -1386,40 +1583,137 @@ function createTuiStore(options) {
|
|
|
1386
1583
|
} catch {
|
|
1387
1584
|
dispatch({ type: "daemon/reachable", reachable: !1 });
|
|
1388
1585
|
}
|
|
1389
|
-
|
|
1390
|
-
|
|
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(() => {
|
|
1586
|
+
let opening = Promise.resolve();
|
|
1587
|
+
options.live !== !1 && (opening = openStream(), webTick && clearInterval(webTick), webTick = setInterval(() => {
|
|
1404
1588
|
stopped || actions.refreshWeb();
|
|
1405
1589
|
}, WEB_POLL_MS), trackedTick && clearInterval(trackedTick), trackedTick = setInterval(() => {
|
|
1406
1590
|
!stopped && state.daemonReachable !== !1 && actions.refreshTracked();
|
|
1407
|
-
}, TRACKED_POLL_MS)), await Promise.all([actions.refreshIdentity(), actions.refreshAuth(), actions.refreshAgents(), actions.refreshWeb()]), await actions.refreshTracked();
|
|
1591
|
+
}, TRACKED_POLL_MS)), await Promise.all([opening, actions.refreshIdentity(), actions.refreshAuth(), actions.refreshAgents(), actions.refreshWeb()]), await actions.refreshTracked();
|
|
1592
|
+
}
|
|
1593
|
+
function onStreamState(info) {
|
|
1594
|
+
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) {
|
|
1595
|
+
sessionRetry = !1, reopenSession();
|
|
1596
|
+
return;
|
|
1597
|
+
}
|
|
1598
|
+
info.state === "open" && info.resumed ? (needsResync = !1, resumeFallback && clearTimeout(resumeFallback), resumeFallback = setTimeout(() => {
|
|
1599
|
+
resumeFallback = null, toast("Reconnected to daemon \u2014 resyncing", "info", 2500), resync();
|
|
1600
|
+
}, RESUME_VERDICT_MS)) : info.state === "open" && needsResync && (needsResync = !1, toast("Connected to daemon", "info", 2500), resync());
|
|
1601
|
+
}
|
|
1602
|
+
function onStreamResume(info) {
|
|
1603
|
+
if (resumeFallback && (clearTimeout(resumeFallback), resumeFallback = null), info.exact) {
|
|
1604
|
+
toast("Reconnected to daemon \u2014 no events missed", "info", 2500), Promise.all([actions.refreshIdentity(), actions.refreshAuth(), actions.refreshAgents(), actions.refreshWeb()]);
|
|
1605
|
+
return;
|
|
1606
|
+
}
|
|
1607
|
+
toast(info.reason === "epoch_changed" ? "The daemon restarted \u2014 reloading" : "Events were missed while disconnected \u2014 reloading", "warn", 4e3), resync();
|
|
1608
|
+
}
|
|
1609
|
+
function onStreamGap(gap) {
|
|
1610
|
+
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());
|
|
1611
|
+
}
|
|
1612
|
+
function onClientFrame(frame) {
|
|
1613
|
+
let effects = clientFrameEffects(frame);
|
|
1614
|
+
for (let envelope of effects.frames) onFrame(envelope);
|
|
1615
|
+
if (effects.ownerCommand) {
|
|
1616
|
+
flushFrames();
|
|
1617
|
+
let { agentId, loop, item } = effects.ownerCommand;
|
|
1618
|
+
dispatch({ type: "transcript/owner-command", key: transcriptKey(agentId, loop), item });
|
|
1619
|
+
}
|
|
1620
|
+
if (effects.toolResult) {
|
|
1621
|
+
flushFrames();
|
|
1622
|
+
let { agentId, loop, toolUseId, result, isError } = effects.toolResult;
|
|
1623
|
+
dispatch({ type: "tool/result", key: transcriptKey(agentId, loop), toolUseId, result, isError });
|
|
1624
|
+
}
|
|
1625
|
+
if (effects.notice && toast(effects.notice.text, effects.notice.level, effects.notice.level === "warn" ? 1e4 : 4e3), effects.reload) {
|
|
1626
|
+
let { agentId, loop } = effects.reload, key = transcriptKey(agentId, loop);
|
|
1627
|
+
state.transcripts[key]?.loaded && debounce(`t:${key}`, () => {
|
|
1628
|
+
actions.loadTranscript(agentId, loop);
|
|
1629
|
+
});
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
function noticeFallback(reason) {
|
|
1633
|
+
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.` }));
|
|
1634
|
+
}
|
|
1635
|
+
async function openSession(c) {
|
|
1636
|
+
try {
|
|
1637
|
+
let version = (await c.version()).clientApiVersion;
|
|
1638
|
+
if (typeof version != "number" || version < TUI_MIN_CLIENT_API_VERSION || version > SUPPORTED_CLIENT_API_VERSION)
|
|
1639
|
+
return noticeFallback(`the daemon speaks client API ${version}, this app ${TUI_MIN_CLIENT_API_VERSION}-${SUPPORTED_CLIENT_API_VERSION}`), null;
|
|
1640
|
+
} catch (err) {
|
|
1641
|
+
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);
|
|
1642
|
+
}
|
|
1643
|
+
try {
|
|
1644
|
+
return (await c.createClientSession({ client: TUI_CLIENT_NAME, version: options.clientVersion ?? process.env.ADF_VERSION ?? "dev", umbilical: !0 })).sessionId;
|
|
1645
|
+
} catch (err) {
|
|
1646
|
+
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);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
async function openStream() {
|
|
1650
|
+
let c = plain, id = options.clientSessions === !1 ? null : await openSession(c);
|
|
1651
|
+
if (stale(c) || stopped) {
|
|
1652
|
+
id && c.endClientSession(id).catch(() => {
|
|
1653
|
+
});
|
|
1654
|
+
return;
|
|
1655
|
+
}
|
|
1656
|
+
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();
|
|
1657
|
+
}
|
|
1658
|
+
async function reopenSession() {
|
|
1659
|
+
if (!(reopening || stopped)) {
|
|
1660
|
+
reopening = !0;
|
|
1661
|
+
try {
|
|
1662
|
+
let hadSession = sessionId !== null;
|
|
1663
|
+
if (stream?.close(), stream = null, sessionId = null, useSession(null), await openStream(), stopped) return;
|
|
1664
|
+
hadSession && toast("The daemon no longer had this app's client session \u2014 reopened, reloading", "warn", 4e3), await resync();
|
|
1665
|
+
} finally {
|
|
1666
|
+
reopening = !1;
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
function desiredFocus() {
|
|
1671
|
+
let id = state.selectedAgentId;
|
|
1672
|
+
return state.activeView === CHAT_VIEW_ID && id && !isTrackedKey(id) ? id : null;
|
|
1673
|
+
}
|
|
1674
|
+
async function syncFocus() {
|
|
1675
|
+
if (!sessionId || focusInFlight || Date.now() < focusRetryAt) return;
|
|
1676
|
+
let want = desiredFocus();
|
|
1677
|
+
if (want === focusSent) return;
|
|
1678
|
+
let id = sessionId, c = client;
|
|
1679
|
+
focusInFlight = !0;
|
|
1680
|
+
try {
|
|
1681
|
+
await c.setClientSessionFocus(id, want), sessionId === id && (focusSent = want);
|
|
1682
|
+
} catch {
|
|
1683
|
+
focusRetryAt = Date.now() + 2e3;
|
|
1684
|
+
} finally {
|
|
1685
|
+
focusInFlight = !1;
|
|
1686
|
+
}
|
|
1687
|
+
sessionId === id && desiredFocus() !== focusSent && syncFocus();
|
|
1688
|
+
}
|
|
1689
|
+
function endSession(c) {
|
|
1690
|
+
let id = sessionId;
|
|
1691
|
+
return sessionId = null, c === client && useSession(null), focusSent = void 0, id ? c.endClientSession(id).then(() => {
|
|
1692
|
+
}, () => {
|
|
1693
|
+
}) : Promise.resolve();
|
|
1408
1694
|
}
|
|
1409
1695
|
async function resync() {
|
|
1410
|
-
await Promise.all([actions.refreshIdentity(), actions.refreshAuth(), actions.refreshAgents(), actions.refreshWeb()]), actions.refreshTracked();
|
|
1696
|
+
lastResyncAt = Date.now(), await Promise.all([actions.refreshIdentity(), actions.refreshAuth(), actions.refreshAgents(), actions.refreshWeb()]), actions.refreshTracked();
|
|
1411
1697
|
for (let key of Object.keys(state.transcripts)) {
|
|
1412
1698
|
let at = key.indexOf("\0"), agentId = key.slice(0, at);
|
|
1413
1699
|
state.agents[agentId] && state.transcripts[key].loaded && actions.loadTranscript(agentId, key.slice(at + 1));
|
|
1414
1700
|
}
|
|
1415
1701
|
}
|
|
1416
1702
|
function stop() {
|
|
1417
|
-
stopped = !0, stream?.close(), stream = null
|
|
1703
|
+
stopped = !0, stream?.close(), stream = null;
|
|
1704
|
+
let ended = endSession(client);
|
|
1705
|
+
resumeFallback && (clearTimeout(resumeFallback), resumeFallback = null), webTick && (clearInterval(webTick), webTick = null), trackedTick && (clearInterval(trackedTick), trackedTick = null), pendingFrames = [];
|
|
1418
1706
|
for (let timer of toastTimers.values()) clearTimeout(timer);
|
|
1419
1707
|
for (let timer of debounced.values()) clearTimeout(timer);
|
|
1420
1708
|
toastTimers.clear(), debounced.clear();
|
|
1421
1709
|
for (let resolve of confirmResolvers.values()) resolve(!1);
|
|
1422
|
-
confirmResolvers.clear();
|
|
1710
|
+
return confirmResolvers.clear(), ended;
|
|
1711
|
+
}
|
|
1712
|
+
async function close() {
|
|
1713
|
+
let ended = stop(), timer;
|
|
1714
|
+
await Promise.race([ended, new Promise((resolve) => {
|
|
1715
|
+
timer = setTimeout(resolve, 1e3);
|
|
1716
|
+
})]), timer && clearTimeout(timer);
|
|
1423
1717
|
}
|
|
1424
1718
|
function resolveConfirm(id, confirmed) {
|
|
1425
1719
|
let resolve = confirmResolvers.get(id);
|
|
@@ -1434,7 +1728,13 @@ function createTuiStore(options) {
|
|
|
1434
1728
|
dispatch,
|
|
1435
1729
|
subscribe,
|
|
1436
1730
|
start,
|
|
1437
|
-
stop
|
|
1731
|
+
stop: () => {
|
|
1732
|
+
stop();
|
|
1733
|
+
},
|
|
1734
|
+
close,
|
|
1735
|
+
get liveMode() {
|
|
1736
|
+
return sessionId ? "session" : stream ? "events" : "none";
|
|
1737
|
+
},
|
|
1438
1738
|
resolveConfirm
|
|
1439
1739
|
};
|
|
1440
1740
|
}
|
|
@@ -1477,14 +1777,17 @@ function shallowEqual(a, b) {
|
|
|
1477
1777
|
}
|
|
1478
1778
|
|
|
1479
1779
|
export {
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1780
|
+
MAIN_LOOP,
|
|
1781
|
+
DaemonError,
|
|
1782
|
+
isCredentialsLocked,
|
|
1483
1783
|
isTrackedKey,
|
|
1484
1784
|
folderName,
|
|
1485
1785
|
stoppedLabel,
|
|
1486
1786
|
stoppedError,
|
|
1487
1787
|
findTracked,
|
|
1788
|
+
emptyTranscript,
|
|
1789
|
+
isAsyncInput,
|
|
1790
|
+
askQuestion,
|
|
1488
1791
|
transcriptKey,
|
|
1489
1792
|
isBusyState,
|
|
1490
1793
|
parseServer,
|
|
@@ -1495,6 +1798,7 @@ export {
|
|
|
1495
1798
|
SERVER_STOPPED_TEXT,
|
|
1496
1799
|
serverBadge,
|
|
1497
1800
|
serverText,
|
|
1801
|
+
TUI_MIN_CLIENT_API_VERSION,
|
|
1498
1802
|
PROMPT_PREFILL_KEY,
|
|
1499
1803
|
createTuiStore,
|
|
1500
1804
|
StoreProvider,
|