@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.
Files changed (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2 -2
  3. package/README.zh-TW.md +2 -2
  4. package/dist/backend/antigravity.d.ts +1 -0
  5. package/dist/backend/antigravity.js +1 -0
  6. package/dist/backend/antigravity.js.map +1 -1
  7. package/dist/backend/claude-code.d.ts +1 -0
  8. package/dist/backend/claude-code.js +24 -2
  9. package/dist/backend/claude-code.js.map +1 -1
  10. package/dist/backend/codex.d.ts +1 -0
  11. package/dist/backend/codex.js +43 -4
  12. package/dist/backend/codex.js.map +1 -1
  13. package/dist/backend/gemini-cli.d.ts +1 -0
  14. package/dist/backend/gemini-cli.js +1 -0
  15. package/dist/backend/gemini-cli.js.map +1 -1
  16. package/dist/backend/grok.d.ts +1 -0
  17. package/dist/backend/grok.js +1 -0
  18. package/dist/backend/grok.js.map +1 -1
  19. package/dist/backend/kiro.d.ts +1 -0
  20. package/dist/backend/kiro.js +1 -0
  21. package/dist/backend/kiro.js.map +1 -1
  22. package/dist/backend/mock.d.ts +1 -0
  23. package/dist/backend/mock.js +1 -0
  24. package/dist/backend/mock.js.map +1 -1
  25. package/dist/backend/opencode.d.ts +40 -0
  26. package/dist/backend/opencode.js +83 -5
  27. package/dist/backend/opencode.js.map +1 -1
  28. package/dist/backend/types.d.ts +10 -0
  29. package/dist/backend/types.js +7 -0
  30. package/dist/backend/types.js.map +1 -1
  31. package/dist/channel/adapters/discord.js +24 -7
  32. package/dist/channel/adapters/discord.js.map +1 -1
  33. package/dist/channel/mcp-server.js +6 -20
  34. package/dist/channel/mcp-server.js.map +1 -1
  35. package/dist/channel/mcp-tools.js +1 -1
  36. package/dist/channel/mcp-tools.js.map +1 -1
  37. package/dist/channel/types.d.ts +1 -1
  38. package/dist/classic-channel-manager.d.ts +34 -3
  39. package/dist/classic-channel-manager.js +190 -31
  40. package/dist/classic-channel-manager.js.map +1 -1
  41. package/dist/cli.js +74 -23
  42. package/dist/cli.js.map +1 -1
  43. package/dist/completion-install.d.ts +70 -0
  44. package/dist/completion-install.js +152 -0
  45. package/dist/completion-install.js.map +1 -0
  46. package/dist/completion.d.ts +7 -1
  47. package/dist/completion.js +14 -4
  48. package/dist/completion.js.map +1 -1
  49. package/dist/config-validator.js +35 -7
  50. package/dist/config-validator.js.map +1 -1
  51. package/dist/config.js +1 -0
  52. package/dist/config.js.map +1 -1
  53. package/dist/daemon.d.ts +53 -9
  54. package/dist/daemon.js +222 -86
  55. package/dist/daemon.js.map +1 -1
  56. package/dist/fleet-context.d.ts +8 -0
  57. package/dist/fleet-manager.d.ts +136 -5
  58. package/dist/fleet-manager.js +1088 -316
  59. package/dist/fleet-manager.js.map +1 -1
  60. package/dist/general-knowledge/skills/backend-providers/SKILL.md +114 -0
  61. package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +3 -1
  62. package/dist/general-knowledge/skills/delegation-playbook/SKILL.md +52 -0
  63. package/dist/general-knowledge/skills/development-workflow/SKILL.md +28 -0
  64. package/dist/general-knowledge/skills/fleet-config/SKILL.md +1 -0
  65. package/dist/general-knowledge/skills/fleet-health/SKILL.md +1 -0
  66. package/dist/general-knowledge/skills/fleet-restart/SKILL.md +1 -0
  67. package/dist/general-knowledge/skills/instance-lifecycle/SKILL.md +1 -0
  68. package/dist/general-knowledge/skills/model-discovery/SKILL.md +1 -0
  69. package/dist/general-knowledge/skills/multi-channel/SKILL.md +1 -0
  70. package/dist/general-knowledge/skills/scheduling/SKILL.md +1 -0
  71. package/dist/general-knowledge/skills/session-management/SKILL.md +1 -0
  72. package/dist/general-knowledge/skills/tui-effort/SKILL.md +1 -0
  73. package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +30 -0
  74. package/dist/instance-lifecycle.d.ts +10 -0
  75. package/dist/instance-lifecycle.js +50 -33
  76. package/dist/instance-lifecycle.js.map +1 -1
  77. package/dist/instructions.d.ts +12 -0
  78. package/dist/instructions.js +33 -0
  79. package/dist/instructions.js.map +1 -1
  80. package/dist/locale.js +130 -0
  81. package/dist/locale.js.map +1 -1
  82. package/dist/outbound-schemas.d.ts +2 -1
  83. package/dist/outbound-schemas.js +1 -0
  84. package/dist/outbound-schemas.js.map +1 -1
  85. package/dist/quickstart.js +29 -2
  86. package/dist/quickstart.js.map +1 -1
  87. package/dist/restart-progress.d.ts +7 -1
  88. package/dist/restart-progress.js +27 -6
  89. package/dist/restart-progress.js.map +1 -1
  90. package/dist/setup-wizard.d.ts +4 -2
  91. package/dist/setup-wizard.js +2 -2
  92. package/dist/setup-wizard.js.map +1 -1
  93. package/dist/tool-progress.d.ts +40 -0
  94. package/dist/tool-progress.js +289 -0
  95. package/dist/tool-progress.js.map +1 -0
  96. package/dist/topic-commands.d.ts +26 -0
  97. package/dist/topic-commands.js +117 -1
  98. package/dist/topic-commands.js.map +1 -1
  99. package/dist/transcript-monitor.d.ts +15 -2
  100. package/dist/transcript-monitor.js +63 -17
  101. package/dist/transcript-monitor.js.map +1 -1
  102. package/dist/transcript-sources.d.ts +106 -0
  103. package/dist/transcript-sources.js +428 -0
  104. package/dist/transcript-sources.js.map +1 -0
  105. package/dist/types.d.ts +8 -0
  106. package/dist/ui/dashboard.html +5 -4
  107. package/dist/update-marker.d.ts +30 -0
  108. package/dist/update-marker.js +71 -20
  109. package/dist/update-marker.js.map +1 -1
  110. package/dist/update-progress.d.ts +6 -0
  111. package/dist/update-progress.js +29 -0
  112. package/dist/update-progress.js.map +1 -0
  113. package/dist/web-api.js +2 -2
  114. package/dist/web-api.js.map +1 -1
  115. package/dist/workflow-templates/default.md +2 -1
  116. package/package.json +2 -2
@@ -0,0 +1,428 @@
1
+ /**
2
+ * Per-backend tool-event sources for the transcript monitor.
3
+ *
4
+ * claude-code keeps its transcript path in statusline.json and is handled
5
+ * inside TranscriptMonitor itself (it predates this file). The sources here
6
+ * cover backends whose CLIs persist their conversation elsewhere:
7
+ *
8
+ * codex — rollout JSONL under <codex home>/sessions/YYYY/MM/DD/,
9
+ * matched to this instance by session_meta.cwd (sessions are a
10
+ * shared symlinked dir across instances, #507)
11
+ * kiro-cli — ~/.kiro/sessions/cli/<uuid>.jsonl with a sibling <uuid>.json
12
+ * carrying { cwd, updated_at }
13
+ * opencode — $XDG_DATA_HOME/opencode/opencode.db `part` table rows of
14
+ * data JSON { type: "tool", tool, state.input }, matched by the
15
+ * `session` table's directory column
16
+ *
17
+ * Common rules, learned the hard way (#528 traps):
18
+ * - No persisted byte offsets. Codex writes a fresh rollout per process and
19
+ * kiro/opencode keep full history — a stale offset is meaningless at best
20
+ * and replays history at worst.
21
+ * - First attach to a PRE-EXISTING transcript baselines to its end: only
22
+ * new work emits. A transcript that APPEARS after the source was created
23
+ * is this instance's own new session and is read from the start.
24
+ * - Every poll re-resolves which transcript is active. Pinning to the first
25
+ * one found silently goes blind when the CLI starts a new session.
26
+ */
27
+ import { closeSync, existsSync, openSync, readdirSync, readFileSync, readSync, statSync } from "node:fs";
28
+ import { open, stat } from "node:fs/promises";
29
+ import { homedir } from "node:os";
30
+ import { join } from "node:path";
31
+ const EMPTY = { toolUses: [], toolResults: [], assistantTexts: [] };
32
+ function emptyEvents() {
33
+ return { toolUses: [], toolResults: [], assistantTexts: [] };
34
+ }
35
+ /** Shared JSONL tailer: byte-offset incremental reads of a single file. */
36
+ async function readNewLines(path, fromOffset) {
37
+ const stats = await stat(path);
38
+ if (stats.size <= fromOffset)
39
+ return { lines: [], newOffset: fromOffset };
40
+ const fh = await open(path, "r");
41
+ try {
42
+ const length = stats.size - fromOffset;
43
+ const buffer = Buffer.alloc(length);
44
+ await fh.read(buffer, 0, length, fromOffset);
45
+ return { lines: buffer.toString("utf-8").split("\n").filter(l => l.trim()), newOffset: stats.size };
46
+ }
47
+ finally {
48
+ await fh.close();
49
+ }
50
+ }
51
+ /* ------------------------------------------------------------------ codex */
52
+ /**
53
+ * Follows the newest rollout JSONL whose session_meta.cwd matches this
54
+ * instance's working directory. Rollouts are date-sharded and shared across
55
+ * instances, so cwd is the only reliable ownership signal.
56
+ */
57
+ export class CodexRolloutSource {
58
+ workingDirectory;
59
+ sessionsDir;
60
+ currentFile = null;
61
+ byteOffset = 0;
62
+ createdAt;
63
+ /** Files whose session_meta was read and did NOT match our cwd. */
64
+ rejected = new Set();
65
+ constructor(workingDirectory, sessionsDir = join(process.env.CODEX_HOME?.trim() || join(homedir(), ".codex"), "sessions"), now = Date.now()) {
66
+ this.workingDirectory = workingDirectory;
67
+ this.sessionsDir = sessionsDir;
68
+ this.createdAt = now;
69
+ }
70
+ reset() {
71
+ this.currentFile = null;
72
+ this.byteOffset = 0;
73
+ }
74
+ /** Newest rollout files first, bounded to the last two date shards. */
75
+ candidateFiles() {
76
+ const out = [];
77
+ const walk = (dir, depth) => {
78
+ let entries;
79
+ try {
80
+ entries = readdirSync(dir);
81
+ }
82
+ catch {
83
+ return;
84
+ }
85
+ // Date-sharded YYYY/MM/DD tree: at each level only the two newest
86
+ // subdirs can contain today's/yesterday's rollouts.
87
+ const dirs = [];
88
+ for (const e of entries) {
89
+ const p = join(dir, e);
90
+ try {
91
+ const st = statSync(p);
92
+ if (st.isDirectory())
93
+ dirs.push(e);
94
+ else if (depth >= 3 && e.startsWith("rollout-") && e.endsWith(".jsonl")) {
95
+ out.push({ path: p, mtimeMs: st.mtimeMs });
96
+ }
97
+ }
98
+ catch { /* raced with deletion */ }
99
+ }
100
+ if (depth < 3) {
101
+ for (const d of dirs.sort().reverse().slice(0, 2))
102
+ walk(join(dir, d), depth + 1);
103
+ }
104
+ };
105
+ walk(this.sessionsDir, 0);
106
+ return out.sort((a, b) => b.mtimeMs - a.mtimeMs);
107
+ }
108
+ fileBelongsToUs(path) {
109
+ if (this.rejected.has(path))
110
+ return false;
111
+ try {
112
+ // session_meta is the first line. It can carry long instructions, so
113
+ // give it headroom — but never read the whole rollout.
114
+ const fd = openSync(path, "r");
115
+ let head;
116
+ try {
117
+ const buf = Buffer.alloc(65536);
118
+ const bytes = readSync(fd, buf, 0, buf.length, 0);
119
+ head = buf.toString("utf-8", 0, bytes);
120
+ }
121
+ finally {
122
+ closeSync(fd);
123
+ }
124
+ const firstLine = head.split("\n")[0];
125
+ const meta = JSON.parse(firstLine);
126
+ const cwd = meta?.payload?.cwd;
127
+ if (meta?.type === "session_meta" && cwd === this.workingDirectory)
128
+ return true;
129
+ this.rejected.add(path);
130
+ return false;
131
+ }
132
+ catch {
133
+ // First line unreadable/partial — retry next poll, do not cache the verdict.
134
+ return false;
135
+ }
136
+ }
137
+ async poll() {
138
+ // Re-resolve every poll: a restarted codex writes a NEW rollout, and
139
+ // staying pinned to the old one goes silently blind (#528 trap 1).
140
+ const candidates = this.candidateFiles();
141
+ const active = candidates.find(c => this.fileBelongsToUs(c.path));
142
+ if (!active)
143
+ return EMPTY;
144
+ if (active.path !== this.currentFile) {
145
+ this.currentFile = active.path;
146
+ // A rollout born after this source existed is our own fresh session —
147
+ // read it from the start. A pre-existing one is history — baseline EOF.
148
+ if (active.mtimeMs >= this.createdAt) {
149
+ this.byteOffset = 0;
150
+ }
151
+ else {
152
+ try {
153
+ this.byteOffset = (await stat(active.path)).size;
154
+ }
155
+ catch {
156
+ this.byteOffset = 0;
157
+ }
158
+ return EMPTY;
159
+ }
160
+ }
161
+ const { lines, newOffset } = await readNewLines(this.currentFile, this.byteOffset);
162
+ this.byteOffset = newOffset;
163
+ const events = emptyEvents();
164
+ for (const line of lines) {
165
+ let entry;
166
+ try {
167
+ entry = JSON.parse(line);
168
+ }
169
+ catch {
170
+ continue;
171
+ }
172
+ if (entry.type !== "response_item")
173
+ continue;
174
+ const p = entry.payload;
175
+ if (!p)
176
+ continue;
177
+ if (p.type === "function_call") {
178
+ let input = p.arguments;
179
+ if (typeof input === "string") {
180
+ try {
181
+ input = JSON.parse(input);
182
+ }
183
+ catch { /* keep raw */ }
184
+ }
185
+ events.toolUses.push({ name: String(p.name ?? "unknown"), input });
186
+ }
187
+ else if (p.type === "custom_tool_call") {
188
+ events.toolUses.push({ name: String(p.name ?? "unknown"), input: p.input });
189
+ }
190
+ else if (p.type === "local_shell_call") {
191
+ const action = p.action;
192
+ events.toolUses.push({ name: "shell", input: { command: action?.command } });
193
+ }
194
+ else if (p.type === "function_call_output" || p.type === "custom_tool_call_output") {
195
+ events.toolResults.push({ name: String(p.name ?? "unknown") });
196
+ }
197
+ else if (p.type === "message" && p.role === "assistant") {
198
+ const content = p.content;
199
+ for (const block of content ?? []) {
200
+ const text = block.text;
201
+ if (typeof text === "string" && text.trim())
202
+ events.assistantTexts.push(text);
203
+ }
204
+ }
205
+ }
206
+ return events;
207
+ }
208
+ }
209
+ /* -------------------------------------------------------------------- kiro */
210
+ /**
211
+ * Follows the newest kiro session whose metadata cwd matches this instance's
212
+ * working directory. Session transcript is <uuid>.jsonl; ownership and
213
+ * recency come from the sibling <uuid>.json ({ cwd, updated_at,
214
+ * session_created_reason }).
215
+ */
216
+ export class KiroSessionSource {
217
+ workingDirectory;
218
+ sessionsDir;
219
+ currentFile = null;
220
+ byteOffset = 0;
221
+ createdAt;
222
+ constructor(workingDirectory, sessionsDir = join(homedir(), ".kiro", "sessions", "cli"), now = Date.now()) {
223
+ this.workingDirectory = workingDirectory;
224
+ this.sessionsDir = sessionsDir;
225
+ this.createdAt = now;
226
+ }
227
+ reset() {
228
+ this.currentFile = null;
229
+ this.byteOffset = 0;
230
+ }
231
+ resolveActiveSession() {
232
+ let entries;
233
+ try {
234
+ entries = readdirSync(this.sessionsDir);
235
+ }
236
+ catch {
237
+ return null;
238
+ }
239
+ let best = null;
240
+ for (const e of entries) {
241
+ if (!e.endsWith(".json") || e.endsWith(".jsonl"))
242
+ continue;
243
+ const metaPath = join(this.sessionsDir, e);
244
+ try {
245
+ const meta = JSON.parse(readFileSync(metaPath, "utf-8"));
246
+ if (meta.cwd !== this.workingDirectory)
247
+ continue;
248
+ // Subagent sessions are children of a turn already being reported.
249
+ if (meta.session_created_reason === "subagent")
250
+ continue;
251
+ const updated = Date.parse(meta.updated_at ?? "") || 0;
252
+ const created = Date.parse(meta.created_at ?? "") || 0;
253
+ if (!best || updated > best.updated) {
254
+ const jsonlPath = join(this.sessionsDir, e.replace(/\.json$/, ".jsonl"));
255
+ best = { jsonlPath, updated, createdAtMs: created };
256
+ }
257
+ }
258
+ catch { /* partially written metadata — next poll */ }
259
+ }
260
+ return best && existsSync(best.jsonlPath)
261
+ ? { jsonlPath: best.jsonlPath, createdAtMs: best.createdAtMs }
262
+ : null;
263
+ }
264
+ async poll() {
265
+ const active = this.resolveActiveSession();
266
+ if (!active)
267
+ return EMPTY;
268
+ if (active.jsonlPath !== this.currentFile) {
269
+ this.currentFile = active.jsonlPath;
270
+ if (active.createdAtMs >= this.createdAt) {
271
+ this.byteOffset = 0; // our own fresh session — observable from the start
272
+ }
273
+ else {
274
+ try {
275
+ this.byteOffset = (await stat(active.jsonlPath)).size;
276
+ }
277
+ catch {
278
+ this.byteOffset = 0;
279
+ }
280
+ return EMPTY;
281
+ }
282
+ }
283
+ const { lines, newOffset } = await readNewLines(this.currentFile, this.byteOffset);
284
+ this.byteOffset = newOffset;
285
+ const events = emptyEvents();
286
+ for (const line of lines) {
287
+ let entry;
288
+ try {
289
+ entry = JSON.parse(line);
290
+ }
291
+ catch {
292
+ continue;
293
+ }
294
+ collectKiroEvents(entry, events);
295
+ }
296
+ return events;
297
+ }
298
+ }
299
+ /**
300
+ * Kiro nests { kind: "toolUse", data: { name, input } } blocks inside
301
+ * AssistantMessage content; exact nesting has shifted across kiro versions,
302
+ * so walk the tree for the kind markers instead of hardcoding a path.
303
+ */
304
+ function collectKiroEvents(node, out, depth = 0) {
305
+ if (depth > 8 || node === null || typeof node !== "object")
306
+ return;
307
+ if (Array.isArray(node)) {
308
+ for (const item of node)
309
+ collectKiroEvents(item, out, depth + 1);
310
+ return;
311
+ }
312
+ const obj = node;
313
+ if (obj.kind === "toolUse" && obj.data && typeof obj.data === "object") {
314
+ const d = obj.data;
315
+ out.toolUses.push({ name: String(d.name ?? "unknown"), input: d.input });
316
+ return;
317
+ }
318
+ if (obj.kind === "toolResult" && obj.data && typeof obj.data === "object") {
319
+ out.toolResults.push({ name: "toolResult" });
320
+ return;
321
+ }
322
+ for (const value of Object.values(obj))
323
+ collectKiroEvents(value, out, depth + 1);
324
+ }
325
+ function loadSqlite() {
326
+ try {
327
+ return process
328
+ .getBuiltinModule?.("node:sqlite");
329
+ }
330
+ catch {
331
+ return undefined;
332
+ }
333
+ }
334
+ /**
335
+ * Reads tool parts from opencode's sqlite DB for the newest top-level
336
+ * session in this instance's working directory. Rows are cursored by
337
+ * time_created, which is immutable — a part that later flips from `running`
338
+ * to `completed` only changes time_updated, so each tool use emits once.
339
+ *
340
+ * Requires node:sqlite (Node ≥22.13); silently inert otherwise, matching the
341
+ * session-resume feature's degradation.
342
+ */
343
+ export class OpenCodeDbSource {
344
+ workingDirectory;
345
+ dbPath;
346
+ sessionId = null;
347
+ partCursor = 0;
348
+ createdAt;
349
+ constructor(workingDirectory, dbPath = join(process.env.XDG_DATA_HOME || join(homedir(), ".local", "share"), "opencode", "opencode.db"), now = Date.now()) {
350
+ this.workingDirectory = workingDirectory;
351
+ this.dbPath = dbPath;
352
+ this.createdAt = now;
353
+ }
354
+ reset() {
355
+ this.sessionId = null;
356
+ this.partCursor = 0;
357
+ }
358
+ async poll() {
359
+ const sqlite = loadSqlite();
360
+ if (!sqlite || !existsSync(this.dbPath))
361
+ return EMPTY;
362
+ let db;
363
+ try {
364
+ db = new sqlite.DatabaseSync(this.dbPath, { readOnly: true });
365
+ }
366
+ catch {
367
+ return EMPTY;
368
+ }
369
+ try {
370
+ const session = db.prepare("SELECT id, time_created FROM session WHERE directory = ? AND parent_id IS NULL ORDER BY time_updated DESC LIMIT 1").get(this.workingDirectory);
371
+ if (!session)
372
+ return EMPTY;
373
+ if (session.id !== this.sessionId) {
374
+ this.sessionId = session.id;
375
+ // Fresh session started under us → report from its beginning;
376
+ // pre-existing session → only new parts.
377
+ this.partCursor = session.time_created >= this.createdAt ? 0 : Date.now();
378
+ }
379
+ const rows = db.prepare("SELECT data, time_created FROM part WHERE session_id = ? AND time_created > ? ORDER BY time_created ASC LIMIT 100").all(this.sessionId, this.partCursor);
380
+ const events = emptyEvents();
381
+ for (const row of rows) {
382
+ this.partCursor = Math.max(this.partCursor, row.time_created);
383
+ let data;
384
+ try {
385
+ data = JSON.parse(row.data);
386
+ }
387
+ catch {
388
+ continue;
389
+ }
390
+ if (data.type === "tool") {
391
+ const state = data.state;
392
+ events.toolUses.push({ name: String(data.tool ?? "unknown"), input: state?.input });
393
+ }
394
+ else if (data.type === "text") {
395
+ const text = data.text;
396
+ if (typeof text === "string" && text.trim())
397
+ events.assistantTexts.push(text);
398
+ }
399
+ }
400
+ return events;
401
+ }
402
+ catch {
403
+ return EMPTY;
404
+ }
405
+ finally {
406
+ try {
407
+ db.close();
408
+ }
409
+ catch { /* already closed */ }
410
+ }
411
+ }
412
+ }
413
+ /* ----------------------------------------------------------------- factory */
414
+ /**
415
+ * Source for a backend, or null for backends handled elsewhere (claude-code
416
+ * lives inside TranscriptMonitor) and backends with no known source
417
+ * (antigravity, gemini-cli — nothing usable found on disk; grok has
418
+ * events.jsonl with tool names only and can be added later).
419
+ */
420
+ export function createTranscriptSource(backend, workingDirectory) {
421
+ switch (backend) {
422
+ case "codex": return new CodexRolloutSource(workingDirectory);
423
+ case "kiro-cli": return new KiroSessionSource(workingDirectory);
424
+ case "opencode": return new OpenCodeDbSource(workingDirectory);
425
+ default: return null;
426
+ }
427
+ }
428
+ //# sourceMappingURL=transcript-sources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript-sources.js","sourceRoot":"","sources":["../src/transcript-sources.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -119,6 +119,12 @@ export interface InstanceConfig {
119
119
  kiro_ui?: "legacy" | "tui" | "v3";
120
120
  /** MCP tool profile: "full" (20 tools), "standard" (8), "minimal" (3). Default: "full" */
121
121
  tool_set?: string;
122
+ /**
123
+ * Tool-progress detail shown in the channel processing bubble.
124
+ * "standard" (default) shows semantic labels with no shell arguments;
125
+ * "verbose" adds truncated command previews; "off" disables the list.
126
+ */
127
+ tool_progress?: "off" | "standard" | "verbose";
122
128
  /** Skip non-essential subsystems (transcript monitor, context guardian, approval server, prompt detector) */
123
129
  lightweight?: boolean;
124
130
  /** System prompt — supports comma-separated file: paths for modularization */
@@ -166,6 +172,8 @@ export interface InstanceConfig {
166
172
  terminal?: TerminalConfig;
167
173
  /** Command to paste raw before each user message (e.g. "/chat load base.json") */
168
174
  pre_task_command?: string;
175
+ /** Per-backend options keyed by backend name (e.g. { codex: { provider: "glm" } }) */
176
+ backend_options?: Record<string, Record<string, unknown>>;
169
177
  }
170
178
  export interface WebhookConfig {
171
179
  url: string;
@@ -463,12 +463,13 @@ async function showCreateInstance() {
463
463
  let backendOpts = '<option value="">Use fleet default</option>';
464
464
  try {
465
465
  const bd = await api("GET", "/ui/backends");
466
- const first = (bd.backends || []).find(b => b.installed);
466
+ const first = (bd.backends || []).find(b => b.installed && !b.deprecated) || (bd.backends || []).find(b => b.installed);
467
467
  backendOpts += (bd.backends || []).map(b => {
468
- const label = b.installed ? b.name : `${b.name} (not installed)`;
468
+ let label = b.deprecated ? `${b.name} (deprecated)` : b.name;
469
+ if (!b.installed) label += " (not installed)";
469
470
  return `<option value="${b.name}" ${b.installed ? "" : "disabled"} ${b.name === first?.name ? "selected" : ""}>${label}</option>`;
470
471
  }).join("");
471
- } catch { backendOpts += ["claude-code","codex","gemini-cli","opencode","kiro-cli","antigravity","grok"].map(b => `<option value="${b}">${b}</option>`).join(""); }
472
+ } catch { backendOpts += ["claude-code","codex","opencode","kiro-cli","antigravity","grok","gemini-cli"].map(b => `<option value="${b}">${b === "gemini-cli" ? "gemini-cli (deprecated)" : b}</option>`).join(""); }
472
473
  ov.innerHTML = `<div class="form-card"><h2>Create Instance</h2>
473
474
  <div class="form-field"><label>Directory</label><input id="ci-dir" placeholder="Optional — auto-creates workspace if empty"></div>
474
475
  <div class="form-field"><label id="ci-topic-label">Topic Name</label><input id="ci-topic" placeholder="Auto from directory name"></div>
@@ -689,7 +690,7 @@ async function loadConfig() {
689
690
  <div class="card"><h3>Defaults</h3>
690
691
  <div class="form-field"><label>Backend</label>
691
692
  <select id="cfg-backend">
692
- ${["claude-code","codex","gemini-cli","opencode","kiro-cli","antigravity","grok"].map(b => `<option value="${b}" ${defs.backend===b?"selected":""}>${b}</option>`).join("")}
693
+ ${["claude-code","codex","opencode","kiro-cli","antigravity","grok","gemini-cli"].map(b => `<option value="${b}" ${defs.backend===b?"selected":""}>${b === "gemini-cli" ? "gemini-cli (deprecated)" : b}</option>`).join("")}
693
694
  </select></div>
694
695
  </div>
695
696
  <div class="card"><h3>Project Roots</h3>
@@ -4,6 +4,36 @@
4
4
  * one quiet window, not silence until someone notices.
5
5
  */
6
6
  export declare const UPDATE_MARKER_MAX_AGE_MS: number;
7
+ export type UpdateProgressStage = "preparing" | "downloading" | "installed" | "stopping" | "starting" | "complete" | "failed";
8
+ export interface UpdateProgressTarget {
9
+ adapterId: string;
10
+ chatId: string;
11
+ threadId?: string;
12
+ messageId: string;
13
+ }
14
+ export interface UpdateProgressState {
15
+ stage: UpdateProgressStage;
16
+ target: UpdateProgressTarget;
17
+ version?: string;
18
+ error?: string;
19
+ failedStage?: UpdateProgressStage;
20
+ }
21
+ export interface UpdateMarker {
22
+ startedAt: number;
23
+ pid: number;
24
+ progress?: UpdateProgressState;
25
+ }
26
+ /** Persist the channel message that `/update` will edit across process restart. */
27
+ export declare function beginUpdateProgress(dataDir: string, target: UpdateProgressTarget, now?: number): void;
28
+ /** Read the live progress contract shared by the old CLI and the new fleet. */
29
+ export declare function readUpdateProgress(dataDir: string): (UpdateMarker & {
30
+ progress: UpdateProgressState;
31
+ }) | null;
32
+ /** Advance the cross-process progress state without losing its message target. */
33
+ export declare function setUpdateProgressStage(dataDir: string, stage: UpdateProgressStage, details?: {
34
+ version?: string;
35
+ error?: string;
36
+ }): boolean;
7
37
  /** Called by `agend update` before it touches anything. */
8
38
  export declare function markUpdateInProgress(dataDir: string, now?: number): void;
9
39
  /** Called when the update finishes or gives up, and by the new fleet on startup. */
@@ -13,7 +13,7 @@
13
13
  * machine reboots) must not leave the fleet permanently unable to report a real
14
14
  * crash — a stale marker is ignored, and the next fleet startup deletes it.
15
15
  */
16
- import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
16
+ import { existsSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
17
17
  import { join } from "node:path";
18
18
  /**
19
19
  * How long a marker is believed. Long enough for a slow npm install plus a
@@ -25,16 +25,75 @@ const FILE = "update-in-progress.json";
25
25
  function markerPath(dataDir) {
26
26
  return join(dataDir, FILE);
27
27
  }
28
- /** Called by `agend update` before it touches anything. */
29
- export function markUpdateInProgress(dataDir, now = Date.now()) {
28
+ function readMarker(dataDir) {
29
+ try {
30
+ const parsed = JSON.parse(readFileSync(markerPath(dataDir), "utf-8"));
31
+ if (typeof parsed.startedAt !== "number" || !Number.isFinite(parsed.startedAt))
32
+ return null;
33
+ if (typeof parsed.pid !== "number" || !Number.isFinite(parsed.pid))
34
+ return null;
35
+ return parsed;
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ function writeMarker(dataDir, marker) {
42
+ const path = markerPath(dataDir);
43
+ const temp = `${path}.${process.pid}.${Date.now()}.tmp`;
30
44
  try {
31
- writeFileSync(markerPath(dataDir), JSON.stringify({ startedAt: now, pid: process.pid }));
45
+ writeFileSync(temp, JSON.stringify(marker), { mode: 0o600 });
46
+ renameSync(temp, path);
47
+ return true;
32
48
  }
33
49
  catch {
34
- // Best effort: failing to write the marker costs a few spurious alerts,
35
- // which is not a reason to abort someone's upgrade.
50
+ try {
51
+ unlinkSync(temp);
52
+ }
53
+ catch { /* best effort */ }
54
+ return false;
36
55
  }
37
56
  }
57
+ /** Persist the channel message that `/update` will edit across process restart. */
58
+ export function beginUpdateProgress(dataDir, target, now = Date.now()) {
59
+ writeMarker(dataDir, {
60
+ startedAt: now,
61
+ pid: process.pid,
62
+ progress: { stage: "preparing", target },
63
+ });
64
+ }
65
+ /** Read the live progress contract shared by the old CLI and the new fleet. */
66
+ export function readUpdateProgress(dataDir) {
67
+ const marker = readMarker(dataDir);
68
+ if (!marker?.progress?.target?.messageId || !marker.progress.target.adapterId)
69
+ return null;
70
+ return marker;
71
+ }
72
+ /** Advance the cross-process progress state without losing its message target. */
73
+ export function setUpdateProgressStage(dataDir, stage, details = {}) {
74
+ const marker = readMarker(dataDir);
75
+ if (!marker?.progress)
76
+ return false;
77
+ const previousStage = marker.progress.stage;
78
+ marker.pid = process.pid;
79
+ marker.progress = {
80
+ ...marker.progress,
81
+ stage,
82
+ ...(details.version !== undefined ? { version: details.version } : {}),
83
+ ...(details.error !== undefined ? { error: details.error.replace(/\s+/g, " ").trim().slice(0, 300) } : {}),
84
+ ...(stage === "failed" ? { failedStage: previousStage } : {}),
85
+ };
86
+ return writeMarker(dataDir, marker);
87
+ }
88
+ /** Called by `agend update` before it touches anything. */
89
+ export function markUpdateInProgress(dataDir, now = Date.now()) {
90
+ const existing = readMarker(dataDir);
91
+ writeMarker(dataDir, {
92
+ startedAt: existing?.startedAt ?? now,
93
+ pid: process.pid,
94
+ ...(existing?.progress ? { progress: existing.progress } : {}),
95
+ });
96
+ }
38
97
  /** Called when the update finishes or gives up, and by the new fleet on startup. */
39
98
  export function clearUpdateMarker(dataDir) {
40
99
  try {
@@ -47,23 +106,15 @@ export function clearUpdateMarker(dataDir) {
47
106
  * abandoned marker must not silence real incidents forever.
48
107
  */
49
108
  export function isUpdateInProgress(dataDir, now = Date.now()) {
50
- const path = markerPath(dataDir);
51
- if (!existsSync(path))
109
+ if (!existsSync(markerPath(dataDir)))
52
110
  return false;
53
- let startedAt = null;
54
- try {
55
- const parsed = JSON.parse(readFileSync(path, "utf-8"));
56
- if (typeof parsed.startedAt === "number" && Number.isFinite(parsed.startedAt)) {
57
- startedAt = parsed.startedAt;
58
- }
59
- }
60
- catch {
61
- // Truncated or hand-edited: treat as unknown age rather than as fresh.
62
- }
63
- if (startedAt === null)
111
+ const marker = readMarker(dataDir);
112
+ if (!marker)
113
+ return false;
114
+ if (marker.progress?.stage === "failed" || marker.progress?.stage === "complete")
64
115
  return false;
65
116
  // A clock jump backwards would otherwise make a marker look infinitely fresh.
66
- const age = now - startedAt;
117
+ const age = now - marker.startedAt;
67
118
  return age >= 0 && age < UPDATE_MARKER_MAX_AGE_MS;
68
119
  }
69
120
  //# sourceMappingURL=update-marker.js.map