opencode-subagent-magazine 1.5.2 → 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 -1484
- 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 -289
- 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 -1750
- 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,77 +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 || !(Number(t2.output) > 0)) continue;
|
|
759
|
-
const ctx = (Number(t2.input) || 0) + (Number(t2.output) || 0) + (Number(t2.reasoning) || 0) + (Number(t2.cache?.read) || 0) + (Number(t2.cache?.write) || 0);
|
|
760
|
-
if (ctx > 0) return ctx;
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
return void 0;
|
|
764
|
-
} catch {
|
|
765
|
-
return void 0;
|
|
766
|
-
}
|
|
767
|
-
};
|
|
768
|
-
const readSessionCost = (sid) => {
|
|
769
|
-
if (!sid) return void 0;
|
|
770
|
-
try {
|
|
771
|
-
const session = props.api.state.session.get(sid);
|
|
772
|
-
if (session?.cost != null && session.cost > 0) return session.cost;
|
|
773
|
-
const msgs = props.api.state.session.messages(sid);
|
|
774
|
-
if (!msgs) return void 0;
|
|
775
|
-
let total = 0;
|
|
776
|
-
for (const m of msgs) {
|
|
777
|
-
if (m.role === "assistant" && typeof m.cost === "number") total += m.cost;
|
|
778
|
-
}
|
|
779
|
-
return total > 0 ? total : void 0;
|
|
780
|
-
} catch {
|
|
781
|
-
return void 0;
|
|
782
|
-
}
|
|
783
|
-
};
|
|
784
|
-
const readSessionModel = (sid) => {
|
|
785
|
-
if (!sid) return void 0;
|
|
786
|
-
try {
|
|
787
|
-
const msgs = props.api.state.session.messages(sid);
|
|
788
|
-
if (msgs) {
|
|
789
|
-
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
790
|
-
const m = msgs[i];
|
|
791
|
-
if (m.role === "assistant" && m.modelID) return String(m.modelID);
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
return void 0;
|
|
795
|
-
} catch {
|
|
796
|
-
return void 0;
|
|
797
|
-
}
|
|
798
|
-
};
|
|
799
|
-
const readSessionTodo = (sid) => {
|
|
800
|
-
if (!sid) return void 0;
|
|
801
|
-
try {
|
|
802
|
-
const todos = props.api.state.session.todo(sid);
|
|
803
|
-
if (!todos || todos.length === 0) return void 0;
|
|
804
|
-
let done = 0;
|
|
805
|
-
for (const t2 of todos) {
|
|
806
|
-
if (t2.status === "completed" || t2.status === "cancelled") done++;
|
|
807
|
-
}
|
|
808
|
-
return {
|
|
809
|
-
total: todos.length,
|
|
810
|
-
done
|
|
811
|
-
};
|
|
812
|
-
} catch {
|
|
813
|
-
return void 0;
|
|
814
|
-
}
|
|
815
|
-
};
|
|
816
774
|
const upsertEntry = (partial) => {
|
|
817
775
|
setEntryMap((prev) => {
|
|
818
776
|
const existing = prev.get(partial.id);
|
|
@@ -834,12 +792,12 @@ function SubAgentPanel(props) {
|
|
|
834
792
|
const isDescendantOf = (childId, rootId) => {
|
|
835
793
|
const visited = /* @__PURE__ */ new Set();
|
|
836
794
|
try {
|
|
837
|
-
let current = props.api.
|
|
795
|
+
let current = props.api.session.get(childId);
|
|
838
796
|
while (current?.parentID) {
|
|
839
797
|
if (visited.has(current.id)) return false;
|
|
840
798
|
visited.add(current.id);
|
|
841
799
|
if (current.parentID === rootId) return true;
|
|
842
|
-
current = props.api.
|
|
800
|
+
current = props.api.session.get(current.parentID);
|
|
843
801
|
}
|
|
844
802
|
} catch {
|
|
845
803
|
}
|
|
@@ -852,40 +810,36 @@ function SubAgentPanel(props) {
|
|
|
852
810
|
const cancelEntry = async (entry) => {
|
|
853
811
|
const childId = entry.sessionId;
|
|
854
812
|
if (!childId) {
|
|
855
|
-
props.api.ui.toast({
|
|
856
|
-
title: entry.title || entry.agent
|
|
857
|
-
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
|
|
858
815
|
});
|
|
859
816
|
return;
|
|
860
817
|
}
|
|
861
818
|
try {
|
|
862
|
-
const child = props.api.
|
|
819
|
+
const child = props.api.session.get(childId);
|
|
863
820
|
if (!child?.parentID) {
|
|
864
|
-
props.api.ui.toast({
|
|
865
|
-
title: entry.title || entry.agent
|
|
866
|
-
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
|
|
867
823
|
});
|
|
868
824
|
return;
|
|
869
825
|
}
|
|
870
826
|
} catch {
|
|
871
|
-
props.api.ui.toast({
|
|
872
|
-
title: entry.title || entry.agent
|
|
873
|
-
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
|
|
874
829
|
});
|
|
875
830
|
return;
|
|
876
831
|
}
|
|
877
832
|
if (!isDescendantOf(childId, props.sessionId)) {
|
|
878
|
-
props.api.ui.toast({
|
|
879
|
-
title: entry.title || entry.agent
|
|
880
|
-
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
|
|
881
835
|
});
|
|
882
836
|
return;
|
|
883
837
|
}
|
|
884
838
|
try {
|
|
885
|
-
const st = props.api.
|
|
839
|
+
const st = props.api.session.status(childId);
|
|
886
840
|
if (st?.type !== "busy") {
|
|
887
|
-
const tokens = readSessionTokens(childId);
|
|
888
|
-
const cost = readSessionCost(childId);
|
|
841
|
+
const tokens = props.api.usage.readSessionTokens(childId);
|
|
842
|
+
const cost = props.api.usage.readSessionCost(childId);
|
|
889
843
|
upsertEntry({
|
|
890
844
|
id: entry.id,
|
|
891
845
|
title: entry.title,
|
|
@@ -899,9 +853,8 @@ function SubAgentPanel(props) {
|
|
|
899
853
|
return;
|
|
900
854
|
}
|
|
901
855
|
} catch {
|
|
902
|
-
props.api.ui.toast({
|
|
903
|
-
title: entry.title || entry.agent
|
|
904
|
-
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
|
|
905
858
|
});
|
|
906
859
|
return;
|
|
907
860
|
}
|
|
@@ -917,7 +870,7 @@ function SubAgentPanel(props) {
|
|
|
917
870
|
cancelReason: "manual"
|
|
918
871
|
});
|
|
919
872
|
try {
|
|
920
|
-
await props.api.client.
|
|
873
|
+
await props.api.client.abort({
|
|
921
874
|
sessionID: childId
|
|
922
875
|
});
|
|
923
876
|
upsertEntry({
|
|
@@ -929,9 +882,7 @@ function SubAgentPanel(props) {
|
|
|
929
882
|
sessionId: entry.sessionId,
|
|
930
883
|
abortAccepted: true
|
|
931
884
|
});
|
|
932
|
-
props.api.ui.toast(
|
|
933
|
-
message: t("cancel.label") + ": " + t("cancel.sent")
|
|
934
|
-
});
|
|
885
|
+
props.api.ui.toast(t("cancel.label") + ": " + t("cancel.sent"));
|
|
935
886
|
} catch (err) {
|
|
936
887
|
upsertEntry({
|
|
937
888
|
id: entry.id,
|
|
@@ -942,16 +893,13 @@ function SubAgentPanel(props) {
|
|
|
942
893
|
sessionId: entry.sessionId,
|
|
943
894
|
error: String(err)
|
|
944
895
|
});
|
|
945
|
-
props.api.ui.toast({
|
|
946
|
-
title: entry.title || entry.agent
|
|
947
|
-
message: t("cancel.label") + ": " + t("cancel.failed")
|
|
896
|
+
props.api.ui.toast(t("cancel.label") + ": " + t("cancel.failed"), {
|
|
897
|
+
title: entry.title || entry.agent
|
|
948
898
|
});
|
|
949
899
|
}
|
|
950
900
|
};
|
|
951
901
|
const handlePartUpdated = (event) => {
|
|
952
|
-
const
|
|
953
|
-
const props_ = e.properties;
|
|
954
|
-
const part = props_?.part;
|
|
902
|
+
const part = event.payload?.part;
|
|
955
903
|
if (!part) return;
|
|
956
904
|
if (part.type === "subtask") {
|
|
957
905
|
const agent = String(part.agent ?? "?");
|
|
@@ -1019,24 +967,23 @@ function SubAgentPanel(props) {
|
|
|
1019
967
|
}
|
|
1020
968
|
};
|
|
1021
969
|
const handleSessionEnd = (event, status) => {
|
|
1022
|
-
const
|
|
1023
|
-
const props_ = e.properties;
|
|
970
|
+
const props_ = event.payload;
|
|
1024
971
|
const sid = String(props_?.sessionID ?? "");
|
|
1025
972
|
if (!sid) return;
|
|
1026
|
-
const sessionTokens = readSessionTokens(sid);
|
|
1027
|
-
const sessionCost = readSessionCost(sid);
|
|
1028
|
-
const sessionModel = readSessionModel(sid);
|
|
1029
|
-
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);
|
|
1030
977
|
let sessionAgent;
|
|
1031
978
|
let errorMsg;
|
|
1032
979
|
try {
|
|
1033
|
-
const s = props.api.
|
|
980
|
+
const s = props.api.session.get(sid);
|
|
1034
981
|
sessionAgent = s?.agent;
|
|
1035
982
|
if (status === "error") {
|
|
1036
983
|
const evtErr = props_?.error;
|
|
1037
984
|
errorMsg = safeErrorMsg(evtErr) || safeErrorMsg(props_?.message);
|
|
1038
985
|
if (!errorMsg) {
|
|
1039
|
-
const msgs = props.api.
|
|
986
|
+
const msgs = props.api.session.messages(sid);
|
|
1040
987
|
if (msgs) {
|
|
1041
988
|
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
1042
989
|
const m = msgs[i];
|
|
@@ -1176,7 +1123,7 @@ function SubAgentPanel(props) {
|
|
|
1176
1123
|
return changed ? next : prev;
|
|
1177
1124
|
});
|
|
1178
1125
|
try {
|
|
1179
|
-
const sessionObj = props.api.
|
|
1126
|
+
const sessionObj = props.api.session.get(sid);
|
|
1180
1127
|
const parentSid = sessionObj?.parentID;
|
|
1181
1128
|
if (parentSid && parentSid !== props.sessionId) {
|
|
1182
1129
|
const parentCache = globalEntryCache.get(parentSid);
|
|
@@ -1189,7 +1136,7 @@ function SubAgentPanel(props) {
|
|
|
1189
1136
|
const data = loadSessionData();
|
|
1190
1137
|
const rec = data[parentSid];
|
|
1191
1138
|
if (rec?.entries) {
|
|
1192
|
-
const fallbackMap = new Map(rec.entries.map((
|
|
1139
|
+
const fallbackMap = new Map(rec.entries.map((e) => [e.id, e]));
|
|
1193
1140
|
found = tryMatchAndUpdate(fallbackMap, sid, status, nowTs);
|
|
1194
1141
|
if (found) {
|
|
1195
1142
|
data[parentSid] = {
|
|
@@ -1216,10 +1163,10 @@ function SubAgentPanel(props) {
|
|
|
1216
1163
|
}
|
|
1217
1164
|
setTimeout(() => {
|
|
1218
1165
|
if (disposed) return;
|
|
1219
|
-
const finalTokens = readSessionTokens(sid);
|
|
1220
|
-
const finalCost = readSessionCost(sid);
|
|
1221
|
-
const finalModel = readSessionModel(sid);
|
|
1222
|
-
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);
|
|
1223
1170
|
setEntryMap((prev) => {
|
|
1224
1171
|
let changed = false;
|
|
1225
1172
|
const next = new Map(prev);
|
|
@@ -1262,14 +1209,14 @@ function SubAgentPanel(props) {
|
|
|
1262
1209
|
if (entry.status === "running" && entry.sessionId) {
|
|
1263
1210
|
let isChild = false;
|
|
1264
1211
|
try {
|
|
1265
|
-
const s = props.api.
|
|
1212
|
+
const s = props.api.session.get(entry.sessionId);
|
|
1266
1213
|
isChild = s?.parentID === props.sessionId;
|
|
1267
1214
|
} catch {
|
|
1268
1215
|
}
|
|
1269
1216
|
if (!isChild) continue;
|
|
1270
|
-
const total = readSessionTokens(entry.sessionId);
|
|
1271
|
-
const todo = readSessionTodo(entry.sessionId);
|
|
1272
|
-
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);
|
|
1273
1220
|
const nextEntry = {
|
|
1274
1221
|
...entry
|
|
1275
1222
|
};
|
|
@@ -1297,7 +1244,7 @@ function SubAgentPanel(props) {
|
|
|
1297
1244
|
bump();
|
|
1298
1245
|
}, 500);
|
|
1299
1246
|
bump();
|
|
1300
|
-
const unsubPart = props.api.event.on("
|
|
1247
|
+
const unsubPart = props.api.event.on("part.updated", (e) => {
|
|
1301
1248
|
handlePartUpdated(e);
|
|
1302
1249
|
bump();
|
|
1303
1250
|
});
|
|
@@ -1353,10 +1300,10 @@ function SubAgentPanel(props) {
|
|
|
1353
1300
|
const scanRec = loadSessionData()[scanPSid];
|
|
1354
1301
|
const clearedIds = new Set(scanChild ? scanRec?.children?.[sid]?.clearedIds : scanRec?.clearedIds);
|
|
1355
1302
|
try {
|
|
1356
|
-
const msgs = props.api.
|
|
1303
|
+
const msgs = props.api.session.messages(sid);
|
|
1357
1304
|
if (msgs && msgs.length) {
|
|
1358
1305
|
for (const msg of msgs) {
|
|
1359
|
-
const parts = props.api.
|
|
1306
|
+
const parts = props.api.session.part(msg.id) ?? [];
|
|
1360
1307
|
for (const partRaw of parts) {
|
|
1361
1308
|
const part = partRaw;
|
|
1362
1309
|
if (part.type === "tool") {
|
|
@@ -1409,7 +1356,7 @@ function SubAgentPanel(props) {
|
|
|
1409
1356
|
let tokens;
|
|
1410
1357
|
const scanStMeta2 = st?.metadata;
|
|
1411
1358
|
const scanSubSid = scanStMeta2?.session_id !== void 0 ? String(scanStMeta2.session_id) : scanStMeta2?.sessionId !== void 0 ? String(scanStMeta2.sessionId) : void 0;
|
|
1412
|
-
if (scanSubSid) tokens = readSessionTokens(scanSubSid);
|
|
1359
|
+
if (scanSubSid) tokens = props.api.usage.readSessionTokens(scanSubSid);
|
|
1413
1360
|
const ended = status === "done";
|
|
1414
1361
|
next.set(id, {
|
|
1415
1362
|
id,
|
|
@@ -1437,10 +1384,10 @@ function SubAgentPanel(props) {
|
|
|
1437
1384
|
for (const [id, entry] of next) {
|
|
1438
1385
|
if (entry.status !== "running" && entry.status !== "cancel_requested" || !entry.sessionId) continue;
|
|
1439
1386
|
try {
|
|
1440
|
-
const st = props.api.
|
|
1387
|
+
const st = props.api.session.status(entry.sessionId);
|
|
1441
1388
|
if (!st || st.type !== "idle") continue;
|
|
1442
|
-
const tokens = readSessionTokens(entry.sessionId);
|
|
1443
|
-
const cost = readSessionCost(entry.sessionId);
|
|
1389
|
+
const tokens = props.api.usage.readSessionTokens(entry.sessionId);
|
|
1390
|
+
const cost = props.api.usage.readSessionCost(entry.sessionId);
|
|
1444
1391
|
const finalStatus = entry.status === "cancel_requested" && entry.abortAccepted ? "cancelled" : "done";
|
|
1445
1392
|
next.set(id, {
|
|
1446
1393
|
...entry,
|
|
@@ -2170,20 +2117,18 @@ function SubAgentPanel(props) {
|
|
|
2170
2117
|
if (!sessionId) return;
|
|
2171
2118
|
const result = await copyText(sessionId);
|
|
2172
2119
|
if (result.copied) {
|
|
2173
|
-
props.api.ui.toast({
|
|
2120
|
+
props.api.ui.toast(t("session.toast.copied"), {
|
|
2174
2121
|
variant: "success",
|
|
2175
2122
|
title: entry.title || entry.agent,
|
|
2176
|
-
message: t("session.toast.copied"),
|
|
2177
2123
|
duration: 2500
|
|
2178
2124
|
});
|
|
2179
2125
|
return;
|
|
2180
2126
|
}
|
|
2181
|
-
props.api.ui.toast({
|
|
2127
|
+
props.api.ui.toast(`${sessionId}
|
|
2128
|
+
|
|
2129
|
+
${t("session.toast.copy_failed")}`, {
|
|
2182
2130
|
variant: "warning",
|
|
2183
2131
|
title: entry.title || entry.agent,
|
|
2184
|
-
message: `${sessionId}
|
|
2185
|
-
|
|
2186
|
-
${t("session.toast.copy_failed")}`,
|
|
2187
2132
|
duration: 8e3
|
|
2188
2133
|
});
|
|
2189
2134
|
});
|
|
@@ -2244,9 +2189,7 @@ ${t("session.toast.copy_failed")}`,
|
|
|
2244
2189
|
_$setProp(_el$92, "onMouseOut", () => setHoveredOpen(void 0));
|
|
2245
2190
|
_$setProp(_el$92, "onMouseUp", () => {
|
|
2246
2191
|
if (entry.sessionId) {
|
|
2247
|
-
props.api.route.
|
|
2248
|
-
sessionID: entry.sessionId
|
|
2249
|
-
});
|
|
2192
|
+
props.api.route.navigateSession(entry.sessionId);
|
|
2250
2193
|
}
|
|
2251
2194
|
});
|
|
2252
2195
|
_$insert(_el$93, openPrefix);
|
|
@@ -2408,17 +2351,19 @@ ${t("session.toast.copy_failed")}`,
|
|
|
2408
2351
|
return _el$;
|
|
2409
2352
|
})();
|
|
2410
2353
|
}
|
|
2411
|
-
|
|
2354
|
+
|
|
2355
|
+
// src/index.tsx
|
|
2356
|
+
function createSidebarSlot(api, panelApi, sig) {
|
|
2412
2357
|
return {
|
|
2413
2358
|
order: 60,
|
|
2414
2359
|
slots: {
|
|
2415
2360
|
sidebar_content(ctx, input) {
|
|
2416
2361
|
sig.sessionId = input.session_id;
|
|
2417
|
-
return _$
|
|
2362
|
+
return _$createComponent2(SubAgentPanel, {
|
|
2363
|
+
api: panelApi,
|
|
2418
2364
|
get theme() {
|
|
2419
2365
|
return ctx.theme.current;
|
|
2420
2366
|
},
|
|
2421
|
-
api,
|
|
2422
2367
|
get lang() {
|
|
2423
2368
|
return sig.lang;
|
|
2424
2369
|
},
|
|
@@ -2439,14 +2384,13 @@ function createSidebarSlot(api, sig) {
|
|
|
2439
2384
|
}
|
|
2440
2385
|
};
|
|
2441
2386
|
}
|
|
2442
|
-
var KV_PREFIX = "subagent_magazine";
|
|
2443
2387
|
var tui = async (api) => {
|
|
2444
2388
|
const stored = String(api.kv.get(`${KV_PREFIX}.lang`, ""));
|
|
2445
2389
|
const initialLang = LANG_META.some((m) => m.code === stored) ? stored : detectLang();
|
|
2446
|
-
const [lang, setLang] =
|
|
2447
|
-
const [maxEntries, setMaxEntries] =
|
|
2448
|
-
const [sortOrder, setSortOrder] =
|
|
2449
|
-
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");
|
|
2450
2394
|
const signals = {
|
|
2451
2395
|
lang,
|
|
2452
2396
|
setLang,
|
|
@@ -2458,7 +2402,157 @@ var tui = async (api) => {
|
|
|
2458
2402
|
setScrollMode,
|
|
2459
2403
|
sessionId: ""
|
|
2460
2404
|
};
|
|
2461
|
-
|
|
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));
|
|
2462
2556
|
api.command?.register(() => [{
|
|
2463
2557
|
title: "SubAgent Magazine: Language",
|
|
2464
2558
|
value: "subagent-lang",
|
|
@@ -2467,7 +2561,7 @@ var tui = async (api) => {
|
|
|
2467
2561
|
name: "subagent-lang"
|
|
2468
2562
|
},
|
|
2469
2563
|
onSelect: (dialog) => {
|
|
2470
|
-
dialog?.replace(() => _$
|
|
2564
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2471
2565
|
title: "Language / \u8BED\u8A00",
|
|
2472
2566
|
get options() {
|
|
2473
2567
|
return LANG_META.map((m) => ({
|
|
@@ -2495,7 +2589,7 @@ var tui = async (api) => {
|
|
|
2495
2589
|
},
|
|
2496
2590
|
onSelect: (dialog) => {
|
|
2497
2591
|
const t = createT(() => lang());
|
|
2498
|
-
dialog?.replace(() => _$
|
|
2592
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2499
2593
|
title: "Sort Order / \u6392\u5E8F\u65B9\u5F0F",
|
|
2500
2594
|
get options() {
|
|
2501
2595
|
return [{
|
|
@@ -2526,7 +2620,7 @@ var tui = async (api) => {
|
|
|
2526
2620
|
},
|
|
2527
2621
|
onSelect: (dialog) => {
|
|
2528
2622
|
const t = createT(() => lang());
|
|
2529
|
-
dialog?.replace(() => _$
|
|
2623
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2530
2624
|
title: "Scroll Mode / \u6EDA\u52A8\u6A21\u5F0F",
|
|
2531
2625
|
get options() {
|
|
2532
2626
|
return [{
|
|
@@ -2556,12 +2650,12 @@ var tui = async (api) => {
|
|
|
2556
2650
|
name: "subagent-max"
|
|
2557
2651
|
},
|
|
2558
2652
|
onSelect: (dialog) => {
|
|
2559
|
-
dialog?.replace(() => _$
|
|
2653
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogPrompt, {
|
|
2560
2654
|
title: "Max Visible Entries",
|
|
2561
2655
|
description: () => (() => {
|
|
2562
|
-
var _el$
|
|
2563
|
-
_$
|
|
2564
|
-
return _el
|
|
2656
|
+
var _el$ = _$createElement2("text");
|
|
2657
|
+
_$insertNode2(_el$, _$createTextNode2(`Number of entries to show in the sidebar (1\u201350)`));
|
|
2658
|
+
return _el$;
|
|
2565
2659
|
})(),
|
|
2566
2660
|
get value() {
|
|
2567
2661
|
return String(maxEntries());
|
|
@@ -2688,7 +2782,7 @@ var tui = async (api) => {
|
|
|
2688
2782
|
const curRaw = parseInt(String(api.kv.get(`${KV_PREFIX}.ttl_days`, "3")), 10);
|
|
2689
2783
|
const curDays = Number.isNaN(curRaw) ? 3 : curRaw;
|
|
2690
2784
|
const curLabel = curDays === 0 ? t("ttl.unlimited") : `${curDays}d`;
|
|
2691
|
-
dialog?.replace(() => _$
|
|
2785
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2692
2786
|
get title() {
|
|
2693
2787
|
return `${t("ttl.label")} (${curLabel})`;
|
|
2694
2788
|
},
|
|
@@ -2745,7 +2839,7 @@ var tui = async (api) => {
|
|
|
2745
2839
|
const msg = runningCount > 0 ? t("clear.prompt_running", {
|
|
2746
2840
|
n: runningCount
|
|
2747
2841
|
}) : t("clear.prompt");
|
|
2748
|
-
dialog?.replace(() => _$
|
|
2842
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogConfirm, {
|
|
2749
2843
|
get title() {
|
|
2750
2844
|
return t("clear.title");
|
|
2751
2845
|
},
|