@agimon-ai/po-team 0.0.0-alpha.2 → 0.0.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +166 -5
- package/README.md +11 -12
- package/dist/{agentDiscovery-Whwzc4dP.cjs → agentDiscovery-DTTlM_LT.cjs} +246 -350
- package/dist/agentDiscovery-DTTlM_LT.cjs.map +1 -0
- package/dist/{agentDiscovery-ZQlFkKvB.mjs → agentDiscovery-ZNG8iZXV.mjs} +210 -279
- package/dist/agentDiscovery-ZNG8iZXV.mjs.map +1 -0
- package/dist/apiContracts.cjs +10 -3
- package/dist/apiContracts.cjs.map +1 -1
- package/dist/apiContracts.d.mts.map +1 -1
- package/dist/apiContracts.mjs +10 -3
- package/dist/apiContracts.mjs.map +1 -1
- package/dist/{externalProcessIpc-ojE0pvw0.cjs → atomicJson-DRT03Ql5.cjs} +155 -21
- package/dist/atomicJson-DRT03Ql5.cjs.map +1 -0
- package/dist/{externalProcessIpc-C-15lJrB.mjs → atomicJson-VVM1iAPu.mjs} +140 -12
- package/dist/atomicJson-VVM1iAPu.mjs.map +1 -0
- package/dist/{capabilityCeiling-CF7kAS18.mjs → capabilityCeiling-BaHT9v9S.mjs} +3 -3
- package/dist/capabilityCeiling-BaHT9v9S.mjs.map +1 -0
- package/dist/{capabilityCeiling-C-Y7H8oC.cjs → capabilityCeiling-CO3ZjYmY.cjs} +3 -3
- package/dist/capabilityCeiling-CO3ZjYmY.cjs.map +1 -0
- package/dist/capabilityCeiling.cjs +2 -2
- package/dist/capabilityCeiling.d.mts +2 -2
- package/dist/capabilityCeiling.mjs +2 -2
- package/dist/delegation.cjs +1 -1
- package/dist/delegation.cjs.map +1 -1
- package/dist/delegation.d.mts +1 -1
- package/dist/delegation.mjs +1 -1
- package/dist/delegation.mjs.map +1 -1
- package/dist/delegationApi.cjs +30 -30
- package/dist/delegationApi.d.mts +2 -2
- package/dist/delegationApi.mjs +1 -2
- package/dist/env.cjs +1 -1
- package/dist/env.d.mts +1 -1
- package/dist/env.mjs +1 -2
- package/dist/{environment-DrqhrxG_.mjs → environment-BtvJI2S-.mjs} +3 -3
- package/dist/environment-BtvJI2S-.mjs.map +1 -0
- package/dist/{environment-ma5oQ7uM.d.mts → environment-Bz1OlWIT.d.mts} +2 -2
- package/dist/{environment-ma5oQ7uM.d.mts.map → environment-Bz1OlWIT.d.mts.map} +1 -1
- package/dist/{environment-CaCW3SgT.cjs → environment-Cqs7vHJL.cjs} +3 -3
- package/dist/environment-Cqs7vHJL.cjs.map +1 -0
- package/dist/extensions/native.mjs +34 -12
- package/dist/extensions/native.mjs.map +1 -1
- package/dist/extensions/server.cjs +990 -786
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.mts +2 -2
- package/dist/extensions/server.d.mts.map +1 -1
- package/dist/extensions/server.mjs +975 -772
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/extensions/web.mjs +994 -807
- package/dist/extensions/web.mjs.map +1 -1
- package/dist/fablePlan.cjs +3 -3
- package/dist/fablePlan.d.mts +2 -2
- package/dist/fablePlan.mjs +1 -2
- package/dist/{fablePlanApi-CZ3uUcMi.d.mts → fablePlanApi-BTNKjLni.d.mts} +6 -6
- package/dist/{fablePlanApi-CZ3uUcMi.d.mts.map → fablePlanApi-BTNKjLni.d.mts.map} +1 -1
- package/dist/{fablePlanApi-wBu9bRXU.cjs → fablePlanApi-BhI4jnDP.cjs} +12 -12
- package/dist/fablePlanApi-BhI4jnDP.cjs.map +1 -0
- package/dist/{fablePlanApi-BsHhgVFV.mjs → fablePlanApi-DuMg43Hu.mjs} +5 -5
- package/dist/fablePlanApi-DuMg43Hu.mjs.map +1 -0
- package/dist/fablePlanApi.cjs +3 -3
- package/dist/fablePlanApi.d.mts +2 -2
- package/dist/fablePlanApi.mjs +1 -2
- package/dist/index.cjs +17 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +5 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +15 -5
- package/dist/index.mjs.map +1 -1
- package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
- package/dist/runs/background/cliRunnerEntry.cjs +26 -25
- package/dist/runs/background/cliRunnerEntry.cjs.map +1 -1
- package/dist/runs/background/cliRunnerEntry.mjs +14 -14
- package/dist/runs/background/cliRunnerEntry.mjs.map +1 -1
- package/dist/runtimeSubagentPolicy.cjs +3 -3
- package/dist/runtimeSubagentPolicy.d.mts +2 -2
- package/dist/runtimeSubagentPolicy.mjs +1 -2
- package/dist/runtimeSubagentTool.cjs +7 -2
- package/dist/runtimeSubagentTool.d.mts +1 -1
- package/dist/runtimeSubagentTool.mjs +1 -2
- package/dist/{subagentPolicy-ALJam4GN.d.mts → subagentPolicy-BE-OZoa-.d.mts} +6 -6
- package/dist/subagentPolicy-BE-OZoa-.d.mts.map +1 -0
- package/dist/{subagentPolicy-DQRyKDH-.cjs → subagentPolicy-DIpaKHO8.cjs} +8 -8
- package/dist/subagentPolicy-DIpaKHO8.cjs.map +1 -0
- package/dist/{subagentPolicy-DxjsKeyj.mjs → subagentPolicy-LfcXuqO5.mjs} +5 -5
- package/dist/subagentPolicy-LfcXuqO5.mjs.map +1 -0
- package/dist/subagentPolicy.cjs +3 -3
- package/dist/subagentPolicy.d.mts +2 -2
- package/dist/subagentPolicy.mjs +1 -2
- package/dist/{subagentTool-Ca2zQXKw.cjs → subagentTool-BueNPGHo.cjs} +5 -16
- package/dist/subagentTool-BueNPGHo.cjs.map +1 -0
- package/dist/{subagentTool-BTssGLw8.d.mts → subagentTool-UdB3s6Mn.d.mts} +2 -11
- package/dist/subagentTool-UdB3s6Mn.d.mts.map +1 -0
- package/dist/{subagentTool-WOYrjxgT.mjs → subagentTool-a2oh2v5B.mjs} +5 -16
- package/dist/subagentTool-a2oh2v5B.mjs.map +1 -0
- package/dist/subagentTool.cjs +7 -2
- package/dist/subagentTool.d.mts +1 -1
- package/dist/subagentTool.mjs +1 -2
- package/dist/teamSnapshot.d.mts +1 -0
- package/dist/teamSnapshot.d.mts.map +1 -1
- package/dist/teamSnapshot.mjs +1 -2
- package/package.json +25 -24
- package/dist/agentDiscovery-Whwzc4dP.cjs.map +0 -1
- package/dist/agentDiscovery-ZQlFkKvB.mjs.map +0 -1
- package/dist/atomicJson-D0346bt5.cjs +0 -178
- package/dist/atomicJson-D0346bt5.cjs.map +0 -1
- package/dist/atomicJson-D2t0CDh9.mjs +0 -137
- package/dist/atomicJson-D2t0CDh9.mjs.map +0 -1
- package/dist/capabilityCeiling-C-Y7H8oC.cjs.map +0 -1
- package/dist/capabilityCeiling-CF7kAS18.mjs.map +0 -1
- package/dist/environment-CaCW3SgT.cjs.map +0 -1
- package/dist/environment-DrqhrxG_.mjs.map +0 -1
- package/dist/externalProcessIpc-C-15lJrB.mjs.map +0 -1
- package/dist/externalProcessIpc-ojE0pvw0.cjs.map +0 -1
- package/dist/fablePlanApi-BsHhgVFV.mjs.map +0 -1
- package/dist/fablePlanApi-wBu9bRXU.cjs.map +0 -1
- package/dist/subagentPolicy-ALJam4GN.d.mts.map +0 -1
- package/dist/subagentPolicy-DQRyKDH-.cjs.map +0 -1
- package/dist/subagentPolicy-DxjsKeyj.mjs.map +0 -1
- package/dist/subagentTool-BTssGLw8.d.mts.map +0 -1
- package/dist/subagentTool-Ca2zQXKw.cjs.map +0 -1
- package/dist/subagentTool-WOYrjxgT.mjs.map +0 -1
|
@@ -1 +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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"}
|
|
1
|
+
{"version":3,"file":"cliRunnerEntry.cjs","names":["path","scopeRunsDir","parseExternalParentMessage","EXTERNAL_IPC_CHANNEL","sendRunnerMessage","SUBAGENT_RUN_ID_ENV","adoptSessionScopeFromEnv","SUBAGENT_ROOT_SESSION_ENV","createPoTelemetry","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 { createPoTelemetry, type PoTelemetry } 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: PoTelemetry | 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 ...(config.sensitiveTask ? { promptWithheld: true } : {}),\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 = createPoTelemetry({\n serviceName: 'po-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('po_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(`[po-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('po_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 'po_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('po_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('po_team.child_failed', { outcome: 'failed' }, error);\n process.stderr.write(`[po-team cli runner] ${errorMessage(error)}\\n`);\n process.exitCode = 1;\n});\n"],"mappings":"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"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { F as SUBAGENT_ROOT_SESSION_ENV, I as SUBAGENT_RUN_ID_ENV } from "../../environment-
|
|
2
|
-
import { n as writePrivateAtomicJson, t as writeAtomicJson } from "../../atomicJson-
|
|
3
|
-
import { c as cleanupClaudeFableLaunch, d as adoptSessionScopeFromEnv, i as parseExternalParentMessage, l as parseClaudeFableOutput, m as scopeRunsDir, o as sendRunnerMessage, s as CLAUDE_FABLE_PROFILE, t as EXTERNAL_IPC_CHANNEL } from "../../externalProcessIpc-C-15lJrB.mjs";
|
|
4
|
-
import * as fs from "node:fs";
|
|
1
|
+
import { F as SUBAGENT_ROOT_SESSION_ENV, I as SUBAGENT_RUN_ID_ENV } from "../../environment-BtvJI2S-.mjs";
|
|
2
|
+
import { c as sendRunnerMessage, d as parseClaudeFableOutput, g as scopeRunsDir, l as CLAUDE_FABLE_PROFILE, n as writePrivateAtomicJson, o as parseExternalParentMessage, p as adoptSessionScopeFromEnv, r as EXTERNAL_IPC_CHANNEL, t as writeAtomicJson, u as cleanupClaudeFableLaunch } from "../../atomicJson-VVM1iAPu.mjs";
|
|
5
3
|
import * as path from "node:path";
|
|
6
|
-
import
|
|
4
|
+
import * as fs from "node:fs";
|
|
5
|
+
import { createPoTelemetry } from "@agimon-ai/po-telemetry";
|
|
7
6
|
import { spawn } from "node:child_process";
|
|
8
7
|
//#region src/services/statusWriter/index.ts
|
|
9
8
|
/**
|
|
@@ -225,6 +224,7 @@ function projection(config, state, startedAt, fields = {}) {
|
|
|
225
224
|
runId: config.runId,
|
|
226
225
|
agent: config.agent,
|
|
227
226
|
task: config.sensitiveTask ? "" : config.task,
|
|
227
|
+
...config.sensitiveTask ? { promptWithheld: true } : {},
|
|
228
228
|
runtime: config.runtime,
|
|
229
229
|
state,
|
|
230
230
|
startedAt,
|
|
@@ -274,8 +274,8 @@ async function run() {
|
|
|
274
274
|
const scope = adoptSessionScopeFromEnv(STARTUP_ENVIRONMENT);
|
|
275
275
|
if (!scope) throw new Error(`${SUBAGENT_ROOT_SESSION_ENV} is required: a child cannot resolve its session scope without it.`);
|
|
276
276
|
const config = await receiveLaunchConfig(scope, runId);
|
|
277
|
-
childTelemetry =
|
|
278
|
-
serviceName: "
|
|
277
|
+
childTelemetry = createPoTelemetry({
|
|
278
|
+
serviceName: "po-team-cli-child",
|
|
279
279
|
packageName: "@agimon-ai/po-team",
|
|
280
280
|
env: config.env,
|
|
281
281
|
enableLogs: true,
|
|
@@ -294,7 +294,7 @@ async function run() {
|
|
|
294
294
|
startedAt,
|
|
295
295
|
lastUpdate: startedAt
|
|
296
296
|
});
|
|
297
|
-
await childTelemetry.recordEvent("
|
|
297
|
+
await childTelemetry.recordEvent("po_team.child_started", {
|
|
298
298
|
runtime: config.runtime,
|
|
299
299
|
"agent.name": config.agent,
|
|
300
300
|
outcome: "started"
|
|
@@ -332,7 +332,7 @@ async function run() {
|
|
|
332
332
|
try {
|
|
333
333
|
process.kill(-child.pid, signal);
|
|
334
334
|
} catch (error) {
|
|
335
|
-
process.stderr.write(`[
|
|
335
|
+
process.stderr.write(`[po-team cli runner] Could not signal vendor process: ${errorMessage(error)}\n`);
|
|
336
336
|
}
|
|
337
337
|
};
|
|
338
338
|
const onSigterm = () => stopVendor("SIGTERM");
|
|
@@ -378,7 +378,7 @@ async function run() {
|
|
|
378
378
|
});
|
|
379
379
|
statusWriter.close();
|
|
380
380
|
cleanupProfile(true);
|
|
381
|
-
finishTelemetry("
|
|
381
|
+
finishTelemetry("po_team.child_finished", {
|
|
382
382
|
runtime: config.runtime,
|
|
383
383
|
"agent.name": config.agent,
|
|
384
384
|
duration_ms: Date.now() - startedAt,
|
|
@@ -430,7 +430,7 @@ async function run() {
|
|
|
430
430
|
});
|
|
431
431
|
statusWriter.close();
|
|
432
432
|
cleanupProfile(true);
|
|
433
|
-
await finishTelemetry("
|
|
433
|
+
await finishTelemetry("po_team.child_failed", {
|
|
434
434
|
runtime: config.runtime,
|
|
435
435
|
"agent.name": config.agent,
|
|
436
436
|
duration_ms: Date.now() - startedAt,
|
|
@@ -507,7 +507,7 @@ async function run() {
|
|
|
507
507
|
});
|
|
508
508
|
statusWriter.close();
|
|
509
509
|
cleanupProfile(!success);
|
|
510
|
-
await finishTelemetry("
|
|
510
|
+
await finishTelemetry("po_team.child_finished", {
|
|
511
511
|
runtime: config.runtime,
|
|
512
512
|
"agent.name": config.agent,
|
|
513
513
|
duration_ms: Date.now() - startedAt,
|
|
@@ -527,8 +527,8 @@ run().catch(async (error) => {
|
|
|
527
527
|
error: errorMessage(error)
|
|
528
528
|
});
|
|
529
529
|
} catch {}
|
|
530
|
-
await finishTelemetry("
|
|
531
|
-
process.stderr.write(`[
|
|
530
|
+
await finishTelemetry("po_team.child_failed", { outcome: "failed" }, error);
|
|
531
|
+
process.stderr.write(`[po-team cli runner] ${errorMessage(error)}\n`);
|
|
532
532
|
process.exitCode = 1;
|
|
533
533
|
});
|
|
534
534
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cliRunnerEntry.mjs","names":[],"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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"}
|
|
1
|
+
{"version":3,"file":"cliRunnerEntry.mjs","names":[],"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 { createPoTelemetry, type PoTelemetry } 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: PoTelemetry | 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 ...(config.sensitiveTask ? { promptWithheld: true } : {}),\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 = createPoTelemetry({\n serviceName: 'po-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('po_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(`[po-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('po_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 'po_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('po_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('po_team.child_failed', { outcome: 'failed' }, error);\n process.stderr.write(`[po-team cli runner] ${errorMessage(error)}\\n`);\n process.exitCode = 1;\n});\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_subagentPolicy = require("./subagentPolicy-
|
|
3
|
-
exports.
|
|
2
|
+
const require_subagentPolicy = require("./subagentPolicy-DIpaKHO8.cjs");
|
|
3
|
+
exports.PO_SUBAGENT_POLICY_SERVICE = require_subagentPolicy.PO_SUBAGENT_POLICY_SERVICE;
|
|
4
4
|
exports.SubagentPolicySchema = require_subagentPolicy.SubagentPolicySchema;
|
|
5
|
-
exports.
|
|
5
|
+
exports.readPoSubagentPolicyService = require_subagentPolicy.readPoSubagentPolicyService;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as SubagentPolicySchema, i as SubagentPolicyHandle, n as
|
|
2
|
-
export {
|
|
1
|
+
import { a as SubagentPolicySchema, i as SubagentPolicyHandle, n as PoSubagentPolicyService, o as readPoSubagentPolicyService, r as SubagentPolicy, t as PO_SUBAGENT_POLICY_SERVICE } from "./subagentPolicy-BE-OZoa-.mjs";
|
|
2
|
+
export { PO_SUBAGENT_POLICY_SERVICE, PoSubagentPolicyService, SubagentPolicy, SubagentPolicyHandle, SubagentPolicySchema, readPoSubagentPolicyService };
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { DOOM_SUBAGENT_POLICY_SERVICE, SubagentPolicySchema, readDoomSubagentPolicyService };
|
|
1
|
+
export { t as PO_SUBAGENT_POLICY_SERVICE, n as SubagentPolicySchema, r as readPoSubagentPolicyService } from "./subagentPolicy-LfcXuqO5.mjs";
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_subagentTool = require("./subagentTool-
|
|
2
|
+
const require_subagentTool = require("./subagentTool-BueNPGHo.cjs");
|
|
3
3
|
let _agimon_ai_po_core_delegation = require("@agimon-ai/po-core/delegation");
|
|
4
|
-
exports
|
|
4
|
+
Object.defineProperty(exports, "InlineAgentSchema", {
|
|
5
|
+
enumerable: true,
|
|
6
|
+
get: function() {
|
|
7
|
+
return _agimon_ai_po_core_delegation.InlineAgentSchema;
|
|
8
|
+
}
|
|
9
|
+
});
|
|
5
10
|
exports.SUBAGENT_ACTIONS = require_subagentTool.SUBAGENT_ACTIONS;
|
|
6
11
|
exports.SUBAGENT_ACTION_FIELDS = require_subagentTool.SUBAGENT_ACTION_FIELDS;
|
|
7
12
|
exports.SubagentParams = require_subagentTool.SubagentParams;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as SubagentAction, c as SubagentToolSchema, d as subagentActionAcceptsField, i as SUBAGENT_ACTION_FIELDS, l as isSubagentAction, n as InlineAgentSchema, o as SubagentParams, r as SUBAGENT_ACTIONS, s as SubagentToolParams, t as InlineAgent, u as normalizeSubagentToolParams } from "./subagentTool-
|
|
1
|
+
import { a as SubagentAction, c as SubagentToolSchema, d as subagentActionAcceptsField, i as SUBAGENT_ACTION_FIELDS, l as isSubagentAction, n as InlineAgentSchema, o as SubagentParams, r as SUBAGENT_ACTIONS, s as SubagentToolParams, t as InlineAgent, u as normalizeSubagentToolParams } from "./subagentTool-UdB3s6Mn.mjs";
|
|
2
2
|
export { type InlineAgent, InlineAgentSchema, SUBAGENT_ACTIONS, SUBAGENT_ACTION_FIELDS, SubagentAction, SubagentParams, SubagentToolParams, SubagentToolSchema, isSubagentAction, normalizeSubagentToolParams, subagentActionAcceptsField };
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { InlineAgentSchema, SUBAGENT_ACTIONS, SUBAGENT_ACTION_FIELDS, SubagentParams, SubagentToolSchema, isSubagentAction, normalizeSubagentToolParams, subagentActionAcceptsField };
|
|
1
|
+
export { t as InlineAgentSchema, n as SUBAGENT_ACTIONS, r as SUBAGENT_ACTION_FIELDS, i as SubagentParams, a as SubagentToolSchema, o as isSubagentAction, s as normalizeSubagentToolParams, c as subagentActionAcceptsField } from "./subagentTool-a2oh2v5B.mjs";
|
|
@@ -2,7 +2,7 @@ import { Static, Type } from "typebox";
|
|
|
2
2
|
import { Context } from "@deepseek-ai/cordis";
|
|
3
3
|
//#region src/schemas/subagentPolicy.d.ts
|
|
4
4
|
/** Team-owned Cordis service for session-scoped subagent policy contributions. */
|
|
5
|
-
declare const
|
|
5
|
+
declare const PO_SUBAGENT_POLICY_SERVICE = "po/subagent-policy";
|
|
6
6
|
declare const SubagentPolicySchema: Type.TObject<{
|
|
7
7
|
owner: Type.TString;
|
|
8
8
|
allowedTools: Type.TOptional<Type.TArray<Type.TString>>;
|
|
@@ -18,16 +18,16 @@ interface SubagentPolicyHandle {
|
|
|
18
18
|
update(policy: SubagentPolicy): void;
|
|
19
19
|
dispose(): void;
|
|
20
20
|
}
|
|
21
|
-
interface
|
|
21
|
+
interface PoSubagentPolicyService {
|
|
22
22
|
readonly generation: string;
|
|
23
23
|
register(policy: SubagentPolicy): SubagentPolicyHandle;
|
|
24
24
|
}
|
|
25
25
|
declare module '@deepseek-ai/cordis' {
|
|
26
26
|
interface Context {
|
|
27
|
-
'
|
|
27
|
+
'po/subagent-policy': PoSubagentPolicyService;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
declare function
|
|
30
|
+
declare function readPoSubagentPolicyService(ctx: Context): PoSubagentPolicyService | undefined;
|
|
31
31
|
//#endregion
|
|
32
|
-
export { SubagentPolicySchema as a, SubagentPolicyHandle as i,
|
|
33
|
-
//# sourceMappingURL=subagentPolicy-
|
|
32
|
+
export { SubagentPolicySchema as a, SubagentPolicyHandle as i, PoSubagentPolicyService as n, readPoSubagentPolicyService as o, SubagentPolicy as r, PO_SUBAGENT_POLICY_SERVICE as t };
|
|
33
|
+
//# sourceMappingURL=subagentPolicy-BE-OZoa-.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagentPolicy-BE-OZoa-.d.mts","names":[],"sources":["../src/schemas/subagentPolicy.ts"],"mappings":";;;;cAIa;cAEA,sBAAoB,KAAA;;;;;;;;KAWrB,iBAAiB,cAAc;UAE1B;WACN;WACA;EACT,OAAO,QAAQ;EACf;;UAGe;WACN;EACT,SAAS,QAAQ,iBAAiB;;;YAIxB;IACR,sBAAsB;;;iBAIV,4BAA4B,KAAK,UAAU"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
let typebox = require("typebox");
|
|
2
2
|
//#region src/schemas/subagentPolicy.ts
|
|
3
3
|
/** Team-owned Cordis service for session-scoped subagent policy contributions. */
|
|
4
|
-
const
|
|
4
|
+
const PO_SUBAGENT_POLICY_SERVICE = "po/subagent-policy";
|
|
5
5
|
const SubagentPolicySchema = typebox.Type.Object({
|
|
6
6
|
owner: typebox.Type.String({ minLength: 1 }),
|
|
7
7
|
allowedTools: typebox.Type.Optional(typebox.Type.Array(typebox.Type.String({ minLength: 1 }))),
|
|
@@ -13,14 +13,14 @@ const SubagentPolicySchema = typebox.Type.Object({
|
|
|
13
13
|
}))),
|
|
14
14
|
denyExtensions: typebox.Type.Optional(typebox.Type.Boolean())
|
|
15
15
|
}, { additionalProperties: false });
|
|
16
|
-
function
|
|
17
|
-
return ctx.get(
|
|
16
|
+
function readPoSubagentPolicyService(ctx) {
|
|
17
|
+
return ctx.get(PO_SUBAGENT_POLICY_SERVICE);
|
|
18
18
|
}
|
|
19
19
|
//#endregion
|
|
20
|
-
Object.defineProperty(exports, "
|
|
20
|
+
Object.defineProperty(exports, "PO_SUBAGENT_POLICY_SERVICE", {
|
|
21
21
|
enumerable: true,
|
|
22
22
|
get: function() {
|
|
23
|
-
return
|
|
23
|
+
return PO_SUBAGENT_POLICY_SERVICE;
|
|
24
24
|
}
|
|
25
25
|
});
|
|
26
26
|
Object.defineProperty(exports, "SubagentPolicySchema", {
|
|
@@ -29,11 +29,11 @@ Object.defineProperty(exports, "SubagentPolicySchema", {
|
|
|
29
29
|
return SubagentPolicySchema;
|
|
30
30
|
}
|
|
31
31
|
});
|
|
32
|
-
Object.defineProperty(exports, "
|
|
32
|
+
Object.defineProperty(exports, "readPoSubagentPolicyService", {
|
|
33
33
|
enumerable: true,
|
|
34
34
|
get: function() {
|
|
35
|
-
return
|
|
35
|
+
return readPoSubagentPolicyService;
|
|
36
36
|
}
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
//# sourceMappingURL=subagentPolicy-
|
|
39
|
+
//# sourceMappingURL=subagentPolicy-DIpaKHO8.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagentPolicy-DIpaKHO8.cjs","names":["Type"],"sources":["../src/schemas/subagentPolicy.ts"],"sourcesContent":["import type { Context } from '@deepseek-ai/cordis';\nimport { type Static, Type } from 'typebox';\n\n/** Team-owned Cordis service for session-scoped subagent policy contributions. */\nexport const PO_SUBAGENT_POLICY_SERVICE = 'po/subagent-policy';\n\nexport const SubagentPolicySchema = Type.Object(\n {\n owner: Type.String({ minLength: 1 }),\n allowedTools: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),\n requiredTools: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),\n allowMcpTools: Type.Optional(Type.Boolean()),\n allowedExternalProfiles: Type.Optional(Type.Array(Type.String({ minLength: 1, maxLength: 128 }))),\n denyExtensions: Type.Optional(Type.Boolean()),\n },\n { additionalProperties: false },\n);\nexport type SubagentPolicy = Static<typeof SubagentPolicySchema>;\n\nexport interface SubagentPolicyHandle {\n readonly owner: string;\n readonly generation: string;\n update(policy: SubagentPolicy): void;\n dispose(): void;\n}\n\nexport interface PoSubagentPolicyService {\n readonly generation: string;\n register(policy: SubagentPolicy): SubagentPolicyHandle;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'po/subagent-policy': PoSubagentPolicyService;\n }\n}\n\nexport function readPoSubagentPolicyService(ctx: Context): PoSubagentPolicyService | undefined {\n return ctx.get(PO_SUBAGENT_POLICY_SERVICE) as PoSubagentPolicyService | undefined;\n}\n"],"mappings":";;;AAIA,MAAa,6BAA6B;AAE1C,MAAa,uBAAuBA,QAAAA,KAAK,OACvC;CACE,OAAOA,QAAAA,KAAK,OAAO,EAAE,WAAW,EAAE,CAAC;CACnC,cAAcA,QAAAA,KAAK,SAASA,QAAAA,KAAK,MAAMA,QAAAA,KAAK,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;CACrE,eAAeA,QAAAA,KAAK,SAASA,QAAAA,KAAK,MAAMA,QAAAA,KAAK,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;CACtE,eAAeA,QAAAA,KAAK,SAASA,QAAAA,KAAK,QAAQ,CAAC;CAC3C,yBAAyBA,QAAAA,KAAK,SAASA,QAAAA,KAAK,MAAMA,QAAAA,KAAK,OAAO;EAAE,WAAW;EAAG,WAAW;CAAI,CAAC,CAAC,CAAC;CAChG,gBAAgBA,QAAAA,KAAK,SAASA,QAAAA,KAAK,QAAQ,CAAC;AAC9C,GACA,EAAE,sBAAsB,MAAM,CAChC;AAqBA,SAAgB,4BAA4B,KAAmD;CAC7F,OAAO,IAAI,IAAI,0BAA0B;AAC3C"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
//#region src/schemas/subagentPolicy.ts
|
|
3
3
|
/** Team-owned Cordis service for session-scoped subagent policy contributions. */
|
|
4
|
-
const
|
|
4
|
+
const PO_SUBAGENT_POLICY_SERVICE = "po/subagent-policy";
|
|
5
5
|
const SubagentPolicySchema = Type.Object({
|
|
6
6
|
owner: Type.String({ minLength: 1 }),
|
|
7
7
|
allowedTools: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
|
|
@@ -13,10 +13,10 @@ const SubagentPolicySchema = Type.Object({
|
|
|
13
13
|
}))),
|
|
14
14
|
denyExtensions: Type.Optional(Type.Boolean())
|
|
15
15
|
}, { additionalProperties: false });
|
|
16
|
-
function
|
|
17
|
-
return ctx.get(
|
|
16
|
+
function readPoSubagentPolicyService(ctx) {
|
|
17
|
+
return ctx.get(PO_SUBAGENT_POLICY_SERVICE);
|
|
18
18
|
}
|
|
19
19
|
//#endregion
|
|
20
|
-
export { SubagentPolicySchema as n,
|
|
20
|
+
export { SubagentPolicySchema as n, readPoSubagentPolicyService as r, PO_SUBAGENT_POLICY_SERVICE as t };
|
|
21
21
|
|
|
22
|
-
//# sourceMappingURL=subagentPolicy-
|
|
22
|
+
//# sourceMappingURL=subagentPolicy-LfcXuqO5.mjs.map
|