opencode-subagent-magazine 1.5.1 → 1.6.0-beta.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.
- package/LICENSE +21 -21
- package/README.md +192 -192
- package/dist/_version.d.ts +1 -1
- package/dist/_version.js +1 -1
- package/dist/core/color.d.ts +20 -0
- package/dist/core/color.js +68 -0
- package/dist/core/format.d.ts +5 -0
- package/dist/core/format.js +68 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +6 -0
- package/dist/core/kv.d.ts +20 -0
- package/dist/core/kv.js +30 -0
- package/dist/core/state-machine.d.ts +17 -0
- package/dist/core/state-machine.js +27 -0
- package/dist/core/types.d.ts +51 -0
- package/dist/core/types.js +2 -0
- package/dist/core/usage.d.ts +15 -0
- package/dist/core/usage.js +1 -0
- package/dist/index.js +148 -1480
- package/dist/panel/SubAgentPanel.d.ts +13 -0
- package/dist/panel/SubAgentPanel.js +1232 -0
- package/dist/panel/panel-api.d.ts +67 -0
- package/dist/panel/panel-api.js +1 -0
- package/dist/panel/store.d.ts +5 -0
- package/dist/panel/store.js +5 -0
- package/dist/tui.js +383 -290
- package/dist/v2/commands.d.ts +7 -0
- package/dist/v2/commands.js +263 -0
- package/dist/v2/index.d.ts +8 -0
- package/dist/v2/index.js +62 -0
- package/dist/v2/theme.d.ts +3 -0
- package/dist/v2/theme.js +12 -0
- package/dist/v2/types.d.ts +231 -0
- package/dist/v2/types.js +6 -0
- package/dist/v2/v2-panel-api.d.ts +12 -0
- package/dist/v2/v2-panel-api.js +345 -0
- package/dist/v2.js +3003 -0
- package/install.mjs +103 -103
- package/package.json +64 -63
- package/src/_version.ts +1 -1
- package/src/clipboard.ts +134 -134
- package/src/core/color.ts +70 -0
- package/src/core/format.ts +61 -0
- package/src/core/index.ts +6 -0
- package/src/core/kv.ts +36 -0
- package/src/core/state-machine.ts +46 -0
- package/src/core/types.ts +58 -0
- package/src/core/usage.ts +16 -0
- package/src/i18n.ts +261 -261
- package/src/index.tsx +124 -1745
- package/src/panel/SubAgentPanel.tsx +1460 -0
- package/src/panel/panel-api.ts +72 -0
- package/src/panel/store.ts +8 -0
- package/src/server.ts +10 -10
- package/src/v2/commands.ts +251 -0
- package/src/v2/index.tsx +98 -0
- package/src/v2/theme.ts +14 -0
- package/src/v2/types.ts +165 -0
- package/src/v2/v2-panel-api.ts +301 -0
- package/tui/index.js +11 -0
package/dist/tui.js
CHANGED
|
@@ -1,113 +1,12 @@
|
|
|
1
1
|
// src/index.tsx
|
|
2
|
-
import { createTextNode as _$
|
|
3
|
-
import { insertNode as _$
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { memo as _$memo } from "@opentui/solid";
|
|
8
|
-
import { use as _$use } from "@opentui/solid";
|
|
9
|
-
import { setProp as _$setProp } from "@opentui/solid";
|
|
10
|
-
import { createElement as _$createElement } from "@opentui/solid";
|
|
11
|
-
import { createMemo, createSignal, createEffect, onMount, onCleanup, untrack, Show, For } from "solid-js";
|
|
2
|
+
import { createTextNode as _$createTextNode2 } from "@opentui/solid";
|
|
3
|
+
import { insertNode as _$insertNode2 } from "@opentui/solid";
|
|
4
|
+
import { createElement as _$createElement2 } from "@opentui/solid";
|
|
5
|
+
import { createComponent as _$createComponent2 } from "@opentui/solid";
|
|
6
|
+
import { createSignal as createSignal3 } from "solid-js";
|
|
12
7
|
|
|
13
8
|
// src/_version.ts
|
|
14
|
-
var PLUGIN_VERSION = "1.
|
|
15
|
-
|
|
16
|
-
// src/clipboard.ts
|
|
17
|
-
import { spawn } from "node:child_process";
|
|
18
|
-
import { platform, release } from "node:os";
|
|
19
|
-
function runWithInput(command, args, input) {
|
|
20
|
-
return new Promise((resolve, reject) => {
|
|
21
|
-
const child = spawn(command, args, {
|
|
22
|
-
stdio: ["pipe", "ignore", "ignore"],
|
|
23
|
-
windowsHide: true
|
|
24
|
-
});
|
|
25
|
-
child.once("error", reject);
|
|
26
|
-
child.once("close", (code) => {
|
|
27
|
-
if (code === 0) resolve();
|
|
28
|
-
else reject(new Error(`${command} exited with code ${code}`));
|
|
29
|
-
});
|
|
30
|
-
child.stdin?.end(input);
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
function writeOsc52(text) {
|
|
34
|
-
if (!process.stdout.isTTY) return false;
|
|
35
|
-
const payload = Buffer.from(text, "utf8").toString("base64");
|
|
36
|
-
const sequence = `\x1B]52;c;${payload}\x07`;
|
|
37
|
-
const wrapped = process.env.TMUX || process.env.STY ? `\x1BPtmux;\x1B${sequence}\x1B\\` : sequence;
|
|
38
|
-
process.stdout.write(wrapped);
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
async function tryCommand(method, command, args, text) {
|
|
42
|
-
try {
|
|
43
|
-
await runWithInput(command, args, text);
|
|
44
|
-
return { copied: true, method };
|
|
45
|
-
} catch {
|
|
46
|
-
return void 0;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
async function copyText(text) {
|
|
50
|
-
if (!text) return { copied: false, method: "none", error: "empty_text" };
|
|
51
|
-
const os = platform();
|
|
52
|
-
const isWsl = release().toLowerCase().includes("microsoft");
|
|
53
|
-
const attempts = [];
|
|
54
|
-
if (os === "darwin") {
|
|
55
|
-
attempts.push(() => tryCommand("pbcopy", "pbcopy", [], text));
|
|
56
|
-
attempts.push(
|
|
57
|
-
() => tryCommand(
|
|
58
|
-
"osascript",
|
|
59
|
-
"osascript",
|
|
60
|
-
["-e", 'set the clipboard to (read (POSIX file "/dev/stdin") as text)'],
|
|
61
|
-
text
|
|
62
|
-
)
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
if (os === "linux" && isWsl) {
|
|
66
|
-
attempts.push(
|
|
67
|
-
() => tryCommand(
|
|
68
|
-
"powershell",
|
|
69
|
-
"powershell.exe",
|
|
70
|
-
[
|
|
71
|
-
"-NonInteractive",
|
|
72
|
-
"-NoProfile",
|
|
73
|
-
"-Command",
|
|
74
|
-
"[Console]::InputEncoding=[Text.Encoding]::UTF8; Set-Clipboard ([Console]::In.ReadToEnd())"
|
|
75
|
-
],
|
|
76
|
-
text
|
|
77
|
-
)
|
|
78
|
-
);
|
|
79
|
-
} else if (os === "linux") {
|
|
80
|
-
if (process.env.WAYLAND_DISPLAY) {
|
|
81
|
-
attempts.push(() => tryCommand("wl-copy", "wl-copy", [], text));
|
|
82
|
-
}
|
|
83
|
-
attempts.push(() => tryCommand("xclip", "xclip", ["-selection", "clipboard"], text));
|
|
84
|
-
attempts.push(() => tryCommand("xsel", "xsel", ["--clipboard", "--input"], text));
|
|
85
|
-
}
|
|
86
|
-
if (os === "win32") {
|
|
87
|
-
attempts.push(
|
|
88
|
-
() => tryCommand(
|
|
89
|
-
"powershell",
|
|
90
|
-
"powershell.exe",
|
|
91
|
-
[
|
|
92
|
-
"-NonInteractive",
|
|
93
|
-
"-NoProfile",
|
|
94
|
-
"-Command",
|
|
95
|
-
"[Console]::InputEncoding=[Text.Encoding]::UTF8; Set-Clipboard ([Console]::In.ReadToEnd())"
|
|
96
|
-
],
|
|
97
|
-
text
|
|
98
|
-
)
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
for (const attempt of attempts) {
|
|
102
|
-
const result = await attempt();
|
|
103
|
-
if (result) return result;
|
|
104
|
-
}
|
|
105
|
-
try {
|
|
106
|
-
if (writeOsc52(text)) return { copied: true, method: "osc52" };
|
|
107
|
-
} catch {
|
|
108
|
-
}
|
|
109
|
-
return { copied: false, method: "none", error: "clipboard_unavailable" };
|
|
110
|
-
}
|
|
9
|
+
var PLUGIN_VERSION = "1.6.0-beta.0";
|
|
111
10
|
|
|
112
11
|
// src/i18n.ts
|
|
113
12
|
var ZH_T = {
|
|
@@ -343,14 +242,137 @@ function detectLang() {
|
|
|
343
242
|
}
|
|
344
243
|
}
|
|
345
244
|
|
|
346
|
-
// src/
|
|
245
|
+
// src/core/kv.ts
|
|
246
|
+
var KV_PREFIX = "subagent_magazine";
|
|
247
|
+
var SESSION_DATA_KEY = `${KV_PREFIX}.session_data`;
|
|
248
|
+
var SETTING_KEYS = {
|
|
249
|
+
lang: `${KV_PREFIX}.lang`,
|
|
250
|
+
maxEntries: `${KV_PREFIX}.max_entries`,
|
|
251
|
+
order: `${KV_PREFIX}.order`,
|
|
252
|
+
scrollMode: `${KV_PREFIX}.scroll_mode`,
|
|
253
|
+
open: `${KV_PREFIX}.open`,
|
|
254
|
+
ttlDays: `${KV_PREFIX}.ttl_days`
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// src/panel/SubAgentPanel.tsx
|
|
258
|
+
import { createTextNode as _$createTextNode } from "@opentui/solid";
|
|
259
|
+
import { insertNode as _$insertNode } from "@opentui/solid";
|
|
260
|
+
import { createComponent as _$createComponent } from "@opentui/solid";
|
|
261
|
+
import { effect as _$effect } from "@opentui/solid";
|
|
262
|
+
import { insert as _$insert } from "@opentui/solid";
|
|
263
|
+
import { memo as _$memo } from "@opentui/solid";
|
|
264
|
+
import { use as _$use } from "@opentui/solid";
|
|
265
|
+
import { setProp as _$setProp } from "@opentui/solid";
|
|
266
|
+
import { createElement as _$createElement } from "@opentui/solid";
|
|
267
|
+
import { createMemo, createSignal as createSignal2, createEffect, onMount, onCleanup, untrack, Show, For } from "solid-js";
|
|
268
|
+
|
|
269
|
+
// src/clipboard.ts
|
|
270
|
+
import { spawn } from "node:child_process";
|
|
271
|
+
import { platform, release } from "node:os";
|
|
272
|
+
function runWithInput(command, args, input) {
|
|
273
|
+
return new Promise((resolve, reject) => {
|
|
274
|
+
const child = spawn(command, args, {
|
|
275
|
+
stdio: ["pipe", "ignore", "ignore"],
|
|
276
|
+
windowsHide: true
|
|
277
|
+
});
|
|
278
|
+
child.once("error", reject);
|
|
279
|
+
child.once("close", (code) => {
|
|
280
|
+
if (code === 0) resolve();
|
|
281
|
+
else reject(new Error(`${command} exited with code ${code}`));
|
|
282
|
+
});
|
|
283
|
+
child.stdin?.end(input);
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
function writeOsc52(text) {
|
|
287
|
+
if (!process.stdout.isTTY) return false;
|
|
288
|
+
const payload = Buffer.from(text, "utf8").toString("base64");
|
|
289
|
+
const sequence = `\x1B]52;c;${payload}\x07`;
|
|
290
|
+
const wrapped = process.env.TMUX || process.env.STY ? `\x1BPtmux;\x1B${sequence}\x1B\\` : sequence;
|
|
291
|
+
process.stdout.write(wrapped);
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
async function tryCommand(method, command, args, text) {
|
|
295
|
+
try {
|
|
296
|
+
await runWithInput(command, args, text);
|
|
297
|
+
return { copied: true, method };
|
|
298
|
+
} catch {
|
|
299
|
+
return void 0;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
async function copyText(text) {
|
|
303
|
+
if (!text) return { copied: false, method: "none", error: "empty_text" };
|
|
304
|
+
const os = platform();
|
|
305
|
+
const isWsl = release().toLowerCase().includes("microsoft");
|
|
306
|
+
const attempts = [];
|
|
307
|
+
if (os === "darwin") {
|
|
308
|
+
attempts.push(() => tryCommand("pbcopy", "pbcopy", [], text));
|
|
309
|
+
attempts.push(
|
|
310
|
+
() => tryCommand(
|
|
311
|
+
"osascript",
|
|
312
|
+
"osascript",
|
|
313
|
+
["-e", 'set the clipboard to (read (POSIX file "/dev/stdin") as text)'],
|
|
314
|
+
text
|
|
315
|
+
)
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
if (os === "linux" && isWsl) {
|
|
319
|
+
attempts.push(
|
|
320
|
+
() => tryCommand(
|
|
321
|
+
"powershell",
|
|
322
|
+
"powershell.exe",
|
|
323
|
+
[
|
|
324
|
+
"-NonInteractive",
|
|
325
|
+
"-NoProfile",
|
|
326
|
+
"-Command",
|
|
327
|
+
"[Console]::InputEncoding=[Text.Encoding]::UTF8; Set-Clipboard ([Console]::In.ReadToEnd())"
|
|
328
|
+
],
|
|
329
|
+
text
|
|
330
|
+
)
|
|
331
|
+
);
|
|
332
|
+
} else if (os === "linux") {
|
|
333
|
+
if (process.env.WAYLAND_DISPLAY) {
|
|
334
|
+
attempts.push(() => tryCommand("wl-copy", "wl-copy", [], text));
|
|
335
|
+
}
|
|
336
|
+
attempts.push(() => tryCommand("xclip", "xclip", ["-selection", "clipboard"], text));
|
|
337
|
+
attempts.push(() => tryCommand("xsel", "xsel", ["--clipboard", "--input"], text));
|
|
338
|
+
}
|
|
339
|
+
if (os === "win32") {
|
|
340
|
+
attempts.push(
|
|
341
|
+
() => tryCommand(
|
|
342
|
+
"powershell",
|
|
343
|
+
"powershell.exe",
|
|
344
|
+
[
|
|
345
|
+
"-NonInteractive",
|
|
346
|
+
"-NoProfile",
|
|
347
|
+
"-Command",
|
|
348
|
+
"[Console]::InputEncoding=[Text.Encoding]::UTF8; Set-Clipboard ([Console]::In.ReadToEnd())"
|
|
349
|
+
],
|
|
350
|
+
text
|
|
351
|
+
)
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
for (const attempt of attempts) {
|
|
355
|
+
const result = await attempt();
|
|
356
|
+
if (result) return result;
|
|
357
|
+
}
|
|
358
|
+
try {
|
|
359
|
+
if (writeOsc52(text)) return { copied: true, method: "osc52" };
|
|
360
|
+
} catch {
|
|
361
|
+
}
|
|
362
|
+
return { copied: false, method: "none", error: "clipboard_unavailable" };
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// src/core/types.ts
|
|
347
366
|
var SUBAGENT_TOOLS = /* @__PURE__ */ new Set(["task", "delegate", "call_omo_agent"]);
|
|
367
|
+
|
|
368
|
+
// src/core/format.ts
|
|
348
369
|
function charColumns(c) {
|
|
349
370
|
const code = c.codePointAt(0) ?? 0;
|
|
350
371
|
if (code < 32) return 0;
|
|
351
372
|
if (code < 127) return 1;
|
|
352
373
|
if (code < 160) return 0;
|
|
353
|
-
if (code >= 4352 && code <= 4447 || code >= 11904 && code <= 42191 || code >= 44032 && code <= 55203 || code >= 63744 && code <= 64255 || code >= 65040 && code <= 65135 || code >= 65281 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 127744 && code <= 128591 || code >= 131072 && code <= 262141)
|
|
374
|
+
if (code >= 4352 && code <= 4447 || code >= 11904 && code <= 42191 || code >= 44032 && code <= 55203 || code >= 63744 && code <= 64255 || code >= 65040 && code <= 65135 || code >= 65281 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 127744 && code <= 128591 || code >= 131072 && code <= 262141)
|
|
375
|
+
return 2;
|
|
354
376
|
return 1;
|
|
355
377
|
}
|
|
356
378
|
function visualWidth(s) {
|
|
@@ -383,6 +405,14 @@ function fmtTokens(n) {
|
|
|
383
405
|
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
384
406
|
return `${(n / 1e6).toFixed(1)}M`;
|
|
385
407
|
}
|
|
408
|
+
function safeErrorMsg(err) {
|
|
409
|
+
if (!err) return "";
|
|
410
|
+
if (typeof err === "string") return err;
|
|
411
|
+
if (typeof err === "object") return String(err.message || err.code || "");
|
|
412
|
+
return "";
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// src/core/color.ts
|
|
386
416
|
function rgb(raw) {
|
|
387
417
|
if (typeof raw === "string" && raw.startsWith("#")) {
|
|
388
418
|
const h = raw.slice(1);
|
|
@@ -396,11 +426,7 @@ function rgb(raw) {
|
|
|
396
426
|
const o = raw;
|
|
397
427
|
if (typeof o.r === "number" && typeof o.g === "number" && typeof o.b === "number") {
|
|
398
428
|
const scale = o.r > 1 || o.g > 1 || o.b > 1 ? 1 : 255;
|
|
399
|
-
return {
|
|
400
|
-
r: Math.round(o.r * scale),
|
|
401
|
-
g: Math.round(o.g * scale),
|
|
402
|
-
b: Math.round(o.b * scale)
|
|
403
|
-
};
|
|
429
|
+
return { r: Math.round(o.r * scale), g: Math.round(o.g * scale), b: Math.round(o.b * scale) };
|
|
404
430
|
}
|
|
405
431
|
}
|
|
406
432
|
return null;
|
|
@@ -453,25 +479,24 @@ var FALLBACK = {
|
|
|
453
479
|
border: "#6B6B63"
|
|
454
480
|
};
|
|
455
481
|
var MAX_SAT = 0.28;
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
if (!err) return "";
|
|
460
|
-
if (typeof err === "string") return err;
|
|
461
|
-
if (typeof err === "object") return String(err.message || err.code || "");
|
|
462
|
-
return "";
|
|
463
|
-
}
|
|
482
|
+
|
|
483
|
+
// src/panel/store.ts
|
|
484
|
+
import { createSignal } from "solid-js";
|
|
464
485
|
var globalEntryCache = /* @__PURE__ */ new Map();
|
|
465
486
|
var [clearTick, setClearTick] = createSignal(0);
|
|
487
|
+
|
|
488
|
+
// src/panel/SubAgentPanel.tsx
|
|
489
|
+
var LEFT_PAD = 4;
|
|
490
|
+
var INDENT = 2;
|
|
466
491
|
function SubAgentPanel(props) {
|
|
467
492
|
const t = createT(() => props.lang());
|
|
468
|
-
const
|
|
493
|
+
const SESSION_DATA_KEY2 = `${KV_PREFIX}.session_data`;
|
|
469
494
|
const ttlDaysRaw = parseInt(String(props.api.kv.get(`${KV_PREFIX}.ttl_days`, "3")), 10);
|
|
470
495
|
const ttlDays = Number.isNaN(ttlDaysRaw) ? 3 : ttlDaysRaw;
|
|
471
496
|
const TTL_MS = ttlDays * 24 * 60 * 60 * 1e3;
|
|
472
497
|
const loadSessionData = () => {
|
|
473
498
|
try {
|
|
474
|
-
const raw = props.api.kv.get(
|
|
499
|
+
const raw = props.api.kv.get(SESSION_DATA_KEY2, "{}");
|
|
475
500
|
return JSON.parse(String(raw));
|
|
476
501
|
} catch {
|
|
477
502
|
return {};
|
|
@@ -479,13 +504,13 @@ function SubAgentPanel(props) {
|
|
|
479
504
|
};
|
|
480
505
|
const saveSessionData = (data) => {
|
|
481
506
|
try {
|
|
482
|
-
props.api.kv.set(
|
|
507
|
+
props.api.kv.set(SESSION_DATA_KEY2, JSON.stringify(data));
|
|
483
508
|
} catch {
|
|
484
509
|
}
|
|
485
510
|
};
|
|
486
511
|
const resolveParent = (sid) => {
|
|
487
512
|
try {
|
|
488
|
-
const session = props.api.
|
|
513
|
+
const session = props.api.session.get(sid);
|
|
489
514
|
const parentID = session?.parentID;
|
|
490
515
|
if (parentID) return {
|
|
491
516
|
parentSid: parentID,
|
|
@@ -648,7 +673,7 @@ function SubAgentPanel(props) {
|
|
|
648
673
|
}
|
|
649
674
|
};
|
|
650
675
|
cleanupOldSessions();
|
|
651
|
-
const [entryMap, setEntryMapRaw] =
|
|
676
|
+
const [entryMap, setEntryMapRaw] = createSignal2(loadEntries(props.sessionId));
|
|
652
677
|
const setEntryMap = (arg) => {
|
|
653
678
|
setEntryMapRaw((prev) => {
|
|
654
679
|
const next = typeof arg === "function" ? arg(prev) : arg;
|
|
@@ -704,15 +729,15 @@ function SubAgentPanel(props) {
|
|
|
704
729
|
return next;
|
|
705
730
|
});
|
|
706
731
|
};
|
|
707
|
-
const [panelWidth, setPanelWidth] =
|
|
708
|
-
const [open, setOpen] =
|
|
732
|
+
const [panelWidth, setPanelWidth] = createSignal2(28);
|
|
733
|
+
const [open, setOpen] = createSignal2((() => {
|
|
709
734
|
try {
|
|
710
735
|
return props.api.kv.get(`${KV_PREFIX}.open`, true);
|
|
711
736
|
} catch {
|
|
712
737
|
return true;
|
|
713
738
|
}
|
|
714
739
|
})());
|
|
715
|
-
const [expanded, setExpanded] =
|
|
740
|
+
const [expanded, setExpanded] = createSignal2((() => {
|
|
716
741
|
try {
|
|
717
742
|
const {
|
|
718
743
|
parentSid,
|
|
@@ -724,13 +749,13 @@ function SubAgentPanel(props) {
|
|
|
724
749
|
}
|
|
725
750
|
return void 0;
|
|
726
751
|
})());
|
|
727
|
-
const [hoveredOpen, setHoveredOpen] =
|
|
728
|
-
const [hoveredDismiss, setHoveredDismiss] =
|
|
729
|
-
const [hoveredCancel, setHoveredCancel] =
|
|
730
|
-
const [hoveredTop, setHoveredTop] =
|
|
731
|
-
const [hoveredMoreAbove, setHoveredMoreAbove] =
|
|
732
|
-
const [hoveredMoreBelow, setHoveredMoreBelow] =
|
|
733
|
-
const [scrollOffset, setScrollOffset] =
|
|
752
|
+
const [hoveredOpen, setHoveredOpen] = createSignal2(void 0);
|
|
753
|
+
const [hoveredDismiss, setHoveredDismiss] = createSignal2(void 0);
|
|
754
|
+
const [hoveredCancel, setHoveredCancel] = createSignal2(void 0);
|
|
755
|
+
const [hoveredTop, setHoveredTop] = createSignal2(false);
|
|
756
|
+
const [hoveredMoreAbove, setHoveredMoreAbove] = createSignal2(false);
|
|
757
|
+
const [hoveredMoreBelow, setHoveredMoreBelow] = createSignal2(false);
|
|
758
|
+
const [scrollOffset, setScrollOffset] = createSignal2((() => {
|
|
734
759
|
try {
|
|
735
760
|
const {
|
|
736
761
|
parentSid,
|
|
@@ -742,78 +767,10 @@ function SubAgentPanel(props) {
|
|
|
742
767
|
return 0;
|
|
743
768
|
}
|
|
744
769
|
})());
|
|
745
|
-
const [now, setNow] =
|
|
746
|
-
const [renderTick, setRenderTick] =
|
|
770
|
+
const [now, setNow] = createSignal2(Date.now());
|
|
771
|
+
const [renderTick, setRenderTick] = createSignal2(0);
|
|
747
772
|
let boxEl;
|
|
748
773
|
let disposed = false;
|
|
749
|
-
const readSessionTokens = (sid) => {
|
|
750
|
-
if (!sid) return void 0;
|
|
751
|
-
try {
|
|
752
|
-
const msgs = props.api.state.session.messages(sid);
|
|
753
|
-
if (msgs) {
|
|
754
|
-
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
755
|
-
const m = msgs[i];
|
|
756
|
-
if (m.role !== "assistant") continue;
|
|
757
|
-
const t2 = m.tokens;
|
|
758
|
-
if (!t2) continue;
|
|
759
|
-
const cache = t2.cache;
|
|
760
|
-
const ctx = (Number(t2.input) || 0) + (cache?.read ?? 0);
|
|
761
|
-
if (ctx > 0) return ctx;
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
return void 0;
|
|
765
|
-
} catch {
|
|
766
|
-
return void 0;
|
|
767
|
-
}
|
|
768
|
-
};
|
|
769
|
-
const readSessionCost = (sid) => {
|
|
770
|
-
if (!sid) return void 0;
|
|
771
|
-
try {
|
|
772
|
-
const session = props.api.state.session.get(sid);
|
|
773
|
-
if (session?.cost != null && session.cost > 0) return session.cost;
|
|
774
|
-
const msgs = props.api.state.session.messages(sid);
|
|
775
|
-
if (!msgs) return void 0;
|
|
776
|
-
let total = 0;
|
|
777
|
-
for (const m of msgs) {
|
|
778
|
-
if (m.role === "assistant" && typeof m.cost === "number") total += m.cost;
|
|
779
|
-
}
|
|
780
|
-
return total > 0 ? total : void 0;
|
|
781
|
-
} catch {
|
|
782
|
-
return void 0;
|
|
783
|
-
}
|
|
784
|
-
};
|
|
785
|
-
const readSessionModel = (sid) => {
|
|
786
|
-
if (!sid) return void 0;
|
|
787
|
-
try {
|
|
788
|
-
const msgs = props.api.state.session.messages(sid);
|
|
789
|
-
if (msgs) {
|
|
790
|
-
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
791
|
-
const m = msgs[i];
|
|
792
|
-
if (m.role === "assistant" && m.modelID) return String(m.modelID);
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
return void 0;
|
|
796
|
-
} catch {
|
|
797
|
-
return void 0;
|
|
798
|
-
}
|
|
799
|
-
};
|
|
800
|
-
const readSessionTodo = (sid) => {
|
|
801
|
-
if (!sid) return void 0;
|
|
802
|
-
try {
|
|
803
|
-
const todos = props.api.state.session.todo(sid);
|
|
804
|
-
if (!todos || todos.length === 0) return void 0;
|
|
805
|
-
let done = 0;
|
|
806
|
-
for (const t2 of todos) {
|
|
807
|
-
if (t2.status === "completed" || t2.status === "cancelled") done++;
|
|
808
|
-
}
|
|
809
|
-
return {
|
|
810
|
-
total: todos.length,
|
|
811
|
-
done
|
|
812
|
-
};
|
|
813
|
-
} catch {
|
|
814
|
-
return void 0;
|
|
815
|
-
}
|
|
816
|
-
};
|
|
817
774
|
const upsertEntry = (partial) => {
|
|
818
775
|
setEntryMap((prev) => {
|
|
819
776
|
const existing = prev.get(partial.id);
|
|
@@ -835,12 +792,12 @@ function SubAgentPanel(props) {
|
|
|
835
792
|
const isDescendantOf = (childId, rootId) => {
|
|
836
793
|
const visited = /* @__PURE__ */ new Set();
|
|
837
794
|
try {
|
|
838
|
-
let current = props.api.
|
|
795
|
+
let current = props.api.session.get(childId);
|
|
839
796
|
while (current?.parentID) {
|
|
840
797
|
if (visited.has(current.id)) return false;
|
|
841
798
|
visited.add(current.id);
|
|
842
799
|
if (current.parentID === rootId) return true;
|
|
843
|
-
current = props.api.
|
|
800
|
+
current = props.api.session.get(current.parentID);
|
|
844
801
|
}
|
|
845
802
|
} catch {
|
|
846
803
|
}
|
|
@@ -853,40 +810,36 @@ function SubAgentPanel(props) {
|
|
|
853
810
|
const cancelEntry = async (entry) => {
|
|
854
811
|
const childId = entry.sessionId;
|
|
855
812
|
if (!childId) {
|
|
856
|
-
props.api.ui.toast({
|
|
857
|
-
title: entry.title || entry.agent
|
|
858
|
-
message: t("cancel.label") + ": " + t("cancel.no_session")
|
|
813
|
+
props.api.ui.toast(t("cancel.label") + ": " + t("cancel.no_session"), {
|
|
814
|
+
title: entry.title || entry.agent
|
|
859
815
|
});
|
|
860
816
|
return;
|
|
861
817
|
}
|
|
862
818
|
try {
|
|
863
|
-
const child = props.api.
|
|
819
|
+
const child = props.api.session.get(childId);
|
|
864
820
|
if (!child?.parentID) {
|
|
865
|
-
props.api.ui.toast({
|
|
866
|
-
title: entry.title || entry.agent
|
|
867
|
-
message: t("cancel.label") + ": " + t("cancel.not_child")
|
|
821
|
+
props.api.ui.toast(t("cancel.label") + ": " + t("cancel.not_child"), {
|
|
822
|
+
title: entry.title || entry.agent
|
|
868
823
|
});
|
|
869
824
|
return;
|
|
870
825
|
}
|
|
871
826
|
} catch {
|
|
872
|
-
props.api.ui.toast({
|
|
873
|
-
title: entry.title || entry.agent
|
|
874
|
-
message: t("cancel.label") + ": " + t("cancel.read_error")
|
|
827
|
+
props.api.ui.toast(t("cancel.label") + ": " + t("cancel.read_error"), {
|
|
828
|
+
title: entry.title || entry.agent
|
|
875
829
|
});
|
|
876
830
|
return;
|
|
877
831
|
}
|
|
878
832
|
if (!isDescendantOf(childId, props.sessionId)) {
|
|
879
|
-
props.api.ui.toast({
|
|
880
|
-
title: entry.title || entry.agent
|
|
881
|
-
message: t("cancel.label") + ": " + t("cancel.outside_tree")
|
|
833
|
+
props.api.ui.toast(t("cancel.label") + ": " + t("cancel.outside_tree"), {
|
|
834
|
+
title: entry.title || entry.agent
|
|
882
835
|
});
|
|
883
836
|
return;
|
|
884
837
|
}
|
|
885
838
|
try {
|
|
886
|
-
const st = props.api.
|
|
839
|
+
const st = props.api.session.status(childId);
|
|
887
840
|
if (st?.type !== "busy") {
|
|
888
|
-
const tokens = readSessionTokens(childId);
|
|
889
|
-
const cost = readSessionCost(childId);
|
|
841
|
+
const tokens = props.api.usage.readSessionTokens(childId);
|
|
842
|
+
const cost = props.api.usage.readSessionCost(childId);
|
|
890
843
|
upsertEntry({
|
|
891
844
|
id: entry.id,
|
|
892
845
|
title: entry.title,
|
|
@@ -900,9 +853,8 @@ function SubAgentPanel(props) {
|
|
|
900
853
|
return;
|
|
901
854
|
}
|
|
902
855
|
} catch {
|
|
903
|
-
props.api.ui.toast({
|
|
904
|
-
title: entry.title || entry.agent
|
|
905
|
-
message: t("cancel.label") + ": " + t("cancel.status_error")
|
|
856
|
+
props.api.ui.toast(t("cancel.label") + ": " + t("cancel.status_error"), {
|
|
857
|
+
title: entry.title || entry.agent
|
|
906
858
|
});
|
|
907
859
|
return;
|
|
908
860
|
}
|
|
@@ -918,7 +870,7 @@ function SubAgentPanel(props) {
|
|
|
918
870
|
cancelReason: "manual"
|
|
919
871
|
});
|
|
920
872
|
try {
|
|
921
|
-
await props.api.client.
|
|
873
|
+
await props.api.client.abort({
|
|
922
874
|
sessionID: childId
|
|
923
875
|
});
|
|
924
876
|
upsertEntry({
|
|
@@ -930,9 +882,7 @@ function SubAgentPanel(props) {
|
|
|
930
882
|
sessionId: entry.sessionId,
|
|
931
883
|
abortAccepted: true
|
|
932
884
|
});
|
|
933
|
-
props.api.ui.toast(
|
|
934
|
-
message: t("cancel.label") + ": " + t("cancel.sent")
|
|
935
|
-
});
|
|
885
|
+
props.api.ui.toast(t("cancel.label") + ": " + t("cancel.sent"));
|
|
936
886
|
} catch (err) {
|
|
937
887
|
upsertEntry({
|
|
938
888
|
id: entry.id,
|
|
@@ -943,16 +893,13 @@ function SubAgentPanel(props) {
|
|
|
943
893
|
sessionId: entry.sessionId,
|
|
944
894
|
error: String(err)
|
|
945
895
|
});
|
|
946
|
-
props.api.ui.toast({
|
|
947
|
-
title: entry.title || entry.agent
|
|
948
|
-
message: t("cancel.label") + ": " + t("cancel.failed")
|
|
896
|
+
props.api.ui.toast(t("cancel.label") + ": " + t("cancel.failed"), {
|
|
897
|
+
title: entry.title || entry.agent
|
|
949
898
|
});
|
|
950
899
|
}
|
|
951
900
|
};
|
|
952
901
|
const handlePartUpdated = (event) => {
|
|
953
|
-
const
|
|
954
|
-
const props_ = e.properties;
|
|
955
|
-
const part = props_?.part;
|
|
902
|
+
const part = event.payload?.part;
|
|
956
903
|
if (!part) return;
|
|
957
904
|
if (part.type === "subtask") {
|
|
958
905
|
const agent = String(part.agent ?? "?");
|
|
@@ -1020,24 +967,23 @@ function SubAgentPanel(props) {
|
|
|
1020
967
|
}
|
|
1021
968
|
};
|
|
1022
969
|
const handleSessionEnd = (event, status) => {
|
|
1023
|
-
const
|
|
1024
|
-
const props_ = e.properties;
|
|
970
|
+
const props_ = event.payload;
|
|
1025
971
|
const sid = String(props_?.sessionID ?? "");
|
|
1026
972
|
if (!sid) return;
|
|
1027
|
-
const sessionTokens = readSessionTokens(sid);
|
|
1028
|
-
const sessionCost = readSessionCost(sid);
|
|
1029
|
-
const sessionModel = readSessionModel(sid);
|
|
1030
|
-
const sessionTodo = readSessionTodo(sid);
|
|
973
|
+
const sessionTokens = props.api.usage.readSessionTokens(sid);
|
|
974
|
+
const sessionCost = props.api.usage.readSessionCost(sid);
|
|
975
|
+
const sessionModel = props.api.usage.readSessionModel(sid);
|
|
976
|
+
const sessionTodo = props.api.usage.readSessionTodo(sid);
|
|
1031
977
|
let sessionAgent;
|
|
1032
978
|
let errorMsg;
|
|
1033
979
|
try {
|
|
1034
|
-
const s = props.api.
|
|
980
|
+
const s = props.api.session.get(sid);
|
|
1035
981
|
sessionAgent = s?.agent;
|
|
1036
982
|
if (status === "error") {
|
|
1037
983
|
const evtErr = props_?.error;
|
|
1038
984
|
errorMsg = safeErrorMsg(evtErr) || safeErrorMsg(props_?.message);
|
|
1039
985
|
if (!errorMsg) {
|
|
1040
|
-
const msgs = props.api.
|
|
986
|
+
const msgs = props.api.session.messages(sid);
|
|
1041
987
|
if (msgs) {
|
|
1042
988
|
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
1043
989
|
const m = msgs[i];
|
|
@@ -1177,7 +1123,7 @@ function SubAgentPanel(props) {
|
|
|
1177
1123
|
return changed ? next : prev;
|
|
1178
1124
|
});
|
|
1179
1125
|
try {
|
|
1180
|
-
const sessionObj = props.api.
|
|
1126
|
+
const sessionObj = props.api.session.get(sid);
|
|
1181
1127
|
const parentSid = sessionObj?.parentID;
|
|
1182
1128
|
if (parentSid && parentSid !== props.sessionId) {
|
|
1183
1129
|
const parentCache = globalEntryCache.get(parentSid);
|
|
@@ -1190,7 +1136,7 @@ function SubAgentPanel(props) {
|
|
|
1190
1136
|
const data = loadSessionData();
|
|
1191
1137
|
const rec = data[parentSid];
|
|
1192
1138
|
if (rec?.entries) {
|
|
1193
|
-
const fallbackMap = new Map(rec.entries.map((
|
|
1139
|
+
const fallbackMap = new Map(rec.entries.map((e) => [e.id, e]));
|
|
1194
1140
|
found = tryMatchAndUpdate(fallbackMap, sid, status, nowTs);
|
|
1195
1141
|
if (found) {
|
|
1196
1142
|
data[parentSid] = {
|
|
@@ -1217,10 +1163,10 @@ function SubAgentPanel(props) {
|
|
|
1217
1163
|
}
|
|
1218
1164
|
setTimeout(() => {
|
|
1219
1165
|
if (disposed) return;
|
|
1220
|
-
const finalTokens = readSessionTokens(sid);
|
|
1221
|
-
const finalCost = readSessionCost(sid);
|
|
1222
|
-
const finalModel = readSessionModel(sid);
|
|
1223
|
-
const finalTodo = readSessionTodo(sid);
|
|
1166
|
+
const finalTokens = props.api.usage.readSessionTokens(sid);
|
|
1167
|
+
const finalCost = props.api.usage.readSessionCost(sid);
|
|
1168
|
+
const finalModel = props.api.usage.readSessionModel(sid);
|
|
1169
|
+
const finalTodo = props.api.usage.readSessionTodo(sid);
|
|
1224
1170
|
setEntryMap((prev) => {
|
|
1225
1171
|
let changed = false;
|
|
1226
1172
|
const next = new Map(prev);
|
|
@@ -1263,14 +1209,14 @@ function SubAgentPanel(props) {
|
|
|
1263
1209
|
if (entry.status === "running" && entry.sessionId) {
|
|
1264
1210
|
let isChild = false;
|
|
1265
1211
|
try {
|
|
1266
|
-
const s = props.api.
|
|
1212
|
+
const s = props.api.session.get(entry.sessionId);
|
|
1267
1213
|
isChild = s?.parentID === props.sessionId;
|
|
1268
1214
|
} catch {
|
|
1269
1215
|
}
|
|
1270
1216
|
if (!isChild) continue;
|
|
1271
|
-
const total = readSessionTokens(entry.sessionId);
|
|
1272
|
-
const todo = readSessionTodo(entry.sessionId);
|
|
1273
|
-
const model = entry.model ?? readSessionModel(entry.sessionId);
|
|
1217
|
+
const total = props.api.usage.readSessionTokens(entry.sessionId);
|
|
1218
|
+
const todo = props.api.usage.readSessionTodo(entry.sessionId);
|
|
1219
|
+
const model = entry.model ?? props.api.usage.readSessionModel(entry.sessionId);
|
|
1274
1220
|
const nextEntry = {
|
|
1275
1221
|
...entry
|
|
1276
1222
|
};
|
|
@@ -1298,7 +1244,7 @@ function SubAgentPanel(props) {
|
|
|
1298
1244
|
bump();
|
|
1299
1245
|
}, 500);
|
|
1300
1246
|
bump();
|
|
1301
|
-
const unsubPart = props.api.event.on("
|
|
1247
|
+
const unsubPart = props.api.event.on("part.updated", (e) => {
|
|
1302
1248
|
handlePartUpdated(e);
|
|
1303
1249
|
bump();
|
|
1304
1250
|
});
|
|
@@ -1354,10 +1300,10 @@ function SubAgentPanel(props) {
|
|
|
1354
1300
|
const scanRec = loadSessionData()[scanPSid];
|
|
1355
1301
|
const clearedIds = new Set(scanChild ? scanRec?.children?.[sid]?.clearedIds : scanRec?.clearedIds);
|
|
1356
1302
|
try {
|
|
1357
|
-
const msgs = props.api.
|
|
1303
|
+
const msgs = props.api.session.messages(sid);
|
|
1358
1304
|
if (msgs && msgs.length) {
|
|
1359
1305
|
for (const msg of msgs) {
|
|
1360
|
-
const parts = props.api.
|
|
1306
|
+
const parts = props.api.session.part(msg.id) ?? [];
|
|
1361
1307
|
for (const partRaw of parts) {
|
|
1362
1308
|
const part = partRaw;
|
|
1363
1309
|
if (part.type === "tool") {
|
|
@@ -1410,7 +1356,7 @@ function SubAgentPanel(props) {
|
|
|
1410
1356
|
let tokens;
|
|
1411
1357
|
const scanStMeta2 = st?.metadata;
|
|
1412
1358
|
const scanSubSid = scanStMeta2?.session_id !== void 0 ? String(scanStMeta2.session_id) : scanStMeta2?.sessionId !== void 0 ? String(scanStMeta2.sessionId) : void 0;
|
|
1413
|
-
if (scanSubSid) tokens = readSessionTokens(scanSubSid);
|
|
1359
|
+
if (scanSubSid) tokens = props.api.usage.readSessionTokens(scanSubSid);
|
|
1414
1360
|
const ended = status === "done";
|
|
1415
1361
|
next.set(id, {
|
|
1416
1362
|
id,
|
|
@@ -1438,10 +1384,10 @@ function SubAgentPanel(props) {
|
|
|
1438
1384
|
for (const [id, entry] of next) {
|
|
1439
1385
|
if (entry.status !== "running" && entry.status !== "cancel_requested" || !entry.sessionId) continue;
|
|
1440
1386
|
try {
|
|
1441
|
-
const st = props.api.
|
|
1387
|
+
const st = props.api.session.status(entry.sessionId);
|
|
1442
1388
|
if (!st || st.type !== "idle") continue;
|
|
1443
|
-
const tokens = readSessionTokens(entry.sessionId);
|
|
1444
|
-
const cost = readSessionCost(entry.sessionId);
|
|
1389
|
+
const tokens = props.api.usage.readSessionTokens(entry.sessionId);
|
|
1390
|
+
const cost = props.api.usage.readSessionCost(entry.sessionId);
|
|
1445
1391
|
const finalStatus = entry.status === "cancel_requested" && entry.abortAccepted ? "cancelled" : "done";
|
|
1446
1392
|
next.set(id, {
|
|
1447
1393
|
...entry,
|
|
@@ -2171,20 +2117,18 @@ function SubAgentPanel(props) {
|
|
|
2171
2117
|
if (!sessionId) return;
|
|
2172
2118
|
const result = await copyText(sessionId);
|
|
2173
2119
|
if (result.copied) {
|
|
2174
|
-
props.api.ui.toast({
|
|
2120
|
+
props.api.ui.toast(t("session.toast.copied"), {
|
|
2175
2121
|
variant: "success",
|
|
2176
2122
|
title: entry.title || entry.agent,
|
|
2177
|
-
message: t("session.toast.copied"),
|
|
2178
2123
|
duration: 2500
|
|
2179
2124
|
});
|
|
2180
2125
|
return;
|
|
2181
2126
|
}
|
|
2182
|
-
props.api.ui.toast({
|
|
2127
|
+
props.api.ui.toast(`${sessionId}
|
|
2128
|
+
|
|
2129
|
+
${t("session.toast.copy_failed")}`, {
|
|
2183
2130
|
variant: "warning",
|
|
2184
2131
|
title: entry.title || entry.agent,
|
|
2185
|
-
message: `${sessionId}
|
|
2186
|
-
|
|
2187
|
-
${t("session.toast.copy_failed")}`,
|
|
2188
2132
|
duration: 8e3
|
|
2189
2133
|
});
|
|
2190
2134
|
});
|
|
@@ -2245,9 +2189,7 @@ ${t("session.toast.copy_failed")}`,
|
|
|
2245
2189
|
_$setProp(_el$92, "onMouseOut", () => setHoveredOpen(void 0));
|
|
2246
2190
|
_$setProp(_el$92, "onMouseUp", () => {
|
|
2247
2191
|
if (entry.sessionId) {
|
|
2248
|
-
props.api.route.
|
|
2249
|
-
sessionID: entry.sessionId
|
|
2250
|
-
});
|
|
2192
|
+
props.api.route.navigateSession(entry.sessionId);
|
|
2251
2193
|
}
|
|
2252
2194
|
});
|
|
2253
2195
|
_$insert(_el$93, openPrefix);
|
|
@@ -2409,17 +2351,19 @@ ${t("session.toast.copy_failed")}`,
|
|
|
2409
2351
|
return _el$;
|
|
2410
2352
|
})();
|
|
2411
2353
|
}
|
|
2412
|
-
|
|
2354
|
+
|
|
2355
|
+
// src/index.tsx
|
|
2356
|
+
function createSidebarSlot(api, panelApi, sig) {
|
|
2413
2357
|
return {
|
|
2414
2358
|
order: 60,
|
|
2415
2359
|
slots: {
|
|
2416
2360
|
sidebar_content(ctx, input) {
|
|
2417
2361
|
sig.sessionId = input.session_id;
|
|
2418
|
-
return _$
|
|
2362
|
+
return _$createComponent2(SubAgentPanel, {
|
|
2363
|
+
api: panelApi,
|
|
2419
2364
|
get theme() {
|
|
2420
2365
|
return ctx.theme.current;
|
|
2421
2366
|
},
|
|
2422
|
-
api,
|
|
2423
2367
|
get lang() {
|
|
2424
2368
|
return sig.lang;
|
|
2425
2369
|
},
|
|
@@ -2440,14 +2384,13 @@ function createSidebarSlot(api, sig) {
|
|
|
2440
2384
|
}
|
|
2441
2385
|
};
|
|
2442
2386
|
}
|
|
2443
|
-
var KV_PREFIX = "subagent_magazine";
|
|
2444
2387
|
var tui = async (api) => {
|
|
2445
2388
|
const stored = String(api.kv.get(`${KV_PREFIX}.lang`, ""));
|
|
2446
2389
|
const initialLang = LANG_META.some((m) => m.code === stored) ? stored : detectLang();
|
|
2447
|
-
const [lang, setLang] =
|
|
2448
|
-
const [maxEntries, setMaxEntries] =
|
|
2449
|
-
const [sortOrder, setSortOrder] =
|
|
2450
|
-
const [scrollMode, setScrollMode] =
|
|
2390
|
+
const [lang, setLang] = createSignal3(initialLang);
|
|
2391
|
+
const [maxEntries, setMaxEntries] = createSignal3(parseInt(String(api.kv.get(`${KV_PREFIX}.max_entries`, "10")), 10) || 10);
|
|
2392
|
+
const [sortOrder, setSortOrder] = createSignal3(String(api.kv.get(`${KV_PREFIX}.order`, "desc")) === "asc" ? "asc" : "desc");
|
|
2393
|
+
const [scrollMode, setScrollMode] = createSignal3(String(api.kv.get(`${KV_PREFIX}.scroll_mode`, "wheel")) === "click" ? "click" : "wheel");
|
|
2451
2394
|
const signals = {
|
|
2452
2395
|
lang,
|
|
2453
2396
|
setLang,
|
|
@@ -2459,7 +2402,157 @@ var tui = async (api) => {
|
|
|
2459
2402
|
setScrollMode,
|
|
2460
2403
|
sessionId: ""
|
|
2461
2404
|
};
|
|
2462
|
-
|
|
2405
|
+
const v1Api = {
|
|
2406
|
+
kv: api.kv,
|
|
2407
|
+
usage: {
|
|
2408
|
+
readSessionTokens: (sid) => {
|
|
2409
|
+
if (!sid) return void 0;
|
|
2410
|
+
try {
|
|
2411
|
+
const msgs = api.state.session.messages(sid);
|
|
2412
|
+
if (msgs) {
|
|
2413
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
2414
|
+
const m = msgs[i];
|
|
2415
|
+
if (m.role !== "assistant") continue;
|
|
2416
|
+
const t = m.tokens;
|
|
2417
|
+
if (!t || !(Number(t.output) > 0)) continue;
|
|
2418
|
+
const ctx = (Number(t.input) || 0) + (Number(t.output) || 0) + (Number(t.reasoning) || 0) + (Number(t.cache?.read) || 0) + (Number(t.cache?.write) || 0);
|
|
2419
|
+
if (ctx > 0) return ctx;
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
return void 0;
|
|
2423
|
+
} catch {
|
|
2424
|
+
return void 0;
|
|
2425
|
+
}
|
|
2426
|
+
},
|
|
2427
|
+
readSessionCost: (sid) => {
|
|
2428
|
+
if (!sid) return void 0;
|
|
2429
|
+
try {
|
|
2430
|
+
const session = api.state.session.get(sid);
|
|
2431
|
+
if (session?.cost != null && session.cost > 0) return session.cost;
|
|
2432
|
+
const msgs = api.state.session.messages(sid);
|
|
2433
|
+
if (!msgs) return void 0;
|
|
2434
|
+
let total = 0;
|
|
2435
|
+
for (const m of msgs) {
|
|
2436
|
+
if (m.role === "assistant" && typeof m.cost === "number") total += m.cost;
|
|
2437
|
+
}
|
|
2438
|
+
return total > 0 ? total : void 0;
|
|
2439
|
+
} catch {
|
|
2440
|
+
return void 0;
|
|
2441
|
+
}
|
|
2442
|
+
},
|
|
2443
|
+
readSessionModel: (sid) => {
|
|
2444
|
+
if (!sid) return void 0;
|
|
2445
|
+
try {
|
|
2446
|
+
const msgs = api.state.session.messages(sid);
|
|
2447
|
+
if (msgs) {
|
|
2448
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
2449
|
+
const m = msgs[i];
|
|
2450
|
+
if (m.role === "assistant" && m.modelID) return String(m.modelID);
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
return void 0;
|
|
2454
|
+
} catch {
|
|
2455
|
+
return void 0;
|
|
2456
|
+
}
|
|
2457
|
+
},
|
|
2458
|
+
readSessionTodo: (sid) => {
|
|
2459
|
+
if (!sid) return void 0;
|
|
2460
|
+
try {
|
|
2461
|
+
const todos = api.state.session.todo(sid);
|
|
2462
|
+
if (!todos || todos.length === 0) return void 0;
|
|
2463
|
+
let done = 0;
|
|
2464
|
+
for (const t of todos) {
|
|
2465
|
+
if (t.status === "completed" || t.status === "cancelled") done++;
|
|
2466
|
+
}
|
|
2467
|
+
return {
|
|
2468
|
+
total: todos.length,
|
|
2469
|
+
done
|
|
2470
|
+
};
|
|
2471
|
+
} catch {
|
|
2472
|
+
return void 0;
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
},
|
|
2476
|
+
session: {
|
|
2477
|
+
get: (sid) => {
|
|
2478
|
+
try {
|
|
2479
|
+
return api.state.session.get(sid);
|
|
2480
|
+
} catch {
|
|
2481
|
+
return void 0;
|
|
2482
|
+
}
|
|
2483
|
+
},
|
|
2484
|
+
status: (sid) => {
|
|
2485
|
+
try {
|
|
2486
|
+
return api.state.session.status(sid);
|
|
2487
|
+
} catch {
|
|
2488
|
+
return void 0;
|
|
2489
|
+
}
|
|
2490
|
+
},
|
|
2491
|
+
messages: (sid) => {
|
|
2492
|
+
try {
|
|
2493
|
+
return api.state.session.messages(sid);
|
|
2494
|
+
} catch {
|
|
2495
|
+
return void 0;
|
|
2496
|
+
}
|
|
2497
|
+
},
|
|
2498
|
+
part: (messageID) => {
|
|
2499
|
+
try {
|
|
2500
|
+
return api.state.part(messageID);
|
|
2501
|
+
} catch {
|
|
2502
|
+
return void 0;
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
},
|
|
2506
|
+
event: {
|
|
2507
|
+
on: (type, cb) => {
|
|
2508
|
+
switch (type) {
|
|
2509
|
+
case "part.updated":
|
|
2510
|
+
return api.event.on("message.part.updated", (e) => cb({
|
|
2511
|
+
type,
|
|
2512
|
+
payload: {
|
|
2513
|
+
part: e.properties?.part
|
|
2514
|
+
}
|
|
2515
|
+
}));
|
|
2516
|
+
case "message.updated":
|
|
2517
|
+
return api.event.on("message.updated", () => cb({
|
|
2518
|
+
type
|
|
2519
|
+
}));
|
|
2520
|
+
case "session.idle":
|
|
2521
|
+
return api.event.on("session.idle", (e) => cb({
|
|
2522
|
+
type,
|
|
2523
|
+
payload: e.properties
|
|
2524
|
+
}));
|
|
2525
|
+
case "session.error":
|
|
2526
|
+
return api.event.on("session.error", (e) => cb({
|
|
2527
|
+
type,
|
|
2528
|
+
payload: e.properties
|
|
2529
|
+
}));
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
},
|
|
2533
|
+
client: {
|
|
2534
|
+
abort: (input) => api.client.session.abort(input).then(() => {
|
|
2535
|
+
})
|
|
2536
|
+
},
|
|
2537
|
+
route: {
|
|
2538
|
+
navigateSession: (sessionID) => api.route.navigate("session", {
|
|
2539
|
+
sessionID
|
|
2540
|
+
})
|
|
2541
|
+
},
|
|
2542
|
+
ui: {
|
|
2543
|
+
toast: (message, opts) => api.ui.toast({
|
|
2544
|
+
...opts,
|
|
2545
|
+
message
|
|
2546
|
+
})
|
|
2547
|
+
},
|
|
2548
|
+
settings: {
|
|
2549
|
+
lang: () => lang(),
|
|
2550
|
+
maxEntries: () => maxEntries(),
|
|
2551
|
+
sortOrder: () => sortOrder(),
|
|
2552
|
+
scrollMode: () => scrollMode()
|
|
2553
|
+
}
|
|
2554
|
+
};
|
|
2555
|
+
api.slots.register(createSidebarSlot(api, v1Api, signals));
|
|
2463
2556
|
api.command?.register(() => [{
|
|
2464
2557
|
title: "SubAgent Magazine: Language",
|
|
2465
2558
|
value: "subagent-lang",
|
|
@@ -2468,7 +2561,7 @@ var tui = async (api) => {
|
|
|
2468
2561
|
name: "subagent-lang"
|
|
2469
2562
|
},
|
|
2470
2563
|
onSelect: (dialog) => {
|
|
2471
|
-
dialog?.replace(() => _$
|
|
2564
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2472
2565
|
title: "Language / \u8BED\u8A00",
|
|
2473
2566
|
get options() {
|
|
2474
2567
|
return LANG_META.map((m) => ({
|
|
@@ -2496,7 +2589,7 @@ var tui = async (api) => {
|
|
|
2496
2589
|
},
|
|
2497
2590
|
onSelect: (dialog) => {
|
|
2498
2591
|
const t = createT(() => lang());
|
|
2499
|
-
dialog?.replace(() => _$
|
|
2592
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2500
2593
|
title: "Sort Order / \u6392\u5E8F\u65B9\u5F0F",
|
|
2501
2594
|
get options() {
|
|
2502
2595
|
return [{
|
|
@@ -2527,7 +2620,7 @@ var tui = async (api) => {
|
|
|
2527
2620
|
},
|
|
2528
2621
|
onSelect: (dialog) => {
|
|
2529
2622
|
const t = createT(() => lang());
|
|
2530
|
-
dialog?.replace(() => _$
|
|
2623
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2531
2624
|
title: "Scroll Mode / \u6EDA\u52A8\u6A21\u5F0F",
|
|
2532
2625
|
get options() {
|
|
2533
2626
|
return [{
|
|
@@ -2557,12 +2650,12 @@ var tui = async (api) => {
|
|
|
2557
2650
|
name: "subagent-max"
|
|
2558
2651
|
},
|
|
2559
2652
|
onSelect: (dialog) => {
|
|
2560
|
-
dialog?.replace(() => _$
|
|
2653
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogPrompt, {
|
|
2561
2654
|
title: "Max Visible Entries",
|
|
2562
2655
|
description: () => (() => {
|
|
2563
|
-
var _el$
|
|
2564
|
-
_$
|
|
2565
|
-
return _el
|
|
2656
|
+
var _el$ = _$createElement2("text");
|
|
2657
|
+
_$insertNode2(_el$, _$createTextNode2(`Number of entries to show in the sidebar (1\u201350)`));
|
|
2658
|
+
return _el$;
|
|
2566
2659
|
})(),
|
|
2567
2660
|
get value() {
|
|
2568
2661
|
return String(maxEntries());
|
|
@@ -2689,7 +2782,7 @@ var tui = async (api) => {
|
|
|
2689
2782
|
const curRaw = parseInt(String(api.kv.get(`${KV_PREFIX}.ttl_days`, "3")), 10);
|
|
2690
2783
|
const curDays = Number.isNaN(curRaw) ? 3 : curRaw;
|
|
2691
2784
|
const curLabel = curDays === 0 ? t("ttl.unlimited") : `${curDays}d`;
|
|
2692
|
-
dialog?.replace(() => _$
|
|
2785
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2693
2786
|
get title() {
|
|
2694
2787
|
return `${t("ttl.label")} (${curLabel})`;
|
|
2695
2788
|
},
|
|
@@ -2746,7 +2839,7 @@ var tui = async (api) => {
|
|
|
2746
2839
|
const msg = runningCount > 0 ? t("clear.prompt_running", {
|
|
2747
2840
|
n: runningCount
|
|
2748
2841
|
}) : t("clear.prompt");
|
|
2749
|
-
dialog?.replace(() => _$
|
|
2842
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogConfirm, {
|
|
2750
2843
|
get title() {
|
|
2751
2844
|
return t("clear.title");
|
|
2752
2845
|
},
|