@agimon-ai/po-team 0.0.0-alpha.0

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 (110) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +156 -0
  3. package/dist/agentDiscovery-Whwzc4dP.cjs +1637 -0
  4. package/dist/agentDiscovery-Whwzc4dP.cjs.map +1 -0
  5. package/dist/agentDiscovery-ZQlFkKvB.mjs +1529 -0
  6. package/dist/agentDiscovery-ZQlFkKvB.mjs.map +1 -0
  7. package/dist/apiContracts.cjs +162 -0
  8. package/dist/apiContracts.cjs.map +1 -0
  9. package/dist/apiContracts.d.mts +53 -0
  10. package/dist/apiContracts.d.mts.map +1 -0
  11. package/dist/apiContracts.mjs +157 -0
  12. package/dist/apiContracts.mjs.map +1 -0
  13. package/dist/atomicJson-D0346bt5.cjs +178 -0
  14. package/dist/atomicJson-D0346bt5.cjs.map +1 -0
  15. package/dist/atomicJson-D2t0CDh9.mjs +137 -0
  16. package/dist/atomicJson-D2t0CDh9.mjs.map +1 -0
  17. package/dist/capabilityCeiling-C-Y7H8oC.cjs +191 -0
  18. package/dist/capabilityCeiling-C-Y7H8oC.cjs.map +1 -0
  19. package/dist/capabilityCeiling-CF7kAS18.mjs +156 -0
  20. package/dist/capabilityCeiling-CF7kAS18.mjs.map +1 -0
  21. package/dist/capabilityCeiling.cjs +10 -0
  22. package/dist/capabilityCeiling.d.mts +46 -0
  23. package/dist/capabilityCeiling.d.mts.map +1 -0
  24. package/dist/capabilityCeiling.mjs +3 -0
  25. package/dist/delegation.cjs +49 -0
  26. package/dist/delegation.cjs.map +1 -0
  27. package/dist/delegation.d.mts +269 -0
  28. package/dist/delegation.d.mts.map +1 -0
  29. package/dist/delegation.mjs +34 -0
  30. package/dist/delegation.mjs.map +1 -0
  31. package/dist/delegationApi.cjs +92 -0
  32. package/dist/delegationApi.d.mts +2 -0
  33. package/dist/delegationApi.mjs +2 -0
  34. package/dist/env.cjs +62 -0
  35. package/dist/env.d.mts +2 -0
  36. package/dist/env.mjs +2 -0
  37. package/dist/environment-CaCW3SgT.cjs +320 -0
  38. package/dist/environment-CaCW3SgT.cjs.map +1 -0
  39. package/dist/environment-DrqhrxG_.mjs +75 -0
  40. package/dist/environment-DrqhrxG_.mjs.map +1 -0
  41. package/dist/environment-ma5oQ7uM.d.mts +63 -0
  42. package/dist/environment-ma5oQ7uM.d.mts.map +1 -0
  43. package/dist/extensions/server.cjs +6940 -0
  44. package/dist/extensions/server.cjs.map +1 -0
  45. package/dist/extensions/server.d.mts +5 -0
  46. package/dist/extensions/server.d.mts.map +1 -0
  47. package/dist/extensions/server.mjs +6932 -0
  48. package/dist/extensions/server.mjs.map +1 -0
  49. package/dist/extensions/web.mjs +2308 -0
  50. package/dist/extensions/web.mjs.map +1 -0
  51. package/dist/externalProcessIpc-C-15lJrB.mjs +584 -0
  52. package/dist/externalProcessIpc-C-15lJrB.mjs.map +1 -0
  53. package/dist/externalProcessIpc-ojE0pvw0.cjs +690 -0
  54. package/dist/externalProcessIpc-ojE0pvw0.cjs.map +1 -0
  55. package/dist/fablePlan.cjs +17 -0
  56. package/dist/fablePlan.d.mts +2 -0
  57. package/dist/fablePlan.mjs +2 -0
  58. package/dist/fablePlanApi-BsHhgVFV.mjs +118 -0
  59. package/dist/fablePlanApi-BsHhgVFV.mjs.map +1 -0
  60. package/dist/fablePlanApi-CZ3uUcMi.d.mts +97 -0
  61. package/dist/fablePlanApi-CZ3uUcMi.d.mts.map +1 -0
  62. package/dist/fablePlanApi-wBu9bRXU.cjs +207 -0
  63. package/dist/fablePlanApi-wBu9bRXU.cjs.map +1 -0
  64. package/dist/fablePlanApi.cjs +17 -0
  65. package/dist/fablePlanApi.d.mts +2 -0
  66. package/dist/fablePlanApi.mjs +2 -0
  67. package/dist/index.cjs +49 -0
  68. package/dist/index.cjs.map +1 -0
  69. package/dist/index.d.mts +160 -0
  70. package/dist/index.d.mts.map +1 -0
  71. package/dist/index.mjs +45 -0
  72. package/dist/index.mjs.map +1 -0
  73. package/dist/runs/background/cliRunnerEntry.cjs +539 -0
  74. package/dist/runs/background/cliRunnerEntry.cjs.map +1 -0
  75. package/dist/runs/background/cliRunnerEntry.d.mts +1 -0
  76. package/dist/runs/background/cliRunnerEntry.mjs +537 -0
  77. package/dist/runs/background/cliRunnerEntry.mjs.map +1 -0
  78. package/dist/runtimeSubagentPolicy.cjs +5 -0
  79. package/dist/runtimeSubagentPolicy.d.mts +2 -0
  80. package/dist/runtimeSubagentPolicy.mjs +2 -0
  81. package/dist/runtimeSubagentTool.cjs +11 -0
  82. package/dist/runtimeSubagentTool.d.mts +2 -0
  83. package/dist/runtimeSubagentTool.mjs +2 -0
  84. package/dist/subagentPolicy-ALJam4GN.d.mts +33 -0
  85. package/dist/subagentPolicy-ALJam4GN.d.mts.map +1 -0
  86. package/dist/subagentPolicy-DQRyKDH-.cjs +39 -0
  87. package/dist/subagentPolicy-DQRyKDH-.cjs.map +1 -0
  88. package/dist/subagentPolicy-DxjsKeyj.mjs +22 -0
  89. package/dist/subagentPolicy-DxjsKeyj.mjs.map +1 -0
  90. package/dist/subagentPolicy.cjs +5 -0
  91. package/dist/subagentPolicy.d.mts +2 -0
  92. package/dist/subagentPolicy.mjs +2 -0
  93. package/dist/subagentTool-BTssGLw8.d.mts +103 -0
  94. package/dist/subagentTool-BTssGLw8.d.mts.map +1 -0
  95. package/dist/subagentTool-Ca2zQXKw.cjs +227 -0
  96. package/dist/subagentTool-Ca2zQXKw.cjs.map +1 -0
  97. package/dist/subagentTool-WOYrjxgT.mjs +186 -0
  98. package/dist/subagentTool-WOYrjxgT.mjs.map +1 -0
  99. package/dist/subagentTool.cjs +10 -0
  100. package/dist/subagentTool.d.mts +2 -0
  101. package/dist/subagentTool.mjs +2 -0
  102. package/dist/teamSnapshot-DgaANhBs.mjs +24 -0
  103. package/dist/teamSnapshot-DgaANhBs.mjs.map +1 -0
  104. package/dist/teamSnapshot-oKuGFdYc.cjs +35 -0
  105. package/dist/teamSnapshot-oKuGFdYc.cjs.map +1 -0
  106. package/dist/teamSnapshot.cjs +4 -0
  107. package/dist/teamSnapshot.d.mts +59 -0
  108. package/dist/teamSnapshot.d.mts.map +1 -0
  109. package/dist/teamSnapshot.mjs +2 -0
  110. package/package.json +201 -0
@@ -0,0 +1,539 @@
1
+ const require_atomicJson = require("../../atomicJson-D0346bt5.cjs");
2
+ const require_environment = require("../../environment-CaCW3SgT.cjs");
3
+ const require_externalProcessIpc = require("../../externalProcessIpc-ojE0pvw0.cjs");
4
+ let node_fs = require("node:fs");
5
+ node_fs = require_atomicJson.__toESM(node_fs, 1);
6
+ let node_path = require("node:path");
7
+ node_path = require_atomicJson.__toESM(node_path, 1);
8
+ let _agimon_ai_po_telemetry = require("@agimon-ai/po-telemetry");
9
+ let node_child_process = require("node:child_process");
10
+ let _agimon_ai_po_core_childProcess = require("@agimon-ai/po-core/childProcess");
11
+ //#region src/services/statusWriter/index.ts
12
+ /**
13
+ * Coalesced writer for a run's `status.json`.
14
+ *
15
+ * WHY THIS EXISTS:
16
+ * In the predecessor (`po-subagents/src/runs/background/subagent-runner.ts`)
17
+ * `status.json` was rewritten in full on every child event, and every rewrite
18
+ * `structuredClone`d the whole run graph first. On a fan-out run that makes the
19
+ * hot path quadratic: N events cost O(N) clones of an O(N)-sized graph. Its
20
+ * `recentTools` and `recentOutput` arrays were also appended to and never
21
+ * trimmed, so a long run's status file, and the cost of cloning it, grew
22
+ * without bound.
23
+ *
24
+ * DESIGN PATTERNS:
25
+ * - Coalescing: `update()` mutates the in-memory status and arms a trailing
26
+ * ~75ms timer. A burst of events inside that window costs one clone and one
27
+ * write, not one per event
28
+ * - The clone is gated by a dirty counter, not by the timer firing. A flush
29
+ * with nothing dirty since the last one performs no clone and no write at
30
+ * all, which is the specific fix for the quadratic behaviour above
31
+ * - `updateSync()` bypasses the timer for transitions that must not be lost if
32
+ * the process dies right after: terminal run status, and chain step
33
+ * transitions. Everything else can wait out the coalescing window
34
+ * - `recentTools` and `recentOutput` are capped at 50 entries, oldest dropped,
35
+ * on every append, so neither the in-memory status nor the cloned snapshot
36
+ * grows across a long run
37
+ *
38
+ * SINGLE WRITER CONTRACT (read this before adding another write site):
39
+ * `CoalescedStatusWriter` is the ONLY thing in this package that may write
40
+ * `status.json`. Not "the preferred way" - the only way. The predecessor had
41
+ * four unsynchronised writers to the same file, which is exactly how a run's
42
+ * displayed status ends up torn, stale, or overwritten by a slower writer
43
+ * racing a faster one; coalescing a single in-memory owner is what makes that
44
+ * class of bug structurally impossible instead of merely unlikely.
45
+ *
46
+ * Anything else that wants to influence a run's displayed status - pause a
47
+ * step, request a steer, ask a run to stop, report progress from a different
48
+ * process than the one that called `open()` - must NOT open or write
49
+ * `status.json` directly. It writes a sidecar/intent file instead, and the
50
+ * process holding this writer observes that file and folds it into its own
51
+ * `update()`. Readers for those intent files do not exist yet; that is a gap
52
+ * to fill, not a license to reach for `writeAtomicJson(statusPath, ...)`
53
+ * somewhere else. If you are about to write `status.json` from outside this
54
+ * class, stop - that is the bug this module exists to remove.
55
+ *
56
+ * AVOID:
57
+ * - Reading back `status.json` from disk to decide what to write next; the
58
+ * in-memory status held by `open()` is the only source of truth this class
59
+ * trusts
60
+ * - Adding a second writer of `status.json` anywhere else in the package,
61
+ * including "just this once" debug or recovery code
62
+ */
63
+ /** How long a burst of updates may be buffered before a trailing flush. */
64
+ const DEFAULT_FLUSH_INTERVAL_MS = 75;
65
+ /** Oldest-dropped cap for `recentTools` and `recentOutput`. */
66
+ const MAX_RECENT_ENTRIES = 50;
67
+ /**
68
+ * The one status filename.
69
+ *
70
+ * Exported because the reconciler and the steering reader both have to find
71
+ * this file without going through the writer. Two modules matching a literal
72
+ * by eye is how a rename silently orphans a reader.
73
+ */
74
+ const STATUS_FILE_NAME = "status.json";
75
+ var CoalescedStatusWriter = class {
76
+ /**
77
+ * Runtime tuning seam for tests, kept out of the dependency constructor. A
78
+ * test subclass overrides this to avoid waiting
79
+ * out the real window when it does exercise the timer directly instead of
80
+ * using fake timers.
81
+ */
82
+ flushIntervalMs = DEFAULT_FLUSH_INTERVAL_MS;
83
+ statusPath;
84
+ status;
85
+ dirtyCount = 0;
86
+ flushTimer;
87
+ open(scope, runId, initialStatus) {
88
+ if (this.flushTimer) {
89
+ clearTimeout(this.flushTimer);
90
+ this.flushTimer = void 0;
91
+ }
92
+ this.statusPath = node_path.join(require_externalProcessIpc.scopeRunsDir(scope), runId, STATUS_FILE_NAME);
93
+ this.status = initialStatus;
94
+ this.dirtyCount = 0;
95
+ require_atomicJson.writeAtomicJson(this.statusPath, this.clone(initialStatus));
96
+ }
97
+ update(mutator) {
98
+ mutator(this.requireStatus());
99
+ this.dirtyCount++;
100
+ this.scheduleFlush();
101
+ }
102
+ updateSync(mutator) {
103
+ mutator(this.requireStatus());
104
+ this.dirtyCount++;
105
+ this.flush();
106
+ }
107
+ appendTool(entry) {
108
+ this.update((status) => appendCapped(status, "recentTools", entry));
109
+ }
110
+ appendOutput(entry) {
111
+ this.update((status) => appendCapped(status, "recentOutput", entry));
112
+ }
113
+ close() {
114
+ this.flush();
115
+ }
116
+ /**
117
+ * The clone-and-write step. Protected so a test can override `clone()`
118
+ * alone and assert it was never called across a run of no-op flushes,
119
+ * which is the direct, observable proof that the dirty-counter gate works.
120
+ */
121
+ clone(value) {
122
+ return structuredClone(value);
123
+ }
124
+ flush() {
125
+ if (this.flushTimer) {
126
+ clearTimeout(this.flushTimer);
127
+ this.flushTimer = void 0;
128
+ }
129
+ if (this.dirtyCount === 0) return;
130
+ const status = this.status;
131
+ const statusPath = this.statusPath;
132
+ if (!status || !statusPath) return;
133
+ const snapshot = this.clone(status);
134
+ this.dirtyCount = 0;
135
+ require_atomicJson.writeAtomicJson(statusPath, snapshot);
136
+ }
137
+ scheduleFlush() {
138
+ if (this.flushTimer) return;
139
+ const timer = setTimeout(() => this.flush(), this.flushIntervalMs);
140
+ timer.unref?.();
141
+ this.flushTimer = timer;
142
+ }
143
+ requireStatus() {
144
+ if (!this.status) throw new Error("CoalescedStatusWriter used before open().");
145
+ return this.status;
146
+ }
147
+ };
148
+ /** Push `entry` onto `status[field]`, dropping the oldest until at most 50 remain. */
149
+ function appendCapped(status, field, entry) {
150
+ const list = status[field] ?? [];
151
+ list.push(entry);
152
+ if (list.length > MAX_RECENT_ENTRIES) list.splice(0, list.length - MAX_RECENT_ENTRIES);
153
+ status[field] = list;
154
+ }
155
+ //#endregion
156
+ //#region src/bin/cliRunner.ts
157
+ /**
158
+ * Detached child process for an explicitly selected external agent CLI.
159
+ *
160
+ * Launch, readiness, control, status, and completion use one bounded Node IPC
161
+ * protocol. Durable status and result files are output records only. They are
162
+ * never read to discover live state or coordinate the parent and child.
163
+ */
164
+ const MAX_RESULT_BYTES = 65536;
165
+ const MAX_STDERR_BYTES = 8192;
166
+ const LAUNCH_TIMEOUT_MS = 15e3;
167
+ const PARENT_LOST_MESSAGE = "Parent process was lost.";
168
+ const FORCE_KILL_SIGNAL = "SIGKILL";
169
+ const STARTUP_ENVIRONMENT = Object.freeze({ ...process.env });
170
+ function errorMessage(error) {
171
+ return error instanceof Error ? error.message : String(error);
172
+ }
173
+ function isRecord(value) {
174
+ return typeof value === "object" && value !== null && !Array.isArray(value);
175
+ }
176
+ function validateLaunchConfig(value, runId) {
177
+ if (value.runId !== runId || typeof value.agent !== "string" || typeof value.task !== "string" || typeof value.runtime !== "string" || typeof value.command !== "string" || !Array.isArray(value.args) || !value.args.every((entry) => typeof entry === "string") || typeof value.cwd !== "string" || !isRecord(value.env) || typeof value.resultPath !== "string") throw new Error(`CLI launch config for run '${runId}' is invalid.`);
178
+ return value;
179
+ }
180
+ async function receiveLaunchConfig(scope, runId) {
181
+ return await new Promise((resolve, reject) => {
182
+ const finish = (error, config) => {
183
+ clearTimeout(timer);
184
+ process.off("message", onMessage);
185
+ process.off("disconnect", onDisconnect);
186
+ if (error) reject(error);
187
+ else resolve(config);
188
+ };
189
+ const onDisconnect = () => finish(/* @__PURE__ */ new Error(PARENT_LOST_MESSAGE));
190
+ const onMessage = (raw) => {
191
+ try {
192
+ const message = require_externalProcessIpc.parseExternalParentMessage(raw, {
193
+ runId,
194
+ scopeKey: scope.scopeKey
195
+ });
196
+ if (!message || message.kind !== "launch") return;
197
+ finish(void 0, validateLaunchConfig(message.config, runId));
198
+ } catch (error) {
199
+ finish(error instanceof Error ? error : new Error(String(error)));
200
+ }
201
+ };
202
+ const timer = setTimeout(() => finish(/* @__PURE__ */ new Error(`Timed out waiting for CLI launch config for run '${runId}'.`)), LAUNCH_TIMEOUT_MS);
203
+ timer.unref();
204
+ process.on("message", onMessage);
205
+ process.once("disconnect", onDisconnect);
206
+ });
207
+ }
208
+ function appendBounded(buffer, chunk, limit) {
209
+ let combined = buffer + chunk;
210
+ while (Buffer.byteLength(combined, "utf8") > limit && combined.length > 0) {
211
+ const excess = Buffer.byteLength(combined, "utf8") - limit;
212
+ combined = combined.slice(Math.max(1, Math.ceil(excess / 2)));
213
+ }
214
+ return combined;
215
+ }
216
+ let childTelemetry;
217
+ async function finishTelemetry(event, attributes, error) {
218
+ const telemetry = childTelemetry;
219
+ childTelemetry = void 0;
220
+ if (!telemetry) return;
221
+ if (error === void 0) await telemetry.recordEvent(event, attributes);
222
+ else await telemetry.recordError(event, error, attributes);
223
+ await telemetry.flush();
224
+ await telemetry.shutdown();
225
+ }
226
+ function projection(config, state, startedAt, fields = {}) {
227
+ return {
228
+ runId: config.runId,
229
+ agent: config.agent,
230
+ task: config.sensitiveTask ? "" : config.task,
231
+ runtime: config.runtime,
232
+ state,
233
+ startedAt,
234
+ updatedAt: Date.now(),
235
+ cwd: config.cwd,
236
+ ...fields
237
+ };
238
+ }
239
+ function resultFor(config, success, summary, exit) {
240
+ return {
241
+ runId: config.runId,
242
+ ...config.operationId ? { operationId: config.operationId } : {},
243
+ ...config.internal ? { internal: true } : {},
244
+ agent: config.agent,
245
+ runtime: config.runtime,
246
+ success,
247
+ summary,
248
+ ...exit?.code === null || exit?.code === void 0 ? {} : { exitCode: exit.code },
249
+ ...exit?.signal ? { signal: exit.signal } : {}
250
+ };
251
+ }
252
+ function runnerMessage(scope, runId, message) {
253
+ const base = {
254
+ channel: require_externalProcessIpc.EXTERNAL_IPC_CHANNEL,
255
+ version: 1,
256
+ direction: "runner",
257
+ runId,
258
+ scopeKey: scope.scopeKey
259
+ };
260
+ if (message.kind === "ack") return {
261
+ ...base,
262
+ ...message,
263
+ command: "steer"
264
+ };
265
+ return {
266
+ ...base,
267
+ ...message
268
+ };
269
+ }
270
+ function send(scope, runId, message) {
271
+ return require_externalProcessIpc.sendRunnerMessage(runnerMessage(scope, runId, message));
272
+ }
273
+ async function run() {
274
+ const startedAt = Date.now();
275
+ const runId = STARTUP_ENVIRONMENT[require_environment.SUBAGENT_RUN_ID_ENV]?.trim();
276
+ if (!runId) throw new Error(`${require_environment.SUBAGENT_RUN_ID_ENV} is required.`);
277
+ const scope = require_externalProcessIpc.adoptSessionScopeFromEnv(STARTUP_ENVIRONMENT);
278
+ if (!scope) throw new Error(`${_agimon_ai_po_core_childProcess.SUBAGENT_ROOT_SESSION_ENV} is required: a child cannot resolve its session scope without it.`);
279
+ const config = await receiveLaunchConfig(scope, runId);
280
+ childTelemetry = (0, _agimon_ai_po_telemetry.createDoomTelemetry)({
281
+ serviceName: "doom-team-cli-child",
282
+ packageName: "@agimon-ai/po-team",
283
+ env: config.env,
284
+ enableLogs: true,
285
+ enableTraces: true
286
+ });
287
+ const statusWriter = new CoalescedStatusWriter();
288
+ statusWriter.open(scope, runId, {
289
+ version: 1,
290
+ runId,
291
+ ...config.operationId ? { operationId: config.operationId } : {},
292
+ agent: config.agent,
293
+ ...config.sensitiveTask ? {} : { task: config.task },
294
+ cwd: config.cwd,
295
+ runtime: config.runtime,
296
+ state: "queued",
297
+ startedAt,
298
+ lastUpdate: startedAt
299
+ });
300
+ await childTelemetry.recordEvent("doom_team.child_started", {
301
+ runtime: config.runtime,
302
+ "agent.name": config.agent,
303
+ outcome: "started"
304
+ });
305
+ const profileLaunch = config.profile === require_externalProcessIpc.CLAUDE_FABLE_PROFILE;
306
+ if (config.profile !== void 0 && !profileLaunch) throw new Error("Untrusted external profile.");
307
+ if (profileLaunch && (!config.stdinPath || !config.profileResultPath)) throw new Error("Fable profile launch config is incomplete.");
308
+ const stdinFd = profileLaunch ? node_fs.openSync(config.stdinPath, "r") : void 0;
309
+ let child;
310
+ try {
311
+ child = (0, node_child_process.spawn)(config.command, config.args, {
312
+ cwd: config.cwd,
313
+ env: config.env,
314
+ stdio: [
315
+ stdinFd ?? "ignore",
316
+ "pipe",
317
+ "pipe"
318
+ ],
319
+ detached: true,
320
+ windowsHide: true
321
+ });
322
+ } finally {
323
+ if (stdinFd !== void 0) node_fs.closeSync(stdinFd);
324
+ }
325
+ const cleanupProfile = (removeResult) => {
326
+ if (!profileLaunch) return;
327
+ require_externalProcessIpc.cleanupClaudeFableLaunch({ cleanupPaths: config.cleanupPaths ?? [] });
328
+ if (removeResult && config.profileResultPath) node_fs.rmSync(config.profileResultPath, { force: true });
329
+ };
330
+ let requestedSignal;
331
+ let finalizing = false;
332
+ const stopVendor = (signal) => {
333
+ requestedSignal = signal;
334
+ if (!child.pid) return;
335
+ try {
336
+ process.kill(-child.pid, signal);
337
+ } catch (error) {
338
+ process.stderr.write(`[doom-team cli runner] Could not signal vendor process: ${errorMessage(error)}\n`);
339
+ }
340
+ };
341
+ const onSigterm = () => stopVendor("SIGTERM");
342
+ const onSigint = () => stopVendor("SIGINT");
343
+ process.once("SIGTERM", onSigterm);
344
+ process.once("SIGINT", onSigint);
345
+ const onControl = (raw) => {
346
+ const message = require_externalProcessIpc.parseExternalParentMessage(raw, {
347
+ runId,
348
+ scopeKey: scope.scopeKey
349
+ });
350
+ if (!message || message.kind !== "control") return;
351
+ if (message.command === "steer") {
352
+ send(scope, runId, {
353
+ kind: "ack",
354
+ requestId: message.requestId,
355
+ state: "failed",
356
+ message: `Runtime '${config.runtime}' does not support live steering.`
357
+ });
358
+ return;
359
+ }
360
+ stopVendor(message.command === "interrupt" ? "SIGINT" : "SIGTERM");
361
+ };
362
+ process.on("message", onControl);
363
+ const onParentLost = () => {
364
+ if (finalizing) return;
365
+ finalizing = true;
366
+ stopVendor(FORCE_KILL_SIGNAL);
367
+ const endedAt = Date.now();
368
+ statusWriter.updateSync((status) => {
369
+ status.state = "stopped";
370
+ status.error = PARENT_LOST_MESSAGE;
371
+ status.lastUpdate = endedAt;
372
+ status.endedAt = endedAt;
373
+ });
374
+ require_atomicJson.writeAtomicJson(config.resultPath, {
375
+ ...resultFor(config, false, PARENT_LOST_MESSAGE, {
376
+ code: null,
377
+ signal: FORCE_KILL_SIGNAL
378
+ }),
379
+ state: "stopped",
380
+ ...config.internal ? { internal: true } : {}
381
+ });
382
+ statusWriter.close();
383
+ cleanupProfile(true);
384
+ finishTelemetry("doom_team.child_finished", {
385
+ runtime: config.runtime,
386
+ "agent.name": config.agent,
387
+ duration_ms: Date.now() - startedAt,
388
+ outcome: "parent_lost"
389
+ }).finally(() => process.exit(0));
390
+ };
391
+ process.once("disconnect", onParentLost);
392
+ try {
393
+ await new Promise((resolve, reject) => {
394
+ child.once("spawn", resolve);
395
+ child.once("error", reject);
396
+ });
397
+ const running = projection(config, "running", startedAt);
398
+ statusWriter.updateSync((status) => {
399
+ status.state = "running";
400
+ status.activityState = "working";
401
+ status.lastUpdate = Date.now();
402
+ });
403
+ await send(scope, runId, {
404
+ kind: "status",
405
+ status: running
406
+ });
407
+ await send(scope, runId, { kind: "ready" });
408
+ } catch (error) {
409
+ finalizing = true;
410
+ const message = errorMessage(error);
411
+ const endedAt = Date.now();
412
+ const result = {
413
+ ...resultFor(config, false, profileLaunch ? "Fable Claude launch failed." : message),
414
+ state: "failed"
415
+ };
416
+ statusWriter.updateSync((status) => {
417
+ status.state = "failed";
418
+ status.error = message;
419
+ status.lastUpdate = endedAt;
420
+ status.endedAt = endedAt;
421
+ });
422
+ require_atomicJson.writeAtomicJson(config.resultPath, {
423
+ ...result,
424
+ ...config.internal ? { internal: true } : {}
425
+ });
426
+ await send(scope, runId, {
427
+ kind: "error",
428
+ error: message
429
+ });
430
+ await send(scope, runId, {
431
+ kind: "result",
432
+ result
433
+ });
434
+ statusWriter.close();
435
+ cleanupProfile(true);
436
+ await finishTelemetry("doom_team.child_failed", {
437
+ runtime: config.runtime,
438
+ "agent.name": config.agent,
439
+ duration_ms: Date.now() - startedAt,
440
+ outcome: "failed"
441
+ }, error);
442
+ process.exit(1);
443
+ }
444
+ let stdout = "";
445
+ let stderr = "";
446
+ child.stdout?.on("data", (chunk) => {
447
+ stdout = appendBounded(stdout, chunk.toString("utf8"), MAX_RESULT_BYTES);
448
+ });
449
+ child.stderr?.on("data", (chunk) => {
450
+ stderr = appendBounded(stderr, chunk.toString("utf8"), MAX_STDERR_BYTES);
451
+ });
452
+ const exit = await new Promise((resolve) => {
453
+ child.on("error", (error) => resolve({
454
+ code: null,
455
+ signal: null,
456
+ error
457
+ }));
458
+ child.on("close", (code, signal) => resolve({
459
+ code,
460
+ signal
461
+ }));
462
+ });
463
+ finalizing = true;
464
+ process.off("message", onControl);
465
+ process.off("disconnect", onParentLost);
466
+ process.off("SIGTERM", onSigterm);
467
+ process.off("SIGINT", onSigint);
468
+ const stopped = requestedSignal !== void 0;
469
+ let profileError;
470
+ if (profileLaunch && !stopped && exit.error === void 0 && exit.code === 0) try {
471
+ const parsed = require_externalProcessIpc.parseClaudeFableOutput(stdout);
472
+ require_atomicJson.writePrivateAtomicJson(config.profileResultPath, {
473
+ text: parsed.text,
474
+ outputBytes: parsed.outputBytes
475
+ });
476
+ } catch (error) {
477
+ profileError = error instanceof Error ? error : new Error(String(error));
478
+ }
479
+ const success = !stopped && exit.error === void 0 && exit.code === 0 && profileError === void 0;
480
+ const failureDetail = profileLaunch ? profileError?.message ?? "Fable Claude launch failed." : stderr.trim() || `${config.runtime} exited with ${exit.signal ?? `code ${exit.code ?? "unknown"}`}.`;
481
+ const summary = stopped ? `Stopped by ${requestedSignal}.` : success ? profileLaunch ? "Fable profile completed." : stdout.trim() : exit.error?.message ?? failureDetail;
482
+ const endedAt = Date.now();
483
+ const state = stopped ? "stopped" : success ? "completed" : "failed";
484
+ const result = {
485
+ ...resultFor(config, success, summary, exit),
486
+ state
487
+ };
488
+ statusWriter.updateSync((status) => {
489
+ status.state = state;
490
+ status.activityState = "finalizing";
491
+ status.summary = summary;
492
+ if (!success) status.error = summary;
493
+ status.lastUpdate = endedAt;
494
+ status.endedAt = endedAt;
495
+ });
496
+ require_atomicJson.writeAtomicJson(config.resultPath, {
497
+ ...result,
498
+ ...config.internal ? { internal: true } : {}
499
+ });
500
+ await send(scope, runId, {
501
+ kind: "status",
502
+ status: projection(config, state, startedAt, {
503
+ summary,
504
+ ...!success ? { error: summary } : {}
505
+ })
506
+ });
507
+ await send(scope, runId, {
508
+ kind: "result",
509
+ result
510
+ });
511
+ statusWriter.close();
512
+ cleanupProfile(!success);
513
+ await finishTelemetry("doom_team.child_finished", {
514
+ runtime: config.runtime,
515
+ "agent.name": config.agent,
516
+ duration_ms: Date.now() - startedAt,
517
+ "runner.stdout_bytes": Buffer.byteLength(stdout, "utf8"),
518
+ "runner.stderr_bytes": Buffer.byteLength(stderr, "utf8"),
519
+ "runner.exit_code": exit.code ?? 0,
520
+ outcome: state
521
+ });
522
+ process.exit(0);
523
+ }
524
+ run().catch(async (error) => {
525
+ const runId = STARTUP_ENVIRONMENT[require_environment.SUBAGENT_RUN_ID_ENV]?.trim();
526
+ const scope = require_externalProcessIpc.adoptSessionScopeFromEnv(STARTUP_ENVIRONMENT);
527
+ if (runId && scope && process.connected) try {
528
+ await send(scope, runId, {
529
+ kind: "error",
530
+ error: errorMessage(error)
531
+ });
532
+ } catch {}
533
+ await finishTelemetry("doom_team.child_failed", { outcome: "failed" }, error);
534
+ process.stderr.write(`[doom-team cli runner] ${errorMessage(error)}\n`);
535
+ process.exitCode = 1;
536
+ });
537
+ //#endregion
538
+
539
+ //# sourceMappingURL=cliRunnerEntry.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cliRunnerEntry.cjs","names":["path","scopeRunsDir","parseExternalParentMessage","EXTERNAL_IPC_CHANNEL","sendRunnerMessage","SUBAGENT_RUN_ID_ENV","adoptSessionScopeFromEnv","SUBAGENT_ROOT_SESSION_ENV","createDoomTelemetry","CLAUDE_FABLE_PROFILE","fs","spawn","parseClaudeFableOutput"],"sources":["../../../src/services/statusWriter/index.ts","../../../src/bin/cliRunner.ts"],"sourcesContent":["/**\n * Coalesced writer for a run's `status.json`.\n *\n * WHY THIS EXISTS:\n * In the predecessor (`po-subagents/src/runs/background/subagent-runner.ts`)\n * `status.json` was rewritten in full on every child event, and every rewrite\n * `structuredClone`d the whole run graph first. On a fan-out run that makes the\n * hot path quadratic: N events cost O(N) clones of an O(N)-sized graph. Its\n * `recentTools` and `recentOutput` arrays were also appended to and never\n * trimmed, so a long run's status file, and the cost of cloning it, grew\n * without bound.\n *\n * DESIGN PATTERNS:\n * - Coalescing: `update()` mutates the in-memory status and arms a trailing\n * ~75ms timer. A burst of events inside that window costs one clone and one\n * write, not one per event\n * - The clone is gated by a dirty counter, not by the timer firing. A flush\n * with nothing dirty since the last one performs no clone and no write at\n * all, which is the specific fix for the quadratic behaviour above\n * - `updateSync()` bypasses the timer for transitions that must not be lost if\n * the process dies right after: terminal run status, and chain step\n * transitions. Everything else can wait out the coalescing window\n * - `recentTools` and `recentOutput` are capped at 50 entries, oldest dropped,\n * on every append, so neither the in-memory status nor the cloned snapshot\n * grows across a long run\n *\n * SINGLE WRITER CONTRACT (read this before adding another write site):\n * `CoalescedStatusWriter` is the ONLY thing in this package that may write\n * `status.json`. Not \"the preferred way\" - the only way. The predecessor had\n * four unsynchronised writers to the same file, which is exactly how a run's\n * displayed status ends up torn, stale, or overwritten by a slower writer\n * racing a faster one; coalescing a single in-memory owner is what makes that\n * class of bug structurally impossible instead of merely unlikely.\n *\n * Anything else that wants to influence a run's displayed status - pause a\n * step, request a steer, ask a run to stop, report progress from a different\n * process than the one that called `open()` - must NOT open or write\n * `status.json` directly. It writes a sidecar/intent file instead, and the\n * process holding this writer observes that file and folds it into its own\n * `update()`. Readers for those intent files do not exist yet; that is a gap\n * to fill, not a license to reach for `writeAtomicJson(statusPath, ...)`\n * somewhere else. If you are about to write `status.json` from outside this\n * class, stop - that is the bug this module exists to remove.\n *\n * AVOID:\n * - Reading back `status.json` from disk to decide what to write next; the\n * in-memory status held by `open()` is the only source of truth this class\n * trusts\n * - Adding a second writer of `status.json` anywhere else in the package,\n * including \"just this once\" debug or recovery code\n */\n\nimport * as path from 'node:path';\n\nimport { writeAtomicJson } from '../atomicJson';\nimport { scopeRunsDir, type SessionScope } from '../sessionPaths';\n\n/** How long a burst of updates may be buffered before a trailing flush. */\nconst DEFAULT_FLUSH_INTERVAL_MS = 75;\n\n/** Oldest-dropped cap for `recentTools` and `recentOutput`. */\nconst MAX_RECENT_ENTRIES = 50;\n\n/**\n * The one status filename.\n *\n * Exported because the reconciler and the steering reader both have to find\n * this file without going through the writer. Two modules matching a literal\n * by eye is how a rename silently orphans a reader.\n */\nexport const STATUS_FILE_NAME = 'status.json';\n\n/**\n * The minimum shape this writer needs to know about. Everything else in a\n * concrete run's status is opaque to it: capping `recentTools` and\n * `recentOutput` is the one piece of run semantics this module owns, because\n * it is the specific fix for the unbounded-growth bug above.\n */\nexport interface StatusWithRecentEntries {\n recentTools?: unknown[];\n recentOutput?: unknown[];\n}\n\nexport interface CoalescedStatusWriterContract<TStatus extends StatusWithRecentEntries = StatusWithRecentEntries> {\n /**\n * Start tracking a run's status and write it once, synchronously, so the\n * file exists before the caller does anything else.\n *\n * Calling this again, on the same or a different `runId`, is a reset, not\n * an error: it discards whatever was previously tracked, including any\n * mutation buffered by `update()` that had not flushed yet, cancels the\n * pending coalescing timer, and starts a fresh session against the new\n * status. This is deliberate so a runner that retries a bootstrap step can\n * just call `open()` again rather than having to detect and recover from a\n * half-initialized writer.\n */\n open(scope: SessionScope, runId: string, initialStatus: TStatus): void;\n /** Apply an in-memory mutation and let the trailing timer coalesce the write. */\n update(mutator: (status: TStatus) => void): void;\n /** Apply an in-memory mutation and flush synchronously, for transitions that must survive a crash. */\n updateSync(mutator: (status: TStatus) => void): void;\n /** Append one entry to `recentTools`, capped at 50, coalesced like `update()`. */\n appendTool(entry: unknown): void;\n /** Append one entry to `recentOutput`, capped at 50, coalesced like `update()`. */\n appendOutput(entry: unknown): void;\n /** Cancel any pending timer and flush whatever is dirty. Safe to call more than once. */\n close(): void;\n}\n\nexport class CoalescedStatusWriter<\n TStatus extends StatusWithRecentEntries = StatusWithRecentEntries,\n> implements CoalescedStatusWriterContract<TStatus> {\n /**\n * Runtime tuning seam for tests, kept out of the dependency constructor. A\n * test subclass overrides this to avoid waiting\n * out the real window when it does exercise the timer directly instead of\n * using fake timers.\n */\n protected readonly flushIntervalMs: number = DEFAULT_FLUSH_INTERVAL_MS;\n\n private statusPath: string | undefined;\n private status: TStatus | undefined;\n private dirtyCount = 0;\n private flushTimer: NodeJS.Timeout | undefined;\n\n open(scope: SessionScope, runId: string, initialStatus: TStatus): void {\n // A second open() is a reset: cancel whatever this instance was\n // previously tracking (including an unflushed dirty mutation) rather\n // than merging with it. See the doc comment on the interface method.\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = undefined;\n }\n this.statusPath = path.join(scopeRunsDir(scope), runId, STATUS_FILE_NAME);\n this.status = initialStatus;\n this.dirtyCount = 0;\n // The initial write is not a coalescing candidate: callers rely on the\n // file existing as soon as `open()` returns, so it always goes straight\n // to disk rather than waiting for a timer.\n writeAtomicJson(this.statusPath, this.clone(initialStatus));\n }\n\n update(mutator: (status: TStatus) => void): void {\n mutator(this.requireStatus());\n this.dirtyCount++;\n this.scheduleFlush();\n }\n\n updateSync(mutator: (status: TStatus) => void): void {\n mutator(this.requireStatus());\n this.dirtyCount++;\n this.flush();\n }\n\n appendTool(entry: unknown): void {\n this.update((status) => appendCapped(status, 'recentTools', entry));\n }\n\n appendOutput(entry: unknown): void {\n this.update((status) => appendCapped(status, 'recentOutput', entry));\n }\n\n close(): void {\n this.flush();\n }\n\n /**\n * The clone-and-write step. Protected so a test can override `clone()`\n * alone and assert it was never called across a run of no-op flushes,\n * which is the direct, observable proof that the dirty-counter gate works.\n */\n protected clone<T>(value: T): T {\n return structuredClone(value);\n }\n\n private flush(): void {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = undefined;\n }\n if (this.dirtyCount === 0) return;\n const status = this.status;\n const statusPath = this.statusPath;\n if (!status || !statusPath) return;\n const snapshot = this.clone(status);\n this.dirtyCount = 0;\n writeAtomicJson(statusPath, snapshot);\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer) return;\n const timer = setTimeout(() => this.flush(), this.flushIntervalMs);\n // A pending flush timer must never be the reason the process stays alive.\n timer.unref?.();\n this.flushTimer = timer;\n }\n\n private requireStatus(): TStatus {\n if (!this.status) throw new Error('CoalescedStatusWriter used before open().');\n return this.status;\n }\n}\n\n/** Push `entry` onto `status[field]`, dropping the oldest until at most 50 remain. */\nfunction appendCapped(status: StatusWithRecentEntries, field: 'recentTools' | 'recentOutput', entry: unknown): void {\n const list = status[field] ?? [];\n list.push(entry);\n if (list.length > MAX_RECENT_ENTRIES) list.splice(0, list.length - MAX_RECENT_ENTRIES);\n status[field] = list;\n}\n","/**\n * Detached child process for an explicitly selected external agent CLI.\n *\n * Launch, readiness, control, status, and completion use one bounded Node IPC\n * protocol. Durable status and result files are output records only. They are\n * never read to discover live state or coordinate the parent and child.\n */\n\nimport { spawn } from 'node:child_process';\nimport * as fs from 'node:fs';\n\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/po-telemetry';\n\nimport type { AsyncRunStatus } from '../services/asyncExecution';\nimport { writeAtomicJson, writePrivateAtomicJson } from '../services/atomicJson';\nimport { CLAUDE_FABLE_PROFILE, cleanupClaudeFableLaunch, parseClaudeFableOutput } from '../services/claudeFableProfile';\nimport type { CliLaunchConfig } from '../services/cliLaunchConfig';\nimport {\n EXTERNAL_IPC_CHANNEL,\n EXTERNAL_IPC_VERSION,\n parseExternalParentMessage,\n sendRunnerMessage,\n type ExternalRunProjection,\n type ExternalRunnerMessage,\n} from '../services/externalProcessIpc';\nimport { adoptSessionScopeFromEnv, type SessionScope } from '../services/sessionPaths';\nimport { CoalescedStatusWriter } from '../services/statusWriter';\nimport { SUBAGENT_ROOT_SESSION_ENV, SUBAGENT_RUN_ID_ENV } from '../types/environment';\n\nconst MAX_RESULT_BYTES = 64 * 1024;\nconst MAX_STDERR_BYTES = 8 * 1024;\nconst LAUNCH_TIMEOUT_MS = 15_000;\nconst PARENT_LOST_MESSAGE = 'Parent process was lost.';\nconst FORCE_KILL_SIGNAL: NodeJS.Signals = 'SIGKILL';\nconst STARTUP_ENVIRONMENT: Readonly<Record<string, string | undefined>> = Object.freeze({ ...process.env });\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction validateLaunchConfig(value: Record<string, unknown>, runId: string): CliLaunchConfig {\n if (\n value.runId !== runId ||\n typeof value.agent !== 'string' ||\n typeof value.task !== 'string' ||\n typeof value.runtime !== 'string' ||\n typeof value.command !== 'string' ||\n !Array.isArray(value.args) ||\n !value.args.every((entry) => typeof entry === 'string') ||\n typeof value.cwd !== 'string' ||\n !isRecord(value.env) ||\n typeof value.resultPath !== 'string'\n ) {\n throw new Error(`CLI launch config for run '${runId}' is invalid.`);\n }\n return value as unknown as CliLaunchConfig;\n}\n\nasync function receiveLaunchConfig(scope: SessionScope, runId: string): Promise<CliLaunchConfig> {\n return await new Promise<CliLaunchConfig>((resolve, reject) => {\n const finish = (error?: Error, config?: CliLaunchConfig): void => {\n clearTimeout(timer);\n process.off('message', onMessage);\n process.off('disconnect', onDisconnect);\n if (error) reject(error);\n else resolve(config!);\n };\n const onDisconnect = (): void => finish(new Error(PARENT_LOST_MESSAGE));\n const onMessage = (raw: unknown): void => {\n try {\n const message = parseExternalParentMessage(raw, { runId, scopeKey: scope.scopeKey });\n if (!message || message.kind !== 'launch') return;\n finish(undefined, validateLaunchConfig(message.config, runId));\n } catch (error) {\n finish(error instanceof Error ? error : new Error(String(error)));\n }\n };\n const timer = setTimeout(\n () => finish(new Error(`Timed out waiting for CLI launch config for run '${runId}'.`)),\n LAUNCH_TIMEOUT_MS,\n );\n timer.unref();\n process.on('message', onMessage);\n process.once('disconnect', onDisconnect);\n });\n}\n\nfunction appendBounded(buffer: string, chunk: string, limit: number): string {\n let combined = buffer + chunk;\n while (Buffer.byteLength(combined, 'utf8') > limit && combined.length > 0) {\n const excess = Buffer.byteLength(combined, 'utf8') - limit;\n combined = combined.slice(Math.max(1, Math.ceil(excess / 2)));\n }\n return combined;\n}\n\nlet childTelemetry: DoomTelemetry | undefined;\n\nasync function finishTelemetry(event: string, attributes: Record<string, unknown>, error?: unknown): Promise<void> {\n const telemetry = childTelemetry;\n childTelemetry = undefined;\n if (!telemetry) return;\n if (error === undefined) await telemetry.recordEvent(event, attributes);\n else await telemetry.recordError(event, error, attributes);\n await telemetry.flush();\n await telemetry.shutdown();\n}\n\nfunction projection(\n config: CliLaunchConfig,\n state: ExternalRunProjection['state'],\n startedAt: number,\n fields: Partial<Pick<ExternalRunProjection, 'summary' | 'error'>> = {},\n): ExternalRunProjection {\n return {\n runId: config.runId,\n agent: config.agent,\n task: config.sensitiveTask ? '' : config.task,\n runtime: config.runtime,\n state,\n startedAt,\n updatedAt: Date.now(),\n cwd: config.cwd,\n ...fields,\n };\n}\n\nfunction resultFor(\n config: CliLaunchConfig,\n success: boolean,\n summary: string,\n exit?: { code: number | null; signal: NodeJS.Signals | null },\n): Record<string, unknown> {\n return {\n runId: config.runId,\n ...(config.operationId ? { operationId: config.operationId } : {}),\n ...(config.internal ? { internal: true } : {}),\n agent: config.agent,\n runtime: config.runtime,\n success,\n summary,\n ...(exit?.code === null || exit?.code === undefined ? {} : { exitCode: exit.code }),\n ...(exit?.signal ? { signal: exit.signal } : {}),\n };\n}\n\nfunction runnerMessage(\n scope: SessionScope,\n runId: string,\n message:\n | { kind: 'ready' }\n | { kind: 'status'; status: ExternalRunProjection }\n | { kind: 'result'; result: Record<string, unknown> }\n | { kind: 'error'; error: string }\n | { kind: 'ack'; requestId: string; state: 'delivered' | 'failed'; message: string },\n): ExternalRunnerMessage {\n const base = {\n channel: EXTERNAL_IPC_CHANNEL,\n version: EXTERNAL_IPC_VERSION,\n direction: 'runner',\n runId,\n scopeKey: scope.scopeKey,\n } as const;\n if (message.kind === 'ack') return { ...base, ...message, command: 'steer' };\n return { ...base, ...message };\n}\n\nfunction send(scope: SessionScope, runId: string, message: Parameters<typeof runnerMessage>[2]): Promise<void> {\n return sendRunnerMessage(runnerMessage(scope, runId, message));\n}\n\nasync function run(): Promise<void> {\n const startedAt = Date.now();\n const runId = STARTUP_ENVIRONMENT[SUBAGENT_RUN_ID_ENV]?.trim();\n if (!runId) throw new Error(`${SUBAGENT_RUN_ID_ENV} is required.`);\n const scope = adoptSessionScopeFromEnv(STARTUP_ENVIRONMENT);\n if (!scope) {\n throw new Error(`${SUBAGENT_ROOT_SESSION_ENV} is required: a child cannot resolve its session scope without it.`);\n }\n const config = await receiveLaunchConfig(scope, runId);\n\n childTelemetry = createDoomTelemetry({\n serviceName: 'doom-team-cli-child',\n packageName: '@agimon-ai/po-team',\n env: config.env,\n enableLogs: true,\n enableTraces: true,\n });\n\n const statusWriter = new CoalescedStatusWriter<AsyncRunStatus>();\n statusWriter.open(scope, runId, {\n version: 1,\n runId,\n ...(config.operationId ? { operationId: config.operationId } : {}),\n agent: config.agent,\n ...(config.sensitiveTask ? {} : { task: config.task }),\n cwd: config.cwd,\n runtime: config.runtime,\n state: 'queued',\n startedAt,\n lastUpdate: startedAt,\n });\n\n await childTelemetry.recordEvent('doom_team.child_started', {\n runtime: config.runtime,\n 'agent.name': config.agent,\n outcome: 'started',\n });\n\n const profileLaunch = config.profile === CLAUDE_FABLE_PROFILE;\n if (config.profile !== undefined && !profileLaunch) throw new Error('Untrusted external profile.');\n if (profileLaunch && (!config.stdinPath || !config.profileResultPath)) {\n throw new Error('Fable profile launch config is incomplete.');\n }\n\n const stdinFd = profileLaunch ? fs.openSync(config.stdinPath!, 'r') : undefined;\n let child: ReturnType<typeof spawn>;\n try {\n child = spawn(config.command, config.args, {\n cwd: config.cwd,\n env: config.env,\n stdio: [stdinFd ?? 'ignore', 'pipe', 'pipe'],\n detached: true,\n windowsHide: true,\n });\n } finally {\n if (stdinFd !== undefined) fs.closeSync(stdinFd);\n }\n\n const cleanupProfile = (removeResult: boolean): void => {\n if (!profileLaunch) return;\n cleanupClaudeFableLaunch({ cleanupPaths: config.cleanupPaths ?? [] });\n if (removeResult && config.profileResultPath) fs.rmSync(config.profileResultPath, { force: true });\n };\n\n let requestedSignal: NodeJS.Signals | undefined;\n let finalizing = false;\n const stopVendor = (signal: NodeJS.Signals): void => {\n requestedSignal = signal;\n if (!child.pid) return;\n try {\n process.kill(-child.pid, signal);\n } catch (error) {\n process.stderr.write(`[doom-team cli runner] Could not signal vendor process: ${errorMessage(error)}\\n`);\n }\n };\n const onSigterm = (): void => stopVendor('SIGTERM');\n const onSigint = (): void => stopVendor('SIGINT');\n process.once('SIGTERM', onSigterm);\n process.once('SIGINT', onSigint);\n\n const onControl = (raw: unknown): void => {\n const message = parseExternalParentMessage(raw, { runId, scopeKey: scope.scopeKey });\n if (!message || message.kind !== 'control') return;\n if (message.command === 'steer') {\n void send(scope, runId, {\n kind: 'ack',\n requestId: message.requestId,\n state: 'failed',\n message: `Runtime '${config.runtime}' does not support live steering.`,\n });\n return;\n }\n stopVendor(message.command === 'interrupt' ? 'SIGINT' : 'SIGTERM');\n };\n process.on('message', onControl);\n\n const onParentLost = (): void => {\n if (finalizing) return;\n finalizing = true;\n stopVendor(FORCE_KILL_SIGNAL);\n const endedAt = Date.now();\n statusWriter.updateSync((status) => {\n status.state = 'stopped';\n status.error = PARENT_LOST_MESSAGE;\n status.lastUpdate = endedAt;\n status.endedAt = endedAt;\n });\n writeAtomicJson(config.resultPath, {\n ...resultFor(config, false, PARENT_LOST_MESSAGE, { code: null, signal: FORCE_KILL_SIGNAL }),\n state: 'stopped',\n ...(config.internal ? { internal: true } : {}),\n });\n statusWriter.close();\n cleanupProfile(true);\n void finishTelemetry('doom_team.child_finished', {\n runtime: config.runtime,\n 'agent.name': config.agent,\n duration_ms: Date.now() - startedAt,\n outcome: 'parent_lost',\n }).finally(() => process.exit(0));\n };\n process.once('disconnect', onParentLost);\n\n try {\n await new Promise<void>((resolve, reject) => {\n child.once('spawn', resolve);\n child.once('error', reject);\n });\n const running = projection(config, 'running', startedAt);\n statusWriter.updateSync((status) => {\n status.state = 'running';\n status.activityState = 'working';\n status.lastUpdate = Date.now();\n });\n await send(scope, runId, { kind: 'status', status: running });\n await send(scope, runId, { kind: 'ready' });\n } catch (error) {\n finalizing = true;\n const message = errorMessage(error);\n const endedAt = Date.now();\n const result = {\n ...resultFor(config, false, profileLaunch ? 'Fable Claude launch failed.' : message),\n state: 'failed',\n };\n statusWriter.updateSync((status) => {\n status.state = 'failed';\n status.error = message;\n status.lastUpdate = endedAt;\n status.endedAt = endedAt;\n });\n writeAtomicJson(config.resultPath, { ...result, ...(config.internal ? { internal: true } : {}) });\n await send(scope, runId, { kind: 'error', error: message });\n await send(scope, runId, { kind: 'result', result });\n statusWriter.close();\n cleanupProfile(true);\n await finishTelemetry(\n 'doom_team.child_failed',\n { runtime: config.runtime, 'agent.name': config.agent, duration_ms: Date.now() - startedAt, outcome: 'failed' },\n error,\n );\n process.exit(1);\n }\n\n let stdout = '';\n let stderr = '';\n child.stdout?.on('data', (chunk: Buffer) => {\n stdout = appendBounded(stdout, chunk.toString('utf8'), MAX_RESULT_BYTES);\n });\n child.stderr?.on('data', (chunk: Buffer) => {\n stderr = appendBounded(stderr, chunk.toString('utf8'), MAX_STDERR_BYTES);\n });\n\n const exit = await new Promise<{ code: number | null; signal: NodeJS.Signals | null; error?: Error }>((resolve) => {\n child.on('error', (error) => resolve({ code: null, signal: null, error }));\n child.on('close', (code, signal) => resolve({ code, signal }));\n });\n finalizing = true;\n process.off('message', onControl);\n process.off('disconnect', onParentLost);\n process.off('SIGTERM', onSigterm);\n process.off('SIGINT', onSigint);\n\n const stopped = requestedSignal !== undefined;\n let profileError: Error | undefined;\n if (profileLaunch && !stopped && exit.error === undefined && exit.code === 0) {\n try {\n const parsed = parseClaudeFableOutput(stdout);\n writePrivateAtomicJson(config.profileResultPath!, { text: parsed.text, outputBytes: parsed.outputBytes });\n } catch (error) {\n profileError = error instanceof Error ? error : new Error(String(error));\n }\n }\n\n const success = !stopped && exit.error === undefined && exit.code === 0 && profileError === undefined;\n const failureDetail = profileLaunch\n ? (profileError?.message ?? 'Fable Claude launch failed.')\n : stderr.trim() || `${config.runtime} exited with ${exit.signal ?? `code ${exit.code ?? 'unknown'}`}.`;\n const summary = stopped\n ? `Stopped by ${requestedSignal}.`\n : success\n ? profileLaunch\n ? 'Fable profile completed.'\n : stdout.trim()\n : (exit.error?.message ?? failureDetail);\n const endedAt = Date.now();\n const state = stopped ? ('stopped' as const) : success ? ('completed' as const) : ('failed' as const);\n const result = { ...resultFor(config, success, summary, exit), state };\n\n statusWriter.updateSync((status) => {\n status.state = state;\n status.activityState = 'finalizing';\n status.summary = summary;\n if (!success) status.error = summary;\n status.lastUpdate = endedAt;\n status.endedAt = endedAt;\n });\n writeAtomicJson(config.resultPath, { ...result, ...(config.internal ? { internal: true } : {}) });\n await send(scope, runId, {\n kind: 'status',\n status: projection(config, state, startedAt, {\n summary,\n ...(!success ? { error: summary } : {}),\n }),\n });\n await send(scope, runId, { kind: 'result', result });\n\n statusWriter.close();\n cleanupProfile(!success);\n await finishTelemetry('doom_team.child_finished', {\n runtime: config.runtime,\n 'agent.name': config.agent,\n duration_ms: Date.now() - startedAt,\n 'runner.stdout_bytes': Buffer.byteLength(stdout, 'utf8'),\n 'runner.stderr_bytes': Buffer.byteLength(stderr, 'utf8'),\n 'runner.exit_code': exit.code ?? 0,\n outcome: state,\n });\n process.exit(0);\n}\n\nvoid run().catch(async (error: unknown) => {\n const runId = STARTUP_ENVIRONMENT[SUBAGENT_RUN_ID_ENV]?.trim();\n const scope = adoptSessionScopeFromEnv(STARTUP_ENVIRONMENT);\n if (runId && scope && process.connected) {\n try {\n await send(scope, runId, { kind: 'error', error: errorMessage(error) });\n } catch {\n // The parent channel is already gone, so stderr is the only remaining diagnostic.\n }\n }\n await finishTelemetry('doom_team.child_failed', { outcome: 'failed' }, error);\n process.stderr.write(`[doom-team cli runner] ${errorMessage(error)}\\n`);\n process.exitCode = 1;\n});\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {}