opencode-subagent-magazine 1.6.1 → 1.7.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/dist/tui.js CHANGED
@@ -6,13 +6,17 @@ import { createComponent as _$createComponent2 } from "@opentui/solid";
6
6
  import { createSignal as createSignal3 } from "solid-js";
7
7
 
8
8
  // src/_version.ts
9
- var PLUGIN_VERSION = "1.6.1";
9
+ var PLUGIN_VERSION = "1.7.1";
10
10
 
11
11
  // src/i18n.ts
12
12
  var ZH_T = {
13
13
  "panel.title": "\u5B50\u4EE3\u7406",
14
14
  "status.none": "\u6682\u65E0\u5B50\u4EE3\u7406",
15
15
  "agent.label": "\u4EE3\u7406",
16
+ "origin.label": "\u6765\u6E90",
17
+ "origin.tool": "\u5B50\u4EE3\u7406\u8C03\u7528",
18
+ "origin.sub": "\u884D\u751F\u4F1A\u8BDD",
19
+ "origin.background": "\u540E\u53F0",
16
20
  "status.label": "\u72B6\u6001",
17
21
  "time.label": "\u8017\u65F6",
18
22
  "tokens.label": "\u4E0A\u4E0B\u6587",
@@ -50,6 +54,7 @@ var ZH_T = {
50
54
  "clear.prompt": "\u786E\u5B9A\u6E05\u9664\u5F53\u524D\u4F1A\u8BDD\u6240\u6709\u5B50\u4EE3\u7406\u8BB0\u5F55\uFF1F\u6B64\u64CD\u4F5C\u4E0D\u53EF\u64A4\u9500\u3002",
51
55
  "clear.prompt_running": "\u5F53\u524D\u6709 {n} \u4E2A\u8FD0\u884C\u4E2D\u7684\u5B50\u4EE3\u7406\uFF0C\u6E05\u9664\u540E\u5C06\u4E0D\u53EF\u6062\u590D\u3002\u786E\u5B9A\u7EE7\u7EED\uFF1F",
52
56
  "clear.done": "\u5DF2\u6E05\u9664 {n} \u6761\u5B50\u4EE3\u7406\u8BB0\u5F55",
57
+ "clear.failed": "\u6E05\u9664\u5931\u8D25",
53
58
  "clear.empty": "\u5F53\u524D\u4F1A\u8BDD\u65E0\u5B50\u4EE3\u7406\u8BB0\u5F55",
54
59
  "cancel.no_session": "\u5B50\u4F1A\u8BDD ID \u4E0D\u53EF\u7528",
55
60
  "cancel.not_child": "\u76EE\u6807\u4E0D\u662F\u5B50\u4F1A\u8BDD",
@@ -60,12 +65,35 @@ var ZH_T = {
60
65
  "cancel.sent": "\u5DF2\u53D1\u9001\u53D6\u6D88\u6307\u4EE4",
61
66
  "cancel.failed": "\u53D6\u6D88\u5931\u8D25",
62
67
  "borderShown": "\u9762\u677F\u8FB9\u6846 \u5DF2\u663E\u793A",
63
- "borderHidden": "\u9762\u677F\u8FB9\u6846 \u5DF2\u9690\u85CF"
68
+ "borderHidden": "\u9762\u677F\u8FB9\u6846 \u5DF2\u9690\u85CF",
69
+ "settings.title": "SubAgent Magazine \u2014 \u8BBE\u7F6E",
70
+ "settings.section.general": "\u901A\u7528",
71
+ "settings.lang": "\u8BED\u8A00",
72
+ "settings.max": "\u6700\u5927\u6761\u76EE\u6570",
73
+ "settings.order": "\u6392\u5E8F\u65B9\u5F0F",
74
+ "settings.scroll": "\u6EDA\u52A8\u6A21\u5F0F",
75
+ "settings.ttl": "\u4FDD\u7559\u671F\u9650",
76
+ "settings.border": "\u9762\u677F\u8FB9\u6846",
77
+ "settings.showEntryCost": "\u6BCF\u6761\u5B50\u4EE3\u7406\u663E\u793A\u8D39\u7528",
78
+ "settings.showEntryTime": "\u5217\u8868\u4E2D\u663E\u793A\u8017\u65F6",
79
+ "settings.showEntryTokens": "\u5217\u8868\u4E2D\u663E\u793A Token \u6570",
80
+ "settings.timeFormat": "\u65F6\u95F4\u683C\u5F0F",
81
+ "settings.showOrigin": "\u5217\u8868\u663E\u793A\u6765\u6E90\u6807\u8BB0",
82
+ "settings.dbSync": "\u672C\u5730\u6570\u636E\u5E93\u8865\u5168",
83
+ "settings.on": "\u5F00",
84
+ "settings.off": "\u5173",
85
+ "settings.saved": "\u5DF2\u4FDD\u5B58 {item}\uFF1A{value}",
86
+ "settings.invalid": "\u65E0\u6548\u7684\u6570\u503C",
87
+ "settings.close": "\u5173\u95ED"
64
88
  };
65
89
  var EN_T = {
66
90
  "panel.title": "SubAgent",
67
91
  "status.none": "No sub-agents yet",
68
92
  "agent.label": "agent",
93
+ "origin.label": "origin",
94
+ "origin.tool": "sub-agent call",
95
+ "origin.sub": "spawned session",
96
+ "origin.background": "background",
69
97
  "status.label": "status",
70
98
  "time.label": "time",
71
99
  "tokens.label": "tokens",
@@ -103,6 +131,7 @@ var EN_T = {
103
131
  "clear.prompt": "Clear all sub-agent records for this session? This cannot be undone.",
104
132
  "clear.prompt_running": "{n} sub-agent(s) are still running. Clearing will discard them permanently. Continue?",
105
133
  "clear.done": "Cleared {n} sub-agent record(s)",
134
+ "clear.failed": "Clear failed",
106
135
  "clear.empty": "No sub-agent records in this session",
107
136
  "cancel.no_session": "Child session ID is unavailable",
108
137
  "cancel.not_child": "Target is not a child session",
@@ -113,12 +142,35 @@ var EN_T = {
113
142
  "cancel.sent": "Cancel instruction sent",
114
143
  "cancel.failed": "Cancellation failed",
115
144
  "borderShown": "Panel border shown",
116
- "borderHidden": "Panel border hidden"
145
+ "borderHidden": "Panel border hidden",
146
+ "settings.title": "SubAgent Magazine \u2014 Settings",
147
+ "settings.section.general": "General",
148
+ "settings.lang": "Language",
149
+ "settings.max": "Max entries",
150
+ "settings.order": "Sort order",
151
+ "settings.scroll": "Scroll mode",
152
+ "settings.ttl": "Retention",
153
+ "settings.border": "Panel border",
154
+ "settings.showEntryCost": "Cost per sub-agent",
155
+ "settings.showEntryTime": "Elapsed time in list",
156
+ "settings.showEntryTokens": "Token count in list",
157
+ "settings.showOrigin": "Origin indicators in list",
158
+ "settings.timeFormat": "Time format",
159
+ "settings.dbSync": "Local database enrichment",
160
+ "settings.on": "on",
161
+ "settings.off": "off",
162
+ "settings.saved": "Saved {item}: {value}",
163
+ "settings.invalid": "Invalid value",
164
+ "settings.close": "Close"
117
165
  };
118
166
  var JA_T = {
119
167
  "panel.title": "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8",
120
168
  "status.none": "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u306A\u3057",
121
169
  "agent.label": "\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8",
170
+ "origin.label": "\u767A\u751F\u5143",
171
+ "origin.tool": "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u547C\u3073\u51FA\u3057",
172
+ "origin.sub": "\u751F\u6210\u3055\u308C\u305F\u30BB\u30C3\u30B7\u30E7\u30F3",
173
+ "origin.background": "\u30D0\u30C3\u30AF\u30B0\u30E9\u30A6\u30F3\u30C9",
122
174
  "status.label": "\u72B6\u614B",
123
175
  "time.label": "\u6642\u9593",
124
176
  "tokens.label": "\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8",
@@ -156,6 +208,7 @@ var JA_T = {
156
208
  "clear.prompt": "\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u5168\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u8A18\u9332\u3092\u524A\u9664\u3057\u307E\u3059\u304B\uFF1F\u3053\u306E\u64CD\u4F5C\u306F\u5143\u306B\u623B\u305B\u307E\u305B\u3093\u3002",
157
209
  "clear.prompt_running": "\u5B9F\u884C\u4E2D\u306E\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u304C {n} \u500B\u3042\u308A\u307E\u3059\u3002\u524A\u9664\u3059\u308B\u3068\u5FA9\u5143\u3067\u304D\u307E\u305B\u3093\u3002\u7D9A\u884C\u3057\u307E\u3059\u304B\uFF1F",
158
210
  "clear.done": "{n} \u4EF6\u306E\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u8A18\u9332\u3092\u524A\u9664\u3057\u307E\u3057\u305F",
211
+ "clear.failed": "\u30AF\u30EA\u30A2\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
159
212
  "clear.empty": "\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306B\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u8A18\u9332\u306F\u3042\u308A\u307E\u305B\u3093",
160
213
  "cancel.no_session": "\u5B50\u30BB\u30C3\u30B7\u30E7\u30F3 ID \u304C\u5229\u7528\u3067\u304D\u307E\u305B\u3093",
161
214
  "cancel.not_child": "\u5BFE\u8C61\u306F\u5B50\u30BB\u30C3\u30B7\u30E7\u30F3\u3067\u306F\u3042\u308A\u307E\u305B\u3093",
@@ -166,12 +219,35 @@ var JA_T = {
166
219
  "cancel.sent": "\u30AD\u30E3\u30F3\u30BB\u30EB\u6307\u793A\u3092\u9001\u4FE1\u3057\u307E\u3057\u305F",
167
220
  "cancel.failed": "\u30AD\u30E3\u30F3\u30BB\u30EB\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
168
221
  "borderShown": "\u30D1\u30CD\u30EB\u67A0\u7DDA \u8868\u793A",
169
- "borderHidden": "\u30D1\u30CD\u30EB\u67A0\u7DDA \u975E\u8868\u793A"
222
+ "borderHidden": "\u30D1\u30CD\u30EB\u67A0\u7DDA \u975E\u8868\u793A",
223
+ "settings.title": "SubAgent Magazine \u2014 \u8A2D\u5B9A",
224
+ "settings.section.general": "\u4E00\u822C",
225
+ "settings.lang": "\u8A00\u8A9E",
226
+ "settings.max": "\u6700\u5927\u8868\u793A\u6570",
227
+ "settings.order": "\u4E26\u3073\u9806",
228
+ "settings.scroll": "\u30B9\u30AF\u30ED\u30FC\u30EB",
229
+ "settings.ttl": "\u4FDD\u6301\u671F\u9593",
230
+ "settings.border": "\u30D1\u30CD\u30EB\u67A0",
231
+ "settings.showEntryCost": "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u6BCE\u306E\u8CBB\u7528",
232
+ "settings.showEntryTime": "\u4E00\u89A7\u306B\u6240\u8981\u6642\u9593\u3092\u8868\u793A",
233
+ "settings.showEntryTokens": "\u4E00\u89A7\u306B\u30C8\u30FC\u30AF\u30F3\u6570\u3092\u8868\u793A",
234
+ "settings.showOrigin": "\u4E00\u89A7\u306B\u7531\u6765\u30DE\u30FC\u30AF\u3092\u8868\u793A",
235
+ "settings.timeFormat": "\u6642\u9593\u5F62\u5F0F",
236
+ "settings.dbSync": "\u30ED\u30FC\u30AB\u30EBDB\u88DC\u5B8C",
237
+ "settings.on": "\u30AA\u30F3",
238
+ "settings.off": "\u30AA\u30D5",
239
+ "settings.saved": "\u4FDD\u5B58\u3057\u307E\u3057\u305F {item}\uFF1A{value}",
240
+ "settings.invalid": "\u7121\u52B9\u306A\u5024\u3067\u3059",
241
+ "settings.close": "\u9589\u3058\u308B"
170
242
  };
171
243
  var KO_T = {
172
244
  "panel.title": "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8",
173
245
  "status.none": "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uC5C6\uC74C",
174
246
  "agent.label": "\uC5D0\uC774\uC804\uD2B8",
247
+ "origin.label": "\uCD9C\uCC98",
248
+ "origin.tool": "\uD558\uC704 \uC5D0\uC774\uC804\uD2B8 \uD638\uCD9C",
249
+ "origin.sub": "\uC0DD\uC131\uB41C \uC138\uC158",
250
+ "origin.background": "\uBC31\uADF8\uB77C\uC6B4\uB4DC",
175
251
  "status.label": "\uC0C1\uD0DC",
176
252
  "time.label": "\uC2DC\uAC04",
177
253
  "tokens.label": "\uCEE8\uD14D\uC2A4\uD2B8",
@@ -209,6 +285,7 @@ var KO_T = {
209
285
  "clear.prompt": "\uC774 \uC138\uC158\uC758 \uBAA8\uB4E0 \uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uAE30\uB85D\uC744 \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C? \uC774 \uC791\uC5C5\uC740 \uB418\uB3CC\uB9B4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
210
286
  "clear.prompt_running": "\uC2E4\uD589 \uC911\uC778 \uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8\uAC00 {n}\uAC1C \uC788\uC2B5\uB2C8\uB2E4. \uC0AD\uC81C\uD558\uBA74 \uBCF5\uAD6C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uACC4\uC18D\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
211
287
  "clear.done": "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uAE30\uB85D {n}\uAC1C\uB97C \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4",
288
+ "clear.failed": "\uC9C0\uC6B0\uAE30\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4",
212
289
  "clear.empty": "\uC774 \uC138\uC158\uC5D0 \uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uAE30\uB85D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4",
213
290
  "cancel.no_session": "\uD558\uC704 \uC138\uC158 ID\uB97C \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
214
291
  "cancel.not_child": "\uB300\uC0C1\uC774 \uD558\uC704 \uC138\uC158\uC774 \uC544\uB2D9\uB2C8\uB2E4",
@@ -219,7 +296,26 @@ var KO_T = {
219
296
  "cancel.sent": "\uCDE8\uC18C \uC9C0\uC2DC\uB97C \uBCF4\uB0C8\uC2B5\uB2C8\uB2E4",
220
297
  "cancel.failed": "\uCDE8\uC18C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4",
221
298
  "borderShown": "\uD328\uB110 \uD14C\uB450\uB9AC \uD45C\uC2DC",
222
- "borderHidden": "\uD328\uB110 \uD14C\uB450\uB9AC \uC228\uAE40"
299
+ "borderHidden": "\uD328\uB110 \uD14C\uB450\uB9AC \uC228\uAE40",
300
+ "settings.title": "SubAgent Magazine \u2014 \uC124\uC815",
301
+ "settings.section.general": "\uC77C\uBC18",
302
+ "settings.lang": "\uC5B8\uC5B4",
303
+ "settings.max": "\uCD5C\uB300 \uD56D\uBAA9 \uC218",
304
+ "settings.order": "\uC815\uB82C \uC21C\uC11C",
305
+ "settings.scroll": "\uC2A4\uD06C\uB864 \uBAA8\uB4DC",
306
+ "settings.ttl": "\uBCF4\uC874 \uAE30\uAC04",
307
+ "settings.border": "\uD328\uB110 \uD14C\uB450\uB9AC",
308
+ "settings.showEntryCost": "\uD558\uC704 \uC5D0\uC774\uC804\uD2B8\uBCC4 \uBE44\uC6A9",
309
+ "settings.showEntryTime": "\uBAA9\uB85D\uC5D0 \uC18C\uC694 \uC2DC\uAC04 \uD45C\uC2DC",
310
+ "settings.showEntryTokens": "\uBAA9\uB85D\uC5D0 \uD1A0\uD070 \uC218 \uD45C\uC2DC",
311
+ "settings.showOrigin": "\uBAA9\uB85D\uC5D0 \uCD9C\uCC98 \uC544\uC774\uCF58 \uD45C\uC2DC",
312
+ "settings.timeFormat": "\uC2DC\uAC04 \uD615\uC2DD",
313
+ "settings.dbSync": "\uB85C\uCEEC DB \uBCF4\uC644",
314
+ "settings.on": "\uCF2C",
315
+ "settings.off": "\uB054",
316
+ "settings.saved": "\uC800\uC7A5\uB428 {item}: {value}",
317
+ "settings.invalid": "\uC798\uBABB\uB41C \uAC12",
318
+ "settings.close": "\uB2EB\uAE30"
223
319
  };
224
320
  var LANGS = { zh: ZH_T, en: EN_T, ja: JA_T, ko: KO_T };
225
321
  var LANG_META = [
@@ -260,8 +356,126 @@ var SETTING_KEYS = {
260
356
  scrollMode: `${KV_PREFIX}.scroll_mode`,
261
357
  open: `${KV_PREFIX}.open`,
262
358
  ttlDays: `${KV_PREFIX}.ttl_days`,
263
- border: `${KV_PREFIX}.border`
359
+ border: `${KV_PREFIX}.border`,
360
+ showEntryCost: `${KV_PREFIX}.show_entry_cost`,
361
+ showEntryTime: `${KV_PREFIX}.show_entry_time`,
362
+ showEntryTokens: `${KV_PREFIX}.show_entry_tokens`,
363
+ timeFormat: `${KV_PREFIX}.time_format`,
364
+ showOrigin: `${KV_PREFIX}.show_origin`,
365
+ dbSync: `${KV_PREFIX}.db_sync`
264
366
  };
367
+ function loadSessionData(kv) {
368
+ try {
369
+ const raw = kv.get(SESSION_DATA_KEY, "{}");
370
+ return JSON.parse(String(raw));
371
+ } catch {
372
+ return {};
373
+ }
374
+ }
375
+ function updateSessionData(kv, mutator) {
376
+ try {
377
+ if (typeof kv.update === "function") {
378
+ return kv.update(SESSION_DATA_KEY, (raw) => {
379
+ const data2 = parseSessionData(raw);
380
+ mutator(data2);
381
+ return JSON.stringify(data2);
382
+ });
383
+ }
384
+ const data = loadSessionData(kv);
385
+ mutator(data);
386
+ kv.set(SESSION_DATA_KEY, JSON.stringify(data));
387
+ } catch {
388
+ }
389
+ }
390
+ function parseSessionData(raw) {
391
+ try {
392
+ return JSON.parse(String(raw ?? "{}"));
393
+ } catch {
394
+ return {};
395
+ }
396
+ }
397
+
398
+ // src/core/format.ts
399
+ function charColumns(c) {
400
+ const code = c.codePointAt(0) ?? 0;
401
+ if (code < 32) return 0;
402
+ if (code < 127) return 1;
403
+ if (code < 160) return 0;
404
+ 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)
405
+ return 2;
406
+ return 1;
407
+ }
408
+ function visualWidth(s) {
409
+ let w = 0;
410
+ for (const c of s) w += charColumns(c);
411
+ return w;
412
+ }
413
+ function truncate(text, maxCols) {
414
+ if (visualWidth(text) <= maxCols) return text;
415
+ let cols = 0;
416
+ let i = 0;
417
+ for (const c of text) {
418
+ const w = charColumns(c);
419
+ if (cols + w > maxCols - 1) break;
420
+ cols += w;
421
+ i += c.length;
422
+ }
423
+ return text.slice(0, i) + "\u2026";
424
+ }
425
+ function fmtDurationShort(ms, running) {
426
+ if (running && ms < 2e3) return "";
427
+ if (ms < 1e3) return (ms / 1e3).toFixed(2) + "s";
428
+ if (ms < 6e4) return (ms / 1e3).toFixed(2) + "s";
429
+ const m = Math.floor(ms / 6e4);
430
+ const s = Math.round(ms % 6e4 / 1e3);
431
+ return `${m}m${s}s`;
432
+ }
433
+ var TIME_FORMATS = ["short", "decimal", "clock", "compact", "seconds"];
434
+ var TIME_FORMAT_SAMPLES = {
435
+ decimal: "45.3s \xB7 9.5m \xB7 1.9h",
436
+ short: "45.32s \xB7 112m35s",
437
+ clock: "0:45 \xB7 1:52:35",
438
+ compact: "45s \xB7 1h52m",
439
+ seconds: "45s \xB7 6755s"
440
+ };
441
+ function fmtDuration(ms, running, mode = "short") {
442
+ if (running && ms < 2e3) return "";
443
+ const t = Number.isFinite(ms) && ms > 0 ? ms : 0;
444
+ switch (mode) {
445
+ case "short":
446
+ return fmtDurationShort(t, false);
447
+ case "compact": {
448
+ if (t < 6e4) return `${Math.floor(t / 1e3)}s`;
449
+ if (t < 36e5) return `${Math.floor(t / 6e4)}m${Math.floor(t % 6e4 / 1e3)}s`;
450
+ return `${Math.floor(t / 36e5)}h${Math.floor(t % 36e5 / 6e4)}m`;
451
+ }
452
+ case "clock": {
453
+ const s = Math.floor(t % 6e4 / 1e3);
454
+ if (t < 36e5) return `${Math.floor(t / 6e4)}:${String(s).padStart(2, "0")}`;
455
+ const m = Math.floor(t % 36e5 / 6e4);
456
+ return `${Math.floor(t / 36e5)}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
457
+ }
458
+ case "seconds":
459
+ return `${Math.floor(t / 1e3)}s`;
460
+ case "decimal":
461
+ default: {
462
+ if (t < 59950) return `${(t / 1e3).toFixed(1)}s`;
463
+ if (t < 3597e3) return `${(t / 6e4).toFixed(1)}m`;
464
+ return `${(t / 36e5).toFixed(1)}h`;
465
+ }
466
+ }
467
+ }
468
+ function fmtTokens(n) {
469
+ if (n < 1e3) return `${n}`;
470
+ if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
471
+ return `${(n / 1e6).toFixed(1)}M`;
472
+ }
473
+ function safeErrorMsg(err) {
474
+ if (!err) return "";
475
+ if (typeof err === "string") return err;
476
+ if (typeof err === "object") return String(err.message || err.code || "");
477
+ return "";
478
+ }
265
479
 
266
480
  // src/panel/SubAgentPanel.tsx
267
481
  import { createTextNode as _$createTextNode } from "@opentui/solid";
@@ -375,52 +589,10 @@ async function copyText(text) {
375
589
 
376
590
  // src/core/types.ts
377
591
  var SUBAGENT_TOOLS = /* @__PURE__ */ new Set(["task", "subagent", "delegate", "call_omo_agent"]);
378
-
379
- // src/core/format.ts
380
- function charColumns(c) {
381
- const code = c.codePointAt(0) ?? 0;
382
- if (code < 32) return 0;
383
- if (code < 127) return 1;
384
- if (code < 160) return 0;
385
- 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)
386
- return 2;
387
- return 1;
388
- }
389
- function visualWidth(s) {
390
- let w = 0;
391
- for (const c of s) w += charColumns(c);
392
- return w;
393
- }
394
- function truncate(text, maxCols) {
395
- if (visualWidth(text) <= maxCols) return text;
396
- let cols = 0;
397
- let i = 0;
398
- for (const c of text) {
399
- const w = charColumns(c);
400
- if (cols + w > maxCols - 1) break;
401
- cols += w;
402
- i += c.length;
403
- }
404
- return text.slice(0, i) + "\u2026";
405
- }
406
- function fmtDurationShort(ms, running) {
407
- if (running && ms < 2e3) return "";
408
- if (ms < 1e3) return (ms / 1e3).toFixed(2) + "s";
409
- if (ms < 6e4) return (ms / 1e3).toFixed(2) + "s";
410
- const m = Math.floor(ms / 6e4);
411
- const s = Math.round(ms % 6e4 / 1e3);
412
- return `${m}m${s}s`;
413
- }
414
- function fmtTokens(n) {
415
- if (n < 1e3) return `${n}`;
416
- if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
417
- return `${(n / 1e6).toFixed(1)}M`;
418
- }
419
- function safeErrorMsg(err) {
420
- if (!err) return "";
421
- if (typeof err === "string") return err;
422
- if (typeof err === "object") return String(err.message || err.code || "");
423
- return "";
592
+ function isBackgroundInput(input) {
593
+ if (!input || typeof input !== "object") return false;
594
+ const i = input;
595
+ return i.background === true || i.run_in_background === true;
424
596
  }
425
597
 
426
598
  // src/core/color.ts
@@ -521,21 +693,84 @@ function upsertSubEntry(entries, partial, now = Date.now()) {
521
693
  ...partial,
522
694
  id: existing?.id ?? partial.id,
523
695
  startedAt: existing?.startedAt || partial.startedAt || now,
524
- endedAt: ended ? existing?.endedAt || now : void 0
696
+ endedAt: ended ? existing?.endedAt ?? partial.endedAt ?? now : void 0
525
697
  });
526
698
  return next;
527
699
  }
700
+ function statusRank(status) {
701
+ if (status === "running") return 0;
702
+ if (status === "cancel_requested") return 1;
703
+ return 2;
704
+ }
705
+ var isTerminalStatus = (status) => statusRank(status) === 2;
706
+ function minDefined(a, b) {
707
+ if (a === void 0) return b;
708
+ if (b === void 0) return a;
709
+ return Math.min(a, b);
710
+ }
711
+ function maxDefined(a, b) {
712
+ if (a === void 0) return b;
713
+ if (b === void 0) return a;
714
+ return Math.max(a, b);
715
+ }
716
+ function mergeSubEntry(base, incoming) {
717
+ const successor = statusRank(incoming.status) > statusRank(base.status) ? incoming : base;
718
+ const status = successor.status;
719
+ const ended = isTerminalStatus(status);
720
+ return {
721
+ ...base,
722
+ ...incoming,
723
+ id: base.id,
724
+ status,
725
+ sessionId: incoming.sessionId ?? base.sessionId,
726
+ startedAt: minDefined(base.startedAt, incoming.startedAt) ?? base.startedAt,
727
+ endedAt: ended ? base.endedAt ?? incoming.endedAt ?? Date.now() : void 0,
728
+ tokens: maxDefined(base.tokens, incoming.tokens),
729
+ cost: maxDefined(base.cost, incoming.cost),
730
+ model: incoming.model ?? base.model,
731
+ todoTotal: maxDefined(base.todoTotal, incoming.todoTotal),
732
+ todoDone: maxDefined(base.todoDone, incoming.todoDone),
733
+ error: incoming.error ?? base.error,
734
+ cancelRequestedAt: minDefined(base.cancelRequestedAt, incoming.cancelRequestedAt),
735
+ abortAccepted: base.abortAccepted || incoming.abortAccepted || void 0,
736
+ cancelReason: incoming.cancelReason ?? base.cancelReason
737
+ };
738
+ }
739
+ function mergeSubEntries(base, incoming) {
740
+ const out = /* @__PURE__ */ new Map();
741
+ for (const entry of base) out.set(entry.id, entry);
742
+ for (const entry of incoming) {
743
+ const key = findSubEntryKey(out, entry.id, entry.sessionId);
744
+ if (!key) {
745
+ out.set(entry.id, entry);
746
+ continue;
747
+ }
748
+ out.set(key, mergeSubEntry(out.get(key), entry));
749
+ }
750
+ return out;
751
+ }
528
752
 
529
753
  // src/panel/SubAgentPanel.tsx
530
754
  var LEFT_PAD = 4;
531
755
  var INDENT = 2;
756
+ function partMetadata(part, st) {
757
+ const partMeta = part?.metadata;
758
+ if (partMeta && Object.keys(partMeta).length > 0) return partMeta;
759
+ const stateMeta = st?.metadata;
760
+ return stateMeta && Object.keys(stateMeta).length > 0 ? stateMeta : void 0;
761
+ }
762
+ function validModel(model) {
763
+ if (typeof model !== "string") return false;
764
+ const s = model.trim();
765
+ return s.length > 0 && s !== "[object Object]" && !s.startsWith("{");
766
+ }
532
767
  function SubAgentPanel(props) {
533
768
  const t = createT(() => props.lang());
534
769
  const SESSION_DATA_KEY2 = `${KV_PREFIX}.session_data`;
535
770
  const ttlDaysRaw = parseInt(String(props.api.kv.get(`${KV_PREFIX}.ttl_days`, "3")), 10);
536
771
  const ttlDays = Number.isNaN(ttlDaysRaw) ? 3 : ttlDaysRaw;
537
772
  const TTL_MS = ttlDays * 24 * 60 * 60 * 1e3;
538
- const loadSessionData = () => {
773
+ const loadSessionData2 = () => {
539
774
  try {
540
775
  const raw = props.api.kv.get(SESSION_DATA_KEY2, "{}");
541
776
  return JSON.parse(String(raw));
@@ -543,11 +778,32 @@ function SubAgentPanel(props) {
543
778
  return {};
544
779
  }
545
780
  };
546
- const saveSessionData = (data) => {
547
- try {
548
- props.api.kv.set(SESSION_DATA_KEY2, JSON.stringify(data));
549
- } catch {
550
- }
781
+ const mutateSessionData = (mutator) => {
782
+ void Promise.resolve(updateSessionData(props.api.kv, mutator)).catch(() => {
783
+ });
784
+ };
785
+ const ensureRootRecord = (data, sid) => {
786
+ const rec = data[sid];
787
+ if (rec) return rec;
788
+ const created = {
789
+ ts: Date.now(),
790
+ entries: [],
791
+ scroll: 0,
792
+ expanded: "",
793
+ children: {}
794
+ };
795
+ data[sid] = created;
796
+ return created;
797
+ };
798
+ const ensureChildRecord = (data, parentSid, sid) => {
799
+ const parent = ensureRootRecord(data, parentSid);
800
+ if (!parent.children) parent.children = {};
801
+ if (!parent.children[sid]) parent.children[sid] = {
802
+ scroll: 0,
803
+ expanded: "",
804
+ entries: []
805
+ };
806
+ return parent.children[sid];
551
807
  };
552
808
  const resolveParent = (sid) => {
553
809
  try {
@@ -571,7 +827,7 @@ function SubAgentPanel(props) {
571
827
  parentSid,
572
828
  isChild
573
829
  } = resolveParent(sid);
574
- const rec = loadSessionData()[parentSid];
830
+ const rec = loadSessionData2()[parentSid];
575
831
  if (rec) {
576
832
  const source = isChild ? rec.children?.[sid]?.entries : rec.entries;
577
833
  if (source) {
@@ -589,129 +845,71 @@ function SubAgentPanel(props) {
589
845
  clearTimeout(persistTimer);
590
846
  persistTimer = setTimeout(() => {
591
847
  try {
592
- const data = loadSessionData();
848
+ mutateSessionData((data) => {
849
+ const {
850
+ parentSid,
851
+ isChild
852
+ } = resolveParent(sid);
853
+ if (isChild) {
854
+ const parent = ensureRootRecord(data, parentSid);
855
+ const child = ensureChildRecord(data, parentSid, sid);
856
+ child.entries = [...mergeSubEntries(child.entries ?? [], entries2.values()).values()];
857
+ parent.ts = Date.now();
858
+ } else {
859
+ const rec = ensureRootRecord(data, sid);
860
+ rec.ts = Date.now();
861
+ rec.entries = [...mergeSubEntries(rec.entries ?? [], entries2.values()).values()];
862
+ }
863
+ });
864
+ } catch {
865
+ }
866
+ }, 200);
867
+ };
868
+ const persistScroll = (sid, scroll) => {
869
+ try {
870
+ mutateSessionData((data) => {
593
871
  const {
594
872
  parentSid,
595
873
  isChild
596
874
  } = resolveParent(sid);
597
875
  if (isChild) {
598
- if (!data[parentSid]) data[parentSid] = {
599
- ts: Date.now(),
600
- entries: [],
601
- scroll: 0,
602
- expanded: "",
603
- children: {}
604
- };
605
- if (!data[parentSid].children) data[parentSid].children = {};
606
- if (!data[parentSid].children[sid]) data[parentSid].children[sid] = {
607
- scroll: 0,
608
- expanded: "",
609
- entries: []
610
- };
611
- data[parentSid].children[sid] = {
612
- ...data[parentSid].children[sid],
613
- entries: [...entries2.values()]
614
- };
876
+ ensureChildRecord(data, parentSid, sid).scroll = scroll;
615
877
  } else {
616
- data[sid] = {
617
- ...data[sid],
618
- ts: Date.now(),
619
- entries: [...entries2.values()],
620
- children: data[sid]?.children ?? {}
621
- };
878
+ const rec = ensureRootRecord(data, sid);
879
+ rec.ts = Date.now();
880
+ rec.scroll = scroll;
622
881
  }
623
- saveSessionData(data);
624
- } catch {
625
- }
626
- }, 200);
627
- };
628
- const persistScroll = (sid, scroll) => {
629
- try {
630
- const data = loadSessionData();
631
- const {
632
- parentSid,
633
- isChild
634
- } = resolveParent(sid);
635
- if (isChild) {
636
- if (!data[parentSid]) data[parentSid] = {
637
- ts: Date.now(),
638
- entries: [],
639
- scroll: 0,
640
- expanded: "",
641
- children: {}
642
- };
643
- if (!data[parentSid].children) data[parentSid].children = {};
644
- if (!data[parentSid].children[sid]) data[parentSid].children[sid] = {
645
- scroll: 0,
646
- expanded: "",
647
- entries: []
648
- };
649
- data[parentSid].children[sid] = {
650
- ...data[parentSid].children[sid],
651
- scroll
652
- };
653
- } else {
654
- data[sid] = {
655
- ...data[sid],
656
- ts: Date.now(),
657
- scroll,
658
- children: data[sid]?.children ?? {}
659
- };
660
- }
661
- saveSessionData(data);
882
+ });
662
883
  } catch {
663
884
  }
664
885
  };
665
886
  const persistExpanded = (sid, expanded2) => {
666
887
  try {
667
- const data = loadSessionData();
668
- const {
669
- parentSid,
670
- isChild
671
- } = resolveParent(sid);
672
- if (isChild) {
673
- if (!data[parentSid]) data[parentSid] = {
674
- ts: Date.now(),
675
- entries: [],
676
- scroll: 0,
677
- expanded: "",
678
- children: {}
679
- };
680
- if (!data[parentSid].children) data[parentSid].children = {};
681
- if (!data[parentSid].children[sid]) data[parentSid].children[sid] = {
682
- scroll: 0,
683
- expanded: "",
684
- entries: []
685
- };
686
- data[parentSid].children[sid] = {
687
- ...data[parentSid].children[sid],
688
- expanded: expanded2
689
- };
690
- } else {
691
- data[sid] = {
692
- ...data[sid],
693
- ts: Date.now(),
694
- expanded: expanded2,
695
- children: data[sid]?.children ?? {}
696
- };
697
- }
698
- saveSessionData(data);
888
+ mutateSessionData((data) => {
889
+ const {
890
+ parentSid,
891
+ isChild
892
+ } = resolveParent(sid);
893
+ if (isChild) {
894
+ ensureChildRecord(data, parentSid, sid).expanded = expanded2;
895
+ } else {
896
+ const rec = ensureRootRecord(data, sid);
897
+ rec.ts = Date.now();
898
+ rec.expanded = expanded2;
899
+ }
900
+ });
699
901
  } catch {
700
902
  }
701
903
  };
702
904
  const cleanupOldSessions = () => {
703
905
  if (ttlDays <= 0) return;
704
906
  try {
705
- const data = loadSessionData();
706
907
  const cutoff = Date.now() - TTL_MS;
707
- let changed = false;
708
- for (const sid of Object.keys(data)) {
709
- if (data[sid].ts < cutoff) {
710
- delete data[sid];
711
- changed = true;
908
+ mutateSessionData((data) => {
909
+ for (const sid of Object.keys(data)) {
910
+ if (data[sid].ts < cutoff) delete data[sid];
712
911
  }
713
- }
714
- if (changed) saveSessionData(data);
912
+ });
715
913
  } catch {
716
914
  }
717
915
  };
@@ -731,38 +929,22 @@ function SubAgentPanel(props) {
731
929
  if (needsImmediateFlush) {
732
930
  clearTimeout(persistTimer);
733
931
  try {
734
- const data = loadSessionData();
735
- const {
736
- parentSid,
737
- isChild
738
- } = resolveParent(props.sessionId);
739
- if (isChild) {
740
- if (!data[parentSid]) data[parentSid] = {
741
- ts: Date.now(),
742
- entries: [],
743
- scroll: 0,
744
- expanded: "",
745
- children: {}
746
- };
747
- if (!data[parentSid].children) data[parentSid].children = {};
748
- if (!data[parentSid].children[props.sessionId]) data[parentSid].children[props.sessionId] = {
749
- scroll: 0,
750
- expanded: "",
751
- entries: []
752
- };
753
- data[parentSid].children[props.sessionId] = {
754
- ...data[parentSid].children[props.sessionId],
755
- entries: [...next.values()]
756
- };
757
- } else {
758
- data[props.sessionId] = {
759
- ...data[props.sessionId],
760
- ts: Date.now(),
761
- entries: [...next.values()],
762
- children: data[props.sessionId]?.children ?? {}
763
- };
764
- }
765
- saveSessionData(data);
932
+ mutateSessionData((data) => {
933
+ const {
934
+ parentSid,
935
+ isChild
936
+ } = resolveParent(props.sessionId);
937
+ if (isChild) {
938
+ const parent = ensureRootRecord(data, parentSid);
939
+ const child = ensureChildRecord(data, parentSid, props.sessionId);
940
+ child.entries = [...mergeSubEntries(child.entries ?? [], next.values()).values()];
941
+ parent.ts = Date.now();
942
+ } else {
943
+ const rec = ensureRootRecord(data, props.sessionId);
944
+ rec.ts = Date.now();
945
+ rec.entries = [...mergeSubEntries(rec.entries ?? [], next.values()).values()];
946
+ }
947
+ });
766
948
  } catch {
767
949
  }
768
950
  } else {
@@ -786,7 +968,7 @@ function SubAgentPanel(props) {
786
968
  parentSid,
787
969
  isChild
788
970
  } = resolveParent(props.sessionId);
789
- const rec = loadSessionData()[parentSid];
971
+ const rec = loadSessionData2()[parentSid];
790
972
  if (rec) return isChild ? rec.children?.[props.sessionId]?.expanded || void 0 : rec.expanded || void 0;
791
973
  } catch {
792
974
  }
@@ -804,7 +986,7 @@ function SubAgentPanel(props) {
804
986
  parentSid,
805
987
  isChild
806
988
  } = resolveParent(props.sessionId);
807
- const rec = loadSessionData()[parentSid];
989
+ const rec = loadSessionData2()[parentSid];
808
990
  return isChild ? rec?.children?.[props.sessionId]?.scroll ?? 0 : rec?.scroll ?? 0;
809
991
  } catch {
810
992
  return 0;
@@ -930,7 +1112,9 @@ function SubAgentPanel(props) {
930
1112
  const part = event.payload?.part;
931
1113
  if (!part) return;
932
1114
  const eventSid = event.payload?.sessionID !== void 0 ? String(event.payload.sessionID) : void 0;
933
- if (event.scope === "global" && eventSid !== props.sessionId) return;
1115
+ if (event.scope === "global" && eventSid !== props.sessionId) {
1116
+ return;
1117
+ }
934
1118
  if (part.type === "subtask") {
935
1119
  const agent = String(part.agent ?? "?");
936
1120
  const prompt = String(part.prompt ?? "");
@@ -947,7 +1131,8 @@ function SubAgentPanel(props) {
947
1131
  prompt,
948
1132
  sessionId: subSid,
949
1133
  status: "running",
950
- model: modelId
1134
+ model: modelId,
1135
+ origin: "sub"
951
1136
  });
952
1137
  }
953
1138
  if (part.type === "tool") {
@@ -959,7 +1144,7 @@ function SubAgentPanel(props) {
959
1144
  if (rawStatus === "error") {
960
1145
  const id2 = `tool:${String(part.id ?? "")}`;
961
1146
  if (!part.id) return;
962
- const stMeta2 = st?.metadata;
1147
+ const stMeta2 = partMetadata(part, st);
963
1148
  const errorSid = stMeta2?.session_id !== void 0 ? String(stMeta2.session_id) : stMeta2?.sessionId !== void 0 ? String(stMeta2.sessionId) : void 0;
964
1149
  const key = findSubEntryKey(entryMap(), id2, errorSid);
965
1150
  const existing = key ? entryMap().get(key) : void 0;
@@ -970,7 +1155,9 @@ function SubAgentPanel(props) {
970
1155
  agent: existing.agent,
971
1156
  prompt: existing.prompt,
972
1157
  sessionId: existing.sessionId ?? errorSid,
973
- status: "error"
1158
+ status: "error",
1159
+ origin: "tool",
1160
+ background: isBackgroundInput(st?.input)
974
1161
  });
975
1162
  }
976
1163
  return;
@@ -978,8 +1165,8 @@ function SubAgentPanel(props) {
978
1165
  const input = st?.input;
979
1166
  let status = "running";
980
1167
  if (rawStatus === "completed") status = "done";
981
- if ((input?.run_in_background === true || input?.background === true) && status === "done") {
982
- const stMetaCheck = st?.metadata;
1168
+ if (isBackgroundInput(input) && status === "done") {
1169
+ const stMetaCheck = partMetadata(part, st);
983
1170
  const hasChild = stMetaCheck?.session_id !== void 0 || stMetaCheck?.sessionId !== void 0;
984
1171
  if (hasChild) status = "running";
985
1172
  }
@@ -988,7 +1175,7 @@ function SubAgentPanel(props) {
988
1175
  const desc = input?.description !== void 0 ? String(input.description) : "";
989
1176
  const title = desc || truncate(prompt.replace(/\n/g, " ").replace(/\s+/g, " ").trim(), 40);
990
1177
  const id = `tool:${String(part.id ?? crypto.randomUUID())}`;
991
- const stMeta = st?.metadata;
1178
+ const stMeta = partMetadata(part, st);
992
1179
  const subSid = stMeta?.session_id !== void 0 ? String(stMeta.session_id) : stMeta?.sessionId !== void 0 ? String(stMeta.sessionId) : void 0;
993
1180
  upsertEntry({
994
1181
  id,
@@ -996,7 +1183,9 @@ function SubAgentPanel(props) {
996
1183
  agent,
997
1184
  prompt,
998
1185
  sessionId: subSid,
999
- status
1186
+ status,
1187
+ origin: "tool",
1188
+ background: isBackgroundInput(input)
1000
1189
  });
1001
1190
  }
1002
1191
  };
@@ -1176,30 +1365,39 @@ function SubAgentPanel(props) {
1176
1365
  found = tryMatchAndUpdate(parentCache, sid, status, nowTs);
1177
1366
  }
1178
1367
  if (!found) {
1179
- const data = loadSessionData();
1368
+ const data = loadSessionData2();
1180
1369
  const rec = data[parentSid];
1181
- if (rec?.entries) {
1370
+ if (rec?.entries?.length) {
1182
1371
  const fallbackMap = new Map(rec.entries.map((e) => [e.id, e]));
1183
1372
  found = tryMatchAndUpdate(fallbackMap, sid, status, nowTs);
1184
1373
  if (found) {
1185
- data[parentSid] = {
1186
- ...rec,
1187
- ts: nowTs,
1188
- entries: [...fallbackMap.values()]
1189
- };
1190
- saveSessionData(data);
1191
1374
  globalEntryCache.set(parentSid, fallbackMap);
1375
+ mutateSessionData((latest) => {
1376
+ const latestRec = latest[parentSid];
1377
+ latest[parentSid] = {
1378
+ ...latestRec ?? rec,
1379
+ ts: nowTs,
1380
+ entries: [...mergeSubEntries(latestRec?.entries ?? [], fallbackMap.values()).values()]
1381
+ };
1382
+ });
1192
1383
  }
1193
1384
  }
1194
1385
  }
1195
1386
  if (found && parentCache) {
1196
- const data = loadSessionData();
1197
- data[parentSid] = {
1198
- ...data[parentSid],
1199
- ts: nowTs,
1200
- entries: [...parentCache.values()]
1201
- };
1202
- saveSessionData(data);
1387
+ mutateSessionData((data) => {
1388
+ const rec = data[parentSid];
1389
+ data[parentSid] = {
1390
+ ...rec ?? {
1391
+ entries: [],
1392
+ scroll: 0,
1393
+ expanded: "",
1394
+ children: {},
1395
+ ts: nowTs
1396
+ },
1397
+ ts: nowTs,
1398
+ entries: [...mergeSubEntries(rec?.entries ?? [], parentCache.values()).values()]
1399
+ };
1400
+ });
1203
1401
  }
1204
1402
  }
1205
1403
  } catch {
@@ -1234,56 +1432,417 @@ function SubAgentPanel(props) {
1234
1432
  }
1235
1433
  return changed ? next : prev;
1236
1434
  });
1237
- bump();
1238
- }, 150);
1435
+ bump();
1436
+ }, 150);
1437
+ };
1438
+ const bump = () => setRenderTick((v) => v + 1);
1439
+ const settleIdleEntries = (prev) => {
1440
+ let changed = false;
1441
+ const next = new Map(prev);
1442
+ for (const [id, entry] of next) {
1443
+ if (entry.status !== "running" && entry.status !== "cancel_requested") continue;
1444
+ let sid = entry.sessionId;
1445
+ if (!sid) {
1446
+ try {
1447
+ const callId = String(entry.id).replace(/^tool:/, "");
1448
+ sid = props.api.session.resolveChild?.({
1449
+ parentId: props.sessionId,
1450
+ callId,
1451
+ agent: entry.agent,
1452
+ startedAt: entry.startedAt
1453
+ });
1454
+ } catch {
1455
+ }
1456
+ if (!sid) continue;
1457
+ next.set(id, {
1458
+ ...entry,
1459
+ sessionId: sid
1460
+ });
1461
+ changed = true;
1462
+ }
1463
+ try {
1464
+ const st = props.api.session.status(sid);
1465
+ if (!st || st.type !== "idle") continue;
1466
+ const tokens = props.api.usage.readSessionTokens(sid);
1467
+ const cost = props.api.usage.readSessionCost(sid);
1468
+ const finalStatus = entry.status === "cancel_requested" && entry.abortAccepted ? "cancelled" : "done";
1469
+ next.set(id, {
1470
+ ...entry,
1471
+ sessionId: sid,
1472
+ status: finalStatus,
1473
+ endedAt: Date.now(),
1474
+ tokens: tokens ?? entry.tokens,
1475
+ cost: cost ?? entry.cost
1476
+ });
1477
+ changed = true;
1478
+ } catch {
1479
+ }
1480
+ }
1481
+ return changed ? next : prev;
1482
+ };
1483
+ const reconcileIdleEntries = () => {
1484
+ try {
1485
+ const before = entryMap();
1486
+ const after = settleIdleEntries(before);
1487
+ if (after !== before) setEntryMap(after);
1488
+ } catch {
1489
+ }
1490
+ };
1491
+ const runSessionScan = (sid, replace) => {
1492
+ let msgs;
1493
+ try {
1494
+ msgs = props.api.session.messages(sid);
1495
+ } catch {
1496
+ }
1497
+ if (!msgs || msgs.length === 0) return false;
1498
+ setEntryMapRaw((prev) => {
1499
+ const next = replace ? new Map(globalEntryCache.get(sid) ?? loadEntries(sid)) : new Map(prev);
1500
+ const {
1501
+ parentSid: scanPSid,
1502
+ isChild: scanChild
1503
+ } = resolveParent(sid);
1504
+ const scanRec = loadSessionData2()[scanPSid];
1505
+ const clearedIds = new Set(scanChild ? scanRec?.children?.[sid]?.clearedIds : scanRec?.clearedIds);
1506
+ try {
1507
+ for (const msg of msgs) {
1508
+ const parts = props.api.session.part(msg.id) ?? [];
1509
+ for (const partRaw of parts) {
1510
+ const part = partRaw;
1511
+ if (part.type === "tool") {
1512
+ const tool = String(part.tool ?? "");
1513
+ if (!SUBAGENT_TOOLS.has(tool)) continue;
1514
+ const id = `tool:${String(part.id ?? "")}`;
1515
+ if (!part.id) continue;
1516
+ const st = part.state;
1517
+ const rawStatus = String(st?.status ?? "");
1518
+ const scanInput = st?.input;
1519
+ const scanMeta = partMetadata(part, st);
1520
+ let scanSubSid = scanMeta?.session_id !== void 0 ? String(scanMeta.session_id) : scanMeta?.sessionId !== void 0 ? String(scanMeta.sessionId) : scanMeta?.sessionID !== void 0 ? String(scanMeta.sessionID) : void 0;
1521
+ if (!scanSubSid) {
1522
+ try {
1523
+ scanSubSid = props.api.session.resolveChild?.({
1524
+ parentId: sid,
1525
+ callId: String(part.id)
1526
+ });
1527
+ } catch {
1528
+ }
1529
+ }
1530
+ const existingKey = findSubEntryKey(next, id, scanSubSid);
1531
+ const exists = existingKey ? next.get(existingKey) : void 0;
1532
+ if (!exists && clearedIds.has(id)) continue;
1533
+ if ((rawStatus === "pending" || rawStatus === "") && !exists) continue;
1534
+ if (rawStatus === "error") {
1535
+ if (exists && exists.status === "running") {
1536
+ next.set(existingKey ?? id, {
1537
+ ...exists,
1538
+ status: "error",
1539
+ endedAt: Date.now()
1540
+ });
1541
+ }
1542
+ continue;
1543
+ }
1544
+ const settled = exists !== void 0 && exists.status !== "running" && exists.status !== "cancel_requested";
1545
+ const needsRepair = settled && (exists.sessionId === void 0 || exists.tokens === void 0 || exists.cost === void 0 || !validModel(exists.model));
1546
+ if (settled && !needsRepair) continue;
1547
+ let status = "running";
1548
+ if (rawStatus === "completed") status = "done";
1549
+ if (isBackgroundInput(scanInput) && status === "done") {
1550
+ if (scanSubSid !== void 0) status = "running";
1551
+ }
1552
+ if (status === "done" && scanSubSid) {
1553
+ try {
1554
+ const childStatus = props.api.session.status(scanSubSid);
1555
+ if (childStatus && childStatus.type !== "idle") status = "running";
1556
+ } catch {
1557
+ }
1558
+ }
1559
+ if (settled) {
1560
+ status = exists.status;
1561
+ } else if (exists && status === "running") {
1562
+ if (!rawStatus) {
1563
+ const msgTokens = msg?.tokens;
1564
+ if (msgTokens && (Number(msgTokens.input) > 0 || Number(msgTokens.output) > 0)) {
1565
+ status = "done";
1566
+ } else {
1567
+ continue;
1568
+ }
1569
+ } else {
1570
+ continue;
1571
+ }
1572
+ }
1573
+ const agent = String(part.subagent_type ?? scanInput?.agent ?? scanInput?.subagent_type ?? tool);
1574
+ const prompt = String(scanInput?.prompt ?? part.description ?? "");
1575
+ const desc = scanInput?.description !== void 0 ? String(scanInput.description) : "";
1576
+ const title = desc || truncate(prompt.replace(/\n/g, " ").trim(), 40);
1577
+ let tokens;
1578
+ if (scanSubSid) tokens = props.api.usage.readSessionTokens(scanSubSid);
1579
+ let cost;
1580
+ if (scanSubSid) cost = props.api.usage.readSessionCost(scanSubSid);
1581
+ let model;
1582
+ if (scanSubSid) model = props.api.usage.readSessionModel(scanSubSid);
1583
+ const entryKey = existingKey ?? id;
1584
+ next.set(entryKey, {
1585
+ ...exists ?? {
1586
+ id
1587
+ },
1588
+ title: title || exists?.title || "",
1589
+ agent: exists?.agent ?? agent,
1590
+ prompt: prompt || exists?.prompt || "",
1591
+ // Preserve existing values (from handleSessionEnd / KV) — scan must not overwrite
1592
+ tokens: exists?.tokens ?? tokens,
1593
+ cost: exists?.cost ?? cost,
1594
+ model: validModel(exists?.model) ? exists.model : model,
1595
+ sessionId: exists?.sessionId ?? scanSubSid,
1596
+ status,
1597
+ startedAt: exists?.startedAt || Date.now(),
1598
+ endedAt: exists?.endedAt ?? (status === "done" ? Date.now() : void 0),
1599
+ origin: "tool",
1600
+ background: isBackgroundInput(scanInput) || exists?.background === true
1601
+ });
1602
+ if (entryKey !== id) next.delete(id);
1603
+ }
1604
+ }
1605
+ }
1606
+ } catch {
1607
+ }
1608
+ return next;
1609
+ });
1610
+ setEntryMapRaw((prev) => settleIdleEntries(prev));
1611
+ const snapshot = entryMap();
1612
+ if (snapshot.size > 0) {
1613
+ globalEntryCache.set(sid, new Map(snapshot));
1614
+ persistEntries(sid, snapshot);
1615
+ }
1616
+ return true;
1617
+ };
1618
+ let rescanTimer;
1619
+ const missingNewestToolPart = () => {
1620
+ try {
1621
+ const msgs = props.api.session.messages(props.sessionId);
1622
+ if (!msgs || msgs.length === 0) return false;
1623
+ const map = entryMap();
1624
+ const from = Math.max(0, msgs.length - 6);
1625
+ for (let i = msgs.length - 1; i >= from; i--) {
1626
+ const parts = props.api.session.part(msgs[i]?.id) ?? [];
1627
+ for (const part of parts) {
1628
+ if (!part || part.type !== "tool") continue;
1629
+ if (!SUBAGENT_TOOLS.has(String(part.tool ?? ""))) continue;
1630
+ const partId = String(part.id ?? "");
1631
+ if (!partId) continue;
1632
+ const st = part.state;
1633
+ const rawStatus = String(st?.status ?? "");
1634
+ if (rawStatus !== "running" && rawStatus !== "completed") continue;
1635
+ const id = `tool:${partId}`;
1636
+ const meta = partMetadata(part, st);
1637
+ const subSid = meta?.session_id !== void 0 ? String(meta.session_id) : meta?.sessionId !== void 0 ? String(meta.sessionId) : void 0;
1638
+ const key = findSubEntryKey(map, id, subSid);
1639
+ const entry = key ? map.get(key) : void 0;
1640
+ if (!entry) return true;
1641
+ const input = st?.input;
1642
+ const isBackground = isBackgroundInput(input);
1643
+ const stillRunning = entry.status === "running" || entry.status === "cancel_requested";
1644
+ if (rawStatus === "completed" && !isBackground && stillRunning) return true;
1645
+ }
1646
+ }
1647
+ } catch {
1648
+ }
1649
+ return false;
1650
+ };
1651
+ const scheduleRescan = () => {
1652
+ if (disposed) return;
1653
+ clearTimeout(rescanTimer);
1654
+ rescanTimer = setTimeout(() => {
1655
+ if (disposed) return;
1656
+ untrack(() => {
1657
+ if (!missingNewestToolPart()) return;
1658
+ runSessionScan(props.sessionId, false);
1659
+ bump();
1660
+ });
1661
+ }, 400);
1239
1662
  };
1240
- const bump = () => setRenderTick((v) => v + 1);
1663
+ let enrichCursor = 0;
1241
1664
  onMount(() => {
1242
1665
  const clock = setInterval(() => {
1243
1666
  setNow(Date.now());
1244
1667
  bump();
1245
1668
  }, 100);
1669
+ let tick = 0;
1246
1670
  const tokenTimer = setInterval(() => {
1671
+ tick++;
1247
1672
  untrack(() => {
1673
+ let enriched;
1674
+ let attempted = 0;
1248
1675
  setEntryMapRaw((prev) => {
1249
1676
  let changed = false;
1250
1677
  const next = new Map(prev);
1678
+ if (tick % 4 === 0) {
1679
+ try {
1680
+ const children = props.api.session.listChildren?.(props.sessionId);
1681
+ if (children) {
1682
+ const linked = /* @__PURE__ */ new Set();
1683
+ for (const e of next.values()) if (e.sessionId) linked.add(e.sessionId);
1684
+ const {
1685
+ parentSid,
1686
+ isChild
1687
+ } = resolveParent(props.sessionId);
1688
+ const rec = loadSessionData2()[parentSid];
1689
+ const cleared = new Set(isChild ? rec?.children?.[props.sessionId]?.clearedIds : rec?.clearedIds);
1690
+ for (const child of children) {
1691
+ if (!child.id || linked.has(child.id)) continue;
1692
+ const id = `sub:${child.id}`;
1693
+ if (cleared.has(id)) continue;
1694
+ const finished = child.timeIdle != null && child.active !== true;
1695
+ const status = finished ? child.idleOutcome === "interrupted" ? "cancelled" : "done" : "running";
1696
+ next.set(id, {
1697
+ id,
1698
+ title: child.title ?? child.agent ?? "",
1699
+ agent: child.agent ?? "?",
1700
+ prompt: "",
1701
+ status,
1702
+ sessionId: child.id,
1703
+ startedAt: child.timeCreated ?? Date.now(),
1704
+ endedAt: finished ? child.timeIdle : void 0,
1705
+ tokens: child.tokens,
1706
+ cost: child.cost,
1707
+ model: child.model,
1708
+ origin: "sub"
1709
+ });
1710
+ changed = true;
1711
+ }
1712
+ }
1713
+ } catch {
1714
+ }
1715
+ for (const [id, entry] of next) {
1716
+ if (entry.status !== "done" && entry.status !== "error") continue;
1717
+ const sid = entry.sessionId;
1718
+ if (!sid) continue;
1719
+ try {
1720
+ if (props.api.session.status(sid)?.type === "busy") {
1721
+ next.set(id, {
1722
+ ...entry,
1723
+ status: "running",
1724
+ endedAt: void 0
1725
+ });
1726
+ changed = true;
1727
+ }
1728
+ } catch {
1729
+ }
1730
+ }
1731
+ }
1732
+ const candidates = [];
1251
1733
  for (const [id, entry] of next) {
1252
- if (entry.status === "running" && entry.sessionId) {
1734
+ const running = entry.status === "running" || entry.status === "cancel_requested";
1735
+ const missing = entry.tokens === void 0 || entry.cost === void 0 || !validModel(entry.model);
1736
+ if (entry.sessionId && !running && !missing) continue;
1737
+ candidates.push(id);
1738
+ }
1739
+ if (candidates.length > 0) {
1740
+ const start = enrichCursor % candidates.length;
1741
+ let budget = 4;
1742
+ for (let k = 0; k < candidates.length && budget > 0; k++) {
1743
+ const id = candidates[(start + k) % candidates.length];
1744
+ let entry = next.get(id);
1745
+ if (!entry) continue;
1746
+ if (!entry.sessionId) {
1747
+ try {
1748
+ const callId = String(entry.id).replace(/^tool:/, "");
1749
+ const sid = props.api.session.resolveChild?.({
1750
+ parentId: props.sessionId,
1751
+ callId,
1752
+ agent: entry.agent,
1753
+ startedAt: entry.startedAt
1754
+ });
1755
+ if (sid) {
1756
+ entry = {
1757
+ ...entry,
1758
+ sessionId: sid
1759
+ };
1760
+ next.set(id, entry);
1761
+ changed = true;
1762
+ }
1763
+ } catch {
1764
+ }
1765
+ }
1766
+ if (!entry.sessionId) continue;
1767
+ const childSid = entry.sessionId;
1253
1768
  let isChild = false;
1254
1769
  try {
1255
- const s = props.api.session.get(entry.sessionId);
1256
- isChild = s?.parentID === props.sessionId;
1770
+ const s = props.api.session.get(childSid);
1771
+ isChild = !s || s.parentID === props.sessionId;
1257
1772
  } catch {
1773
+ isChild = true;
1258
1774
  }
1259
1775
  if (!isChild) continue;
1260
- const total = props.api.usage.readSessionTokens(entry.sessionId);
1261
- const todo = props.api.usage.readSessionTodo(entry.sessionId);
1262
- const model = entry.model ?? props.api.usage.readSessionModel(entry.sessionId);
1776
+ budget--;
1777
+ attempted++;
1778
+ const running = entry.status === "running" || entry.status === "cancel_requested";
1779
+ let entryChanged = false;
1263
1780
  const nextEntry = {
1264
1781
  ...entry
1265
1782
  };
1266
- if (total !== void 0 && total !== entry.tokens) {
1267
- nextEntry.tokens = total;
1268
- changed = true;
1783
+ if (running || entry.tokens === void 0) {
1784
+ const total = props.api.usage.readSessionTokens(childSid);
1785
+ if (total !== void 0 && total !== entry.tokens) {
1786
+ nextEntry.tokens = total;
1787
+ entryChanged = true;
1788
+ }
1789
+ }
1790
+ if (running || entry.cost === void 0) {
1791
+ const cost = props.api.usage.readSessionCost(childSid);
1792
+ if (cost !== void 0 && cost !== entry.cost) {
1793
+ nextEntry.cost = cost;
1794
+ entryChanged = true;
1795
+ }
1269
1796
  }
1270
- if (todo !== void 0) {
1271
- if (todo.total !== entry.todoTotal || todo.done !== entry.todoDone) {
1797
+ if (running || !validModel(entry.model)) {
1798
+ const model = props.api.usage.readSessionModel(childSid);
1799
+ if (model && model !== entry.model) {
1800
+ nextEntry.model = model;
1801
+ entryChanged = true;
1802
+ }
1803
+ }
1804
+ if (running) {
1805
+ const todo = props.api.usage.readSessionTodo(childSid);
1806
+ if (todo !== void 0 && (todo.total !== entry.todoTotal || todo.done !== entry.todoDone)) {
1272
1807
  nextEntry.todoTotal = todo.total;
1273
1808
  nextEntry.todoDone = todo.done;
1274
- changed = true;
1809
+ entryChanged = true;
1275
1810
  }
1276
1811
  }
1277
- if (model && !entry.model) {
1278
- nextEntry.model = model;
1812
+ if (entryChanged) {
1813
+ next.set(id, nextEntry);
1279
1814
  changed = true;
1280
1815
  }
1281
- if (changed) next.set(id, nextEntry);
1282
1816
  }
1817
+ enrichCursor = (start + Math.max(1, attempted)) % candidates.length;
1283
1818
  }
1284
- return changed ? next : prev;
1819
+ if (!changed) return prev;
1820
+ enriched = next;
1821
+ return next;
1285
1822
  });
1823
+ if (enriched) {
1824
+ globalEntryCache.set(props.sessionId, new Map(enriched));
1825
+ persistEntries(props.sessionId, enriched);
1826
+ }
1286
1827
  });
1828
+ reconcileIdleEntries();
1829
+ if (tick % 4 === 0) {
1830
+ untrack(() => {
1831
+ if (missingNewestToolPart()) {
1832
+ runSessionScan(props.sessionId, false);
1833
+ bump();
1834
+ }
1835
+ });
1836
+ }
1837
+ if (tick % 60 === 0) {
1838
+ untrack(() => {
1839
+ const hasRunning = entryList().some((e) => e.status === "running" || e.status === "cancel_requested");
1840
+ if (hasRunning) {
1841
+ runSessionScan(props.sessionId, false);
1842
+ bump();
1843
+ }
1844
+ });
1845
+ }
1287
1846
  bump();
1288
1847
  }, 500);
1289
1848
  bump();
@@ -1291,7 +1850,10 @@ function SubAgentPanel(props) {
1291
1850
  handlePartUpdated(e);
1292
1851
  bump();
1293
1852
  });
1294
- const unsubMsg = props.api.event.on("message.updated", () => bump());
1853
+ const unsubMsg = props.api.event.on("message.updated", () => {
1854
+ bump();
1855
+ scheduleRescan();
1856
+ });
1295
1857
  const unsubIdle = props.api.event.on("session.idle", (e) => {
1296
1858
  handleSessionEnd(e, "done");
1297
1859
  bump();
@@ -1302,6 +1864,7 @@ function SubAgentPanel(props) {
1302
1864
  });
1303
1865
  onCleanup(() => {
1304
1866
  disposed = true;
1867
+ clearTimeout(rescanTimer);
1305
1868
  clearInterval(clock);
1306
1869
  clearInterval(tokenTimer);
1307
1870
  unsubPart();
@@ -1319,139 +1882,38 @@ function SubAgentPanel(props) {
1319
1882
  const tick = clearTick();
1320
1883
  const forceReload = tick !== lastTick && !switched;
1321
1884
  lastTick = tick;
1322
- const t2 = setTimeout(() => {
1885
+ let attempts = 0;
1886
+ let retryTimer;
1887
+ const run = () => {
1323
1888
  untrack(() => {
1324
1889
  if (switched) {
1325
1890
  const {
1326
1891
  parentSid,
1327
1892
  isChild
1328
1893
  } = resolveParent(sid);
1329
- const data = loadSessionData();
1894
+ const data = loadSessionData2();
1330
1895
  const saved = isChild ? data[parentSid]?.children?.[sid]?.scroll ?? 0 : data[sid]?.scroll ?? 0;
1331
1896
  setScrollOffset(saved);
1332
1897
  if (!isChild && data[sid]?.entries?.length) {
1333
- data[sid].ts = Date.now();
1334
- saveSessionData(data);
1898
+ void Promise.resolve(updateSessionData(props.api.kv, (latest) => {
1899
+ if (latest[sid]?.entries?.length) latest[sid].ts = Date.now();
1900
+ })).catch(() => {
1901
+ });
1335
1902
  }
1336
1903
  }
1337
- setEntryMapRaw((prev) => {
1338
- const next = switched || forceReload ? new Map(globalEntryCache.get(sid) ?? loadEntries(sid)) : new Map(prev);
1339
- const {
1340
- parentSid: scanPSid,
1341
- isChild: scanChild
1342
- } = resolveParent(sid);
1343
- const scanRec = loadSessionData()[scanPSid];
1344
- const clearedIds = new Set(scanChild ? scanRec?.children?.[sid]?.clearedIds : scanRec?.clearedIds);
1345
- try {
1346
- const msgs = props.api.session.messages(sid);
1347
- if (msgs && msgs.length) {
1348
- for (const msg of msgs) {
1349
- const parts = props.api.session.part(msg.id) ?? [];
1350
- for (const partRaw of parts) {
1351
- const part = partRaw;
1352
- if (part.type === "tool") {
1353
- const tool = String(part.tool ?? "");
1354
- if (!SUBAGENT_TOOLS.has(tool)) continue;
1355
- const id = `tool:${String(part.id ?? "")}`;
1356
- if (!part.id) continue;
1357
- const st = part.state;
1358
- const rawStatus = String(st?.status ?? "");
1359
- const scanStMeta = st?.metadata;
1360
- const scanSubSid = scanStMeta?.session_id !== void 0 ? String(scanStMeta.session_id) : scanStMeta?.sessionId !== void 0 ? String(scanStMeta.sessionId) : void 0;
1361
- const existingKey = findSubEntryKey(next, id, scanSubSid);
1362
- const exists = existingKey ? next.get(existingKey) : void 0;
1363
- if (!exists && clearedIds.has(id)) continue;
1364
- if ((rawStatus === "pending" || rawStatus === "") && !exists) continue;
1365
- if (rawStatus === "error") {
1366
- if (exists && exists.status === "running") {
1367
- next.set(existingKey ?? id, {
1368
- ...exists,
1369
- status: "error",
1370
- endedAt: Date.now()
1371
- });
1372
- }
1373
- continue;
1374
- }
1375
- let status = "running";
1376
- if (rawStatus === "completed") status = "done";
1377
- if ((st?.input?.run_in_background === true || st?.input?.background === true) && status === "done") {
1378
- const scanStMeta2 = st?.metadata;
1379
- const scanHasChild = scanStMeta2?.session_id !== void 0 || scanStMeta2?.sessionId !== void 0;
1380
- if (scanHasChild) status = "running";
1381
- }
1382
- if (exists && existingKey === id && exists.status !== "running" && exists.status !== "cancel_requested") continue;
1383
- if (exists && status === "running") {
1384
- if (!rawStatus) {
1385
- const msgTokens = msg?.tokens;
1386
- if (msgTokens && (Number(msgTokens.input) > 0 || Number(msgTokens.output) > 0)) {
1387
- status = "done";
1388
- } else if (Date.now() - exists.startedAt > 30 * 60 * 1e3) {
1389
- status = "done";
1390
- } else {
1391
- continue;
1392
- }
1393
- } else {
1394
- continue;
1395
- }
1396
- }
1397
- const input = st?.input;
1398
- const agent = String(part.subagent_type ?? input?.agent ?? input?.subagent_type ?? tool);
1399
- const prompt = String(input?.prompt ?? part.description ?? "");
1400
- const desc = input?.description !== void 0 ? String(input.description) : "";
1401
- const title = desc || truncate(prompt.replace(/\n/g, " ").trim(), 40);
1402
- let tokens;
1403
- if (scanSubSid) tokens = props.api.usage.readSessionTokens(scanSubSid);
1404
- const ended = status === "done";
1405
- const entryKey = existingKey ?? id;
1406
- next.set(entryKey, {
1407
- id: exists?.id ?? id,
1408
- title,
1409
- agent,
1410
- prompt,
1411
- // Preserve existing values (from handleSessionEnd / KV) — scan must not overwrite
1412
- tokens: exists?.tokens ?? tokens,
1413
- sessionId: exists?.sessionId ?? scanSubSid,
1414
- status,
1415
- startedAt: exists?.startedAt || Date.now(),
1416
- endedAt: ended ? exists?.endedAt || Date.now() : void 0
1417
- });
1418
- if (entryKey !== id) next.delete(id);
1419
- }
1420
- }
1421
- }
1422
- }
1423
- } catch {
1424
- }
1425
- return next;
1426
- });
1427
- setEntryMapRaw((prev) => {
1428
- let changed = false;
1429
- const next = new Map(prev);
1430
- for (const [id, entry] of next) {
1431
- if (entry.status !== "running" && entry.status !== "cancel_requested" || !entry.sessionId) continue;
1432
- try {
1433
- const st = props.api.session.status(entry.sessionId);
1434
- if (!st || st.type !== "idle") continue;
1435
- const tokens = props.api.usage.readSessionTokens(entry.sessionId);
1436
- const cost = props.api.usage.readSessionCost(entry.sessionId);
1437
- const finalStatus = entry.status === "cancel_requested" && entry.abortAccepted ? "cancelled" : "done";
1438
- next.set(id, {
1439
- ...entry,
1440
- status: finalStatus,
1441
- endedAt: Date.now(),
1442
- tokens: tokens ?? entry.tokens,
1443
- cost: cost ?? entry.cost
1444
- });
1445
- changed = true;
1446
- } catch {
1447
- }
1448
- }
1449
- return changed ? next : prev;
1450
- });
1451
- bump();
1904
+ const ok = runSessionScan(sid, switched || forceReload);
1905
+ if (!ok && attempts < 4) {
1906
+ attempts++;
1907
+ retryTimer = setTimeout(run, 400);
1908
+ }
1452
1909
  });
1453
- }, 150);
1454
- onCleanup(() => clearTimeout(t2));
1910
+ bump();
1911
+ };
1912
+ const t2 = setTimeout(run, 150);
1913
+ onCleanup(() => {
1914
+ clearTimeout(t2);
1915
+ if (retryTimer) clearTimeout(retryTimer);
1916
+ });
1455
1917
  });
1456
1918
  const pal = createMemo(() => {
1457
1919
  const th = props.theme;
@@ -1830,17 +2292,26 @@ function SubAgentPanel(props) {
1830
2292
  return "#" + [r, g, bl].map((v) => Math.max(0, Math.min(255, v)).toString(16).padStart(2, "0")).join("");
1831
2293
  };
1832
2294
  const timeColor = () => isActiveRunning ? pal().warning : isError ? pal().error : pal().muted;
1833
- const tokenText = () => !isExpanded() && entry.tokens !== void 0 && entry.tokens > 0 ? ` ${fmtTokens(entry.tokens)}` : "";
1834
- const timeText = () => !isExpanded() && (elapsed() >= 2e3 || entry.endedAt !== void 0) ? fmtDurationShort(elapsed(), isActiveRunning) : "";
2295
+ const tokenText = () => !isExpanded() && props.showEntryTokens() && entry.tokens !== void 0 && entry.tokens > 0 ? ` ${fmtTokens(entry.tokens)}` : "";
2296
+ const costText = () => !isExpanded() && props.showEntryCost() && entry.cost !== void 0 && entry.cost > 0 ? ` $${entry.cost.toFixed(4)}` : "";
2297
+ const timeText = () => !isExpanded() && props.showEntryTime() && (elapsed() >= 2e3 || entry.endedAt !== void 0) ? fmtDuration(elapsed(), isActiveRunning, props.timeFormat()) : "";
2298
+ const originMark = () => {
2299
+ if (!props.showOrigin()) return "";
2300
+ if (entry.origin === "sub") return "\u21B3";
2301
+ return entry.background === true ? "\u21E2" : "";
2302
+ };
2303
+ const originW = () => originMark() ? 2 : 0;
1835
2304
  const suffixW = () => {
1836
2305
  let w = 0;
1837
2306
  const t2 = timeText();
1838
2307
  if (t2) w += 1 + visualWidth(t2);
1839
2308
  const tk = tokenText();
1840
2309
  if (tk) w += visualWidth(tk);
2310
+ const c = costText();
2311
+ if (c) w += visualWidth(c);
1841
2312
  return w;
1842
2313
  };
1843
- const labelAvail = () => Math.max(6, panelWidth() - gutter() - LEFT_PAD - suffixW());
2314
+ const labelAvail = () => Math.max(6, panelWidth() - gutter() - LEFT_PAD - originW() - suffixW());
1844
2315
  const labelText = () => {
1845
2316
  const max2 = labelAvail();
1846
2317
  const text = entry.title || entry.agent;
@@ -1858,27 +2329,49 @@ function SubAgentPanel(props) {
1858
2329
  _$setProp(_el$25, "onMouseUp", () => toggleExpand(entry.id));
1859
2330
  _$insert(_el$26, () => isExpanded() ? "\u25BC" : "\u25B6");
1860
2331
  _$insert(_el$28, statusDot);
2332
+ _$insert(_el$25, (() => {
2333
+ var _c$2 = _$memo(() => !!originMark());
2334
+ return () => _c$2() ? (() => {
2335
+ var _el$88 = _$createElement("span");
2336
+ _$insert(_el$88, () => originMark() + " ");
2337
+ _$effect((_$p) => _$setProp(_el$88, "style", {
2338
+ fg: pal().muted
2339
+ }, _$p));
2340
+ return _el$88;
2341
+ })() : null;
2342
+ })(), _el$30);
1861
2343
  _$insert(_el$30, labelText);
1862
2344
  _$insert(_el$25, (() => {
1863
- var _c$2 = _$memo(() => !!timeText());
1864
- return () => _c$2() ? [" ", (() => {
1865
- var _el$82 = _$createElement("span");
1866
- _$insert(_el$82, timeText);
1867
- _$effect((_$p) => _$setProp(_el$82, "style", {
2345
+ var _c$3 = _$memo(() => !!timeText());
2346
+ return () => _c$3() ? [" ", (() => {
2347
+ var _el$89 = _$createElement("span");
2348
+ _$insert(_el$89, timeText);
2349
+ _$effect((_$p) => _$setProp(_el$89, "style", {
1868
2350
  fg: timeColor()
1869
2351
  }, _$p));
1870
- return _el$82;
2352
+ return _el$89;
1871
2353
  })()] : null;
1872
2354
  })(), null);
1873
2355
  _$insert(_el$25, (() => {
1874
- var _c$3 = _$memo(() => !!tokenText());
1875
- return () => _c$3() ? (() => {
1876
- var _el$83 = _$createElement("span");
1877
- _$insert(_el$83, tokenText);
1878
- _$effect((_$p) => _$setProp(_el$83, "style", {
2356
+ var _c$4 = _$memo(() => !!tokenText());
2357
+ return () => _c$4() ? (() => {
2358
+ var _el$90 = _$createElement("span");
2359
+ _$insert(_el$90, tokenText);
2360
+ _$effect((_$p) => _$setProp(_el$90, "style", {
1879
2361
  fg: pal().muted
1880
2362
  }, _$p));
1881
- return _el$83;
2363
+ return _el$90;
2364
+ })() : null;
2365
+ })(), null);
2366
+ _$insert(_el$25, (() => {
2367
+ var _c$5 = _$memo(() => !!costText());
2368
+ return () => _c$5() ? (() => {
2369
+ var _el$91 = _$createElement("span");
2370
+ _$insert(_el$91, costText);
2371
+ _$effect((_$p) => _$setProp(_el$91, "style", {
2372
+ fg: pal().warning
2373
+ }, _$p));
2374
+ return _el$91;
1882
2375
  })() : null;
1883
2376
  })(), null);
1884
2377
  _$effect((_p$) => {
@@ -1932,70 +2425,77 @@ function SubAgentPanel(props) {
1932
2425
  a: void 0
1933
2426
  });
1934
2427
  return _el$31;
1935
- })(), (() => {
1936
- var _el$37 = _$createElement("text"), _el$38 = _$createTextNode(` `), _el$39 = _$createElement("span"), _el$40 = _$createTextNode(`: `), _el$41 = _$createElement("span"), _el$42 = _$createElement("span");
1937
- _$insertNode(_el$37, _el$38);
1938
- _$insertNode(_el$37, _el$39);
1939
- _$insertNode(_el$37, _el$41);
1940
- _$insertNode(_el$37, _el$42);
1941
- _$insertNode(_el$39, _el$40);
1942
- _$insert(_el$39, () => t("status.label"), _el$40);
1943
- _$insert(_el$41, () => " ".repeat(expandedPad(t("status.label"))));
1944
- _$insert(_el$42, () => isActiveRunning ? t("status.running") : isCancelled ? t("status.cancelled") : isError ? t("status.error") : t("status.done"));
1945
- _$effect((_p$) => {
1946
- var _v$9 = {
1947
- fg: pal().primary
1948
- }, _v$0 = {
1949
- fg: pal().muted
1950
- }, _v$1 = {
1951
- fg: isActiveRunning ? pal().warning : isCancelled ? pal().muted : isError ? pal().error : pal().success
1952
- };
1953
- _v$9 !== _p$.e && (_p$.e = _$setProp(_el$39, "style", _v$9, _p$.e));
1954
- _v$0 !== _p$.t && (_p$.t = _$setProp(_el$41, "style", _v$0, _p$.t));
1955
- _v$1 !== _p$.a && (_p$.a = _$setProp(_el$42, "style", _v$1, _p$.a));
1956
- return _p$;
1957
- }, {
1958
- e: void 0,
1959
- t: void 0,
1960
- a: void 0
1961
- });
1962
- return _el$37;
1963
2428
  })(), _$createComponent(Show, {
1964
2429
  get when() {
1965
- return elapsed() >= 2e3 || entry.endedAt !== void 0;
2430
+ return props.showOrigin();
1966
2431
  },
1967
2432
  get children() {
1968
- var _el$43 = _$createElement("text"), _el$44 = _$createTextNode(` `), _el$45 = _$createElement("span"), _el$46 = _$createTextNode(`: `), _el$47 = _$createElement("span"), _el$48 = _$createElement("span");
1969
- _$insertNode(_el$43, _el$44);
1970
- _$insertNode(_el$43, _el$45);
1971
- _$insertNode(_el$43, _el$47);
1972
- _$insertNode(_el$43, _el$48);
1973
- _$insertNode(_el$45, _el$46);
1974
- _$insert(_el$45, () => t("time.label"), _el$46);
1975
- _$insert(_el$47, () => " ".repeat(expandedPad(t("time.label"))));
1976
- _$insert(_el$48, () => fmtDurationShort(elapsed(), isActiveRunning));
2433
+ var _el$37 = _$createElement("text"), _el$38 = _$createTextNode(` `), _el$39 = _$createElement("span"), _el$40 = _$createTextNode(`: `), _el$41 = _$createElement("span"), _el$42 = _$createElement("span");
2434
+ _$insertNode(_el$37, _el$38);
2435
+ _$insertNode(_el$37, _el$39);
2436
+ _$insertNode(_el$37, _el$41);
2437
+ _$insertNode(_el$37, _el$42);
2438
+ _$insertNode(_el$39, _el$40);
2439
+ _$insert(_el$39, () => t("origin.label"), _el$40);
2440
+ _$insert(_el$41, () => " ".repeat(expandedPad(t("origin.label"))));
2441
+ _$insert(_el$42, (() => {
2442
+ var _c$6 = _$memo(() => entry.origin === "sub");
2443
+ return () => _c$6() ? t("origin.sub") : t("origin.tool");
2444
+ })(), null);
2445
+ _$insert(_el$42, (() => {
2446
+ var _c$7 = _$memo(() => entry.background === true);
2447
+ return () => _c$7() ? ` (${t("origin.background")})` : "";
2448
+ })(), null);
1977
2449
  _$effect((_p$) => {
1978
- var _v$10 = {
2450
+ var _v$9 = {
1979
2451
  fg: pal().primary
1980
- }, _v$11 = {
2452
+ }, _v$0 = {
1981
2453
  fg: pal().muted
1982
- }, _v$12 = {
2454
+ }, _v$1 = {
1983
2455
  fg: pal().muted
1984
2456
  };
1985
- _v$10 !== _p$.e && (_p$.e = _$setProp(_el$45, "style", _v$10, _p$.e));
1986
- _v$11 !== _p$.t && (_p$.t = _$setProp(_el$47, "style", _v$11, _p$.t));
1987
- _v$12 !== _p$.a && (_p$.a = _$setProp(_el$48, "style", _v$12, _p$.a));
2457
+ _v$9 !== _p$.e && (_p$.e = _$setProp(_el$39, "style", _v$9, _p$.e));
2458
+ _v$0 !== _p$.t && (_p$.t = _$setProp(_el$41, "style", _v$0, _p$.t));
2459
+ _v$1 !== _p$.a && (_p$.a = _$setProp(_el$42, "style", _v$1, _p$.a));
1988
2460
  return _p$;
1989
2461
  }, {
1990
2462
  e: void 0,
1991
2463
  t: void 0,
1992
2464
  a: void 0
1993
2465
  });
1994
- return _el$43;
2466
+ return _el$37;
1995
2467
  }
1996
- }), _$createComponent(Show, {
2468
+ }), (() => {
2469
+ var _el$43 = _$createElement("text"), _el$44 = _$createTextNode(` `), _el$45 = _$createElement("span"), _el$46 = _$createTextNode(`: `), _el$47 = _$createElement("span"), _el$48 = _$createElement("span");
2470
+ _$insertNode(_el$43, _el$44);
2471
+ _$insertNode(_el$43, _el$45);
2472
+ _$insertNode(_el$43, _el$47);
2473
+ _$insertNode(_el$43, _el$48);
2474
+ _$insertNode(_el$45, _el$46);
2475
+ _$insert(_el$45, () => t("status.label"), _el$46);
2476
+ _$insert(_el$47, () => " ".repeat(expandedPad(t("status.label"))));
2477
+ _$insert(_el$48, () => isActiveRunning ? t("status.running") : isCancelled ? t("status.cancelled") : isError ? t("status.error") : t("status.done"));
2478
+ _$effect((_p$) => {
2479
+ var _v$10 = {
2480
+ fg: pal().primary
2481
+ }, _v$11 = {
2482
+ fg: pal().muted
2483
+ }, _v$12 = {
2484
+ fg: isActiveRunning ? pal().warning : isCancelled ? pal().muted : isError ? pal().error : pal().success
2485
+ };
2486
+ _v$10 !== _p$.e && (_p$.e = _$setProp(_el$45, "style", _v$10, _p$.e));
2487
+ _v$11 !== _p$.t && (_p$.t = _$setProp(_el$47, "style", _v$11, _p$.t));
2488
+ _v$12 !== _p$.a && (_p$.a = _$setProp(_el$48, "style", _v$12, _p$.a));
2489
+ return _p$;
2490
+ }, {
2491
+ e: void 0,
2492
+ t: void 0,
2493
+ a: void 0
2494
+ });
2495
+ return _el$43;
2496
+ })(), _$createComponent(Show, {
1997
2497
  get when() {
1998
- return entry.tokens !== void 0;
2498
+ return elapsed() >= 2e3 || entry.endedAt !== void 0;
1999
2499
  },
2000
2500
  get children() {
2001
2501
  var _el$49 = _$createElement("text"), _el$50 = _$createTextNode(` `), _el$51 = _$createElement("span"), _el$52 = _$createTextNode(`: `), _el$53 = _$createElement("span"), _el$54 = _$createElement("span");
@@ -2004,9 +2504,9 @@ function SubAgentPanel(props) {
2004
2504
  _$insertNode(_el$49, _el$53);
2005
2505
  _$insertNode(_el$49, _el$54);
2006
2506
  _$insertNode(_el$51, _el$52);
2007
- _$insert(_el$51, () => t("tokens.label"), _el$52);
2008
- _$insert(_el$53, () => " ".repeat(expandedPad(t("tokens.label"))));
2009
- _$insert(_el$54, () => fmtTokens(entry.tokens));
2507
+ _$insert(_el$51, () => t("time.label"), _el$52);
2508
+ _$insert(_el$53, () => " ".repeat(expandedPad(t("time.label"))));
2509
+ _$insert(_el$54, () => fmtDuration(elapsed(), isActiveRunning, props.timeFormat()));
2010
2510
  _$effect((_p$) => {
2011
2511
  var _v$13 = {
2012
2512
  fg: pal().primary
@@ -2028,7 +2528,7 @@ function SubAgentPanel(props) {
2028
2528
  }
2029
2529
  }), _$createComponent(Show, {
2030
2530
  get when() {
2031
- return entry.error;
2531
+ return entry.tokens !== void 0;
2032
2532
  },
2033
2533
  get children() {
2034
2534
  var _el$55 = _$createElement("text"), _el$56 = _$createTextNode(` `), _el$57 = _$createElement("span"), _el$58 = _$createTextNode(`: `), _el$59 = _$createElement("span"), _el$60 = _$createElement("span");
@@ -2037,16 +2537,16 @@ function SubAgentPanel(props) {
2037
2537
  _$insertNode(_el$55, _el$59);
2038
2538
  _$insertNode(_el$55, _el$60);
2039
2539
  _$insertNode(_el$57, _el$58);
2040
- _$insert(_el$57, () => t("error.label"), _el$58);
2041
- _$insert(_el$59, () => " ".repeat(expandedPad(t("error.label"))));
2042
- _$insert(_el$60, () => truncate(String(entry.error), expandedValAvail()));
2540
+ _$insert(_el$57, () => t("tokens.label"), _el$58);
2541
+ _$insert(_el$59, () => " ".repeat(expandedPad(t("tokens.label"))));
2542
+ _$insert(_el$60, () => fmtTokens(entry.tokens));
2043
2543
  _$effect((_p$) => {
2044
2544
  var _v$16 = {
2045
- fg: pal().error
2545
+ fg: pal().primary
2046
2546
  }, _v$17 = {
2047
2547
  fg: pal().muted
2048
2548
  }, _v$18 = {
2049
- fg: pal().error
2549
+ fg: pal().muted
2050
2550
  };
2051
2551
  _v$16 !== _p$.e && (_p$.e = _$setProp(_el$57, "style", _v$16, _p$.e));
2052
2552
  _v$17 !== _p$.t && (_p$.t = _$setProp(_el$59, "style", _v$17, _p$.t));
@@ -2061,46 +2561,7 @@ function SubAgentPanel(props) {
2061
2561
  }
2062
2562
  }), _$createComponent(Show, {
2063
2563
  get when() {
2064
- return entry.cost !== void 0;
2065
- },
2066
- get children() {
2067
- return (() => {
2068
- const cost = entry.cost;
2069
- return (() => {
2070
- var _el$84 = _$createElement("text"), _el$85 = _$createTextNode(` `), _el$86 = _$createElement("span"), _el$87 = _$createTextNode(`: `), _el$88 = _$createElement("span"), _el$89 = _$createElement("span"), _el$90 = _$createTextNode(`$`);
2071
- _$insertNode(_el$84, _el$85);
2072
- _$insertNode(_el$84, _el$86);
2073
- _$insertNode(_el$84, _el$88);
2074
- _$insertNode(_el$84, _el$89);
2075
- _$insertNode(_el$86, _el$87);
2076
- _$insert(_el$86, () => t("cost.label"), _el$87);
2077
- _$insert(_el$88, () => " ".repeat(expandedPad(t("cost.label"))));
2078
- _$insertNode(_el$89, _el$90);
2079
- _$insert(_el$89, () => cost.toFixed(4), null);
2080
- _$effect((_p$) => {
2081
- var _v$29 = {
2082
- fg: pal().primary
2083
- }, _v$30 = {
2084
- fg: pal().muted
2085
- }, _v$31 = {
2086
- fg: pal().muted
2087
- };
2088
- _v$29 !== _p$.e && (_p$.e = _$setProp(_el$86, "style", _v$29, _p$.e));
2089
- _v$30 !== _p$.t && (_p$.t = _$setProp(_el$88, "style", _v$30, _p$.t));
2090
- _v$31 !== _p$.a && (_p$.a = _$setProp(_el$89, "style", _v$31, _p$.a));
2091
- return _p$;
2092
- }, {
2093
- e: void 0,
2094
- t: void 0,
2095
- a: void 0
2096
- });
2097
- return _el$84;
2098
- })();
2099
- })();
2100
- }
2101
- }), _$createComponent(Show, {
2102
- get when() {
2103
- return entry.model;
2564
+ return entry.error;
2104
2565
  },
2105
2566
  get children() {
2106
2567
  var _el$61 = _$createElement("text"), _el$62 = _$createTextNode(` `), _el$63 = _$createElement("span"), _el$64 = _$createTextNode(`: `), _el$65 = _$createElement("span"), _el$66 = _$createElement("span");
@@ -2109,16 +2570,16 @@ function SubAgentPanel(props) {
2109
2570
  _$insertNode(_el$61, _el$65);
2110
2571
  _$insertNode(_el$61, _el$66);
2111
2572
  _$insertNode(_el$63, _el$64);
2112
- _$insert(_el$63, () => t("model.label"), _el$64);
2113
- _$insert(_el$65, () => " ".repeat(expandedPad(t("model.label"))));
2114
- _$insert(_el$66, () => truncate(entry.model, expandedValAvail()));
2573
+ _$insert(_el$63, () => t("error.label"), _el$64);
2574
+ _$insert(_el$65, () => " ".repeat(expandedPad(t("error.label"))));
2575
+ _$insert(_el$66, () => truncate(String(entry.error), expandedValAvail()));
2115
2576
  _$effect((_p$) => {
2116
2577
  var _v$19 = {
2117
- fg: pal().primary
2578
+ fg: pal().error
2118
2579
  }, _v$20 = {
2119
2580
  fg: pal().muted
2120
2581
  }, _v$21 = {
2121
- fg: pal().muted
2582
+ fg: pal().error
2122
2583
  };
2123
2584
  _v$19 !== _p$.e && (_p$.e = _$setProp(_el$63, "style", _v$19, _p$.e));
2124
2585
  _v$20 !== _p$.t && (_p$.t = _$setProp(_el$65, "style", _v$20, _p$.t));
@@ -2133,20 +2594,57 @@ function SubAgentPanel(props) {
2133
2594
  }
2134
2595
  }), _$createComponent(Show, {
2135
2596
  get when() {
2136
- return entry.todoTotal !== void 0;
2597
+ return entry.cost !== void 0;
2598
+ },
2599
+ get children() {
2600
+ return (() => {
2601
+ const cost = entry.cost;
2602
+ return (() => {
2603
+ var _el$92 = _$createElement("text"), _el$93 = _$createTextNode(` `), _el$94 = _$createElement("span"), _el$95 = _$createTextNode(`: `), _el$96 = _$createElement("span"), _el$97 = _$createElement("span"), _el$98 = _$createTextNode(`$`);
2604
+ _$insertNode(_el$92, _el$93);
2605
+ _$insertNode(_el$92, _el$94);
2606
+ _$insertNode(_el$92, _el$96);
2607
+ _$insertNode(_el$92, _el$97);
2608
+ _$insertNode(_el$94, _el$95);
2609
+ _$insert(_el$94, () => t("cost.label"), _el$95);
2610
+ _$insert(_el$96, () => " ".repeat(expandedPad(t("cost.label"))));
2611
+ _$insertNode(_el$97, _el$98);
2612
+ _$insert(_el$97, () => cost.toFixed(4), null);
2613
+ _$effect((_p$) => {
2614
+ var _v$32 = {
2615
+ fg: pal().primary
2616
+ }, _v$33 = {
2617
+ fg: pal().muted
2618
+ }, _v$34 = {
2619
+ fg: pal().muted
2620
+ };
2621
+ _v$32 !== _p$.e && (_p$.e = _$setProp(_el$94, "style", _v$32, _p$.e));
2622
+ _v$33 !== _p$.t && (_p$.t = _$setProp(_el$96, "style", _v$33, _p$.t));
2623
+ _v$34 !== _p$.a && (_p$.a = _$setProp(_el$97, "style", _v$34, _p$.a));
2624
+ return _p$;
2625
+ }, {
2626
+ e: void 0,
2627
+ t: void 0,
2628
+ a: void 0
2629
+ });
2630
+ return _el$92;
2631
+ })();
2632
+ })();
2633
+ }
2634
+ }), _$createComponent(Show, {
2635
+ get when() {
2636
+ return _$memo(() => !!validModel(entry.model))() ? entry.model : void 0;
2137
2637
  },
2138
2638
  get children() {
2139
- var _el$67 = _$createElement("text"), _el$68 = _$createTextNode(` `), _el$69 = _$createElement("span"), _el$70 = _$createTextNode(`: `), _el$71 = _$createElement("span"), _el$72 = _$createElement("span"), _el$73 = _$createTextNode(`/`);
2639
+ var _el$67 = _$createElement("text"), _el$68 = _$createTextNode(` `), _el$69 = _$createElement("span"), _el$70 = _$createTextNode(`: `), _el$71 = _$createElement("span"), _el$72 = _$createElement("span");
2140
2640
  _$insertNode(_el$67, _el$68);
2141
2641
  _$insertNode(_el$67, _el$69);
2142
2642
  _$insertNode(_el$67, _el$71);
2143
2643
  _$insertNode(_el$67, _el$72);
2144
2644
  _$insertNode(_el$69, _el$70);
2145
- _$insert(_el$69, () => t("todo.label"), _el$70);
2146
- _$insert(_el$71, () => " ".repeat(expandedPad(t("todo.label"))));
2147
- _$insertNode(_el$72, _el$73);
2148
- _$insert(_el$72, () => entry.todoDone, _el$73);
2149
- _$insert(_el$72, () => entry.todoTotal, null);
2645
+ _$insert(_el$69, () => t("model.label"), _el$70);
2646
+ _$insert(_el$71, () => " ".repeat(expandedPad(t("model.label"))));
2647
+ _$insert(_el$72, () => truncate(entry.model, expandedValAvail()));
2150
2648
  _$effect((_p$) => {
2151
2649
  var _v$22 = {
2152
2650
  fg: pal().primary
@@ -2166,18 +2664,53 @@ function SubAgentPanel(props) {
2166
2664
  });
2167
2665
  return _el$67;
2168
2666
  }
2667
+ }), _$createComponent(Show, {
2668
+ get when() {
2669
+ return entry.todoTotal !== void 0;
2670
+ },
2671
+ get children() {
2672
+ var _el$73 = _$createElement("text"), _el$74 = _$createTextNode(` `), _el$75 = _$createElement("span"), _el$76 = _$createTextNode(`: `), _el$77 = _$createElement("span"), _el$78 = _$createElement("span"), _el$79 = _$createTextNode(`/`);
2673
+ _$insertNode(_el$73, _el$74);
2674
+ _$insertNode(_el$73, _el$75);
2675
+ _$insertNode(_el$73, _el$77);
2676
+ _$insertNode(_el$73, _el$78);
2677
+ _$insertNode(_el$75, _el$76);
2678
+ _$insert(_el$75, () => t("todo.label"), _el$76);
2679
+ _$insert(_el$77, () => " ".repeat(expandedPad(t("todo.label"))));
2680
+ _$insertNode(_el$78, _el$79);
2681
+ _$insert(_el$78, () => entry.todoDone, _el$79);
2682
+ _$insert(_el$78, () => entry.todoTotal, null);
2683
+ _$effect((_p$) => {
2684
+ var _v$25 = {
2685
+ fg: pal().primary
2686
+ }, _v$26 = {
2687
+ fg: pal().muted
2688
+ }, _v$27 = {
2689
+ fg: pal().muted
2690
+ };
2691
+ _v$25 !== _p$.e && (_p$.e = _$setProp(_el$75, "style", _v$25, _p$.e));
2692
+ _v$26 !== _p$.t && (_p$.t = _$setProp(_el$77, "style", _v$26, _p$.t));
2693
+ _v$27 !== _p$.a && (_p$.a = _$setProp(_el$78, "style", _v$27, _p$.a));
2694
+ return _p$;
2695
+ }, {
2696
+ e: void 0,
2697
+ t: void 0,
2698
+ a: void 0
2699
+ });
2700
+ return _el$73;
2701
+ }
2169
2702
  }), _$createComponent(Show, {
2170
2703
  get when() {
2171
2704
  return entry.sessionId;
2172
2705
  },
2173
2706
  get children() {
2174
- var _el$74 = _$createElement("text"), _el$75 = _$createTextNode(` `), _el$76 = _$createElement("span"), _el$77 = _$createTextNode(`: `), _el$78 = _$createElement("span"), _el$79 = _$createElement("span"), _el$80 = _$createElement("span");
2175
- _$insertNode(_el$74, _el$75);
2176
- _$insertNode(_el$74, _el$76);
2177
- _$insertNode(_el$74, _el$78);
2178
- _$insertNode(_el$74, _el$79);
2179
- _$insertNode(_el$74, _el$80);
2180
- _$setProp(_el$74, "onMouseUp", async () => {
2707
+ var _el$80 = _$createElement("text"), _el$81 = _$createTextNode(` `), _el$82 = _$createElement("span"), _el$83 = _$createTextNode(`: `), _el$84 = _$createElement("span"), _el$85 = _$createElement("span"), _el$86 = _$createElement("span");
2708
+ _$insertNode(_el$80, _el$81);
2709
+ _$insertNode(_el$80, _el$82);
2710
+ _$insertNode(_el$80, _el$84);
2711
+ _$insertNode(_el$80, _el$85);
2712
+ _$insertNode(_el$80, _el$86);
2713
+ _$setProp(_el$80, "onMouseUp", async () => {
2181
2714
  const sessionId = entry.sessionId;
2182
2715
  if (!sessionId) return;
2183
2716
  const result = await copyText(sessionId);
@@ -2197,25 +2730,25 @@ ${t("session.toast.copy_failed")}`, {
2197
2730
  duration: 8e3
2198
2731
  });
2199
2732
  });
2200
- _$insertNode(_el$76, _el$77);
2201
- _$insert(_el$76, () => t("session.label"), _el$77);
2202
- _$insert(_el$78, () => " ".repeat(expandedPad(t("session.label"))));
2203
- _$insert(_el$79, () => truncate(entry.sessionId, expandedValAvail() - visualWidth(" \u2398")));
2204
- _$insertNode(_el$80, _$createTextNode(` \u2398`));
2733
+ _$insertNode(_el$82, _el$83);
2734
+ _$insert(_el$82, () => t("session.label"), _el$83);
2735
+ _$insert(_el$84, () => " ".repeat(expandedPad(t("session.label"))));
2736
+ _$insert(_el$85, () => truncate(entry.sessionId, expandedValAvail() - visualWidth(" \u2398")));
2737
+ _$insertNode(_el$86, _$createTextNode(` \u2398`));
2205
2738
  _$effect((_p$) => {
2206
- var _v$25 = {
2739
+ var _v$28 = {
2207
2740
  fg: pal().primary
2208
- }, _v$26 = {
2741
+ }, _v$29 = {
2209
2742
  fg: pal().muted
2210
- }, _v$27 = {
2743
+ }, _v$30 = {
2211
2744
  fg: pal().muted
2212
- }, _v$28 = {
2745
+ }, _v$31 = {
2213
2746
  fg: pal().warning
2214
2747
  };
2215
- _v$25 !== _p$.e && (_p$.e = _$setProp(_el$76, "style", _v$25, _p$.e));
2216
- _v$26 !== _p$.t && (_p$.t = _$setProp(_el$78, "style", _v$26, _p$.t));
2217
- _v$27 !== _p$.a && (_p$.a = _$setProp(_el$79, "style", _v$27, _p$.a));
2218
- _v$28 !== _p$.o && (_p$.o = _$setProp(_el$80, "style", _v$28, _p$.o));
2748
+ _v$28 !== _p$.e && (_p$.e = _$setProp(_el$82, "style", _v$28, _p$.e));
2749
+ _v$29 !== _p$.t && (_p$.t = _$setProp(_el$84, "style", _v$29, _p$.t));
2750
+ _v$30 !== _p$.a && (_p$.a = _$setProp(_el$85, "style", _v$30, _p$.a));
2751
+ _v$31 !== _p$.o && (_p$.o = _$setProp(_el$86, "style", _v$31, _p$.o));
2219
2752
  return _p$;
2220
2753
  }, {
2221
2754
  e: void 0,
@@ -2223,7 +2756,7 @@ ${t("session.toast.copy_failed")}`, {
2223
2756
  a: void 0,
2224
2757
  o: void 0
2225
2758
  });
2226
- return _el$74;
2759
+ return _el$80;
2227
2760
  }
2228
2761
  }), _$createComponent(Show, {
2229
2762
  get when() {
@@ -2239,68 +2772,68 @@ ${t("session.toast.copy_failed")}`, {
2239
2772
  const rightW = (isRunning ? visualWidth(dismissLabel()) : 0) + (isRunning && entry.sessionId ? visualWidth(cancelLabel()) : 0);
2240
2773
  const spacerW = () => Math.max(1, panelWidth() - gutter() - openW() - rightW - 2);
2241
2774
  return (() => {
2242
- var _el$91 = _$createElement("box"), _el$95 = _$createElement("text");
2243
- _$insertNode(_el$91, _el$95);
2244
- _$setProp(_el$91, "flexDirection", "row");
2245
- _$insert(_el$91, _$createComponent(Show, {
2775
+ var _el$99 = _$createElement("box"), _el$103 = _$createElement("text");
2776
+ _$insertNode(_el$99, _el$103);
2777
+ _$setProp(_el$99, "flexDirection", "row");
2778
+ _$insert(_el$99, _$createComponent(Show, {
2246
2779
  get when() {
2247
2780
  return entry.sessionId;
2248
2781
  },
2249
2782
  get children() {
2250
- var _el$92 = _$createElement("text"), _el$93 = _$createElement("span"), _el$94 = _$createElement("span");
2251
- _$insertNode(_el$92, _el$93);
2252
- _$insertNode(_el$92, _el$94);
2253
- _$setProp(_el$92, "onMouseOver", () => setHoveredOpen(entry.id));
2254
- _$setProp(_el$92, "onMouseOut", () => setHoveredOpen(void 0));
2255
- _$setProp(_el$92, "onMouseUp", () => {
2783
+ var _el$100 = _$createElement("text"), _el$101 = _$createElement("span"), _el$102 = _$createElement("span");
2784
+ _$insertNode(_el$100, _el$101);
2785
+ _$insertNode(_el$100, _el$102);
2786
+ _$setProp(_el$100, "onMouseOver", () => setHoveredOpen(entry.id));
2787
+ _$setProp(_el$100, "onMouseOut", () => setHoveredOpen(void 0));
2788
+ _$setProp(_el$100, "onMouseUp", () => {
2256
2789
  if (entry.sessionId) {
2257
2790
  props.api.route.navigateSession(entry.sessionId);
2258
2791
  }
2259
2792
  });
2260
- _$insert(_el$93, openPrefix);
2261
- _$insert(_el$94, () => t("open.label"));
2793
+ _$insert(_el$101, openPrefix);
2794
+ _$insert(_el$102, () => t("open.label"));
2262
2795
  _$effect((_p$) => {
2263
- var _v$32 = {
2796
+ var _v$35 = {
2264
2797
  fg: hoveredOpen() === entry.id ? pal().warning : pal().primary
2265
- }, _v$33 = {
2798
+ }, _v$36 = {
2266
2799
  fg: hoveredOpen() === entry.id ? pal().warning : pal().primary
2267
2800
  };
2268
- _v$32 !== _p$.e && (_p$.e = _$setProp(_el$93, "style", _v$32, _p$.e));
2269
- _v$33 !== _p$.t && (_p$.t = _$setProp(_el$94, "style", _v$33, _p$.t));
2801
+ _v$35 !== _p$.e && (_p$.e = _$setProp(_el$101, "style", _v$35, _p$.e));
2802
+ _v$36 !== _p$.t && (_p$.t = _$setProp(_el$102, "style", _v$36, _p$.t));
2270
2803
  return _p$;
2271
2804
  }, {
2272
2805
  e: void 0,
2273
2806
  t: void 0
2274
2807
  });
2275
- return _el$92;
2808
+ return _el$100;
2276
2809
  }
2277
- }), _el$95);
2278
- _$insert(_el$95, () => " ".repeat(spacerW()));
2279
- _$insert(_el$91, _$createComponent(Show, {
2810
+ }), _el$103);
2811
+ _$insert(_el$103, () => " ".repeat(spacerW()));
2812
+ _$insert(_el$99, _$createComponent(Show, {
2280
2813
  get when() {
2281
2814
  return isRunning && entry.sessionId;
2282
2815
  },
2283
2816
  get children() {
2284
- var _el$96 = _$createElement("text"), _el$97 = _$createElement("span");
2285
- _$insertNode(_el$96, _el$97);
2286
- _$setProp(_el$96, "onMouseOver", () => setHoveredCancel(entry.id));
2287
- _$setProp(_el$96, "onMouseOut", () => setHoveredCancel(void 0));
2288
- _$setProp(_el$96, "onMouseUp", () => cancelEntry(entry));
2289
- _$insert(_el$97, cancelLabel);
2290
- _$effect((_$p) => _$setProp(_el$97, "style", {
2817
+ var _el$104 = _$createElement("text"), _el$105 = _$createElement("span");
2818
+ _$insertNode(_el$104, _el$105);
2819
+ _$setProp(_el$104, "onMouseOver", () => setHoveredCancel(entry.id));
2820
+ _$setProp(_el$104, "onMouseOut", () => setHoveredCancel(void 0));
2821
+ _$setProp(_el$104, "onMouseUp", () => cancelEntry(entry));
2822
+ _$insert(_el$105, cancelLabel);
2823
+ _$effect((_$p) => _$setProp(_el$105, "style", {
2291
2824
  fg: hoveredCancel() === entry.id ? pal().warning : pal().error
2292
2825
  }, _$p));
2293
- return _el$96;
2826
+ return _el$104;
2294
2827
  }
2295
2828
  }), null);
2296
- _$insert(_el$91, _$createComponent(Show, {
2829
+ _$insert(_el$99, _$createComponent(Show, {
2297
2830
  when: isRunning,
2298
2831
  get children() {
2299
- var _el$98 = _$createElement("text"), _el$99 = _$createElement("span");
2300
- _$insertNode(_el$98, _el$99);
2301
- _$setProp(_el$98, "onMouseOver", () => setHoveredDismiss(entry.id));
2302
- _$setProp(_el$98, "onMouseOut", () => setHoveredDismiss(void 0));
2303
- _$setProp(_el$98, "onMouseUp", () => {
2832
+ var _el$106 = _$createElement("text"), _el$107 = _$createElement("span");
2833
+ _$insertNode(_el$106, _el$107);
2834
+ _$setProp(_el$106, "onMouseOver", () => setHoveredDismiss(entry.id));
2835
+ _$setProp(_el$106, "onMouseOut", () => setHoveredDismiss(void 0));
2836
+ _$setProp(_el$106, "onMouseUp", () => {
2304
2837
  upsertEntry({
2305
2838
  id: entry.id,
2306
2839
  title: entry.title,
@@ -2309,17 +2842,17 @@ ${t("session.toast.copy_failed")}`, {
2309
2842
  status: "done"
2310
2843
  });
2311
2844
  });
2312
- _$insert(_el$99, dismissLabel);
2313
- _$effect((_$p) => _$setProp(_el$99, "style", {
2845
+ _$insert(_el$107, dismissLabel);
2846
+ _$effect((_$p) => _$setProp(_el$107, "style", {
2314
2847
  fg: hoveredDismiss() === entry.id ? pal().warning : pal().muted
2315
2848
  }, _$p));
2316
- return _el$98;
2849
+ return _el$106;
2317
2850
  }
2318
2851
  }), null);
2319
- _$effect((_$p) => _$setProp(_el$95, "style", {
2852
+ _$effect((_$p) => _$setProp(_el$103, "style", {
2320
2853
  fg: pal().muted
2321
2854
  }, _$p));
2322
- return _el$91;
2855
+ return _el$99;
2323
2856
  })();
2324
2857
  })();
2325
2858
  }
@@ -2340,13 +2873,13 @@ ${t("session.toast.copy_failed")}`, {
2340
2873
  const right = props.sortOrder() === "desc" ? `\u2191 ${t("scroll.top")}` : `\u2193 ${t("scroll.bottom")}`;
2341
2874
  const pad = showTop ? Math.max(1, panelWidth() - gutter() - visualWidth(left) - visualWidth(right)) : 0;
2342
2875
  return (() => {
2343
- var _el$100 = _$createElement("box"), _el$101 = _$createElement("text"), _el$102 = _$createElement("span");
2344
- _$insertNode(_el$100, _el$101);
2345
- _$setProp(_el$100, "flexDirection", "row");
2346
- _$insertNode(_el$101, _el$102);
2347
- _$setProp(_el$101, "onMouseOver", () => showMore && setHoveredMoreBelow(true));
2348
- _$setProp(_el$101, "onMouseOut", () => setHoveredMoreBelow(false));
2349
- _$setProp(_el$101, "onMouseUp", () => {
2876
+ var _el$108 = _$createElement("box"), _el$109 = _$createElement("text"), _el$110 = _$createElement("span");
2877
+ _$insertNode(_el$108, _el$109);
2878
+ _$setProp(_el$108, "flexDirection", "row");
2879
+ _$insertNode(_el$109, _el$110);
2880
+ _$setProp(_el$109, "onMouseOver", () => showMore && setHoveredMoreBelow(true));
2881
+ _$setProp(_el$109, "onMouseOut", () => setHoveredMoreBelow(false));
2882
+ _$setProp(_el$109, "onMouseUp", () => {
2350
2883
  if (!showMore) return;
2351
2884
  const total = entryList().length;
2352
2885
  const m = max();
@@ -2358,20 +2891,20 @@ ${t("session.toast.copy_failed")}`, {
2358
2891
  }
2359
2892
  setHoveredMoreBelow(false);
2360
2893
  });
2361
- _$insert(_el$102, left);
2362
- _$insert(_el$100, showTop ? [(() => {
2363
- var _el$103 = _$createElement("text");
2364
- _$insert(_el$103, () => " ".repeat(pad));
2365
- _$effect((_$p) => _$setProp(_el$103, "style", {
2894
+ _$insert(_el$110, left);
2895
+ _$insert(_el$108, showTop ? [(() => {
2896
+ var _el$111 = _$createElement("text");
2897
+ _$insert(_el$111, () => " ".repeat(pad));
2898
+ _$effect((_$p) => _$setProp(_el$111, "style", {
2366
2899
  fg: pal().muted
2367
2900
  }, _$p));
2368
- return _el$103;
2901
+ return _el$111;
2369
2902
  })(), (() => {
2370
- var _el$104 = _$createElement("text"), _el$105 = _$createElement("span");
2371
- _$insertNode(_el$104, _el$105);
2372
- _$setProp(_el$104, "onMouseOver", () => setHoveredTop(true));
2373
- _$setProp(_el$104, "onMouseOut", () => setHoveredTop(false));
2374
- _$setProp(_el$104, "onMouseUp", () => {
2903
+ var _el$112 = _$createElement("text"), _el$113 = _$createElement("span");
2904
+ _$insertNode(_el$112, _el$113);
2905
+ _$setProp(_el$112, "onMouseOver", () => setHoveredTop(true));
2906
+ _$setProp(_el$112, "onMouseOut", () => setHoveredTop(false));
2907
+ _$setProp(_el$112, "onMouseUp", () => {
2375
2908
  const total = entryList().length;
2376
2909
  const m = max();
2377
2910
  if (props.sortOrder() === "desc") {
@@ -2381,16 +2914,16 @@ ${t("session.toast.copy_failed")}`, {
2381
2914
  }
2382
2915
  setHoveredTop(false);
2383
2916
  });
2384
- _$insert(_el$105, right);
2385
- _$effect((_$p) => _$setProp(_el$105, "style", {
2917
+ _$insert(_el$113, right);
2918
+ _$effect((_$p) => _$setProp(_el$113, "style", {
2386
2919
  fg: hoveredTop() ? pal().warning : pal().muted
2387
2920
  }, _$p));
2388
- return _el$104;
2921
+ return _el$112;
2389
2922
  })()] : null, null);
2390
- _$effect((_$p) => _$setProp(_el$102, "style", {
2923
+ _$effect((_$p) => _$setProp(_el$110, "style", {
2391
2924
  fg: showMore && hoveredMoreBelow() ? pal().warning : pal().muted
2392
2925
  }, _$p));
2393
- return _el$100;
2926
+ return _el$108;
2394
2927
  })();
2395
2928
  })();
2396
2929
  }
@@ -2444,6 +2977,21 @@ function createSidebarSlot(api, panelApi, sig) {
2444
2977
  get borderVisible() {
2445
2978
  return sig.borderVisible;
2446
2979
  },
2980
+ get showEntryCost() {
2981
+ return sig.showEntryCost;
2982
+ },
2983
+ get showEntryTime() {
2984
+ return sig.showEntryTime;
2985
+ },
2986
+ get showEntryTokens() {
2987
+ return sig.showEntryTokens;
2988
+ },
2989
+ get timeFormat() {
2990
+ return sig.timeFormat;
2991
+ },
2992
+ get showOrigin() {
2993
+ return sig.showOrigin;
2994
+ },
2447
2995
  get sessionId() {
2448
2996
  return input.session_id;
2449
2997
  }
@@ -2460,6 +3008,13 @@ var tui = async (api) => {
2460
3008
  const [sortOrder, setSortOrder] = createSignal3(String(api.kv.get(`${KV_PREFIX}.order`, "desc")) === "asc" ? "asc" : "desc");
2461
3009
  const [scrollMode, setScrollMode] = createSignal3(String(api.kv.get(`${KV_PREFIX}.scroll_mode`, "wheel")) === "click" ? "click" : "wheel");
2462
3010
  const [borderVisible, setBorderVisible] = createSignal3(api.kv.get(`${KV_PREFIX}.border`, false) === true);
3011
+ const [showEntryCost, setShowEntryCost] = createSignal3(api.kv.get(`${KV_PREFIX}.show_entry_cost`, false) === true);
3012
+ const [showEntryTime, setShowEntryTime] = createSignal3(api.kv.get(`${KV_PREFIX}.show_entry_time`, true) !== false);
3013
+ const [showEntryTokens, setShowEntryTokens] = createSignal3(api.kv.get(`${KV_PREFIX}.show_entry_tokens`, true) !== false);
3014
+ const storedTimeFormat = String(api.kv.get(`${KV_PREFIX}.time_format`, "short"));
3015
+ const [timeFormat, setTimeFormat] = createSignal3(TIME_FORMATS.includes(storedTimeFormat) ? storedTimeFormat : "short");
3016
+ const [showOrigin, setShowOrigin] = createSignal3(api.kv.get(`${KV_PREFIX}.show_origin`, false) === true);
3017
+ const [dbSync, setDbSync] = createSignal3(api.kv.get(`${KV_PREFIX}.db_sync`, true) !== false);
2463
3018
  const signals = {
2464
3019
  lang,
2465
3020
  setLang,
@@ -2471,6 +3026,18 @@ var tui = async (api) => {
2471
3026
  setScrollMode,
2472
3027
  borderVisible,
2473
3028
  setBorderVisible,
3029
+ showEntryCost,
3030
+ setShowEntryCost,
3031
+ showEntryTime,
3032
+ setShowEntryTime,
3033
+ showEntryTokens,
3034
+ setShowEntryTokens,
3035
+ timeFormat,
3036
+ setTimeFormat,
3037
+ showOrigin,
3038
+ setShowOrigin,
3039
+ dbSync,
3040
+ setDbSync,
2474
3041
  sessionId: ""
2475
3042
  };
2476
3043
  const v1Api = {
@@ -2971,6 +3538,102 @@ var tui = async (api) => {
2971
3538
  });
2972
3539
  dialog?.clear();
2973
3540
  }
3541
+ }, {
3542
+ title: "SubAgent Magazine: Entry Cost",
3543
+ value: "subagent-cost",
3544
+ description: "Show or hide the per-sub-agent cost in the sidebar",
3545
+ slash: {
3546
+ name: "subagent-cost"
3547
+ },
3548
+ onSelect: (dialog) => {
3549
+ const t = createT(() => signals.lang());
3550
+ const cur = Boolean(api.kv.get(`${KV_PREFIX}.show_entry_cost`, false));
3551
+ api.kv.set(`${KV_PREFIX}.show_entry_cost`, !cur);
3552
+ signals.setShowEntryCost(!cur);
3553
+ api.ui.toast({
3554
+ message: `${t("settings.showEntryCost")}: ${!cur ? t("settings.on") : t("settings.off")}`
3555
+ });
3556
+ dialog?.clear();
3557
+ }
3558
+ }, {
3559
+ title: "SubAgent Magazine: Entry Time",
3560
+ value: "subagent-time",
3561
+ description: "Show or hide the elapsed time in the sidebar list",
3562
+ slash: {
3563
+ name: "subagent-time"
3564
+ },
3565
+ onSelect: (dialog) => {
3566
+ const t = createT(() => signals.lang());
3567
+ const cur = Boolean(api.kv.get(`${KV_PREFIX}.show_entry_time`, true));
3568
+ api.kv.set(`${KV_PREFIX}.show_entry_time`, !cur);
3569
+ signals.setShowEntryTime(!cur);
3570
+ api.ui.toast({
3571
+ message: `${t("settings.showEntryTime")}: ${!cur ? t("settings.on") : t("settings.off")}`
3572
+ });
3573
+ dialog?.clear();
3574
+ }
3575
+ }, {
3576
+ title: "SubAgent Magazine: Entry Tokens",
3577
+ value: "subagent-tokens",
3578
+ description: "Show or hide the token count in the sidebar list",
3579
+ slash: {
3580
+ name: "subagent-tokens"
3581
+ },
3582
+ onSelect: (dialog) => {
3583
+ const t = createT(() => signals.lang());
3584
+ const cur = Boolean(api.kv.get(`${KV_PREFIX}.show_entry_tokens`, true));
3585
+ api.kv.set(`${KV_PREFIX}.show_entry_tokens`, !cur);
3586
+ signals.setShowEntryTokens(!cur);
3587
+ api.ui.toast({
3588
+ message: `${t("settings.showEntryTokens")}: ${!cur ? t("settings.on") : t("settings.off")}`
3589
+ });
3590
+ dialog?.clear();
3591
+ }
3592
+ }, {
3593
+ title: "SubAgent Magazine: Time Format",
3594
+ value: "subagent-time-format",
3595
+ description: "Set how elapsed time is displayed",
3596
+ slash: {
3597
+ name: "subagent-time-format"
3598
+ },
3599
+ onSelect: (dialog) => {
3600
+ dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
3601
+ title: "Time Format / \u65F6\u95F4\u683C\u5F0F",
3602
+ get options() {
3603
+ return TIME_FORMATS.map((f) => ({
3604
+ title: `${f} \u2014 ${TIME_FORMAT_SAMPLES[f]}`,
3605
+ value: f
3606
+ }));
3607
+ },
3608
+ onSelect: (opt) => {
3609
+ const f = opt.value;
3610
+ setTimeFormat(f);
3611
+ api.kv.set(`${KV_PREFIX}.time_format`, f);
3612
+ const t = createT(() => lang());
3613
+ api.ui.toast({
3614
+ message: `${t("settings.timeFormat")}: ${TIME_FORMAT_SAMPLES[f]}`
3615
+ });
3616
+ dialog?.clear();
3617
+ }
3618
+ }));
3619
+ }
3620
+ }, {
3621
+ title: "SubAgent Magazine: Origin Indicators",
3622
+ value: "subagent-origin",
3623
+ description: "Show or hide origin markers (\u21E2/\u21B3) in the sidebar list",
3624
+ slash: {
3625
+ name: "subagent-origin"
3626
+ },
3627
+ onSelect: (dialog) => {
3628
+ const t = createT(() => signals.lang());
3629
+ const cur = Boolean(api.kv.get(`${KV_PREFIX}.show_origin`, false));
3630
+ api.kv.set(`${KV_PREFIX}.show_origin`, !cur);
3631
+ signals.setShowOrigin(!cur);
3632
+ api.ui.toast({
3633
+ message: `${t("settings.showOrigin")}: ${!cur ? t("settings.on") : t("settings.off")}`
3634
+ });
3635
+ dialog?.clear();
3636
+ }
2974
3637
  }]);
2975
3638
  };
2976
3639
  var mod = {