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/README.md +12 -1
- package/dist/_version.d.ts +1 -1
- package/dist/_version.js +1 -1
- package/dist/core/format.d.ts +7 -0
- package/dist/core/format.js +45 -0
- package/dist/core/kv.d.ts +22 -1
- package/dist/core/kv.js +34 -1
- package/dist/core/types.d.ts +20 -0
- package/dist/core/types.js +7 -0
- package/dist/i18n.d.ts +24 -0
- package/dist/i18n.js +96 -0
- package/dist/index.js +90 -2
- package/dist/panel/SubAgentPanel.d.ts +6 -1
- package/dist/panel/SubAgentPanel.js +645 -266
- package/dist/panel/entry-map.d.ts +17 -0
- package/dist/panel/entry-map.js +75 -1
- package/dist/panel/panel-api.d.ts +24 -0
- package/dist/tui.js +1230 -567
- package/dist/v2/commands.js +202 -44
- package/dist/v2/db.d.ts +60 -0
- package/dist/v2/db.js +341 -0
- package/dist/v2/index.js +28 -6
- package/dist/v2/settings-menu.d.ts +9 -0
- package/dist/v2/settings-menu.js +242 -0
- package/dist/v2/v2-panel-api.js +315 -44
- package/dist/v2.js +2139 -708
- package/package.json +1 -1
- package/src/_version.ts +1 -1
- package/src/core/format.ts +44 -0
- package/src/core/kv.ts +43 -2
- package/src/core/types.ts +25 -0
- package/src/i18n.ts +96 -0
- package/src/index.tsx +113 -2
- package/src/panel/SubAgentPanel.tsx +621 -238
- package/src/panel/entry-map.ts +79 -2
- package/src/panel/panel-api.ts +25 -0
- package/src/v2/commands.ts +201 -43
- package/src/v2/db.ts +346 -0
- package/src/v2/index.tsx +54 -7
- package/src/v2/settings-menu.ts +259 -0
- package/src/v2/types.ts +3 -1
- package/src/v2/v2-panel-api.ts +246 -33
package/dist/v2.js
CHANGED
|
@@ -2,6 +2,336 @@
|
|
|
2
2
|
import { createComponent as _$createComponent2 } from "@opentui/solid";
|
|
3
3
|
import { createSignal as createSignal3 } from "solid-js";
|
|
4
4
|
|
|
5
|
+
// src/core/kv.ts
|
|
6
|
+
var KV_PREFIX = "subagent_magazine";
|
|
7
|
+
var SESSION_DATA_KEY = `${KV_PREFIX}.session_data`;
|
|
8
|
+
var SETTING_KEYS = {
|
|
9
|
+
lang: `${KV_PREFIX}.lang`,
|
|
10
|
+
maxEntries: `${KV_PREFIX}.max_entries`,
|
|
11
|
+
order: `${KV_PREFIX}.order`,
|
|
12
|
+
scrollMode: `${KV_PREFIX}.scroll_mode`,
|
|
13
|
+
open: `${KV_PREFIX}.open`,
|
|
14
|
+
ttlDays: `${KV_PREFIX}.ttl_days`,
|
|
15
|
+
border: `${KV_PREFIX}.border`,
|
|
16
|
+
showEntryCost: `${KV_PREFIX}.show_entry_cost`,
|
|
17
|
+
showEntryTime: `${KV_PREFIX}.show_entry_time`,
|
|
18
|
+
showEntryTokens: `${KV_PREFIX}.show_entry_tokens`,
|
|
19
|
+
timeFormat: `${KV_PREFIX}.time_format`,
|
|
20
|
+
showOrigin: `${KV_PREFIX}.show_origin`,
|
|
21
|
+
dbSync: `${KV_PREFIX}.db_sync`
|
|
22
|
+
};
|
|
23
|
+
function loadSessionData(kv) {
|
|
24
|
+
try {
|
|
25
|
+
const raw = kv.get(SESSION_DATA_KEY, "{}");
|
|
26
|
+
return JSON.parse(String(raw));
|
|
27
|
+
} catch {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function updateSessionData(kv, mutator) {
|
|
32
|
+
try {
|
|
33
|
+
if (typeof kv.update === "function") {
|
|
34
|
+
return kv.update(SESSION_DATA_KEY, (raw) => {
|
|
35
|
+
const data2 = parseSessionData(raw);
|
|
36
|
+
mutator(data2);
|
|
37
|
+
return JSON.stringify(data2);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
const data = loadSessionData(kv);
|
|
41
|
+
mutator(data);
|
|
42
|
+
kv.set(SESSION_DATA_KEY, JSON.stringify(data));
|
|
43
|
+
} catch {
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function parseSessionData(raw) {
|
|
47
|
+
try {
|
|
48
|
+
return JSON.parse(String(raw ?? "{}"));
|
|
49
|
+
} catch {
|
|
50
|
+
return {};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function readTTLDays(kv) {
|
|
54
|
+
const ttlDaysRaw = parseInt(String(kv.get(SETTING_KEYS.ttlDays, "3")), 10);
|
|
55
|
+
return Number.isNaN(ttlDaysRaw) ? 3 : ttlDaysRaw;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/v2/db.ts
|
|
59
|
+
import { homedir } from "node:os";
|
|
60
|
+
var BUN_SQLITE = "bun:sqlite";
|
|
61
|
+
function modelIdOf(value) {
|
|
62
|
+
if (typeof value === "string") {
|
|
63
|
+
const s = value.trim();
|
|
64
|
+
if (s.length === 0) return void 0;
|
|
65
|
+
if (s.startsWith("{")) {
|
|
66
|
+
try {
|
|
67
|
+
return modelIdOf(JSON.parse(s));
|
|
68
|
+
} catch {
|
|
69
|
+
return void 0;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return s;
|
|
73
|
+
}
|
|
74
|
+
if (value && typeof value === "object") {
|
|
75
|
+
const id = value.id;
|
|
76
|
+
if (id === void 0) return void 0;
|
|
77
|
+
const direct = modelIdOf(id);
|
|
78
|
+
if (direct !== void 0) return direct;
|
|
79
|
+
const s = String(id);
|
|
80
|
+
return s.length > 0 ? s : void 0;
|
|
81
|
+
}
|
|
82
|
+
return void 0;
|
|
83
|
+
}
|
|
84
|
+
function contextTokens(tokens) {
|
|
85
|
+
if (!tokens || typeof tokens !== "object") return void 0;
|
|
86
|
+
const t = tokens;
|
|
87
|
+
const cache = t.cache && typeof t.cache === "object" ? t.cache : {};
|
|
88
|
+
const sum = (Number(t.input) || 0) + (Number(t.output) || 0) + (Number(t.reasoning) || 0) + (Number(cache.read) || 0) + (Number(cache.write) || 0);
|
|
89
|
+
return sum > 0 ? sum : void 0;
|
|
90
|
+
}
|
|
91
|
+
function isSessionActive(input) {
|
|
92
|
+
const { timeIdle, lastMessageType, lastMessageAt } = input;
|
|
93
|
+
if (lastMessageType === "idle") return false;
|
|
94
|
+
if (lastMessageAt === void 0) return false;
|
|
95
|
+
if (timeIdle === void 0) return true;
|
|
96
|
+
return lastMessageAt > timeIdle;
|
|
97
|
+
}
|
|
98
|
+
function statusOfChild(info) {
|
|
99
|
+
if (!info) return void 0;
|
|
100
|
+
if (info.active === true) return void 0;
|
|
101
|
+
if (info.timeIdle == null) return void 0;
|
|
102
|
+
return info.idleOutcome === "interrupted" ? "cancelled" : "done";
|
|
103
|
+
}
|
|
104
|
+
function findDbPath(env = process.env, home = safeHomedir()) {
|
|
105
|
+
if (env.OPENCODE_DB) return env.OPENCODE_DB;
|
|
106
|
+
const base = env.XDG_DATA_HOME && env.XDG_DATA_HOME.length > 0 ? env.XDG_DATA_HOME : `${home}/.local/share`;
|
|
107
|
+
if (!base || base === "/.local/share") return void 0;
|
|
108
|
+
return `${base}/opencode/opencode.db`;
|
|
109
|
+
}
|
|
110
|
+
function safeHomedir() {
|
|
111
|
+
try {
|
|
112
|
+
return homedir();
|
|
113
|
+
} catch {
|
|
114
|
+
return "";
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
var CALL_MAP_SQL = `
|
|
118
|
+
SELECT json_extract(p.value, '$.id') AS call_id,
|
|
119
|
+
json_extract(p.value, '$.state.metadata.sessionID') AS child_sid
|
|
120
|
+
FROM session_message m, json_each(m.data, '$.content') p
|
|
121
|
+
WHERE m.session_id = ? AND m.type = 'assistant'
|
|
122
|
+
AND json_extract(p.value, '$.id') LIKE 'call_%'
|
|
123
|
+
AND json_extract(p.value, '$.state.metadata.sessionID') IS NOT NULL`;
|
|
124
|
+
var CHILD_INFO_SQL = `
|
|
125
|
+
SELECT parent_id, agent, title, model, cost,
|
|
126
|
+
tokens_input, tokens_output, tokens_reasoning, tokens_cache_read, tokens_cache_write,
|
|
127
|
+
time_created, time_idle, idle_outcome
|
|
128
|
+
FROM session_v2 WHERE id = ?`;
|
|
129
|
+
var LAST_ASSISTANT_SQL = `
|
|
130
|
+
SELECT json_extract(data, '$.tokens.input') AS input,
|
|
131
|
+
json_extract(data, '$.tokens.output') AS output,
|
|
132
|
+
json_extract(data, '$.tokens.reasoning') AS reasoning,
|
|
133
|
+
json_extract(data, '$.tokens.cache.read') AS cache_read,
|
|
134
|
+
json_extract(data, '$.tokens.cache.write') AS cache_write,
|
|
135
|
+
json_extract(data, '$.model.id') AS model_id
|
|
136
|
+
FROM session_message
|
|
137
|
+
WHERE session_id = ? AND type = 'assistant' AND json_extract(data, '$.tokens.output') > 0
|
|
138
|
+
ORDER BY seq DESC LIMIT 1`;
|
|
139
|
+
var LAST_MESSAGE_SQL = `
|
|
140
|
+
SELECT type, COALESCE(time_updated, time_created) AS at
|
|
141
|
+
FROM session_message WHERE session_id = ? ORDER BY seq DESC LIMIT 1`;
|
|
142
|
+
var ASSISTANT_COST_SQL = `
|
|
143
|
+
SELECT COUNT(*) AS n, SUM(COALESCE(json_extract(data, '$.cost'), 0)) AS total
|
|
144
|
+
FROM session_message WHERE session_id = ? AND type = 'assistant'`;
|
|
145
|
+
var CHILDREN_SQL = `
|
|
146
|
+
SELECT id, agent, title, model, cost,
|
|
147
|
+
tokens_input, tokens_output, tokens_reasoning, tokens_cache_read, tokens_cache_write,
|
|
148
|
+
time_created, time_idle, idle_outcome
|
|
149
|
+
FROM session_v2
|
|
150
|
+
WHERE parent_id = ? AND (fork_session_id IS NULL OR fork_session_id = '')
|
|
151
|
+
ORDER BY time_created`;
|
|
152
|
+
var num = (v) => {
|
|
153
|
+
const n = Number(v);
|
|
154
|
+
return Number.isFinite(n) ? n : void 0;
|
|
155
|
+
};
|
|
156
|
+
var str = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
|
|
157
|
+
function createSessionDbIndex(enabled) {
|
|
158
|
+
const dbPath = findDbPath();
|
|
159
|
+
if (!dbPath) return void 0;
|
|
160
|
+
let db;
|
|
161
|
+
let failed = false;
|
|
162
|
+
void (async () => {
|
|
163
|
+
try {
|
|
164
|
+
const mod2 = await import(BUN_SQLITE);
|
|
165
|
+
const Database = mod2?.Database;
|
|
166
|
+
if (!Database) {
|
|
167
|
+
failed = true;
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
db = new Database(dbPath, { readonly: true });
|
|
171
|
+
try {
|
|
172
|
+
db.query("pragma query_only = on").all();
|
|
173
|
+
} catch {
|
|
174
|
+
}
|
|
175
|
+
} catch {
|
|
176
|
+
failed = true;
|
|
177
|
+
db = void 0;
|
|
178
|
+
}
|
|
179
|
+
})();
|
|
180
|
+
const CALL_MAP_TTL_MS = 15e3;
|
|
181
|
+
const CALL_MAP_RETRY_MS = 2e3;
|
|
182
|
+
const INFO_TTL_MS = 5e3;
|
|
183
|
+
const callMaps = /* @__PURE__ */ new Map();
|
|
184
|
+
const infos = /* @__PURE__ */ new Map();
|
|
185
|
+
const childrenCache = /* @__PURE__ */ new Map();
|
|
186
|
+
const ready = () => {
|
|
187
|
+
if (failed || db === void 0) return false;
|
|
188
|
+
try {
|
|
189
|
+
return enabled();
|
|
190
|
+
} catch {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
const buildCallMap = (parentId) => {
|
|
195
|
+
const now = Date.now();
|
|
196
|
+
const prev = callMaps.get(parentId);
|
|
197
|
+
if (prev && now - prev.at < CALL_MAP_RETRY_MS) return prev.map;
|
|
198
|
+
const map = /* @__PURE__ */ new Map();
|
|
199
|
+
try {
|
|
200
|
+
for (const row of db.query(CALL_MAP_SQL).all(parentId)) {
|
|
201
|
+
const id = str(row.call_id);
|
|
202
|
+
const sid = str(row.child_sid);
|
|
203
|
+
if (id && sid) map.set(id, sid);
|
|
204
|
+
}
|
|
205
|
+
} catch {
|
|
206
|
+
}
|
|
207
|
+
callMaps.set(parentId, { map, at: now });
|
|
208
|
+
return map;
|
|
209
|
+
};
|
|
210
|
+
const resolveCall = (parentId, callId) => {
|
|
211
|
+
if (!ready() || !parentId || !callId) return void 0;
|
|
212
|
+
const prev = callMaps.get(parentId);
|
|
213
|
+
const map = prev && Date.now() - prev.at < CALL_MAP_TTL_MS ? prev.map : buildCallMap(parentId);
|
|
214
|
+
return map.get(callId) ?? buildCallMap(parentId).get(callId);
|
|
215
|
+
};
|
|
216
|
+
const matchChild = (parentId, agent, startedAt) => {
|
|
217
|
+
if (!ready() || !parentId || startedAt === void 0) return void 0;
|
|
218
|
+
const now = Date.now();
|
|
219
|
+
let cached = childrenCache.get(parentId);
|
|
220
|
+
if (!cached || now - cached.at > CALL_MAP_TTL_MS) {
|
|
221
|
+
let list = [];
|
|
222
|
+
try {
|
|
223
|
+
list = db.query(CHILDREN_SQL).all(parentId);
|
|
224
|
+
} catch {
|
|
225
|
+
}
|
|
226
|
+
cached = { list, at: now };
|
|
227
|
+
childrenCache.set(parentId, cached);
|
|
228
|
+
}
|
|
229
|
+
let best;
|
|
230
|
+
let bestAt = Number.POSITIVE_INFINITY;
|
|
231
|
+
for (const row of cached.list) {
|
|
232
|
+
const sid = str(row.id);
|
|
233
|
+
const t = num(row.time_created);
|
|
234
|
+
if (!sid || t === void 0) continue;
|
|
235
|
+
if (t < startedAt - 2e3) continue;
|
|
236
|
+
if (agent !== void 0 && str(row.agent) !== agent) continue;
|
|
237
|
+
if (t < bestAt) {
|
|
238
|
+
bestAt = t;
|
|
239
|
+
best = sid;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return best;
|
|
243
|
+
};
|
|
244
|
+
const info = (sid) => {
|
|
245
|
+
if (!sid) return void 0;
|
|
246
|
+
const hit = infos.get(sid);
|
|
247
|
+
if (hit && Date.now() - hit.at < INFO_TTL_MS) return hit.info;
|
|
248
|
+
if (!ready()) return void 0;
|
|
249
|
+
let result;
|
|
250
|
+
try {
|
|
251
|
+
const row = db.query(CHILD_INFO_SQL).get(sid);
|
|
252
|
+
if (row) {
|
|
253
|
+
const last = db.query(LAST_ASSISTANT_SQL).get(sid);
|
|
254
|
+
const lastMsg = db.query(LAST_MESSAGE_SQL).get(sid);
|
|
255
|
+
let tokens = contextTokens(last ? {
|
|
256
|
+
input: last.input,
|
|
257
|
+
output: last.output,
|
|
258
|
+
reasoning: last.reasoning,
|
|
259
|
+
cache: { read: last.cache_read, write: last.cache_write }
|
|
260
|
+
} : void 0);
|
|
261
|
+
if (tokens === void 0) {
|
|
262
|
+
const agg = (num(row.tokens_input) || 0) + (num(row.tokens_output) || 0) + (num(row.tokens_reasoning) || 0) + (num(row.tokens_cache_read) || 0) + (num(row.tokens_cache_write) || 0);
|
|
263
|
+
if (agg > 0) tokens = agg;
|
|
264
|
+
}
|
|
265
|
+
let cost = num(row.cost);
|
|
266
|
+
if (!(typeof cost === "number" && cost > 0)) {
|
|
267
|
+
const aggCost = db.query(ASSISTANT_COST_SQL).get(sid);
|
|
268
|
+
if (aggCost && Number(aggCost.n) > 0) cost = Number(aggCost.total) || 0;
|
|
269
|
+
}
|
|
270
|
+
result = {
|
|
271
|
+
id: sid,
|
|
272
|
+
parentId: str(row.parent_id),
|
|
273
|
+
agent: str(row.agent),
|
|
274
|
+
title: str(row.title),
|
|
275
|
+
model: modelIdOf(last?.model_id) ?? modelIdOf(row.model),
|
|
276
|
+
cost,
|
|
277
|
+
tokens,
|
|
278
|
+
timeCreated: num(row.time_created),
|
|
279
|
+
timeIdle: num(row.time_idle),
|
|
280
|
+
idleOutcome: str(row.idle_outcome),
|
|
281
|
+
active: isSessionActive({
|
|
282
|
+
timeIdle: num(row.time_idle),
|
|
283
|
+
lastMessageType: str(lastMsg?.type),
|
|
284
|
+
lastMessageAt: num(lastMsg?.at)
|
|
285
|
+
})
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
} catch {
|
|
289
|
+
result = void 0;
|
|
290
|
+
}
|
|
291
|
+
infos.set(sid, { info: result, at: Date.now() });
|
|
292
|
+
return result;
|
|
293
|
+
};
|
|
294
|
+
const children = (parentId) => {
|
|
295
|
+
if (!ready() || !parentId) return void 0;
|
|
296
|
+
const now = Date.now();
|
|
297
|
+
let cached = childrenCache.get(parentId);
|
|
298
|
+
if (!cached || now - cached.at > CALL_MAP_TTL_MS) {
|
|
299
|
+
let list = [];
|
|
300
|
+
try {
|
|
301
|
+
list = db.query(CHILDREN_SQL).all(parentId);
|
|
302
|
+
} catch {
|
|
303
|
+
}
|
|
304
|
+
cached = { list, at: now };
|
|
305
|
+
childrenCache.set(parentId, cached);
|
|
306
|
+
}
|
|
307
|
+
const out = [];
|
|
308
|
+
for (const row of cached.list) {
|
|
309
|
+
const sid = str(row.id);
|
|
310
|
+
if (!sid) continue;
|
|
311
|
+
const full = info(sid);
|
|
312
|
+
if (full) {
|
|
313
|
+
out.push(full);
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
const agg = (num(row.tokens_input) || 0) + (num(row.tokens_output) || 0) + (num(row.tokens_reasoning) || 0) + (num(row.tokens_cache_read) || 0) + (num(row.tokens_cache_write) || 0);
|
|
317
|
+
out.push({
|
|
318
|
+
id: sid,
|
|
319
|
+
parentId,
|
|
320
|
+
agent: str(row.agent),
|
|
321
|
+
title: str(row.title),
|
|
322
|
+
model: modelIdOf(row.model),
|
|
323
|
+
cost: num(row.cost),
|
|
324
|
+
tokens: agg > 0 ? agg : void 0,
|
|
325
|
+
timeCreated: num(row.time_created),
|
|
326
|
+
timeIdle: num(row.time_idle),
|
|
327
|
+
idleOutcome: str(row.idle_outcome)
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
return out;
|
|
331
|
+
};
|
|
332
|
+
return { enabled: ready, resolveCall, matchChild, info, children };
|
|
333
|
+
}
|
|
334
|
+
|
|
5
335
|
// src/v2/v2-panel-api.ts
|
|
6
336
|
var SUBAGENT_TOOL_V2 = "subagent";
|
|
7
337
|
function normalizeMeta(meta) {
|
|
@@ -18,7 +348,11 @@ function toV1Part(p) {
|
|
|
18
348
|
if (st.output === void 0 && Array.isArray(st.content)) {
|
|
19
349
|
st.output = st.content.map((c) => c.type === "text" ? c.text : c.type === "file" ? String(c.path ?? c.filename ?? "") : JSON.stringify(c)).filter((t) => typeof t === "string" && t.length > 0).join("\n");
|
|
20
350
|
}
|
|
21
|
-
|
|
351
|
+
const meta = normalizeMeta({
|
|
352
|
+
...st.metadata ?? {},
|
|
353
|
+
...p.metadata ?? {}
|
|
354
|
+
});
|
|
355
|
+
return { type: "tool", id: p.id, tool: p.tool ?? p.name, state: st, subagent_type: p.subagent_type, metadata: meta };
|
|
22
356
|
}
|
|
23
357
|
if (p.type === "text") return { type: "text", text: String(p.text ?? "") };
|
|
24
358
|
if (p.type === "file") return { type: "file", source: p.source ?? {} };
|
|
@@ -55,7 +389,60 @@ function createPanelApi(context, settings) {
|
|
|
55
389
|
d.value = value;
|
|
56
390
|
});
|
|
57
391
|
};
|
|
392
|
+
const kvUpdate = (key, updater) => {
|
|
393
|
+
let entry = kvStore.get(key);
|
|
394
|
+
if (!entry) {
|
|
395
|
+
const created = context.storage.store(`subagent_magazine.${key}`, {
|
|
396
|
+
initial: { value: void 0 }
|
|
397
|
+
});
|
|
398
|
+
entry = created;
|
|
399
|
+
kvStore.set(key, entry);
|
|
400
|
+
}
|
|
401
|
+
const [, mutate] = entry;
|
|
402
|
+
return mutate((d) => {
|
|
403
|
+
d.value = updater(d.value);
|
|
404
|
+
});
|
|
405
|
+
};
|
|
406
|
+
const dbIndex = createSessionDbIndex(() => kvGet(SETTING_KEYS.dbSync, true) !== false);
|
|
407
|
+
const withResolvedSid = (data, meta) => {
|
|
408
|
+
if (meta.sessionID !== void 0) return meta;
|
|
409
|
+
try {
|
|
410
|
+
const parent = data.sessionID !== void 0 ? String(data.sessionID) : "";
|
|
411
|
+
const callId = data.id !== void 0 ? String(data.id) : "";
|
|
412
|
+
const sid = parent && callId ? dbIndex?.resolveCall(parent, callId) : void 0;
|
|
413
|
+
if (sid) return normalizeMeta({ ...meta, sessionID: sid });
|
|
414
|
+
} catch {
|
|
415
|
+
}
|
|
416
|
+
return meta;
|
|
417
|
+
};
|
|
58
418
|
const isSubagentTool = (name) => name === SUBAGENT_TOOL_V2 || name === "task" || name === "delegate" || name === "call_omo_agent";
|
|
419
|
+
const findToolPart = (data) => {
|
|
420
|
+
const sid = data.sessionID;
|
|
421
|
+
const msgID = data.assistantMessageID;
|
|
422
|
+
const partID = data.id;
|
|
423
|
+
if (sid === void 0 || msgID === void 0 || partID === void 0) return void 0;
|
|
424
|
+
try {
|
|
425
|
+
const raw = context.data.session.message.list(String(sid));
|
|
426
|
+
if (!raw) return void 0;
|
|
427
|
+
for (let i = raw.length - 1; i >= 0; i--) {
|
|
428
|
+
const m = raw[i];
|
|
429
|
+
if (!m || String(m.id) !== String(msgID)) continue;
|
|
430
|
+
const content = Array.isArray(m.content) ? m.content : [];
|
|
431
|
+
for (const p of content) {
|
|
432
|
+
const pp = p;
|
|
433
|
+
if (pp && pp.type === "tool" && String(pp.id) === String(partID)) {
|
|
434
|
+
const st = pp.state ?? {};
|
|
435
|
+
const input = st.input && typeof st.input === "object" ? st.input : void 0;
|
|
436
|
+
const name = pp.name ?? pp.tool;
|
|
437
|
+
return { name: name !== void 0 ? String(name) : void 0, input };
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
} catch {
|
|
443
|
+
}
|
|
444
|
+
return void 0;
|
|
445
|
+
};
|
|
59
446
|
const toolEventToPart = (event) => {
|
|
60
447
|
const type = event.type;
|
|
61
448
|
const data = event.data;
|
|
@@ -73,20 +460,29 @@ function createPanelApi(context, settings) {
|
|
|
73
460
|
return { type: "tool", tool: normName(String(data.name)), id: String(data.id), state: { status: "pending", input: {} } };
|
|
74
461
|
}
|
|
75
462
|
if (type === "session.tool.called") {
|
|
76
|
-
|
|
463
|
+
let name = data.name ?? info?.name;
|
|
464
|
+
let input = data.input ?? info?.input;
|
|
465
|
+
if (!name) {
|
|
466
|
+
const resolved = findToolPart(data);
|
|
467
|
+
if (resolved?.name) {
|
|
468
|
+
name = resolved.name;
|
|
469
|
+
if (input === void 0) input = resolved.input;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
77
472
|
if (name && !isSubagentTool(name)) return void 0;
|
|
78
473
|
if (!name) return void 0;
|
|
79
|
-
if (key) toolInfo.set(key, { name: String(name), input:
|
|
474
|
+
if (key) toolInfo.set(key, { name: String(name), input: input ?? {} });
|
|
80
475
|
return {
|
|
81
476
|
type: "tool",
|
|
82
477
|
tool: normName(String(name)),
|
|
83
478
|
id: String(data.id),
|
|
84
|
-
subagent_type: agentOf(
|
|
85
|
-
state: { status: "running", input:
|
|
479
|
+
subagent_type: agentOf(input),
|
|
480
|
+
state: { status: "running", input: input ?? {}, metadata: withResolvedSid(data, {}) }
|
|
86
481
|
};
|
|
87
482
|
}
|
|
88
483
|
if (type === "session.tool.progress") {
|
|
89
|
-
|
|
484
|
+
let name = data.name ?? info?.name;
|
|
485
|
+
if (!name) name = findToolPart(data)?.name;
|
|
90
486
|
if (name && !isSubagentTool(name)) return void 0;
|
|
91
487
|
if (!name) return void 0;
|
|
92
488
|
return {
|
|
@@ -94,24 +490,42 @@ function createPanelApi(context, settings) {
|
|
|
94
490
|
tool: normName(String(name)),
|
|
95
491
|
id: String(data.id),
|
|
96
492
|
subagent_type: agentOf(info?.input),
|
|
97
|
-
state: { status: "running", input: info?.input ?? {}, metadata: normalizeMeta(data.metadata) }
|
|
493
|
+
state: { status: "running", input: info?.input ?? {}, metadata: withResolvedSid(data, normalizeMeta(data.metadata)) }
|
|
98
494
|
};
|
|
99
495
|
}
|
|
100
496
|
if (type === "session.tool.success" || type === "session.tool.failed") {
|
|
101
|
-
const
|
|
102
|
-
|
|
497
|
+
const eventMeta = normalizeMeta(data.metadata);
|
|
498
|
+
const meta = withResolvedSid(data, eventMeta);
|
|
103
499
|
if (type === "session.tool.failed" && meta.status === "running") return void 0;
|
|
104
|
-
|
|
500
|
+
let name = data.name ?? info?.name;
|
|
501
|
+
let input = info?.input ?? data.input;
|
|
502
|
+
if (!name || input === void 0) {
|
|
503
|
+
const resolved = findToolPart(data);
|
|
504
|
+
if (!name && resolved?.name) name = resolved.name;
|
|
505
|
+
if (input === void 0 && resolved?.input) input = resolved.input;
|
|
506
|
+
}
|
|
105
507
|
if (name && !isSubagentTool(name)) return void 0;
|
|
106
|
-
|
|
508
|
+
if (key && name) toolInfo.set(key, { name: String(name), input: input ?? info?.input ?? {} });
|
|
509
|
+
const finalInput = input ?? {};
|
|
510
|
+
if (meta.sessionID === void 0 && (finalInput.background === true || finalInput.run_in_background === true)) {
|
|
511
|
+
return void 0;
|
|
512
|
+
}
|
|
513
|
+
let status = type === "session.tool.failed" ? "error" : "completed";
|
|
514
|
+
if (meta.sessionID !== void 0 && meta.sessionID !== eventMeta.sessionID) {
|
|
515
|
+
try {
|
|
516
|
+
const childInfo = dbIndex?.info(String(meta.sessionID));
|
|
517
|
+
if (childInfo && statusOfChild(childInfo) === void 0) status = "running";
|
|
518
|
+
} catch {
|
|
519
|
+
}
|
|
520
|
+
}
|
|
107
521
|
return {
|
|
108
522
|
type: "tool",
|
|
109
523
|
tool: normName(String(name ?? "task")),
|
|
110
524
|
id: String(data.id),
|
|
111
|
-
subagent_type: agentOf(
|
|
525
|
+
subagent_type: agentOf(finalInput),
|
|
112
526
|
state: {
|
|
113
|
-
status
|
|
114
|
-
input,
|
|
527
|
+
status,
|
|
528
|
+
input: finalInput,
|
|
115
529
|
metadata: meta
|
|
116
530
|
}
|
|
117
531
|
};
|
|
@@ -133,14 +547,55 @@ function createPanelApi(context, settings) {
|
|
|
133
547
|
}
|
|
134
548
|
return out;
|
|
135
549
|
};
|
|
550
|
+
const usageCache = /* @__PURE__ */ new Map();
|
|
551
|
+
const syncRequestedAt = /* @__PURE__ */ new Map();
|
|
552
|
+
const USAGE_CACHE_TTL_MS = 5e3;
|
|
553
|
+
const SYNC_THROTTLE_MS = 3e4;
|
|
554
|
+
const rememberUsage = (sid, patch) => {
|
|
555
|
+
const prev = usageCache.get(sid);
|
|
556
|
+
usageCache.set(sid, { ...prev, ...patch, at: Date.now() });
|
|
557
|
+
};
|
|
558
|
+
const cachedUsage = (sid) => {
|
|
559
|
+
const hit = usageCache.get(sid);
|
|
560
|
+
if (!hit) return void 0;
|
|
561
|
+
if (Date.now() - hit.at > USAGE_CACHE_TTL_MS) return void 0;
|
|
562
|
+
return hit;
|
|
563
|
+
};
|
|
564
|
+
const requestMessageSync = (sid) => {
|
|
565
|
+
const last = syncRequestedAt.get(sid) ?? 0;
|
|
566
|
+
if (Date.now() - last < SYNC_THROTTLE_MS) return;
|
|
567
|
+
syncRequestedAt.set(sid, Date.now());
|
|
568
|
+
try {
|
|
569
|
+
const sync = context.data.session.message.sync;
|
|
570
|
+
if (typeof sync === "function") void sync.call(context.data.session.message, sid).catch(() => {
|
|
571
|
+
});
|
|
572
|
+
} catch {
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
const listedSession = (sid) => {
|
|
576
|
+
try {
|
|
577
|
+
return context.data.session.list()?.find((s) => s.id === sid);
|
|
578
|
+
} catch {
|
|
579
|
+
return void 0;
|
|
580
|
+
}
|
|
581
|
+
};
|
|
136
582
|
return {
|
|
137
583
|
kv: {
|
|
138
584
|
get: kvGet,
|
|
139
|
-
set: kvSet
|
|
585
|
+
set: kvSet,
|
|
586
|
+
update: kvUpdate
|
|
140
587
|
},
|
|
141
588
|
usage: {
|
|
142
589
|
readSessionTokens: (sid) => {
|
|
143
590
|
if (!sid) return void 0;
|
|
591
|
+
try {
|
|
592
|
+
const dbTokens = dbIndex?.info(sid)?.tokens;
|
|
593
|
+
if (dbTokens !== void 0) {
|
|
594
|
+
rememberUsage(sid, { tokens: dbTokens });
|
|
595
|
+
return dbTokens;
|
|
596
|
+
}
|
|
597
|
+
} catch {
|
|
598
|
+
}
|
|
144
599
|
try {
|
|
145
600
|
const msgs = context.data.session.message.list(sid);
|
|
146
601
|
if (msgs) {
|
|
@@ -150,9 +605,15 @@ function createPanelApi(context, settings) {
|
|
|
150
605
|
const t = m.tokens;
|
|
151
606
|
if (!t || !(Number(t.output) > 0)) continue;
|
|
152
607
|
const ctx = (Number(t.input) || 0) + (Number(t.output) || 0) + (Number(t.reasoning) || 0) + (Number(t.cache?.read) || 0) + (Number(t.cache?.write) || 0);
|
|
153
|
-
if (ctx > 0)
|
|
608
|
+
if (ctx > 0) {
|
|
609
|
+
rememberUsage(sid, { tokens: ctx });
|
|
610
|
+
return ctx;
|
|
611
|
+
}
|
|
154
612
|
}
|
|
155
613
|
}
|
|
614
|
+
const cached = cachedUsage(sid)?.tokens;
|
|
615
|
+
if (cached !== void 0) return cached;
|
|
616
|
+
requestMessageSync(sid);
|
|
156
617
|
return void 0;
|
|
157
618
|
} catch {
|
|
158
619
|
return void 0;
|
|
@@ -160,33 +621,91 @@ function createPanelApi(context, settings) {
|
|
|
160
621
|
},
|
|
161
622
|
readSessionCost: (sid) => {
|
|
162
623
|
if (!sid) return void 0;
|
|
624
|
+
try {
|
|
625
|
+
const dbCost = dbIndex?.info(sid)?.cost;
|
|
626
|
+
if (dbCost !== void 0) {
|
|
627
|
+
rememberUsage(sid, { cost: dbCost });
|
|
628
|
+
return dbCost;
|
|
629
|
+
}
|
|
630
|
+
} catch {
|
|
631
|
+
}
|
|
632
|
+
try {
|
|
633
|
+
const direct = context.data.session.cost(sid);
|
|
634
|
+
if (typeof direct === "number" && direct > 0) {
|
|
635
|
+
rememberUsage(sid, { cost: direct });
|
|
636
|
+
return direct;
|
|
637
|
+
}
|
|
638
|
+
} catch {
|
|
639
|
+
}
|
|
163
640
|
try {
|
|
164
641
|
const session = context.data.session.get(sid);
|
|
165
|
-
if (session?.cost != null && session.cost > 0)
|
|
642
|
+
if (session?.cost != null && session.cost > 0) {
|
|
643
|
+
rememberUsage(sid, { cost: session.cost });
|
|
644
|
+
return session.cost;
|
|
645
|
+
}
|
|
646
|
+
const listed = listedSession(sid);
|
|
647
|
+
if (listed?.cost != null && listed.cost > 0) {
|
|
648
|
+
rememberUsage(sid, { cost: listed.cost });
|
|
649
|
+
return listed.cost;
|
|
650
|
+
}
|
|
166
651
|
const msgs = context.data.session.message.list(sid);
|
|
167
|
-
if (
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
652
|
+
if (Array.isArray(msgs) && msgs.length > 0) {
|
|
653
|
+
let total = 0;
|
|
654
|
+
let sawAssistant = false;
|
|
655
|
+
for (const m of msgs) {
|
|
656
|
+
if (m.type !== "assistant") continue;
|
|
657
|
+
sawAssistant = true;
|
|
658
|
+
if (typeof m.cost === "number") total += m.cost;
|
|
659
|
+
}
|
|
660
|
+
if (sawAssistant) {
|
|
661
|
+
rememberUsage(sid, { cost: total });
|
|
662
|
+
return total;
|
|
663
|
+
}
|
|
171
664
|
}
|
|
172
|
-
|
|
665
|
+
const cached = cachedUsage(sid)?.cost;
|
|
666
|
+
if (cached !== void 0) return cached;
|
|
667
|
+
requestMessageSync(sid);
|
|
668
|
+
return void 0;
|
|
173
669
|
} catch {
|
|
174
670
|
return void 0;
|
|
175
671
|
}
|
|
176
672
|
},
|
|
177
673
|
readSessionModel: (sid) => {
|
|
178
674
|
if (!sid) return void 0;
|
|
675
|
+
try {
|
|
676
|
+
const dbModel = dbIndex?.info(sid)?.model;
|
|
677
|
+
if (dbModel !== void 0) {
|
|
678
|
+
rememberUsage(sid, { model: dbModel });
|
|
679
|
+
return dbModel;
|
|
680
|
+
}
|
|
681
|
+
} catch {
|
|
682
|
+
}
|
|
179
683
|
try {
|
|
180
684
|
const msgs = context.data.session.message.list(sid);
|
|
181
685
|
if (msgs) {
|
|
182
686
|
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
183
687
|
const m = msgs[i];
|
|
184
688
|
if (m.type !== "assistant") continue;
|
|
185
|
-
const
|
|
186
|
-
if (
|
|
187
|
-
|
|
689
|
+
const id = modelIdOf(m.model);
|
|
690
|
+
if (id) {
|
|
691
|
+
rememberUsage(sid, { model: id });
|
|
692
|
+
return id;
|
|
693
|
+
}
|
|
188
694
|
}
|
|
189
695
|
}
|
|
696
|
+
const sessionModel = modelIdOf(context.data.session.get(sid)?.model);
|
|
697
|
+
if (sessionModel) {
|
|
698
|
+
rememberUsage(sid, { model: sessionModel });
|
|
699
|
+
return sessionModel;
|
|
700
|
+
}
|
|
701
|
+
const listedModel = modelIdOf(listedSession(sid)?.model);
|
|
702
|
+
if (listedModel) {
|
|
703
|
+
rememberUsage(sid, { model: listedModel });
|
|
704
|
+
return listedModel;
|
|
705
|
+
}
|
|
706
|
+
const cached = cachedUsage(sid)?.model;
|
|
707
|
+
if (cached !== void 0) return cached;
|
|
708
|
+
requestMessageSync(sid);
|
|
190
709
|
return void 0;
|
|
191
710
|
} catch {
|
|
192
711
|
return void 0;
|
|
@@ -198,7 +717,14 @@ function createPanelApi(context, settings) {
|
|
|
198
717
|
session: {
|
|
199
718
|
get: (sid) => {
|
|
200
719
|
try {
|
|
201
|
-
|
|
720
|
+
const direct = context.data.session.get(sid);
|
|
721
|
+
if (direct) return direct;
|
|
722
|
+
const list = context.data.session.list?.();
|
|
723
|
+
if (Array.isArray(list)) {
|
|
724
|
+
const found = list.find((s) => s?.id === sid);
|
|
725
|
+
if (found) return found;
|
|
726
|
+
}
|
|
727
|
+
return void 0;
|
|
202
728
|
} catch {
|
|
203
729
|
return void 0;
|
|
204
730
|
}
|
|
@@ -206,11 +732,19 @@ function createPanelApi(context, settings) {
|
|
|
206
732
|
status: (sid) => {
|
|
207
733
|
try {
|
|
208
734
|
const st = context.data.session.status(sid);
|
|
209
|
-
|
|
210
|
-
|
|
735
|
+
if (st) {
|
|
736
|
+
const type = st === "running" ? "busy" : st;
|
|
737
|
+
return { type };
|
|
738
|
+
}
|
|
739
|
+
} catch {
|
|
740
|
+
}
|
|
741
|
+
try {
|
|
742
|
+
const info = dbIndex?.info(sid);
|
|
743
|
+
if (info?.active === true) return { type: "busy" };
|
|
744
|
+
if (statusOfChild(info) !== void 0) return { type: "idle" };
|
|
211
745
|
} catch {
|
|
212
|
-
return void 0;
|
|
213
746
|
}
|
|
747
|
+
return void 0;
|
|
214
748
|
},
|
|
215
749
|
messages: (sid) => {
|
|
216
750
|
try {
|
|
@@ -229,6 +763,22 @@ function createPanelApi(context, settings) {
|
|
|
229
763
|
return [];
|
|
230
764
|
}
|
|
231
765
|
return msg.content.map((p) => toV1Part(p));
|
|
766
|
+
},
|
|
767
|
+
resolveChild: (input) => {
|
|
768
|
+
try {
|
|
769
|
+
const sid = input.callId ? dbIndex?.resolveCall(input.parentId, input.callId) : void 0;
|
|
770
|
+
if (sid) return sid;
|
|
771
|
+
return dbIndex?.matchChild(input.parentId, input.agent, input.startedAt);
|
|
772
|
+
} catch {
|
|
773
|
+
return void 0;
|
|
774
|
+
}
|
|
775
|
+
},
|
|
776
|
+
listChildren: (parentId) => {
|
|
777
|
+
try {
|
|
778
|
+
return dbIndex?.enabled() ? dbIndex.children(parentId) : void 0;
|
|
779
|
+
} catch {
|
|
780
|
+
return void 0;
|
|
781
|
+
}
|
|
232
782
|
}
|
|
233
783
|
},
|
|
234
784
|
event: {
|
|
@@ -239,9 +789,11 @@ function createPanelApi(context, settings) {
|
|
|
239
789
|
for (const evt of ["session.tool.input.started", "session.tool.called", "session.tool.progress", "session.tool.success", "session.tool.failed"]) {
|
|
240
790
|
unsubs.push(context.data.on(evt, (e) => {
|
|
241
791
|
const part = toolEventToPart(e);
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
792
|
+
const evtData = e.data;
|
|
793
|
+
if (!part) {
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
const sid = evtData?.sessionID !== void 0 ? String(evtData.sessionID) : void 0;
|
|
245
797
|
if (!sid) return;
|
|
246
798
|
cb({ type, scope: "global", payload: { part, sessionID: sid } });
|
|
247
799
|
}));
|
|
@@ -298,45 +850,100 @@ function createPanelApi(context, settings) {
|
|
|
298
850
|
};
|
|
299
851
|
}
|
|
300
852
|
|
|
301
|
-
// src/core/
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
853
|
+
// src/core/format.ts
|
|
854
|
+
function charColumns(c) {
|
|
855
|
+
const code = c.codePointAt(0) ?? 0;
|
|
856
|
+
if (code < 32) return 0;
|
|
857
|
+
if (code < 127) return 1;
|
|
858
|
+
if (code < 160) return 0;
|
|
859
|
+
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)
|
|
860
|
+
return 2;
|
|
861
|
+
return 1;
|
|
862
|
+
}
|
|
863
|
+
function visualWidth(s) {
|
|
864
|
+
let w = 0;
|
|
865
|
+
for (const c of s) w += charColumns(c);
|
|
866
|
+
return w;
|
|
867
|
+
}
|
|
868
|
+
function truncate(text, maxCols) {
|
|
869
|
+
if (visualWidth(text) <= maxCols) return text;
|
|
870
|
+
let cols = 0;
|
|
871
|
+
let i = 0;
|
|
872
|
+
for (const c of text) {
|
|
873
|
+
const w = charColumns(c);
|
|
874
|
+
if (cols + w > maxCols - 1) break;
|
|
875
|
+
cols += w;
|
|
876
|
+
i += c.length;
|
|
319
877
|
}
|
|
878
|
+
return text.slice(0, i) + "\u2026";
|
|
320
879
|
}
|
|
321
|
-
function
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
880
|
+
function fmtDurationShort(ms, running) {
|
|
881
|
+
if (running && ms < 2e3) return "";
|
|
882
|
+
if (ms < 1e3) return (ms / 1e3).toFixed(2) + "s";
|
|
883
|
+
if (ms < 6e4) return (ms / 1e3).toFixed(2) + "s";
|
|
884
|
+
const m = Math.floor(ms / 6e4);
|
|
885
|
+
const s = Math.round(ms % 6e4 / 1e3);
|
|
886
|
+
return `${m}m${s}s`;
|
|
887
|
+
}
|
|
888
|
+
var TIME_FORMATS = ["short", "decimal", "clock", "compact", "seconds"];
|
|
889
|
+
var TIME_FORMAT_SAMPLES = {
|
|
890
|
+
decimal: "45.3s \xB7 9.5m \xB7 1.9h",
|
|
891
|
+
short: "45.32s \xB7 112m35s",
|
|
892
|
+
clock: "0:45 \xB7 1:52:35",
|
|
893
|
+
compact: "45s \xB7 1h52m",
|
|
894
|
+
seconds: "45s \xB7 6755s"
|
|
895
|
+
};
|
|
896
|
+
function fmtDuration(ms, running, mode = "short") {
|
|
897
|
+
if (running && ms < 2e3) return "";
|
|
898
|
+
const t = Number.isFinite(ms) && ms > 0 ? ms : 0;
|
|
899
|
+
switch (mode) {
|
|
900
|
+
case "short":
|
|
901
|
+
return fmtDurationShort(t, false);
|
|
902
|
+
case "compact": {
|
|
903
|
+
if (t < 6e4) return `${Math.floor(t / 1e3)}s`;
|
|
904
|
+
if (t < 36e5) return `${Math.floor(t / 6e4)}m${Math.floor(t % 6e4 / 1e3)}s`;
|
|
905
|
+
return `${Math.floor(t / 36e5)}h${Math.floor(t % 36e5 / 6e4)}m`;
|
|
906
|
+
}
|
|
907
|
+
case "clock": {
|
|
908
|
+
const s = Math.floor(t % 6e4 / 1e3);
|
|
909
|
+
if (t < 36e5) return `${Math.floor(t / 6e4)}:${String(s).padStart(2, "0")}`;
|
|
910
|
+
const m = Math.floor(t % 36e5 / 6e4);
|
|
911
|
+
return `${Math.floor(t / 36e5)}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
912
|
+
}
|
|
913
|
+
case "seconds":
|
|
914
|
+
return `${Math.floor(t / 1e3)}s`;
|
|
915
|
+
case "decimal":
|
|
916
|
+
default: {
|
|
917
|
+
if (t < 59950) return `${(t / 1e3).toFixed(1)}s`;
|
|
918
|
+
if (t < 3597e3) return `${(t / 6e4).toFixed(1)}m`;
|
|
919
|
+
return `${(t / 36e5).toFixed(1)}h`;
|
|
920
|
+
}
|
|
325
921
|
}
|
|
326
922
|
}
|
|
327
|
-
function
|
|
328
|
-
|
|
329
|
-
|
|
923
|
+
function fmtTokens(n) {
|
|
924
|
+
if (n < 1e3) return `${n}`;
|
|
925
|
+
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
926
|
+
return `${(n / 1e6).toFixed(1)}M`;
|
|
927
|
+
}
|
|
928
|
+
function safeErrorMsg(err) {
|
|
929
|
+
if (!err) return "";
|
|
930
|
+
if (typeof err === "string") return err;
|
|
931
|
+
if (typeof err === "object") return String(err.message || err.code || "");
|
|
932
|
+
return "";
|
|
330
933
|
}
|
|
331
934
|
|
|
332
935
|
// src/_version.ts
|
|
333
|
-
var PLUGIN_VERSION = "1.
|
|
936
|
+
var PLUGIN_VERSION = "1.7.1";
|
|
334
937
|
|
|
335
938
|
// src/i18n.ts
|
|
336
939
|
var ZH_T = {
|
|
337
940
|
"panel.title": "\u5B50\u4EE3\u7406",
|
|
338
941
|
"status.none": "\u6682\u65E0\u5B50\u4EE3\u7406",
|
|
339
942
|
"agent.label": "\u4EE3\u7406",
|
|
943
|
+
"origin.label": "\u6765\u6E90",
|
|
944
|
+
"origin.tool": "\u5B50\u4EE3\u7406\u8C03\u7528",
|
|
945
|
+
"origin.sub": "\u884D\u751F\u4F1A\u8BDD",
|
|
946
|
+
"origin.background": "\u540E\u53F0",
|
|
340
947
|
"status.label": "\u72B6\u6001",
|
|
341
948
|
"time.label": "\u8017\u65F6",
|
|
342
949
|
"tokens.label": "\u4E0A\u4E0B\u6587",
|
|
@@ -374,6 +981,7 @@ var ZH_T = {
|
|
|
374
981
|
"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",
|
|
375
982
|
"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",
|
|
376
983
|
"clear.done": "\u5DF2\u6E05\u9664 {n} \u6761\u5B50\u4EE3\u7406\u8BB0\u5F55",
|
|
984
|
+
"clear.failed": "\u6E05\u9664\u5931\u8D25",
|
|
377
985
|
"clear.empty": "\u5F53\u524D\u4F1A\u8BDD\u65E0\u5B50\u4EE3\u7406\u8BB0\u5F55",
|
|
378
986
|
"cancel.no_session": "\u5B50\u4F1A\u8BDD ID \u4E0D\u53EF\u7528",
|
|
379
987
|
"cancel.not_child": "\u76EE\u6807\u4E0D\u662F\u5B50\u4F1A\u8BDD",
|
|
@@ -384,12 +992,35 @@ var ZH_T = {
|
|
|
384
992
|
"cancel.sent": "\u5DF2\u53D1\u9001\u53D6\u6D88\u6307\u4EE4",
|
|
385
993
|
"cancel.failed": "\u53D6\u6D88\u5931\u8D25",
|
|
386
994
|
"borderShown": "\u9762\u677F\u8FB9\u6846 \u5DF2\u663E\u793A",
|
|
387
|
-
"borderHidden": "\u9762\u677F\u8FB9\u6846 \u5DF2\u9690\u85CF"
|
|
995
|
+
"borderHidden": "\u9762\u677F\u8FB9\u6846 \u5DF2\u9690\u85CF",
|
|
996
|
+
"settings.title": "SubAgent Magazine \u2014 \u8BBE\u7F6E",
|
|
997
|
+
"settings.section.general": "\u901A\u7528",
|
|
998
|
+
"settings.lang": "\u8BED\u8A00",
|
|
999
|
+
"settings.max": "\u6700\u5927\u6761\u76EE\u6570",
|
|
1000
|
+
"settings.order": "\u6392\u5E8F\u65B9\u5F0F",
|
|
1001
|
+
"settings.scroll": "\u6EDA\u52A8\u6A21\u5F0F",
|
|
1002
|
+
"settings.ttl": "\u4FDD\u7559\u671F\u9650",
|
|
1003
|
+
"settings.border": "\u9762\u677F\u8FB9\u6846",
|
|
1004
|
+
"settings.showEntryCost": "\u6BCF\u6761\u5B50\u4EE3\u7406\u663E\u793A\u8D39\u7528",
|
|
1005
|
+
"settings.showEntryTime": "\u5217\u8868\u4E2D\u663E\u793A\u8017\u65F6",
|
|
1006
|
+
"settings.showEntryTokens": "\u5217\u8868\u4E2D\u663E\u793A Token \u6570",
|
|
1007
|
+
"settings.timeFormat": "\u65F6\u95F4\u683C\u5F0F",
|
|
1008
|
+
"settings.showOrigin": "\u5217\u8868\u663E\u793A\u6765\u6E90\u6807\u8BB0",
|
|
1009
|
+
"settings.dbSync": "\u672C\u5730\u6570\u636E\u5E93\u8865\u5168",
|
|
1010
|
+
"settings.on": "\u5F00",
|
|
1011
|
+
"settings.off": "\u5173",
|
|
1012
|
+
"settings.saved": "\u5DF2\u4FDD\u5B58 {item}\uFF1A{value}",
|
|
1013
|
+
"settings.invalid": "\u65E0\u6548\u7684\u6570\u503C",
|
|
1014
|
+
"settings.close": "\u5173\u95ED"
|
|
388
1015
|
};
|
|
389
1016
|
var EN_T = {
|
|
390
1017
|
"panel.title": "SubAgent",
|
|
391
1018
|
"status.none": "No sub-agents yet",
|
|
392
1019
|
"agent.label": "agent",
|
|
1020
|
+
"origin.label": "origin",
|
|
1021
|
+
"origin.tool": "sub-agent call",
|
|
1022
|
+
"origin.sub": "spawned session",
|
|
1023
|
+
"origin.background": "background",
|
|
393
1024
|
"status.label": "status",
|
|
394
1025
|
"time.label": "time",
|
|
395
1026
|
"tokens.label": "tokens",
|
|
@@ -427,6 +1058,7 @@ var EN_T = {
|
|
|
427
1058
|
"clear.prompt": "Clear all sub-agent records for this session? This cannot be undone.",
|
|
428
1059
|
"clear.prompt_running": "{n} sub-agent(s) are still running. Clearing will discard them permanently. Continue?",
|
|
429
1060
|
"clear.done": "Cleared {n} sub-agent record(s)",
|
|
1061
|
+
"clear.failed": "Clear failed",
|
|
430
1062
|
"clear.empty": "No sub-agent records in this session",
|
|
431
1063
|
"cancel.no_session": "Child session ID is unavailable",
|
|
432
1064
|
"cancel.not_child": "Target is not a child session",
|
|
@@ -437,12 +1069,35 @@ var EN_T = {
|
|
|
437
1069
|
"cancel.sent": "Cancel instruction sent",
|
|
438
1070
|
"cancel.failed": "Cancellation failed",
|
|
439
1071
|
"borderShown": "Panel border shown",
|
|
440
|
-
"borderHidden": "Panel border hidden"
|
|
1072
|
+
"borderHidden": "Panel border hidden",
|
|
1073
|
+
"settings.title": "SubAgent Magazine \u2014 Settings",
|
|
1074
|
+
"settings.section.general": "General",
|
|
1075
|
+
"settings.lang": "Language",
|
|
1076
|
+
"settings.max": "Max entries",
|
|
1077
|
+
"settings.order": "Sort order",
|
|
1078
|
+
"settings.scroll": "Scroll mode",
|
|
1079
|
+
"settings.ttl": "Retention",
|
|
1080
|
+
"settings.border": "Panel border",
|
|
1081
|
+
"settings.showEntryCost": "Cost per sub-agent",
|
|
1082
|
+
"settings.showEntryTime": "Elapsed time in list",
|
|
1083
|
+
"settings.showEntryTokens": "Token count in list",
|
|
1084
|
+
"settings.showOrigin": "Origin indicators in list",
|
|
1085
|
+
"settings.timeFormat": "Time format",
|
|
1086
|
+
"settings.dbSync": "Local database enrichment",
|
|
1087
|
+
"settings.on": "on",
|
|
1088
|
+
"settings.off": "off",
|
|
1089
|
+
"settings.saved": "Saved {item}: {value}",
|
|
1090
|
+
"settings.invalid": "Invalid value",
|
|
1091
|
+
"settings.close": "Close"
|
|
441
1092
|
};
|
|
442
1093
|
var JA_T = {
|
|
443
1094
|
"panel.title": "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8",
|
|
444
1095
|
"status.none": "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u306A\u3057",
|
|
445
1096
|
"agent.label": "\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8",
|
|
1097
|
+
"origin.label": "\u767A\u751F\u5143",
|
|
1098
|
+
"origin.tool": "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u547C\u3073\u51FA\u3057",
|
|
1099
|
+
"origin.sub": "\u751F\u6210\u3055\u308C\u305F\u30BB\u30C3\u30B7\u30E7\u30F3",
|
|
1100
|
+
"origin.background": "\u30D0\u30C3\u30AF\u30B0\u30E9\u30A6\u30F3\u30C9",
|
|
446
1101
|
"status.label": "\u72B6\u614B",
|
|
447
1102
|
"time.label": "\u6642\u9593",
|
|
448
1103
|
"tokens.label": "\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8",
|
|
@@ -480,6 +1135,7 @@ var JA_T = {
|
|
|
480
1135
|
"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",
|
|
481
1136
|
"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",
|
|
482
1137
|
"clear.done": "{n} \u4EF6\u306E\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u8A18\u9332\u3092\u524A\u9664\u3057\u307E\u3057\u305F",
|
|
1138
|
+
"clear.failed": "\u30AF\u30EA\u30A2\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
|
|
483
1139
|
"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",
|
|
484
1140
|
"cancel.no_session": "\u5B50\u30BB\u30C3\u30B7\u30E7\u30F3 ID \u304C\u5229\u7528\u3067\u304D\u307E\u305B\u3093",
|
|
485
1141
|
"cancel.not_child": "\u5BFE\u8C61\u306F\u5B50\u30BB\u30C3\u30B7\u30E7\u30F3\u3067\u306F\u3042\u308A\u307E\u305B\u3093",
|
|
@@ -490,12 +1146,35 @@ var JA_T = {
|
|
|
490
1146
|
"cancel.sent": "\u30AD\u30E3\u30F3\u30BB\u30EB\u6307\u793A\u3092\u9001\u4FE1\u3057\u307E\u3057\u305F",
|
|
491
1147
|
"cancel.failed": "\u30AD\u30E3\u30F3\u30BB\u30EB\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
|
|
492
1148
|
"borderShown": "\u30D1\u30CD\u30EB\u67A0\u7DDA \u8868\u793A",
|
|
493
|
-
"borderHidden": "\u30D1\u30CD\u30EB\u67A0\u7DDA \u975E\u8868\u793A"
|
|
1149
|
+
"borderHidden": "\u30D1\u30CD\u30EB\u67A0\u7DDA \u975E\u8868\u793A",
|
|
1150
|
+
"settings.title": "SubAgent Magazine \u2014 \u8A2D\u5B9A",
|
|
1151
|
+
"settings.section.general": "\u4E00\u822C",
|
|
1152
|
+
"settings.lang": "\u8A00\u8A9E",
|
|
1153
|
+
"settings.max": "\u6700\u5927\u8868\u793A\u6570",
|
|
1154
|
+
"settings.order": "\u4E26\u3073\u9806",
|
|
1155
|
+
"settings.scroll": "\u30B9\u30AF\u30ED\u30FC\u30EB",
|
|
1156
|
+
"settings.ttl": "\u4FDD\u6301\u671F\u9593",
|
|
1157
|
+
"settings.border": "\u30D1\u30CD\u30EB\u67A0",
|
|
1158
|
+
"settings.showEntryCost": "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u6BCE\u306E\u8CBB\u7528",
|
|
1159
|
+
"settings.showEntryTime": "\u4E00\u89A7\u306B\u6240\u8981\u6642\u9593\u3092\u8868\u793A",
|
|
1160
|
+
"settings.showEntryTokens": "\u4E00\u89A7\u306B\u30C8\u30FC\u30AF\u30F3\u6570\u3092\u8868\u793A",
|
|
1161
|
+
"settings.showOrigin": "\u4E00\u89A7\u306B\u7531\u6765\u30DE\u30FC\u30AF\u3092\u8868\u793A",
|
|
1162
|
+
"settings.timeFormat": "\u6642\u9593\u5F62\u5F0F",
|
|
1163
|
+
"settings.dbSync": "\u30ED\u30FC\u30AB\u30EBDB\u88DC\u5B8C",
|
|
1164
|
+
"settings.on": "\u30AA\u30F3",
|
|
1165
|
+
"settings.off": "\u30AA\u30D5",
|
|
1166
|
+
"settings.saved": "\u4FDD\u5B58\u3057\u307E\u3057\u305F {item}\uFF1A{value}",
|
|
1167
|
+
"settings.invalid": "\u7121\u52B9\u306A\u5024\u3067\u3059",
|
|
1168
|
+
"settings.close": "\u9589\u3058\u308B"
|
|
494
1169
|
};
|
|
495
1170
|
var KO_T = {
|
|
496
1171
|
"panel.title": "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8",
|
|
497
1172
|
"status.none": "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uC5C6\uC74C",
|
|
498
1173
|
"agent.label": "\uC5D0\uC774\uC804\uD2B8",
|
|
1174
|
+
"origin.label": "\uCD9C\uCC98",
|
|
1175
|
+
"origin.tool": "\uD558\uC704 \uC5D0\uC774\uC804\uD2B8 \uD638\uCD9C",
|
|
1176
|
+
"origin.sub": "\uC0DD\uC131\uB41C \uC138\uC158",
|
|
1177
|
+
"origin.background": "\uBC31\uADF8\uB77C\uC6B4\uB4DC",
|
|
499
1178
|
"status.label": "\uC0C1\uD0DC",
|
|
500
1179
|
"time.label": "\uC2DC\uAC04",
|
|
501
1180
|
"tokens.label": "\uCEE8\uD14D\uC2A4\uD2B8",
|
|
@@ -533,6 +1212,7 @@ var KO_T = {
|
|
|
533
1212
|
"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.",
|
|
534
1213
|
"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?",
|
|
535
1214
|
"clear.done": "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uAE30\uB85D {n}\uAC1C\uB97C \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4",
|
|
1215
|
+
"clear.failed": "\uC9C0\uC6B0\uAE30\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4",
|
|
536
1216
|
"clear.empty": "\uC774 \uC138\uC158\uC5D0 \uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uAE30\uB85D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
537
1217
|
"cancel.no_session": "\uD558\uC704 \uC138\uC158 ID\uB97C \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
538
1218
|
"cancel.not_child": "\uB300\uC0C1\uC774 \uD558\uC704 \uC138\uC158\uC774 \uC544\uB2D9\uB2C8\uB2E4",
|
|
@@ -543,7 +1223,26 @@ var KO_T = {
|
|
|
543
1223
|
"cancel.sent": "\uCDE8\uC18C \uC9C0\uC2DC\uB97C \uBCF4\uB0C8\uC2B5\uB2C8\uB2E4",
|
|
544
1224
|
"cancel.failed": "\uCDE8\uC18C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4",
|
|
545
1225
|
"borderShown": "\uD328\uB110 \uD14C\uB450\uB9AC \uD45C\uC2DC",
|
|
546
|
-
"borderHidden": "\uD328\uB110 \uD14C\uB450\uB9AC \uC228\uAE40"
|
|
1226
|
+
"borderHidden": "\uD328\uB110 \uD14C\uB450\uB9AC \uC228\uAE40",
|
|
1227
|
+
"settings.title": "SubAgent Magazine \u2014 \uC124\uC815",
|
|
1228
|
+
"settings.section.general": "\uC77C\uBC18",
|
|
1229
|
+
"settings.lang": "\uC5B8\uC5B4",
|
|
1230
|
+
"settings.max": "\uCD5C\uB300 \uD56D\uBAA9 \uC218",
|
|
1231
|
+
"settings.order": "\uC815\uB82C \uC21C\uC11C",
|
|
1232
|
+
"settings.scroll": "\uC2A4\uD06C\uB864 \uBAA8\uB4DC",
|
|
1233
|
+
"settings.ttl": "\uBCF4\uC874 \uAE30\uAC04",
|
|
1234
|
+
"settings.border": "\uD328\uB110 \uD14C\uB450\uB9AC",
|
|
1235
|
+
"settings.showEntryCost": "\uD558\uC704 \uC5D0\uC774\uC804\uD2B8\uBCC4 \uBE44\uC6A9",
|
|
1236
|
+
"settings.showEntryTime": "\uBAA9\uB85D\uC5D0 \uC18C\uC694 \uC2DC\uAC04 \uD45C\uC2DC",
|
|
1237
|
+
"settings.showEntryTokens": "\uBAA9\uB85D\uC5D0 \uD1A0\uD070 \uC218 \uD45C\uC2DC",
|
|
1238
|
+
"settings.showOrigin": "\uBAA9\uB85D\uC5D0 \uCD9C\uCC98 \uC544\uC774\uCF58 \uD45C\uC2DC",
|
|
1239
|
+
"settings.timeFormat": "\uC2DC\uAC04 \uD615\uC2DD",
|
|
1240
|
+
"settings.dbSync": "\uB85C\uCEEC DB \uBCF4\uC644",
|
|
1241
|
+
"settings.on": "\uCF2C",
|
|
1242
|
+
"settings.off": "\uB054",
|
|
1243
|
+
"settings.saved": "\uC800\uC7A5\uB428 {item}: {value}",
|
|
1244
|
+
"settings.invalid": "\uC798\uBABB\uB41C \uAC12",
|
|
1245
|
+
"settings.close": "\uB2EB\uAE30"
|
|
547
1246
|
};
|
|
548
1247
|
var LANGS = { zh: ZH_T, en: EN_T, ja: JA_T, ko: KO_T };
|
|
549
1248
|
var LANG_META = [
|
|
@@ -579,11 +1278,308 @@ import { createSignal } from "solid-js";
|
|
|
579
1278
|
var globalEntryCache = /* @__PURE__ */ new Map();
|
|
580
1279
|
var [clearTick, setClearTick] = createSignal(0);
|
|
581
1280
|
|
|
1281
|
+
// src/panel/entry-map.ts
|
|
1282
|
+
function findSubEntryKey(entries, id, sessionId) {
|
|
1283
|
+
if (sessionId) {
|
|
1284
|
+
for (const [key, entry] of entries) {
|
|
1285
|
+
if (entry.sessionId === sessionId) return key;
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
return entries.has(id) ? id : void 0;
|
|
1289
|
+
}
|
|
1290
|
+
function upsertSubEntry(entries, partial, now = Date.now()) {
|
|
1291
|
+
const key = findSubEntryKey(entries, partial.id, partial.sessionId) ?? partial.id;
|
|
1292
|
+
const existing = entries.get(key);
|
|
1293
|
+
const next = new Map(entries);
|
|
1294
|
+
if (key !== partial.id) next.delete(partial.id);
|
|
1295
|
+
const ended = partial.status === "done" || partial.status === "error" || partial.status === "cancelled";
|
|
1296
|
+
next.set(key, {
|
|
1297
|
+
...existing ?? { startedAt: now },
|
|
1298
|
+
...partial,
|
|
1299
|
+
id: existing?.id ?? partial.id,
|
|
1300
|
+
startedAt: existing?.startedAt || partial.startedAt || now,
|
|
1301
|
+
endedAt: ended ? existing?.endedAt ?? partial.endedAt ?? now : void 0
|
|
1302
|
+
});
|
|
1303
|
+
return next;
|
|
1304
|
+
}
|
|
1305
|
+
function statusRank(status) {
|
|
1306
|
+
if (status === "running") return 0;
|
|
1307
|
+
if (status === "cancel_requested") return 1;
|
|
1308
|
+
return 2;
|
|
1309
|
+
}
|
|
1310
|
+
var isTerminalStatus = (status) => statusRank(status) === 2;
|
|
1311
|
+
function minDefined(a, b) {
|
|
1312
|
+
if (a === void 0) return b;
|
|
1313
|
+
if (b === void 0) return a;
|
|
1314
|
+
return Math.min(a, b);
|
|
1315
|
+
}
|
|
1316
|
+
function maxDefined(a, b) {
|
|
1317
|
+
if (a === void 0) return b;
|
|
1318
|
+
if (b === void 0) return a;
|
|
1319
|
+
return Math.max(a, b);
|
|
1320
|
+
}
|
|
1321
|
+
function mergeSubEntry(base, incoming) {
|
|
1322
|
+
const successor = statusRank(incoming.status) > statusRank(base.status) ? incoming : base;
|
|
1323
|
+
const status = successor.status;
|
|
1324
|
+
const ended = isTerminalStatus(status);
|
|
1325
|
+
return {
|
|
1326
|
+
...base,
|
|
1327
|
+
...incoming,
|
|
1328
|
+
id: base.id,
|
|
1329
|
+
status,
|
|
1330
|
+
sessionId: incoming.sessionId ?? base.sessionId,
|
|
1331
|
+
startedAt: minDefined(base.startedAt, incoming.startedAt) ?? base.startedAt,
|
|
1332
|
+
endedAt: ended ? base.endedAt ?? incoming.endedAt ?? Date.now() : void 0,
|
|
1333
|
+
tokens: maxDefined(base.tokens, incoming.tokens),
|
|
1334
|
+
cost: maxDefined(base.cost, incoming.cost),
|
|
1335
|
+
model: incoming.model ?? base.model,
|
|
1336
|
+
todoTotal: maxDefined(base.todoTotal, incoming.todoTotal),
|
|
1337
|
+
todoDone: maxDefined(base.todoDone, incoming.todoDone),
|
|
1338
|
+
error: incoming.error ?? base.error,
|
|
1339
|
+
cancelRequestedAt: minDefined(base.cancelRequestedAt, incoming.cancelRequestedAt),
|
|
1340
|
+
abortAccepted: base.abortAccepted || incoming.abortAccepted || void 0,
|
|
1341
|
+
cancelReason: incoming.cancelReason ?? base.cancelReason
|
|
1342
|
+
};
|
|
1343
|
+
}
|
|
1344
|
+
function mergeSubEntries(base, incoming) {
|
|
1345
|
+
const out = /* @__PURE__ */ new Map();
|
|
1346
|
+
for (const entry of base) out.set(entry.id, entry);
|
|
1347
|
+
for (const entry of incoming) {
|
|
1348
|
+
const key = findSubEntryKey(out, entry.id, entry.sessionId);
|
|
1349
|
+
if (!key) {
|
|
1350
|
+
out.set(entry.id, entry);
|
|
1351
|
+
continue;
|
|
1352
|
+
}
|
|
1353
|
+
out.set(key, mergeSubEntry(out.get(key), entry));
|
|
1354
|
+
}
|
|
1355
|
+
return out;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
// src/v2/settings-menu.ts
|
|
1359
|
+
var TTL_VALUES = [3, 7, 14, 30, 0];
|
|
1360
|
+
var nextTick = () => new Promise((resolve) => setTimeout(resolve, 0));
|
|
1361
|
+
function openSettingsMenu(context, api, signals) {
|
|
1362
|
+
runSettingsMenu(context, api, signals).catch((err) => {
|
|
1363
|
+
try {
|
|
1364
|
+
context.ui.toast.show({ message: String(err), variant: "error" });
|
|
1365
|
+
} catch {
|
|
1366
|
+
}
|
|
1367
|
+
});
|
|
1368
|
+
}
|
|
1369
|
+
async function runSettingsMenu(context, api, signals) {
|
|
1370
|
+
const t = createT(() => signals.lang());
|
|
1371
|
+
const kv = api.kv;
|
|
1372
|
+
const onOff = (v) => v ? t("settings.on") : t("settings.off");
|
|
1373
|
+
const langLabel = () => LANG_META.find((m) => m.code === signals.lang())?.label ?? signals.lang();
|
|
1374
|
+
const ttlTitle = (d) => d === 0 ? t("ttl.unlimited") : t(d === 3 ? "ttl.3d" : d === 7 ? "ttl.7d" : d === 14 ? "ttl.14d" : "ttl.30d");
|
|
1375
|
+
const ttlLabel = () => ttlTitle(readTTLDays(kv));
|
|
1376
|
+
const orderLabel = () => signals.sortOrder() === "desc" ? t("order.desc") : t("order.asc");
|
|
1377
|
+
const scrollLabel = () => signals.scrollMode() === "wheel" ? t("scroll.wheel") : t("scroll.click");
|
|
1378
|
+
const toast = (item, value) => context.ui.toast.show({ message: t("settings.saved", { item, value }) });
|
|
1379
|
+
while (true) {
|
|
1380
|
+
const category = t("settings.section.general");
|
|
1381
|
+
const choice = await context.ui.dialog.select({
|
|
1382
|
+
title: t("settings.title"),
|
|
1383
|
+
options: [
|
|
1384
|
+
{ title: t("settings.lang"), value: "lang", description: langLabel(), category },
|
|
1385
|
+
{ title: t("settings.max"), value: "max", description: String(signals.maxEntries()), category },
|
|
1386
|
+
{ title: t("settings.order"), value: "order", description: orderLabel(), category },
|
|
1387
|
+
{ title: t("settings.scroll"), value: "scroll", description: scrollLabel(), category },
|
|
1388
|
+
{ title: t("settings.ttl"), value: "ttl", description: ttlLabel(), category },
|
|
1389
|
+
{ title: t("settings.border"), value: "border", description: onOff(signals.borderVisible()), category },
|
|
1390
|
+
{ title: t("settings.showEntryCost"), value: "cost", description: onOff(signals.showEntryCost()), category },
|
|
1391
|
+
{ title: t("settings.showEntryTime"), value: "time", description: onOff(signals.showEntryTime()), category },
|
|
1392
|
+
{ title: t("settings.timeFormat"), value: "timefmt", description: TIME_FORMAT_SAMPLES[signals.timeFormat()], category },
|
|
1393
|
+
{ title: t("settings.showEntryTokens"), value: "tokens", description: onOff(signals.showEntryTokens()), category },
|
|
1394
|
+
{ title: t("settings.showOrigin"), value: "origin", description: onOff(signals.showOrigin()), category },
|
|
1395
|
+
{ title: t("settings.dbSync"), value: "dbsync", description: onOff(signals.dbSync()), category },
|
|
1396
|
+
{ title: t("settings.close"), value: "close" }
|
|
1397
|
+
]
|
|
1398
|
+
});
|
|
1399
|
+
if (choice === void 0 || choice === "close") return;
|
|
1400
|
+
if (choice === "lang") {
|
|
1401
|
+
const picked = await context.ui.dialog.select({
|
|
1402
|
+
title: t("settings.lang"),
|
|
1403
|
+
options: LANG_META.map((m) => ({ title: m.label, value: m.code })),
|
|
1404
|
+
current: signals.lang()
|
|
1405
|
+
});
|
|
1406
|
+
if (picked) {
|
|
1407
|
+
signals.setLang(picked);
|
|
1408
|
+
kv.set(SETTING_KEYS.lang, picked);
|
|
1409
|
+
toast(t("settings.lang"), LANG_META.find((m) => m.code === picked)?.label ?? picked);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
if (choice === "max") {
|
|
1413
|
+
const val = await context.ui.dialog.prompt({
|
|
1414
|
+
title: t("settings.max"),
|
|
1415
|
+
message: "1\u201350",
|
|
1416
|
+
placeholder: String(signals.maxEntries())
|
|
1417
|
+
});
|
|
1418
|
+
if (val !== void 0) {
|
|
1419
|
+
const n = parseInt(val.trim(), 10);
|
|
1420
|
+
if (Number.isNaN(n)) {
|
|
1421
|
+
context.ui.toast.show({ message: t("settings.invalid"), variant: "warning" });
|
|
1422
|
+
} else {
|
|
1423
|
+
const clamped = Math.max(1, Math.min(50, n));
|
|
1424
|
+
signals.setMaxEntries(clamped);
|
|
1425
|
+
kv.set(SETTING_KEYS.maxEntries, clamped);
|
|
1426
|
+
toast(t("settings.max"), String(clamped));
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
if (choice === "order") {
|
|
1431
|
+
const picked = await context.ui.dialog.select({
|
|
1432
|
+
title: t("settings.order"),
|
|
1433
|
+
options: [
|
|
1434
|
+
{ title: t("order.desc"), value: "desc" },
|
|
1435
|
+
{ title: t("order.asc"), value: "asc" }
|
|
1436
|
+
],
|
|
1437
|
+
current: signals.sortOrder()
|
|
1438
|
+
});
|
|
1439
|
+
if (picked) {
|
|
1440
|
+
signals.setSortOrder(picked);
|
|
1441
|
+
kv.set(SETTING_KEYS.order, picked);
|
|
1442
|
+
toast(t("settings.order"), picked === "desc" ? t("order.desc") : t("order.asc"));
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
if (choice === "scroll") {
|
|
1446
|
+
const picked = await context.ui.dialog.select({
|
|
1447
|
+
title: t("settings.scroll"),
|
|
1448
|
+
options: [
|
|
1449
|
+
{ title: t("scroll.wheel"), value: "wheel" },
|
|
1450
|
+
{ title: t("scroll.click"), value: "click" }
|
|
1451
|
+
],
|
|
1452
|
+
current: signals.scrollMode()
|
|
1453
|
+
});
|
|
1454
|
+
if (picked) {
|
|
1455
|
+
signals.setScrollMode(picked);
|
|
1456
|
+
kv.set(SETTING_KEYS.scrollMode, picked);
|
|
1457
|
+
toast(t("settings.scroll"), picked === "wheel" ? t("scroll.wheel") : t("scroll.click"));
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
if (choice === "ttl") {
|
|
1461
|
+
const picked = await context.ui.dialog.select({
|
|
1462
|
+
title: t("settings.ttl"),
|
|
1463
|
+
options: TTL_VALUES.map((d) => ({ title: ttlTitle(d), value: d })),
|
|
1464
|
+
current: readTTLDays(kv)
|
|
1465
|
+
});
|
|
1466
|
+
if (picked !== void 0) {
|
|
1467
|
+
kv.set(SETTING_KEYS.ttlDays, String(picked));
|
|
1468
|
+
toast(t("settings.ttl"), ttlTitle(picked));
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
if (choice === "border") {
|
|
1472
|
+
const picked = await context.ui.dialog.select({
|
|
1473
|
+
title: t("settings.border"),
|
|
1474
|
+
options: [
|
|
1475
|
+
{ title: t("settings.on"), value: true },
|
|
1476
|
+
{ title: t("settings.off"), value: false }
|
|
1477
|
+
],
|
|
1478
|
+
current: signals.borderVisible()
|
|
1479
|
+
});
|
|
1480
|
+
if (picked !== void 0) {
|
|
1481
|
+
signals.setBorderVisible(picked);
|
|
1482
|
+
kv.set(SETTING_KEYS.border, picked);
|
|
1483
|
+
toast(t("settings.border"), onOff(picked));
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
if (choice === "cost") {
|
|
1487
|
+
const picked = await context.ui.dialog.select({
|
|
1488
|
+
title: t("settings.showEntryCost"),
|
|
1489
|
+
options: [
|
|
1490
|
+
{ title: t("settings.on"), value: true },
|
|
1491
|
+
{ title: t("settings.off"), value: false }
|
|
1492
|
+
],
|
|
1493
|
+
current: signals.showEntryCost()
|
|
1494
|
+
});
|
|
1495
|
+
if (picked !== void 0) {
|
|
1496
|
+
signals.setShowEntryCost(picked);
|
|
1497
|
+
kv.set(SETTING_KEYS.showEntryCost, picked);
|
|
1498
|
+
toast(t("settings.showEntryCost"), onOff(picked));
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
if (choice === "time") {
|
|
1502
|
+
const picked = await context.ui.dialog.select({
|
|
1503
|
+
title: t("settings.showEntryTime"),
|
|
1504
|
+
options: [
|
|
1505
|
+
{ title: t("settings.on"), value: true },
|
|
1506
|
+
{ title: t("settings.off"), value: false }
|
|
1507
|
+
],
|
|
1508
|
+
current: signals.showEntryTime()
|
|
1509
|
+
});
|
|
1510
|
+
if (picked !== void 0) {
|
|
1511
|
+
signals.setShowEntryTime(picked);
|
|
1512
|
+
kv.set(SETTING_KEYS.showEntryTime, picked);
|
|
1513
|
+
toast(t("settings.showEntryTime"), onOff(picked));
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
if (choice === "timefmt") {
|
|
1517
|
+
const picked = await context.ui.dialog.select({
|
|
1518
|
+
title: t("settings.timeFormat"),
|
|
1519
|
+
options: TIME_FORMATS.map((f) => ({ title: `${f} \u2014 ${TIME_FORMAT_SAMPLES[f]}`, value: f })),
|
|
1520
|
+
current: signals.timeFormat()
|
|
1521
|
+
});
|
|
1522
|
+
if (picked) {
|
|
1523
|
+
signals.setTimeFormat(picked);
|
|
1524
|
+
kv.set(SETTING_KEYS.timeFormat, picked);
|
|
1525
|
+
toast(t("settings.timeFormat"), TIME_FORMAT_SAMPLES[picked]);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
if (choice === "tokens") {
|
|
1529
|
+
const picked = await context.ui.dialog.select({
|
|
1530
|
+
title: t("settings.showEntryTokens"),
|
|
1531
|
+
options: [
|
|
1532
|
+
{ title: t("settings.on"), value: true },
|
|
1533
|
+
{ title: t("settings.off"), value: false }
|
|
1534
|
+
],
|
|
1535
|
+
current: signals.showEntryTokens()
|
|
1536
|
+
});
|
|
1537
|
+
if (picked !== void 0) {
|
|
1538
|
+
signals.setShowEntryTokens(picked);
|
|
1539
|
+
kv.set(SETTING_KEYS.showEntryTokens, picked);
|
|
1540
|
+
toast(t("settings.showEntryTokens"), onOff(picked));
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
if (choice === "origin") {
|
|
1544
|
+
const picked = await context.ui.dialog.select({
|
|
1545
|
+
title: t("settings.showOrigin"),
|
|
1546
|
+
options: [
|
|
1547
|
+
{ title: t("settings.on"), value: true },
|
|
1548
|
+
{ title: t("settings.off"), value: false }
|
|
1549
|
+
],
|
|
1550
|
+
current: signals.showOrigin()
|
|
1551
|
+
});
|
|
1552
|
+
if (picked !== void 0) {
|
|
1553
|
+
signals.setShowOrigin(picked);
|
|
1554
|
+
kv.set(SETTING_KEYS.showOrigin, picked);
|
|
1555
|
+
toast(t("settings.showOrigin"), onOff(picked));
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
if (choice === "dbsync") {
|
|
1559
|
+
const picked = await context.ui.dialog.select({
|
|
1560
|
+
title: t("settings.dbSync"),
|
|
1561
|
+
options: [
|
|
1562
|
+
{ title: t("settings.on"), value: true },
|
|
1563
|
+
{ title: t("settings.off"), value: false }
|
|
1564
|
+
],
|
|
1565
|
+
current: signals.dbSync()
|
|
1566
|
+
});
|
|
1567
|
+
if (picked !== void 0) {
|
|
1568
|
+
signals.setDbSync(picked);
|
|
1569
|
+
kv.set(SETTING_KEYS.dbSync, picked);
|
|
1570
|
+
toast(t("settings.dbSync"), onOff(picked));
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
await nextTick();
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
|
|
582
1577
|
// src/v2/commands.ts
|
|
583
1578
|
function makeCommands(context, api, signals) {
|
|
584
1579
|
const t = createT(() => signals.lang());
|
|
585
1580
|
const kv = api.kv;
|
|
586
1581
|
const clampMax = (n) => Math.max(1, Math.min(50, n));
|
|
1582
|
+
const onOff = (v) => v ? t("settings.on") : t("settings.off");
|
|
587
1583
|
const resolveParent = (sid) => {
|
|
588
1584
|
try {
|
|
589
1585
|
const session = api.session.get(sid);
|
|
@@ -670,6 +1666,125 @@ function makeCommands(context, api, signals) {
|
|
|
670
1666
|
api.ui.toast(`Max entries: ${n}`);
|
|
671
1667
|
}
|
|
672
1668
|
},
|
|
1669
|
+
{
|
|
1670
|
+
id: "opencode-subagent-magazine.subagent.config",
|
|
1671
|
+
title: "SubAgent Magazine: Settings",
|
|
1672
|
+
description: "Show current settings (change each via its own command)",
|
|
1673
|
+
slash: { name: "subagent-config" },
|
|
1674
|
+
palette: true,
|
|
1675
|
+
run: () => {
|
|
1676
|
+
const ttl = readTTLDays(kv);
|
|
1677
|
+
const langLabel = LANG_META.find((m) => m.code === signals.lang())?.label ?? signals.lang();
|
|
1678
|
+
const message = [
|
|
1679
|
+
`${t("settings.lang")}: ${langLabel}`,
|
|
1680
|
+
`${t("settings.max")}: ${signals.maxEntries()}`,
|
|
1681
|
+
`${t("settings.order")}: ${signals.sortOrder() === "desc" ? t("order.desc") : t("order.asc")}`,
|
|
1682
|
+
`${t("settings.scroll")}: ${signals.scrollMode() === "wheel" ? t("scroll.wheel") : t("scroll.click")}`,
|
|
1683
|
+
`${t("settings.ttl")}: ${ttl === 0 ? t("ttl.unlimited") : `${ttl}d`}`,
|
|
1684
|
+
`${t("settings.border")}: ${onOff(signals.borderVisible())}`,
|
|
1685
|
+
`${t("settings.showEntryCost")}: ${onOff(signals.showEntryCost())}`,
|
|
1686
|
+
`${t("settings.showEntryTime")}: ${onOff(signals.showEntryTime())}`,
|
|
1687
|
+
`${t("settings.showEntryTokens")}: ${onOff(signals.showEntryTokens())}`,
|
|
1688
|
+
`${t("settings.showOrigin")}: ${onOff(signals.showOrigin())}`,
|
|
1689
|
+
`${t("settings.timeFormat")}: ${TIME_FORMAT_SAMPLES[signals.timeFormat()]}`,
|
|
1690
|
+
`${t("settings.dbSync")}: ${onOff(signals.dbSync())}`
|
|
1691
|
+
].join("\n");
|
|
1692
|
+
context.ui.toast.show({ title: t("settings.title"), message });
|
|
1693
|
+
}
|
|
1694
|
+
},
|
|
1695
|
+
{
|
|
1696
|
+
id: "opencode-subagent-magazine.subagent.sections",
|
|
1697
|
+
title: "SubAgent Magazine: Settings Menu",
|
|
1698
|
+
description: "Open the interactive settings menu (Esc to close)",
|
|
1699
|
+
slash: { name: "subagent-sections" },
|
|
1700
|
+
palette: true,
|
|
1701
|
+
run: () => {
|
|
1702
|
+
openSettingsMenu(context, api, signals);
|
|
1703
|
+
}
|
|
1704
|
+
},
|
|
1705
|
+
{
|
|
1706
|
+
id: "opencode-subagent-magazine.subagent.cost",
|
|
1707
|
+
title: "SubAgent Magazine: Toggle Entry Cost",
|
|
1708
|
+
description: "Show or hide the per-sub-agent cost in the sidebar",
|
|
1709
|
+
slash: { name: "subagent-cost" },
|
|
1710
|
+
palette: true,
|
|
1711
|
+
run: () => {
|
|
1712
|
+
const v = !signals.showEntryCost();
|
|
1713
|
+
signals.setShowEntryCost(v);
|
|
1714
|
+
kv.set(SETTING_KEYS.showEntryCost, v);
|
|
1715
|
+
api.ui.toast(`${t("settings.showEntryCost")}: ${onOff(v)}`);
|
|
1716
|
+
}
|
|
1717
|
+
},
|
|
1718
|
+
{
|
|
1719
|
+
id: "opencode-subagent-magazine.subagent.time",
|
|
1720
|
+
title: "SubAgent Magazine: Toggle Entry Time",
|
|
1721
|
+
description: "Show or hide the elapsed time in the sidebar list",
|
|
1722
|
+
slash: { name: "subagent-time" },
|
|
1723
|
+
palette: true,
|
|
1724
|
+
run: () => {
|
|
1725
|
+
const v = !signals.showEntryTime();
|
|
1726
|
+
signals.setShowEntryTime(v);
|
|
1727
|
+
kv.set(SETTING_KEYS.showEntryTime, v);
|
|
1728
|
+
api.ui.toast(`${t("settings.showEntryTime")}: ${onOff(v)}`);
|
|
1729
|
+
}
|
|
1730
|
+
},
|
|
1731
|
+
{
|
|
1732
|
+
id: "opencode-subagent-magazine.subagent.time-format",
|
|
1733
|
+
title: "SubAgent Magazine: Time Format",
|
|
1734
|
+
description: "Set how elapsed time is displayed (short / decimal / clock / compact / seconds)",
|
|
1735
|
+
slash: { name: "subagent-time-format" },
|
|
1736
|
+
palette: true,
|
|
1737
|
+
run: async () => {
|
|
1738
|
+
const picked = await context.ui.dialog.select({
|
|
1739
|
+
title: t("settings.timeFormat"),
|
|
1740
|
+
options: TIME_FORMATS.map((f) => ({ title: `${f} \u2014 ${TIME_FORMAT_SAMPLES[f]}`, value: f })),
|
|
1741
|
+
current: signals.timeFormat()
|
|
1742
|
+
});
|
|
1743
|
+
if (!picked) return;
|
|
1744
|
+
signals.setTimeFormat(picked);
|
|
1745
|
+
kv.set(SETTING_KEYS.timeFormat, picked);
|
|
1746
|
+
api.ui.toast(`${t("settings.timeFormat")}: ${TIME_FORMAT_SAMPLES[picked]}`);
|
|
1747
|
+
}
|
|
1748
|
+
},
|
|
1749
|
+
{
|
|
1750
|
+
id: "opencode-subagent-magazine.subagent.tokens",
|
|
1751
|
+
title: "SubAgent Magazine: Toggle Entry Tokens",
|
|
1752
|
+
description: "Show or hide the token count in the sidebar list",
|
|
1753
|
+
slash: { name: "subagent-tokens" },
|
|
1754
|
+
palette: true,
|
|
1755
|
+
run: () => {
|
|
1756
|
+
const v = !signals.showEntryTokens();
|
|
1757
|
+
signals.setShowEntryTokens(v);
|
|
1758
|
+
kv.set(SETTING_KEYS.showEntryTokens, v);
|
|
1759
|
+
api.ui.toast(`${t("settings.showEntryTokens")}: ${onOff(v)}`);
|
|
1760
|
+
}
|
|
1761
|
+
},
|
|
1762
|
+
{
|
|
1763
|
+
id: "opencode-subagent-magazine.subagent.origin",
|
|
1764
|
+
title: "SubAgent Magazine: Toggle Origin Indicators",
|
|
1765
|
+
description: "Show or hide origin markers (\u21E2 background / \u21B3 spawned) in the sidebar list",
|
|
1766
|
+
slash: { name: "subagent-origin" },
|
|
1767
|
+
palette: true,
|
|
1768
|
+
run: () => {
|
|
1769
|
+
const v = !signals.showOrigin();
|
|
1770
|
+
signals.setShowOrigin(v);
|
|
1771
|
+
kv.set(SETTING_KEYS.showOrigin, v);
|
|
1772
|
+
api.ui.toast(`${t("settings.showOrigin")}: ${onOff(v)}`);
|
|
1773
|
+
}
|
|
1774
|
+
},
|
|
1775
|
+
{
|
|
1776
|
+
id: "opencode-subagent-magazine.subagent.db",
|
|
1777
|
+
title: "SubAgent Magazine: Toggle Local DB",
|
|
1778
|
+
description: "Enrich sub-agent entries from the local OpenCode database (V2)",
|
|
1779
|
+
slash: { name: "subagent-db" },
|
|
1780
|
+
palette: true,
|
|
1781
|
+
run: () => {
|
|
1782
|
+
const v = !signals.dbSync();
|
|
1783
|
+
signals.setDbSync(v);
|
|
1784
|
+
kv.set(SETTING_KEYS.dbSync, v);
|
|
1785
|
+
api.ui.toast(`${t("settings.dbSync")}: ${onOff(v)}`);
|
|
1786
|
+
}
|
|
1787
|
+
},
|
|
673
1788
|
{
|
|
674
1789
|
id: "opencode-subagent-magazine.subagent.version",
|
|
675
1790
|
title: "SubAgent Magazine: Version",
|
|
@@ -712,27 +1827,43 @@ function makeCommands(context, api, signals) {
|
|
|
712
1827
|
}
|
|
713
1828
|
}
|
|
714
1829
|
if (count > 0) {
|
|
1830
|
+
const ok = () => api.ui.toast(signals.lang() === "zh" ? `\u5DF2\u6807\u8BB0 ${count} \u4E2A\u8FD0\u884C\u4E2D\u7684\u6761\u76EE\u4E3A\u5B8C\u6210` : `Marked ${count} running entries as done`);
|
|
1831
|
+
const fail = () => {
|
|
1832
|
+
try {
|
|
1833
|
+
api.ui.toast(t("clear.failed"));
|
|
1834
|
+
} catch {
|
|
1835
|
+
}
|
|
1836
|
+
};
|
|
715
1837
|
try {
|
|
716
|
-
const data = loadSessionData(kv);
|
|
717
1838
|
const { parentSid, isChild } = resolveParent(sid);
|
|
718
|
-
|
|
719
|
-
if (
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
1839
|
+
const done = updateSessionData(kv, (data) => {
|
|
1840
|
+
if (isChild) {
|
|
1841
|
+
if (!data[parentSid]) data[parentSid] = { ts: Date.now(), entries: [], scroll: 0, expanded: "", children: {} };
|
|
1842
|
+
if (!data[parentSid].children) data[parentSid].children = {};
|
|
1843
|
+
const prev = data[parentSid].children[sid]?.entries ?? [];
|
|
1844
|
+
const merged = [...mergeSubEntries(prev, entries.values()).values()].map(
|
|
1845
|
+
(e) => e.status === "running" || e.status === "cancel_requested" ? { ...e, status: "done", endedAt: e.endedAt ?? Date.now() } : e
|
|
1846
|
+
);
|
|
1847
|
+
data[parentSid].children[sid] = {
|
|
1848
|
+
...data[parentSid].children[sid] ?? { scroll: 0, expanded: "" },
|
|
1849
|
+
entries: merged
|
|
1850
|
+
};
|
|
1851
|
+
} else {
|
|
1852
|
+
const rec = data[parentSid] ?? { ts: Date.now(), entries: [], scroll: 0, expanded: "", children: {} };
|
|
1853
|
+
const merged = [...mergeSubEntries(rec.entries ?? [], entries.values()).values()].map(
|
|
1854
|
+
(e) => e.status === "running" || e.status === "cancel_requested" ? { ...e, status: "done", endedAt: e.endedAt ?? Date.now() } : e
|
|
1855
|
+
);
|
|
1856
|
+
data[parentSid] = { ...rec, ts: Date.now(), entries: merged, children: rec.children ?? {} };
|
|
1857
|
+
}
|
|
1858
|
+
});
|
|
1859
|
+
if (done && typeof done.then === "function") {
|
|
1860
|
+
void done.then(ok, fail);
|
|
723
1861
|
} else {
|
|
724
|
-
|
|
725
|
-
ts: Date.now(),
|
|
726
|
-
entries: [...entries.values()],
|
|
727
|
-
scroll: data[sid]?.scroll ?? 0,
|
|
728
|
-
expanded: data[sid]?.expanded ?? "",
|
|
729
|
-
children: data[sid]?.children ?? {}
|
|
730
|
-
};
|
|
1862
|
+
ok();
|
|
731
1863
|
}
|
|
732
|
-
saveSessionData(kv, data);
|
|
733
1864
|
} catch {
|
|
1865
|
+
fail();
|
|
734
1866
|
}
|
|
735
|
-
api.ui.toast(signals.lang() === "zh" ? `\u5DF2\u6807\u8BB0 ${count} \u4E2A\u8FD0\u884C\u4E2D\u7684\u6761\u76EE\u4E3A\u5B8C\u6210` : `Marked ${count} running entries as done`);
|
|
736
1867
|
} else {
|
|
737
1868
|
api.ui.toast(signals.lang() === "zh" ? "\u6CA1\u6709\u9700\u8981\u6E05\u7406\u7684\u8FD0\u884C\u4E2D\u6761\u76EE" : "No running entries to clear");
|
|
738
1869
|
}
|
|
@@ -789,32 +1920,45 @@ function makeCommands(context, api, signals) {
|
|
|
789
1920
|
});
|
|
790
1921
|
if (choice !== "yes") return;
|
|
791
1922
|
try {
|
|
792
|
-
const data = loadSessionData(kv);
|
|
793
1923
|
let count = 0;
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
child
|
|
802
|
-
|
|
1924
|
+
const finish = () => {
|
|
1925
|
+
globalEntryCache.delete(sid);
|
|
1926
|
+
setClearTick((v) => v + 1);
|
|
1927
|
+
api.ui.toast(t("clear.done", { n: count }));
|
|
1928
|
+
};
|
|
1929
|
+
const done = updateSessionData(kv, (data) => {
|
|
1930
|
+
if (parentID) {
|
|
1931
|
+
const child = data[parentID]?.children?.[sid];
|
|
1932
|
+
if (child) {
|
|
1933
|
+
const ids = child.entries?.map((e) => e.id) ?? [];
|
|
1934
|
+
count = ids.length;
|
|
1935
|
+
child.entries = [];
|
|
1936
|
+
child.scroll = 0;
|
|
1937
|
+
child.expanded = "";
|
|
1938
|
+
child.clearedIds = [.../* @__PURE__ */ new Set([...child.clearedIds ?? [], ...ids])];
|
|
1939
|
+
}
|
|
1940
|
+
} else {
|
|
1941
|
+
const rec = data[sid];
|
|
1942
|
+
if (rec) {
|
|
1943
|
+
const ids = rec.entries?.map((e) => e.id) ?? [];
|
|
1944
|
+
count = ids.length;
|
|
1945
|
+
rec.entries = [];
|
|
1946
|
+
rec.scroll = 0;
|
|
1947
|
+
rec.expanded = "";
|
|
1948
|
+
rec.clearedIds = [.../* @__PURE__ */ new Set([...rec.clearedIds ?? [], ...ids])];
|
|
1949
|
+
}
|
|
803
1950
|
}
|
|
1951
|
+
});
|
|
1952
|
+
if (done && typeof done.then === "function") {
|
|
1953
|
+
void done.then(finish, () => {
|
|
1954
|
+
try {
|
|
1955
|
+
api.ui.toast(t("clear.failed"));
|
|
1956
|
+
} catch {
|
|
1957
|
+
}
|
|
1958
|
+
});
|
|
804
1959
|
} else {
|
|
805
|
-
|
|
806
|
-
if (data[sid]) {
|
|
807
|
-
const ids = data[sid].entries?.map((e) => e.id) ?? [];
|
|
808
|
-
data[sid].entries = [];
|
|
809
|
-
data[sid].scroll = 0;
|
|
810
|
-
data[sid].expanded = "";
|
|
811
|
-
data[sid].clearedIds = [.../* @__PURE__ */ new Set([...data[sid].clearedIds ?? [], ...ids])];
|
|
812
|
-
}
|
|
1960
|
+
finish();
|
|
813
1961
|
}
|
|
814
|
-
saveSessionData(kv, data);
|
|
815
|
-
globalEntryCache.delete(sid);
|
|
816
|
-
setClearTick((v) => v + 1);
|
|
817
|
-
api.ui.toast(t("clear.done", { n: count }));
|
|
818
1962
|
} catch {
|
|
819
1963
|
}
|
|
820
1964
|
}
|
|
@@ -960,52 +2104,10 @@ async function copyText(text) {
|
|
|
960
2104
|
|
|
961
2105
|
// src/core/types.ts
|
|
962
2106
|
var SUBAGENT_TOOLS = /* @__PURE__ */ new Set(["task", "subagent", "delegate", "call_omo_agent"]);
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
if (code < 32) return 0;
|
|
968
|
-
if (code < 127) return 1;
|
|
969
|
-
if (code < 160) return 0;
|
|
970
|
-
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)
|
|
971
|
-
return 2;
|
|
972
|
-
return 1;
|
|
973
|
-
}
|
|
974
|
-
function visualWidth(s) {
|
|
975
|
-
let w = 0;
|
|
976
|
-
for (const c of s) w += charColumns(c);
|
|
977
|
-
return w;
|
|
978
|
-
}
|
|
979
|
-
function truncate(text, maxCols) {
|
|
980
|
-
if (visualWidth(text) <= maxCols) return text;
|
|
981
|
-
let cols = 0;
|
|
982
|
-
let i = 0;
|
|
983
|
-
for (const c of text) {
|
|
984
|
-
const w = charColumns(c);
|
|
985
|
-
if (cols + w > maxCols - 1) break;
|
|
986
|
-
cols += w;
|
|
987
|
-
i += c.length;
|
|
988
|
-
}
|
|
989
|
-
return text.slice(0, i) + "\u2026";
|
|
990
|
-
}
|
|
991
|
-
function fmtDurationShort(ms, running) {
|
|
992
|
-
if (running && ms < 2e3) return "";
|
|
993
|
-
if (ms < 1e3) return (ms / 1e3).toFixed(2) + "s";
|
|
994
|
-
if (ms < 6e4) return (ms / 1e3).toFixed(2) + "s";
|
|
995
|
-
const m = Math.floor(ms / 6e4);
|
|
996
|
-
const s = Math.round(ms % 6e4 / 1e3);
|
|
997
|
-
return `${m}m${s}s`;
|
|
998
|
-
}
|
|
999
|
-
function fmtTokens(n) {
|
|
1000
|
-
if (n < 1e3) return `${n}`;
|
|
1001
|
-
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
1002
|
-
return `${(n / 1e6).toFixed(1)}M`;
|
|
1003
|
-
}
|
|
1004
|
-
function safeErrorMsg(err) {
|
|
1005
|
-
if (!err) return "";
|
|
1006
|
-
if (typeof err === "string") return err;
|
|
1007
|
-
if (typeof err === "object") return String(err.message || err.code || "");
|
|
1008
|
-
return "";
|
|
2107
|
+
function isBackgroundInput(input) {
|
|
2108
|
+
if (!input || typeof input !== "object") return false;
|
|
2109
|
+
const i = input;
|
|
2110
|
+
return i.background === true || i.run_in_background === true;
|
|
1009
2111
|
}
|
|
1010
2112
|
|
|
1011
2113
|
// src/core/color.ts
|
|
@@ -1081,34 +2183,20 @@ function isDirectChildSession(currentSessionId, eventSessionId, eventSession) {
|
|
|
1081
2183
|
return eventSessionId !== currentSessionId && eventSession?.parentID === currentSessionId;
|
|
1082
2184
|
}
|
|
1083
2185
|
|
|
1084
|
-
// src/panel/entry-map.ts
|
|
1085
|
-
function findSubEntryKey(entries, id, sessionId) {
|
|
1086
|
-
if (sessionId) {
|
|
1087
|
-
for (const [key, entry] of entries) {
|
|
1088
|
-
if (entry.sessionId === sessionId) return key;
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
return entries.has(id) ? id : void 0;
|
|
1092
|
-
}
|
|
1093
|
-
function upsertSubEntry(entries, partial, now = Date.now()) {
|
|
1094
|
-
const key = findSubEntryKey(entries, partial.id, partial.sessionId) ?? partial.id;
|
|
1095
|
-
const existing = entries.get(key);
|
|
1096
|
-
const next = new Map(entries);
|
|
1097
|
-
if (key !== partial.id) next.delete(partial.id);
|
|
1098
|
-
const ended = partial.status === "done" || partial.status === "error" || partial.status === "cancelled";
|
|
1099
|
-
next.set(key, {
|
|
1100
|
-
...existing ?? { startedAt: now },
|
|
1101
|
-
...partial,
|
|
1102
|
-
id: existing?.id ?? partial.id,
|
|
1103
|
-
startedAt: existing?.startedAt || partial.startedAt || now,
|
|
1104
|
-
endedAt: ended ? existing?.endedAt || now : void 0
|
|
1105
|
-
});
|
|
1106
|
-
return next;
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
2186
|
// src/panel/SubAgentPanel.tsx
|
|
1110
2187
|
var LEFT_PAD = 4;
|
|
1111
2188
|
var INDENT = 2;
|
|
2189
|
+
function partMetadata(part, st) {
|
|
2190
|
+
const partMeta = part?.metadata;
|
|
2191
|
+
if (partMeta && Object.keys(partMeta).length > 0) return partMeta;
|
|
2192
|
+
const stateMeta = st?.metadata;
|
|
2193
|
+
return stateMeta && Object.keys(stateMeta).length > 0 ? stateMeta : void 0;
|
|
2194
|
+
}
|
|
2195
|
+
function validModel(model) {
|
|
2196
|
+
if (typeof model !== "string") return false;
|
|
2197
|
+
const s = model.trim();
|
|
2198
|
+
return s.length > 0 && s !== "[object Object]" && !s.startsWith("{");
|
|
2199
|
+
}
|
|
1112
2200
|
function SubAgentPanel(props) {
|
|
1113
2201
|
const t = createT(() => props.lang());
|
|
1114
2202
|
const SESSION_DATA_KEY2 = `${KV_PREFIX}.session_data`;
|
|
@@ -1123,11 +2211,32 @@ function SubAgentPanel(props) {
|
|
|
1123
2211
|
return {};
|
|
1124
2212
|
}
|
|
1125
2213
|
};
|
|
1126
|
-
const
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
2214
|
+
const mutateSessionData = (mutator) => {
|
|
2215
|
+
void Promise.resolve(updateSessionData(props.api.kv, mutator)).catch(() => {
|
|
2216
|
+
});
|
|
2217
|
+
};
|
|
2218
|
+
const ensureRootRecord = (data, sid) => {
|
|
2219
|
+
const rec = data[sid];
|
|
2220
|
+
if (rec) return rec;
|
|
2221
|
+
const created = {
|
|
2222
|
+
ts: Date.now(),
|
|
2223
|
+
entries: [],
|
|
2224
|
+
scroll: 0,
|
|
2225
|
+
expanded: "",
|
|
2226
|
+
children: {}
|
|
2227
|
+
};
|
|
2228
|
+
data[sid] = created;
|
|
2229
|
+
return created;
|
|
2230
|
+
};
|
|
2231
|
+
const ensureChildRecord = (data, parentSid, sid) => {
|
|
2232
|
+
const parent = ensureRootRecord(data, parentSid);
|
|
2233
|
+
if (!parent.children) parent.children = {};
|
|
2234
|
+
if (!parent.children[sid]) parent.children[sid] = {
|
|
2235
|
+
scroll: 0,
|
|
2236
|
+
expanded: "",
|
|
2237
|
+
entries: []
|
|
2238
|
+
};
|
|
2239
|
+
return parent.children[sid];
|
|
1131
2240
|
};
|
|
1132
2241
|
const resolveParent = (sid) => {
|
|
1133
2242
|
try {
|
|
@@ -1169,129 +2278,71 @@ function SubAgentPanel(props) {
|
|
|
1169
2278
|
clearTimeout(persistTimer);
|
|
1170
2279
|
persistTimer = setTimeout(() => {
|
|
1171
2280
|
try {
|
|
1172
|
-
|
|
2281
|
+
mutateSessionData((data) => {
|
|
2282
|
+
const {
|
|
2283
|
+
parentSid,
|
|
2284
|
+
isChild
|
|
2285
|
+
} = resolveParent(sid);
|
|
2286
|
+
if (isChild) {
|
|
2287
|
+
const parent = ensureRootRecord(data, parentSid);
|
|
2288
|
+
const child = ensureChildRecord(data, parentSid, sid);
|
|
2289
|
+
child.entries = [...mergeSubEntries(child.entries ?? [], entries2.values()).values()];
|
|
2290
|
+
parent.ts = Date.now();
|
|
2291
|
+
} else {
|
|
2292
|
+
const rec = ensureRootRecord(data, sid);
|
|
2293
|
+
rec.ts = Date.now();
|
|
2294
|
+
rec.entries = [...mergeSubEntries(rec.entries ?? [], entries2.values()).values()];
|
|
2295
|
+
}
|
|
2296
|
+
});
|
|
2297
|
+
} catch {
|
|
2298
|
+
}
|
|
2299
|
+
}, 200);
|
|
2300
|
+
};
|
|
2301
|
+
const persistScroll = (sid, scroll) => {
|
|
2302
|
+
try {
|
|
2303
|
+
mutateSessionData((data) => {
|
|
1173
2304
|
const {
|
|
1174
2305
|
parentSid,
|
|
1175
2306
|
isChild
|
|
1176
2307
|
} = resolveParent(sid);
|
|
1177
2308
|
if (isChild) {
|
|
1178
|
-
|
|
1179
|
-
ts: Date.now(),
|
|
1180
|
-
entries: [],
|
|
1181
|
-
scroll: 0,
|
|
1182
|
-
expanded: "",
|
|
1183
|
-
children: {}
|
|
1184
|
-
};
|
|
1185
|
-
if (!data[parentSid].children) data[parentSid].children = {};
|
|
1186
|
-
if (!data[parentSid].children[sid]) data[parentSid].children[sid] = {
|
|
1187
|
-
scroll: 0,
|
|
1188
|
-
expanded: "",
|
|
1189
|
-
entries: []
|
|
1190
|
-
};
|
|
1191
|
-
data[parentSid].children[sid] = {
|
|
1192
|
-
...data[parentSid].children[sid],
|
|
1193
|
-
entries: [...entries2.values()]
|
|
1194
|
-
};
|
|
2309
|
+
ensureChildRecord(data, parentSid, sid).scroll = scroll;
|
|
1195
2310
|
} else {
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
entries: [...entries2.values()],
|
|
1200
|
-
children: data[sid]?.children ?? {}
|
|
1201
|
-
};
|
|
2311
|
+
const rec = ensureRootRecord(data, sid);
|
|
2312
|
+
rec.ts = Date.now();
|
|
2313
|
+
rec.scroll = scroll;
|
|
1202
2314
|
}
|
|
1203
|
-
|
|
1204
|
-
} catch {
|
|
1205
|
-
}
|
|
1206
|
-
}, 200);
|
|
1207
|
-
};
|
|
1208
|
-
const persistScroll = (sid, scroll) => {
|
|
1209
|
-
try {
|
|
1210
|
-
const data = loadSessionData2();
|
|
1211
|
-
const {
|
|
1212
|
-
parentSid,
|
|
1213
|
-
isChild
|
|
1214
|
-
} = resolveParent(sid);
|
|
1215
|
-
if (isChild) {
|
|
1216
|
-
if (!data[parentSid]) data[parentSid] = {
|
|
1217
|
-
ts: Date.now(),
|
|
1218
|
-
entries: [],
|
|
1219
|
-
scroll: 0,
|
|
1220
|
-
expanded: "",
|
|
1221
|
-
children: {}
|
|
1222
|
-
};
|
|
1223
|
-
if (!data[parentSid].children) data[parentSid].children = {};
|
|
1224
|
-
if (!data[parentSid].children[sid]) data[parentSid].children[sid] = {
|
|
1225
|
-
scroll: 0,
|
|
1226
|
-
expanded: "",
|
|
1227
|
-
entries: []
|
|
1228
|
-
};
|
|
1229
|
-
data[parentSid].children[sid] = {
|
|
1230
|
-
...data[parentSid].children[sid],
|
|
1231
|
-
scroll
|
|
1232
|
-
};
|
|
1233
|
-
} else {
|
|
1234
|
-
data[sid] = {
|
|
1235
|
-
...data[sid],
|
|
1236
|
-
ts: Date.now(),
|
|
1237
|
-
scroll,
|
|
1238
|
-
children: data[sid]?.children ?? {}
|
|
1239
|
-
};
|
|
1240
|
-
}
|
|
1241
|
-
saveSessionData2(data);
|
|
2315
|
+
});
|
|
1242
2316
|
} catch {
|
|
1243
2317
|
}
|
|
1244
2318
|
};
|
|
1245
2319
|
const persistExpanded = (sid, expanded2) => {
|
|
1246
2320
|
try {
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
expanded
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
if (!data[parentSid].children) data[parentSid].children = {};
|
|
1261
|
-
if (!data[parentSid].children[sid]) data[parentSid].children[sid] = {
|
|
1262
|
-
scroll: 0,
|
|
1263
|
-
expanded: "",
|
|
1264
|
-
entries: []
|
|
1265
|
-
};
|
|
1266
|
-
data[parentSid].children[sid] = {
|
|
1267
|
-
...data[parentSid].children[sid],
|
|
1268
|
-
expanded: expanded2
|
|
1269
|
-
};
|
|
1270
|
-
} else {
|
|
1271
|
-
data[sid] = {
|
|
1272
|
-
...data[sid],
|
|
1273
|
-
ts: Date.now(),
|
|
1274
|
-
expanded: expanded2,
|
|
1275
|
-
children: data[sid]?.children ?? {}
|
|
1276
|
-
};
|
|
1277
|
-
}
|
|
1278
|
-
saveSessionData2(data);
|
|
2321
|
+
mutateSessionData((data) => {
|
|
2322
|
+
const {
|
|
2323
|
+
parentSid,
|
|
2324
|
+
isChild
|
|
2325
|
+
} = resolveParent(sid);
|
|
2326
|
+
if (isChild) {
|
|
2327
|
+
ensureChildRecord(data, parentSid, sid).expanded = expanded2;
|
|
2328
|
+
} else {
|
|
2329
|
+
const rec = ensureRootRecord(data, sid);
|
|
2330
|
+
rec.ts = Date.now();
|
|
2331
|
+
rec.expanded = expanded2;
|
|
2332
|
+
}
|
|
2333
|
+
});
|
|
1279
2334
|
} catch {
|
|
1280
2335
|
}
|
|
1281
2336
|
};
|
|
1282
2337
|
const cleanupOldSessions = () => {
|
|
1283
2338
|
if (ttlDays <= 0) return;
|
|
1284
2339
|
try {
|
|
1285
|
-
const data = loadSessionData2();
|
|
1286
2340
|
const cutoff = Date.now() - TTL_MS;
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
delete data[sid];
|
|
1291
|
-
changed = true;
|
|
2341
|
+
mutateSessionData((data) => {
|
|
2342
|
+
for (const sid of Object.keys(data)) {
|
|
2343
|
+
if (data[sid].ts < cutoff) delete data[sid];
|
|
1292
2344
|
}
|
|
1293
|
-
}
|
|
1294
|
-
if (changed) saveSessionData2(data);
|
|
2345
|
+
});
|
|
1295
2346
|
} catch {
|
|
1296
2347
|
}
|
|
1297
2348
|
};
|
|
@@ -1311,38 +2362,22 @@ function SubAgentPanel(props) {
|
|
|
1311
2362
|
if (needsImmediateFlush) {
|
|
1312
2363
|
clearTimeout(persistTimer);
|
|
1313
2364
|
try {
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
entries
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
expanded: "",
|
|
1331
|
-
entries: []
|
|
1332
|
-
};
|
|
1333
|
-
data[parentSid].children[props.sessionId] = {
|
|
1334
|
-
...data[parentSid].children[props.sessionId],
|
|
1335
|
-
entries: [...next.values()]
|
|
1336
|
-
};
|
|
1337
|
-
} else {
|
|
1338
|
-
data[props.sessionId] = {
|
|
1339
|
-
...data[props.sessionId],
|
|
1340
|
-
ts: Date.now(),
|
|
1341
|
-
entries: [...next.values()],
|
|
1342
|
-
children: data[props.sessionId]?.children ?? {}
|
|
1343
|
-
};
|
|
1344
|
-
}
|
|
1345
|
-
saveSessionData2(data);
|
|
2365
|
+
mutateSessionData((data) => {
|
|
2366
|
+
const {
|
|
2367
|
+
parentSid,
|
|
2368
|
+
isChild
|
|
2369
|
+
} = resolveParent(props.sessionId);
|
|
2370
|
+
if (isChild) {
|
|
2371
|
+
const parent = ensureRootRecord(data, parentSid);
|
|
2372
|
+
const child = ensureChildRecord(data, parentSid, props.sessionId);
|
|
2373
|
+
child.entries = [...mergeSubEntries(child.entries ?? [], next.values()).values()];
|
|
2374
|
+
parent.ts = Date.now();
|
|
2375
|
+
} else {
|
|
2376
|
+
const rec = ensureRootRecord(data, props.sessionId);
|
|
2377
|
+
rec.ts = Date.now();
|
|
2378
|
+
rec.entries = [...mergeSubEntries(rec.entries ?? [], next.values()).values()];
|
|
2379
|
+
}
|
|
2380
|
+
});
|
|
1346
2381
|
} catch {
|
|
1347
2382
|
}
|
|
1348
2383
|
} else {
|
|
@@ -1510,7 +2545,9 @@ function SubAgentPanel(props) {
|
|
|
1510
2545
|
const part = event.payload?.part;
|
|
1511
2546
|
if (!part) return;
|
|
1512
2547
|
const eventSid = event.payload?.sessionID !== void 0 ? String(event.payload.sessionID) : void 0;
|
|
1513
|
-
if (event.scope === "global" && eventSid !== props.sessionId)
|
|
2548
|
+
if (event.scope === "global" && eventSid !== props.sessionId) {
|
|
2549
|
+
return;
|
|
2550
|
+
}
|
|
1514
2551
|
if (part.type === "subtask") {
|
|
1515
2552
|
const agent = String(part.agent ?? "?");
|
|
1516
2553
|
const prompt = String(part.prompt ?? "");
|
|
@@ -1527,7 +2564,8 @@ function SubAgentPanel(props) {
|
|
|
1527
2564
|
prompt,
|
|
1528
2565
|
sessionId: subSid,
|
|
1529
2566
|
status: "running",
|
|
1530
|
-
model: modelId
|
|
2567
|
+
model: modelId,
|
|
2568
|
+
origin: "sub"
|
|
1531
2569
|
});
|
|
1532
2570
|
}
|
|
1533
2571
|
if (part.type === "tool") {
|
|
@@ -1539,7 +2577,7 @@ function SubAgentPanel(props) {
|
|
|
1539
2577
|
if (rawStatus === "error") {
|
|
1540
2578
|
const id2 = `tool:${String(part.id ?? "")}`;
|
|
1541
2579
|
if (!part.id) return;
|
|
1542
|
-
const stMeta2 = st
|
|
2580
|
+
const stMeta2 = partMetadata(part, st);
|
|
1543
2581
|
const errorSid = stMeta2?.session_id !== void 0 ? String(stMeta2.session_id) : stMeta2?.sessionId !== void 0 ? String(stMeta2.sessionId) : void 0;
|
|
1544
2582
|
const key = findSubEntryKey(entryMap(), id2, errorSid);
|
|
1545
2583
|
const existing = key ? entryMap().get(key) : void 0;
|
|
@@ -1550,7 +2588,9 @@ function SubAgentPanel(props) {
|
|
|
1550
2588
|
agent: existing.agent,
|
|
1551
2589
|
prompt: existing.prompt,
|
|
1552
2590
|
sessionId: existing.sessionId ?? errorSid,
|
|
1553
|
-
status: "error"
|
|
2591
|
+
status: "error",
|
|
2592
|
+
origin: "tool",
|
|
2593
|
+
background: isBackgroundInput(st?.input)
|
|
1554
2594
|
});
|
|
1555
2595
|
}
|
|
1556
2596
|
return;
|
|
@@ -1558,8 +2598,8 @@ function SubAgentPanel(props) {
|
|
|
1558
2598
|
const input = st?.input;
|
|
1559
2599
|
let status = "running";
|
|
1560
2600
|
if (rawStatus === "completed") status = "done";
|
|
1561
|
-
if ((input
|
|
1562
|
-
const stMetaCheck = st
|
|
2601
|
+
if (isBackgroundInput(input) && status === "done") {
|
|
2602
|
+
const stMetaCheck = partMetadata(part, st);
|
|
1563
2603
|
const hasChild = stMetaCheck?.session_id !== void 0 || stMetaCheck?.sessionId !== void 0;
|
|
1564
2604
|
if (hasChild) status = "running";
|
|
1565
2605
|
}
|
|
@@ -1568,7 +2608,7 @@ function SubAgentPanel(props) {
|
|
|
1568
2608
|
const desc = input?.description !== void 0 ? String(input.description) : "";
|
|
1569
2609
|
const title = desc || truncate(prompt.replace(/\n/g, " ").replace(/\s+/g, " ").trim(), 40);
|
|
1570
2610
|
const id = `tool:${String(part.id ?? crypto.randomUUID())}`;
|
|
1571
|
-
const stMeta = st
|
|
2611
|
+
const stMeta = partMetadata(part, st);
|
|
1572
2612
|
const subSid = stMeta?.session_id !== void 0 ? String(stMeta.session_id) : stMeta?.sessionId !== void 0 ? String(stMeta.sessionId) : void 0;
|
|
1573
2613
|
upsertEntry({
|
|
1574
2614
|
id,
|
|
@@ -1576,7 +2616,9 @@ function SubAgentPanel(props) {
|
|
|
1576
2616
|
agent,
|
|
1577
2617
|
prompt,
|
|
1578
2618
|
sessionId: subSid,
|
|
1579
|
-
status
|
|
2619
|
+
status,
|
|
2620
|
+
origin: "tool",
|
|
2621
|
+
background: isBackgroundInput(input)
|
|
1580
2622
|
});
|
|
1581
2623
|
}
|
|
1582
2624
|
};
|
|
@@ -1758,112 +2800,482 @@ function SubAgentPanel(props) {
|
|
|
1758
2800
|
if (!found) {
|
|
1759
2801
|
const data = loadSessionData2();
|
|
1760
2802
|
const rec = data[parentSid];
|
|
1761
|
-
if (rec?.entries) {
|
|
2803
|
+
if (rec?.entries?.length) {
|
|
1762
2804
|
const fallbackMap = new Map(rec.entries.map((e) => [e.id, e]));
|
|
1763
2805
|
found = tryMatchAndUpdate(fallbackMap, sid, status, nowTs);
|
|
1764
2806
|
if (found) {
|
|
1765
|
-
data[parentSid] = {
|
|
1766
|
-
...rec,
|
|
1767
|
-
ts: nowTs,
|
|
1768
|
-
entries: [...fallbackMap.values()]
|
|
1769
|
-
};
|
|
1770
|
-
saveSessionData2(data);
|
|
1771
2807
|
globalEntryCache.set(parentSid, fallbackMap);
|
|
2808
|
+
mutateSessionData((latest) => {
|
|
2809
|
+
const latestRec = latest[parentSid];
|
|
2810
|
+
latest[parentSid] = {
|
|
2811
|
+
...latestRec ?? rec,
|
|
2812
|
+
ts: nowTs,
|
|
2813
|
+
entries: [...mergeSubEntries(latestRec?.entries ?? [], fallbackMap.values()).values()]
|
|
2814
|
+
};
|
|
2815
|
+
});
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
if (found && parentCache) {
|
|
2820
|
+
mutateSessionData((data) => {
|
|
2821
|
+
const rec = data[parentSid];
|
|
2822
|
+
data[parentSid] = {
|
|
2823
|
+
...rec ?? {
|
|
2824
|
+
entries: [],
|
|
2825
|
+
scroll: 0,
|
|
2826
|
+
expanded: "",
|
|
2827
|
+
children: {},
|
|
2828
|
+
ts: nowTs
|
|
2829
|
+
},
|
|
2830
|
+
ts: nowTs,
|
|
2831
|
+
entries: [...mergeSubEntries(rec?.entries ?? [], parentCache.values()).values()]
|
|
2832
|
+
};
|
|
2833
|
+
});
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
} catch {
|
|
2837
|
+
}
|
|
2838
|
+
setTimeout(() => {
|
|
2839
|
+
if (disposed) return;
|
|
2840
|
+
const finalTokens = props.api.usage.readSessionTokens(sid);
|
|
2841
|
+
const finalCost = props.api.usage.readSessionCost(sid);
|
|
2842
|
+
const finalModel = props.api.usage.readSessionModel(sid);
|
|
2843
|
+
const finalTodo = props.api.usage.readSessionTodo(sid);
|
|
2844
|
+
setEntryMap((prev) => {
|
|
2845
|
+
let changed = false;
|
|
2846
|
+
const next = new Map(prev);
|
|
2847
|
+
for (const [id, entry] of next) {
|
|
2848
|
+
if (entry.sessionId !== sid) continue;
|
|
2849
|
+
const t2 = finalTokens ?? entry.tokens;
|
|
2850
|
+
const c = finalCost ?? entry.cost;
|
|
2851
|
+
const m = finalModel ?? entry.model;
|
|
2852
|
+
const tt = finalTodo?.total ?? entry.todoTotal;
|
|
2853
|
+
const td = finalTodo?.done ?? entry.todoDone;
|
|
2854
|
+
if (t2 !== entry.tokens || c !== entry.cost || m !== entry.model || tt !== entry.todoTotal || td !== entry.todoDone) {
|
|
2855
|
+
next.set(id, {
|
|
2856
|
+
...entry,
|
|
2857
|
+
tokens: t2,
|
|
2858
|
+
cost: c,
|
|
2859
|
+
model: m,
|
|
2860
|
+
todoTotal: tt,
|
|
2861
|
+
todoDone: td
|
|
2862
|
+
});
|
|
2863
|
+
changed = true;
|
|
2864
|
+
}
|
|
2865
|
+
}
|
|
2866
|
+
return changed ? next : prev;
|
|
2867
|
+
});
|
|
2868
|
+
bump();
|
|
2869
|
+
}, 150);
|
|
2870
|
+
};
|
|
2871
|
+
const bump = () => setRenderTick((v) => v + 1);
|
|
2872
|
+
const settleIdleEntries = (prev) => {
|
|
2873
|
+
let changed = false;
|
|
2874
|
+
const next = new Map(prev);
|
|
2875
|
+
for (const [id, entry] of next) {
|
|
2876
|
+
if (entry.status !== "running" && entry.status !== "cancel_requested") continue;
|
|
2877
|
+
let sid = entry.sessionId;
|
|
2878
|
+
if (!sid) {
|
|
2879
|
+
try {
|
|
2880
|
+
const callId = String(entry.id).replace(/^tool:/, "");
|
|
2881
|
+
sid = props.api.session.resolveChild?.({
|
|
2882
|
+
parentId: props.sessionId,
|
|
2883
|
+
callId,
|
|
2884
|
+
agent: entry.agent,
|
|
2885
|
+
startedAt: entry.startedAt
|
|
2886
|
+
});
|
|
2887
|
+
} catch {
|
|
2888
|
+
}
|
|
2889
|
+
if (!sid) continue;
|
|
2890
|
+
next.set(id, {
|
|
2891
|
+
...entry,
|
|
2892
|
+
sessionId: sid
|
|
2893
|
+
});
|
|
2894
|
+
changed = true;
|
|
2895
|
+
}
|
|
2896
|
+
try {
|
|
2897
|
+
const st = props.api.session.status(sid);
|
|
2898
|
+
if (!st || st.type !== "idle") continue;
|
|
2899
|
+
const tokens = props.api.usage.readSessionTokens(sid);
|
|
2900
|
+
const cost = props.api.usage.readSessionCost(sid);
|
|
2901
|
+
const finalStatus = entry.status === "cancel_requested" && entry.abortAccepted ? "cancelled" : "done";
|
|
2902
|
+
next.set(id, {
|
|
2903
|
+
...entry,
|
|
2904
|
+
sessionId: sid,
|
|
2905
|
+
status: finalStatus,
|
|
2906
|
+
endedAt: Date.now(),
|
|
2907
|
+
tokens: tokens ?? entry.tokens,
|
|
2908
|
+
cost: cost ?? entry.cost
|
|
2909
|
+
});
|
|
2910
|
+
changed = true;
|
|
2911
|
+
} catch {
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
return changed ? next : prev;
|
|
2915
|
+
};
|
|
2916
|
+
const reconcileIdleEntries = () => {
|
|
2917
|
+
try {
|
|
2918
|
+
const before = entryMap();
|
|
2919
|
+
const after = settleIdleEntries(before);
|
|
2920
|
+
if (after !== before) setEntryMap(after);
|
|
2921
|
+
} catch {
|
|
2922
|
+
}
|
|
2923
|
+
};
|
|
2924
|
+
const runSessionScan = (sid, replace) => {
|
|
2925
|
+
let msgs;
|
|
2926
|
+
try {
|
|
2927
|
+
msgs = props.api.session.messages(sid);
|
|
2928
|
+
} catch {
|
|
2929
|
+
}
|
|
2930
|
+
if (!msgs || msgs.length === 0) return false;
|
|
2931
|
+
setEntryMapRaw((prev) => {
|
|
2932
|
+
const next = replace ? new Map(globalEntryCache.get(sid) ?? loadEntries(sid)) : new Map(prev);
|
|
2933
|
+
const {
|
|
2934
|
+
parentSid: scanPSid,
|
|
2935
|
+
isChild: scanChild
|
|
2936
|
+
} = resolveParent(sid);
|
|
2937
|
+
const scanRec = loadSessionData2()[scanPSid];
|
|
2938
|
+
const clearedIds = new Set(scanChild ? scanRec?.children?.[sid]?.clearedIds : scanRec?.clearedIds);
|
|
2939
|
+
try {
|
|
2940
|
+
for (const msg of msgs) {
|
|
2941
|
+
const parts = props.api.session.part(msg.id) ?? [];
|
|
2942
|
+
for (const partRaw of parts) {
|
|
2943
|
+
const part = partRaw;
|
|
2944
|
+
if (part.type === "tool") {
|
|
2945
|
+
const tool = String(part.tool ?? "");
|
|
2946
|
+
if (!SUBAGENT_TOOLS.has(tool)) continue;
|
|
2947
|
+
const id = `tool:${String(part.id ?? "")}`;
|
|
2948
|
+
if (!part.id) continue;
|
|
2949
|
+
const st = part.state;
|
|
2950
|
+
const rawStatus = String(st?.status ?? "");
|
|
2951
|
+
const scanInput = st?.input;
|
|
2952
|
+
const scanMeta = partMetadata(part, st);
|
|
2953
|
+
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;
|
|
2954
|
+
if (!scanSubSid) {
|
|
2955
|
+
try {
|
|
2956
|
+
scanSubSid = props.api.session.resolveChild?.({
|
|
2957
|
+
parentId: sid,
|
|
2958
|
+
callId: String(part.id)
|
|
2959
|
+
});
|
|
2960
|
+
} catch {
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
2963
|
+
const existingKey = findSubEntryKey(next, id, scanSubSid);
|
|
2964
|
+
const exists = existingKey ? next.get(existingKey) : void 0;
|
|
2965
|
+
if (!exists && clearedIds.has(id)) continue;
|
|
2966
|
+
if ((rawStatus === "pending" || rawStatus === "") && !exists) continue;
|
|
2967
|
+
if (rawStatus === "error") {
|
|
2968
|
+
if (exists && exists.status === "running") {
|
|
2969
|
+
next.set(existingKey ?? id, {
|
|
2970
|
+
...exists,
|
|
2971
|
+
status: "error",
|
|
2972
|
+
endedAt: Date.now()
|
|
2973
|
+
});
|
|
2974
|
+
}
|
|
2975
|
+
continue;
|
|
2976
|
+
}
|
|
2977
|
+
const settled = exists !== void 0 && exists.status !== "running" && exists.status !== "cancel_requested";
|
|
2978
|
+
const needsRepair = settled && (exists.sessionId === void 0 || exists.tokens === void 0 || exists.cost === void 0 || !validModel(exists.model));
|
|
2979
|
+
if (settled && !needsRepair) continue;
|
|
2980
|
+
let status = "running";
|
|
2981
|
+
if (rawStatus === "completed") status = "done";
|
|
2982
|
+
if (isBackgroundInput(scanInput) && status === "done") {
|
|
2983
|
+
if (scanSubSid !== void 0) status = "running";
|
|
2984
|
+
}
|
|
2985
|
+
if (status === "done" && scanSubSid) {
|
|
2986
|
+
try {
|
|
2987
|
+
const childStatus = props.api.session.status(scanSubSid);
|
|
2988
|
+
if (childStatus && childStatus.type !== "idle") status = "running";
|
|
2989
|
+
} catch {
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
if (settled) {
|
|
2993
|
+
status = exists.status;
|
|
2994
|
+
} else if (exists && status === "running") {
|
|
2995
|
+
if (!rawStatus) {
|
|
2996
|
+
const msgTokens = msg?.tokens;
|
|
2997
|
+
if (msgTokens && (Number(msgTokens.input) > 0 || Number(msgTokens.output) > 0)) {
|
|
2998
|
+
status = "done";
|
|
2999
|
+
} else {
|
|
3000
|
+
continue;
|
|
3001
|
+
}
|
|
3002
|
+
} else {
|
|
3003
|
+
continue;
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
const agent = String(part.subagent_type ?? scanInput?.agent ?? scanInput?.subagent_type ?? tool);
|
|
3007
|
+
const prompt = String(scanInput?.prompt ?? part.description ?? "");
|
|
3008
|
+
const desc = scanInput?.description !== void 0 ? String(scanInput.description) : "";
|
|
3009
|
+
const title = desc || truncate(prompt.replace(/\n/g, " ").trim(), 40);
|
|
3010
|
+
let tokens;
|
|
3011
|
+
if (scanSubSid) tokens = props.api.usage.readSessionTokens(scanSubSid);
|
|
3012
|
+
let cost;
|
|
3013
|
+
if (scanSubSid) cost = props.api.usage.readSessionCost(scanSubSid);
|
|
3014
|
+
let model;
|
|
3015
|
+
if (scanSubSid) model = props.api.usage.readSessionModel(scanSubSid);
|
|
3016
|
+
const entryKey = existingKey ?? id;
|
|
3017
|
+
next.set(entryKey, {
|
|
3018
|
+
...exists ?? {
|
|
3019
|
+
id
|
|
3020
|
+
},
|
|
3021
|
+
title: title || exists?.title || "",
|
|
3022
|
+
agent: exists?.agent ?? agent,
|
|
3023
|
+
prompt: prompt || exists?.prompt || "",
|
|
3024
|
+
// Preserve existing values (from handleSessionEnd / KV) — scan must not overwrite
|
|
3025
|
+
tokens: exists?.tokens ?? tokens,
|
|
3026
|
+
cost: exists?.cost ?? cost,
|
|
3027
|
+
model: validModel(exists?.model) ? exists.model : model,
|
|
3028
|
+
sessionId: exists?.sessionId ?? scanSubSid,
|
|
3029
|
+
status,
|
|
3030
|
+
startedAt: exists?.startedAt || Date.now(),
|
|
3031
|
+
endedAt: exists?.endedAt ?? (status === "done" ? Date.now() : void 0),
|
|
3032
|
+
origin: "tool",
|
|
3033
|
+
background: isBackgroundInput(scanInput) || exists?.background === true
|
|
3034
|
+
});
|
|
3035
|
+
if (entryKey !== id) next.delete(id);
|
|
1772
3036
|
}
|
|
1773
3037
|
}
|
|
1774
3038
|
}
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
3039
|
+
} catch {
|
|
3040
|
+
}
|
|
3041
|
+
return next;
|
|
3042
|
+
});
|
|
3043
|
+
setEntryMapRaw((prev) => settleIdleEntries(prev));
|
|
3044
|
+
const snapshot = entryMap();
|
|
3045
|
+
if (snapshot.size > 0) {
|
|
3046
|
+
globalEntryCache.set(sid, new Map(snapshot));
|
|
3047
|
+
persistEntries(sid, snapshot);
|
|
3048
|
+
}
|
|
3049
|
+
return true;
|
|
3050
|
+
};
|
|
3051
|
+
let rescanTimer;
|
|
3052
|
+
const missingNewestToolPart = () => {
|
|
3053
|
+
try {
|
|
3054
|
+
const msgs = props.api.session.messages(props.sessionId);
|
|
3055
|
+
if (!msgs || msgs.length === 0) return false;
|
|
3056
|
+
const map = entryMap();
|
|
3057
|
+
const from = Math.max(0, msgs.length - 6);
|
|
3058
|
+
for (let i = msgs.length - 1; i >= from; i--) {
|
|
3059
|
+
const parts = props.api.session.part(msgs[i]?.id) ?? [];
|
|
3060
|
+
for (const part of parts) {
|
|
3061
|
+
if (!part || part.type !== "tool") continue;
|
|
3062
|
+
if (!SUBAGENT_TOOLS.has(String(part.tool ?? ""))) continue;
|
|
3063
|
+
const partId = String(part.id ?? "");
|
|
3064
|
+
if (!partId) continue;
|
|
3065
|
+
const st = part.state;
|
|
3066
|
+
const rawStatus = String(st?.status ?? "");
|
|
3067
|
+
if (rawStatus !== "running" && rawStatus !== "completed") continue;
|
|
3068
|
+
const id = `tool:${partId}`;
|
|
3069
|
+
const meta = partMetadata(part, st);
|
|
3070
|
+
const subSid = meta?.session_id !== void 0 ? String(meta.session_id) : meta?.sessionId !== void 0 ? String(meta.sessionId) : void 0;
|
|
3071
|
+
const key = findSubEntryKey(map, id, subSid);
|
|
3072
|
+
const entry = key ? map.get(key) : void 0;
|
|
3073
|
+
if (!entry) return true;
|
|
3074
|
+
const input = st?.input;
|
|
3075
|
+
const isBackground = isBackgroundInput(input);
|
|
3076
|
+
const stillRunning = entry.status === "running" || entry.status === "cancel_requested";
|
|
3077
|
+
if (rawStatus === "completed" && !isBackground && stillRunning) return true;
|
|
1783
3078
|
}
|
|
1784
3079
|
}
|
|
1785
3080
|
} catch {
|
|
1786
3081
|
}
|
|
1787
|
-
|
|
3082
|
+
return false;
|
|
3083
|
+
};
|
|
3084
|
+
const scheduleRescan = () => {
|
|
3085
|
+
if (disposed) return;
|
|
3086
|
+
clearTimeout(rescanTimer);
|
|
3087
|
+
rescanTimer = setTimeout(() => {
|
|
1788
3088
|
if (disposed) return;
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
setEntryMap((prev) => {
|
|
1794
|
-
let changed = false;
|
|
1795
|
-
const next = new Map(prev);
|
|
1796
|
-
for (const [id, entry] of next) {
|
|
1797
|
-
if (entry.sessionId !== sid) continue;
|
|
1798
|
-
const t2 = finalTokens ?? entry.tokens;
|
|
1799
|
-
const c = finalCost ?? entry.cost;
|
|
1800
|
-
const m = finalModel ?? entry.model;
|
|
1801
|
-
const tt = finalTodo?.total ?? entry.todoTotal;
|
|
1802
|
-
const td = finalTodo?.done ?? entry.todoDone;
|
|
1803
|
-
if (t2 !== entry.tokens || c !== entry.cost || m !== entry.model || tt !== entry.todoTotal || td !== entry.todoDone) {
|
|
1804
|
-
next.set(id, {
|
|
1805
|
-
...entry,
|
|
1806
|
-
tokens: t2,
|
|
1807
|
-
cost: c,
|
|
1808
|
-
model: m,
|
|
1809
|
-
todoTotal: tt,
|
|
1810
|
-
todoDone: td
|
|
1811
|
-
});
|
|
1812
|
-
changed = true;
|
|
1813
|
-
}
|
|
1814
|
-
}
|
|
1815
|
-
return changed ? next : prev;
|
|
3089
|
+
untrack(() => {
|
|
3090
|
+
if (!missingNewestToolPart()) return;
|
|
3091
|
+
runSessionScan(props.sessionId, false);
|
|
3092
|
+
bump();
|
|
1816
3093
|
});
|
|
1817
|
-
|
|
1818
|
-
}, 150);
|
|
3094
|
+
}, 400);
|
|
1819
3095
|
};
|
|
1820
|
-
|
|
3096
|
+
let enrichCursor = 0;
|
|
1821
3097
|
onMount(() => {
|
|
1822
3098
|
const clock = setInterval(() => {
|
|
1823
3099
|
setNow(Date.now());
|
|
1824
3100
|
bump();
|
|
1825
3101
|
}, 100);
|
|
3102
|
+
let tick = 0;
|
|
1826
3103
|
const tokenTimer = setInterval(() => {
|
|
3104
|
+
tick++;
|
|
1827
3105
|
untrack(() => {
|
|
3106
|
+
let enriched;
|
|
3107
|
+
let attempted = 0;
|
|
1828
3108
|
setEntryMapRaw((prev) => {
|
|
1829
3109
|
let changed = false;
|
|
1830
3110
|
const next = new Map(prev);
|
|
3111
|
+
if (tick % 4 === 0) {
|
|
3112
|
+
try {
|
|
3113
|
+
const children = props.api.session.listChildren?.(props.sessionId);
|
|
3114
|
+
if (children) {
|
|
3115
|
+
const linked = /* @__PURE__ */ new Set();
|
|
3116
|
+
for (const e of next.values()) if (e.sessionId) linked.add(e.sessionId);
|
|
3117
|
+
const {
|
|
3118
|
+
parentSid,
|
|
3119
|
+
isChild
|
|
3120
|
+
} = resolveParent(props.sessionId);
|
|
3121
|
+
const rec = loadSessionData2()[parentSid];
|
|
3122
|
+
const cleared = new Set(isChild ? rec?.children?.[props.sessionId]?.clearedIds : rec?.clearedIds);
|
|
3123
|
+
for (const child of children) {
|
|
3124
|
+
if (!child.id || linked.has(child.id)) continue;
|
|
3125
|
+
const id = `sub:${child.id}`;
|
|
3126
|
+
if (cleared.has(id)) continue;
|
|
3127
|
+
const finished = child.timeIdle != null && child.active !== true;
|
|
3128
|
+
const status = finished ? child.idleOutcome === "interrupted" ? "cancelled" : "done" : "running";
|
|
3129
|
+
next.set(id, {
|
|
3130
|
+
id,
|
|
3131
|
+
title: child.title ?? child.agent ?? "",
|
|
3132
|
+
agent: child.agent ?? "?",
|
|
3133
|
+
prompt: "",
|
|
3134
|
+
status,
|
|
3135
|
+
sessionId: child.id,
|
|
3136
|
+
startedAt: child.timeCreated ?? Date.now(),
|
|
3137
|
+
endedAt: finished ? child.timeIdle : void 0,
|
|
3138
|
+
tokens: child.tokens,
|
|
3139
|
+
cost: child.cost,
|
|
3140
|
+
model: child.model,
|
|
3141
|
+
origin: "sub"
|
|
3142
|
+
});
|
|
3143
|
+
changed = true;
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
} catch {
|
|
3147
|
+
}
|
|
3148
|
+
for (const [id, entry] of next) {
|
|
3149
|
+
if (entry.status !== "done" && entry.status !== "error") continue;
|
|
3150
|
+
const sid = entry.sessionId;
|
|
3151
|
+
if (!sid) continue;
|
|
3152
|
+
try {
|
|
3153
|
+
if (props.api.session.status(sid)?.type === "busy") {
|
|
3154
|
+
next.set(id, {
|
|
3155
|
+
...entry,
|
|
3156
|
+
status: "running",
|
|
3157
|
+
endedAt: void 0
|
|
3158
|
+
});
|
|
3159
|
+
changed = true;
|
|
3160
|
+
}
|
|
3161
|
+
} catch {
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3165
|
+
const candidates = [];
|
|
1831
3166
|
for (const [id, entry] of next) {
|
|
1832
|
-
|
|
3167
|
+
const running = entry.status === "running" || entry.status === "cancel_requested";
|
|
3168
|
+
const missing = entry.tokens === void 0 || entry.cost === void 0 || !validModel(entry.model);
|
|
3169
|
+
if (entry.sessionId && !running && !missing) continue;
|
|
3170
|
+
candidates.push(id);
|
|
3171
|
+
}
|
|
3172
|
+
if (candidates.length > 0) {
|
|
3173
|
+
const start = enrichCursor % candidates.length;
|
|
3174
|
+
let budget = 4;
|
|
3175
|
+
for (let k = 0; k < candidates.length && budget > 0; k++) {
|
|
3176
|
+
const id = candidates[(start + k) % candidates.length];
|
|
3177
|
+
let entry = next.get(id);
|
|
3178
|
+
if (!entry) continue;
|
|
3179
|
+
if (!entry.sessionId) {
|
|
3180
|
+
try {
|
|
3181
|
+
const callId = String(entry.id).replace(/^tool:/, "");
|
|
3182
|
+
const sid = props.api.session.resolveChild?.({
|
|
3183
|
+
parentId: props.sessionId,
|
|
3184
|
+
callId,
|
|
3185
|
+
agent: entry.agent,
|
|
3186
|
+
startedAt: entry.startedAt
|
|
3187
|
+
});
|
|
3188
|
+
if (sid) {
|
|
3189
|
+
entry = {
|
|
3190
|
+
...entry,
|
|
3191
|
+
sessionId: sid
|
|
3192
|
+
};
|
|
3193
|
+
next.set(id, entry);
|
|
3194
|
+
changed = true;
|
|
3195
|
+
}
|
|
3196
|
+
} catch {
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
if (!entry.sessionId) continue;
|
|
3200
|
+
const childSid = entry.sessionId;
|
|
1833
3201
|
let isChild = false;
|
|
1834
3202
|
try {
|
|
1835
|
-
const s = props.api.session.get(
|
|
1836
|
-
isChild = s
|
|
3203
|
+
const s = props.api.session.get(childSid);
|
|
3204
|
+
isChild = !s || s.parentID === props.sessionId;
|
|
1837
3205
|
} catch {
|
|
3206
|
+
isChild = true;
|
|
1838
3207
|
}
|
|
1839
3208
|
if (!isChild) continue;
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
const
|
|
3209
|
+
budget--;
|
|
3210
|
+
attempted++;
|
|
3211
|
+
const running = entry.status === "running" || entry.status === "cancel_requested";
|
|
3212
|
+
let entryChanged = false;
|
|
1843
3213
|
const nextEntry = {
|
|
1844
3214
|
...entry
|
|
1845
3215
|
};
|
|
1846
|
-
if (
|
|
1847
|
-
|
|
1848
|
-
|
|
3216
|
+
if (running || entry.tokens === void 0) {
|
|
3217
|
+
const total = props.api.usage.readSessionTokens(childSid);
|
|
3218
|
+
if (total !== void 0 && total !== entry.tokens) {
|
|
3219
|
+
nextEntry.tokens = total;
|
|
3220
|
+
entryChanged = true;
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3223
|
+
if (running || entry.cost === void 0) {
|
|
3224
|
+
const cost = props.api.usage.readSessionCost(childSid);
|
|
3225
|
+
if (cost !== void 0 && cost !== entry.cost) {
|
|
3226
|
+
nextEntry.cost = cost;
|
|
3227
|
+
entryChanged = true;
|
|
3228
|
+
}
|
|
1849
3229
|
}
|
|
1850
|
-
if (
|
|
1851
|
-
|
|
3230
|
+
if (running || !validModel(entry.model)) {
|
|
3231
|
+
const model = props.api.usage.readSessionModel(childSid);
|
|
3232
|
+
if (model && model !== entry.model) {
|
|
3233
|
+
nextEntry.model = model;
|
|
3234
|
+
entryChanged = true;
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
if (running) {
|
|
3238
|
+
const todo = props.api.usage.readSessionTodo(childSid);
|
|
3239
|
+
if (todo !== void 0 && (todo.total !== entry.todoTotal || todo.done !== entry.todoDone)) {
|
|
1852
3240
|
nextEntry.todoTotal = todo.total;
|
|
1853
3241
|
nextEntry.todoDone = todo.done;
|
|
1854
|
-
|
|
3242
|
+
entryChanged = true;
|
|
1855
3243
|
}
|
|
1856
3244
|
}
|
|
1857
|
-
if (
|
|
1858
|
-
|
|
3245
|
+
if (entryChanged) {
|
|
3246
|
+
next.set(id, nextEntry);
|
|
1859
3247
|
changed = true;
|
|
1860
3248
|
}
|
|
1861
|
-
if (changed) next.set(id, nextEntry);
|
|
1862
3249
|
}
|
|
3250
|
+
enrichCursor = (start + Math.max(1, attempted)) % candidates.length;
|
|
1863
3251
|
}
|
|
1864
|
-
|
|
3252
|
+
if (!changed) return prev;
|
|
3253
|
+
enriched = next;
|
|
3254
|
+
return next;
|
|
1865
3255
|
});
|
|
3256
|
+
if (enriched) {
|
|
3257
|
+
globalEntryCache.set(props.sessionId, new Map(enriched));
|
|
3258
|
+
persistEntries(props.sessionId, enriched);
|
|
3259
|
+
}
|
|
1866
3260
|
});
|
|
3261
|
+
reconcileIdleEntries();
|
|
3262
|
+
if (tick % 4 === 0) {
|
|
3263
|
+
untrack(() => {
|
|
3264
|
+
if (missingNewestToolPart()) {
|
|
3265
|
+
runSessionScan(props.sessionId, false);
|
|
3266
|
+
bump();
|
|
3267
|
+
}
|
|
3268
|
+
});
|
|
3269
|
+
}
|
|
3270
|
+
if (tick % 60 === 0) {
|
|
3271
|
+
untrack(() => {
|
|
3272
|
+
const hasRunning = entryList().some((e) => e.status === "running" || e.status === "cancel_requested");
|
|
3273
|
+
if (hasRunning) {
|
|
3274
|
+
runSessionScan(props.sessionId, false);
|
|
3275
|
+
bump();
|
|
3276
|
+
}
|
|
3277
|
+
});
|
|
3278
|
+
}
|
|
1867
3279
|
bump();
|
|
1868
3280
|
}, 500);
|
|
1869
3281
|
bump();
|
|
@@ -1871,7 +3283,10 @@ function SubAgentPanel(props) {
|
|
|
1871
3283
|
handlePartUpdated(e);
|
|
1872
3284
|
bump();
|
|
1873
3285
|
});
|
|
1874
|
-
const unsubMsg = props.api.event.on("message.updated", () =>
|
|
3286
|
+
const unsubMsg = props.api.event.on("message.updated", () => {
|
|
3287
|
+
bump();
|
|
3288
|
+
scheduleRescan();
|
|
3289
|
+
});
|
|
1875
3290
|
const unsubIdle = props.api.event.on("session.idle", (e) => {
|
|
1876
3291
|
handleSessionEnd(e, "done");
|
|
1877
3292
|
bump();
|
|
@@ -1882,6 +3297,7 @@ function SubAgentPanel(props) {
|
|
|
1882
3297
|
});
|
|
1883
3298
|
onCleanup(() => {
|
|
1884
3299
|
disposed = true;
|
|
3300
|
+
clearTimeout(rescanTimer);
|
|
1885
3301
|
clearInterval(clock);
|
|
1886
3302
|
clearInterval(tokenTimer);
|
|
1887
3303
|
unsubPart();
|
|
@@ -1899,7 +3315,9 @@ function SubAgentPanel(props) {
|
|
|
1899
3315
|
const tick = clearTick();
|
|
1900
3316
|
const forceReload = tick !== lastTick && !switched;
|
|
1901
3317
|
lastTick = tick;
|
|
1902
|
-
|
|
3318
|
+
let attempts = 0;
|
|
3319
|
+
let retryTimer;
|
|
3320
|
+
const run = () => {
|
|
1903
3321
|
untrack(() => {
|
|
1904
3322
|
if (switched) {
|
|
1905
3323
|
const {
|
|
@@ -1910,128 +3328,25 @@ function SubAgentPanel(props) {
|
|
|
1910
3328
|
const saved = isChild ? data[parentSid]?.children?.[sid]?.scroll ?? 0 : data[sid]?.scroll ?? 0;
|
|
1911
3329
|
setScrollOffset(saved);
|
|
1912
3330
|
if (!isChild && data[sid]?.entries?.length) {
|
|
1913
|
-
|
|
1914
|
-
|
|
3331
|
+
void Promise.resolve(updateSessionData(props.api.kv, (latest) => {
|
|
3332
|
+
if (latest[sid]?.entries?.length) latest[sid].ts = Date.now();
|
|
3333
|
+
})).catch(() => {
|
|
3334
|
+
});
|
|
1915
3335
|
}
|
|
1916
3336
|
}
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
} = resolveParent(sid);
|
|
1923
|
-
const scanRec = loadSessionData2()[scanPSid];
|
|
1924
|
-
const clearedIds = new Set(scanChild ? scanRec?.children?.[sid]?.clearedIds : scanRec?.clearedIds);
|
|
1925
|
-
try {
|
|
1926
|
-
const msgs = props.api.session.messages(sid);
|
|
1927
|
-
if (msgs && msgs.length) {
|
|
1928
|
-
for (const msg of msgs) {
|
|
1929
|
-
const parts = props.api.session.part(msg.id) ?? [];
|
|
1930
|
-
for (const partRaw of parts) {
|
|
1931
|
-
const part = partRaw;
|
|
1932
|
-
if (part.type === "tool") {
|
|
1933
|
-
const tool = String(part.tool ?? "");
|
|
1934
|
-
if (!SUBAGENT_TOOLS.has(tool)) continue;
|
|
1935
|
-
const id = `tool:${String(part.id ?? "")}`;
|
|
1936
|
-
if (!part.id) continue;
|
|
1937
|
-
const st = part.state;
|
|
1938
|
-
const rawStatus = String(st?.status ?? "");
|
|
1939
|
-
const scanStMeta = st?.metadata;
|
|
1940
|
-
const scanSubSid = scanStMeta?.session_id !== void 0 ? String(scanStMeta.session_id) : scanStMeta?.sessionId !== void 0 ? String(scanStMeta.sessionId) : void 0;
|
|
1941
|
-
const existingKey = findSubEntryKey(next, id, scanSubSid);
|
|
1942
|
-
const exists = existingKey ? next.get(existingKey) : void 0;
|
|
1943
|
-
if (!exists && clearedIds.has(id)) continue;
|
|
1944
|
-
if ((rawStatus === "pending" || rawStatus === "") && !exists) continue;
|
|
1945
|
-
if (rawStatus === "error") {
|
|
1946
|
-
if (exists && exists.status === "running") {
|
|
1947
|
-
next.set(existingKey ?? id, {
|
|
1948
|
-
...exists,
|
|
1949
|
-
status: "error",
|
|
1950
|
-
endedAt: Date.now()
|
|
1951
|
-
});
|
|
1952
|
-
}
|
|
1953
|
-
continue;
|
|
1954
|
-
}
|
|
1955
|
-
let status = "running";
|
|
1956
|
-
if (rawStatus === "completed") status = "done";
|
|
1957
|
-
if ((st?.input?.run_in_background === true || st?.input?.background === true) && status === "done") {
|
|
1958
|
-
const scanStMeta2 = st?.metadata;
|
|
1959
|
-
const scanHasChild = scanStMeta2?.session_id !== void 0 || scanStMeta2?.sessionId !== void 0;
|
|
1960
|
-
if (scanHasChild) status = "running";
|
|
1961
|
-
}
|
|
1962
|
-
if (exists && existingKey === id && exists.status !== "running" && exists.status !== "cancel_requested") continue;
|
|
1963
|
-
if (exists && status === "running") {
|
|
1964
|
-
if (!rawStatus) {
|
|
1965
|
-
const msgTokens = msg?.tokens;
|
|
1966
|
-
if (msgTokens && (Number(msgTokens.input) > 0 || Number(msgTokens.output) > 0)) {
|
|
1967
|
-
status = "done";
|
|
1968
|
-
} else if (Date.now() - exists.startedAt > 30 * 60 * 1e3) {
|
|
1969
|
-
status = "done";
|
|
1970
|
-
} else {
|
|
1971
|
-
continue;
|
|
1972
|
-
}
|
|
1973
|
-
} else {
|
|
1974
|
-
continue;
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
|
-
const input = st?.input;
|
|
1978
|
-
const agent = String(part.subagent_type ?? input?.agent ?? input?.subagent_type ?? tool);
|
|
1979
|
-
const prompt = String(input?.prompt ?? part.description ?? "");
|
|
1980
|
-
const desc = input?.description !== void 0 ? String(input.description) : "";
|
|
1981
|
-
const title = desc || truncate(prompt.replace(/\n/g, " ").trim(), 40);
|
|
1982
|
-
let tokens;
|
|
1983
|
-
if (scanSubSid) tokens = props.api.usage.readSessionTokens(scanSubSid);
|
|
1984
|
-
const ended = status === "done";
|
|
1985
|
-
const entryKey = existingKey ?? id;
|
|
1986
|
-
next.set(entryKey, {
|
|
1987
|
-
id: exists?.id ?? id,
|
|
1988
|
-
title,
|
|
1989
|
-
agent,
|
|
1990
|
-
prompt,
|
|
1991
|
-
// Preserve existing values (from handleSessionEnd / KV) — scan must not overwrite
|
|
1992
|
-
tokens: exists?.tokens ?? tokens,
|
|
1993
|
-
sessionId: exists?.sessionId ?? scanSubSid,
|
|
1994
|
-
status,
|
|
1995
|
-
startedAt: exists?.startedAt || Date.now(),
|
|
1996
|
-
endedAt: ended ? exists?.endedAt || Date.now() : void 0
|
|
1997
|
-
});
|
|
1998
|
-
if (entryKey !== id) next.delete(id);
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
}
|
|
2002
|
-
}
|
|
2003
|
-
} catch {
|
|
2004
|
-
}
|
|
2005
|
-
return next;
|
|
2006
|
-
});
|
|
2007
|
-
setEntryMapRaw((prev) => {
|
|
2008
|
-
let changed = false;
|
|
2009
|
-
const next = new Map(prev);
|
|
2010
|
-
for (const [id, entry] of next) {
|
|
2011
|
-
if (entry.status !== "running" && entry.status !== "cancel_requested" || !entry.sessionId) continue;
|
|
2012
|
-
try {
|
|
2013
|
-
const st = props.api.session.status(entry.sessionId);
|
|
2014
|
-
if (!st || st.type !== "idle") continue;
|
|
2015
|
-
const tokens = props.api.usage.readSessionTokens(entry.sessionId);
|
|
2016
|
-
const cost = props.api.usage.readSessionCost(entry.sessionId);
|
|
2017
|
-
const finalStatus = entry.status === "cancel_requested" && entry.abortAccepted ? "cancelled" : "done";
|
|
2018
|
-
next.set(id, {
|
|
2019
|
-
...entry,
|
|
2020
|
-
status: finalStatus,
|
|
2021
|
-
endedAt: Date.now(),
|
|
2022
|
-
tokens: tokens ?? entry.tokens,
|
|
2023
|
-
cost: cost ?? entry.cost
|
|
2024
|
-
});
|
|
2025
|
-
changed = true;
|
|
2026
|
-
} catch {
|
|
2027
|
-
}
|
|
2028
|
-
}
|
|
2029
|
-
return changed ? next : prev;
|
|
2030
|
-
});
|
|
2031
|
-
bump();
|
|
3337
|
+
const ok = runSessionScan(sid, switched || forceReload);
|
|
3338
|
+
if (!ok && attempts < 4) {
|
|
3339
|
+
attempts++;
|
|
3340
|
+
retryTimer = setTimeout(run, 400);
|
|
3341
|
+
}
|
|
2032
3342
|
});
|
|
2033
|
-
|
|
2034
|
-
|
|
3343
|
+
bump();
|
|
3344
|
+
};
|
|
3345
|
+
const t2 = setTimeout(run, 150);
|
|
3346
|
+
onCleanup(() => {
|
|
3347
|
+
clearTimeout(t2);
|
|
3348
|
+
if (retryTimer) clearTimeout(retryTimer);
|
|
3349
|
+
});
|
|
2035
3350
|
});
|
|
2036
3351
|
const pal = createMemo(() => {
|
|
2037
3352
|
const th = props.theme;
|
|
@@ -2410,17 +3725,26 @@ function SubAgentPanel(props) {
|
|
|
2410
3725
|
return "#" + [r, g, bl].map((v) => Math.max(0, Math.min(255, v)).toString(16).padStart(2, "0")).join("");
|
|
2411
3726
|
};
|
|
2412
3727
|
const timeColor = () => isActiveRunning ? pal().warning : isError ? pal().error : pal().muted;
|
|
2413
|
-
const tokenText = () => !isExpanded() && entry.tokens !== void 0 && entry.tokens > 0 ? ` ${fmtTokens(entry.tokens)}` : "";
|
|
2414
|
-
const
|
|
3728
|
+
const tokenText = () => !isExpanded() && props.showEntryTokens() && entry.tokens !== void 0 && entry.tokens > 0 ? ` ${fmtTokens(entry.tokens)}` : "";
|
|
3729
|
+
const costText = () => !isExpanded() && props.showEntryCost() && entry.cost !== void 0 && entry.cost > 0 ? ` $${entry.cost.toFixed(4)}` : "";
|
|
3730
|
+
const timeText = () => !isExpanded() && props.showEntryTime() && (elapsed() >= 2e3 || entry.endedAt !== void 0) ? fmtDuration(elapsed(), isActiveRunning, props.timeFormat()) : "";
|
|
3731
|
+
const originMark = () => {
|
|
3732
|
+
if (!props.showOrigin()) return "";
|
|
3733
|
+
if (entry.origin === "sub") return "\u21B3";
|
|
3734
|
+
return entry.background === true ? "\u21E2" : "";
|
|
3735
|
+
};
|
|
3736
|
+
const originW = () => originMark() ? 2 : 0;
|
|
2415
3737
|
const suffixW = () => {
|
|
2416
3738
|
let w = 0;
|
|
2417
3739
|
const t2 = timeText();
|
|
2418
3740
|
if (t2) w += 1 + visualWidth(t2);
|
|
2419
3741
|
const tk = tokenText();
|
|
2420
3742
|
if (tk) w += visualWidth(tk);
|
|
3743
|
+
const c = costText();
|
|
3744
|
+
if (c) w += visualWidth(c);
|
|
2421
3745
|
return w;
|
|
2422
3746
|
};
|
|
2423
|
-
const labelAvail = () => Math.max(6, panelWidth() - gutter() - LEFT_PAD - suffixW());
|
|
3747
|
+
const labelAvail = () => Math.max(6, panelWidth() - gutter() - LEFT_PAD - originW() - suffixW());
|
|
2424
3748
|
const labelText = () => {
|
|
2425
3749
|
const max2 = labelAvail();
|
|
2426
3750
|
const text = entry.title || entry.agent;
|
|
@@ -2438,27 +3762,49 @@ function SubAgentPanel(props) {
|
|
|
2438
3762
|
_$setProp(_el$25, "onMouseUp", () => toggleExpand(entry.id));
|
|
2439
3763
|
_$insert(_el$26, () => isExpanded() ? "\u25BC" : "\u25B6");
|
|
2440
3764
|
_$insert(_el$28, statusDot);
|
|
3765
|
+
_$insert(_el$25, (() => {
|
|
3766
|
+
var _c$2 = _$memo(() => !!originMark());
|
|
3767
|
+
return () => _c$2() ? (() => {
|
|
3768
|
+
var _el$88 = _$createElement("span");
|
|
3769
|
+
_$insert(_el$88, () => originMark() + " ");
|
|
3770
|
+
_$effect((_$p) => _$setProp(_el$88, "style", {
|
|
3771
|
+
fg: pal().muted
|
|
3772
|
+
}, _$p));
|
|
3773
|
+
return _el$88;
|
|
3774
|
+
})() : null;
|
|
3775
|
+
})(), _el$30);
|
|
2441
3776
|
_$insert(_el$30, labelText);
|
|
2442
3777
|
_$insert(_el$25, (() => {
|
|
2443
|
-
var _c$
|
|
2444
|
-
return () => _c$
|
|
2445
|
-
var _el$
|
|
2446
|
-
_$insert(_el$
|
|
2447
|
-
_$effect((_$p) => _$setProp(_el$
|
|
3778
|
+
var _c$3 = _$memo(() => !!timeText());
|
|
3779
|
+
return () => _c$3() ? [" ", (() => {
|
|
3780
|
+
var _el$89 = _$createElement("span");
|
|
3781
|
+
_$insert(_el$89, timeText);
|
|
3782
|
+
_$effect((_$p) => _$setProp(_el$89, "style", {
|
|
2448
3783
|
fg: timeColor()
|
|
2449
3784
|
}, _$p));
|
|
2450
|
-
return _el$
|
|
3785
|
+
return _el$89;
|
|
2451
3786
|
})()] : null;
|
|
2452
3787
|
})(), null);
|
|
2453
3788
|
_$insert(_el$25, (() => {
|
|
2454
|
-
var _c$
|
|
2455
|
-
return () => _c$
|
|
2456
|
-
var _el$
|
|
2457
|
-
_$insert(_el$
|
|
2458
|
-
_$effect((_$p) => _$setProp(_el$
|
|
3789
|
+
var _c$4 = _$memo(() => !!tokenText());
|
|
3790
|
+
return () => _c$4() ? (() => {
|
|
3791
|
+
var _el$90 = _$createElement("span");
|
|
3792
|
+
_$insert(_el$90, tokenText);
|
|
3793
|
+
_$effect((_$p) => _$setProp(_el$90, "style", {
|
|
2459
3794
|
fg: pal().muted
|
|
2460
3795
|
}, _$p));
|
|
2461
|
-
return _el$
|
|
3796
|
+
return _el$90;
|
|
3797
|
+
})() : null;
|
|
3798
|
+
})(), null);
|
|
3799
|
+
_$insert(_el$25, (() => {
|
|
3800
|
+
var _c$5 = _$memo(() => !!costText());
|
|
3801
|
+
return () => _c$5() ? (() => {
|
|
3802
|
+
var _el$91 = _$createElement("span");
|
|
3803
|
+
_$insert(_el$91, costText);
|
|
3804
|
+
_$effect((_$p) => _$setProp(_el$91, "style", {
|
|
3805
|
+
fg: pal().warning
|
|
3806
|
+
}, _$p));
|
|
3807
|
+
return _el$91;
|
|
2462
3808
|
})() : null;
|
|
2463
3809
|
})(), null);
|
|
2464
3810
|
_$effect((_p$) => {
|
|
@@ -2512,70 +3858,77 @@ function SubAgentPanel(props) {
|
|
|
2512
3858
|
a: void 0
|
|
2513
3859
|
});
|
|
2514
3860
|
return _el$31;
|
|
2515
|
-
})(), (() => {
|
|
2516
|
-
var _el$37 = _$createElement("text"), _el$38 = _$createTextNode(` `), _el$39 = _$createElement("span"), _el$40 = _$createTextNode(`: `), _el$41 = _$createElement("span"), _el$42 = _$createElement("span");
|
|
2517
|
-
_$insertNode(_el$37, _el$38);
|
|
2518
|
-
_$insertNode(_el$37, _el$39);
|
|
2519
|
-
_$insertNode(_el$37, _el$41);
|
|
2520
|
-
_$insertNode(_el$37, _el$42);
|
|
2521
|
-
_$insertNode(_el$39, _el$40);
|
|
2522
|
-
_$insert(_el$39, () => t("status.label"), _el$40);
|
|
2523
|
-
_$insert(_el$41, () => " ".repeat(expandedPad(t("status.label"))));
|
|
2524
|
-
_$insert(_el$42, () => isActiveRunning ? t("status.running") : isCancelled ? t("status.cancelled") : isError ? t("status.error") : t("status.done"));
|
|
2525
|
-
_$effect((_p$) => {
|
|
2526
|
-
var _v$9 = {
|
|
2527
|
-
fg: pal().primary
|
|
2528
|
-
}, _v$0 = {
|
|
2529
|
-
fg: pal().muted
|
|
2530
|
-
}, _v$1 = {
|
|
2531
|
-
fg: isActiveRunning ? pal().warning : isCancelled ? pal().muted : isError ? pal().error : pal().success
|
|
2532
|
-
};
|
|
2533
|
-
_v$9 !== _p$.e && (_p$.e = _$setProp(_el$39, "style", _v$9, _p$.e));
|
|
2534
|
-
_v$0 !== _p$.t && (_p$.t = _$setProp(_el$41, "style", _v$0, _p$.t));
|
|
2535
|
-
_v$1 !== _p$.a && (_p$.a = _$setProp(_el$42, "style", _v$1, _p$.a));
|
|
2536
|
-
return _p$;
|
|
2537
|
-
}, {
|
|
2538
|
-
e: void 0,
|
|
2539
|
-
t: void 0,
|
|
2540
|
-
a: void 0
|
|
2541
|
-
});
|
|
2542
|
-
return _el$37;
|
|
2543
3861
|
})(), _$createComponent(Show, {
|
|
2544
3862
|
get when() {
|
|
2545
|
-
return
|
|
3863
|
+
return props.showOrigin();
|
|
2546
3864
|
},
|
|
2547
3865
|
get children() {
|
|
2548
|
-
var _el$
|
|
2549
|
-
_$insertNode(_el$
|
|
2550
|
-
_$insertNode(_el$
|
|
2551
|
-
_$insertNode(_el$
|
|
2552
|
-
_$insertNode(_el$
|
|
2553
|
-
_$insertNode(_el$
|
|
2554
|
-
_$insert(_el$
|
|
2555
|
-
_$insert(_el$
|
|
2556
|
-
_$insert(_el$
|
|
3866
|
+
var _el$37 = _$createElement("text"), _el$38 = _$createTextNode(` `), _el$39 = _$createElement("span"), _el$40 = _$createTextNode(`: `), _el$41 = _$createElement("span"), _el$42 = _$createElement("span");
|
|
3867
|
+
_$insertNode(_el$37, _el$38);
|
|
3868
|
+
_$insertNode(_el$37, _el$39);
|
|
3869
|
+
_$insertNode(_el$37, _el$41);
|
|
3870
|
+
_$insertNode(_el$37, _el$42);
|
|
3871
|
+
_$insertNode(_el$39, _el$40);
|
|
3872
|
+
_$insert(_el$39, () => t("origin.label"), _el$40);
|
|
3873
|
+
_$insert(_el$41, () => " ".repeat(expandedPad(t("origin.label"))));
|
|
3874
|
+
_$insert(_el$42, (() => {
|
|
3875
|
+
var _c$6 = _$memo(() => entry.origin === "sub");
|
|
3876
|
+
return () => _c$6() ? t("origin.sub") : t("origin.tool");
|
|
3877
|
+
})(), null);
|
|
3878
|
+
_$insert(_el$42, (() => {
|
|
3879
|
+
var _c$7 = _$memo(() => entry.background === true);
|
|
3880
|
+
return () => _c$7() ? ` (${t("origin.background")})` : "";
|
|
3881
|
+
})(), null);
|
|
2557
3882
|
_$effect((_p$) => {
|
|
2558
|
-
var _v$
|
|
3883
|
+
var _v$9 = {
|
|
2559
3884
|
fg: pal().primary
|
|
2560
|
-
}, _v$
|
|
3885
|
+
}, _v$0 = {
|
|
2561
3886
|
fg: pal().muted
|
|
2562
|
-
}, _v$
|
|
3887
|
+
}, _v$1 = {
|
|
2563
3888
|
fg: pal().muted
|
|
2564
3889
|
};
|
|
2565
|
-
_v$
|
|
2566
|
-
_v$
|
|
2567
|
-
_v$
|
|
3890
|
+
_v$9 !== _p$.e && (_p$.e = _$setProp(_el$39, "style", _v$9, _p$.e));
|
|
3891
|
+
_v$0 !== _p$.t && (_p$.t = _$setProp(_el$41, "style", _v$0, _p$.t));
|
|
3892
|
+
_v$1 !== _p$.a && (_p$.a = _$setProp(_el$42, "style", _v$1, _p$.a));
|
|
2568
3893
|
return _p$;
|
|
2569
3894
|
}, {
|
|
2570
3895
|
e: void 0,
|
|
2571
3896
|
t: void 0,
|
|
2572
3897
|
a: void 0
|
|
2573
3898
|
});
|
|
2574
|
-
return _el$
|
|
3899
|
+
return _el$37;
|
|
2575
3900
|
}
|
|
2576
|
-
}),
|
|
3901
|
+
}), (() => {
|
|
3902
|
+
var _el$43 = _$createElement("text"), _el$44 = _$createTextNode(` `), _el$45 = _$createElement("span"), _el$46 = _$createTextNode(`: `), _el$47 = _$createElement("span"), _el$48 = _$createElement("span");
|
|
3903
|
+
_$insertNode(_el$43, _el$44);
|
|
3904
|
+
_$insertNode(_el$43, _el$45);
|
|
3905
|
+
_$insertNode(_el$43, _el$47);
|
|
3906
|
+
_$insertNode(_el$43, _el$48);
|
|
3907
|
+
_$insertNode(_el$45, _el$46);
|
|
3908
|
+
_$insert(_el$45, () => t("status.label"), _el$46);
|
|
3909
|
+
_$insert(_el$47, () => " ".repeat(expandedPad(t("status.label"))));
|
|
3910
|
+
_$insert(_el$48, () => isActiveRunning ? t("status.running") : isCancelled ? t("status.cancelled") : isError ? t("status.error") : t("status.done"));
|
|
3911
|
+
_$effect((_p$) => {
|
|
3912
|
+
var _v$10 = {
|
|
3913
|
+
fg: pal().primary
|
|
3914
|
+
}, _v$11 = {
|
|
3915
|
+
fg: pal().muted
|
|
3916
|
+
}, _v$12 = {
|
|
3917
|
+
fg: isActiveRunning ? pal().warning : isCancelled ? pal().muted : isError ? pal().error : pal().success
|
|
3918
|
+
};
|
|
3919
|
+
_v$10 !== _p$.e && (_p$.e = _$setProp(_el$45, "style", _v$10, _p$.e));
|
|
3920
|
+
_v$11 !== _p$.t && (_p$.t = _$setProp(_el$47, "style", _v$11, _p$.t));
|
|
3921
|
+
_v$12 !== _p$.a && (_p$.a = _$setProp(_el$48, "style", _v$12, _p$.a));
|
|
3922
|
+
return _p$;
|
|
3923
|
+
}, {
|
|
3924
|
+
e: void 0,
|
|
3925
|
+
t: void 0,
|
|
3926
|
+
a: void 0
|
|
3927
|
+
});
|
|
3928
|
+
return _el$43;
|
|
3929
|
+
})(), _$createComponent(Show, {
|
|
2577
3930
|
get when() {
|
|
2578
|
-
return entry.
|
|
3931
|
+
return elapsed() >= 2e3 || entry.endedAt !== void 0;
|
|
2579
3932
|
},
|
|
2580
3933
|
get children() {
|
|
2581
3934
|
var _el$49 = _$createElement("text"), _el$50 = _$createTextNode(` `), _el$51 = _$createElement("span"), _el$52 = _$createTextNode(`: `), _el$53 = _$createElement("span"), _el$54 = _$createElement("span");
|
|
@@ -2584,9 +3937,9 @@ function SubAgentPanel(props) {
|
|
|
2584
3937
|
_$insertNode(_el$49, _el$53);
|
|
2585
3938
|
_$insertNode(_el$49, _el$54);
|
|
2586
3939
|
_$insertNode(_el$51, _el$52);
|
|
2587
|
-
_$insert(_el$51, () => t("
|
|
2588
|
-
_$insert(_el$53, () => " ".repeat(expandedPad(t("
|
|
2589
|
-
_$insert(_el$54, () =>
|
|
3940
|
+
_$insert(_el$51, () => t("time.label"), _el$52);
|
|
3941
|
+
_$insert(_el$53, () => " ".repeat(expandedPad(t("time.label"))));
|
|
3942
|
+
_$insert(_el$54, () => fmtDuration(elapsed(), isActiveRunning, props.timeFormat()));
|
|
2590
3943
|
_$effect((_p$) => {
|
|
2591
3944
|
var _v$13 = {
|
|
2592
3945
|
fg: pal().primary
|
|
@@ -2608,7 +3961,7 @@ function SubAgentPanel(props) {
|
|
|
2608
3961
|
}
|
|
2609
3962
|
}), _$createComponent(Show, {
|
|
2610
3963
|
get when() {
|
|
2611
|
-
return entry.
|
|
3964
|
+
return entry.tokens !== void 0;
|
|
2612
3965
|
},
|
|
2613
3966
|
get children() {
|
|
2614
3967
|
var _el$55 = _$createElement("text"), _el$56 = _$createTextNode(` `), _el$57 = _$createElement("span"), _el$58 = _$createTextNode(`: `), _el$59 = _$createElement("span"), _el$60 = _$createElement("span");
|
|
@@ -2617,16 +3970,16 @@ function SubAgentPanel(props) {
|
|
|
2617
3970
|
_$insertNode(_el$55, _el$59);
|
|
2618
3971
|
_$insertNode(_el$55, _el$60);
|
|
2619
3972
|
_$insertNode(_el$57, _el$58);
|
|
2620
|
-
_$insert(_el$57, () => t("
|
|
2621
|
-
_$insert(_el$59, () => " ".repeat(expandedPad(t("
|
|
2622
|
-
_$insert(_el$60, () =>
|
|
3973
|
+
_$insert(_el$57, () => t("tokens.label"), _el$58);
|
|
3974
|
+
_$insert(_el$59, () => " ".repeat(expandedPad(t("tokens.label"))));
|
|
3975
|
+
_$insert(_el$60, () => fmtTokens(entry.tokens));
|
|
2623
3976
|
_$effect((_p$) => {
|
|
2624
3977
|
var _v$16 = {
|
|
2625
|
-
fg: pal().
|
|
3978
|
+
fg: pal().primary
|
|
2626
3979
|
}, _v$17 = {
|
|
2627
3980
|
fg: pal().muted
|
|
2628
3981
|
}, _v$18 = {
|
|
2629
|
-
fg: pal().
|
|
3982
|
+
fg: pal().muted
|
|
2630
3983
|
};
|
|
2631
3984
|
_v$16 !== _p$.e && (_p$.e = _$setProp(_el$57, "style", _v$16, _p$.e));
|
|
2632
3985
|
_v$17 !== _p$.t && (_p$.t = _$setProp(_el$59, "style", _v$17, _p$.t));
|
|
@@ -2641,46 +3994,7 @@ function SubAgentPanel(props) {
|
|
|
2641
3994
|
}
|
|
2642
3995
|
}), _$createComponent(Show, {
|
|
2643
3996
|
get when() {
|
|
2644
|
-
return entry.
|
|
2645
|
-
},
|
|
2646
|
-
get children() {
|
|
2647
|
-
return (() => {
|
|
2648
|
-
const cost = entry.cost;
|
|
2649
|
-
return (() => {
|
|
2650
|
-
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(`$`);
|
|
2651
|
-
_$insertNode(_el$84, _el$85);
|
|
2652
|
-
_$insertNode(_el$84, _el$86);
|
|
2653
|
-
_$insertNode(_el$84, _el$88);
|
|
2654
|
-
_$insertNode(_el$84, _el$89);
|
|
2655
|
-
_$insertNode(_el$86, _el$87);
|
|
2656
|
-
_$insert(_el$86, () => t("cost.label"), _el$87);
|
|
2657
|
-
_$insert(_el$88, () => " ".repeat(expandedPad(t("cost.label"))));
|
|
2658
|
-
_$insertNode(_el$89, _el$90);
|
|
2659
|
-
_$insert(_el$89, () => cost.toFixed(4), null);
|
|
2660
|
-
_$effect((_p$) => {
|
|
2661
|
-
var _v$29 = {
|
|
2662
|
-
fg: pal().primary
|
|
2663
|
-
}, _v$30 = {
|
|
2664
|
-
fg: pal().muted
|
|
2665
|
-
}, _v$31 = {
|
|
2666
|
-
fg: pal().muted
|
|
2667
|
-
};
|
|
2668
|
-
_v$29 !== _p$.e && (_p$.e = _$setProp(_el$86, "style", _v$29, _p$.e));
|
|
2669
|
-
_v$30 !== _p$.t && (_p$.t = _$setProp(_el$88, "style", _v$30, _p$.t));
|
|
2670
|
-
_v$31 !== _p$.a && (_p$.a = _$setProp(_el$89, "style", _v$31, _p$.a));
|
|
2671
|
-
return _p$;
|
|
2672
|
-
}, {
|
|
2673
|
-
e: void 0,
|
|
2674
|
-
t: void 0,
|
|
2675
|
-
a: void 0
|
|
2676
|
-
});
|
|
2677
|
-
return _el$84;
|
|
2678
|
-
})();
|
|
2679
|
-
})();
|
|
2680
|
-
}
|
|
2681
|
-
}), _$createComponent(Show, {
|
|
2682
|
-
get when() {
|
|
2683
|
-
return entry.model;
|
|
3997
|
+
return entry.error;
|
|
2684
3998
|
},
|
|
2685
3999
|
get children() {
|
|
2686
4000
|
var _el$61 = _$createElement("text"), _el$62 = _$createTextNode(` `), _el$63 = _$createElement("span"), _el$64 = _$createTextNode(`: `), _el$65 = _$createElement("span"), _el$66 = _$createElement("span");
|
|
@@ -2689,16 +4003,16 @@ function SubAgentPanel(props) {
|
|
|
2689
4003
|
_$insertNode(_el$61, _el$65);
|
|
2690
4004
|
_$insertNode(_el$61, _el$66);
|
|
2691
4005
|
_$insertNode(_el$63, _el$64);
|
|
2692
|
-
_$insert(_el$63, () => t("
|
|
2693
|
-
_$insert(_el$65, () => " ".repeat(expandedPad(t("
|
|
2694
|
-
_$insert(_el$66, () => truncate(entry.
|
|
4006
|
+
_$insert(_el$63, () => t("error.label"), _el$64);
|
|
4007
|
+
_$insert(_el$65, () => " ".repeat(expandedPad(t("error.label"))));
|
|
4008
|
+
_$insert(_el$66, () => truncate(String(entry.error), expandedValAvail()));
|
|
2695
4009
|
_$effect((_p$) => {
|
|
2696
4010
|
var _v$19 = {
|
|
2697
|
-
fg: pal().
|
|
4011
|
+
fg: pal().error
|
|
2698
4012
|
}, _v$20 = {
|
|
2699
4013
|
fg: pal().muted
|
|
2700
4014
|
}, _v$21 = {
|
|
2701
|
-
fg: pal().
|
|
4015
|
+
fg: pal().error
|
|
2702
4016
|
};
|
|
2703
4017
|
_v$19 !== _p$.e && (_p$.e = _$setProp(_el$63, "style", _v$19, _p$.e));
|
|
2704
4018
|
_v$20 !== _p$.t && (_p$.t = _$setProp(_el$65, "style", _v$20, _p$.t));
|
|
@@ -2713,20 +4027,57 @@ function SubAgentPanel(props) {
|
|
|
2713
4027
|
}
|
|
2714
4028
|
}), _$createComponent(Show, {
|
|
2715
4029
|
get when() {
|
|
2716
|
-
return entry.
|
|
4030
|
+
return entry.cost !== void 0;
|
|
4031
|
+
},
|
|
4032
|
+
get children() {
|
|
4033
|
+
return (() => {
|
|
4034
|
+
const cost = entry.cost;
|
|
4035
|
+
return (() => {
|
|
4036
|
+
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(`$`);
|
|
4037
|
+
_$insertNode(_el$92, _el$93);
|
|
4038
|
+
_$insertNode(_el$92, _el$94);
|
|
4039
|
+
_$insertNode(_el$92, _el$96);
|
|
4040
|
+
_$insertNode(_el$92, _el$97);
|
|
4041
|
+
_$insertNode(_el$94, _el$95);
|
|
4042
|
+
_$insert(_el$94, () => t("cost.label"), _el$95);
|
|
4043
|
+
_$insert(_el$96, () => " ".repeat(expandedPad(t("cost.label"))));
|
|
4044
|
+
_$insertNode(_el$97, _el$98);
|
|
4045
|
+
_$insert(_el$97, () => cost.toFixed(4), null);
|
|
4046
|
+
_$effect((_p$) => {
|
|
4047
|
+
var _v$32 = {
|
|
4048
|
+
fg: pal().primary
|
|
4049
|
+
}, _v$33 = {
|
|
4050
|
+
fg: pal().muted
|
|
4051
|
+
}, _v$34 = {
|
|
4052
|
+
fg: pal().muted
|
|
4053
|
+
};
|
|
4054
|
+
_v$32 !== _p$.e && (_p$.e = _$setProp(_el$94, "style", _v$32, _p$.e));
|
|
4055
|
+
_v$33 !== _p$.t && (_p$.t = _$setProp(_el$96, "style", _v$33, _p$.t));
|
|
4056
|
+
_v$34 !== _p$.a && (_p$.a = _$setProp(_el$97, "style", _v$34, _p$.a));
|
|
4057
|
+
return _p$;
|
|
4058
|
+
}, {
|
|
4059
|
+
e: void 0,
|
|
4060
|
+
t: void 0,
|
|
4061
|
+
a: void 0
|
|
4062
|
+
});
|
|
4063
|
+
return _el$92;
|
|
4064
|
+
})();
|
|
4065
|
+
})();
|
|
4066
|
+
}
|
|
4067
|
+
}), _$createComponent(Show, {
|
|
4068
|
+
get when() {
|
|
4069
|
+
return _$memo(() => !!validModel(entry.model))() ? entry.model : void 0;
|
|
2717
4070
|
},
|
|
2718
4071
|
get children() {
|
|
2719
|
-
var _el$67 = _$createElement("text"), _el$68 = _$createTextNode(` `), _el$69 = _$createElement("span"), _el$70 = _$createTextNode(`: `), _el$71 = _$createElement("span"), _el$72 = _$createElement("span")
|
|
4072
|
+
var _el$67 = _$createElement("text"), _el$68 = _$createTextNode(` `), _el$69 = _$createElement("span"), _el$70 = _$createTextNode(`: `), _el$71 = _$createElement("span"), _el$72 = _$createElement("span");
|
|
2720
4073
|
_$insertNode(_el$67, _el$68);
|
|
2721
4074
|
_$insertNode(_el$67, _el$69);
|
|
2722
4075
|
_$insertNode(_el$67, _el$71);
|
|
2723
4076
|
_$insertNode(_el$67, _el$72);
|
|
2724
4077
|
_$insertNode(_el$69, _el$70);
|
|
2725
|
-
_$insert(_el$69, () => t("
|
|
2726
|
-
_$insert(_el$71, () => " ".repeat(expandedPad(t("
|
|
2727
|
-
_$
|
|
2728
|
-
_$insert(_el$72, () => entry.todoDone, _el$73);
|
|
2729
|
-
_$insert(_el$72, () => entry.todoTotal, null);
|
|
4078
|
+
_$insert(_el$69, () => t("model.label"), _el$70);
|
|
4079
|
+
_$insert(_el$71, () => " ".repeat(expandedPad(t("model.label"))));
|
|
4080
|
+
_$insert(_el$72, () => truncate(entry.model, expandedValAvail()));
|
|
2730
4081
|
_$effect((_p$) => {
|
|
2731
4082
|
var _v$22 = {
|
|
2732
4083
|
fg: pal().primary
|
|
@@ -2746,18 +4097,53 @@ function SubAgentPanel(props) {
|
|
|
2746
4097
|
});
|
|
2747
4098
|
return _el$67;
|
|
2748
4099
|
}
|
|
4100
|
+
}), _$createComponent(Show, {
|
|
4101
|
+
get when() {
|
|
4102
|
+
return entry.todoTotal !== void 0;
|
|
4103
|
+
},
|
|
4104
|
+
get children() {
|
|
4105
|
+
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(`/`);
|
|
4106
|
+
_$insertNode(_el$73, _el$74);
|
|
4107
|
+
_$insertNode(_el$73, _el$75);
|
|
4108
|
+
_$insertNode(_el$73, _el$77);
|
|
4109
|
+
_$insertNode(_el$73, _el$78);
|
|
4110
|
+
_$insertNode(_el$75, _el$76);
|
|
4111
|
+
_$insert(_el$75, () => t("todo.label"), _el$76);
|
|
4112
|
+
_$insert(_el$77, () => " ".repeat(expandedPad(t("todo.label"))));
|
|
4113
|
+
_$insertNode(_el$78, _el$79);
|
|
4114
|
+
_$insert(_el$78, () => entry.todoDone, _el$79);
|
|
4115
|
+
_$insert(_el$78, () => entry.todoTotal, null);
|
|
4116
|
+
_$effect((_p$) => {
|
|
4117
|
+
var _v$25 = {
|
|
4118
|
+
fg: pal().primary
|
|
4119
|
+
}, _v$26 = {
|
|
4120
|
+
fg: pal().muted
|
|
4121
|
+
}, _v$27 = {
|
|
4122
|
+
fg: pal().muted
|
|
4123
|
+
};
|
|
4124
|
+
_v$25 !== _p$.e && (_p$.e = _$setProp(_el$75, "style", _v$25, _p$.e));
|
|
4125
|
+
_v$26 !== _p$.t && (_p$.t = _$setProp(_el$77, "style", _v$26, _p$.t));
|
|
4126
|
+
_v$27 !== _p$.a && (_p$.a = _$setProp(_el$78, "style", _v$27, _p$.a));
|
|
4127
|
+
return _p$;
|
|
4128
|
+
}, {
|
|
4129
|
+
e: void 0,
|
|
4130
|
+
t: void 0,
|
|
4131
|
+
a: void 0
|
|
4132
|
+
});
|
|
4133
|
+
return _el$73;
|
|
4134
|
+
}
|
|
2749
4135
|
}), _$createComponent(Show, {
|
|
2750
4136
|
get when() {
|
|
2751
4137
|
return entry.sessionId;
|
|
2752
4138
|
},
|
|
2753
4139
|
get children() {
|
|
2754
|
-
var _el$
|
|
2755
|
-
_$insertNode(_el$
|
|
2756
|
-
_$insertNode(_el$
|
|
2757
|
-
_$insertNode(_el$
|
|
2758
|
-
_$insertNode(_el$
|
|
2759
|
-
_$insertNode(_el$
|
|
2760
|
-
_$setProp(_el$
|
|
4140
|
+
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");
|
|
4141
|
+
_$insertNode(_el$80, _el$81);
|
|
4142
|
+
_$insertNode(_el$80, _el$82);
|
|
4143
|
+
_$insertNode(_el$80, _el$84);
|
|
4144
|
+
_$insertNode(_el$80, _el$85);
|
|
4145
|
+
_$insertNode(_el$80, _el$86);
|
|
4146
|
+
_$setProp(_el$80, "onMouseUp", async () => {
|
|
2761
4147
|
const sessionId = entry.sessionId;
|
|
2762
4148
|
if (!sessionId) return;
|
|
2763
4149
|
const result = await copyText(sessionId);
|
|
@@ -2777,25 +4163,25 @@ ${t("session.toast.copy_failed")}`, {
|
|
|
2777
4163
|
duration: 8e3
|
|
2778
4164
|
});
|
|
2779
4165
|
});
|
|
2780
|
-
_$insertNode(_el$
|
|
2781
|
-
_$insert(_el$
|
|
2782
|
-
_$insert(_el$
|
|
2783
|
-
_$insert(_el$
|
|
2784
|
-
_$insertNode(_el$
|
|
4166
|
+
_$insertNode(_el$82, _el$83);
|
|
4167
|
+
_$insert(_el$82, () => t("session.label"), _el$83);
|
|
4168
|
+
_$insert(_el$84, () => " ".repeat(expandedPad(t("session.label"))));
|
|
4169
|
+
_$insert(_el$85, () => truncate(entry.sessionId, expandedValAvail() - visualWidth(" \u2398")));
|
|
4170
|
+
_$insertNode(_el$86, _$createTextNode(` \u2398`));
|
|
2785
4171
|
_$effect((_p$) => {
|
|
2786
|
-
var _v$
|
|
4172
|
+
var _v$28 = {
|
|
2787
4173
|
fg: pal().primary
|
|
2788
|
-
}, _v$
|
|
4174
|
+
}, _v$29 = {
|
|
2789
4175
|
fg: pal().muted
|
|
2790
|
-
}, _v$
|
|
4176
|
+
}, _v$30 = {
|
|
2791
4177
|
fg: pal().muted
|
|
2792
|
-
}, _v$
|
|
4178
|
+
}, _v$31 = {
|
|
2793
4179
|
fg: pal().warning
|
|
2794
4180
|
};
|
|
2795
|
-
_v$
|
|
2796
|
-
_v$
|
|
2797
|
-
_v$
|
|
2798
|
-
_v$
|
|
4181
|
+
_v$28 !== _p$.e && (_p$.e = _$setProp(_el$82, "style", _v$28, _p$.e));
|
|
4182
|
+
_v$29 !== _p$.t && (_p$.t = _$setProp(_el$84, "style", _v$29, _p$.t));
|
|
4183
|
+
_v$30 !== _p$.a && (_p$.a = _$setProp(_el$85, "style", _v$30, _p$.a));
|
|
4184
|
+
_v$31 !== _p$.o && (_p$.o = _$setProp(_el$86, "style", _v$31, _p$.o));
|
|
2799
4185
|
return _p$;
|
|
2800
4186
|
}, {
|
|
2801
4187
|
e: void 0,
|
|
@@ -2803,7 +4189,7 @@ ${t("session.toast.copy_failed")}`, {
|
|
|
2803
4189
|
a: void 0,
|
|
2804
4190
|
o: void 0
|
|
2805
4191
|
});
|
|
2806
|
-
return _el$
|
|
4192
|
+
return _el$80;
|
|
2807
4193
|
}
|
|
2808
4194
|
}), _$createComponent(Show, {
|
|
2809
4195
|
get when() {
|
|
@@ -2819,68 +4205,68 @@ ${t("session.toast.copy_failed")}`, {
|
|
|
2819
4205
|
const rightW = (isRunning ? visualWidth(dismissLabel()) : 0) + (isRunning && entry.sessionId ? visualWidth(cancelLabel()) : 0);
|
|
2820
4206
|
const spacerW = () => Math.max(1, panelWidth() - gutter() - openW() - rightW - 2);
|
|
2821
4207
|
return (() => {
|
|
2822
|
-
var _el$
|
|
2823
|
-
_$insertNode(_el$
|
|
2824
|
-
_$setProp(_el$
|
|
2825
|
-
_$insert(_el$
|
|
4208
|
+
var _el$99 = _$createElement("box"), _el$103 = _$createElement("text");
|
|
4209
|
+
_$insertNode(_el$99, _el$103);
|
|
4210
|
+
_$setProp(_el$99, "flexDirection", "row");
|
|
4211
|
+
_$insert(_el$99, _$createComponent(Show, {
|
|
2826
4212
|
get when() {
|
|
2827
4213
|
return entry.sessionId;
|
|
2828
4214
|
},
|
|
2829
4215
|
get children() {
|
|
2830
|
-
var _el$
|
|
2831
|
-
_$insertNode(_el$
|
|
2832
|
-
_$insertNode(_el$
|
|
2833
|
-
_$setProp(_el$
|
|
2834
|
-
_$setProp(_el$
|
|
2835
|
-
_$setProp(_el$
|
|
4216
|
+
var _el$100 = _$createElement("text"), _el$101 = _$createElement("span"), _el$102 = _$createElement("span");
|
|
4217
|
+
_$insertNode(_el$100, _el$101);
|
|
4218
|
+
_$insertNode(_el$100, _el$102);
|
|
4219
|
+
_$setProp(_el$100, "onMouseOver", () => setHoveredOpen(entry.id));
|
|
4220
|
+
_$setProp(_el$100, "onMouseOut", () => setHoveredOpen(void 0));
|
|
4221
|
+
_$setProp(_el$100, "onMouseUp", () => {
|
|
2836
4222
|
if (entry.sessionId) {
|
|
2837
4223
|
props.api.route.navigateSession(entry.sessionId);
|
|
2838
4224
|
}
|
|
2839
4225
|
});
|
|
2840
|
-
_$insert(_el$
|
|
2841
|
-
_$insert(_el$
|
|
4226
|
+
_$insert(_el$101, openPrefix);
|
|
4227
|
+
_$insert(_el$102, () => t("open.label"));
|
|
2842
4228
|
_$effect((_p$) => {
|
|
2843
|
-
var _v$
|
|
4229
|
+
var _v$35 = {
|
|
2844
4230
|
fg: hoveredOpen() === entry.id ? pal().warning : pal().primary
|
|
2845
|
-
}, _v$
|
|
4231
|
+
}, _v$36 = {
|
|
2846
4232
|
fg: hoveredOpen() === entry.id ? pal().warning : pal().primary
|
|
2847
4233
|
};
|
|
2848
|
-
_v$
|
|
2849
|
-
_v$
|
|
4234
|
+
_v$35 !== _p$.e && (_p$.e = _$setProp(_el$101, "style", _v$35, _p$.e));
|
|
4235
|
+
_v$36 !== _p$.t && (_p$.t = _$setProp(_el$102, "style", _v$36, _p$.t));
|
|
2850
4236
|
return _p$;
|
|
2851
4237
|
}, {
|
|
2852
4238
|
e: void 0,
|
|
2853
4239
|
t: void 0
|
|
2854
4240
|
});
|
|
2855
|
-
return _el$
|
|
4241
|
+
return _el$100;
|
|
2856
4242
|
}
|
|
2857
|
-
}), _el$
|
|
2858
|
-
_$insert(_el$
|
|
2859
|
-
_$insert(_el$
|
|
4243
|
+
}), _el$103);
|
|
4244
|
+
_$insert(_el$103, () => " ".repeat(spacerW()));
|
|
4245
|
+
_$insert(_el$99, _$createComponent(Show, {
|
|
2860
4246
|
get when() {
|
|
2861
4247
|
return isRunning && entry.sessionId;
|
|
2862
4248
|
},
|
|
2863
4249
|
get children() {
|
|
2864
|
-
var _el$
|
|
2865
|
-
_$insertNode(_el$
|
|
2866
|
-
_$setProp(_el$
|
|
2867
|
-
_$setProp(_el$
|
|
2868
|
-
_$setProp(_el$
|
|
2869
|
-
_$insert(_el$
|
|
2870
|
-
_$effect((_$p) => _$setProp(_el$
|
|
4250
|
+
var _el$104 = _$createElement("text"), _el$105 = _$createElement("span");
|
|
4251
|
+
_$insertNode(_el$104, _el$105);
|
|
4252
|
+
_$setProp(_el$104, "onMouseOver", () => setHoveredCancel(entry.id));
|
|
4253
|
+
_$setProp(_el$104, "onMouseOut", () => setHoveredCancel(void 0));
|
|
4254
|
+
_$setProp(_el$104, "onMouseUp", () => cancelEntry(entry));
|
|
4255
|
+
_$insert(_el$105, cancelLabel);
|
|
4256
|
+
_$effect((_$p) => _$setProp(_el$105, "style", {
|
|
2871
4257
|
fg: hoveredCancel() === entry.id ? pal().warning : pal().error
|
|
2872
4258
|
}, _$p));
|
|
2873
|
-
return _el$
|
|
4259
|
+
return _el$104;
|
|
2874
4260
|
}
|
|
2875
4261
|
}), null);
|
|
2876
|
-
_$insert(_el$
|
|
4262
|
+
_$insert(_el$99, _$createComponent(Show, {
|
|
2877
4263
|
when: isRunning,
|
|
2878
4264
|
get children() {
|
|
2879
|
-
var _el$
|
|
2880
|
-
_$insertNode(_el$
|
|
2881
|
-
_$setProp(_el$
|
|
2882
|
-
_$setProp(_el$
|
|
2883
|
-
_$setProp(_el$
|
|
4265
|
+
var _el$106 = _$createElement("text"), _el$107 = _$createElement("span");
|
|
4266
|
+
_$insertNode(_el$106, _el$107);
|
|
4267
|
+
_$setProp(_el$106, "onMouseOver", () => setHoveredDismiss(entry.id));
|
|
4268
|
+
_$setProp(_el$106, "onMouseOut", () => setHoveredDismiss(void 0));
|
|
4269
|
+
_$setProp(_el$106, "onMouseUp", () => {
|
|
2884
4270
|
upsertEntry({
|
|
2885
4271
|
id: entry.id,
|
|
2886
4272
|
title: entry.title,
|
|
@@ -2889,17 +4275,17 @@ ${t("session.toast.copy_failed")}`, {
|
|
|
2889
4275
|
status: "done"
|
|
2890
4276
|
});
|
|
2891
4277
|
});
|
|
2892
|
-
_$insert(_el$
|
|
2893
|
-
_$effect((_$p) => _$setProp(_el$
|
|
4278
|
+
_$insert(_el$107, dismissLabel);
|
|
4279
|
+
_$effect((_$p) => _$setProp(_el$107, "style", {
|
|
2894
4280
|
fg: hoveredDismiss() === entry.id ? pal().warning : pal().muted
|
|
2895
4281
|
}, _$p));
|
|
2896
|
-
return _el$
|
|
4282
|
+
return _el$106;
|
|
2897
4283
|
}
|
|
2898
4284
|
}), null);
|
|
2899
|
-
_$effect((_$p) => _$setProp(_el$
|
|
4285
|
+
_$effect((_$p) => _$setProp(_el$103, "style", {
|
|
2900
4286
|
fg: pal().muted
|
|
2901
4287
|
}, _$p));
|
|
2902
|
-
return _el$
|
|
4288
|
+
return _el$99;
|
|
2903
4289
|
})();
|
|
2904
4290
|
})();
|
|
2905
4291
|
}
|
|
@@ -2920,13 +4306,13 @@ ${t("session.toast.copy_failed")}`, {
|
|
|
2920
4306
|
const right = props.sortOrder() === "desc" ? `\u2191 ${t("scroll.top")}` : `\u2193 ${t("scroll.bottom")}`;
|
|
2921
4307
|
const pad = showTop ? Math.max(1, panelWidth() - gutter() - visualWidth(left) - visualWidth(right)) : 0;
|
|
2922
4308
|
return (() => {
|
|
2923
|
-
var _el$
|
|
2924
|
-
_$insertNode(_el$
|
|
2925
|
-
_$setProp(_el$
|
|
2926
|
-
_$insertNode(_el$
|
|
2927
|
-
_$setProp(_el$
|
|
2928
|
-
_$setProp(_el$
|
|
2929
|
-
_$setProp(_el$
|
|
4309
|
+
var _el$108 = _$createElement("box"), _el$109 = _$createElement("text"), _el$110 = _$createElement("span");
|
|
4310
|
+
_$insertNode(_el$108, _el$109);
|
|
4311
|
+
_$setProp(_el$108, "flexDirection", "row");
|
|
4312
|
+
_$insertNode(_el$109, _el$110);
|
|
4313
|
+
_$setProp(_el$109, "onMouseOver", () => showMore && setHoveredMoreBelow(true));
|
|
4314
|
+
_$setProp(_el$109, "onMouseOut", () => setHoveredMoreBelow(false));
|
|
4315
|
+
_$setProp(_el$109, "onMouseUp", () => {
|
|
2930
4316
|
if (!showMore) return;
|
|
2931
4317
|
const total = entryList().length;
|
|
2932
4318
|
const m = max();
|
|
@@ -2938,20 +4324,20 @@ ${t("session.toast.copy_failed")}`, {
|
|
|
2938
4324
|
}
|
|
2939
4325
|
setHoveredMoreBelow(false);
|
|
2940
4326
|
});
|
|
2941
|
-
_$insert(_el$
|
|
2942
|
-
_$insert(_el$
|
|
2943
|
-
var _el$
|
|
2944
|
-
_$insert(_el$
|
|
2945
|
-
_$effect((_$p) => _$setProp(_el$
|
|
4327
|
+
_$insert(_el$110, left);
|
|
4328
|
+
_$insert(_el$108, showTop ? [(() => {
|
|
4329
|
+
var _el$111 = _$createElement("text");
|
|
4330
|
+
_$insert(_el$111, () => " ".repeat(pad));
|
|
4331
|
+
_$effect((_$p) => _$setProp(_el$111, "style", {
|
|
2946
4332
|
fg: pal().muted
|
|
2947
4333
|
}, _$p));
|
|
2948
|
-
return _el$
|
|
4334
|
+
return _el$111;
|
|
2949
4335
|
})(), (() => {
|
|
2950
|
-
var _el$
|
|
2951
|
-
_$insertNode(_el$
|
|
2952
|
-
_$setProp(_el$
|
|
2953
|
-
_$setProp(_el$
|
|
2954
|
-
_$setProp(_el$
|
|
4336
|
+
var _el$112 = _$createElement("text"), _el$113 = _$createElement("span");
|
|
4337
|
+
_$insertNode(_el$112, _el$113);
|
|
4338
|
+
_$setProp(_el$112, "onMouseOver", () => setHoveredTop(true));
|
|
4339
|
+
_$setProp(_el$112, "onMouseOut", () => setHoveredTop(false));
|
|
4340
|
+
_$setProp(_el$112, "onMouseUp", () => {
|
|
2955
4341
|
const total = entryList().length;
|
|
2956
4342
|
const m = max();
|
|
2957
4343
|
if (props.sortOrder() === "desc") {
|
|
@@ -2961,16 +4347,16 @@ ${t("session.toast.copy_failed")}`, {
|
|
|
2961
4347
|
}
|
|
2962
4348
|
setHoveredTop(false);
|
|
2963
4349
|
});
|
|
2964
|
-
_$insert(_el$
|
|
2965
|
-
_$effect((_$p) => _$setProp(_el$
|
|
4350
|
+
_$insert(_el$113, right);
|
|
4351
|
+
_$effect((_$p) => _$setProp(_el$113, "style", {
|
|
2966
4352
|
fg: hoveredTop() ? pal().warning : pal().muted
|
|
2967
4353
|
}, _$p));
|
|
2968
|
-
return _el$
|
|
4354
|
+
return _el$112;
|
|
2969
4355
|
})()] : null, null);
|
|
2970
|
-
_$effect((_$p) => _$setProp(_el$
|
|
4356
|
+
_$effect((_$p) => _$setProp(_el$110, "style", {
|
|
2971
4357
|
fg: showMore && hoveredMoreBelow() ? pal().warning : pal().muted
|
|
2972
4358
|
}, _$p));
|
|
2973
|
-
return _el$
|
|
4359
|
+
return _el$108;
|
|
2974
4360
|
})();
|
|
2975
4361
|
})();
|
|
2976
4362
|
}
|
|
@@ -2998,11 +4384,14 @@ ${t("session.toast.copy_failed")}`, {
|
|
|
2998
4384
|
}
|
|
2999
4385
|
|
|
3000
4386
|
// src/v2/index.tsx
|
|
3001
|
-
function
|
|
4387
|
+
function CommandRoot(props) {
|
|
3002
4388
|
props.context.keymap.layer(() => ({
|
|
3003
4389
|
mode: "global",
|
|
3004
4390
|
commands: makeCommands(props.context, props.api, props.signals)
|
|
3005
4391
|
}));
|
|
4392
|
+
return null;
|
|
4393
|
+
}
|
|
4394
|
+
function PluginRoot(props) {
|
|
3006
4395
|
return _$createComponent2(SubAgentPanel, {
|
|
3007
4396
|
get api() {
|
|
3008
4397
|
return props.api;
|
|
@@ -3025,6 +4414,21 @@ function PluginRoot(props) {
|
|
|
3025
4414
|
get borderVisible() {
|
|
3026
4415
|
return props.signals.borderVisible;
|
|
3027
4416
|
},
|
|
4417
|
+
get showEntryCost() {
|
|
4418
|
+
return props.signals.showEntryCost;
|
|
4419
|
+
},
|
|
4420
|
+
get showEntryTime() {
|
|
4421
|
+
return props.signals.showEntryTime;
|
|
4422
|
+
},
|
|
4423
|
+
get showEntryTokens() {
|
|
4424
|
+
return props.signals.showEntryTokens;
|
|
4425
|
+
},
|
|
4426
|
+
get timeFormat() {
|
|
4427
|
+
return props.signals.timeFormat;
|
|
4428
|
+
},
|
|
4429
|
+
get showOrigin() {
|
|
4430
|
+
return props.signals.showOrigin;
|
|
4431
|
+
},
|
|
3028
4432
|
get sessionId() {
|
|
3029
4433
|
return props.sessionID;
|
|
3030
4434
|
}
|
|
@@ -3050,6 +4454,13 @@ var mod = {
|
|
|
3050
4454
|
const [orderSignal, setSortOrder] = createSignal3(String(api.kv.get(SETTING_KEYS.order, "desc")) === "asc" ? "asc" : "desc");
|
|
3051
4455
|
const [scrollSignal, setScrollMode] = createSignal3(String(api.kv.get(SETTING_KEYS.scrollMode, "wheel")) === "click" ? "click" : "wheel");
|
|
3052
4456
|
const [borderSignal, setBorderVisible] = createSignal3(api.kv.get(SETTING_KEYS.border, false) === true);
|
|
4457
|
+
const [showEntryCostSignal, setShowEntryCost] = createSignal3(api.kv.get(SETTING_KEYS.showEntryCost, false) === true);
|
|
4458
|
+
const [showEntryTimeSignal, setShowEntryTime] = createSignal3(api.kv.get(SETTING_KEYS.showEntryTime, true) !== false);
|
|
4459
|
+
const [showEntryTokensSignal, setShowEntryTokens] = createSignal3(api.kv.get(SETTING_KEYS.showEntryTokens, true) !== false);
|
|
4460
|
+
const storedTimeFormat = String(api.kv.get(SETTING_KEYS.timeFormat, "short"));
|
|
4461
|
+
const [timeFormatSignal, setTimeFormat] = createSignal3(TIME_FORMATS.includes(storedTimeFormat) ? storedTimeFormat : "short");
|
|
4462
|
+
const [showOriginSignal, setShowOrigin] = createSignal3(api.kv.get(SETTING_KEYS.showOrigin, false) === true);
|
|
4463
|
+
const [dbSyncSignal, setDbSync] = createSignal3(api.kv.get(SETTING_KEYS.dbSync, true) !== false);
|
|
3053
4464
|
lang = langSignal;
|
|
3054
4465
|
maxEntries = maxSignal;
|
|
3055
4466
|
sortOrder = orderSignal;
|
|
@@ -3065,8 +4476,28 @@ var mod = {
|
|
|
3065
4476
|
setScrollMode,
|
|
3066
4477
|
borderVisible: borderSignal,
|
|
3067
4478
|
setBorderVisible,
|
|
4479
|
+
showEntryCost: showEntryCostSignal,
|
|
4480
|
+
setShowEntryCost,
|
|
4481
|
+
showEntryTime: showEntryTimeSignal,
|
|
4482
|
+
setShowEntryTime,
|
|
4483
|
+
showEntryTokens: showEntryTokensSignal,
|
|
4484
|
+
setShowEntryTokens,
|
|
4485
|
+
timeFormat: timeFormatSignal,
|
|
4486
|
+
setTimeFormat,
|
|
4487
|
+
showOrigin: showOriginSignal,
|
|
4488
|
+
setShowOrigin,
|
|
4489
|
+
dbSync: dbSyncSignal,
|
|
4490
|
+
setDbSync,
|
|
3068
4491
|
sessionId: ""
|
|
3069
4492
|
};
|
|
4493
|
+
context.ui.slot({
|
|
4494
|
+
append: "app",
|
|
4495
|
+
render: () => _$createComponent2(CommandRoot, {
|
|
4496
|
+
context,
|
|
4497
|
+
api,
|
|
4498
|
+
signals
|
|
4499
|
+
})
|
|
4500
|
+
});
|
|
3070
4501
|
context.ui.slot({
|
|
3071
4502
|
prepend: "sidebar.content",
|
|
3072
4503
|
render: (props) => {
|