opencode-subagent-magazine 1.5.2 → 1.5.3
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/i18n.d.ts +2 -0
- package/dist/i18n.js +8 -0
- package/dist/index.js +38 -11
- package/dist/tui.js +78 -26
- package/package.json +1 -1
- package/src/_version.ts +1 -1
- package/src/i18n.ts +8 -0
- package/src/index.tsx +48 -11
package/README.md
CHANGED
|
@@ -56,7 +56,8 @@
|
|
|
56
56
|
- **TTL 自动清理**:可配置数据保留期限(3/7/14/30 天/无期限),每次访问自动续期,过期自动清除
|
|
57
57
|
- **手动清除条目**:`/subagent-clear-entries` 清除当前会话所有记录,防止历史条目扫描重建
|
|
58
58
|
- **语言适配**:支持 `/subagent-lang` 运行时切换中/英文,偏好持久化
|
|
59
|
-
-
|
|
59
|
+
- **可切换边框**:`/subagent-border` 控制面板外边框显隐(默认隐藏),开启后与缓存统计面板风格统一
|
|
60
|
+
- **斜杠命令**:`/subagent-lang` `/subagent-max` `/subagent-order` `/subagent-scroll` `/subagent-ttl` `/subagent-clear-entries` `/subagent-session` `/subagent-version` `/subagent-clear-running` `/subagent-border` 动态配置
|
|
60
61
|
|
|
61
62
|
---
|
|
62
63
|
|
|
@@ -114,6 +115,7 @@ npm install -g opencode-subagent-magazine@latest
|
|
|
114
115
|
| `/subagent-session` | 查看当前会话 ID | 弹出当前 OpenCode 会话 ID |
|
|
115
116
|
| `/subagent-version` | 查看插件版本 | 弹出当前插件版本号 |
|
|
116
117
|
| `/subagent-clear-running` | 批量清理僵尸条目 | 一键将所有运行中的条目标记为完成,清理卡住的旧数据 |
|
|
118
|
+
| `/subagent-border` | 开关面板边框 | 切换面板外边框显隐(默认隐藏),即时生效并持久化 |
|
|
117
119
|
|
|
118
120
|
<div align="center">
|
|
119
121
|
<img src="https://raw.githubusercontent.com/Hotakus/opencode-subagent-magazine/master/assets/slash_cmds.png" alt="斜杠命令" width="49%"></img>
|
package/dist/_version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PLUGIN_VERSION = "1.5.
|
|
1
|
+
export declare const PLUGIN_VERSION = "1.5.3";
|
package/dist/_version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// auto-generated
|
|
2
|
-
export const PLUGIN_VERSION = "1.5.
|
|
2
|
+
export const PLUGIN_VERSION = "1.5.3";
|
package/dist/i18n.d.ts
CHANGED
|
@@ -49,6 +49,8 @@ declare const ZH_T: {
|
|
|
49
49
|
readonly "cancel.status_error": "无法查询会话状态";
|
|
50
50
|
readonly "cancel.sent": "已发送取消指令";
|
|
51
51
|
readonly "cancel.failed": "取消失败";
|
|
52
|
+
readonly borderShown: "面板边框 已显示";
|
|
53
|
+
readonly borderHidden: "面板边框 已隐藏";
|
|
52
54
|
};
|
|
53
55
|
/** 结构约束:值放宽为 string,键集合来自中文表(新增语言缺 key 会编译报错)。 */
|
|
54
56
|
export type Translation = {
|
package/dist/i18n.js
CHANGED
|
@@ -53,6 +53,8 @@ const ZH_T = {
|
|
|
53
53
|
"cancel.status_error": "无法查询会话状态",
|
|
54
54
|
"cancel.sent": "已发送取消指令",
|
|
55
55
|
"cancel.failed": "取消失败",
|
|
56
|
+
"borderShown": "面板边框 已显示",
|
|
57
|
+
"borderHidden": "面板边框 已隐藏",
|
|
56
58
|
};
|
|
57
59
|
const EN_T = {
|
|
58
60
|
"panel.title": "SubAgent",
|
|
@@ -104,6 +106,8 @@ const EN_T = {
|
|
|
104
106
|
"cancel.status_error": "Cannot query session status",
|
|
105
107
|
"cancel.sent": "Cancel instruction sent",
|
|
106
108
|
"cancel.failed": "Cancellation failed",
|
|
109
|
+
"borderShown": "Panel border shown",
|
|
110
|
+
"borderHidden": "Panel border hidden",
|
|
107
111
|
};
|
|
108
112
|
const JA_T = {
|
|
109
113
|
"panel.title": "サブエージェント",
|
|
@@ -155,6 +159,8 @@ const JA_T = {
|
|
|
155
159
|
"cancel.status_error": "セッション状態を照会できません",
|
|
156
160
|
"cancel.sent": "キャンセル指示を送信しました",
|
|
157
161
|
"cancel.failed": "キャンセルに失敗しました",
|
|
162
|
+
"borderShown": "パネル枠線 表示",
|
|
163
|
+
"borderHidden": "パネル枠線 非表示",
|
|
158
164
|
};
|
|
159
165
|
const KO_T = {
|
|
160
166
|
"panel.title": "서브 에이전트",
|
|
@@ -206,6 +212,8 @@ const KO_T = {
|
|
|
206
212
|
"cancel.status_error": "세션 상태를 조회할 수 없습니다",
|
|
207
213
|
"cancel.sent": "취소 지시를 보냈습니다",
|
|
208
214
|
"cancel.failed": "취소에 실패했습니다",
|
|
215
|
+
"borderShown": "패널 테두리 표시",
|
|
216
|
+
"borderHidden": "패널 테두리 숨김",
|
|
209
217
|
};
|
|
210
218
|
export const LANGS = { zh: ZH_T, en: EN_T, ja: JA_T, ko: KO_T };
|
|
211
219
|
/** 语言元数据:/subagent-lang 选项与自动检测共用。 */
|
package/dist/index.js
CHANGED
|
@@ -1252,7 +1252,19 @@ function SubAgentPanel(props) {
|
|
|
1252
1252
|
return next;
|
|
1253
1253
|
});
|
|
1254
1254
|
};
|
|
1255
|
-
|
|
1255
|
+
/** Horizontal space eaten by the panel border (1+1) and its padding (2+2). */
|
|
1256
|
+
const gutter = createMemo(() => (props.borderVisible() ? 6 : 0));
|
|
1257
|
+
const sep = () => "\u2500".repeat(Math.max(1, panelWidth() - gutter()));
|
|
1258
|
+
// The border toggling shifts the box dimensions, which may not reliably
|
|
1259
|
+
// re-fire onSizeChange across (re)mount cycles; re-sync panelWidth with the
|
|
1260
|
+
// live box so the content width stays correct.
|
|
1261
|
+
createEffect(() => {
|
|
1262
|
+
props.borderVisible();
|
|
1263
|
+
if (boxEl && typeof boxEl.width === "number" && boxEl.width > 0) {
|
|
1264
|
+
const w = Math.max(20, boxEl.width);
|
|
1265
|
+
setPanelWidth((prev) => (prev === w ? prev : w));
|
|
1266
|
+
}
|
|
1267
|
+
});
|
|
1256
1268
|
// ── expanded detail right-align ──
|
|
1257
1269
|
const expandedMaxLabelW = createMemo(() => {
|
|
1258
1270
|
const labels = [
|
|
@@ -1262,7 +1274,7 @@ function SubAgentPanel(props) {
|
|
|
1262
1274
|
return Math.max(...labels.map(l => visualWidth(l + ": ")));
|
|
1263
1275
|
});
|
|
1264
1276
|
const expandedPad = (label) => Math.max(0, expandedMaxLabelW() - visualWidth(label + ": "));
|
|
1265
|
-
const expandedValAvail = () => Math.max(6, panelWidth() - INDENT - expandedMaxLabelW());
|
|
1277
|
+
const expandedValAvail = () => Math.max(6, panelWidth() - gutter() - INDENT - expandedMaxLabelW());
|
|
1266
1278
|
// ── header parts for colored spans ──
|
|
1267
1279
|
const summaryParts = createMemo(() => {
|
|
1268
1280
|
if (!anyEntry())
|
|
@@ -1297,7 +1309,7 @@ function SubAgentPanel(props) {
|
|
|
1297
1309
|
return false;
|
|
1298
1310
|
const icon = "\u25bc";
|
|
1299
1311
|
const need = visualWidth(icon) + 1 + visualWidth(t("panel.title")) + versionW + summaryCols();
|
|
1300
|
-
return need <= panelWidth();
|
|
1312
|
+
return need <= panelWidth() - gutter();
|
|
1301
1313
|
});
|
|
1302
1314
|
const leftCols = createMemo(() => {
|
|
1303
1315
|
const icon = open() ? "\u25bc" : "\u25b6";
|
|
@@ -1309,11 +1321,11 @@ function SubAgentPanel(props) {
|
|
|
1309
1321
|
const spacerCols = createMemo(() => {
|
|
1310
1322
|
if (!anyEntry())
|
|
1311
1323
|
return 0;
|
|
1312
|
-
return Math.max(0, panelWidth() - leftCols() - summaryCols());
|
|
1324
|
+
return Math.max(0, panelWidth() - gutter() - leftCols() - summaryCols());
|
|
1313
1325
|
});
|
|
1314
|
-
const valueCols = (label) => Math.max(4, panelWidth() - INDENT - visualWidth(label + ": "));
|
|
1326
|
+
const valueCols = (label) => Math.max(4, panelWidth() - gutter() - INDENT - visualWidth(label + ": "));
|
|
1315
1327
|
// ── render ──
|
|
1316
|
-
return (_jsxs("box", { border:
|
|
1328
|
+
return (_jsxs("box", { border: props.borderVisible(), ...(props.borderVisible() ? { borderColor: pal().border } : {}), paddingTop: 0, paddingBottom: 0, paddingLeft: props.borderVisible() ? 2 : 0, paddingRight: props.borderVisible() ? 2 : 0, flexDirection: "column", gap: 0, ref: boxEl, onSizeChange: () => {
|
|
1317
1329
|
const w = boxEl ? Math.max(20, boxEl.width ?? 0) : 28;
|
|
1318
1330
|
setPanelWidth((prev) => (prev === w ? prev : w));
|
|
1319
1331
|
}, children: [_jsxs("text", { onMouseUp: () => {
|
|
@@ -1405,7 +1417,7 @@ function SubAgentPanel(props) {
|
|
|
1405
1417
|
w += visualWidth(tk);
|
|
1406
1418
|
return w;
|
|
1407
1419
|
};
|
|
1408
|
-
const labelAvail = () => Math.max(6, panelWidth() - LEFT_PAD - suffixW());
|
|
1420
|
+
const labelAvail = () => Math.max(6, panelWidth() - gutter() - LEFT_PAD - suffixW());
|
|
1409
1421
|
const labelText = () => {
|
|
1410
1422
|
const max = labelAvail();
|
|
1411
1423
|
const text = entry.title || entry.agent;
|
|
@@ -1443,7 +1455,7 @@ function SubAgentPanel(props) {
|
|
|
1443
1455
|
const cancelLabel = () => ` ${t("cancel.label")}`;
|
|
1444
1456
|
const dismissLabel = () => ` ${t("dismiss.label")}`;
|
|
1445
1457
|
const rightW = (isRunning ? visualWidth(dismissLabel()) : 0) + (isRunning && entry.sessionId ? visualWidth(cancelLabel()) : 0);
|
|
1446
|
-
const spacerW = () => Math.max(1, panelWidth() - openW() - rightW - 2);
|
|
1458
|
+
const spacerW = () => Math.max(1, panelWidth() - gutter() - openW() - rightW - 2);
|
|
1447
1459
|
return (_jsxs("box", { flexDirection: "row", children: [_jsx(Show, { when: entry.sessionId, children: _jsxs("text", { onMouseOver: () => setHoveredOpen(entry.id), onMouseOut: () => setHoveredOpen(undefined), onMouseUp: () => {
|
|
1448
1460
|
if (entry.sessionId) {
|
|
1449
1461
|
props.api.route.navigate("session", { sessionID: entry.sessionId });
|
|
@@ -1461,7 +1473,7 @@ function SubAgentPanel(props) {
|
|
|
1461
1473
|
const right = props.sortOrder() === "desc"
|
|
1462
1474
|
? `\u2191 ${t("scroll.top")}`
|
|
1463
1475
|
: `\u2193 ${t("scroll.bottom")}`;
|
|
1464
|
-
const pad = showTop ? Math.max(1, panelWidth() - visualWidth(left) - visualWidth(right)) : 0;
|
|
1476
|
+
const pad = showTop ? Math.max(1, panelWidth() - gutter() - visualWidth(left) - visualWidth(right)) : 0;
|
|
1465
1477
|
return (_jsxs("box", { flexDirection: "row", children: [_jsx("text", { onMouseOver: () => showMore && setHoveredMoreBelow(true), onMouseOut: () => setHoveredMoreBelow(false), onMouseUp: () => {
|
|
1466
1478
|
if (!showMore)
|
|
1467
1479
|
return;
|
|
@@ -1494,7 +1506,7 @@ function createSidebarSlot(api, sig) {
|
|
|
1494
1506
|
slots: {
|
|
1495
1507
|
sidebar_content(ctx, input) {
|
|
1496
1508
|
sig.sessionId = input.session_id;
|
|
1497
|
-
return (_jsx(SubAgentPanel, { theme: ctx.theme.current, api: api, lang: sig.lang, maxEntries: sig.maxEntries, sortOrder: sig.sortOrder, scrollMode: sig.scrollMode, sessionId: input.session_id }));
|
|
1509
|
+
return (_jsx(SubAgentPanel, { theme: ctx.theme.current, api: api, lang: sig.lang, maxEntries: sig.maxEntries, sortOrder: sig.sortOrder, scrollMode: sig.scrollMode, borderVisible: sig.borderVisible, sessionId: input.session_id }));
|
|
1498
1510
|
},
|
|
1499
1511
|
},
|
|
1500
1512
|
};
|
|
@@ -1508,7 +1520,8 @@ const tui = async (api) => {
|
|
|
1508
1520
|
const [maxEntries, setMaxEntries] = createSignal(parseInt(String(api.kv.get(`${KV_PREFIX}.max_entries`, "10")), 10) || 10);
|
|
1509
1521
|
const [sortOrder, setSortOrder] = createSignal(String(api.kv.get(`${KV_PREFIX}.order`, "desc")) === "asc" ? "asc" : "desc");
|
|
1510
1522
|
const [scrollMode, setScrollMode] = createSignal(String(api.kv.get(`${KV_PREFIX}.scroll_mode`, "wheel")) === "click" ? "click" : "wheel");
|
|
1511
|
-
const
|
|
1523
|
+
const [borderVisible, setBorderVisible] = createSignal(api.kv.get(`${KV_PREFIX}.border`, false) === true);
|
|
1524
|
+
const signals = { lang, setLang, maxEntries, setMaxEntries, sortOrder, setSortOrder, scrollMode, setScrollMode, borderVisible, setBorderVisible, sessionId: "" };
|
|
1512
1525
|
api.slots.register(createSidebarSlot(api, signals));
|
|
1513
1526
|
// ── slash command: /subagent-lang ──
|
|
1514
1527
|
api.command?.register(() => [
|
|
@@ -1752,6 +1765,20 @@ const tui = async (api) => {
|
|
|
1752
1765
|
} })));
|
|
1753
1766
|
},
|
|
1754
1767
|
},
|
|
1768
|
+
{
|
|
1769
|
+
title: "SubAgent Magazine: Border",
|
|
1770
|
+
value: "subagent-border",
|
|
1771
|
+
description: "Show or hide the panel border",
|
|
1772
|
+
slash: { name: "subagent-border" },
|
|
1773
|
+
onSelect: (dialog) => {
|
|
1774
|
+
const t = createT(() => signals.lang());
|
|
1775
|
+
const cur = Boolean(api.kv.get(`${KV_PREFIX}.border`, false));
|
|
1776
|
+
api.kv.set(`${KV_PREFIX}.border`, !cur);
|
|
1777
|
+
signals.setBorderVisible(!cur);
|
|
1778
|
+
api.ui.toast({ message: !cur ? t("borderShown") : t("borderHidden") });
|
|
1779
|
+
dialog?.clear();
|
|
1780
|
+
},
|
|
1781
|
+
},
|
|
1755
1782
|
]);
|
|
1756
1783
|
};
|
|
1757
1784
|
const mod = {
|
package/dist/tui.js
CHANGED
|
@@ -4,14 +4,16 @@ import { insertNode as _$insertNode } from "@opentui/solid";
|
|
|
4
4
|
import { createComponent as _$createComponent } from "@opentui/solid";
|
|
5
5
|
import { effect as _$effect } from "@opentui/solid";
|
|
6
6
|
import { insert as _$insert } from "@opentui/solid";
|
|
7
|
-
import { memo as _$memo } from "@opentui/solid";
|
|
8
|
-
import { use as _$use } from "@opentui/solid";
|
|
9
7
|
import { setProp as _$setProp } from "@opentui/solid";
|
|
8
|
+
import { use as _$use } from "@opentui/solid";
|
|
9
|
+
import { spread as _$spread } from "@opentui/solid";
|
|
10
|
+
import { mergeProps as _$mergeProps } from "@opentui/solid";
|
|
11
|
+
import { memo as _$memo } from "@opentui/solid";
|
|
10
12
|
import { createElement as _$createElement } from "@opentui/solid";
|
|
11
13
|
import { createMemo, createSignal, createEffect, onMount, onCleanup, untrack, Show, For } from "solid-js";
|
|
12
14
|
|
|
13
15
|
// src/_version.ts
|
|
14
|
-
var PLUGIN_VERSION = "1.5.
|
|
16
|
+
var PLUGIN_VERSION = "1.5.3";
|
|
15
17
|
|
|
16
18
|
// src/clipboard.ts
|
|
17
19
|
import { spawn } from "node:child_process";
|
|
@@ -159,7 +161,9 @@ var ZH_T = {
|
|
|
159
161
|
"cancel.already_ended": "\u4F1A\u8BDD\u5DF2\u7ED3\u675F\uFF0C\u65E0\u9700\u53D6\u6D88",
|
|
160
162
|
"cancel.status_error": "\u65E0\u6CD5\u67E5\u8BE2\u4F1A\u8BDD\u72B6\u6001",
|
|
161
163
|
"cancel.sent": "\u5DF2\u53D1\u9001\u53D6\u6D88\u6307\u4EE4",
|
|
162
|
-
"cancel.failed": "\u53D6\u6D88\u5931\u8D25"
|
|
164
|
+
"cancel.failed": "\u53D6\u6D88\u5931\u8D25",
|
|
165
|
+
"borderShown": "\u9762\u677F\u8FB9\u6846 \u5DF2\u663E\u793A",
|
|
166
|
+
"borderHidden": "\u9762\u677F\u8FB9\u6846 \u5DF2\u9690\u85CF"
|
|
163
167
|
};
|
|
164
168
|
var EN_T = {
|
|
165
169
|
"panel.title": "SubAgent",
|
|
@@ -210,7 +214,9 @@ var EN_T = {
|
|
|
210
214
|
"cancel.already_ended": "Session already ended, no need to cancel",
|
|
211
215
|
"cancel.status_error": "Cannot query session status",
|
|
212
216
|
"cancel.sent": "Cancel instruction sent",
|
|
213
|
-
"cancel.failed": "Cancellation failed"
|
|
217
|
+
"cancel.failed": "Cancellation failed",
|
|
218
|
+
"borderShown": "Panel border shown",
|
|
219
|
+
"borderHidden": "Panel border hidden"
|
|
214
220
|
};
|
|
215
221
|
var JA_T = {
|
|
216
222
|
"panel.title": "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8",
|
|
@@ -261,7 +267,9 @@ var JA_T = {
|
|
|
261
267
|
"cancel.already_ended": "\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u65E2\u306B\u7D42\u4E86\u3057\u3066\u3044\u307E\u3059",
|
|
262
268
|
"cancel.status_error": "\u30BB\u30C3\u30B7\u30E7\u30F3\u72B6\u614B\u3092\u7167\u4F1A\u3067\u304D\u307E\u305B\u3093",
|
|
263
269
|
"cancel.sent": "\u30AD\u30E3\u30F3\u30BB\u30EB\u6307\u793A\u3092\u9001\u4FE1\u3057\u307E\u3057\u305F",
|
|
264
|
-
"cancel.failed": "\u30AD\u30E3\u30F3\u30BB\u30EB\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
|
|
270
|
+
"cancel.failed": "\u30AD\u30E3\u30F3\u30BB\u30EB\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
|
|
271
|
+
"borderShown": "\u30D1\u30CD\u30EB\u67A0\u7DDA \u8868\u793A",
|
|
272
|
+
"borderHidden": "\u30D1\u30CD\u30EB\u67A0\u7DDA \u975E\u8868\u793A"
|
|
265
273
|
};
|
|
266
274
|
var KO_T = {
|
|
267
275
|
"panel.title": "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8",
|
|
@@ -312,7 +320,9 @@ var KO_T = {
|
|
|
312
320
|
"cancel.already_ended": "\uC138\uC158\uC774 \uC774\uBBF8 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
|
|
313
321
|
"cancel.status_error": "\uC138\uC158 \uC0C1\uD0DC\uB97C \uC870\uD68C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
314
322
|
"cancel.sent": "\uCDE8\uC18C \uC9C0\uC2DC\uB97C \uBCF4\uB0C8\uC2B5\uB2C8\uB2E4",
|
|
315
|
-
"cancel.failed": "\uCDE8\uC18C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4"
|
|
323
|
+
"cancel.failed": "\uCDE8\uC18C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4",
|
|
324
|
+
"borderShown": "\uD328\uB110 \uD14C\uB450\uB9AC \uD45C\uC2DC",
|
|
325
|
+
"borderHidden": "\uD328\uB110 \uD14C\uB450\uB9AC \uC228\uAE40"
|
|
316
326
|
};
|
|
317
327
|
var LANGS = { zh: ZH_T, en: EN_T, ja: JA_T, ko: KO_T };
|
|
318
328
|
var LANG_META = [
|
|
@@ -1568,13 +1578,21 @@ function SubAgentPanel(props) {
|
|
|
1568
1578
|
return next;
|
|
1569
1579
|
});
|
|
1570
1580
|
};
|
|
1571
|
-
const
|
|
1581
|
+
const gutter = createMemo(() => props.borderVisible() ? 6 : 0);
|
|
1582
|
+
const sep = () => "\u2500".repeat(Math.max(1, panelWidth() - gutter()));
|
|
1583
|
+
createEffect(() => {
|
|
1584
|
+
props.borderVisible();
|
|
1585
|
+
if (boxEl && typeof boxEl.width === "number" && boxEl.width > 0) {
|
|
1586
|
+
const w = Math.max(20, boxEl.width);
|
|
1587
|
+
setPanelWidth((prev) => prev === w ? prev : w);
|
|
1588
|
+
}
|
|
1589
|
+
});
|
|
1572
1590
|
const expandedMaxLabelW = createMemo(() => {
|
|
1573
1591
|
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")];
|
|
1574
1592
|
return Math.max(...labels.map((l) => visualWidth(l + ": ")));
|
|
1575
1593
|
});
|
|
1576
1594
|
const expandedPad = (label) => Math.max(0, expandedMaxLabelW() - visualWidth(label + ": "));
|
|
1577
|
-
const expandedValAvail = () => Math.max(6, panelWidth() - INDENT - expandedMaxLabelW());
|
|
1595
|
+
const expandedValAvail = () => Math.max(6, panelWidth() - gutter() - INDENT - expandedMaxLabelW());
|
|
1578
1596
|
const summaryParts = createMemo(() => {
|
|
1579
1597
|
if (!anyEntry()) return null;
|
|
1580
1598
|
const dot = "\u25CF";
|
|
@@ -1603,7 +1621,7 @@ function SubAgentPanel(props) {
|
|
|
1603
1621
|
if (!open()) return false;
|
|
1604
1622
|
const icon = "\u25BC";
|
|
1605
1623
|
const need = visualWidth(icon) + 1 + visualWidth(t("panel.title")) + versionW + summaryCols();
|
|
1606
|
-
return need <= panelWidth();
|
|
1624
|
+
return need <= panelWidth() - gutter();
|
|
1607
1625
|
});
|
|
1608
1626
|
const leftCols = createMemo(() => {
|
|
1609
1627
|
const icon = open() ? "\u25BC" : "\u25B6";
|
|
@@ -1613,25 +1631,36 @@ function SubAgentPanel(props) {
|
|
|
1613
1631
|
});
|
|
1614
1632
|
const spacerCols = createMemo(() => {
|
|
1615
1633
|
if (!anyEntry()) return 0;
|
|
1616
|
-
return Math.max(0, panelWidth() - leftCols() - summaryCols());
|
|
1634
|
+
return Math.max(0, panelWidth() - gutter() - leftCols() - summaryCols());
|
|
1617
1635
|
});
|
|
1618
|
-
const valueCols = (label) => Math.max(4, panelWidth() - INDENT - visualWidth(label + ": "));
|
|
1636
|
+
const valueCols = (label) => Math.max(4, panelWidth() - gutter() - INDENT - visualWidth(label + ": "));
|
|
1619
1637
|
return (() => {
|
|
1620
1638
|
var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("span"), _el$4 = _$createElement("span");
|
|
1621
1639
|
_$insertNode(_el$, _el$2);
|
|
1622
1640
|
var _ref$ = boxEl;
|
|
1623
1641
|
typeof _ref$ === "function" ? _$use(_ref$, _el$) : boxEl = _el$;
|
|
1624
|
-
_$
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1642
|
+
_$spread(_el$, _$mergeProps({
|
|
1643
|
+
get border() {
|
|
1644
|
+
return props.borderVisible();
|
|
1645
|
+
}
|
|
1646
|
+
}, () => props.borderVisible() ? {
|
|
1647
|
+
borderColor: pal().border
|
|
1648
|
+
} : {}, {
|
|
1649
|
+
"paddingTop": 0,
|
|
1650
|
+
"paddingBottom": 0,
|
|
1651
|
+
get paddingLeft() {
|
|
1652
|
+
return props.borderVisible() ? 2 : 0;
|
|
1653
|
+
},
|
|
1654
|
+
get paddingRight() {
|
|
1655
|
+
return props.borderVisible() ? 2 : 0;
|
|
1656
|
+
},
|
|
1657
|
+
"flexDirection": "column",
|
|
1658
|
+
"gap": 0,
|
|
1659
|
+
"onSizeChange": () => {
|
|
1660
|
+
const w = boxEl ? Math.max(20, boxEl.width ?? 0) : 28;
|
|
1661
|
+
setPanelWidth((prev) => prev === w ? prev : w);
|
|
1662
|
+
}
|
|
1663
|
+
}), true);
|
|
1635
1664
|
_$insertNode(_el$2, _el$3);
|
|
1636
1665
|
_$insertNode(_el$2, _el$4);
|
|
1637
1666
|
_$setProp(_el$2, "onMouseUp", () => {
|
|
@@ -1828,7 +1857,7 @@ function SubAgentPanel(props) {
|
|
|
1828
1857
|
if (tk) w += visualWidth(tk);
|
|
1829
1858
|
return w;
|
|
1830
1859
|
};
|
|
1831
|
-
const labelAvail = () => Math.max(6, panelWidth() - LEFT_PAD - suffixW());
|
|
1860
|
+
const labelAvail = () => Math.max(6, panelWidth() - gutter() - LEFT_PAD - suffixW());
|
|
1832
1861
|
const labelText = () => {
|
|
1833
1862
|
const max2 = labelAvail();
|
|
1834
1863
|
const text = entry.title || entry.agent;
|
|
@@ -2227,7 +2256,7 @@ ${t("session.toast.copy_failed")}`,
|
|
|
2227
2256
|
const cancelLabel = () => ` ${t("cancel.label")}`;
|
|
2228
2257
|
const dismissLabel = () => ` ${t("dismiss.label")}`;
|
|
2229
2258
|
const rightW = (isRunning ? visualWidth(dismissLabel()) : 0) + (isRunning && entry.sessionId ? visualWidth(cancelLabel()) : 0);
|
|
2230
|
-
const spacerW = () => Math.max(1, panelWidth() - openW() - rightW - 2);
|
|
2259
|
+
const spacerW = () => Math.max(1, panelWidth() - gutter() - openW() - rightW - 2);
|
|
2231
2260
|
return (() => {
|
|
2232
2261
|
var _el$91 = _$createElement("box"), _el$95 = _$createElement("text");
|
|
2233
2262
|
_$insertNode(_el$91, _el$95);
|
|
@@ -2330,7 +2359,7 @@ ${t("session.toast.copy_failed")}`,
|
|
|
2330
2359
|
const showTop = props.sortOrder() === "desc" ? scrollOffset() > 0 : entryList().length > max() && clampedOffset() < entryList().length - max();
|
|
2331
2360
|
const left = showMore ? ` \u2193 ${hiddenBelow()} ${t("scroll.more")}` : " ";
|
|
2332
2361
|
const right = props.sortOrder() === "desc" ? `\u2191 ${t("scroll.top")}` : `\u2193 ${t("scroll.bottom")}`;
|
|
2333
|
-
const pad = showTop ? Math.max(1, panelWidth() - visualWidth(left) - visualWidth(right)) : 0;
|
|
2362
|
+
const pad = showTop ? Math.max(1, panelWidth() - gutter() - visualWidth(left) - visualWidth(right)) : 0;
|
|
2334
2363
|
return (() => {
|
|
2335
2364
|
var _el$100 = _$createElement("box"), _el$101 = _$createElement("text"), _el$102 = _$createElement("span");
|
|
2336
2365
|
_$insertNode(_el$100, _el$101);
|
|
@@ -2431,6 +2460,9 @@ function createSidebarSlot(api, sig) {
|
|
|
2431
2460
|
get scrollMode() {
|
|
2432
2461
|
return sig.scrollMode;
|
|
2433
2462
|
},
|
|
2463
|
+
get borderVisible() {
|
|
2464
|
+
return sig.borderVisible;
|
|
2465
|
+
},
|
|
2434
2466
|
get sessionId() {
|
|
2435
2467
|
return input.session_id;
|
|
2436
2468
|
}
|
|
@@ -2447,6 +2479,7 @@ var tui = async (api) => {
|
|
|
2447
2479
|
const [maxEntries, setMaxEntries] = createSignal(parseInt(String(api.kv.get(`${KV_PREFIX}.max_entries`, "10")), 10) || 10);
|
|
2448
2480
|
const [sortOrder, setSortOrder] = createSignal(String(api.kv.get(`${KV_PREFIX}.order`, "desc")) === "asc" ? "asc" : "desc");
|
|
2449
2481
|
const [scrollMode, setScrollMode] = createSignal(String(api.kv.get(`${KV_PREFIX}.scroll_mode`, "wheel")) === "click" ? "click" : "wheel");
|
|
2482
|
+
const [borderVisible, setBorderVisible] = createSignal(api.kv.get(`${KV_PREFIX}.border`, false) === true);
|
|
2450
2483
|
const signals = {
|
|
2451
2484
|
lang,
|
|
2452
2485
|
setLang,
|
|
@@ -2456,6 +2489,8 @@ var tui = async (api) => {
|
|
|
2456
2489
|
setSortOrder,
|
|
2457
2490
|
scrollMode,
|
|
2458
2491
|
setScrollMode,
|
|
2492
|
+
borderVisible,
|
|
2493
|
+
setBorderVisible,
|
|
2459
2494
|
sessionId: ""
|
|
2460
2495
|
};
|
|
2461
2496
|
api.slots.register(createSidebarSlot(api, signals));
|
|
@@ -2789,6 +2824,23 @@ var tui = async (api) => {
|
|
|
2789
2824
|
}
|
|
2790
2825
|
}));
|
|
2791
2826
|
}
|
|
2827
|
+
}, {
|
|
2828
|
+
title: "SubAgent Magazine: Border",
|
|
2829
|
+
value: "subagent-border",
|
|
2830
|
+
description: "Show or hide the panel border",
|
|
2831
|
+
slash: {
|
|
2832
|
+
name: "subagent-border"
|
|
2833
|
+
},
|
|
2834
|
+
onSelect: (dialog) => {
|
|
2835
|
+
const t = createT(() => signals.lang());
|
|
2836
|
+
const cur = Boolean(api.kv.get(`${KV_PREFIX}.border`, false));
|
|
2837
|
+
api.kv.set(`${KV_PREFIX}.border`, !cur);
|
|
2838
|
+
signals.setBorderVisible(!cur);
|
|
2839
|
+
api.ui.toast({
|
|
2840
|
+
message: !cur ? t("borderShown") : t("borderHidden")
|
|
2841
|
+
});
|
|
2842
|
+
dialog?.clear();
|
|
2843
|
+
}
|
|
2792
2844
|
}]);
|
|
2793
2845
|
};
|
|
2794
2846
|
var mod = {
|
package/package.json
CHANGED
package/src/_version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// auto-generated
|
|
2
|
-
export const PLUGIN_VERSION="1.5.
|
|
2
|
+
export const PLUGIN_VERSION="1.5.3";
|
package/src/i18n.ts
CHANGED
|
@@ -56,6 +56,8 @@ const ZH_T = {
|
|
|
56
56
|
"cancel.status_error": "无法查询会话状态",
|
|
57
57
|
"cancel.sent": "已发送取消指令",
|
|
58
58
|
"cancel.failed": "取消失败",
|
|
59
|
+
"borderShown": "面板边框 已显示",
|
|
60
|
+
"borderHidden": "面板边框 已隐藏",
|
|
59
61
|
} as const
|
|
60
62
|
|
|
61
63
|
/** 结构约束:值放宽为 string,键集合来自中文表(新增语言缺 key 会编译报错)。 */
|
|
@@ -111,6 +113,8 @@ const EN_T: Translation = {
|
|
|
111
113
|
"cancel.status_error": "Cannot query session status",
|
|
112
114
|
"cancel.sent": "Cancel instruction sent",
|
|
113
115
|
"cancel.failed": "Cancellation failed",
|
|
116
|
+
"borderShown": "Panel border shown",
|
|
117
|
+
"borderHidden": "Panel border hidden",
|
|
114
118
|
}
|
|
115
119
|
|
|
116
120
|
const JA_T: Translation = {
|
|
@@ -163,6 +167,8 @@ const JA_T: Translation = {
|
|
|
163
167
|
"cancel.status_error": "セッション状態を照会できません",
|
|
164
168
|
"cancel.sent": "キャンセル指示を送信しました",
|
|
165
169
|
"cancel.failed": "キャンセルに失敗しました",
|
|
170
|
+
"borderShown": "パネル枠線 表示",
|
|
171
|
+
"borderHidden": "パネル枠線 非表示",
|
|
166
172
|
}
|
|
167
173
|
|
|
168
174
|
const KO_T: Translation = {
|
|
@@ -215,6 +221,8 @@ const KO_T: Translation = {
|
|
|
215
221
|
"cancel.status_error": "세션 상태를 조회할 수 없습니다",
|
|
216
222
|
"cancel.sent": "취소 지시를 보냈습니다",
|
|
217
223
|
"cancel.failed": "취소에 실패했습니다",
|
|
224
|
+
"borderShown": "패널 테두리 표시",
|
|
225
|
+
"borderHidden": "패널 테두리 숨김",
|
|
218
226
|
}
|
|
219
227
|
|
|
220
228
|
export const LANGS: Record<LangCode, Translation> = { zh: ZH_T, en: EN_T, ja: JA_T, ko: KO_T }
|
package/src/index.tsx
CHANGED
|
@@ -214,6 +214,7 @@ function SubAgentPanel(props: {
|
|
|
214
214
|
maxEntries: () => number
|
|
215
215
|
sortOrder: () => SortOrder
|
|
216
216
|
scrollMode: () => ScrollMode
|
|
217
|
+
borderVisible: () => boolean
|
|
217
218
|
sessionId: string
|
|
218
219
|
}): JSX.Element {
|
|
219
220
|
const t = createT(() => props.lang())
|
|
@@ -1281,7 +1282,21 @@ function SubAgentPanel(props: {
|
|
|
1281
1282
|
})
|
|
1282
1283
|
}
|
|
1283
1284
|
|
|
1284
|
-
|
|
1285
|
+
/** Horizontal space eaten by the panel border (1+1) and its padding (2+2). */
|
|
1286
|
+
const gutter = createMemo(() => (props.borderVisible() ? 6 : 0))
|
|
1287
|
+
|
|
1288
|
+
const sep = () => "\u2500".repeat(Math.max(1, panelWidth() - gutter()))
|
|
1289
|
+
|
|
1290
|
+
// The border toggling shifts the box dimensions, which may not reliably
|
|
1291
|
+
// re-fire onSizeChange across (re)mount cycles; re-sync panelWidth with the
|
|
1292
|
+
// live box so the content width stays correct.
|
|
1293
|
+
createEffect(() => {
|
|
1294
|
+
props.borderVisible()
|
|
1295
|
+
if (boxEl && typeof boxEl.width === "number" && boxEl.width > 0) {
|
|
1296
|
+
const w = Math.max(20, boxEl.width)
|
|
1297
|
+
setPanelWidth((prev) => (prev === w ? prev : w))
|
|
1298
|
+
}
|
|
1299
|
+
})
|
|
1285
1300
|
|
|
1286
1301
|
// ── expanded detail right-align ──
|
|
1287
1302
|
const expandedMaxLabelW = createMemo(() => {
|
|
@@ -1294,7 +1309,7 @@ function SubAgentPanel(props: {
|
|
|
1294
1309
|
|
|
1295
1310
|
const expandedPad = (label: string) => Math.max(0, expandedMaxLabelW() - visualWidth(label + ": "))
|
|
1296
1311
|
|
|
1297
|
-
const expandedValAvail = () => Math.max(6, panelWidth() - INDENT - expandedMaxLabelW())
|
|
1312
|
+
const expandedValAvail = () => Math.max(6, panelWidth() - gutter() - INDENT - expandedMaxLabelW())
|
|
1298
1313
|
|
|
1299
1314
|
// ── header parts for colored spans ──
|
|
1300
1315
|
const summaryParts = createMemo(() => {
|
|
@@ -1328,7 +1343,7 @@ function SubAgentPanel(props: {
|
|
|
1328
1343
|
if (!open()) return false
|
|
1329
1344
|
const icon = "\u25bc"
|
|
1330
1345
|
const need = visualWidth(icon) + 1 + visualWidth(t("panel.title")) + versionW + summaryCols()
|
|
1331
|
-
return need <= panelWidth()
|
|
1346
|
+
return need <= panelWidth() - gutter()
|
|
1332
1347
|
})
|
|
1333
1348
|
|
|
1334
1349
|
const leftCols = createMemo(() => {
|
|
@@ -1340,17 +1355,19 @@ function SubAgentPanel(props: {
|
|
|
1340
1355
|
|
|
1341
1356
|
const spacerCols = createMemo(() => {
|
|
1342
1357
|
if (!anyEntry()) return 0
|
|
1343
|
-
return Math.max(0, panelWidth() - leftCols() - summaryCols())
|
|
1358
|
+
return Math.max(0, panelWidth() - gutter() - leftCols() - summaryCols())
|
|
1344
1359
|
})
|
|
1345
1360
|
|
|
1346
1361
|
const valueCols = (label: string) =>
|
|
1347
|
-
Math.max(4, panelWidth() - INDENT - visualWidth(label + ": "))
|
|
1362
|
+
Math.max(4, panelWidth() - gutter() - INDENT - visualWidth(label + ": "))
|
|
1348
1363
|
|
|
1349
1364
|
// ── render ──
|
|
1350
1365
|
return (
|
|
1351
1366
|
<box
|
|
1352
|
-
border={
|
|
1353
|
-
|
|
1367
|
+
border={props.borderVisible()}
|
|
1368
|
+
{...(props.borderVisible() ? { borderColor: pal().border } : {})}
|
|
1369
|
+
paddingTop={0} paddingBottom={0}
|
|
1370
|
+
paddingLeft={props.borderVisible() ? 2 : 0} paddingRight={props.borderVisible() ? 2 : 0}
|
|
1354
1371
|
flexDirection="column" gap={0}
|
|
1355
1372
|
ref={boxEl}
|
|
1356
1373
|
onSizeChange={() => {
|
|
@@ -1487,7 +1504,7 @@ function SubAgentPanel(props: {
|
|
|
1487
1504
|
if (tk) w += visualWidth(tk)
|
|
1488
1505
|
return w
|
|
1489
1506
|
}
|
|
1490
|
-
const labelAvail = () => Math.max(6, panelWidth() - LEFT_PAD - suffixW())
|
|
1507
|
+
const labelAvail = () => Math.max(6, panelWidth() - gutter() - LEFT_PAD - suffixW())
|
|
1491
1508
|
const labelText = () => {
|
|
1492
1509
|
const max = labelAvail()
|
|
1493
1510
|
const text = entry.title || entry.agent
|
|
@@ -1631,7 +1648,7 @@ function SubAgentPanel(props: {
|
|
|
1631
1648
|
const cancelLabel = () => ` ${t("cancel.label")}`
|
|
1632
1649
|
const dismissLabel = () => ` ${t("dismiss.label")}`
|
|
1633
1650
|
const rightW = (isRunning ? visualWidth(dismissLabel()) : 0) + (isRunning && entry.sessionId ? visualWidth(cancelLabel()) : 0)
|
|
1634
|
-
const spacerW = () => Math.max(1, panelWidth() - openW() - rightW - 2)
|
|
1651
|
+
const spacerW = () => Math.max(1, panelWidth() - gutter() - openW() - rightW - 2)
|
|
1635
1652
|
return (
|
|
1636
1653
|
<box flexDirection="row">
|
|
1637
1654
|
<Show when={entry.sessionId}>
|
|
@@ -1688,7 +1705,7 @@ function SubAgentPanel(props: {
|
|
|
1688
1705
|
const right = props.sortOrder() === "desc"
|
|
1689
1706
|
? `\u2191 ${t("scroll.top")}`
|
|
1690
1707
|
: `\u2193 ${t("scroll.bottom")}`
|
|
1691
|
-
const pad = showTop ? Math.max(1, panelWidth() - visualWidth(left) - visualWidth(right)) : 0
|
|
1708
|
+
const pad = showTop ? Math.max(1, panelWidth() - gutter() - visualWidth(left) - visualWidth(right)) : 0
|
|
1692
1709
|
return (
|
|
1693
1710
|
<box flexDirection="row">
|
|
1694
1711
|
<text
|
|
@@ -1753,6 +1770,8 @@ interface SharedSignals {
|
|
|
1753
1770
|
setSortOrder: (o: SortOrder) => void
|
|
1754
1771
|
scrollMode: () => ScrollMode
|
|
1755
1772
|
setScrollMode: (m: ScrollMode) => void
|
|
1773
|
+
borderVisible: () => boolean
|
|
1774
|
+
setBorderVisible: (v: boolean) => void
|
|
1756
1775
|
sessionId: string
|
|
1757
1776
|
}
|
|
1758
1777
|
|
|
@@ -1770,6 +1789,7 @@ function createSidebarSlot(api: TuiPluginApi, sig: SharedSignals): TuiSlotPlugin
|
|
|
1770
1789
|
maxEntries={sig.maxEntries}
|
|
1771
1790
|
sortOrder={sig.sortOrder}
|
|
1772
1791
|
scrollMode={sig.scrollMode}
|
|
1792
|
+
borderVisible={sig.borderVisible}
|
|
1773
1793
|
sessionId={input.session_id}
|
|
1774
1794
|
/>
|
|
1775
1795
|
)
|
|
@@ -1795,8 +1815,11 @@ const tui: TuiPlugin = async (api: TuiPluginApi) => {
|
|
|
1795
1815
|
const [scrollMode, setScrollMode] = createSignal<ScrollMode>(
|
|
1796
1816
|
String(api.kv.get(`${KV_PREFIX}.scroll_mode`, "wheel")) === "click" ? "click" : "wheel"
|
|
1797
1817
|
)
|
|
1818
|
+
const [borderVisible, setBorderVisible] = createSignal<boolean>(
|
|
1819
|
+
(api.kv.get(`${KV_PREFIX}.border`, false) as boolean) === true
|
|
1820
|
+
)
|
|
1798
1821
|
|
|
1799
|
-
const signals: SharedSignals = { lang, setLang, maxEntries, setMaxEntries, sortOrder, setSortOrder, scrollMode, setScrollMode, sessionId: "" }
|
|
1822
|
+
const signals: SharedSignals = { lang, setLang, maxEntries, setMaxEntries, sortOrder, setSortOrder, scrollMode, setScrollMode, borderVisible, setBorderVisible, sessionId: "" }
|
|
1800
1823
|
|
|
1801
1824
|
api.slots.register(createSidebarSlot(api, signals))
|
|
1802
1825
|
|
|
@@ -2070,6 +2093,20 @@ const tui: TuiPlugin = async (api: TuiPluginApi) => {
|
|
|
2070
2093
|
))
|
|
2071
2094
|
},
|
|
2072
2095
|
},
|
|
2096
|
+
{
|
|
2097
|
+
title: "SubAgent Magazine: Border",
|
|
2098
|
+
value: "subagent-border",
|
|
2099
|
+
description: "Show or hide the panel border",
|
|
2100
|
+
slash: { name: "subagent-border" },
|
|
2101
|
+
onSelect: (dialog) => {
|
|
2102
|
+
const t = createT(() => signals.lang())
|
|
2103
|
+
const cur = Boolean(api.kv.get(`${KV_PREFIX}.border`, false))
|
|
2104
|
+
api.kv.set(`${KV_PREFIX}.border`, !cur)
|
|
2105
|
+
signals.setBorderVisible(!cur)
|
|
2106
|
+
api.ui.toast({ message: !cur ? t("borderShown") : t("borderHidden") })
|
|
2107
|
+
dialog?.clear()
|
|
2108
|
+
},
|
|
2109
|
+
},
|
|
2073
2110
|
])
|
|
2074
2111
|
}
|
|
2075
2112
|
|