iosm-cli 0.2.13 → 0.2.15

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 (78) hide show
  1. package/.npmignore +2 -0
  2. package/CHANGELOG.md +49 -0
  3. package/README.md +12 -2
  4. package/dist/cli/args.d.ts +1 -1
  5. package/dist/cli/args.d.ts.map +1 -1
  6. package/dist/cli/args.js +9 -2
  7. package/dist/cli/args.js.map +1 -1
  8. package/dist/core/auth-storage.d.ts.map +1 -1
  9. package/dist/core/auth-storage.js +17 -2
  10. package/dist/core/auth-storage.js.map +1 -1
  11. package/dist/core/command-dispatcher.d.ts +16 -0
  12. package/dist/core/command-dispatcher.d.ts.map +1 -0
  13. package/dist/core/command-dispatcher.js +678 -0
  14. package/dist/core/command-dispatcher.js.map +1 -0
  15. package/dist/core/model-registry.d.ts.map +1 -1
  16. package/dist/core/model-registry.js +13 -1
  17. package/dist/core/model-registry.js.map +1 -1
  18. package/dist/core/model-resolver.d.ts +2 -2
  19. package/dist/core/model-resolver.d.ts.map +1 -1
  20. package/dist/core/model-resolver.js +1 -2
  21. package/dist/core/model-resolver.js.map +1 -1
  22. package/dist/core/provider-policy.d.ts +7 -0
  23. package/dist/core/provider-policy.d.ts.map +1 -0
  24. package/dist/core/provider-policy.js +19 -0
  25. package/dist/core/provider-policy.js.map +1 -0
  26. package/dist/core/settings-manager.d.ts +25 -0
  27. package/dist/core/settings-manager.d.ts.map +1 -1
  28. package/dist/core/settings-manager.js +32 -0
  29. package/dist/core/settings-manager.js.map +1 -1
  30. package/dist/core/slash-commands.d.ts.map +1 -1
  31. package/dist/core/slash-commands.js +4 -1
  32. package/dist/core/slash-commands.js.map +1 -1
  33. package/dist/core/subagent-background-runs.d.ts +56 -0
  34. package/dist/core/subagent-background-runs.d.ts.map +1 -0
  35. package/dist/core/subagent-background-runs.js +275 -0
  36. package/dist/core/subagent-background-runs.js.map +1 -0
  37. package/dist/core/tools/task.d.ts.map +1 -1
  38. package/dist/core/tools/task.js +39 -35
  39. package/dist/core/tools/task.js.map +1 -1
  40. package/dist/main.d.ts.map +1 -1
  41. package/dist/main.js +16 -2
  42. package/dist/main.js.map +1 -1
  43. package/dist/modes/index.d.ts +1 -0
  44. package/dist/modes/index.d.ts.map +1 -1
  45. package/dist/modes/index.js +1 -0
  46. package/dist/modes/index.js.map +1 -1
  47. package/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  48. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  49. package/dist/modes/interactive/components/login-dialog.js +1 -4
  50. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  51. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  52. package/dist/modes/interactive/components/oauth-selector.js +1 -2
  53. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  54. package/dist/modes/interactive/interactive-mode.d.ts +7 -0
  55. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  56. package/dist/modes/interactive/interactive-mode.js +253 -10
  57. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  58. package/dist/modes/rpc/rpc-client.d.ts +11 -1
  59. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  60. package/dist/modes/rpc/rpc-client.js +54 -0
  61. package/dist/modes/rpc/rpc-client.js.map +1 -1
  62. package/dist/modes/rpc/rpc-mode.d.ts +1 -1
  63. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  64. package/dist/modes/rpc/rpc-mode.js +87 -3
  65. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  66. package/dist/modes/rpc/rpc-types.d.ts +69 -0
  67. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  68. package/dist/modes/rpc/rpc-types.js.map +1 -1
  69. package/dist/modes/telegram/telegram-bridge-mode.d.ts +15 -0
  70. package/dist/modes/telegram/telegram-bridge-mode.d.ts.map +1 -0
  71. package/dist/modes/telegram/telegram-bridge-mode.js +2164 -0
  72. package/dist/modes/telegram/telegram-bridge-mode.js.map +1 -0
  73. package/docs/cli-reference.md +10 -1
  74. package/docs/configuration.md +21 -0
  75. package/docs/rpc-json-sdk.md +23 -0
  76. package/examples/extensions/README.md +1 -2
  77. package/package.json +4 -3
  78. package/examples/extensions/antigravity-image-gen.ts +0 -415
@@ -0,0 +1,275 @@
1
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync, } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
+ const BACKGROUND_DIR_SEGMENTS = [".iosm", "subagents", "background"];
4
+ const runningControllers = new Map();
5
+ function isStatus(value) {
6
+ return value === "queued" || value === "running" || value === "done" || value === "error" || value === "cancelled";
7
+ }
8
+ function isTerminalStatus(status) {
9
+ return status === "done" || status === "error" || status === "cancelled";
10
+ }
11
+ function getRootKey(rootCwd) {
12
+ return resolve(rootCwd).toLowerCase();
13
+ }
14
+ function getBackgroundDir(rootCwd) {
15
+ return join(resolve(rootCwd), ...BACKGROUND_DIR_SEGMENTS);
16
+ }
17
+ function getMetaPath(rootCwd, runId) {
18
+ return join(getBackgroundDir(rootCwd), `${runId}.json`);
19
+ }
20
+ export function getSubagentBackgroundRunLogPath(rootCwd, runId) {
21
+ return join(getBackgroundDir(rootCwd), `${runId}.log`);
22
+ }
23
+ function parseRecord(metaPath) {
24
+ try {
25
+ const parsed = JSON.parse(readFileSync(metaPath, "utf8"));
26
+ if (typeof parsed.runId !== "string" ||
27
+ !isStatus(parsed.status) ||
28
+ typeof parsed.createdAt !== "string" ||
29
+ typeof parsed.description !== "string" ||
30
+ typeof parsed.profile !== "string" ||
31
+ typeof parsed.cwd !== "string") {
32
+ return undefined;
33
+ }
34
+ const runId = parsed.runId.trim();
35
+ if (!runId)
36
+ return undefined;
37
+ return {
38
+ runId,
39
+ status: parsed.status,
40
+ createdAt: parsed.createdAt,
41
+ startedAt: typeof parsed.startedAt === "string" ? parsed.startedAt : undefined,
42
+ finishedAt: typeof parsed.finishedAt === "string" ? parsed.finishedAt : undefined,
43
+ description: parsed.description,
44
+ profile: parsed.profile,
45
+ cwd: parsed.cwd,
46
+ agent: typeof parsed.agent === "string" && parsed.agent.trim().length > 0 ? parsed.agent : undefined,
47
+ model: typeof parsed.model === "string" && parsed.model.trim().length > 0 ? parsed.model : undefined,
48
+ error: typeof parsed.error === "string" && parsed.error.trim().length > 0 ? parsed.error : undefined,
49
+ transcriptPath: typeof parsed.transcriptPath === "string" && parsed.transcriptPath.trim().length > 0
50
+ ? parsed.transcriptPath
51
+ : undefined,
52
+ requestedStopAt: typeof parsed.requestedStopAt === "string" && parsed.requestedStopAt.trim().length > 0
53
+ ? parsed.requestedStopAt
54
+ : undefined,
55
+ logPath: typeof parsed.logPath === "string" && parsed.logPath.trim().length > 0
56
+ ? parsed.logPath
57
+ : metaPath.replace(/\.json$/i, ".log"),
58
+ metaPath,
59
+ };
60
+ }
61
+ catch {
62
+ return undefined;
63
+ }
64
+ }
65
+ export function getSubagentBackgroundRun(rootCwd, runId) {
66
+ const normalizedRunId = runId.trim();
67
+ if (!normalizedRunId)
68
+ return undefined;
69
+ const metaPath = getMetaPath(rootCwd, normalizedRunId);
70
+ if (!existsSync(metaPath))
71
+ return undefined;
72
+ return parseRecord(metaPath);
73
+ }
74
+ export function listSubagentBackgroundRuns(rootCwd, limit = 20) {
75
+ const dir = getBackgroundDir(rootCwd);
76
+ if (!existsSync(dir))
77
+ return [];
78
+ const files = readdirSync(dir)
79
+ .filter((name) => name.toLowerCase().endsWith(".json"))
80
+ .map((name) => join(dir, name))
81
+ .sort((a, b) => b.localeCompare(a))
82
+ .slice(0, Math.max(1, limit));
83
+ const records = [];
84
+ for (const file of files) {
85
+ const parsed = parseRecord(file);
86
+ if (parsed)
87
+ records.push(parsed);
88
+ }
89
+ records.sort((left, right) => {
90
+ const byTime = right.createdAt.localeCompare(left.createdAt);
91
+ if (byTime !== 0)
92
+ return byTime;
93
+ return right.runId.localeCompare(left.runId);
94
+ });
95
+ return records;
96
+ }
97
+ export function writeSubagentBackgroundRunStatus(rootCwd, input) {
98
+ try {
99
+ const normalizedRunId = input.runId.trim();
100
+ if (!normalizedRunId)
101
+ return undefined;
102
+ const dir = getBackgroundDir(rootCwd);
103
+ mkdirSync(dir, { recursive: true });
104
+ const existing = getSubagentBackgroundRun(rootCwd, normalizedRunId);
105
+ const metaPath = getMetaPath(rootCwd, normalizedRunId);
106
+ const logPath = (input.logPath?.trim() || existing?.logPath || getSubagentBackgroundRunLogPath(rootCwd, normalizedRunId)).trim();
107
+ const payload = {
108
+ runId: normalizedRunId,
109
+ status: input.status,
110
+ createdAt: input.createdAt,
111
+ startedAt: input.startedAt,
112
+ finishedAt: input.finishedAt,
113
+ description: input.description,
114
+ profile: input.profile,
115
+ cwd: input.cwd,
116
+ agent: input.agent,
117
+ model: input.model,
118
+ error: input.error,
119
+ transcriptPath: input.transcriptPath,
120
+ requestedStopAt: input.requestedStopAt ?? existing?.requestedStopAt,
121
+ logPath,
122
+ };
123
+ writeFileSync(metaPath, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
124
+ return metaPath;
125
+ }
126
+ catch {
127
+ return undefined;
128
+ }
129
+ }
130
+ export function appendSubagentBackgroundRunLog(rootCwd, runId, message) {
131
+ try {
132
+ const normalizedRunId = runId.trim();
133
+ if (!normalizedRunId)
134
+ return undefined;
135
+ const dir = getBackgroundDir(rootCwd);
136
+ mkdirSync(dir, { recursive: true });
137
+ const logPath = getSubagentBackgroundRunLogPath(rootCwd, normalizedRunId);
138
+ const line = `[${new Date().toISOString()}] ${message}\n`;
139
+ appendFileSync(logPath, line, "utf8");
140
+ return logPath;
141
+ }
142
+ catch {
143
+ return undefined;
144
+ }
145
+ }
146
+ export function readSubagentBackgroundRunLogTail(rootCwd, runId, lines = 120) {
147
+ const record = getSubagentBackgroundRun(rootCwd, runId);
148
+ if (!record)
149
+ return undefined;
150
+ const maxLines = Math.max(1, Math.min(1000, Math.floor(lines)));
151
+ if (!existsSync(record.logPath))
152
+ return "";
153
+ try {
154
+ const content = readFileSync(record.logPath, "utf8");
155
+ const entries = content.split(/\r?\n/);
156
+ while (entries.length > 0 && entries[entries.length - 1] === "") {
157
+ entries.pop();
158
+ }
159
+ return entries.slice(-maxLines).join("\n");
160
+ }
161
+ catch {
162
+ return "";
163
+ }
164
+ }
165
+ export function registerSubagentBackgroundRunController(rootCwd, runId, controller) {
166
+ const normalizedRunId = runId.trim();
167
+ if (!normalizedRunId)
168
+ return;
169
+ const rootKey = getRootKey(rootCwd);
170
+ const byRun = runningControllers.get(rootKey) ?? new Map();
171
+ byRun.set(normalizedRunId, controller);
172
+ runningControllers.set(rootKey, byRun);
173
+ }
174
+ export function unregisterSubagentBackgroundRunController(rootCwd, runId) {
175
+ const normalizedRunId = runId.trim();
176
+ if (!normalizedRunId)
177
+ return;
178
+ const rootKey = getRootKey(rootCwd);
179
+ const byRun = runningControllers.get(rootKey);
180
+ if (!byRun)
181
+ return;
182
+ byRun.delete(normalizedRunId);
183
+ if (byRun.size === 0) {
184
+ runningControllers.delete(rootKey);
185
+ }
186
+ }
187
+ function getController(rootCwd, runId) {
188
+ const rootKey = getRootKey(rootCwd);
189
+ const byRun = runningControllers.get(rootKey);
190
+ if (!byRun)
191
+ return undefined;
192
+ return byRun.get(runId.trim());
193
+ }
194
+ export function requestStopSubagentBackgroundRun(rootCwd, runId) {
195
+ const normalizedRunId = runId.trim();
196
+ if (!normalizedRunId)
197
+ return undefined;
198
+ const current = getSubagentBackgroundRun(rootCwd, normalizedRunId);
199
+ if (!current)
200
+ return undefined;
201
+ if (!isTerminalStatus(current.status)) {
202
+ const requestedStopAt = new Date().toISOString();
203
+ writeSubagentBackgroundRunStatus(rootCwd, {
204
+ runId: current.runId,
205
+ status: current.status,
206
+ createdAt: current.createdAt,
207
+ startedAt: current.startedAt,
208
+ finishedAt: current.finishedAt,
209
+ description: current.description,
210
+ profile: current.profile,
211
+ cwd: current.cwd,
212
+ agent: current.agent,
213
+ model: current.model,
214
+ error: current.error,
215
+ transcriptPath: current.transcriptPath,
216
+ requestedStopAt,
217
+ logPath: current.logPath,
218
+ });
219
+ appendSubagentBackgroundRunLog(rootCwd, normalizedRunId, "stop requested");
220
+ }
221
+ const controller = getController(rootCwd, normalizedRunId);
222
+ controller?.abort();
223
+ return getSubagentBackgroundRun(rootCwd, normalizedRunId);
224
+ }
225
+ export function requestStopAllSubagentBackgroundRuns(rootCwd) {
226
+ const records = listSubagentBackgroundRuns(rootCwd, 500).filter((record) => !isTerminalStatus(record.status));
227
+ const requestedIds = [];
228
+ for (const record of records) {
229
+ const updated = requestStopSubagentBackgroundRun(rootCwd, record.runId);
230
+ if (updated)
231
+ requestedIds.push(updated.runId);
232
+ }
233
+ return {
234
+ requested: requestedIds.length,
235
+ requestedIds,
236
+ };
237
+ }
238
+ export function pruneSubagentBackgroundRuns(rootCwd, olderThanHours = 24) {
239
+ const thresholdHours = Number.isFinite(olderThanHours) ? Math.max(1, Math.floor(olderThanHours)) : 24;
240
+ const thresholdMs = thresholdHours * 60 * 60 * 1000;
241
+ const nowMs = Date.now();
242
+ const records = listSubagentBackgroundRuns(rootCwd, 1000);
243
+ const removedIds = [];
244
+ let skippedRunning = 0;
245
+ let skippedRecent = 0;
246
+ for (const record of records) {
247
+ if (!isTerminalStatus(record.status)) {
248
+ skippedRunning += 1;
249
+ continue;
250
+ }
251
+ const anchor = Date.parse(record.finishedAt ?? record.createdAt);
252
+ if (!Number.isFinite(anchor) || nowMs - anchor < thresholdMs) {
253
+ skippedRecent += 1;
254
+ continue;
255
+ }
256
+ try {
257
+ rmSync(record.metaPath, { force: true });
258
+ if (record.logPath && existsSync(record.logPath)) {
259
+ rmSync(record.logPath, { force: true });
260
+ }
261
+ removedIds.push(record.runId);
262
+ }
263
+ catch {
264
+ // best effort
265
+ }
266
+ }
267
+ return {
268
+ removed: removedIds.length,
269
+ removedIds,
270
+ skippedRunning,
271
+ skippedRecent,
272
+ thresholdHours,
273
+ };
274
+ }
275
+ //# sourceMappingURL=subagent-background-runs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent-background-runs.js","sourceRoot":"","sources":["../../src/core/subagent-background-runs.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tappendFileSync,\n\texistsSync,\n\tmkdirSync,\n\treadFileSync,\n\treaddirSync,\n\trmSync,\n\twriteFileSync,\n} from \"node:fs\";\nimport { join, resolve } from \"node:path\";\n\nexport type SubagentBackgroundRunStatus = \"queued\" | \"running\" | \"done\" | \"error\" | \"cancelled\";\n\nexport interface SubagentBackgroundRunRecord {\n\trunId: string;\n\tstatus: SubagentBackgroundRunStatus;\n\tcreatedAt: string;\n\tstartedAt?: string;\n\tfinishedAt?: string;\n\tdescription: string;\n\tprofile: string;\n\tcwd: string;\n\tagent?: string;\n\tmodel?: string;\n\terror?: string;\n\ttranscriptPath?: string;\n\trequestedStopAt?: string;\n\tlogPath: string;\n\tmetaPath: string;\n}\n\nexport interface WriteSubagentBackgroundRunStatusInput {\n\trunId: string;\n\tstatus: SubagentBackgroundRunStatus;\n\tcreatedAt: string;\n\tstartedAt?: string;\n\tfinishedAt?: string;\n\tdescription: string;\n\tprofile: string;\n\tcwd: string;\n\tagent?: string;\n\tmodel?: string;\n\terror?: string;\n\ttranscriptPath?: string;\n\trequestedStopAt?: string;\n\tlogPath?: string;\n}\n\nexport interface PruneSubagentBackgroundRunsResult {\n\tremoved: number;\n\tremovedIds: string[];\n\tskippedRunning: number;\n\tskippedRecent: number;\n\tthresholdHours: number;\n}\n\nconst BACKGROUND_DIR_SEGMENTS = [\".iosm\", \"subagents\", \"background\"] as const;\n\nconst runningControllers = new Map<string, Map<string, AbortController>>();\n\nfunction isStatus(value: unknown): value is SubagentBackgroundRunStatus {\n\treturn value === \"queued\" || value === \"running\" || value === \"done\" || value === \"error\" || value === \"cancelled\";\n}\n\nfunction isTerminalStatus(status: SubagentBackgroundRunStatus): boolean {\n\treturn status === \"done\" || status === \"error\" || status === \"cancelled\";\n}\n\nfunction getRootKey(rootCwd: string): string {\n\treturn resolve(rootCwd).toLowerCase();\n}\n\nfunction getBackgroundDir(rootCwd: string): string {\n\treturn join(resolve(rootCwd), ...BACKGROUND_DIR_SEGMENTS);\n}\n\nfunction getMetaPath(rootCwd: string, runId: string): string {\n\treturn join(getBackgroundDir(rootCwd), `${runId}.json`);\n}\n\nexport function getSubagentBackgroundRunLogPath(rootCwd: string, runId: string): string {\n\treturn join(getBackgroundDir(rootCwd), `${runId}.log`);\n}\n\nfunction parseRecord(metaPath: string): SubagentBackgroundRunRecord | undefined {\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(metaPath, \"utf8\")) as Partial<SubagentBackgroundRunRecord>;\n\t\tif (\n\t\t\ttypeof parsed.runId !== \"string\" ||\n\t\t\t!isStatus(parsed.status) ||\n\t\t\ttypeof parsed.createdAt !== \"string\" ||\n\t\t\ttypeof parsed.description !== \"string\" ||\n\t\t\ttypeof parsed.profile !== \"string\" ||\n\t\t\ttypeof parsed.cwd !== \"string\"\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst runId = parsed.runId.trim();\n\t\tif (!runId) return undefined;\n\t\treturn {\n\t\t\trunId,\n\t\t\tstatus: parsed.status,\n\t\t\tcreatedAt: parsed.createdAt,\n\t\t\tstartedAt: typeof parsed.startedAt === \"string\" ? parsed.startedAt : undefined,\n\t\t\tfinishedAt: typeof parsed.finishedAt === \"string\" ? parsed.finishedAt : undefined,\n\t\t\tdescription: parsed.description,\n\t\t\tprofile: parsed.profile,\n\t\t\tcwd: parsed.cwd,\n\t\t\tagent: typeof parsed.agent === \"string\" && parsed.agent.trim().length > 0 ? parsed.agent : undefined,\n\t\t\tmodel: typeof parsed.model === \"string\" && parsed.model.trim().length > 0 ? parsed.model : undefined,\n\t\t\terror: typeof parsed.error === \"string\" && parsed.error.trim().length > 0 ? parsed.error : undefined,\n\t\t\ttranscriptPath:\n\t\t\t\ttypeof parsed.transcriptPath === \"string\" && parsed.transcriptPath.trim().length > 0\n\t\t\t\t\t? parsed.transcriptPath\n\t\t\t\t\t: undefined,\n\t\t\trequestedStopAt:\n\t\t\t\ttypeof parsed.requestedStopAt === \"string\" && parsed.requestedStopAt.trim().length > 0\n\t\t\t\t\t? parsed.requestedStopAt\n\t\t\t\t\t: undefined,\n\t\t\tlogPath:\n\t\t\t\ttypeof parsed.logPath === \"string\" && parsed.logPath.trim().length > 0\n\t\t\t\t\t? parsed.logPath\n\t\t\t\t\t: metaPath.replace(/\\.json$/i, \".log\"),\n\t\t\tmetaPath,\n\t\t};\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function getSubagentBackgroundRun(rootCwd: string, runId: string): SubagentBackgroundRunRecord | undefined {\n\tconst normalizedRunId = runId.trim();\n\tif (!normalizedRunId) return undefined;\n\tconst metaPath = getMetaPath(rootCwd, normalizedRunId);\n\tif (!existsSync(metaPath)) return undefined;\n\treturn parseRecord(metaPath);\n}\n\nexport function listSubagentBackgroundRuns(rootCwd: string, limit = 20): SubagentBackgroundRunRecord[] {\n\tconst dir = getBackgroundDir(rootCwd);\n\tif (!existsSync(dir)) return [];\n\tconst files = readdirSync(dir)\n\t\t.filter((name) => name.toLowerCase().endsWith(\".json\"))\n\t\t.map((name) => join(dir, name))\n\t\t.sort((a, b) => b.localeCompare(a))\n\t\t.slice(0, Math.max(1, limit));\n\n\tconst records: SubagentBackgroundRunRecord[] = [];\n\tfor (const file of files) {\n\t\tconst parsed = parseRecord(file);\n\t\tif (parsed) records.push(parsed);\n\t}\n\trecords.sort((left, right) => {\n\t\tconst byTime = right.createdAt.localeCompare(left.createdAt);\n\t\tif (byTime !== 0) return byTime;\n\t\treturn right.runId.localeCompare(left.runId);\n\t});\n\treturn records;\n}\n\nexport function writeSubagentBackgroundRunStatus(\n\trootCwd: string,\n\tinput: WriteSubagentBackgroundRunStatusInput,\n): string | undefined {\n\ttry {\n\t\tconst normalizedRunId = input.runId.trim();\n\t\tif (!normalizedRunId) return undefined;\n\t\tconst dir = getBackgroundDir(rootCwd);\n\t\tmkdirSync(dir, { recursive: true });\n\t\tconst existing = getSubagentBackgroundRun(rootCwd, normalizedRunId);\n\t\tconst metaPath = getMetaPath(rootCwd, normalizedRunId);\n\t\tconst logPath = (input.logPath?.trim() || existing?.logPath || getSubagentBackgroundRunLogPath(rootCwd, normalizedRunId)).trim();\n\t\tconst payload = {\n\t\t\trunId: normalizedRunId,\n\t\t\tstatus: input.status,\n\t\t\tcreatedAt: input.createdAt,\n\t\t\tstartedAt: input.startedAt,\n\t\t\tfinishedAt: input.finishedAt,\n\t\t\tdescription: input.description,\n\t\t\tprofile: input.profile,\n\t\t\tcwd: input.cwd,\n\t\t\tagent: input.agent,\n\t\t\tmodel: input.model,\n\t\t\terror: input.error,\n\t\t\ttranscriptPath: input.transcriptPath,\n\t\t\trequestedStopAt: input.requestedStopAt ?? existing?.requestedStopAt,\n\t\t\tlogPath,\n\t\t};\n\t\twriteFileSync(metaPath, `${JSON.stringify(payload, null, 2)}\\n`, \"utf8\");\n\t\treturn metaPath;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function appendSubagentBackgroundRunLog(rootCwd: string, runId: string, message: string): string | undefined {\n\ttry {\n\t\tconst normalizedRunId = runId.trim();\n\t\tif (!normalizedRunId) return undefined;\n\t\tconst dir = getBackgroundDir(rootCwd);\n\t\tmkdirSync(dir, { recursive: true });\n\t\tconst logPath = getSubagentBackgroundRunLogPath(rootCwd, normalizedRunId);\n\t\tconst line = `[${new Date().toISOString()}] ${message}\\n`;\n\t\tappendFileSync(logPath, line, \"utf8\");\n\t\treturn logPath;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function readSubagentBackgroundRunLogTail(rootCwd: string, runId: string, lines = 120): string | undefined {\n\tconst record = getSubagentBackgroundRun(rootCwd, runId);\n\tif (!record) return undefined;\n\tconst maxLines = Math.max(1, Math.min(1000, Math.floor(lines)));\n\tif (!existsSync(record.logPath)) return \"\";\n\ttry {\n\t\tconst content = readFileSync(record.logPath, \"utf8\");\n\t\tconst entries = content.split(/\\r?\\n/);\n\t\twhile (entries.length > 0 && entries[entries.length - 1] === \"\") {\n\t\t\tentries.pop();\n\t\t}\n\t\treturn entries.slice(-maxLines).join(\"\\n\");\n\t} catch {\n\t\treturn \"\";\n\t}\n}\n\nexport function registerSubagentBackgroundRunController(rootCwd: string, runId: string, controller: AbortController): void {\n\tconst normalizedRunId = runId.trim();\n\tif (!normalizedRunId) return;\n\tconst rootKey = getRootKey(rootCwd);\n\tconst byRun = runningControllers.get(rootKey) ?? new Map<string, AbortController>();\n\tbyRun.set(normalizedRunId, controller);\n\trunningControllers.set(rootKey, byRun);\n}\n\nexport function unregisterSubagentBackgroundRunController(rootCwd: string, runId: string): void {\n\tconst normalizedRunId = runId.trim();\n\tif (!normalizedRunId) return;\n\tconst rootKey = getRootKey(rootCwd);\n\tconst byRun = runningControllers.get(rootKey);\n\tif (!byRun) return;\n\tbyRun.delete(normalizedRunId);\n\tif (byRun.size === 0) {\n\t\trunningControllers.delete(rootKey);\n\t}\n}\n\nfunction getController(rootCwd: string, runId: string): AbortController | undefined {\n\tconst rootKey = getRootKey(rootCwd);\n\tconst byRun = runningControllers.get(rootKey);\n\tif (!byRun) return undefined;\n\treturn byRun.get(runId.trim());\n}\n\nexport function requestStopSubagentBackgroundRun(\n\trootCwd: string,\n\trunId: string,\n): SubagentBackgroundRunRecord | undefined {\n\tconst normalizedRunId = runId.trim();\n\tif (!normalizedRunId) return undefined;\n\tconst current = getSubagentBackgroundRun(rootCwd, normalizedRunId);\n\tif (!current) return undefined;\n\tif (!isTerminalStatus(current.status)) {\n\t\tconst requestedStopAt = new Date().toISOString();\n\t\twriteSubagentBackgroundRunStatus(rootCwd, {\n\t\t\trunId: current.runId,\n\t\t\tstatus: current.status,\n\t\t\tcreatedAt: current.createdAt,\n\t\t\tstartedAt: current.startedAt,\n\t\t\tfinishedAt: current.finishedAt,\n\t\t\tdescription: current.description,\n\t\t\tprofile: current.profile,\n\t\t\tcwd: current.cwd,\n\t\t\tagent: current.agent,\n\t\t\tmodel: current.model,\n\t\t\terror: current.error,\n\t\t\ttranscriptPath: current.transcriptPath,\n\t\t\trequestedStopAt,\n\t\t\tlogPath: current.logPath,\n\t\t});\n\t\tappendSubagentBackgroundRunLog(rootCwd, normalizedRunId, \"stop requested\");\n\t}\n\tconst controller = getController(rootCwd, normalizedRunId);\n\tcontroller?.abort();\n\treturn getSubagentBackgroundRun(rootCwd, normalizedRunId);\n}\n\nexport function requestStopAllSubagentBackgroundRuns(rootCwd: string): {\n\trequested: number;\n\trequestedIds: string[];\n} {\n\tconst records = listSubagentBackgroundRuns(rootCwd, 500).filter((record) => !isTerminalStatus(record.status));\n\tconst requestedIds: string[] = [];\n\tfor (const record of records) {\n\t\tconst updated = requestStopSubagentBackgroundRun(rootCwd, record.runId);\n\t\tif (updated) requestedIds.push(updated.runId);\n\t}\n\treturn {\n\t\trequested: requestedIds.length,\n\t\trequestedIds,\n\t};\n}\n\nexport function pruneSubagentBackgroundRuns(\n\trootCwd: string,\n\tolderThanHours = 24,\n): PruneSubagentBackgroundRunsResult {\n\tconst thresholdHours = Number.isFinite(olderThanHours) ? Math.max(1, Math.floor(olderThanHours)) : 24;\n\tconst thresholdMs = thresholdHours * 60 * 60 * 1000;\n\tconst nowMs = Date.now();\n\tconst records = listSubagentBackgroundRuns(rootCwd, 1000);\n\tconst removedIds: string[] = [];\n\tlet skippedRunning = 0;\n\tlet skippedRecent = 0;\n\n\tfor (const record of records) {\n\t\tif (!isTerminalStatus(record.status)) {\n\t\t\tskippedRunning += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst anchor = Date.parse(record.finishedAt ?? record.createdAt);\n\t\tif (!Number.isFinite(anchor) || nowMs - anchor < thresholdMs) {\n\t\t\tskippedRecent += 1;\n\t\t\tcontinue;\n\t\t}\n\t\ttry {\n\t\t\trmSync(record.metaPath, { force: true });\n\t\t\tif (record.logPath && existsSync(record.logPath)) {\n\t\t\t\trmSync(record.logPath, { force: true });\n\t\t\t}\n\t\t\tremovedIds.push(record.runId);\n\t\t} catch {\n\t\t\t// best effort\n\t\t}\n\t}\n\n\treturn {\n\t\tremoved: removedIds.length,\n\t\tremovedIds,\n\t\tskippedRunning,\n\t\tskippedRecent,\n\t\tthresholdHours,\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../../src/core/tools/task.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../../src/core/tools/task.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ import { buildRetrospectiveDirective, classifyFailureCause, formatFailureCauseCo
7
7
  import { MAX_ORCHESTRATION_AGENTS, MAX_ORCHESTRATION_PARALLEL, MAX_SUBAGENT_DELEGATE_PARALLEL, MAX_SUBAGENT_DELEGATION_DEPTH, MAX_SUBAGENT_DELEGATIONS_PER_TASK, } from "../orchestration-limits.js";
8
8
  import { AGENT_PROFILES, isReadOnlyProfileName, isValidProfileName, } from "../agent-profiles.js";
9
9
  import { readSharedMemory, summarizeSharedMemoryUsage, writeSharedMemory, } from "../shared-memory.js";
10
+ import { appendSubagentBackgroundRunLog, registerSubagentBackgroundRunController, unregisterSubagentBackgroundRunController, writeSubagentBackgroundRunStatus, } from "../subagent-background-runs.js";
10
11
  import { normalizeAndFilterToolNames, normalizeToolName } from "../subagents.js";
11
12
  const taskSchema = Type.Object({
12
13
  description: Type.Optional(Type.String({
@@ -959,18 +960,6 @@ function persistSubagentTranscript(input) {
959
960
  return undefined;
960
961
  }
961
962
  }
962
- function writeBackgroundRunStatus(rootCwd, status) {
963
- try {
964
- const dir = path.join(rootCwd, ".iosm", "subagents", "background");
965
- mkdirSync(dir, { recursive: true });
966
- const filePath = path.join(dir, `${status.runId}.json`);
967
- writeFileSync(filePath, `${JSON.stringify(status, null, 2)}\n`, "utf8");
968
- return filePath;
969
- }
970
- catch {
971
- return undefined;
972
- }
973
- }
974
963
  function gitResult(args, cwd) {
975
964
  const result = spawnSync("git", args, {
976
965
  cwd,
@@ -1048,6 +1037,7 @@ export function createTaskTool(cwd, runner, options) {
1048
1037
  customAgentsSnippet,
1049
1038
  parameters: taskSchema,
1050
1039
  execute: async (_toolCallId, { description: rawDescription, task: rawTask, args: rawArgs, prompt: rawPrompt, agent: agentName, profile, cwd: targetCwd, lock_key: lockKey, run_id: orchestrationRunId, task_id: orchestrationTaskId, model: requestedModel, background, isolation, delegate_parallel_hint: delegateParallelHint, }, _signal, onUpdate) => {
1040
+ let runtimeAbortSignal = _signal;
1051
1041
  const updateTrackedTaskStatus = (status) => {
1052
1042
  if (!orchestrationRunId || !orchestrationTaskId)
1053
1043
  return;
@@ -1059,7 +1049,7 @@ export function createTaskTool(cwd, runner, options) {
1059
1049
  });
1060
1050
  };
1061
1051
  const throwIfAborted = () => {
1062
- if (_signal?.aborted) {
1052
+ if (runtimeAbortSignal?.aborted) {
1063
1053
  updateTrackedTaskStatus("cancelled");
1064
1054
  throw new Error("Operation aborted");
1065
1055
  }
@@ -1281,7 +1271,7 @@ export function createTaskTool(cwd, runner, options) {
1281
1271
  cwd,
1282
1272
  runId: orchestrationRunId,
1283
1273
  taskId: orchestrationTaskId,
1284
- signal: _signal,
1274
+ signal: runtimeAbortSignal,
1285
1275
  onWaiting: (waiting) => {
1286
1276
  emitProgress({
1287
1277
  kind: "subagent_progress",
@@ -1294,7 +1284,7 @@ export function createTaskTool(cwd, runner, options) {
1294
1284
  });
1295
1285
  }
1296
1286
  catch (error) {
1297
- if (_signal?.aborted || isAbortError(error)) {
1287
+ if (runtimeAbortSignal?.aborted || isAbortError(error)) {
1298
1288
  updateTrackedTaskStatus("cancelled");
1299
1289
  throw new Error("Operation aborted");
1300
1290
  }
@@ -1388,7 +1378,7 @@ export function createTaskTool(cwd, runner, options) {
1388
1378
  value: payload,
1389
1379
  scope: "run",
1390
1380
  mode: "set",
1391
- }, _signal);
1381
+ }, runtimeAbortSignal);
1392
1382
  }
1393
1383
  catch (error) {
1394
1384
  const message = error instanceof Error ? error.message : String(error);
@@ -1417,7 +1407,7 @@ export function createTaskTool(cwd, runner, options) {
1417
1407
  value: payload,
1418
1408
  scope: "run",
1419
1409
  mode: "set",
1420
- }, _signal);
1410
+ }, runtimeAbortSignal);
1421
1411
  }
1422
1412
  catch (error) {
1423
1413
  const message = error instanceof Error ? error.message : String(error);
@@ -1437,7 +1427,7 @@ export function createTaskTool(cwd, runner, options) {
1437
1427
  scope: "run",
1438
1428
  key,
1439
1429
  includeValues: true,
1440
- }, _signal);
1430
+ }, runtimeAbortSignal);
1441
1431
  const current = snapshot.items[0];
1442
1432
  if (!current) {
1443
1433
  await writeSharedMemory(rootSharedMemoryContext, {
@@ -1449,7 +1439,7 @@ export function createTaskTool(cwd, runner, options) {
1449
1439
  }),
1450
1440
  scope: "run",
1451
1441
  mode: "set",
1452
- }, _signal);
1442
+ }, runtimeAbortSignal);
1453
1443
  lastError = undefined;
1454
1444
  break;
1455
1445
  }
@@ -1482,7 +1472,7 @@ export function createTaskTool(cwd, runner, options) {
1482
1472
  scope: "run",
1483
1473
  mode: "set",
1484
1474
  ifVersion: current.version,
1485
- }, _signal);
1475
+ }, runtimeAbortSignal);
1486
1476
  lastError = undefined;
1487
1477
  break;
1488
1478
  }
@@ -1516,7 +1506,7 @@ export function createTaskTool(cwd, runner, options) {
1516
1506
  cwd: subagentCwd,
1517
1507
  modelOverride: effectiveModelOverride,
1518
1508
  sharedMemoryContext: rootSharedMemoryContext,
1519
- signal: _signal,
1509
+ signal: runtimeAbortSignal,
1520
1510
  onProgress: (progress) => emitProgress(progress),
1521
1511
  });
1522
1512
  throwIfAborted();
@@ -1555,7 +1545,7 @@ export function createTaskTool(cwd, runner, options) {
1555
1545
  });
1556
1546
  }
1557
1547
  catch (error) {
1558
- if (_signal?.aborted || isAbortError(error)) {
1548
+ if (runtimeAbortSignal?.aborted || isAbortError(error)) {
1559
1549
  throw new Error("Operation aborted");
1560
1550
  }
1561
1551
  const message = error instanceof Error ? error.message : String(error);
@@ -1857,7 +1847,7 @@ export function createTaskTool(cwd, runner, options) {
1857
1847
  cwd: nestedCwd,
1858
1848
  modelOverride: nestedModelOverride,
1859
1849
  sharedMemoryContext: nestedSharedMemoryContext,
1860
- signal: _signal,
1850
+ signal: runtimeAbortSignal,
1861
1851
  onProgress: (progress) => {
1862
1852
  emitProgress({
1863
1853
  kind: "subagent_progress",
@@ -2105,7 +2095,7 @@ export function createTaskTool(cwd, runner, options) {
2105
2095
  cwd: childCwd,
2106
2096
  modelOverride: childModelOverride,
2107
2097
  sharedMemoryContext: childSharedMemoryContext,
2108
- signal: _signal,
2098
+ signal: runtimeAbortSignal,
2109
2099
  onProgress: (progress) => {
2110
2100
  emitProgress({
2111
2101
  kind: "subagent_progress",
@@ -2157,7 +2147,7 @@ export function createTaskTool(cwd, runner, options) {
2157
2147
  });
2158
2148
  }
2159
2149
  catch (error) {
2160
- if (_signal?.aborted || isAbortError(error)) {
2150
+ if (runtimeAbortSignal?.aborted || isAbortError(error)) {
2161
2151
  throw new Error("Operation aborted");
2162
2152
  }
2163
2153
  const message = error instanceof Error ? error.message : String(error);
@@ -2299,7 +2289,7 @@ export function createTaskTool(cwd, runner, options) {
2299
2289
  }
2300
2290
  catch (error) {
2301
2291
  const message = error instanceof Error ? error.message : String(error);
2302
- if (_signal?.aborted || isAbortError(error)) {
2292
+ if (runtimeAbortSignal?.aborted || isAbortError(error)) {
2303
2293
  throw new Error("Operation aborted");
2304
2294
  }
2305
2295
  const classified = error && typeof error === "object" && "failureCause" in error
@@ -2375,7 +2365,7 @@ export function createTaskTool(cwd, runner, options) {
2375
2365
  }
2376
2366
  catch (error) {
2377
2367
  const message = error instanceof Error ? error.message : String(error);
2378
- if (_signal?.aborted || isAbortError(error)) {
2368
+ if (runtimeAbortSignal?.aborted || isAbortError(error)) {
2379
2369
  recordFailureCause("aborted");
2380
2370
  const hasFailureCauses = Object.keys(failureCauses).length > 0;
2381
2371
  const details = {
@@ -2494,7 +2484,7 @@ export function createTaskTool(cwd, runner, options) {
2494
2484
  value: summaryPayload,
2495
2485
  scope: "run",
2496
2486
  mode: "set",
2497
- }, _signal);
2487
+ }, runtimeAbortSignal);
2498
2488
  sharedMemorySummaryKey = summaryWrite.key;
2499
2489
  }
2500
2490
  catch (error) {
@@ -2511,7 +2501,7 @@ export function createTaskTool(cwd, runner, options) {
2511
2501
  rootCwd: cwd,
2512
2502
  runId: sharedMemoryRunId,
2513
2503
  taskId: sharedMemoryTaskId,
2514
- }, _signal);
2504
+ }, runtimeAbortSignal);
2515
2505
  if (delegatedTasks > 1 && usage.currentTaskDelegateWrites === 0) {
2516
2506
  delegationWarnings.push("No shared_memory writes detected from delegates in this task. Cross-stream coordination may be weak; use stable keys (findings/<stream>, risks/<stream>, plan/<stream>).");
2517
2507
  }
@@ -2541,7 +2531,7 @@ export function createTaskTool(cwd, runner, options) {
2541
2531
  prefix: "claims/",
2542
2532
  includeValues: true,
2543
2533
  limit: Math.max(40, delegatedTasks * 8),
2544
- }, _signal);
2534
+ }, runtimeAbortSignal);
2545
2535
  const collisions = [];
2546
2536
  for (const item of claims.items) {
2547
2537
  if (!item.value)
@@ -2587,7 +2577,7 @@ export function createTaskTool(cwd, runner, options) {
2587
2577
  prefix: findingsPrefix,
2588
2578
  includeValues: true,
2589
2579
  limit: Math.max(20, delegatedTasks * 4),
2590
- }, _signal);
2580
+ }, runtimeAbortSignal);
2591
2581
  const examples = findings.items.slice(0, 6).map((item) => {
2592
2582
  let excerpt = "";
2593
2583
  if (item.value) {
@@ -2742,7 +2732,11 @@ export function createTaskTool(cwd, runner, options) {
2742
2732
  };
2743
2733
  if (runInBackground) {
2744
2734
  const now = new Date().toISOString();
2745
- const queuedStatusPath = writeBackgroundRunStatus(cwd, {
2735
+ const backgroundAbortController = new AbortController();
2736
+ runtimeAbortSignal = backgroundAbortController.signal;
2737
+ registerSubagentBackgroundRunController(cwd, runId, backgroundAbortController);
2738
+ const logPath = appendSubagentBackgroundRunLog(cwd, runId, `queued · profile=${effectiveProfile} · cwd=${requestedSubagentCwd}`);
2739
+ const queuedStatusPath = writeSubagentBackgroundRunStatus(cwd, {
2746
2740
  runId,
2747
2741
  status: "queued",
2748
2742
  createdAt: now,
@@ -2751,9 +2745,10 @@ export function createTaskTool(cwd, runner, options) {
2751
2745
  cwd: requestedSubagentCwd,
2752
2746
  agent: customSubagent?.name,
2753
2747
  model: effectiveModelOverride,
2748
+ logPath,
2754
2749
  });
2755
2750
  void (async () => {
2756
- writeBackgroundRunStatus(cwd, {
2751
+ writeSubagentBackgroundRunStatus(cwd, {
2757
2752
  runId,
2758
2753
  status: "running",
2759
2754
  createdAt: now,
@@ -2763,10 +2758,12 @@ export function createTaskTool(cwd, runner, options) {
2763
2758
  cwd: requestedSubagentCwd,
2764
2759
  agent: customSubagent?.name,
2765
2760
  model: effectiveModelOverride,
2761
+ logPath,
2766
2762
  });
2763
+ appendSubagentBackgroundRunLog(cwd, runId, "running");
2767
2764
  try {
2768
2765
  const result = await executeSubagent();
2769
- writeBackgroundRunStatus(cwd, {
2766
+ writeSubagentBackgroundRunStatus(cwd, {
2770
2767
  runId,
2771
2768
  status: "done",
2772
2769
  createdAt: now,
@@ -2777,11 +2774,13 @@ export function createTaskTool(cwd, runner, options) {
2777
2774
  agent: customSubagent?.name,
2778
2775
  model: effectiveModelOverride,
2779
2776
  transcriptPath: result.details.transcriptPath,
2777
+ logPath,
2780
2778
  });
2779
+ appendSubagentBackgroundRunLog(cwd, runId, `done · transcript=${result.details.transcriptPath ?? "-"}`);
2781
2780
  }
2782
2781
  catch (error) {
2783
2782
  const aborted = isAbortError(error);
2784
- writeBackgroundRunStatus(cwd, {
2783
+ writeSubagentBackgroundRunStatus(cwd, {
2785
2784
  runId,
2786
2785
  status: aborted ? "cancelled" : "error",
2787
2786
  createdAt: now,
@@ -2792,7 +2791,12 @@ export function createTaskTool(cwd, runner, options) {
2792
2791
  agent: customSubagent?.name,
2793
2792
  model: effectiveModelOverride,
2794
2793
  error: error instanceof Error ? error.message : String(error),
2794
+ logPath,
2795
2795
  });
2796
+ appendSubagentBackgroundRunLog(cwd, runId, `${aborted ? "cancelled" : "error"} · ${error instanceof Error ? error.message : String(error)}`);
2797
+ }
2798
+ finally {
2799
+ unregisterSubagentBackgroundRunController(cwd, runId);
2796
2800
  }
2797
2801
  })();
2798
2802
  return {