opencode-subagent-magazine 1.4.2 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_version.d.ts +1 -1
- package/dist/_version.js +1 -1
- package/dist/clipboard.d.ts +7 -0
- package/dist/clipboard.js +85 -0
- package/dist/i18n.d.ts +75 -0
- package/dist/i18n.js +249 -0
- package/dist/index.js +176 -138
- package/dist/tui.js +564 -172
- package/package.json +2 -1
- package/src/_version.ts +1 -1
- package/src/clipboard.ts +134 -0
- package/src/i18n.ts +261 -0
- package/src/index.tsx +202 -158
package/dist/tui.js
CHANGED
|
@@ -11,95 +11,340 @@ import { createElement as _$createElement } from "@opentui/solid";
|
|
|
11
11
|
import { createMemo, createSignal, createEffect, onMount, onCleanup, untrack, Show, For } from "solid-js";
|
|
12
12
|
|
|
13
13
|
// src/_version.ts
|
|
14
|
-
var PLUGIN_VERSION = "1.
|
|
14
|
+
var PLUGIN_VERSION = "1.5.1";
|
|
15
15
|
|
|
16
|
-
// src/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
"tokens.label": "tokens",
|
|
65
|
-
"error.label": "error",
|
|
66
|
-
"model.label": "model",
|
|
67
|
-
"todo.label": "todo",
|
|
68
|
-
"session.label": "session ID",
|
|
69
|
-
"session.toast.copy": "Copy the ID above manually",
|
|
70
|
-
"open.label": "Open session",
|
|
71
|
-
"cost.label": "cost",
|
|
72
|
-
"scroll.more": "more",
|
|
73
|
-
"scroll.top": "Top",
|
|
74
|
-
"scroll.bottom": "Bottom",
|
|
75
|
-
"dismiss.label": "dismiss",
|
|
76
|
-
"status.running": "running",
|
|
77
|
-
"status.done": "done",
|
|
78
|
-
"status.error": "error",
|
|
79
|
-
"order.desc": "Desc (newest first)",
|
|
80
|
-
"order.asc": "Asc (oldest first)",
|
|
81
|
-
"scroll.wheel": "Wheel Scroll",
|
|
82
|
-
"scroll.click": "Click Scroll",
|
|
83
|
-
"ttl.label": "TTL (Time to Live)",
|
|
84
|
-
"ttl.3d": "3 days",
|
|
85
|
-
"ttl.7d": "7 days",
|
|
86
|
-
"ttl.14d": "14 days",
|
|
87
|
-
"ttl.30d": "30 days",
|
|
88
|
-
"ttl.unlimited": "Never",
|
|
89
|
-
"ttl.toast": "TTL set to {n} days",
|
|
90
|
-
"ttl.toast_unlimited": "TTL set to Never",
|
|
91
|
-
"clear.title": "Confirm",
|
|
92
|
-
"clear.prompt": "Clear all sub-agent records for this session? This cannot be undone.",
|
|
93
|
-
"clear.prompt_running": "{n} sub-agent(s) are still running. Clearing will discard them permanently. Continue?",
|
|
94
|
-
"clear.done": "Cleared {n} sub-agent record(s)",
|
|
95
|
-
"clear.empty": "No sub-agent records in this session"
|
|
16
|
+
// src/clipboard.ts
|
|
17
|
+
import { spawn } from "node:child_process";
|
|
18
|
+
import { platform, release } from "node:os";
|
|
19
|
+
function runWithInput(command, args, input) {
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
const child = spawn(command, args, {
|
|
22
|
+
stdio: ["pipe", "ignore", "ignore"],
|
|
23
|
+
windowsHide: true
|
|
24
|
+
});
|
|
25
|
+
child.once("error", reject);
|
|
26
|
+
child.once("close", (code) => {
|
|
27
|
+
if (code === 0) resolve();
|
|
28
|
+
else reject(new Error(`${command} exited with code ${code}`));
|
|
29
|
+
});
|
|
30
|
+
child.stdin?.end(input);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function writeOsc52(text) {
|
|
34
|
+
if (!process.stdout.isTTY) return false;
|
|
35
|
+
const payload = Buffer.from(text, "utf8").toString("base64");
|
|
36
|
+
const sequence = `\x1B]52;c;${payload}\x07`;
|
|
37
|
+
const wrapped = process.env.TMUX || process.env.STY ? `\x1BPtmux;\x1B${sequence}\x1B\\` : sequence;
|
|
38
|
+
process.stdout.write(wrapped);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
async function tryCommand(method, command, args, text) {
|
|
42
|
+
try {
|
|
43
|
+
await runWithInput(command, args, text);
|
|
44
|
+
return { copied: true, method };
|
|
45
|
+
} catch {
|
|
46
|
+
return void 0;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function copyText(text) {
|
|
50
|
+
if (!text) return { copied: false, method: "none", error: "empty_text" };
|
|
51
|
+
const os = platform();
|
|
52
|
+
const isWsl = release().toLowerCase().includes("microsoft");
|
|
53
|
+
const attempts = [];
|
|
54
|
+
if (os === "darwin") {
|
|
55
|
+
attempts.push(() => tryCommand("pbcopy", "pbcopy", [], text));
|
|
56
|
+
attempts.push(
|
|
57
|
+
() => tryCommand(
|
|
58
|
+
"osascript",
|
|
59
|
+
"osascript",
|
|
60
|
+
["-e", 'set the clipboard to (read (POSIX file "/dev/stdin") as text)'],
|
|
61
|
+
text
|
|
62
|
+
)
|
|
63
|
+
);
|
|
96
64
|
}
|
|
65
|
+
if (os === "linux" && isWsl) {
|
|
66
|
+
attempts.push(
|
|
67
|
+
() => tryCommand(
|
|
68
|
+
"powershell",
|
|
69
|
+
"powershell.exe",
|
|
70
|
+
[
|
|
71
|
+
"-NonInteractive",
|
|
72
|
+
"-NoProfile",
|
|
73
|
+
"-Command",
|
|
74
|
+
"[Console]::InputEncoding=[Text.Encoding]::UTF8; Set-Clipboard ([Console]::In.ReadToEnd())"
|
|
75
|
+
],
|
|
76
|
+
text
|
|
77
|
+
)
|
|
78
|
+
);
|
|
79
|
+
} else if (os === "linux") {
|
|
80
|
+
if (process.env.WAYLAND_DISPLAY) {
|
|
81
|
+
attempts.push(() => tryCommand("wl-copy", "wl-copy", [], text));
|
|
82
|
+
}
|
|
83
|
+
attempts.push(() => tryCommand("xclip", "xclip", ["-selection", "clipboard"], text));
|
|
84
|
+
attempts.push(() => tryCommand("xsel", "xsel", ["--clipboard", "--input"], text));
|
|
85
|
+
}
|
|
86
|
+
if (os === "win32") {
|
|
87
|
+
attempts.push(
|
|
88
|
+
() => tryCommand(
|
|
89
|
+
"powershell",
|
|
90
|
+
"powershell.exe",
|
|
91
|
+
[
|
|
92
|
+
"-NonInteractive",
|
|
93
|
+
"-NoProfile",
|
|
94
|
+
"-Command",
|
|
95
|
+
"[Console]::InputEncoding=[Text.Encoding]::UTF8; Set-Clipboard ([Console]::In.ReadToEnd())"
|
|
96
|
+
],
|
|
97
|
+
text
|
|
98
|
+
)
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
for (const attempt of attempts) {
|
|
102
|
+
const result = await attempt();
|
|
103
|
+
if (result) return result;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
if (writeOsc52(text)) return { copied: true, method: "osc52" };
|
|
107
|
+
} catch {
|
|
108
|
+
}
|
|
109
|
+
return { copied: false, method: "none", error: "clipboard_unavailable" };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// src/i18n.ts
|
|
113
|
+
var ZH_T = {
|
|
114
|
+
"panel.title": "\u5B50\u4EE3\u7406",
|
|
115
|
+
"status.none": "\u6682\u65E0\u5B50\u4EE3\u7406",
|
|
116
|
+
"agent.label": "\u4EE3\u7406",
|
|
117
|
+
"status.label": "\u72B6\u6001",
|
|
118
|
+
"time.label": "\u8017\u65F6",
|
|
119
|
+
"tokens.label": "\u4E0A\u4E0B\u6587",
|
|
120
|
+
"error.label": "\u9519\u8BEF",
|
|
121
|
+
"model.label": "\u6A21\u578B",
|
|
122
|
+
"todo.label": "\u8FDB\u5EA6",
|
|
123
|
+
"session.label": "\u4F1A\u8BDD ID",
|
|
124
|
+
"session.toast.copy": "\u53EF\u624B\u52A8\u590D\u5236\u4E0A\u65B9 ID",
|
|
125
|
+
"session.toast.copied": "\u4F1A\u8BDD ID \u5DF2\u590D\u5236",
|
|
126
|
+
"session.toast.copy_failed": "\u65E0\u6CD5\u8BBF\u95EE\u7CFB\u7EDF\u526A\u8D34\u677F\uFF0C\u8BF7\u624B\u52A8\u590D\u5236\u4E0A\u65B9 ID",
|
|
127
|
+
"open.label": "\u8FDB\u5165\u4F1A\u8BDD",
|
|
128
|
+
"cost.label": "\u8D39\u7528",
|
|
129
|
+
"scroll.more": "\u66F4\u591A",
|
|
130
|
+
"scroll.top": "\u56DE\u9876",
|
|
131
|
+
"scroll.bottom": "\u56DE\u5E95",
|
|
132
|
+
"dismiss.label": "\u6807\u8BB0\u5B8C\u6210",
|
|
133
|
+
"cancel.label": "\u53D6\u6D88",
|
|
134
|
+
"status.running": "\u8FD0\u884C\u4E2D",
|
|
135
|
+
"status.done": "\u5DF2\u5B8C\u6210",
|
|
136
|
+
"status.cancelled": "\u5DF2\u53D6\u6D88",
|
|
137
|
+
"status.error": "\u9519\u8BEF",
|
|
138
|
+
"order.desc": "\u964D\u5E8F\uFF08\u6700\u65B0\u5728\u524D\uFF09",
|
|
139
|
+
"order.asc": "\u5347\u5E8F\uFF08\u6700\u65E9\u5728\u524D\uFF09",
|
|
140
|
+
"scroll.wheel": "\u6EDA\u8F6E\u7FFB\u9875",
|
|
141
|
+
"scroll.click": "\u70B9\u51FB\u7FFB\u9875",
|
|
142
|
+
"ttl.label": "\u6E05\u7406\u5468\u671F",
|
|
143
|
+
"ttl.3d": "3 \u5929",
|
|
144
|
+
"ttl.7d": "7 \u5929",
|
|
145
|
+
"ttl.14d": "14 \u5929",
|
|
146
|
+
"ttl.30d": "30 \u5929",
|
|
147
|
+
"ttl.unlimited": "\u65E0\u671F\u9650",
|
|
148
|
+
"ttl.toast": "\u6E05\u7406\u5468\u671F\u5DF2\u8BBE\u4E3A {n} \u5929",
|
|
149
|
+
"ttl.toast_unlimited": "\u6E05\u7406\u5468\u671F\u5DF2\u8BBE\u4E3A\u65E0\u671F\u9650",
|
|
150
|
+
"clear.title": "\u786E\u8BA4\u6E05\u9664",
|
|
151
|
+
"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",
|
|
152
|
+
"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",
|
|
153
|
+
"clear.done": "\u5DF2\u6E05\u9664 {n} \u6761\u5B50\u4EE3\u7406\u8BB0\u5F55",
|
|
154
|
+
"clear.empty": "\u5F53\u524D\u4F1A\u8BDD\u65E0\u5B50\u4EE3\u7406\u8BB0\u5F55",
|
|
155
|
+
"cancel.no_session": "\u5B50\u4F1A\u8BDD ID \u4E0D\u53EF\u7528",
|
|
156
|
+
"cancel.not_child": "\u76EE\u6807\u4E0D\u662F\u5B50\u4F1A\u8BDD",
|
|
157
|
+
"cancel.read_error": "\u65E0\u6CD5\u8BFB\u53D6\u4F1A\u8BDD\u4FE1\u606F",
|
|
158
|
+
"cancel.outside_tree": "\u76EE\u6807\u4E0D\u5728\u5F53\u524D\u76D1\u63A7\u4F1A\u8BDD\u6811\u4E2D",
|
|
159
|
+
"cancel.already_ended": "\u4F1A\u8BDD\u5DF2\u7ED3\u675F\uFF0C\u65E0\u9700\u53D6\u6D88",
|
|
160
|
+
"cancel.status_error": "\u65E0\u6CD5\u67E5\u8BE2\u4F1A\u8BDD\u72B6\u6001",
|
|
161
|
+
"cancel.sent": "\u5DF2\u53D1\u9001\u53D6\u6D88\u6307\u4EE4",
|
|
162
|
+
"cancel.failed": "\u53D6\u6D88\u5931\u8D25"
|
|
163
|
+
};
|
|
164
|
+
var EN_T = {
|
|
165
|
+
"panel.title": "SubAgent",
|
|
166
|
+
"status.none": "No sub-agents yet",
|
|
167
|
+
"agent.label": "agent",
|
|
168
|
+
"status.label": "status",
|
|
169
|
+
"time.label": "time",
|
|
170
|
+
"tokens.label": "tokens",
|
|
171
|
+
"error.label": "error",
|
|
172
|
+
"model.label": "model",
|
|
173
|
+
"todo.label": "todo",
|
|
174
|
+
"session.label": "session ID",
|
|
175
|
+
"session.toast.copy": "Copy the ID above manually",
|
|
176
|
+
"session.toast.copied": "Session ID copied",
|
|
177
|
+
"session.toast.copy_failed": "Cannot access the system clipboard; copy the ID above manually",
|
|
178
|
+
"open.label": "Open session",
|
|
179
|
+
"cost.label": "cost",
|
|
180
|
+
"scroll.more": "more",
|
|
181
|
+
"scroll.top": "Top",
|
|
182
|
+
"scroll.bottom": "Bottom",
|
|
183
|
+
"dismiss.label": "dismiss",
|
|
184
|
+
"cancel.label": "Cancel",
|
|
185
|
+
"status.running": "running",
|
|
186
|
+
"status.done": "done",
|
|
187
|
+
"status.cancelled": "cancelled",
|
|
188
|
+
"status.error": "error",
|
|
189
|
+
"order.desc": "Desc (newest first)",
|
|
190
|
+
"order.asc": "Asc (oldest first)",
|
|
191
|
+
"scroll.wheel": "Wheel Scroll",
|
|
192
|
+
"scroll.click": "Click Scroll",
|
|
193
|
+
"ttl.label": "TTL (Time to Live)",
|
|
194
|
+
"ttl.3d": "3 days",
|
|
195
|
+
"ttl.7d": "7 days",
|
|
196
|
+
"ttl.14d": "14 days",
|
|
197
|
+
"ttl.30d": "30 days",
|
|
198
|
+
"ttl.unlimited": "Never",
|
|
199
|
+
"ttl.toast": "TTL set to {n} days",
|
|
200
|
+
"ttl.toast_unlimited": "TTL set to Never",
|
|
201
|
+
"clear.title": "Confirm",
|
|
202
|
+
"clear.prompt": "Clear all sub-agent records for this session? This cannot be undone.",
|
|
203
|
+
"clear.prompt_running": "{n} sub-agent(s) are still running. Clearing will discard them permanently. Continue?",
|
|
204
|
+
"clear.done": "Cleared {n} sub-agent record(s)",
|
|
205
|
+
"clear.empty": "No sub-agent records in this session",
|
|
206
|
+
"cancel.no_session": "Child session ID is unavailable",
|
|
207
|
+
"cancel.not_child": "Target is not a child session",
|
|
208
|
+
"cancel.read_error": "Cannot read session info",
|
|
209
|
+
"cancel.outside_tree": "Target is outside the monitored session tree",
|
|
210
|
+
"cancel.already_ended": "Session already ended, no need to cancel",
|
|
211
|
+
"cancel.status_error": "Cannot query session status",
|
|
212
|
+
"cancel.sent": "Cancel instruction sent",
|
|
213
|
+
"cancel.failed": "Cancellation failed"
|
|
214
|
+
};
|
|
215
|
+
var JA_T = {
|
|
216
|
+
"panel.title": "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8",
|
|
217
|
+
"status.none": "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u306A\u3057",
|
|
218
|
+
"agent.label": "\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8",
|
|
219
|
+
"status.label": "\u72B6\u614B",
|
|
220
|
+
"time.label": "\u6642\u9593",
|
|
221
|
+
"tokens.label": "\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8",
|
|
222
|
+
"error.label": "\u30A8\u30E9\u30FC",
|
|
223
|
+
"model.label": "\u30E2\u30C7\u30EB",
|
|
224
|
+
"todo.label": "\u9032\u6357",
|
|
225
|
+
"session.label": "\u30BB\u30C3\u30B7\u30E7\u30F3 ID",
|
|
226
|
+
"session.toast.copy": "\u4E0A\u306E ID \u3092\u624B\u52D5\u3067\u30B3\u30D4\u30FC\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
227
|
+
"session.toast.copied": "\u30BB\u30C3\u30B7\u30E7\u30F3 ID \u3092\u30B3\u30D4\u30FC\u3057\u307E\u3057\u305F",
|
|
228
|
+
"session.toast.copy_failed": "\u30B7\u30B9\u30C6\u30E0\u306E\u30AF\u30EA\u30C3\u30D7\u30DC\u30FC\u30C9\u306B\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u4E0A\u306E ID \u3092\u624B\u52D5\u3067\u30B3\u30D4\u30FC\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
229
|
+
"open.label": "\u30BB\u30C3\u30B7\u30E7\u30F3\u3092\u958B\u304F",
|
|
230
|
+
"cost.label": "\u8CBB\u7528",
|
|
231
|
+
"scroll.more": "\u3082\u3063\u3068",
|
|
232
|
+
"scroll.top": "\u5148\u982D\u3078",
|
|
233
|
+
"scroll.bottom": "\u672B\u5C3E\u3078",
|
|
234
|
+
"dismiss.label": "\u5B8C\u4E86\u306B\u3059\u308B",
|
|
235
|
+
"cancel.label": "\u30AD\u30E3\u30F3\u30BB\u30EB",
|
|
236
|
+
"status.running": "\u5B9F\u884C\u4E2D",
|
|
237
|
+
"status.done": "\u5B8C\u4E86",
|
|
238
|
+
"status.cancelled": "\u30AD\u30E3\u30F3\u30BB\u30EB\u6E08\u307F",
|
|
239
|
+
"status.error": "\u30A8\u30E9\u30FC",
|
|
240
|
+
"order.desc": "\u964D\u9806\uFF08\u65B0\u3057\u3044\u9806\uFF09",
|
|
241
|
+
"order.asc": "\u6607\u9806\uFF08\u53E4\u3044\u9806\uFF09",
|
|
242
|
+
"scroll.wheel": "\u30DB\u30A4\u30FC\u30EB\u30B9\u30AF\u30ED\u30FC\u30EB",
|
|
243
|
+
"scroll.click": "\u30AF\u30EA\u30C3\u30AF\u30B9\u30AF\u30ED\u30FC\u30EB",
|
|
244
|
+
"ttl.label": "\u4FDD\u6301\u671F\u9593",
|
|
245
|
+
"ttl.3d": "3 \u65E5",
|
|
246
|
+
"ttl.7d": "7 \u65E5",
|
|
247
|
+
"ttl.14d": "14 \u65E5",
|
|
248
|
+
"ttl.30d": "30 \u65E5",
|
|
249
|
+
"ttl.unlimited": "\u7121\u671F\u9650",
|
|
250
|
+
"ttl.toast": "\u4FDD\u6301\u671F\u9593\u3092 {n} \u65E5\u306B\u8A2D\u5B9A\u3057\u307E\u3057\u305F",
|
|
251
|
+
"ttl.toast_unlimited": "\u4FDD\u6301\u671F\u9593\u3092\u7121\u671F\u9650\u306B\u8A2D\u5B9A\u3057\u307E\u3057\u305F",
|
|
252
|
+
"clear.title": "\u524A\u9664\u306E\u78BA\u8A8D",
|
|
253
|
+
"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",
|
|
254
|
+
"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",
|
|
255
|
+
"clear.done": "{n} \u4EF6\u306E\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u8A18\u9332\u3092\u524A\u9664\u3057\u307E\u3057\u305F",
|
|
256
|
+
"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",
|
|
257
|
+
"cancel.no_session": "\u5B50\u30BB\u30C3\u30B7\u30E7\u30F3 ID \u304C\u5229\u7528\u3067\u304D\u307E\u305B\u3093",
|
|
258
|
+
"cancel.not_child": "\u5BFE\u8C61\u306F\u5B50\u30BB\u30C3\u30B7\u30E7\u30F3\u3067\u306F\u3042\u308A\u307E\u305B\u3093",
|
|
259
|
+
"cancel.read_error": "\u30BB\u30C3\u30B7\u30E7\u30F3\u60C5\u5831\u3092\u8AAD\u307F\u53D6\u308C\u307E\u305B\u3093",
|
|
260
|
+
"cancel.outside_tree": "\u5BFE\u8C61\u306F\u76E3\u8996\u5BFE\u8C61\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u30C4\u30EA\u30FC\u5916\u3067\u3059",
|
|
261
|
+
"cancel.already_ended": "\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u65E2\u306B\u7D42\u4E86\u3057\u3066\u3044\u307E\u3059",
|
|
262
|
+
"cancel.status_error": "\u30BB\u30C3\u30B7\u30E7\u30F3\u72B6\u614B\u3092\u7167\u4F1A\u3067\u304D\u307E\u305B\u3093",
|
|
263
|
+
"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"
|
|
265
|
+
};
|
|
266
|
+
var KO_T = {
|
|
267
|
+
"panel.title": "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8",
|
|
268
|
+
"status.none": "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uC5C6\uC74C",
|
|
269
|
+
"agent.label": "\uC5D0\uC774\uC804\uD2B8",
|
|
270
|
+
"status.label": "\uC0C1\uD0DC",
|
|
271
|
+
"time.label": "\uC2DC\uAC04",
|
|
272
|
+
"tokens.label": "\uCEE8\uD14D\uC2A4\uD2B8",
|
|
273
|
+
"error.label": "\uC624\uB958",
|
|
274
|
+
"model.label": "\uBAA8\uB378",
|
|
275
|
+
"todo.label": "\uC9C4\uD589\uB3C4",
|
|
276
|
+
"session.label": "\uC138\uC158 ID",
|
|
277
|
+
"session.toast.copy": "\uC704 ID\uB97C \uC218\uB3D9\uC73C\uB85C \uBCF5\uC0AC\uD558\uC138\uC694",
|
|
278
|
+
"session.toast.copied": "\uC138\uC158 ID\uAC00 \uBCF5\uC0AC\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
|
|
279
|
+
"session.toast.copy_failed": "\uC2DC\uC2A4\uD15C \uD074\uB9BD\uBCF4\uB4DC\uC5D0 \uC811\uADFC\uD560 \uC218 \uC5C6\uC5B4 \uC704 ID\uB97C \uC218\uB3D9\uC73C\uB85C \uBCF5\uC0AC\uD558\uC138\uC694",
|
|
280
|
+
"open.label": "\uC138\uC158 \uC5F4\uAE30",
|
|
281
|
+
"cost.label": "\uBE44\uC6A9",
|
|
282
|
+
"scroll.more": "\uB354 \uBCF4\uAE30",
|
|
283
|
+
"scroll.top": "\uB9E8 \uC704\uB85C",
|
|
284
|
+
"scroll.bottom": "\uB9E8 \uC544\uB798\uB85C",
|
|
285
|
+
"dismiss.label": "\uC644\uB8CC \uD45C\uC2DC",
|
|
286
|
+
"cancel.label": "\uCDE8\uC18C",
|
|
287
|
+
"status.running": "\uC2E4\uD589 \uC911",
|
|
288
|
+
"status.done": "\uC644\uB8CC",
|
|
289
|
+
"status.cancelled": "\uCDE8\uC18C\uB428",
|
|
290
|
+
"status.error": "\uC624\uB958",
|
|
291
|
+
"order.desc": "\uB0B4\uB9BC\uCC28\uC21C(\uCD5C\uC2E0\uC21C)",
|
|
292
|
+
"order.asc": "\uC624\uB984\uCC28\uC21C(\uC624\uB798\uB41C\uC21C)",
|
|
293
|
+
"scroll.wheel": "\uD720 \uC2A4\uD06C\uB864",
|
|
294
|
+
"scroll.click": "\uD074\uB9AD \uC2A4\uD06C\uB864",
|
|
295
|
+
"ttl.label": "\uBCF4\uC874 \uAE30\uAC04",
|
|
296
|
+
"ttl.3d": "3\uC77C",
|
|
297
|
+
"ttl.7d": "7\uC77C",
|
|
298
|
+
"ttl.14d": "14\uC77C",
|
|
299
|
+
"ttl.30d": "30\uC77C",
|
|
300
|
+
"ttl.unlimited": "\uBB34\uAE30\uD55C",
|
|
301
|
+
"ttl.toast": "\uBCF4\uC874 \uAE30\uAC04\uC744 {n}\uC77C\uB85C \uC124\uC815\uD588\uC2B5\uB2C8\uB2E4",
|
|
302
|
+
"ttl.toast_unlimited": "\uBCF4\uC874 \uAE30\uAC04\uC744 \uBB34\uAE30\uD55C\uC73C\uB85C \uC124\uC815\uD588\uC2B5\uB2C8\uB2E4",
|
|
303
|
+
"clear.title": "\uC0AD\uC81C \uD655\uC778",
|
|
304
|
+
"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.",
|
|
305
|
+
"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?",
|
|
306
|
+
"clear.done": "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uAE30\uB85D {n}\uAC1C\uB97C \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4",
|
|
307
|
+
"clear.empty": "\uC774 \uC138\uC158\uC5D0 \uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uAE30\uB85D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
308
|
+
"cancel.no_session": "\uD558\uC704 \uC138\uC158 ID\uB97C \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
309
|
+
"cancel.not_child": "\uB300\uC0C1\uC774 \uD558\uC704 \uC138\uC158\uC774 \uC544\uB2D9\uB2C8\uB2E4",
|
|
310
|
+
"cancel.read_error": "\uC138\uC158 \uC815\uBCF4\uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
311
|
+
"cancel.outside_tree": "\uB300\uC0C1\uC774 \uBAA8\uB2C8\uD130\uB9C1 \uC138\uC158 \uD2B8\uB9AC \uBC16\uC5D0 \uC788\uC2B5\uB2C8\uB2E4",
|
|
312
|
+
"cancel.already_ended": "\uC138\uC158\uC774 \uC774\uBBF8 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
|
|
313
|
+
"cancel.status_error": "\uC138\uC158 \uC0C1\uD0DC\uB97C \uC870\uD68C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
314
|
+
"cancel.sent": "\uCDE8\uC18C \uC9C0\uC2DC\uB97C \uBCF4\uB0C8\uC2B5\uB2C8\uB2E4",
|
|
315
|
+
"cancel.failed": "\uCDE8\uC18C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4"
|
|
97
316
|
};
|
|
317
|
+
var LANGS = { zh: ZH_T, en: EN_T, ja: JA_T, ko: KO_T };
|
|
318
|
+
var LANG_META = [
|
|
319
|
+
{ code: "zh", label: "\u4E2D\u6587" },
|
|
320
|
+
{ code: "en", label: "English" },
|
|
321
|
+
{ code: "ja", label: "\u65E5\u672C\u8A9E" },
|
|
322
|
+
{ code: "ko", label: "\uD55C\uAD6D\uC5B4" }
|
|
323
|
+
];
|
|
324
|
+
function applyParams(tpl, params) {
|
|
325
|
+
if (!params) return tpl;
|
|
326
|
+
return tpl.replace(
|
|
327
|
+
/\{(\w+)\}/g,
|
|
328
|
+
(m, k) => k in params ? String(params[k]) : m
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
function createT(getCode) {
|
|
332
|
+
return (key, params) => applyParams(LANGS[getCode()][key] ?? key, params);
|
|
333
|
+
}
|
|
98
334
|
function detectLang() {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
335
|
+
try {
|
|
336
|
+
const loc = Intl.DateTimeFormat().resolvedOptions().locale.toLowerCase();
|
|
337
|
+
if (loc.startsWith("zh")) return "zh";
|
|
338
|
+
if (loc.startsWith("ja")) return "ja";
|
|
339
|
+
if (loc.startsWith("ko")) return "ko";
|
|
340
|
+
return "en";
|
|
341
|
+
} catch {
|
|
342
|
+
return "en";
|
|
343
|
+
}
|
|
102
344
|
}
|
|
345
|
+
|
|
346
|
+
// src/index.tsx
|
|
347
|
+
var SUBAGENT_TOOLS = /* @__PURE__ */ new Set(["task", "delegate", "call_omo_agent"]);
|
|
103
348
|
function charColumns(c) {
|
|
104
349
|
const code = c.codePointAt(0) ?? 0;
|
|
105
350
|
if (code < 32) return 0;
|
|
@@ -219,7 +464,7 @@ function safeErrorMsg(err) {
|
|
|
219
464
|
var globalEntryCache = /* @__PURE__ */ new Map();
|
|
220
465
|
var [clearTick, setClearTick] = createSignal(0);
|
|
221
466
|
function SubAgentPanel(props) {
|
|
222
|
-
const t = (
|
|
467
|
+
const t = createT(() => props.lang());
|
|
223
468
|
const SESSION_DATA_KEY = `${KV_PREFIX}.session_data`;
|
|
224
469
|
const ttlDaysRaw = parseInt(String(props.api.kv.get(`${KV_PREFIX}.ttl_days`, "3")), 10);
|
|
225
470
|
const ttlDays = Number.isNaN(ttlDaysRaw) ? 3 : ttlDaysRaw;
|
|
@@ -410,7 +655,7 @@ function SubAgentPanel(props) {
|
|
|
410
655
|
let needsImmediateFlush = false;
|
|
411
656
|
for (const [id, entry] of next) {
|
|
412
657
|
const prevEntry = prev.get(id);
|
|
413
|
-
if (prevEntry?.status === "running" && (entry.status === "done" || entry.status === "error")) {
|
|
658
|
+
if (prevEntry?.status === "running" && (entry.status === "done" || entry.status === "error" || entry.status === "cancelled")) {
|
|
414
659
|
needsImmediateFlush = true;
|
|
415
660
|
break;
|
|
416
661
|
}
|
|
@@ -481,6 +726,7 @@ function SubAgentPanel(props) {
|
|
|
481
726
|
})());
|
|
482
727
|
const [hoveredOpen, setHoveredOpen] = createSignal(void 0);
|
|
483
728
|
const [hoveredDismiss, setHoveredDismiss] = createSignal(void 0);
|
|
729
|
+
const [hoveredCancel, setHoveredCancel] = createSignal(void 0);
|
|
484
730
|
const [hoveredTop, setHoveredTop] = createSignal(false);
|
|
485
731
|
const [hoveredMoreAbove, setHoveredMoreAbove] = createSignal(false);
|
|
486
732
|
const [hoveredMoreBelow, setHoveredMoreBelow] = createSignal(false);
|
|
@@ -574,7 +820,7 @@ function SubAgentPanel(props) {
|
|
|
574
820
|
const next = new Map(prev);
|
|
575
821
|
const nowTs = Date.now();
|
|
576
822
|
const e = partial.status;
|
|
577
|
-
const ended = e === "done" || e === "error";
|
|
823
|
+
const ended = e === "done" || e === "error" || e === "cancelled";
|
|
578
824
|
next.set(partial.id, {
|
|
579
825
|
...existing ?? {
|
|
580
826
|
startedAt: nowTs
|
|
@@ -586,6 +832,123 @@ function SubAgentPanel(props) {
|
|
|
586
832
|
return next;
|
|
587
833
|
});
|
|
588
834
|
};
|
|
835
|
+
const isDescendantOf = (childId, rootId) => {
|
|
836
|
+
const visited = /* @__PURE__ */ new Set();
|
|
837
|
+
try {
|
|
838
|
+
let current = props.api.state.session.get(childId);
|
|
839
|
+
while (current?.parentID) {
|
|
840
|
+
if (visited.has(current.id)) return false;
|
|
841
|
+
visited.add(current.id);
|
|
842
|
+
if (current.parentID === rootId) return true;
|
|
843
|
+
current = props.api.state.session.get(current.parentID);
|
|
844
|
+
}
|
|
845
|
+
} catch {
|
|
846
|
+
}
|
|
847
|
+
return false;
|
|
848
|
+
};
|
|
849
|
+
const settleOnIdle = (entry) => {
|
|
850
|
+
if (entry.status === "cancel_requested" && entry.abortAccepted) return "cancelled";
|
|
851
|
+
return "done";
|
|
852
|
+
};
|
|
853
|
+
const cancelEntry = async (entry) => {
|
|
854
|
+
const childId = entry.sessionId;
|
|
855
|
+
if (!childId) {
|
|
856
|
+
props.api.ui.toast({
|
|
857
|
+
title: entry.title || entry.agent,
|
|
858
|
+
message: t("cancel.label") + ": " + t("cancel.no_session")
|
|
859
|
+
});
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
try {
|
|
863
|
+
const child = props.api.state.session.get(childId);
|
|
864
|
+
if (!child?.parentID) {
|
|
865
|
+
props.api.ui.toast({
|
|
866
|
+
title: entry.title || entry.agent,
|
|
867
|
+
message: t("cancel.label") + ": " + t("cancel.not_child")
|
|
868
|
+
});
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
} catch {
|
|
872
|
+
props.api.ui.toast({
|
|
873
|
+
title: entry.title || entry.agent,
|
|
874
|
+
message: t("cancel.label") + ": " + t("cancel.read_error")
|
|
875
|
+
});
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
if (!isDescendantOf(childId, props.sessionId)) {
|
|
879
|
+
props.api.ui.toast({
|
|
880
|
+
title: entry.title || entry.agent,
|
|
881
|
+
message: t("cancel.label") + ": " + t("cancel.outside_tree")
|
|
882
|
+
});
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
try {
|
|
886
|
+
const st = props.api.state.session.status(childId);
|
|
887
|
+
if (st?.type !== "busy") {
|
|
888
|
+
const tokens = readSessionTokens(childId);
|
|
889
|
+
const cost = readSessionCost(childId);
|
|
890
|
+
upsertEntry({
|
|
891
|
+
id: entry.id,
|
|
892
|
+
title: entry.title,
|
|
893
|
+
agent: entry.agent,
|
|
894
|
+
prompt: entry.prompt,
|
|
895
|
+
status: "done",
|
|
896
|
+
sessionId: entry.sessionId,
|
|
897
|
+
tokens,
|
|
898
|
+
cost
|
|
899
|
+
});
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
} catch {
|
|
903
|
+
props.api.ui.toast({
|
|
904
|
+
title: entry.title || entry.agent,
|
|
905
|
+
message: t("cancel.label") + ": " + t("cancel.status_error")
|
|
906
|
+
});
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
upsertEntry({
|
|
910
|
+
id: entry.id,
|
|
911
|
+
title: entry.title,
|
|
912
|
+
agent: entry.agent,
|
|
913
|
+
prompt: entry.prompt,
|
|
914
|
+
status: "cancel_requested",
|
|
915
|
+
sessionId: entry.sessionId,
|
|
916
|
+
cancelRequestedAt: Date.now(),
|
|
917
|
+
abortAccepted: false,
|
|
918
|
+
cancelReason: "manual"
|
|
919
|
+
});
|
|
920
|
+
try {
|
|
921
|
+
await props.api.client.session.abort({
|
|
922
|
+
sessionID: childId
|
|
923
|
+
});
|
|
924
|
+
upsertEntry({
|
|
925
|
+
id: entry.id,
|
|
926
|
+
title: entry.title,
|
|
927
|
+
agent: entry.agent,
|
|
928
|
+
prompt: entry.prompt,
|
|
929
|
+
status: "cancel_requested",
|
|
930
|
+
sessionId: entry.sessionId,
|
|
931
|
+
abortAccepted: true
|
|
932
|
+
});
|
|
933
|
+
props.api.ui.toast({
|
|
934
|
+
message: t("cancel.label") + ": " + t("cancel.sent")
|
|
935
|
+
});
|
|
936
|
+
} catch (err) {
|
|
937
|
+
upsertEntry({
|
|
938
|
+
id: entry.id,
|
|
939
|
+
title: entry.title,
|
|
940
|
+
agent: entry.agent,
|
|
941
|
+
prompt: entry.prompt,
|
|
942
|
+
status: "error",
|
|
943
|
+
sessionId: entry.sessionId,
|
|
944
|
+
error: String(err)
|
|
945
|
+
});
|
|
946
|
+
props.api.ui.toast({
|
|
947
|
+
title: entry.title || entry.agent,
|
|
948
|
+
message: t("cancel.label") + ": " + t("cancel.failed")
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
};
|
|
589
952
|
const handlePartUpdated = (event) => {
|
|
590
953
|
const e = event;
|
|
591
954
|
const props_ = e.properties;
|
|
@@ -690,8 +1053,9 @@ function SubAgentPanel(props) {
|
|
|
690
1053
|
}
|
|
691
1054
|
const tryMatchAndUpdate = (entriesMap, targetSid, targetStatus, nowTs) => {
|
|
692
1055
|
for (const [, entry] of entriesMap) {
|
|
693
|
-
if (entry.sessionId === targetSid && entry.status === "running") {
|
|
694
|
-
|
|
1056
|
+
if (entry.sessionId === targetSid && (entry.status === "running" || entry.status === "cancel_requested")) {
|
|
1057
|
+
const finalStatus = targetStatus === "error" ? "error" : settleOnIdle(entry);
|
|
1058
|
+
entry.status = finalStatus;
|
|
695
1059
|
entry.endedAt = nowTs;
|
|
696
1060
|
entry.tokens = entry.tokens ?? sessionTokens;
|
|
697
1061
|
entry.cost = entry.cost ?? sessionCost;
|
|
@@ -707,7 +1071,7 @@ function SubAgentPanel(props) {
|
|
|
707
1071
|
const saNorm = normalize(sessionAgent);
|
|
708
1072
|
let best = null;
|
|
709
1073
|
for (const [, entry] of entriesMap) {
|
|
710
|
-
if (entry.status !== "running") continue;
|
|
1074
|
+
if (entry.status !== "running" && entry.status !== "cancel_requested") continue;
|
|
711
1075
|
const eaNorm = normalize(entry.agent);
|
|
712
1076
|
if (!eaNorm || !saNorm) continue;
|
|
713
1077
|
if (!eaNorm.includes(saNorm) && !saNorm.includes(eaNorm)) continue;
|
|
@@ -719,7 +1083,7 @@ function SubAgentPanel(props) {
|
|
|
719
1083
|
}
|
|
720
1084
|
if (!best) {
|
|
721
1085
|
for (const [, entry] of entriesMap) {
|
|
722
|
-
if (entry.status !== "running") continue;
|
|
1086
|
+
if (entry.status !== "running" && entry.status !== "cancel_requested") continue;
|
|
723
1087
|
if (entry.sessionId) continue;
|
|
724
1088
|
const gap = nowTs - (entry.startedAt || 0);
|
|
725
1089
|
if (!best || gap > best.gap) best = {
|
|
@@ -729,7 +1093,8 @@ function SubAgentPanel(props) {
|
|
|
729
1093
|
}
|
|
730
1094
|
}
|
|
731
1095
|
if (best) {
|
|
732
|
-
|
|
1096
|
+
const finalStatus = targetStatus === "error" ? "error" : settleOnIdle(best.entry);
|
|
1097
|
+
best.entry.status = finalStatus;
|
|
733
1098
|
best.entry.endedAt = nowTs;
|
|
734
1099
|
best.entry.tokens = best.entry.tokens ?? sessionTokens;
|
|
735
1100
|
best.entry.cost = best.entry.cost ?? sessionCost;
|
|
@@ -748,13 +1113,14 @@ function SubAgentPanel(props) {
|
|
|
748
1113
|
const next = new Map(prev);
|
|
749
1114
|
for (const [id, entry] of next) {
|
|
750
1115
|
if (entry.sessionId !== sid) continue;
|
|
751
|
-
if (entry.status !== "running" && entry.status !== "done") continue;
|
|
1116
|
+
if (entry.status !== "running" && entry.status !== "done" && entry.status !== "cancel_requested") continue;
|
|
752
1117
|
if (sid === props.sessionId) continue;
|
|
753
|
-
const alreadySettled = entry.status !== "running";
|
|
1118
|
+
const alreadySettled = entry.status !== "running" && entry.status !== "cancel_requested";
|
|
1119
|
+
const finalStatus = status === "error" ? "error" : settleOnIdle(entry);
|
|
754
1120
|
next.set(id, {
|
|
755
1121
|
...entry,
|
|
756
1122
|
...alreadySettled ? {} : {
|
|
757
|
-
status,
|
|
1123
|
+
status: finalStatus,
|
|
758
1124
|
endedAt: Date.now()
|
|
759
1125
|
},
|
|
760
1126
|
tokens: entry.tokens ?? sessionTokens,
|
|
@@ -772,7 +1138,7 @@ function SubAgentPanel(props) {
|
|
|
772
1138
|
const saNorm = normalize(sessionAgent);
|
|
773
1139
|
let best = null;
|
|
774
1140
|
for (const [id, entry] of next) {
|
|
775
|
-
if (entry.status !== "running") continue;
|
|
1141
|
+
if (entry.status !== "running" && entry.status !== "cancel_requested") continue;
|
|
776
1142
|
const eaNorm = normalize(entry.agent);
|
|
777
1143
|
if (!eaNorm || !saNorm) continue;
|
|
778
1144
|
if (!eaNorm.includes(saNorm) && !saNorm.includes(eaNorm)) continue;
|
|
@@ -784,7 +1150,7 @@ function SubAgentPanel(props) {
|
|
|
784
1150
|
}
|
|
785
1151
|
if (!best) {
|
|
786
1152
|
for (const [id, entry] of next) {
|
|
787
|
-
if (entry.status !== "running") continue;
|
|
1153
|
+
if (entry.status !== "running" && entry.status !== "cancel_requested") continue;
|
|
788
1154
|
if (entry.sessionId) continue;
|
|
789
1155
|
const gap = nowTs - (entry.startedAt || 0);
|
|
790
1156
|
if (!best || gap > best.gap) best = {
|
|
@@ -795,9 +1161,10 @@ function SubAgentPanel(props) {
|
|
|
795
1161
|
}
|
|
796
1162
|
if (best) {
|
|
797
1163
|
const entry = next.get(best.id);
|
|
1164
|
+
const finalStatus = status === "error" ? "error" : settleOnIdle(entry);
|
|
798
1165
|
next.set(best.id, {
|
|
799
1166
|
...entry,
|
|
800
|
-
status,
|
|
1167
|
+
status: finalStatus,
|
|
801
1168
|
endedAt: nowTs,
|
|
802
1169
|
tokens: sessionTokens || entry.tokens,
|
|
803
1170
|
cost: sessionCost || entry.cost,
|
|
@@ -1020,7 +1387,7 @@ function SubAgentPanel(props) {
|
|
|
1020
1387
|
const scanHasChild = scanStMeta?.session_id !== void 0 || scanStMeta?.sessionId !== void 0;
|
|
1021
1388
|
if (scanHasChild) status = "running";
|
|
1022
1389
|
}
|
|
1023
|
-
if (exists && exists.status !== "running") continue;
|
|
1390
|
+
if (exists && exists.status !== "running" && exists.status !== "cancel_requested") continue;
|
|
1024
1391
|
if (exists && status === "running") {
|
|
1025
1392
|
if (!rawStatus) {
|
|
1026
1393
|
const msgTokens = msg?.tokens;
|
|
@@ -1069,15 +1436,16 @@ function SubAgentPanel(props) {
|
|
|
1069
1436
|
let changed = false;
|
|
1070
1437
|
const next = new Map(prev);
|
|
1071
1438
|
for (const [id, entry] of next) {
|
|
1072
|
-
if (entry.status !== "running" || !entry.sessionId) continue;
|
|
1439
|
+
if (entry.status !== "running" && entry.status !== "cancel_requested" || !entry.sessionId) continue;
|
|
1073
1440
|
try {
|
|
1074
1441
|
const st = props.api.state.session.status(entry.sessionId);
|
|
1075
1442
|
if (!st || st.type !== "idle") continue;
|
|
1076
1443
|
const tokens = readSessionTokens(entry.sessionId);
|
|
1077
1444
|
const cost = readSessionCost(entry.sessionId);
|
|
1445
|
+
const finalStatus = entry.status === "cancel_requested" && entry.abortAccepted ? "cancelled" : "done";
|
|
1078
1446
|
next.set(id, {
|
|
1079
1447
|
...entry,
|
|
1080
|
-
status:
|
|
1448
|
+
status: finalStatus,
|
|
1081
1449
|
endedAt: Date.now(),
|
|
1082
1450
|
tokens: tokens ?? entry.tokens,
|
|
1083
1451
|
cost: cost ?? entry.cost
|
|
@@ -1173,8 +1541,8 @@ function SubAgentPanel(props) {
|
|
|
1173
1541
|
elapsed: (e.endedAt ?? nowVal) - e.startedAt
|
|
1174
1542
|
}));
|
|
1175
1543
|
});
|
|
1176
|
-
const doneCount = createMemo(() => entryList().filter((e) => e.status === "done").length);
|
|
1177
|
-
const runningCount = createMemo(() => entryList().filter((e) => e.status === "running").length);
|
|
1544
|
+
const doneCount = createMemo(() => entryList().filter((e) => e.status === "done" || e.status === "cancelled").length);
|
|
1545
|
+
const runningCount = createMemo(() => entryList().filter((e) => e.status === "running" || e.status === "cancel_requested").length);
|
|
1178
1546
|
const errCount = createMemo(() => entryList().filter((e) => e.status === "error").length);
|
|
1179
1547
|
const anyEntry = () => entryList().length > 0;
|
|
1180
1548
|
const totalTokens = createMemo(() => {
|
|
@@ -1433,11 +1801,15 @@ function SubAgentPanel(props) {
|
|
|
1433
1801
|
children: (entry) => {
|
|
1434
1802
|
const isExpanded = () => expanded() === entry.id;
|
|
1435
1803
|
const isRunning = entry.status === "running";
|
|
1804
|
+
const isCancelRequested = entry.status === "cancel_requested";
|
|
1805
|
+
const isCancelled = entry.status === "cancelled";
|
|
1436
1806
|
const isError = entry.status === "error";
|
|
1807
|
+
const isActiveRunning = isRunning || isCancelRequested;
|
|
1437
1808
|
const elapsed = () => (entry.endedAt ?? now()) - entry.startedAt;
|
|
1438
1809
|
const statusDot = () => "\u25CF";
|
|
1439
1810
|
const statusColor = () => {
|
|
1440
|
-
if (
|
|
1811
|
+
if (isCancelled) return pal().muted;
|
|
1812
|
+
if (!isActiveRunning) return isError ? pal().error : pal().success;
|
|
1441
1813
|
const t2 = (Math.sin(now() % 2e3 / 2e3 * Math.PI * 2 - Math.PI / 2) + 1) / 2;
|
|
1442
1814
|
const a = rgb(pal().muted), b = rgb(pal().warning);
|
|
1443
1815
|
if (!a || !b) return pal().warning;
|
|
@@ -1446,9 +1818,9 @@ function SubAgentPanel(props) {
|
|
|
1446
1818
|
const bl = Math.round(a.b + (b.b - a.b) * t2);
|
|
1447
1819
|
return "#" + [r, g, bl].map((v) => Math.max(0, Math.min(255, v)).toString(16).padStart(2, "0")).join("");
|
|
1448
1820
|
};
|
|
1449
|
-
const timeColor = () =>
|
|
1821
|
+
const timeColor = () => isActiveRunning ? pal().warning : isError ? pal().error : pal().muted;
|
|
1450
1822
|
const tokenText = () => !isExpanded() && entry.tokens !== void 0 && entry.tokens > 0 ? ` ${fmtTokens(entry.tokens)}` : "";
|
|
1451
|
-
const timeText = () => !isExpanded() && (elapsed() >= 2e3 || entry.endedAt !== void 0) ? fmtDurationShort(elapsed(),
|
|
1823
|
+
const timeText = () => !isExpanded() && (elapsed() >= 2e3 || entry.endedAt !== void 0) ? fmtDurationShort(elapsed(), isActiveRunning) : "";
|
|
1452
1824
|
const suffixW = () => {
|
|
1453
1825
|
let w = 0;
|
|
1454
1826
|
const t2 = timeText();
|
|
@@ -1558,14 +1930,14 @@ function SubAgentPanel(props) {
|
|
|
1558
1930
|
_$insertNode(_el$39, _el$40);
|
|
1559
1931
|
_$insert(_el$39, () => t("status.label"), _el$40);
|
|
1560
1932
|
_$insert(_el$41, () => " ".repeat(expandedPad(t("status.label"))));
|
|
1561
|
-
_$insert(_el$42, () =>
|
|
1933
|
+
_$insert(_el$42, () => isActiveRunning ? t("status.running") : isCancelled ? t("status.cancelled") : isError ? t("status.error") : t("status.done"));
|
|
1562
1934
|
_$effect((_p$) => {
|
|
1563
1935
|
var _v$9 = {
|
|
1564
1936
|
fg: pal().primary
|
|
1565
1937
|
}, _v$0 = {
|
|
1566
1938
|
fg: pal().muted
|
|
1567
1939
|
}, _v$1 = {
|
|
1568
|
-
fg:
|
|
1940
|
+
fg: isActiveRunning ? pal().warning : isCancelled ? pal().muted : isError ? pal().error : pal().success
|
|
1569
1941
|
};
|
|
1570
1942
|
_v$9 !== _p$.e && (_p$.e = _$setProp(_el$39, "style", _v$9, _p$.e));
|
|
1571
1943
|
_v$0 !== _p$.t && (_p$.t = _$setProp(_el$41, "style", _v$0, _p$.t));
|
|
@@ -1590,7 +1962,7 @@ function SubAgentPanel(props) {
|
|
|
1590
1962
|
_$insertNode(_el$45, _el$46);
|
|
1591
1963
|
_$insert(_el$45, () => t("time.label"), _el$46);
|
|
1592
1964
|
_$insert(_el$47, () => " ".repeat(expandedPad(t("time.label"))));
|
|
1593
|
-
_$insert(_el$48, () => fmtDurationShort(elapsed(),
|
|
1965
|
+
_$insert(_el$48, () => fmtDurationShort(elapsed(), isActiveRunning));
|
|
1594
1966
|
_$effect((_p$) => {
|
|
1595
1967
|
var _v$10 = {
|
|
1596
1968
|
fg: pal().primary
|
|
@@ -1794,16 +2166,27 @@ function SubAgentPanel(props) {
|
|
|
1794
2166
|
_$insertNode(_el$74, _el$78);
|
|
1795
2167
|
_$insertNode(_el$74, _el$79);
|
|
1796
2168
|
_$insertNode(_el$74, _el$80);
|
|
1797
|
-
_$setProp(_el$74, "onMouseUp", () => {
|
|
1798
|
-
|
|
2169
|
+
_$setProp(_el$74, "onMouseUp", async () => {
|
|
2170
|
+
const sessionId = entry.sessionId;
|
|
2171
|
+
if (!sessionId) return;
|
|
2172
|
+
const result = await copyText(sessionId);
|
|
2173
|
+
if (result.copied) {
|
|
1799
2174
|
props.api.ui.toast({
|
|
2175
|
+
variant: "success",
|
|
1800
2176
|
title: entry.title || entry.agent,
|
|
1801
|
-
message:
|
|
1802
|
-
|
|
1803
|
-
${t("session.toast.copy")}`,
|
|
1804
|
-
duration: 8e3
|
|
2177
|
+
message: t("session.toast.copied"),
|
|
2178
|
+
duration: 2500
|
|
1805
2179
|
});
|
|
2180
|
+
return;
|
|
1806
2181
|
}
|
|
2182
|
+
props.api.ui.toast({
|
|
2183
|
+
variant: "warning",
|
|
2184
|
+
title: entry.title || entry.agent,
|
|
2185
|
+
message: `${sessionId}
|
|
2186
|
+
|
|
2187
|
+
${t("session.toast.copy_failed")}`,
|
|
2188
|
+
duration: 8e3
|
|
2189
|
+
});
|
|
1807
2190
|
});
|
|
1808
2191
|
_$insertNode(_el$76, _el$77);
|
|
1809
2192
|
_$insert(_el$76, () => t("session.label"), _el$77);
|
|
@@ -1839,29 +2222,21 @@ ${t("session.toast.copy")}`,
|
|
|
1839
2222
|
},
|
|
1840
2223
|
get children() {
|
|
1841
2224
|
return (() => {
|
|
1842
|
-
const dismissLabel = () => `- ${t("dismiss.label")}`;
|
|
1843
2225
|
const openPrefix = () => " \u2192 ";
|
|
1844
2226
|
const openFull = () => entry.sessionId ? openPrefix() + t("open.label") : "";
|
|
1845
2227
|
const openW = () => entry.sessionId ? visualWidth(openFull()) : 0;
|
|
1846
|
-
const
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
);
|
|
2228
|
+
const cancelLabel = () => ` ${t("cancel.label")}`;
|
|
2229
|
+
const dismissLabel = () => ` ${t("dismiss.label")}`;
|
|
2230
|
+
const rightW = (isRunning ? visualWidth(dismissLabel()) : 0) + (isRunning && entry.sessionId ? visualWidth(cancelLabel()) : 0);
|
|
2231
|
+
const spacerW = () => Math.max(1, panelWidth() - openW() - rightW - 2);
|
|
1851
2232
|
return (() => {
|
|
1852
|
-
var _el$91 = _$createElement("box");
|
|
2233
|
+
var _el$91 = _$createElement("box"), _el$95 = _$createElement("text");
|
|
2234
|
+
_$insertNode(_el$91, _el$95);
|
|
1853
2235
|
_$setProp(_el$91, "flexDirection", "row");
|
|
1854
2236
|
_$insert(_el$91, _$createComponent(Show, {
|
|
1855
2237
|
get when() {
|
|
1856
2238
|
return entry.sessionId;
|
|
1857
2239
|
},
|
|
1858
|
-
get fallback() {
|
|
1859
|
-
return (() => {
|
|
1860
|
-
var _el$98 = _$createElement("text");
|
|
1861
|
-
_$insertNode(_el$98, _$createTextNode(` `));
|
|
1862
|
-
return _el$98;
|
|
1863
|
-
})();
|
|
1864
|
-
},
|
|
1865
2240
|
get children() {
|
|
1866
2241
|
var _el$92 = _$createElement("text"), _el$93 = _$createElement("span"), _el$94 = _$createElement("span");
|
|
1867
2242
|
_$insertNode(_el$92, _el$93);
|
|
@@ -1892,39 +2267,51 @@ ${t("session.toast.copy")}`,
|
|
|
1892
2267
|
});
|
|
1893
2268
|
return _el$92;
|
|
1894
2269
|
}
|
|
2270
|
+
}), _el$95);
|
|
2271
|
+
_$insert(_el$95, () => " ".repeat(spacerW()));
|
|
2272
|
+
_$insert(_el$91, _$createComponent(Show, {
|
|
2273
|
+
get when() {
|
|
2274
|
+
return isRunning && entry.sessionId;
|
|
2275
|
+
},
|
|
2276
|
+
get children() {
|
|
2277
|
+
var _el$96 = _$createElement("text"), _el$97 = _$createElement("span");
|
|
2278
|
+
_$insertNode(_el$96, _el$97);
|
|
2279
|
+
_$setProp(_el$96, "onMouseOver", () => setHoveredCancel(entry.id));
|
|
2280
|
+
_$setProp(_el$96, "onMouseOut", () => setHoveredCancel(void 0));
|
|
2281
|
+
_$setProp(_el$96, "onMouseUp", () => cancelEntry(entry));
|
|
2282
|
+
_$insert(_el$97, cancelLabel);
|
|
2283
|
+
_$effect((_$p) => _$setProp(_el$97, "style", {
|
|
2284
|
+
fg: hoveredCancel() === entry.id ? pal().warning : pal().error
|
|
2285
|
+
}, _$p));
|
|
2286
|
+
return _el$96;
|
|
2287
|
+
}
|
|
1895
2288
|
}), null);
|
|
1896
2289
|
_$insert(_el$91, _$createComponent(Show, {
|
|
1897
2290
|
when: isRunning,
|
|
1898
2291
|
get children() {
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
_$setProp(_el$96, "onMouseOut", () => setHoveredDismiss(void 0));
|
|
1911
|
-
_$setProp(_el$96, "onMouseUp", () => {
|
|
1912
|
-
upsertEntry({
|
|
1913
|
-
id: entry.id,
|
|
1914
|
-
title: entry.title,
|
|
1915
|
-
agent: entry.agent,
|
|
1916
|
-
prompt: entry.prompt,
|
|
1917
|
-
status: "done"
|
|
1918
|
-
});
|
|
2292
|
+
var _el$98 = _$createElement("text"), _el$99 = _$createElement("span");
|
|
2293
|
+
_$insertNode(_el$98, _el$99);
|
|
2294
|
+
_$setProp(_el$98, "onMouseOver", () => setHoveredDismiss(entry.id));
|
|
2295
|
+
_$setProp(_el$98, "onMouseOut", () => setHoveredDismiss(void 0));
|
|
2296
|
+
_$setProp(_el$98, "onMouseUp", () => {
|
|
2297
|
+
upsertEntry({
|
|
2298
|
+
id: entry.id,
|
|
2299
|
+
title: entry.title,
|
|
2300
|
+
agent: entry.agent,
|
|
2301
|
+
prompt: entry.prompt,
|
|
2302
|
+
status: "done"
|
|
1919
2303
|
});
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
2304
|
+
});
|
|
2305
|
+
_$insert(_el$99, dismissLabel);
|
|
2306
|
+
_$effect((_$p) => _$setProp(_el$99, "style", {
|
|
2307
|
+
fg: hoveredDismiss() === entry.id ? pal().warning : pal().muted
|
|
2308
|
+
}, _$p));
|
|
2309
|
+
return _el$98;
|
|
1926
2310
|
}
|
|
1927
2311
|
}), null);
|
|
2312
|
+
_$effect((_$p) => _$setProp(_el$95, "style", {
|
|
2313
|
+
fg: pal().muted
|
|
2314
|
+
}, _$p));
|
|
1928
2315
|
return _el$91;
|
|
1929
2316
|
})();
|
|
1930
2317
|
})();
|
|
@@ -2056,7 +2443,7 @@ function createSidebarSlot(api, sig) {
|
|
|
2056
2443
|
var KV_PREFIX = "subagent_magazine";
|
|
2057
2444
|
var tui = async (api) => {
|
|
2058
2445
|
const stored = String(api.kv.get(`${KV_PREFIX}.lang`, ""));
|
|
2059
|
-
const initialLang =
|
|
2446
|
+
const initialLang = LANG_META.some((m) => m.code === stored) ? stored : detectLang();
|
|
2060
2447
|
const [lang, setLang] = createSignal(initialLang);
|
|
2061
2448
|
const [maxEntries, setMaxEntries] = createSignal(parseInt(String(api.kv.get(`${KV_PREFIX}.max_entries`, "10")), 10) || 10);
|
|
2062
2449
|
const [sortOrder, setSortOrder] = createSignal(String(api.kv.get(`${KV_PREFIX}.order`, "desc")) === "asc" ? "asc" : "desc");
|
|
@@ -2083,19 +2470,18 @@ var tui = async (api) => {
|
|
|
2083
2470
|
onSelect: (dialog) => {
|
|
2084
2471
|
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
2085
2472
|
title: "Language / \u8BED\u8A00",
|
|
2086
|
-
options
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
}],
|
|
2473
|
+
get options() {
|
|
2474
|
+
return LANG_META.map((m) => ({
|
|
2475
|
+
title: m.label,
|
|
2476
|
+
value: m.code
|
|
2477
|
+
}));
|
|
2478
|
+
},
|
|
2093
2479
|
onSelect: (opt) => {
|
|
2094
2480
|
const l = opt.value;
|
|
2095
2481
|
setLang(l);
|
|
2096
2482
|
api.kv.set(`${KV_PREFIX}.lang`, l);
|
|
2097
2483
|
api.ui.toast({
|
|
2098
|
-
message:
|
|
2484
|
+
message: "Language: " + (LANG_META.find((m) => m.code === l)?.label ?? l)
|
|
2099
2485
|
});
|
|
2100
2486
|
dialog?.clear();
|
|
2101
2487
|
}
|
|
@@ -2109,7 +2495,7 @@ var tui = async (api) => {
|
|
|
2109
2495
|
name: "subagent-order"
|
|
2110
2496
|
},
|
|
2111
2497
|
onSelect: (dialog) => {
|
|
2112
|
-
const t = (
|
|
2498
|
+
const t = createT(() => lang());
|
|
2113
2499
|
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
2114
2500
|
title: "Sort Order / \u6392\u5E8F\u65B9\u5F0F",
|
|
2115
2501
|
get options() {
|
|
@@ -2140,7 +2526,7 @@ var tui = async (api) => {
|
|
|
2140
2526
|
name: "subagent-scroll"
|
|
2141
2527
|
},
|
|
2142
2528
|
onSelect: (dialog) => {
|
|
2143
|
-
const t = (
|
|
2529
|
+
const t = createT(() => lang());
|
|
2144
2530
|
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
2145
2531
|
title: "Scroll Mode / \u6EDA\u52A8\u6A21\u5F0F",
|
|
2146
2532
|
get options() {
|
|
@@ -2238,7 +2624,7 @@ var tui = async (api) => {
|
|
|
2238
2624
|
}
|
|
2239
2625
|
let count = 0;
|
|
2240
2626
|
for (const [, entry] of entries) {
|
|
2241
|
-
if (entry.status === "running") {
|
|
2627
|
+
if (entry.status === "running" || entry.status === "cancel_requested") {
|
|
2242
2628
|
entry.status = "done";
|
|
2243
2629
|
entry.endedAt = Date.now();
|
|
2244
2630
|
count++;
|
|
@@ -2299,7 +2685,7 @@ var tui = async (api) => {
|
|
|
2299
2685
|
name: "subagent-ttl"
|
|
2300
2686
|
},
|
|
2301
2687
|
onSelect: (dialog) => {
|
|
2302
|
-
const t = (
|
|
2688
|
+
const t = createT(() => signals.lang());
|
|
2303
2689
|
const curRaw = parseInt(String(api.kv.get(`${KV_PREFIX}.ttl_days`, "3")), 10);
|
|
2304
2690
|
const curDays = Number.isNaN(curRaw) ? 3 : curRaw;
|
|
2305
2691
|
const curLabel = curDays === 0 ? t("ttl.unlimited") : `${curDays}d`;
|
|
@@ -2328,7 +2714,9 @@ var tui = async (api) => {
|
|
|
2328
2714
|
onSelect: (opt) => {
|
|
2329
2715
|
const days = parseInt(opt.value, 10);
|
|
2330
2716
|
api.kv.set(`${KV_PREFIX}.ttl_days`, String(days));
|
|
2331
|
-
const msg = days === 0 ? t("ttl.toast_unlimited") : t("ttl.toast"
|
|
2717
|
+
const msg = days === 0 ? t("ttl.toast_unlimited") : t("ttl.toast", {
|
|
2718
|
+
n: days
|
|
2719
|
+
});
|
|
2332
2720
|
api.ui.toast({
|
|
2333
2721
|
message: msg
|
|
2334
2722
|
});
|
|
@@ -2344,7 +2732,7 @@ var tui = async (api) => {
|
|
|
2344
2732
|
name: "subagent-clear-entries"
|
|
2345
2733
|
},
|
|
2346
2734
|
onSelect: (dialog) => {
|
|
2347
|
-
const t = (
|
|
2735
|
+
const t = createT(() => signals.lang());
|
|
2348
2736
|
const sid = signals.sessionId;
|
|
2349
2737
|
const sessionObj = api.state.session.get(sid);
|
|
2350
2738
|
const parentID = sessionObj?.parentID;
|
|
@@ -2355,7 +2743,9 @@ var tui = async (api) => {
|
|
|
2355
2743
|
if (e.status === "running") runningCount++;
|
|
2356
2744
|
}
|
|
2357
2745
|
}
|
|
2358
|
-
const msg = runningCount > 0 ? t("clear.prompt_running"
|
|
2746
|
+
const msg = runningCount > 0 ? t("clear.prompt_running", {
|
|
2747
|
+
n: runningCount
|
|
2748
|
+
}) : t("clear.prompt");
|
|
2359
2749
|
dialog?.replace(() => _$createComponent(api.ui.DialogConfirm, {
|
|
2360
2750
|
get title() {
|
|
2361
2751
|
return t("clear.title");
|
|
@@ -2388,7 +2778,9 @@ var tui = async (api) => {
|
|
|
2388
2778
|
api.kv.set(`${KV_PREFIX}.session_data`, JSON.stringify(data));
|
|
2389
2779
|
globalEntryCache.delete(sid);
|
|
2390
2780
|
setClearTick((v) => v + 1);
|
|
2391
|
-
const msg2 = t("clear.done"
|
|
2781
|
+
const msg2 = t("clear.done", {
|
|
2782
|
+
n: count
|
|
2783
|
+
});
|
|
2392
2784
|
api.ui.toast({
|
|
2393
2785
|
message: msg2
|
|
2394
2786
|
});
|