@songsid/agend 2.1.3 → 2.1.4-beta.10
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/LICENSE +21 -0
- package/README.md +2 -2
- package/README.zh-TW.md +2 -2
- package/dist/backend/antigravity.d.ts +1 -0
- package/dist/backend/antigravity.js +1 -0
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.d.ts +1 -0
- package/dist/backend/claude-code.js +24 -2
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex.d.ts +1 -0
- package/dist/backend/codex.js +43 -4
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/gemini-cli.d.ts +1 -0
- package/dist/backend/gemini-cli.js +1 -0
- package/dist/backend/gemini-cli.js.map +1 -1
- package/dist/backend/grok.d.ts +1 -0
- package/dist/backend/grok.js +1 -0
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro.d.ts +1 -0
- package/dist/backend/kiro.js +1 -0
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/mock.d.ts +1 -0
- package/dist/backend/mock.js +1 -0
- package/dist/backend/mock.js.map +1 -1
- package/dist/backend/opencode.d.ts +40 -0
- package/dist/backend/opencode.js +83 -5
- package/dist/backend/opencode.js.map +1 -1
- package/dist/backend/types.d.ts +10 -0
- package/dist/backend/types.js +7 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/adapters/discord.js +24 -7
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/mcp-server.js +6 -20
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.js +1 -1
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/types.d.ts +1 -1
- package/dist/classic-channel-manager.d.ts +34 -3
- package/dist/classic-channel-manager.js +190 -31
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +74 -23
- package/dist/cli.js.map +1 -1
- package/dist/completion-install.d.ts +70 -0
- package/dist/completion-install.js +152 -0
- package/dist/completion-install.js.map +1 -0
- package/dist/completion.d.ts +7 -1
- package/dist/completion.js +14 -4
- package/dist/completion.js.map +1 -1
- package/dist/config-validator.js +35 -7
- package/dist/config-validator.js.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/daemon.d.ts +53 -9
- package/dist/daemon.js +222 -86
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-context.d.ts +8 -0
- package/dist/fleet-manager.d.ts +136 -5
- package/dist/fleet-manager.js +1088 -316
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/backend-providers/SKILL.md +114 -0
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +3 -1
- package/dist/general-knowledge/skills/delegation-playbook/SKILL.md +52 -0
- package/dist/general-knowledge/skills/development-workflow/SKILL.md +28 -0
- package/dist/general-knowledge/skills/fleet-config/SKILL.md +1 -0
- package/dist/general-knowledge/skills/fleet-health/SKILL.md +1 -0
- package/dist/general-knowledge/skills/fleet-restart/SKILL.md +1 -0
- package/dist/general-knowledge/skills/instance-lifecycle/SKILL.md +1 -0
- package/dist/general-knowledge/skills/model-discovery/SKILL.md +1 -0
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +1 -0
- package/dist/general-knowledge/skills/scheduling/SKILL.md +1 -0
- package/dist/general-knowledge/skills/session-management/SKILL.md +1 -0
- package/dist/general-knowledge/skills/tui-effort/SKILL.md +1 -0
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +30 -0
- package/dist/instance-lifecycle.d.ts +10 -0
- package/dist/instance-lifecycle.js +50 -33
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.d.ts +12 -0
- package/dist/instructions.js +33 -0
- package/dist/instructions.js.map +1 -1
- package/dist/locale.js +130 -0
- package/dist/locale.js.map +1 -1
- package/dist/outbound-schemas.d.ts +2 -1
- package/dist/outbound-schemas.js +1 -0
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/quickstart.js +29 -2
- package/dist/quickstart.js.map +1 -1
- package/dist/restart-progress.d.ts +7 -1
- package/dist/restart-progress.js +27 -6
- package/dist/restart-progress.js.map +1 -1
- package/dist/setup-wizard.d.ts +4 -2
- package/dist/setup-wizard.js +2 -2
- package/dist/setup-wizard.js.map +1 -1
- package/dist/tool-progress.d.ts +40 -0
- package/dist/tool-progress.js +289 -0
- package/dist/tool-progress.js.map +1 -0
- package/dist/topic-commands.d.ts +26 -0
- package/dist/topic-commands.js +117 -1
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-monitor.d.ts +15 -2
- package/dist/transcript-monitor.js +63 -17
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/transcript-sources.d.ts +106 -0
- package/dist/transcript-sources.js +428 -0
- package/dist/transcript-sources.js.map +1 -0
- package/dist/types.d.ts +8 -0
- package/dist/ui/dashboard.html +5 -4
- package/dist/update-marker.d.ts +30 -0
- package/dist/update-marker.js +71 -20
- package/dist/update-marker.js.map +1 -1
- package/dist/update-progress.d.ts +6 -0
- package/dist/update-progress.js +29 -0
- package/dist/update-progress.js.map +1 -0
- package/dist/web-api.js +2 -2
- package/dist/web-api.js.map +1 -1
- package/dist/workflow-templates/default.md +2 -1
- package/package.json +2 -2
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic tool-progress labelling for the channel processing bubble.
|
|
3
|
+
*
|
|
4
|
+
* This is a SECOND labeller, deliberately separate from `Daemon.summarizeTool`:
|
|
5
|
+
* that one feeds the statusline / `/view` / recent events and is pinned by
|
|
6
|
+
* tests to the terse `Read <path>` / `$ <cmd>` form. This one feeds the
|
|
7
|
+
* channel bubble only — it is semantic (`npm test` → `🧪 執行測試`), may
|
|
8
|
+
* return `""` for uninteresting work, and never carries shell arguments at
|
|
9
|
+
* the default `standard` level. Do not merge the two: they serve different
|
|
10
|
+
* audiences with different safety requirements (the bubble is broadcast to a
|
|
11
|
+
* chat channel; the statusline is an operator surface).
|
|
12
|
+
*/
|
|
13
|
+
/** Max characters for any single progress line (before the display cap). */
|
|
14
|
+
const LABEL_MAX_CHARS = 80;
|
|
15
|
+
/** Max characters of command preview appended at `verbose`. */
|
|
16
|
+
const VERBOSE_PREVIEW_CHARS = 48;
|
|
17
|
+
/**
|
|
18
|
+
* Strip credentials before anything reaches a chat channel. Patterns are
|
|
19
|
+
* deliberately broad — a false positive redacts a harmless token, a false
|
|
20
|
+
* negative broadcasts a secret.
|
|
21
|
+
*/
|
|
22
|
+
export function redactSecrets(text) {
|
|
23
|
+
return text
|
|
24
|
+
// JWTs (three base64url segments) — before generic keys, which match prefixes
|
|
25
|
+
.replace(/\beyJ[\w-]{8,}\.[\w-]{8,}\.[\w-]+/g, "[REDACTED]")
|
|
26
|
+
// Known key shapes: OpenAI/Anthropic/GitHub/Slack/AWS/Telegram bot tokens
|
|
27
|
+
.replace(/\b(sk|pk|rk)-[A-Za-z0-9_-]{16,}/g, "[REDACTED]")
|
|
28
|
+
.replace(/\bsk-ant-[A-Za-z0-9_-]{10,}/g, "[REDACTED]")
|
|
29
|
+
.replace(/\bgh[pousr]_[A-Za-z0-9]{16,}/g, "[REDACTED]")
|
|
30
|
+
.replace(/\bxox[baprs]-[A-Za-z0-9-]{10,}/g, "[REDACTED]")
|
|
31
|
+
.replace(/\bAKIA[0-9A-Z]{16}\b/g, "[REDACTED]")
|
|
32
|
+
.replace(/\b\d{8,10}:AA[A-Za-z0-9_-]{30,}/g, "[REDACTED]")
|
|
33
|
+
// Bearer / basic auth headers
|
|
34
|
+
.replace(/\b(Bearer|Basic)\s+[A-Za-z0-9+/._=-]{8,}/gi, "$1 [REDACTED]")
|
|
35
|
+
// key=value / key: value assignments for sensitive names
|
|
36
|
+
.replace(/\b((?:api[-_]?key|token|secret|passwd|password|authorization|credential)s?\s*[=:]\s*)(["']?)[^\s"']{6,}\2/gi, "$1[REDACTED]")
|
|
37
|
+
// URL userinfo credentials (https://user:pass@host)
|
|
38
|
+
.replace(/(\w+:\/\/[^/\s:@]+:)[^@\s]+@/g, "$1[REDACTED]@");
|
|
39
|
+
}
|
|
40
|
+
/** Flatten whitespace and cap length for a single bubble line. */
|
|
41
|
+
function capLine(s) {
|
|
42
|
+
const flat = s.replace(/\s+/g, " ").trim();
|
|
43
|
+
return flat.length > LABEL_MAX_CHARS ? `${flat.slice(0, LABEL_MAX_CHARS - 1)}…` : flat;
|
|
44
|
+
}
|
|
45
|
+
/** Shorten an absolute path to something readable in a bubble line. */
|
|
46
|
+
function shortPath(p) {
|
|
47
|
+
const clean = String(p).trim();
|
|
48
|
+
if (clean.length <= 48)
|
|
49
|
+
return clean;
|
|
50
|
+
const parts = clean.split("/");
|
|
51
|
+
if (parts.length <= 3)
|
|
52
|
+
return clean;
|
|
53
|
+
return `…/${parts.slice(-3).join("/")}`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Reduce a shell command to its intent. Returns null for commands with no
|
|
57
|
+
* interesting intent — the caller renders a generic "執行指令" line with the
|
|
58
|
+
* program name only (never arguments) at `standard`.
|
|
59
|
+
*/
|
|
60
|
+
function classifyShellCommand(cmd) {
|
|
61
|
+
const c = cmd.trim();
|
|
62
|
+
// Test runners
|
|
63
|
+
if (/\b(npm|pnpm|yarn|bun)( run)? test\b/.test(c) || /\b(vitest|jest|pytest|go test|cargo test|mocha|rspec)\b/.test(c)) {
|
|
64
|
+
return { label: "🧪 執行測試", preview: true };
|
|
65
|
+
}
|
|
66
|
+
// Typecheck / build
|
|
67
|
+
if (/\btsc\b/.test(c) || /\b(npm|pnpm|yarn|bun) run build\b/.test(c) || /\b(cargo|go) build\b/.test(c) || /\bmake\b/.test(c)) {
|
|
68
|
+
return { label: "🔨 建置/型別檢查", preview: true };
|
|
69
|
+
}
|
|
70
|
+
// Dependency install
|
|
71
|
+
if (/\b(npm|pnpm|yarn|bun) (i|ci|install|add)\b/.test(c) || /\bpip3? install\b/.test(c) || /\bcargo add\b/.test(c)) {
|
|
72
|
+
return { label: "📦 安裝依賴", preview: true };
|
|
73
|
+
}
|
|
74
|
+
// Git — order matters: push/pull before generic commit
|
|
75
|
+
if (/\bgit push\b/.test(c))
|
|
76
|
+
return { label: "⬆️ git push", preview: true };
|
|
77
|
+
if (/\bgit (pull|fetch)\b/.test(c))
|
|
78
|
+
return { label: "⬇️ git pull/fetch", preview: true };
|
|
79
|
+
if (/\bgit commit\b/.test(c))
|
|
80
|
+
return { label: "💾 git commit", preview: false };
|
|
81
|
+
if (/\bgit (checkout|switch|branch)\b/.test(c))
|
|
82
|
+
return { label: "🔀 git 分支操作", preview: true };
|
|
83
|
+
if (/\bgit (diff|log|status|show|blame)\b/.test(c))
|
|
84
|
+
return { label: "🔎 檢視 git 狀態", preview: true };
|
|
85
|
+
if (/\bgh (pr|issue|api|run)\b/.test(c))
|
|
86
|
+
return { label: "🐙 GitHub 操作", preview: true };
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
/** Low-signal inspection commands: hidden entirely at `standard`. */
|
|
90
|
+
function isLowSignalCommand(cmd) {
|
|
91
|
+
return /^(rg|grep|find|fd|ls|cat|head|tail|wc|which|pwd|echo|sed|awk|cut|sort|uniq)\b/.test(cmd.trim());
|
|
92
|
+
}
|
|
93
|
+
/** First program name of a shell command, pipelines/chains reduced to the head. */
|
|
94
|
+
function shellProgramName(cmd) {
|
|
95
|
+
const head = cmd.trim().split(/\s*(?:&&|\|\||\||;)\s*/)[0] ?? "";
|
|
96
|
+
const tokens = head.trim().split(/\s+/);
|
|
97
|
+
// Skip env assignments and common wrappers
|
|
98
|
+
let i = 0;
|
|
99
|
+
while (i < tokens.length && /^[A-Za-z_][A-Za-z0-9_]*=/.test(tokens[i]))
|
|
100
|
+
i++;
|
|
101
|
+
if (tokens[i] === "sudo" || tokens[i] === "npx" || tokens[i] === "timeout")
|
|
102
|
+
i++;
|
|
103
|
+
if (tokens[i] && /^\d+[smh]?$/.test(tokens[i]))
|
|
104
|
+
i++; // timeout's duration arg
|
|
105
|
+
return tokens[i] ?? "";
|
|
106
|
+
}
|
|
107
|
+
function labelShell(cmd, level) {
|
|
108
|
+
const intent = classifyShellCommand(cmd);
|
|
109
|
+
if (intent) {
|
|
110
|
+
if (level === "verbose" && intent.preview) {
|
|
111
|
+
return `${intent.label}:${redactSecrets(cmd).slice(0, VERBOSE_PREVIEW_CHARS)}`;
|
|
112
|
+
}
|
|
113
|
+
return intent.label;
|
|
114
|
+
}
|
|
115
|
+
if (level === "verbose")
|
|
116
|
+
return `⚙️ $ ${redactSecrets(cmd).slice(0, VERBOSE_PREVIEW_CHARS)}`;
|
|
117
|
+
if (isLowSignalCommand(cmd))
|
|
118
|
+
return "";
|
|
119
|
+
// standard: program name only, never arguments
|
|
120
|
+
const prog = shellProgramName(cmd);
|
|
121
|
+
return prog ? `⚙️ 執行指令:${prog}` : "";
|
|
122
|
+
}
|
|
123
|
+
/** Extract the shell command from a codex exec input (array or JSON string). */
|
|
124
|
+
function codexShellCommand(input) {
|
|
125
|
+
let inp = input;
|
|
126
|
+
if (typeof inp === "string") {
|
|
127
|
+
// custom_tool_call "exec" input is a JS snippet driving tools.* — surface the call names
|
|
128
|
+
const raw = inp;
|
|
129
|
+
const toolCalls = [...raw.matchAll(/\btools\.(\w+)\s*\(/g)].map(m => m[1]);
|
|
130
|
+
if (toolCalls.length)
|
|
131
|
+
return null; // handled by caller via codexToolsCalled
|
|
132
|
+
// Not JSON → a plain JS snippet for codex's exec runtime, not a shell command.
|
|
133
|
+
try {
|
|
134
|
+
inp = JSON.parse(raw);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const obj = inp;
|
|
141
|
+
if (!obj)
|
|
142
|
+
return null;
|
|
143
|
+
const cmd = obj.command;
|
|
144
|
+
if (Array.isArray(cmd)) {
|
|
145
|
+
// ["bash","-lc","actual command"] — take the last element
|
|
146
|
+
return String(cmd[cmd.length - 1] ?? "");
|
|
147
|
+
}
|
|
148
|
+
if (typeof cmd === "string")
|
|
149
|
+
return cmd;
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
function codexToolsCalled(input) {
|
|
153
|
+
if (typeof input !== "string")
|
|
154
|
+
return [];
|
|
155
|
+
return [...new Set([...input.matchAll(/\btools\.(\w+)\s*\(/g)].map(m => m[1]))];
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Name-level classification shared by direct tool uses and codex exec's
|
|
159
|
+
* tools.* calls. Returns "" for channel-plumbing agend MCP tools (suppressed),
|
|
160
|
+
* `🔌 server:tool` for other MCP tools, undefined for everything else.
|
|
161
|
+
*
|
|
162
|
+
* agend naming varies per CLI: claude-code `mcp__agend__reply`, codex
|
|
163
|
+
* `mcp__agend_<instance>__reply`, opencode `agend-<instance>_reply` — hence
|
|
164
|
+
* prefix matching rather than an exact list.
|
|
165
|
+
*/
|
|
166
|
+
function labelToolName(name) {
|
|
167
|
+
if (/^mcp__agend[_-]|^agend[-_]/.test(name))
|
|
168
|
+
return "";
|
|
169
|
+
const mcpMatch = name.match(/^mcp__(\w+?)__(\w+)$/);
|
|
170
|
+
if (mcpMatch)
|
|
171
|
+
return capLine(`🔌 ${mcpMatch[1]}:${mcpMatch[2]}`);
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The channel-bubble labeller. Returns "" when the tool use is not worth a
|
|
176
|
+
* line (channel-plumbing MCP tools, low-signal inspection commands at
|
|
177
|
+
* `standard`). Input shapes vary per backend; unknown shapes degrade to the
|
|
178
|
+
* bare tool name rather than throwing.
|
|
179
|
+
*/
|
|
180
|
+
export function summarizeProgress(name, input, level = "standard") {
|
|
181
|
+
const inp = (input ?? {});
|
|
182
|
+
const named = labelToolName(name);
|
|
183
|
+
if (named !== undefined)
|
|
184
|
+
return named;
|
|
185
|
+
switch (name) {
|
|
186
|
+
// claude-code shapes
|
|
187
|
+
case "Read": {
|
|
188
|
+
const p = inp.file_path ?? inp.path ?? "";
|
|
189
|
+
return p ? capLine(`📄 讀取檔案:${shortPath(redactSecrets(String(p)))}`) : "📄 讀取檔案";
|
|
190
|
+
}
|
|
191
|
+
case "Edit":
|
|
192
|
+
case "Write":
|
|
193
|
+
case "NotebookEdit": {
|
|
194
|
+
const p = inp.file_path ?? inp.path ?? "";
|
|
195
|
+
return p ? capLine(`✏️ 編輯檔案:${shortPath(redactSecrets(String(p)))}`) : "✏️ 編輯檔案";
|
|
196
|
+
}
|
|
197
|
+
case "Glob":
|
|
198
|
+
case "Grep":
|
|
199
|
+
return level === "verbose" ? capLine(`🔍 搜尋:${redactSecrets(String(inp.pattern ?? ""))}`) : "🔍 搜尋程式碼";
|
|
200
|
+
case "Agent":
|
|
201
|
+
case "Task":
|
|
202
|
+
return "🤝 派工作給子 Agent";
|
|
203
|
+
case "WebFetch":
|
|
204
|
+
return level === "verbose" && inp.url ? capLine(`🌐 讀取網頁:${redactSecrets(String(inp.url))}`) : "🌐 讀取網頁";
|
|
205
|
+
case "WebSearch":
|
|
206
|
+
return "🌐 網路搜尋";
|
|
207
|
+
case "Skill":
|
|
208
|
+
return inp.skill ? capLine(`📚 使用 Skill:${String(inp.skill)}`) : "📚 使用 Skill";
|
|
209
|
+
case "TodoWrite":
|
|
210
|
+
return ""; // bookkeeping, not work
|
|
211
|
+
case "Bash":
|
|
212
|
+
case "bash": // opencode
|
|
213
|
+
case "shell": { // kiro / codex function_call
|
|
214
|
+
const cmd = String(inp.command ?? "");
|
|
215
|
+
return cmd ? capLine(labelShell(cmd, level)) : "";
|
|
216
|
+
}
|
|
217
|
+
case "exec": { // codex custom_tool_call — JS driving tools.*
|
|
218
|
+
const calls = codexToolsCalled(input);
|
|
219
|
+
if (calls.length) {
|
|
220
|
+
const labels = [...new Set(calls.map(c => labelToolName(c) ?? `🔌 ${c}`))].filter(Boolean);
|
|
221
|
+
return labels.length ? capLine(labels.join(" · ")) : "";
|
|
222
|
+
}
|
|
223
|
+
const cmd = codexShellCommand(input);
|
|
224
|
+
if (cmd)
|
|
225
|
+
return capLine(labelShell(cmd, level));
|
|
226
|
+
// A JS snippet with no tools.* calls: still work happening, name it as such.
|
|
227
|
+
return typeof input === "string" && input.trim() ? "⚙️ 執行程式碼" : "";
|
|
228
|
+
}
|
|
229
|
+
// kiro built-in file ops
|
|
230
|
+
case "fs_read": {
|
|
231
|
+
const ops = inp.operations;
|
|
232
|
+
const p = ops?.[0]?.path ?? inp.path ?? "";
|
|
233
|
+
return p ? capLine(`📄 讀取檔案:${shortPath(redactSecrets(String(p)))}`) : "📄 讀取檔案";
|
|
234
|
+
}
|
|
235
|
+
case "fs_write": {
|
|
236
|
+
const p = inp.path ?? "";
|
|
237
|
+
return p ? capLine(`✏️ 編輯檔案:${shortPath(redactSecrets(String(p)))}`) : "✏️ 編輯檔案";
|
|
238
|
+
}
|
|
239
|
+
// opencode built-ins
|
|
240
|
+
case "read":
|
|
241
|
+
return inp.filePath ? capLine(`📄 讀取檔案:${shortPath(redactSecrets(String(inp.filePath)))}`) : "📄 讀取檔案";
|
|
242
|
+
case "edit":
|
|
243
|
+
case "write":
|
|
244
|
+
return inp.filePath ? capLine(`✏️ 編輯檔案:${shortPath(redactSecrets(String(inp.filePath)))}`) : "✏️ 編輯檔案";
|
|
245
|
+
case "glob":
|
|
246
|
+
case "grep":
|
|
247
|
+
return "🔍 搜尋程式碼";
|
|
248
|
+
case "webfetch":
|
|
249
|
+
return "🌐 讀取網頁";
|
|
250
|
+
case "todowrite":
|
|
251
|
+
case "todoread":
|
|
252
|
+
return "";
|
|
253
|
+
}
|
|
254
|
+
// Unknown tool: show its name, nothing else — inputs of unknown tools are
|
|
255
|
+
// the highest-risk place for secrets.
|
|
256
|
+
return capLine(`🔧 ${name}`);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Per-turn progress accumulator: dedupes consecutive repeats, keeps a rolling
|
|
260
|
+
* window of the latest lines, renders to the bubble block.
|
|
261
|
+
*/
|
|
262
|
+
export class ProgressAccumulator {
|
|
263
|
+
maxLines;
|
|
264
|
+
lines = [];
|
|
265
|
+
constructor(maxLines = 8) {
|
|
266
|
+
this.maxLines = maxLines;
|
|
267
|
+
}
|
|
268
|
+
/** Add a labelled line. Empty labels are ignored. Returns true when the rendered block changed. */
|
|
269
|
+
add(label) {
|
|
270
|
+
if (!label)
|
|
271
|
+
return false;
|
|
272
|
+
if (this.lines[this.lines.length - 1] === label)
|
|
273
|
+
return false;
|
|
274
|
+
this.lines.push(label);
|
|
275
|
+
if (this.lines.length > this.maxLines)
|
|
276
|
+
this.lines.splice(0, this.lines.length - this.maxLines);
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
reset() {
|
|
280
|
+
this.lines = [];
|
|
281
|
+
}
|
|
282
|
+
isEmpty() {
|
|
283
|
+
return this.lines.length === 0;
|
|
284
|
+
}
|
|
285
|
+
render() {
|
|
286
|
+
return this.lines.join("\n");
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=tool-progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-progress.js","sourceRoot":"","sources":["../src/tool-progress.ts"],"names":[],"mappings":"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"}
|
package/dist/topic-commands.d.ts
CHANGED
|
@@ -24,6 +24,13 @@ export declare function parsePauseWakeCommand(text: string): {
|
|
|
24
24
|
instance?: string;
|
|
25
25
|
} | null;
|
|
26
26
|
export declare function compactCommandForBackend(backend: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Full conversation-reset command for a backend NAME. Keep this routing-only
|
|
29
|
+
* lookup in sync with CliBackend.getClearCommand(); the fleet process does not
|
|
30
|
+
* own the backend object that lives inside each daemon.
|
|
31
|
+
*/
|
|
32
|
+
export declare function clearCommandForBackend(backend: string): string | null;
|
|
33
|
+
export declare const CLEAR_UNSUPPORTED_MSG = "\u26A0\uFE0F Clear not supported for this backend";
|
|
27
34
|
/**
|
|
28
35
|
* Extract context-usage % from a captured CLI pane. Scans bottom-up so the
|
|
29
36
|
* MOST RECENT prompt wins (a captured scrollback may hold several). Covers the
|
|
@@ -99,6 +106,25 @@ export declare class TopicCommands {
|
|
|
99
106
|
getCtxText(instanceName: string): Promise<string>;
|
|
100
107
|
/** Send the backend-appropriate compact command to an instance's tmux pane */
|
|
101
108
|
sendCompact(instanceName: string): Promise<string>;
|
|
109
|
+
/** Whether the instance backend exposes a verified full-reset command. */
|
|
110
|
+
supportsClear(instanceName: string): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Steer: interject a message into the instance's CURRENT turn. The daemon
|
|
113
|
+
* pastes it into the busy CLI instead of queueing for idle (falling back to
|
|
114
|
+
* the queue if the TUI swallows busy input — see Daemon.steerMessage).
|
|
115
|
+
*/
|
|
116
|
+
/**
|
|
117
|
+
* Backends whose TUI accepts a busy-pane paste as steering input,
|
|
118
|
+
* live-verified: claude-code and codex buffer-then-submit at the turn
|
|
119
|
+
* boundary, grok accepts it in its input line. kiro's legacy TUI swallows
|
|
120
|
+
* the paste outright, and opencode/antigravity are unverified — for those
|
|
121
|
+
* the user gets an honest "not supported" instead of a silent queue
|
|
122
|
+
* fallback that looks like a steer but behaves like a normal message.
|
|
123
|
+
*/
|
|
124
|
+
private static STEER_SUPPORTED_BACKENDS;
|
|
125
|
+
sendSteer(instanceName: string, content: string, msg: Pick<InboundMessage, "chatId" | "messageId" | "username" | "userId" | "threadId" | "adapterId" | "source">): string;
|
|
126
|
+
/** Send the backend-appropriate full conversation reset through raw_paste. */
|
|
127
|
+
sendClear(instanceName: string): Promise<string>;
|
|
102
128
|
/** Send a backend-appropriate session-save command to a fleet-topic instance. */
|
|
103
129
|
sendSave(instanceName: string, filename: string): Promise<string>;
|
|
104
130
|
private handleRestartCommand;
|
package/dist/topic-commands.js
CHANGED
|
@@ -82,6 +82,28 @@ export function compactCommandForBackend(backend) {
|
|
|
82
82
|
return "/clear";
|
|
83
83
|
return "/compact";
|
|
84
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Full conversation-reset command for a backend NAME. Keep this routing-only
|
|
87
|
+
* lookup in sync with CliBackend.getClearCommand(); the fleet process does not
|
|
88
|
+
* own the backend object that lives inside each daemon.
|
|
89
|
+
*/
|
|
90
|
+
export function clearCommandForBackend(backend) {
|
|
91
|
+
switch (backend) {
|
|
92
|
+
case "claude-code":
|
|
93
|
+
case "codex":
|
|
94
|
+
case "kiro-cli":
|
|
95
|
+
case "antigravity":
|
|
96
|
+
case "opencode":
|
|
97
|
+
case "mock":
|
|
98
|
+
return "/clear";
|
|
99
|
+
case "grok":
|
|
100
|
+
return "/new";
|
|
101
|
+
case "gemini-cli":
|
|
102
|
+
default:
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
export const CLEAR_UNSUPPORTED_MSG = "⚠️ Clear not supported for this backend";
|
|
85
107
|
/**
|
|
86
108
|
* Extract context-usage % from a captured CLI pane. Scans bottom-up so the
|
|
87
109
|
* MOST RECENT prompt wins (a captured scrollback may hold several). Covers the
|
|
@@ -400,6 +422,40 @@ export class TopicCommands {
|
|
|
400
422
|
await adapter.sendText(msg.chatId, result, { threadId: msg.threadId });
|
|
401
423
|
return true;
|
|
402
424
|
}
|
|
425
|
+
if (text === "/steer" || text.startsWith("/steer ") || text.startsWith("/steer@")) {
|
|
426
|
+
const adapter = this.getReplyAdapter(msg);
|
|
427
|
+
if (!adapter)
|
|
428
|
+
return false;
|
|
429
|
+
// Deliberately NOT admin-gated: anyone who can speak in this topic can
|
|
430
|
+
// already send the instance a message; /steer only changes WHEN it lands
|
|
431
|
+
// (mid-turn instead of after), and it goes through the full [user:]
|
|
432
|
+
// formatting — unlike /raw, which bypasses it and is gated.
|
|
433
|
+
const content = text.replace(/^\/steer(@\S+)?/, "").trim();
|
|
434
|
+
if (!content) {
|
|
435
|
+
await adapter.sendText(msg.chatId, t("steer.usage"), { threadId: msg.threadId });
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
const result = this.sendSteer(instanceName, content, msg);
|
|
439
|
+
await adapter.sendText(msg.chatId, result, { threadId: msg.threadId });
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
if (text === "/clear" || text.startsWith("/clear@")) {
|
|
443
|
+
const adapter = this.getReplyAdapter(msg);
|
|
444
|
+
if (!adapter)
|
|
445
|
+
return false;
|
|
446
|
+
if (!this.ctx.isFleetAdmin(msg.userId, msg.adapterId)) {
|
|
447
|
+
await adapter.sendText(msg.chatId, t("permission.denied"), { threadId: msg.threadId });
|
|
448
|
+
return true;
|
|
449
|
+
}
|
|
450
|
+
if (!this.ctx.promptClearConfirmation) {
|
|
451
|
+
await adapter.sendText(msg.chatId, t("clear.prompt_unavailable"), { threadId: msg.threadId });
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
const fallback = await this.ctx.promptClearConfirmation(instanceName, msg.threadId ?? msg.chatId, adapter, msg.chatId, msg.threadId);
|
|
455
|
+
if (fallback)
|
|
456
|
+
await adapter.sendText(msg.chatId, fallback, { threadId: msg.threadId });
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
403
459
|
if (text === "/cancel" || text.startsWith("/cancel@")) {
|
|
404
460
|
const adapter = this.getReplyAdapter(msg);
|
|
405
461
|
if (!adapter)
|
|
@@ -489,6 +545,60 @@ export class TopicCommands {
|
|
|
489
545
|
}
|
|
490
546
|
return "❌ Instance not connected (IPC unavailable)";
|
|
491
547
|
}
|
|
548
|
+
/** Whether the instance backend exposes a verified full-reset command. */
|
|
549
|
+
supportsClear(instanceName) {
|
|
550
|
+
return clearCommandForBackend(this.effectiveBackend(instanceName)) !== null;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Steer: interject a message into the instance's CURRENT turn. The daemon
|
|
554
|
+
* pastes it into the busy CLI instead of queueing for idle (falling back to
|
|
555
|
+
* the queue if the TUI swallows busy input — see Daemon.steerMessage).
|
|
556
|
+
*/
|
|
557
|
+
/**
|
|
558
|
+
* Backends whose TUI accepts a busy-pane paste as steering input,
|
|
559
|
+
* live-verified: claude-code and codex buffer-then-submit at the turn
|
|
560
|
+
* boundary, grok accepts it in its input line. kiro's legacy TUI swallows
|
|
561
|
+
* the paste outright, and opencode/antigravity are unverified — for those
|
|
562
|
+
* the user gets an honest "not supported" instead of a silent queue
|
|
563
|
+
* fallback that looks like a steer but behaves like a normal message.
|
|
564
|
+
*/
|
|
565
|
+
static STEER_SUPPORTED_BACKENDS = new Set(["claude-code", "codex", "grok", "mock"]);
|
|
566
|
+
sendSteer(instanceName, content, msg) {
|
|
567
|
+
const backend = this.effectiveBackend(instanceName);
|
|
568
|
+
if (!TopicCommands.STEER_SUPPORTED_BACKENDS.has(backend)) {
|
|
569
|
+
return t("steer.unsupported", backend);
|
|
570
|
+
}
|
|
571
|
+
const ipc = this.ctx.instanceIpcClients.get(instanceName);
|
|
572
|
+
if (!ipc?.connected)
|
|
573
|
+
return t("steer.not_connected");
|
|
574
|
+
ipc.send({
|
|
575
|
+
type: "steer",
|
|
576
|
+
content,
|
|
577
|
+
meta: {
|
|
578
|
+
chat_id: msg.chatId,
|
|
579
|
+
message_id: msg.messageId ?? "",
|
|
580
|
+
user: msg.username,
|
|
581
|
+
user_id: msg.userId,
|
|
582
|
+
thread_id: msg.threadId ?? "",
|
|
583
|
+
adapter_id: msg.adapterId ?? "",
|
|
584
|
+
source: msg.source,
|
|
585
|
+
},
|
|
586
|
+
});
|
|
587
|
+
return t("steer.sent", instanceName);
|
|
588
|
+
}
|
|
589
|
+
/** Send the backend-appropriate full conversation reset through raw_paste. */
|
|
590
|
+
async sendClear(instanceName) {
|
|
591
|
+
const backend = this.effectiveBackend(instanceName);
|
|
592
|
+
const cmd = clearCommandForBackend(backend);
|
|
593
|
+
if (!cmd)
|
|
594
|
+
return CLEAR_UNSUPPORTED_MSG;
|
|
595
|
+
const ipc = this.ctx.instanceIpcClients.get(instanceName);
|
|
596
|
+
if (ipc?.connected) {
|
|
597
|
+
ipc.send({ type: "raw_paste", content: cmd });
|
|
598
|
+
return t("clear.sent", cmd);
|
|
599
|
+
}
|
|
600
|
+
return t("clear.not_connected");
|
|
601
|
+
}
|
|
492
602
|
/** Send a backend-appropriate session-save command to a fleet-topic instance. */
|
|
493
603
|
async sendSave(instanceName, filename) {
|
|
494
604
|
const classicBackend = this.ctx.classicChannels?.getChannelIdByInstance(instanceName)
|
|
@@ -707,11 +817,13 @@ export class TopicCommands {
|
|
|
707
817
|
await adapter.sendText(chatId, t("not_authorized"), { threadId });
|
|
708
818
|
return;
|
|
709
819
|
}
|
|
710
|
-
await adapter.sendText(chatId, t("update.
|
|
820
|
+
const sent = await adapter.sendText(chatId, t("update.progress.preparing", 0), { threadId });
|
|
821
|
+
this.ctx.beginUpdateProgress?.(adapter, chatId, threadId, sent.messageId);
|
|
711
822
|
const currentVersion = createRequire(import.meta.url)("../package.json").version ?? "";
|
|
712
823
|
const updateCmd = currentVersion.includes("beta") ? "agend update --beta" : "agend update";
|
|
713
824
|
const { spawn } = await import("node:child_process");
|
|
714
825
|
const child = spawn("sh", ["-c", `sleep 2 && ${updateCmd}`], { detached: true, stdio: "ignore" });
|
|
826
|
+
child.once("error", err => this.ctx.failUpdateProgress?.(err.message));
|
|
715
827
|
child.unref();
|
|
716
828
|
}
|
|
717
829
|
async handleDoctorCommand(msg) {
|
|
@@ -870,6 +982,8 @@ export class TopicCommands {
|
|
|
870
982
|
{ command: "dashboard", description: "🔒 Get dashboard URLs" },
|
|
871
983
|
{ command: "ctx", description: "Show context usage" },
|
|
872
984
|
{ command: "compact", description: "Compact agent context" },
|
|
985
|
+
{ command: "steer", description: "Interject into the current task" },
|
|
986
|
+
{ command: "clear", description: "🔒 Clear agent conversation context" },
|
|
873
987
|
{ command: "model", description: "🔒 Switch model (admin only)" },
|
|
874
988
|
{ command: "effort", description: "🔒 Set reasoning effort (admin only)" },
|
|
875
989
|
{ command: "pause", description: "🔒 Pause an idle instance" },
|
|
@@ -902,6 +1016,8 @@ export class TopicCommands {
|
|
|
902
1016
|
{ command: "start", description: "🔒 Start an agent in this chat" },
|
|
903
1017
|
{ command: "stop", description: "🔒 Stop the agent" },
|
|
904
1018
|
{ command: "compact", description: "🔒 Compact agent context" },
|
|
1019
|
+
{ command: "steer", description: "Interject into the current task" },
|
|
1020
|
+
{ command: "clear", description: "🔒 Clear agent conversation context" },
|
|
905
1021
|
{ command: "model", description: "🔒 Switch model (admin only)" },
|
|
906
1022
|
{ command: "effort", description: "🔒 Set reasoning effort (admin only)" },
|
|
907
1023
|
{ command: "pause", description: "🔒 Pause the agent" },
|