opencode-subagent-magazine 1.6.0-beta.2 → 1.6.0-beta.4
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 +3 -1
- package/dist/_version.d.ts +1 -1
- package/dist/_version.js +1 -1
- package/dist/core/kv.d.ts +1 -0
- package/dist/core/kv.js +1 -0
- package/dist/core/types.d.ts +2 -0
- package/dist/i18n.d.ts +2 -0
- package/dist/i18n.js +8 -0
- package/dist/index.js +17 -2
- package/dist/panel/SubAgentPanel.d.ts +1 -0
- package/dist/panel/SubAgentPanel.js +54 -37
- package/dist/panel/entry-map.d.ts +6 -0
- package/dist/panel/entry-map.js +25 -0
- package/dist/tui.js +128 -56
- package/dist/v2/commands.js +13 -0
- package/dist/v2/index.js +3 -2
- package/dist/v2.js +124 -56
- package/package.json +1 -1
- package/src/_version.ts +1 -1
- package/src/core/color.ts +70 -70
- package/src/core/format.ts +61 -61
- package/src/core/index.ts +6 -6
- package/src/core/kv.ts +37 -36
- package/src/core/state-machine.ts +46 -46
- package/src/core/types.ts +2 -0
- package/src/core/usage.ts +16 -16
- package/src/i18n.ts +8 -0
- package/src/index.tsx +472 -454
- package/src/panel/SubAgentPanel.tsx +59 -37
- package/src/panel/entry-map.ts +39 -0
- package/src/panel/store.ts +8 -8
- package/src/v2/commands.ts +264 -251
- package/src/v2/index.tsx +102 -98
- package/src/v2/theme.ts +14 -14
- package/src/v2/types.ts +165 -165
- package/tui/index.js +11 -11
package/dist/v2.js
CHANGED
|
@@ -307,7 +307,8 @@ var SETTING_KEYS = {
|
|
|
307
307
|
order: `${KV_PREFIX}.order`,
|
|
308
308
|
scrollMode: `${KV_PREFIX}.scroll_mode`,
|
|
309
309
|
open: `${KV_PREFIX}.open`,
|
|
310
|
-
ttlDays: `${KV_PREFIX}.ttl_days
|
|
310
|
+
ttlDays: `${KV_PREFIX}.ttl_days`,
|
|
311
|
+
border: `${KV_PREFIX}.border`
|
|
311
312
|
};
|
|
312
313
|
function loadSessionData(kv) {
|
|
313
314
|
try {
|
|
@@ -329,7 +330,7 @@ function readTTLDays(kv) {
|
|
|
329
330
|
}
|
|
330
331
|
|
|
331
332
|
// src/_version.ts
|
|
332
|
-
var PLUGIN_VERSION = "1.6.0-beta.
|
|
333
|
+
var PLUGIN_VERSION = "1.6.0-beta.4";
|
|
333
334
|
|
|
334
335
|
// src/i18n.ts
|
|
335
336
|
var ZH_T = {
|
|
@@ -381,7 +382,9 @@ var ZH_T = {
|
|
|
381
382
|
"cancel.already_ended": "\u4F1A\u8BDD\u5DF2\u7ED3\u675F\uFF0C\u65E0\u9700\u53D6\u6D88",
|
|
382
383
|
"cancel.status_error": "\u65E0\u6CD5\u67E5\u8BE2\u4F1A\u8BDD\u72B6\u6001",
|
|
383
384
|
"cancel.sent": "\u5DF2\u53D1\u9001\u53D6\u6D88\u6307\u4EE4",
|
|
384
|
-
"cancel.failed": "\u53D6\u6D88\u5931\u8D25"
|
|
385
|
+
"cancel.failed": "\u53D6\u6D88\u5931\u8D25",
|
|
386
|
+
"borderShown": "\u9762\u677F\u8FB9\u6846 \u5DF2\u663E\u793A",
|
|
387
|
+
"borderHidden": "\u9762\u677F\u8FB9\u6846 \u5DF2\u9690\u85CF"
|
|
385
388
|
};
|
|
386
389
|
var EN_T = {
|
|
387
390
|
"panel.title": "SubAgent",
|
|
@@ -432,7 +435,9 @@ var EN_T = {
|
|
|
432
435
|
"cancel.already_ended": "Session already ended, no need to cancel",
|
|
433
436
|
"cancel.status_error": "Cannot query session status",
|
|
434
437
|
"cancel.sent": "Cancel instruction sent",
|
|
435
|
-
"cancel.failed": "Cancellation failed"
|
|
438
|
+
"cancel.failed": "Cancellation failed",
|
|
439
|
+
"borderShown": "Panel border shown",
|
|
440
|
+
"borderHidden": "Panel border hidden"
|
|
436
441
|
};
|
|
437
442
|
var JA_T = {
|
|
438
443
|
"panel.title": "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8",
|
|
@@ -483,7 +488,9 @@ var JA_T = {
|
|
|
483
488
|
"cancel.already_ended": "\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u65E2\u306B\u7D42\u4E86\u3057\u3066\u3044\u307E\u3059",
|
|
484
489
|
"cancel.status_error": "\u30BB\u30C3\u30B7\u30E7\u30F3\u72B6\u614B\u3092\u7167\u4F1A\u3067\u304D\u307E\u305B\u3093",
|
|
485
490
|
"cancel.sent": "\u30AD\u30E3\u30F3\u30BB\u30EB\u6307\u793A\u3092\u9001\u4FE1\u3057\u307E\u3057\u305F",
|
|
486
|
-
"cancel.failed": "\u30AD\u30E3\u30F3\u30BB\u30EB\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
|
|
491
|
+
"cancel.failed": "\u30AD\u30E3\u30F3\u30BB\u30EB\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
|
|
492
|
+
"borderShown": "\u30D1\u30CD\u30EB\u67A0\u7DDA \u8868\u793A",
|
|
493
|
+
"borderHidden": "\u30D1\u30CD\u30EB\u67A0\u7DDA \u975E\u8868\u793A"
|
|
487
494
|
};
|
|
488
495
|
var KO_T = {
|
|
489
496
|
"panel.title": "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8",
|
|
@@ -534,7 +541,9 @@ var KO_T = {
|
|
|
534
541
|
"cancel.already_ended": "\uC138\uC158\uC774 \uC774\uBBF8 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
|
|
535
542
|
"cancel.status_error": "\uC138\uC158 \uC0C1\uD0DC\uB97C \uC870\uD68C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
536
543
|
"cancel.sent": "\uCDE8\uC18C \uC9C0\uC2DC\uB97C \uBCF4\uB0C8\uC2B5\uB2C8\uB2E4",
|
|
537
|
-
"cancel.failed": "\uCDE8\uC18C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4"
|
|
544
|
+
"cancel.failed": "\uCDE8\uC18C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4",
|
|
545
|
+
"borderShown": "\uD328\uB110 \uD14C\uB450\uB9AC \uD45C\uC2DC",
|
|
546
|
+
"borderHidden": "\uD328\uB110 \uD14C\uB450\uB9AC \uC228\uAE40"
|
|
538
547
|
};
|
|
539
548
|
var LANGS = { zh: ZH_T, en: EN_T, ja: JA_T, ko: KO_T };
|
|
540
549
|
var LANG_META = [
|
|
@@ -809,6 +818,19 @@ function makeCommands(context, api, signals) {
|
|
|
809
818
|
} catch {
|
|
810
819
|
}
|
|
811
820
|
}
|
|
821
|
+
},
|
|
822
|
+
{
|
|
823
|
+
id: "opencode-subagent-magazine.subagent.border",
|
|
824
|
+
title: "SubAgent Magazine: Border",
|
|
825
|
+
description: "Show or hide the panel border",
|
|
826
|
+
slash: { name: "subagent-border" },
|
|
827
|
+
palette: true,
|
|
828
|
+
run: () => {
|
|
829
|
+
const cur = Boolean(kv.get(SETTING_KEYS.border, false));
|
|
830
|
+
kv.set(SETTING_KEYS.border, !cur);
|
|
831
|
+
signals.setBorderVisible(!cur);
|
|
832
|
+
api.ui.toast(!cur ? t("borderShown") : t("borderHidden"));
|
|
833
|
+
}
|
|
812
834
|
}
|
|
813
835
|
];
|
|
814
836
|
}
|
|
@@ -832,9 +854,11 @@ import { insertNode as _$insertNode } from "@opentui/solid";
|
|
|
832
854
|
import { createComponent as _$createComponent } from "@opentui/solid";
|
|
833
855
|
import { effect as _$effect } from "@opentui/solid";
|
|
834
856
|
import { insert as _$insert } from "@opentui/solid";
|
|
835
|
-
import { memo as _$memo } from "@opentui/solid";
|
|
836
|
-
import { use as _$use } from "@opentui/solid";
|
|
837
857
|
import { setProp as _$setProp } from "@opentui/solid";
|
|
858
|
+
import { use as _$use } from "@opentui/solid";
|
|
859
|
+
import { spread as _$spread } from "@opentui/solid";
|
|
860
|
+
import { mergeProps as _$mergeProps } from "@opentui/solid";
|
|
861
|
+
import { memo as _$memo } from "@opentui/solid";
|
|
838
862
|
import { createElement as _$createElement } from "@opentui/solid";
|
|
839
863
|
import { createMemo, createSignal as createSignal2, createEffect, onMount, onCleanup, untrack, Show, For } from "solid-js";
|
|
840
864
|
|
|
@@ -1057,6 +1081,31 @@ function isDirectChildSession(currentSessionId, eventSessionId, eventSession) {
|
|
|
1057
1081
|
return eventSessionId !== currentSessionId && eventSession?.parentID === currentSessionId;
|
|
1058
1082
|
}
|
|
1059
1083
|
|
|
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
|
+
|
|
1060
1109
|
// src/panel/SubAgentPanel.tsx
|
|
1061
1110
|
var LEFT_PAD = 4;
|
|
1062
1111
|
var INDENT = 2;
|
|
@@ -1096,7 +1145,7 @@ function SubAgentPanel(props) {
|
|
|
1096
1145
|
};
|
|
1097
1146
|
};
|
|
1098
1147
|
const loadEntries = (sid) => {
|
|
1099
|
-
|
|
1148
|
+
let m = /* @__PURE__ */ new Map();
|
|
1100
1149
|
try {
|
|
1101
1150
|
const {
|
|
1102
1151
|
parentSid,
|
|
@@ -1106,7 +1155,9 @@ function SubAgentPanel(props) {
|
|
|
1106
1155
|
if (rec) {
|
|
1107
1156
|
const source = isChild ? rec.children?.[sid]?.entries : rec.entries;
|
|
1108
1157
|
if (source) {
|
|
1109
|
-
for (const e of source)
|
|
1158
|
+
for (const e of source) {
|
|
1159
|
+
m = upsertSubEntry(m, e);
|
|
1160
|
+
}
|
|
1110
1161
|
}
|
|
1111
1162
|
}
|
|
1112
1163
|
} catch {
|
|
@@ -1344,22 +1395,7 @@ function SubAgentPanel(props) {
|
|
|
1344
1395
|
let boxEl;
|
|
1345
1396
|
let disposed = false;
|
|
1346
1397
|
const upsertEntry = (partial) => {
|
|
1347
|
-
setEntryMap((prev) =>
|
|
1348
|
-
const existing = prev.get(partial.id);
|
|
1349
|
-
const next = new Map(prev);
|
|
1350
|
-
const nowTs = Date.now();
|
|
1351
|
-
const e = partial.status;
|
|
1352
|
-
const ended = e === "done" || e === "error" || e === "cancelled";
|
|
1353
|
-
next.set(partial.id, {
|
|
1354
|
-
...existing ?? {
|
|
1355
|
-
startedAt: nowTs
|
|
1356
|
-
},
|
|
1357
|
-
...partial,
|
|
1358
|
-
startedAt: existing?.startedAt || partial.startedAt || nowTs,
|
|
1359
|
-
endedAt: ended ? existing?.endedAt || nowTs : void 0
|
|
1360
|
-
});
|
|
1361
|
-
return next;
|
|
1362
|
-
});
|
|
1398
|
+
setEntryMap((prev) => upsertSubEntry(prev, partial));
|
|
1363
1399
|
};
|
|
1364
1400
|
const isDescendantOf = (childId, rootId) => {
|
|
1365
1401
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -1503,13 +1539,17 @@ function SubAgentPanel(props) {
|
|
|
1503
1539
|
if (rawStatus === "error") {
|
|
1504
1540
|
const id2 = `tool:${String(part.id ?? "")}`;
|
|
1505
1541
|
if (!part.id) return;
|
|
1506
|
-
const
|
|
1542
|
+
const stMeta2 = st?.metadata;
|
|
1543
|
+
const errorSid = stMeta2?.session_id !== void 0 ? String(stMeta2.session_id) : stMeta2?.sessionId !== void 0 ? String(stMeta2.sessionId) : void 0;
|
|
1544
|
+
const key = findSubEntryKey(entryMap(), id2, errorSid);
|
|
1545
|
+
const existing = key ? entryMap().get(key) : void 0;
|
|
1507
1546
|
if (existing) {
|
|
1508
1547
|
upsertEntry({
|
|
1509
|
-
id:
|
|
1548
|
+
id: existing.id,
|
|
1510
1549
|
title: existing.title,
|
|
1511
1550
|
agent: existing.agent,
|
|
1512
1551
|
prompt: existing.prompt,
|
|
1552
|
+
sessionId: existing.sessionId ?? errorSid,
|
|
1513
1553
|
status: "error"
|
|
1514
1554
|
});
|
|
1515
1555
|
}
|
|
@@ -1896,12 +1936,15 @@ function SubAgentPanel(props) {
|
|
|
1896
1936
|
if (!part.id) continue;
|
|
1897
1937
|
const st = part.state;
|
|
1898
1938
|
const rawStatus = String(st?.status ?? "");
|
|
1899
|
-
const
|
|
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;
|
|
1900
1943
|
if (!exists && clearedIds.has(id)) continue;
|
|
1901
1944
|
if ((rawStatus === "pending" || rawStatus === "") && !exists) continue;
|
|
1902
1945
|
if (rawStatus === "error") {
|
|
1903
1946
|
if (exists && exists.status === "running") {
|
|
1904
|
-
next.set(id, {
|
|
1947
|
+
next.set(existingKey ?? id, {
|
|
1905
1948
|
...exists,
|
|
1906
1949
|
status: "error",
|
|
1907
1950
|
endedAt: Date.now()
|
|
@@ -1912,11 +1955,11 @@ function SubAgentPanel(props) {
|
|
|
1912
1955
|
let status = "running";
|
|
1913
1956
|
if (rawStatus === "completed") status = "done";
|
|
1914
1957
|
if ((st?.input?.run_in_background === true || st?.input?.background === true) && status === "done") {
|
|
1915
|
-
const
|
|
1916
|
-
const scanHasChild =
|
|
1958
|
+
const scanStMeta2 = st?.metadata;
|
|
1959
|
+
const scanHasChild = scanStMeta2?.session_id !== void 0 || scanStMeta2?.sessionId !== void 0;
|
|
1917
1960
|
if (scanHasChild) status = "running";
|
|
1918
1961
|
}
|
|
1919
|
-
if (exists && exists.status !== "running" && exists.status !== "cancel_requested") continue;
|
|
1962
|
+
if (exists && existingKey === id && exists.status !== "running" && exists.status !== "cancel_requested") continue;
|
|
1920
1963
|
if (exists && status === "running") {
|
|
1921
1964
|
if (!rawStatus) {
|
|
1922
1965
|
const msgTokens = msg?.tokens;
|
|
@@ -1937,12 +1980,11 @@ function SubAgentPanel(props) {
|
|
|
1937
1980
|
const desc = input?.description !== void 0 ? String(input.description) : "";
|
|
1938
1981
|
const title = desc || truncate(prompt.replace(/\n/g, " ").trim(), 40);
|
|
1939
1982
|
let tokens;
|
|
1940
|
-
const scanStMeta2 = st?.metadata;
|
|
1941
|
-
const scanSubSid = scanStMeta2?.session_id !== void 0 ? String(scanStMeta2.session_id) : scanStMeta2?.sessionId !== void 0 ? String(scanStMeta2.sessionId) : void 0;
|
|
1942
1983
|
if (scanSubSid) tokens = props.api.usage.readSessionTokens(scanSubSid);
|
|
1943
1984
|
const ended = status === "done";
|
|
1944
|
-
|
|
1945
|
-
|
|
1985
|
+
const entryKey = existingKey ?? id;
|
|
1986
|
+
next.set(entryKey, {
|
|
1987
|
+
id: exists?.id ?? id,
|
|
1946
1988
|
title,
|
|
1947
1989
|
agent,
|
|
1948
1990
|
prompt,
|
|
@@ -1953,6 +1995,7 @@ function SubAgentPanel(props) {
|
|
|
1953
1995
|
startedAt: exists?.startedAt || Date.now(),
|
|
1954
1996
|
endedAt: ended ? exists?.endedAt || Date.now() : void 0
|
|
1955
1997
|
});
|
|
1998
|
+
if (entryKey !== id) next.delete(id);
|
|
1956
1999
|
}
|
|
1957
2000
|
}
|
|
1958
2001
|
}
|
|
@@ -2098,13 +2141,21 @@ function SubAgentPanel(props) {
|
|
|
2098
2141
|
return next;
|
|
2099
2142
|
});
|
|
2100
2143
|
};
|
|
2101
|
-
const
|
|
2144
|
+
const gutter = createMemo(() => props.borderVisible() ? 6 : 0);
|
|
2145
|
+
const sep = () => "\u2500".repeat(Math.max(1, panelWidth() - gutter()));
|
|
2146
|
+
createEffect(() => {
|
|
2147
|
+
props.borderVisible();
|
|
2148
|
+
if (boxEl && typeof boxEl.width === "number" && boxEl.width > 0) {
|
|
2149
|
+
const w = Math.max(20, boxEl.width);
|
|
2150
|
+
setPanelWidth((prev) => prev === w ? prev : w);
|
|
2151
|
+
}
|
|
2152
|
+
});
|
|
2102
2153
|
const expandedMaxLabelW = createMemo(() => {
|
|
2103
2154
|
const labels = [t("agent.label"), t("status.label"), t("time.label"), t("tokens.label"), t("error.label"), t("cost.label"), t("model.label"), t("todo.label"), t("session.label")];
|
|
2104
2155
|
return Math.max(...labels.map((l) => visualWidth(l + ": ")));
|
|
2105
2156
|
});
|
|
2106
2157
|
const expandedPad = (label) => Math.max(0, expandedMaxLabelW() - visualWidth(label + ": "));
|
|
2107
|
-
const expandedValAvail = () => Math.max(6, panelWidth() - INDENT - expandedMaxLabelW());
|
|
2158
|
+
const expandedValAvail = () => Math.max(6, panelWidth() - gutter() - INDENT - expandedMaxLabelW());
|
|
2108
2159
|
const summaryParts = createMemo(() => {
|
|
2109
2160
|
if (!anyEntry()) return null;
|
|
2110
2161
|
const dot = "\u25CF";
|
|
@@ -2133,7 +2184,7 @@ function SubAgentPanel(props) {
|
|
|
2133
2184
|
if (!open()) return false;
|
|
2134
2185
|
const icon = "\u25BC";
|
|
2135
2186
|
const need = visualWidth(icon) + 1 + visualWidth(t("panel.title")) + versionW + summaryCols();
|
|
2136
|
-
return need <= panelWidth();
|
|
2187
|
+
return need <= panelWidth() - gutter();
|
|
2137
2188
|
});
|
|
2138
2189
|
const leftCols = createMemo(() => {
|
|
2139
2190
|
const icon = open() ? "\u25BC" : "\u25B6";
|
|
@@ -2143,25 +2194,36 @@ function SubAgentPanel(props) {
|
|
|
2143
2194
|
});
|
|
2144
2195
|
const spacerCols = createMemo(() => {
|
|
2145
2196
|
if (!anyEntry()) return 0;
|
|
2146
|
-
return Math.max(0, panelWidth() - leftCols() - summaryCols());
|
|
2197
|
+
return Math.max(0, panelWidth() - gutter() - leftCols() - summaryCols());
|
|
2147
2198
|
});
|
|
2148
|
-
const valueCols = (label) => Math.max(4, panelWidth() - INDENT - visualWidth(label + ": "));
|
|
2199
|
+
const valueCols = (label) => Math.max(4, panelWidth() - gutter() - INDENT - visualWidth(label + ": "));
|
|
2149
2200
|
return (() => {
|
|
2150
2201
|
var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("span"), _el$4 = _$createElement("span");
|
|
2151
2202
|
_$insertNode(_el$, _el$2);
|
|
2152
2203
|
var _ref$ = boxEl;
|
|
2153
2204
|
typeof _ref$ === "function" ? _$use(_ref$, _el$) : boxEl = _el$;
|
|
2154
|
-
_$
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2205
|
+
_$spread(_el$, _$mergeProps({
|
|
2206
|
+
get border() {
|
|
2207
|
+
return props.borderVisible();
|
|
2208
|
+
}
|
|
2209
|
+
}, () => props.borderVisible() ? {
|
|
2210
|
+
borderColor: pal().border
|
|
2211
|
+
} : {}, {
|
|
2212
|
+
"paddingTop": 0,
|
|
2213
|
+
"paddingBottom": 0,
|
|
2214
|
+
get paddingLeft() {
|
|
2215
|
+
return props.borderVisible() ? 2 : 0;
|
|
2216
|
+
},
|
|
2217
|
+
get paddingRight() {
|
|
2218
|
+
return props.borderVisible() ? 2 : 0;
|
|
2219
|
+
},
|
|
2220
|
+
"flexDirection": "column",
|
|
2221
|
+
"gap": 0,
|
|
2222
|
+
"onSizeChange": () => {
|
|
2223
|
+
const w = boxEl ? Math.max(20, boxEl.width ?? 0) : 28;
|
|
2224
|
+
setPanelWidth((prev) => prev === w ? prev : w);
|
|
2225
|
+
}
|
|
2226
|
+
}), true);
|
|
2165
2227
|
_$insertNode(_el$2, _el$3);
|
|
2166
2228
|
_$insertNode(_el$2, _el$4);
|
|
2167
2229
|
_$setProp(_el$2, "onMouseUp", () => {
|
|
@@ -2358,7 +2420,7 @@ function SubAgentPanel(props) {
|
|
|
2358
2420
|
if (tk) w += visualWidth(tk);
|
|
2359
2421
|
return w;
|
|
2360
2422
|
};
|
|
2361
|
-
const labelAvail = () => Math.max(6, panelWidth() - LEFT_PAD - suffixW());
|
|
2423
|
+
const labelAvail = () => Math.max(6, panelWidth() - gutter() - LEFT_PAD - suffixW());
|
|
2362
2424
|
const labelText = () => {
|
|
2363
2425
|
const max2 = labelAvail();
|
|
2364
2426
|
const text = entry.title || entry.agent;
|
|
@@ -2755,7 +2817,7 @@ ${t("session.toast.copy_failed")}`, {
|
|
|
2755
2817
|
const cancelLabel = () => ` ${t("cancel.label")}`;
|
|
2756
2818
|
const dismissLabel = () => ` ${t("dismiss.label")}`;
|
|
2757
2819
|
const rightW = (isRunning ? visualWidth(dismissLabel()) : 0) + (isRunning && entry.sessionId ? visualWidth(cancelLabel()) : 0);
|
|
2758
|
-
const spacerW = () => Math.max(1, panelWidth() - openW() - rightW - 2);
|
|
2820
|
+
const spacerW = () => Math.max(1, panelWidth() - gutter() - openW() - rightW - 2);
|
|
2759
2821
|
return (() => {
|
|
2760
2822
|
var _el$91 = _$createElement("box"), _el$95 = _$createElement("text");
|
|
2761
2823
|
_$insertNode(_el$91, _el$95);
|
|
@@ -2856,7 +2918,7 @@ ${t("session.toast.copy_failed")}`, {
|
|
|
2856
2918
|
const showTop = props.sortOrder() === "desc" ? scrollOffset() > 0 : entryList().length > max() && clampedOffset() < entryList().length - max();
|
|
2857
2919
|
const left = showMore ? ` \u2193 ${hiddenBelow()} ${t("scroll.more")}` : " ";
|
|
2858
2920
|
const right = props.sortOrder() === "desc" ? `\u2191 ${t("scroll.top")}` : `\u2193 ${t("scroll.bottom")}`;
|
|
2859
|
-
const pad = showTop ? Math.max(1, panelWidth() - visualWidth(left) - visualWidth(right)) : 0;
|
|
2921
|
+
const pad = showTop ? Math.max(1, panelWidth() - gutter() - visualWidth(left) - visualWidth(right)) : 0;
|
|
2860
2922
|
return (() => {
|
|
2861
2923
|
var _el$100 = _$createElement("box"), _el$101 = _$createElement("text"), _el$102 = _$createElement("span");
|
|
2862
2924
|
_$insertNode(_el$100, _el$101);
|
|
@@ -2960,6 +3022,9 @@ function PluginRoot(props) {
|
|
|
2960
3022
|
get scrollMode() {
|
|
2961
3023
|
return props.signals.scrollMode;
|
|
2962
3024
|
},
|
|
3025
|
+
get borderVisible() {
|
|
3026
|
+
return props.signals.borderVisible;
|
|
3027
|
+
},
|
|
2963
3028
|
get sessionId() {
|
|
2964
3029
|
return props.sessionID;
|
|
2965
3030
|
}
|
|
@@ -2984,6 +3049,7 @@ var mod = {
|
|
|
2984
3049
|
const [maxSignal, setMaxEntries] = createSignal3(Number(api.kv.get(SETTING_KEYS.maxEntries, "10")) || 10);
|
|
2985
3050
|
const [orderSignal, setSortOrder] = createSignal3(String(api.kv.get(SETTING_KEYS.order, "desc")) === "asc" ? "asc" : "desc");
|
|
2986
3051
|
const [scrollSignal, setScrollMode] = createSignal3(String(api.kv.get(SETTING_KEYS.scrollMode, "wheel")) === "click" ? "click" : "wheel");
|
|
3052
|
+
const [borderSignal, setBorderVisible] = createSignal3(api.kv.get(SETTING_KEYS.border, false) === true);
|
|
2987
3053
|
lang = langSignal;
|
|
2988
3054
|
maxEntries = maxSignal;
|
|
2989
3055
|
sortOrder = orderSignal;
|
|
@@ -2997,6 +3063,8 @@ var mod = {
|
|
|
2997
3063
|
setSortOrder,
|
|
2998
3064
|
scrollMode,
|
|
2999
3065
|
setScrollMode,
|
|
3066
|
+
borderVisible: borderSignal,
|
|
3067
|
+
setBorderVisible,
|
|
3000
3068
|
sessionId: ""
|
|
3001
3069
|
};
|
|
3002
3070
|
context.ui.slot({
|
package/package.json
CHANGED
package/src/_version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// auto-generated
|
|
2
|
-
export const PLUGIN_VERSION="1.6.0-beta.
|
|
2
|
+
export const PLUGIN_VERSION="1.6.0-beta.4";
|
package/src/core/color.ts
CHANGED
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
/** Morandi palette helpers — desaturate any theme color toward a muted fallback. */
|
|
2
|
-
|
|
3
|
-
export function rgb(raw: unknown): { r: number; g: number; b: number } | null {
|
|
4
|
-
if (typeof raw === "string" && raw.startsWith("#")) {
|
|
5
|
-
const h = raw.slice(1)
|
|
6
|
-
return {
|
|
7
|
-
r: parseInt(h.slice(0, 2), 16),
|
|
8
|
-
g: parseInt(h.slice(2, 4), 16),
|
|
9
|
-
b: parseInt(h.slice(4, 6), 16),
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
if (raw && typeof raw === "object") {
|
|
13
|
-
const o = raw as Record<string, unknown>
|
|
14
|
-
if (typeof o.r === "number" && typeof o.g === "number" && typeof o.b === "number") {
|
|
15
|
-
const scale = o.r > 1 || o.g > 1 || o.b > 1 ? 1 : 255
|
|
16
|
-
return { r: Math.round(o.r * scale), g: Math.round(o.g * scale), b: Math.round(o.b * scale) }
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return null
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function saturation(r: number, g: number, b: number): number {
|
|
23
|
-
const max = Math.max(r, g, b) / 255
|
|
24
|
-
const min = Math.min(r, g, b) / 255
|
|
25
|
-
const delta = max - min
|
|
26
|
-
if (delta === 0) return 0
|
|
27
|
-
const L = (max + min) / 2
|
|
28
|
-
return L <= 0.5 ? delta / (max + min) : delta / (2 - max - min)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function desaturateTo(raw: unknown, maxSat: number, fallback: string): string {
|
|
32
|
-
const c = rgb(raw)
|
|
33
|
-
if (!c) return fallback
|
|
34
|
-
const sat = saturation(c.r, c.g, c.b)
|
|
35
|
-
if (sat <= maxSat) {
|
|
36
|
-
return "#" + [c.r, c.g, c.b].map((v) => v.toString(16).padStart(2, "0")).join("")
|
|
37
|
-
}
|
|
38
|
-
const luma = c.r * 0.299 + c.g * 0.587 + c.b * 0.114
|
|
39
|
-
let lo = 0, hi = 1
|
|
40
|
-
for (let i = 0; i < 12; i++) {
|
|
41
|
-
const mid = (lo + hi) / 2
|
|
42
|
-
const nr = Math.round(c.r + (luma - c.r) * mid)
|
|
43
|
-
const ng = Math.round(c.g + (luma - c.g) * mid)
|
|
44
|
-
const nb = Math.round(c.b + (luma - c.b) * mid)
|
|
45
|
-
if (saturation(nr, ng, nb) > maxSat) lo = mid
|
|
46
|
-
else hi = mid
|
|
47
|
-
}
|
|
48
|
-
const nr = Math.round(c.r + (luma - c.r) * hi)
|
|
49
|
-
const ng = Math.round(c.g + (luma - c.g) * hi)
|
|
50
|
-
const nb = Math.round(c.b + (luma - c.b) * hi)
|
|
51
|
-
return "#" + [nr, ng, nb].map((v) => Math.max(0, Math.min(255, v)).toString(16).padStart(2, "0")).join("")
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function dimColor(hex: string, factor = 0.5): string {
|
|
55
|
-
const c = rgb(hex)
|
|
56
|
-
if (!c) return hex
|
|
57
|
-
const r = Math.round(c.r * factor)
|
|
58
|
-
const g = Math.round(c.g * factor)
|
|
59
|
-
const b = Math.round(c.b * factor)
|
|
60
|
-
return "#" + [r, g, b].map((v) => Math.max(0, Math.min(255, v)).toString(16).padStart(2, "0")).join("")
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export const FALLBACK = {
|
|
64
|
-
primary: "#8B9DAF", text: "#C5C5BB", muted: "#7A7A72",
|
|
65
|
-
success: "#9CAF8B", warning: "#C5B88D", error: "#B08A8A", border: "#6B6B63",
|
|
66
|
-
} as const
|
|
67
|
-
|
|
68
|
-
export const MAX_SAT = 0.28
|
|
69
|
-
|
|
70
|
-
export { desaturateTo, dimColor }
|
|
1
|
+
/** Morandi palette helpers — desaturate any theme color toward a muted fallback. */
|
|
2
|
+
|
|
3
|
+
export function rgb(raw: unknown): { r: number; g: number; b: number } | null {
|
|
4
|
+
if (typeof raw === "string" && raw.startsWith("#")) {
|
|
5
|
+
const h = raw.slice(1)
|
|
6
|
+
return {
|
|
7
|
+
r: parseInt(h.slice(0, 2), 16),
|
|
8
|
+
g: parseInt(h.slice(2, 4), 16),
|
|
9
|
+
b: parseInt(h.slice(4, 6), 16),
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
if (raw && typeof raw === "object") {
|
|
13
|
+
const o = raw as Record<string, unknown>
|
|
14
|
+
if (typeof o.r === "number" && typeof o.g === "number" && typeof o.b === "number") {
|
|
15
|
+
const scale = o.r > 1 || o.g > 1 || o.b > 1 ? 1 : 255
|
|
16
|
+
return { r: Math.round(o.r * scale), g: Math.round(o.g * scale), b: Math.round(o.b * scale) }
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return null
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function saturation(r: number, g: number, b: number): number {
|
|
23
|
+
const max = Math.max(r, g, b) / 255
|
|
24
|
+
const min = Math.min(r, g, b) / 255
|
|
25
|
+
const delta = max - min
|
|
26
|
+
if (delta === 0) return 0
|
|
27
|
+
const L = (max + min) / 2
|
|
28
|
+
return L <= 0.5 ? delta / (max + min) : delta / (2 - max - min)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function desaturateTo(raw: unknown, maxSat: number, fallback: string): string {
|
|
32
|
+
const c = rgb(raw)
|
|
33
|
+
if (!c) return fallback
|
|
34
|
+
const sat = saturation(c.r, c.g, c.b)
|
|
35
|
+
if (sat <= maxSat) {
|
|
36
|
+
return "#" + [c.r, c.g, c.b].map((v) => v.toString(16).padStart(2, "0")).join("")
|
|
37
|
+
}
|
|
38
|
+
const luma = c.r * 0.299 + c.g * 0.587 + c.b * 0.114
|
|
39
|
+
let lo = 0, hi = 1
|
|
40
|
+
for (let i = 0; i < 12; i++) {
|
|
41
|
+
const mid = (lo + hi) / 2
|
|
42
|
+
const nr = Math.round(c.r + (luma - c.r) * mid)
|
|
43
|
+
const ng = Math.round(c.g + (luma - c.g) * mid)
|
|
44
|
+
const nb = Math.round(c.b + (luma - c.b) * mid)
|
|
45
|
+
if (saturation(nr, ng, nb) > maxSat) lo = mid
|
|
46
|
+
else hi = mid
|
|
47
|
+
}
|
|
48
|
+
const nr = Math.round(c.r + (luma - c.r) * hi)
|
|
49
|
+
const ng = Math.round(c.g + (luma - c.g) * hi)
|
|
50
|
+
const nb = Math.round(c.b + (luma - c.b) * hi)
|
|
51
|
+
return "#" + [nr, ng, nb].map((v) => Math.max(0, Math.min(255, v)).toString(16).padStart(2, "0")).join("")
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function dimColor(hex: string, factor = 0.5): string {
|
|
55
|
+
const c = rgb(hex)
|
|
56
|
+
if (!c) return hex
|
|
57
|
+
const r = Math.round(c.r * factor)
|
|
58
|
+
const g = Math.round(c.g * factor)
|
|
59
|
+
const b = Math.round(c.b * factor)
|
|
60
|
+
return "#" + [r, g, b].map((v) => Math.max(0, Math.min(255, v)).toString(16).padStart(2, "0")).join("")
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const FALLBACK = {
|
|
64
|
+
primary: "#8B9DAF", text: "#C5C5BB", muted: "#7A7A72",
|
|
65
|
+
success: "#9CAF8B", warning: "#C5B88D", error: "#B08A8A", border: "#6B6B63",
|
|
66
|
+
} as const
|
|
67
|
+
|
|
68
|
+
export const MAX_SAT = 0.28
|
|
69
|
+
|
|
70
|
+
export { desaturateTo, dimColor }
|
package/src/core/format.ts
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
/** Visual width of a single character (CJK/wide chars count as 2). */
|
|
2
|
-
function charColumns(c: string): number {
|
|
3
|
-
const code = c.codePointAt(0) ?? 0
|
|
4
|
-
if (code < 0x20) return 0
|
|
5
|
-
if (code < 0x7f) return 1
|
|
6
|
-
if (code < 0xa0) return 0
|
|
7
|
-
if (
|
|
8
|
-
(code >= 0x1100 && code <= 0x115f) ||
|
|
9
|
-
(code >= 0x2e80 && code <= 0xa4cf) ||
|
|
10
|
-
(code >= 0xac00 && code <= 0xd7a3) ||
|
|
11
|
-
(code >= 0xf900 && code <= 0xfaff) ||
|
|
12
|
-
(code >= 0xfe10 && code <= 0xfe6f) ||
|
|
13
|
-
(code >= 0xff01 && code <= 0xff60) ||
|
|
14
|
-
(code >= 0xffe0 && code <= 0xffe6) ||
|
|
15
|
-
(code >= 0x1f300 && code <= 0x1f64f) ||
|
|
16
|
-
(code >= 0x20000 && code <= 0x3fffd)
|
|
17
|
-
)
|
|
18
|
-
return 2
|
|
19
|
-
return 1
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function visualWidth(s: string): number {
|
|
23
|
-
let w = 0
|
|
24
|
-
for (const c of s) w += charColumns(c)
|
|
25
|
-
return w
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function truncate(text: string, maxCols: number): string {
|
|
29
|
-
if (visualWidth(text) <= maxCols) return text
|
|
30
|
-
let cols = 0
|
|
31
|
-
let i = 0
|
|
32
|
-
for (const c of text) {
|
|
33
|
-
const w = charColumns(c)
|
|
34
|
-
if (cols + w > maxCols - 1) break
|
|
35
|
-
cols += w
|
|
36
|
-
i += c.length
|
|
37
|
-
}
|
|
38
|
-
return text.slice(0, i) + "\u2026"
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function fmtDurationShort(ms: number, running: boolean): string {
|
|
42
|
-
if (running && ms < 2000) return ""
|
|
43
|
-
if (ms < 1000) return (ms / 1000).toFixed(2) + "s"
|
|
44
|
-
if (ms < 60000) return (ms / 1000).toFixed(2) + "s"
|
|
45
|
-
const m = Math.floor(ms / 60000)
|
|
46
|
-
const s = Math.round((ms % 60000) / 1000)
|
|
47
|
-
return `${m}m${s}s`
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function fmtTokens(n: number): string {
|
|
51
|
-
if (n < 1000) return `${n}`
|
|
52
|
-
if (n < 1000000) return `${(n / 1000).toFixed(1)}k`
|
|
53
|
-
return `${(n / 1000000).toFixed(1)}M`
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function safeErrorMsg(err: unknown): string {
|
|
57
|
-
if (!err) return ""
|
|
58
|
-
if (typeof err === "string") return err
|
|
59
|
-
if (typeof err === "object") return String((err as any).message || (err as any).code || "")
|
|
60
|
-
return ""
|
|
61
|
-
}
|
|
1
|
+
/** Visual width of a single character (CJK/wide chars count as 2). */
|
|
2
|
+
function charColumns(c: string): number {
|
|
3
|
+
const code = c.codePointAt(0) ?? 0
|
|
4
|
+
if (code < 0x20) return 0
|
|
5
|
+
if (code < 0x7f) return 1
|
|
6
|
+
if (code < 0xa0) return 0
|
|
7
|
+
if (
|
|
8
|
+
(code >= 0x1100 && code <= 0x115f) ||
|
|
9
|
+
(code >= 0x2e80 && code <= 0xa4cf) ||
|
|
10
|
+
(code >= 0xac00 && code <= 0xd7a3) ||
|
|
11
|
+
(code >= 0xf900 && code <= 0xfaff) ||
|
|
12
|
+
(code >= 0xfe10 && code <= 0xfe6f) ||
|
|
13
|
+
(code >= 0xff01 && code <= 0xff60) ||
|
|
14
|
+
(code >= 0xffe0 && code <= 0xffe6) ||
|
|
15
|
+
(code >= 0x1f300 && code <= 0x1f64f) ||
|
|
16
|
+
(code >= 0x20000 && code <= 0x3fffd)
|
|
17
|
+
)
|
|
18
|
+
return 2
|
|
19
|
+
return 1
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function visualWidth(s: string): number {
|
|
23
|
+
let w = 0
|
|
24
|
+
for (const c of s) w += charColumns(c)
|
|
25
|
+
return w
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function truncate(text: string, maxCols: number): string {
|
|
29
|
+
if (visualWidth(text) <= maxCols) return text
|
|
30
|
+
let cols = 0
|
|
31
|
+
let i = 0
|
|
32
|
+
for (const c of text) {
|
|
33
|
+
const w = charColumns(c)
|
|
34
|
+
if (cols + w > maxCols - 1) break
|
|
35
|
+
cols += w
|
|
36
|
+
i += c.length
|
|
37
|
+
}
|
|
38
|
+
return text.slice(0, i) + "\u2026"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function fmtDurationShort(ms: number, running: boolean): string {
|
|
42
|
+
if (running && ms < 2000) return ""
|
|
43
|
+
if (ms < 1000) return (ms / 1000).toFixed(2) + "s"
|
|
44
|
+
if (ms < 60000) return (ms / 1000).toFixed(2) + "s"
|
|
45
|
+
const m = Math.floor(ms / 60000)
|
|
46
|
+
const s = Math.round((ms % 60000) / 1000)
|
|
47
|
+
return `${m}m${s}s`
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function fmtTokens(n: number): string {
|
|
51
|
+
if (n < 1000) return `${n}`
|
|
52
|
+
if (n < 1000000) return `${(n / 1000).toFixed(1)}k`
|
|
53
|
+
return `${(n / 1000000).toFixed(1)}M`
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function safeErrorMsg(err: unknown): string {
|
|
57
|
+
if (!err) return ""
|
|
58
|
+
if (typeof err === "string") return err
|
|
59
|
+
if (typeof err === "object") return String((err as any).message || (err as any).code || "")
|
|
60
|
+
return ""
|
|
61
|
+
}
|