opencode-subagent-magazine 1.5.2 → 1.6.0-beta.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/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 +1237 -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 +388 -292
- 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 +350 -0
- package/dist/v2.js +3008 -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 +1465 -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 +306 -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.1";
|
|
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/
|
|
347
|
-
var
|
|
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
|
|
366
|
+
var SUBAGENT_TOOLS = /* @__PURE__ */ new Set(["task", "subagent", "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,17 +893,16 @@ 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;
|
|
904
|
+
const eventSid = event.payload?.sessionID !== void 0 ? String(event.payload.sessionID) : void 0;
|
|
905
|
+
if (eventSid !== void 0 && eventSid !== props.sessionId) return;
|
|
956
906
|
if (part.type === "subtask") {
|
|
957
907
|
const agent = String(part.agent ?? "?");
|
|
958
908
|
const prompt = String(part.prompt ?? "");
|
|
@@ -1001,7 +951,7 @@ function SubAgentPanel(props) {
|
|
|
1001
951
|
const hasChild = stMetaCheck?.session_id !== void 0 || stMetaCheck?.sessionId !== void 0;
|
|
1002
952
|
if (hasChild) status = "running";
|
|
1003
953
|
}
|
|
1004
|
-
const agent = String(part.subagent_type ?? input?.subagent_type ?? input?.category ?? tool);
|
|
954
|
+
const agent = String(part.subagent_type ?? input?.agent ?? input?.subagent_type ?? input?.category ?? tool);
|
|
1005
955
|
const prompt = String(input?.prompt ?? part.description ?? "");
|
|
1006
956
|
const desc = input?.description !== void 0 ? String(input.description) : "";
|
|
1007
957
|
const title = desc || truncate(prompt.replace(/\n/g, " ").replace(/\s+/g, " ").trim(), 40);
|
|
@@ -1019,24 +969,23 @@ function SubAgentPanel(props) {
|
|
|
1019
969
|
}
|
|
1020
970
|
};
|
|
1021
971
|
const handleSessionEnd = (event, status) => {
|
|
1022
|
-
const
|
|
1023
|
-
const props_ = e.properties;
|
|
972
|
+
const props_ = event.payload;
|
|
1024
973
|
const sid = String(props_?.sessionID ?? "");
|
|
1025
974
|
if (!sid) return;
|
|
1026
|
-
const sessionTokens = readSessionTokens(sid);
|
|
1027
|
-
const sessionCost = readSessionCost(sid);
|
|
1028
|
-
const sessionModel = readSessionModel(sid);
|
|
1029
|
-
const sessionTodo = readSessionTodo(sid);
|
|
975
|
+
const sessionTokens = props.api.usage.readSessionTokens(sid);
|
|
976
|
+
const sessionCost = props.api.usage.readSessionCost(sid);
|
|
977
|
+
const sessionModel = props.api.usage.readSessionModel(sid);
|
|
978
|
+
const sessionTodo = props.api.usage.readSessionTodo(sid);
|
|
1030
979
|
let sessionAgent;
|
|
1031
980
|
let errorMsg;
|
|
1032
981
|
try {
|
|
1033
|
-
const s = props.api.
|
|
982
|
+
const s = props.api.session.get(sid);
|
|
1034
983
|
sessionAgent = s?.agent;
|
|
1035
984
|
if (status === "error") {
|
|
1036
985
|
const evtErr = props_?.error;
|
|
1037
986
|
errorMsg = safeErrorMsg(evtErr) || safeErrorMsg(props_?.message);
|
|
1038
987
|
if (!errorMsg) {
|
|
1039
|
-
const msgs = props.api.
|
|
988
|
+
const msgs = props.api.session.messages(sid);
|
|
1040
989
|
if (msgs) {
|
|
1041
990
|
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
1042
991
|
const m = msgs[i];
|
|
@@ -1176,7 +1125,7 @@ function SubAgentPanel(props) {
|
|
|
1176
1125
|
return changed ? next : prev;
|
|
1177
1126
|
});
|
|
1178
1127
|
try {
|
|
1179
|
-
const sessionObj = props.api.
|
|
1128
|
+
const sessionObj = props.api.session.get(sid);
|
|
1180
1129
|
const parentSid = sessionObj?.parentID;
|
|
1181
1130
|
if (parentSid && parentSid !== props.sessionId) {
|
|
1182
1131
|
const parentCache = globalEntryCache.get(parentSid);
|
|
@@ -1189,7 +1138,7 @@ function SubAgentPanel(props) {
|
|
|
1189
1138
|
const data = loadSessionData();
|
|
1190
1139
|
const rec = data[parentSid];
|
|
1191
1140
|
if (rec?.entries) {
|
|
1192
|
-
const fallbackMap = new Map(rec.entries.map((
|
|
1141
|
+
const fallbackMap = new Map(rec.entries.map((e) => [e.id, e]));
|
|
1193
1142
|
found = tryMatchAndUpdate(fallbackMap, sid, status, nowTs);
|
|
1194
1143
|
if (found) {
|
|
1195
1144
|
data[parentSid] = {
|
|
@@ -1216,10 +1165,10 @@ function SubAgentPanel(props) {
|
|
|
1216
1165
|
}
|
|
1217
1166
|
setTimeout(() => {
|
|
1218
1167
|
if (disposed) return;
|
|
1219
|
-
const finalTokens = readSessionTokens(sid);
|
|
1220
|
-
const finalCost = readSessionCost(sid);
|
|
1221
|
-
const finalModel = readSessionModel(sid);
|
|
1222
|
-
const finalTodo = readSessionTodo(sid);
|
|
1168
|
+
const finalTokens = props.api.usage.readSessionTokens(sid);
|
|
1169
|
+
const finalCost = props.api.usage.readSessionCost(sid);
|
|
1170
|
+
const finalModel = props.api.usage.readSessionModel(sid);
|
|
1171
|
+
const finalTodo = props.api.usage.readSessionTodo(sid);
|
|
1223
1172
|
setEntryMap((prev) => {
|
|
1224
1173
|
let changed = false;
|
|
1225
1174
|
const next = new Map(prev);
|
|
@@ -1262,14 +1211,14 @@ function SubAgentPanel(props) {
|
|
|
1262
1211
|
if (entry.status === "running" && entry.sessionId) {
|
|
1263
1212
|
let isChild = false;
|
|
1264
1213
|
try {
|
|
1265
|
-
const s = props.api.
|
|
1214
|
+
const s = props.api.session.get(entry.sessionId);
|
|
1266
1215
|
isChild = s?.parentID === props.sessionId;
|
|
1267
1216
|
} catch {
|
|
1268
1217
|
}
|
|
1269
1218
|
if (!isChild) continue;
|
|
1270
|
-
const total = readSessionTokens(entry.sessionId);
|
|
1271
|
-
const todo = readSessionTodo(entry.sessionId);
|
|
1272
|
-
const model = entry.model ?? readSessionModel(entry.sessionId);
|
|
1219
|
+
const total = props.api.usage.readSessionTokens(entry.sessionId);
|
|
1220
|
+
const todo = props.api.usage.readSessionTodo(entry.sessionId);
|
|
1221
|
+
const model = entry.model ?? props.api.usage.readSessionModel(entry.sessionId);
|
|
1273
1222
|
const nextEntry = {
|
|
1274
1223
|
...entry
|
|
1275
1224
|
};
|
|
@@ -1297,7 +1246,7 @@ function SubAgentPanel(props) {
|
|
|
1297
1246
|
bump();
|
|
1298
1247
|
}, 500);
|
|
1299
1248
|
bump();
|
|
1300
|
-
const unsubPart = props.api.event.on("
|
|
1249
|
+
const unsubPart = props.api.event.on("part.updated", (e) => {
|
|
1301
1250
|
handlePartUpdated(e);
|
|
1302
1251
|
bump();
|
|
1303
1252
|
});
|
|
@@ -1353,10 +1302,10 @@ function SubAgentPanel(props) {
|
|
|
1353
1302
|
const scanRec = loadSessionData()[scanPSid];
|
|
1354
1303
|
const clearedIds = new Set(scanChild ? scanRec?.children?.[sid]?.clearedIds : scanRec?.clearedIds);
|
|
1355
1304
|
try {
|
|
1356
|
-
const msgs = props.api.
|
|
1305
|
+
const msgs = props.api.session.messages(sid);
|
|
1357
1306
|
if (msgs && msgs.length) {
|
|
1358
1307
|
for (const msg of msgs) {
|
|
1359
|
-
const parts = props.api.
|
|
1308
|
+
const parts = props.api.session.part(msg.id) ?? [];
|
|
1360
1309
|
for (const partRaw of parts) {
|
|
1361
1310
|
const part = partRaw;
|
|
1362
1311
|
if (part.type === "tool") {
|
|
@@ -1402,14 +1351,14 @@ function SubAgentPanel(props) {
|
|
|
1402
1351
|
}
|
|
1403
1352
|
}
|
|
1404
1353
|
const input = st?.input;
|
|
1405
|
-
const agent = String(part.subagent_type ?? input?.subagent_type ?? tool);
|
|
1354
|
+
const agent = String(part.subagent_type ?? input?.agent ?? input?.subagent_type ?? tool);
|
|
1406
1355
|
const prompt = String(input?.prompt ?? part.description ?? "");
|
|
1407
1356
|
const desc = input?.description !== void 0 ? String(input.description) : "";
|
|
1408
1357
|
const title = desc || truncate(prompt.replace(/\n/g, " ").trim(), 40);
|
|
1409
1358
|
let tokens;
|
|
1410
1359
|
const scanStMeta2 = st?.metadata;
|
|
1411
1360
|
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);
|
|
1361
|
+
if (scanSubSid) tokens = props.api.usage.readSessionTokens(scanSubSid);
|
|
1413
1362
|
const ended = status === "done";
|
|
1414
1363
|
next.set(id, {
|
|
1415
1364
|
id,
|
|
@@ -1437,10 +1386,10 @@ function SubAgentPanel(props) {
|
|
|
1437
1386
|
for (const [id, entry] of next) {
|
|
1438
1387
|
if (entry.status !== "running" && entry.status !== "cancel_requested" || !entry.sessionId) continue;
|
|
1439
1388
|
try {
|
|
1440
|
-
const st = props.api.
|
|
1389
|
+
const st = props.api.session.status(entry.sessionId);
|
|
1441
1390
|
if (!st || st.type !== "idle") continue;
|
|
1442
|
-
const tokens = readSessionTokens(entry.sessionId);
|
|
1443
|
-
const cost = readSessionCost(entry.sessionId);
|
|
1391
|
+
const tokens = props.api.usage.readSessionTokens(entry.sessionId);
|
|
1392
|
+
const cost = props.api.usage.readSessionCost(entry.sessionId);
|
|
1444
1393
|
const finalStatus = entry.status === "cancel_requested" && entry.abortAccepted ? "cancelled" : "done";
|
|
1445
1394
|
next.set(id, {
|
|
1446
1395
|
...entry,
|
|
@@ -2170,20 +2119,18 @@ function SubAgentPanel(props) {
|
|
|
2170
2119
|
if (!sessionId) return;
|
|
2171
2120
|
const result = await copyText(sessionId);
|
|
2172
2121
|
if (result.copied) {
|
|
2173
|
-
props.api.ui.toast({
|
|
2122
|
+
props.api.ui.toast(t("session.toast.copied"), {
|
|
2174
2123
|
variant: "success",
|
|
2175
2124
|
title: entry.title || entry.agent,
|
|
2176
|
-
message: t("session.toast.copied"),
|
|
2177
2125
|
duration: 2500
|
|
2178
2126
|
});
|
|
2179
2127
|
return;
|
|
2180
2128
|
}
|
|
2181
|
-
props.api.ui.toast({
|
|
2129
|
+
props.api.ui.toast(`${sessionId}
|
|
2130
|
+
|
|
2131
|
+
${t("session.toast.copy_failed")}`, {
|
|
2182
2132
|
variant: "warning",
|
|
2183
2133
|
title: entry.title || entry.agent,
|
|
2184
|
-
message: `${sessionId}
|
|
2185
|
-
|
|
2186
|
-
${t("session.toast.copy_failed")}`,
|
|
2187
2134
|
duration: 8e3
|
|
2188
2135
|
});
|
|
2189
2136
|
});
|
|
@@ -2244,9 +2191,7 @@ ${t("session.toast.copy_failed")}`,
|
|
|
2244
2191
|
_$setProp(_el$92, "onMouseOut", () => setHoveredOpen(void 0));
|
|
2245
2192
|
_$setProp(_el$92, "onMouseUp", () => {
|
|
2246
2193
|
if (entry.sessionId) {
|
|
2247
|
-
props.api.route.
|
|
2248
|
-
sessionID: entry.sessionId
|
|
2249
|
-
});
|
|
2194
|
+
props.api.route.navigateSession(entry.sessionId);
|
|
2250
2195
|
}
|
|
2251
2196
|
});
|
|
2252
2197
|
_$insert(_el$93, openPrefix);
|
|
@@ -2408,17 +2353,19 @@ ${t("session.toast.copy_failed")}`,
|
|
|
2408
2353
|
return _el$;
|
|
2409
2354
|
})();
|
|
2410
2355
|
}
|
|
2411
|
-
|
|
2356
|
+
|
|
2357
|
+
// src/index.tsx
|
|
2358
|
+
function createSidebarSlot(api, panelApi, sig) {
|
|
2412
2359
|
return {
|
|
2413
2360
|
order: 60,
|
|
2414
2361
|
slots: {
|
|
2415
2362
|
sidebar_content(ctx, input) {
|
|
2416
2363
|
sig.sessionId = input.session_id;
|
|
2417
|
-
return _$
|
|
2364
|
+
return _$createComponent2(SubAgentPanel, {
|
|
2365
|
+
api: panelApi,
|
|
2418
2366
|
get theme() {
|
|
2419
2367
|
return ctx.theme.current;
|
|
2420
2368
|
},
|
|
2421
|
-
api,
|
|
2422
2369
|
get lang() {
|
|
2423
2370
|
return sig.lang;
|
|
2424
2371
|
},
|
|
@@ -2439,14 +2386,13 @@ function createSidebarSlot(api, sig) {
|
|
|
2439
2386
|
}
|
|
2440
2387
|
};
|
|
2441
2388
|
}
|
|
2442
|
-
var KV_PREFIX = "subagent_magazine";
|
|
2443
2389
|
var tui = async (api) => {
|
|
2444
2390
|
const stored = String(api.kv.get(`${KV_PREFIX}.lang`, ""));
|
|
2445
2391
|
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] =
|
|
2392
|
+
const [lang, setLang] = createSignal3(initialLang);
|
|
2393
|
+
const [maxEntries, setMaxEntries] = createSignal3(parseInt(String(api.kv.get(`${KV_PREFIX}.max_entries`, "10")), 10) || 10);
|
|
2394
|
+
const [sortOrder, setSortOrder] = createSignal3(String(api.kv.get(`${KV_PREFIX}.order`, "desc")) === "asc" ? "asc" : "desc");
|
|
2395
|
+
const [scrollMode, setScrollMode] = createSignal3(String(api.kv.get(`${KV_PREFIX}.scroll_mode`, "wheel")) === "click" ? "click" : "wheel");
|
|
2450
2396
|
const signals = {
|
|
2451
2397
|
lang,
|
|
2452
2398
|
setLang,
|
|
@@ -2458,7 +2404,157 @@ var tui = async (api) => {
|
|
|
2458
2404
|
setScrollMode,
|
|
2459
2405
|
sessionId: ""
|
|
2460
2406
|
};
|
|
2461
|
-
|
|
2407
|
+
const v1Api = {
|
|
2408
|
+
kv: api.kv,
|
|
2409
|
+
usage: {
|
|
2410
|
+
readSessionTokens: (sid) => {
|
|
2411
|
+
if (!sid) return void 0;
|
|
2412
|
+
try {
|
|
2413
|
+
const msgs = api.state.session.messages(sid);
|
|
2414
|
+
if (msgs) {
|
|
2415
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
2416
|
+
const m = msgs[i];
|
|
2417
|
+
if (m.role !== "assistant") continue;
|
|
2418
|
+
const t = m.tokens;
|
|
2419
|
+
if (!t || !(Number(t.output) > 0)) continue;
|
|
2420
|
+
const ctx = (Number(t.input) || 0) + (Number(t.output) || 0) + (Number(t.reasoning) || 0) + (Number(t.cache?.read) || 0) + (Number(t.cache?.write) || 0);
|
|
2421
|
+
if (ctx > 0) return ctx;
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
return void 0;
|
|
2425
|
+
} catch {
|
|
2426
|
+
return void 0;
|
|
2427
|
+
}
|
|
2428
|
+
},
|
|
2429
|
+
readSessionCost: (sid) => {
|
|
2430
|
+
if (!sid) return void 0;
|
|
2431
|
+
try {
|
|
2432
|
+
const session = api.state.session.get(sid);
|
|
2433
|
+
if (session?.cost != null && session.cost > 0) return session.cost;
|
|
2434
|
+
const msgs = api.state.session.messages(sid);
|
|
2435
|
+
if (!msgs) return void 0;
|
|
2436
|
+
let total = 0;
|
|
2437
|
+
for (const m of msgs) {
|
|
2438
|
+
if (m.role === "assistant" && typeof m.cost === "number") total += m.cost;
|
|
2439
|
+
}
|
|
2440
|
+
return total > 0 ? total : void 0;
|
|
2441
|
+
} catch {
|
|
2442
|
+
return void 0;
|
|
2443
|
+
}
|
|
2444
|
+
},
|
|
2445
|
+
readSessionModel: (sid) => {
|
|
2446
|
+
if (!sid) return void 0;
|
|
2447
|
+
try {
|
|
2448
|
+
const msgs = api.state.session.messages(sid);
|
|
2449
|
+
if (msgs) {
|
|
2450
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
2451
|
+
const m = msgs[i];
|
|
2452
|
+
if (m.role === "assistant" && m.modelID) return String(m.modelID);
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
return void 0;
|
|
2456
|
+
} catch {
|
|
2457
|
+
return void 0;
|
|
2458
|
+
}
|
|
2459
|
+
},
|
|
2460
|
+
readSessionTodo: (sid) => {
|
|
2461
|
+
if (!sid) return void 0;
|
|
2462
|
+
try {
|
|
2463
|
+
const todos = api.state.session.todo(sid);
|
|
2464
|
+
if (!todos || todos.length === 0) return void 0;
|
|
2465
|
+
let done = 0;
|
|
2466
|
+
for (const t of todos) {
|
|
2467
|
+
if (t.status === "completed" || t.status === "cancelled") done++;
|
|
2468
|
+
}
|
|
2469
|
+
return {
|
|
2470
|
+
total: todos.length,
|
|
2471
|
+
done
|
|
2472
|
+
};
|
|
2473
|
+
} catch {
|
|
2474
|
+
return void 0;
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
},
|
|
2478
|
+
session: {
|
|
2479
|
+
get: (sid) => {
|
|
2480
|
+
try {
|
|
2481
|
+
return api.state.session.get(sid);
|
|
2482
|
+
} catch {
|
|
2483
|
+
return void 0;
|
|
2484
|
+
}
|
|
2485
|
+
},
|
|
2486
|
+
status: (sid) => {
|
|
2487
|
+
try {
|
|
2488
|
+
return api.state.session.status(sid);
|
|
2489
|
+
} catch {
|
|
2490
|
+
return void 0;
|
|
2491
|
+
}
|
|
2492
|
+
},
|
|
2493
|
+
messages: (sid) => {
|
|
2494
|
+
try {
|
|
2495
|
+
return api.state.session.messages(sid);
|
|
2496
|
+
} catch {
|
|
2497
|
+
return void 0;
|
|
2498
|
+
}
|
|
2499
|
+
},
|
|
2500
|
+
part: (messageID) => {
|
|
2501
|
+
try {
|
|
2502
|
+
return api.state.part(messageID);
|
|
2503
|
+
} catch {
|
|
2504
|
+
return void 0;
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
},
|
|
2508
|
+
event: {
|
|
2509
|
+
on: (type, cb) => {
|
|
2510
|
+
switch (type) {
|
|
2511
|
+
case "part.updated":
|
|
2512
|
+
return api.event.on("message.part.updated", (e) => cb({
|
|
2513
|
+
type,
|
|
2514
|
+
payload: {
|
|
2515
|
+
part: e.properties?.part
|
|
2516
|
+
}
|
|
2517
|
+
}));
|
|
2518
|
+
case "message.updated":
|
|
2519
|
+
return api.event.on("message.updated", () => cb({
|
|
2520
|
+
type
|
|
2521
|
+
}));
|
|
2522
|
+
case "session.idle":
|
|
2523
|
+
return api.event.on("session.idle", (e) => cb({
|
|
2524
|
+
type,
|
|
2525
|
+
payload: e.properties
|
|
2526
|
+
}));
|
|
2527
|
+
case "session.error":
|
|
2528
|
+
return api.event.on("session.error", (e) => cb({
|
|
2529
|
+
type,
|
|
2530
|
+
payload: e.properties
|
|
2531
|
+
}));
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
},
|
|
2535
|
+
client: {
|
|
2536
|
+
abort: (input) => api.client.session.abort(input).then(() => {
|
|
2537
|
+
})
|
|
2538
|
+
},
|
|
2539
|
+
route: {
|
|
2540
|
+
navigateSession: (sessionID) => api.route.navigate("session", {
|
|
2541
|
+
sessionID
|
|
2542
|
+
})
|
|
2543
|
+
},
|
|
2544
|
+
ui: {
|
|
2545
|
+
toast: (message, opts) => api.ui.toast({
|
|
2546
|
+
...opts,
|
|
2547
|
+
message
|
|
2548
|
+
})
|
|
2549
|
+
},
|
|
2550
|
+
settings: {
|
|
2551
|
+
lang: () => lang(),
|
|
2552
|
+
maxEntries: () => maxEntries(),
|
|
2553
|
+
sortOrder: () => sortOrder(),
|
|
2554
|
+
scrollMode: () => scrollMode()
|
|
2555
|
+
}
|
|
2556
|
+
};
|
|
2557
|
+
api.slots.register(createSidebarSlot(api, v1Api, signals));
|
|
2462
2558
|
api.command?.register(() => [{
|
|
2463
2559
|
title: "SubAgent Magazine: Language",
|
|
2464
2560
|
value: "subagent-lang",
|
|
@@ -2467,7 +2563,7 @@ var tui = async (api) => {
|
|
|
2467
2563
|
name: "subagent-lang"
|
|
2468
2564
|
},
|
|
2469
2565
|
onSelect: (dialog) => {
|
|
2470
|
-
dialog?.replace(() => _$
|
|
2566
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2471
2567
|
title: "Language / \u8BED\u8A00",
|
|
2472
2568
|
get options() {
|
|
2473
2569
|
return LANG_META.map((m) => ({
|
|
@@ -2495,7 +2591,7 @@ var tui = async (api) => {
|
|
|
2495
2591
|
},
|
|
2496
2592
|
onSelect: (dialog) => {
|
|
2497
2593
|
const t = createT(() => lang());
|
|
2498
|
-
dialog?.replace(() => _$
|
|
2594
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2499
2595
|
title: "Sort Order / \u6392\u5E8F\u65B9\u5F0F",
|
|
2500
2596
|
get options() {
|
|
2501
2597
|
return [{
|
|
@@ -2526,7 +2622,7 @@ var tui = async (api) => {
|
|
|
2526
2622
|
},
|
|
2527
2623
|
onSelect: (dialog) => {
|
|
2528
2624
|
const t = createT(() => lang());
|
|
2529
|
-
dialog?.replace(() => _$
|
|
2625
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2530
2626
|
title: "Scroll Mode / \u6EDA\u52A8\u6A21\u5F0F",
|
|
2531
2627
|
get options() {
|
|
2532
2628
|
return [{
|
|
@@ -2556,12 +2652,12 @@ var tui = async (api) => {
|
|
|
2556
2652
|
name: "subagent-max"
|
|
2557
2653
|
},
|
|
2558
2654
|
onSelect: (dialog) => {
|
|
2559
|
-
dialog?.replace(() => _$
|
|
2655
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogPrompt, {
|
|
2560
2656
|
title: "Max Visible Entries",
|
|
2561
2657
|
description: () => (() => {
|
|
2562
|
-
var _el$
|
|
2563
|
-
_$
|
|
2564
|
-
return _el
|
|
2658
|
+
var _el$ = _$createElement2("text");
|
|
2659
|
+
_$insertNode2(_el$, _$createTextNode2(`Number of entries to show in the sidebar (1\u201350)`));
|
|
2660
|
+
return _el$;
|
|
2565
2661
|
})(),
|
|
2566
2662
|
get value() {
|
|
2567
2663
|
return String(maxEntries());
|
|
@@ -2688,7 +2784,7 @@ var tui = async (api) => {
|
|
|
2688
2784
|
const curRaw = parseInt(String(api.kv.get(`${KV_PREFIX}.ttl_days`, "3")), 10);
|
|
2689
2785
|
const curDays = Number.isNaN(curRaw) ? 3 : curRaw;
|
|
2690
2786
|
const curLabel = curDays === 0 ? t("ttl.unlimited") : `${curDays}d`;
|
|
2691
|
-
dialog?.replace(() => _$
|
|
2787
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2692
2788
|
get title() {
|
|
2693
2789
|
return `${t("ttl.label")} (${curLabel})`;
|
|
2694
2790
|
},
|
|
@@ -2745,7 +2841,7 @@ var tui = async (api) => {
|
|
|
2745
2841
|
const msg = runningCount > 0 ? t("clear.prompt_running", {
|
|
2746
2842
|
n: runningCount
|
|
2747
2843
|
}) : t("clear.prompt");
|
|
2748
|
-
dialog?.replace(() => _$
|
|
2844
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogConfirm, {
|
|
2749
2845
|
get title() {
|
|
2750
2846
|
return t("clear.title");
|
|
2751
2847
|
},
|