@agimon-ai/doompi-runner 0.0.1-alpha.76 → 0.0.1-alpha.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/extensions/mcp.cjs +105 -0
  2. package/dist/extensions/mcp.cjs.map +1 -0
  3. package/dist/extensions/mcp.d.cts +5 -0
  4. package/dist/extensions/mcp.d.cts.map +1 -0
  5. package/dist/extensions/mcp.d.mts +5 -0
  6. package/dist/extensions/mcp.d.mts.map +1 -0
  7. package/dist/extensions/mcp.mjs +77 -0
  8. package/dist/extensions/mcp.mjs.map +1 -0
  9. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.cjs +13 -5
  10. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.cjs.map +1 -1
  11. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.mjs +13 -6
  12. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.mjs.map +1 -1
  13. package/dist/src/services/launcher/index.cjs +8 -3
  14. package/dist/src/services/launcher/index.cjs.map +1 -1
  15. package/dist/src/services/launcher/index.d.cts +3 -1
  16. package/dist/src/services/launcher/index.d.cts.map +1 -1
  17. package/dist/src/services/launcher/index.d.mts +3 -1
  18. package/dist/src/services/launcher/index.d.mts.map +1 -1
  19. package/dist/src/services/launcher/index.mjs +8 -3
  20. package/dist/src/services/launcher/index.mjs.map +1 -1
  21. package/dist/src/services/lifeline/index.cjs +0 -3
  22. package/dist/src/services/lifeline/index.cjs.map +1 -1
  23. package/dist/src/services/lifeline/index.d.cts.map +1 -1
  24. package/dist/src/services/lifeline/index.d.mts.map +1 -1
  25. package/dist/src/services/lifeline/index.mjs +0 -3
  26. package/dist/src/services/lifeline/index.mjs.map +1 -1
  27. package/dist/src/services/runnerDependencies/index.cjs +1 -1
  28. package/dist/src/services/runnerDependencies/index.cjs.map +1 -1
  29. package/dist/src/services/runnerDependencies/index.mjs +1 -1
  30. package/dist/src/services/runnerDependencies/index.mjs.map +1 -1
  31. package/dist/src/services/runnerServerRuntime/index.cjs +17 -19
  32. package/dist/src/services/runnerServerRuntime/index.cjs.map +1 -1
  33. package/dist/src/services/runnerServerRuntime/index.mjs +17 -19
  34. package/dist/src/services/runnerServerRuntime/index.mjs.map +1 -1
  35. package/dist/src/tui/runnerRuntime.cjs +1 -1
  36. package/dist/src/tui/runnerRuntime.cjs.map +1 -1
  37. package/dist/src/tui/runnerRuntime.mjs +1 -1
  38. package/dist/src/tui/runnerRuntime.mjs.map +1 -1
  39. package/package.json +28 -20
@@ -1 +1 @@
1
- {"version":3,"file":"runnerRuntime.cjs","names":["RunnerSettingsLoader","RUNNER_SETTINGS_FILE","createRunnerDependencies","createDoomTelemetry","reconcileActiveRunners","formatRunnerFooterContribution","RUNNER_STATUS_KEY","formatRunnerStatus","RUNNER_FINISHED_MESSAGE","getLogTtlMs","stopRunnerProcess","STOPPED_REASON","createRunnerCompactionRecovery","SESSION_START_EVENT","resolveRootSessionId","cleanupLegacyRunnerStore","readDoomReadinessCoordinator","createDoomReadinessCoordinator","LEADER_SOURCE","COMMAND_NAME","COMMAND_DESCRIPTION","parseRunnersCommand","ERR_STOP_USAGE","ERR_START_USAGE","ERR_REQUIRES_INTERACTIVE","openRunnerSpace","DOOM_UI_HUB_SERVICE","requireDoomUiHub","DOOM_BACKGROUND_WORK_SERVICE","readDoomBackgroundWorkService","BACKGROUND_WORK_PROVIDER","HISTORY_SWEEP_INTERVAL_MS"],"sources":["../../../src/tui/runnerRuntime.ts"],"sourcesContent":["import {\n type BackgroundProviderWorkItem,\n type BackgroundWorkProviderHandle,\n DOOM_BACKGROUND_WORK_SERVICE,\n readDoomBackgroundWorkService,\n} from '@agimon-ai/doompi-core/background-work';\nimport { resolveRootSessionId } from '@agimon-ai/doompi-core/child-process';\nimport type { DoomFooterContributionHandle } from '@agimon-ai/doompi-core/footer';\nimport {\n createDoomReadinessCoordinator,\n type DoomReadinessCoordinator,\n readDoomReadinessCoordinator,\n} from '@agimon-ai/doompi-core/readiness';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/ui-hub';\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport {\n BACKGROUND_WORK_PROVIDER,\n COMPLETED_STATE,\n ERR_REQUIRES_INTERACTIVE,\n ERR_START_USAGE,\n ERR_STOP_USAGE,\n HISTORY_SWEEP_INTERVAL_MS,\n LEADER_GROUP_ORDER,\n LEADER_SOURCE,\n RMUX_BACKEND,\n RUNNER_FINISHED_MESSAGE,\n RUNNER_FOOTER_ORDER,\n RUNNER_STATUS_KEY,\n RUNNER_STATUS_POLL_MS,\n SESSION_START_EVENT,\n STOPPED_REASON,\n} from '../constants/runnerRuntime';\nimport { COMMAND_DESCRIPTION, COMMAND_NAME } from '../constants/runners';\nimport { RUNNER_SETTINGS_FILE } from '../constants/runnerSettings';\nimport { createRunnerCompactionRecovery } from '../services/compaction';\nimport { summarizeLog } from '../services/logReader';\nimport { cleanupLegacyRunnerStore, reconcileActiveRunners, stopRunnerProcess } from '../services/reconcile';\nimport { getLogTtlMs } from '../services/runnerConfig';\nimport { setRunnerSettings } from '../services/runnerConfig';\nimport { createRunnerDependencies } from '../services/runnerDependencies';\nimport type { RunnerDependencies } from '../services/runnerDependencies/type';\nimport { parseRunnersCommand } from '../services/runnersCommand';\nimport { RunnerSettingsLoader } from '../services/runnerSettings';\nimport type { IBashRunService } from '../types/bashRunService';\nimport type { RunnerRecord } from '../types/runnerRegistry';\n/** After doom-task's `t` (65) and before the core help group (70). */\nimport { formatRunnerFooterContribution, formatRunnerStatus } from './format';\nimport type { RunnerRuntime } from './runnerRuntimeType';\nimport { openRunnerSpace } from './runnerSpace';\n\n/**\n * How often a live session revisits its own runner history. Retention only\n * bounds a session that ends; a session open all day has to sweep itself.\n */\n\n/**\n * Project-local extension config, read the way Pi documents it: one JSON file\n * per extension under the config directory, and only for a trusted project.\n */\nfunction loadRunnerSettings(context: ExtensionContext): void {\n try {\n const trusted = context.isProjectTrusted?.() ?? false;\n const { settings, issues } = new RunnerSettingsLoader().load(context.cwd, trusted);\n setRunnerSettings(settings);\n // A rejected key is surfaced rather than dropped: silence reads as a\n // setting that simply does not work.\n for (const issue of issues) process.emitWarning(`${RUNNER_SETTINGS_FILE}: ${issue}`);\n } catch (error) {\n process.emitWarning(`Could not read ${RUNNER_SETTINGS_FILE}: ${String(error)}`);\n setRunnerSettings({});\n }\n}\n\n/**\n * doom-runner: replaces pi's `bash` tool with a supervised one and provides a\n * CLI for anything it leaves running.\n */\nexport function createRunnerRuntime(pi: ExtensionAPI): RunnerRuntime {\n let cordis: Context | undefined;\n let initialized = false;\n const environment = Object.freeze({ ...process.env });\n const container = createRunnerDependencies({ environment });\n let registry!: RunnerDependencies['runnerRegistry'];\n let launcher!: RunnerDependencies['launcher'];\n let rmuxBackend!: RunnerDependencies['rmuxBackend'];\n let logReader!: RunnerDependencies['logReader'];\n let ptyHost!: RunnerDependencies['ptyHost'];\n let bashRunService!: RunnerDependencies['bashRunService'];\n let paths!: RunnerDependencies['paths'];\n let processControl!: RunnerDependencies['processControl'];\n let lifeline!: RunnerDependencies['lifeline'];\n\n let active = true;\n let sessionGeneration = 0;\n let sessionId: string | undefined;\n let rootSessionId: string | undefined;\n let runners: RunnerRecord[] = [];\n let sessionContext: ExtensionContext | undefined;\n let footerContribution: DoomFooterContributionHandle | undefined;\n let telemetry: DoomTelemetry | undefined;\n let sessionReady = false;\n let disposed = false;\n let refreshInFlight: Promise<void> | undefined;\n let historySweepInFlight: Promise<void> | undefined;\n let historySweepTimer: ReturnType<typeof setImmediate> | undefined;\n let statusPoll: ReturnType<typeof setInterval> | undefined;\n let historySweepPoll: ReturnType<typeof setInterval> | undefined;\n let unsubscribeRegistry: (() => void) | undefined;\n let sessionInitialization: Promise<void> = Promise.resolve();\n let fallbackReadiness: DoomReadinessCoordinator | undefined;\n let refreshQueued = false;\n let queuedReconciliation = false;\n let lastRunnerCount: number | undefined;\n const notifiedRunnerIds = new Set<string>();\n const pendingPromotedRunnerIds = new Set<string>();\n const terminalRunners = new Map<string, RunnerRecord>();\n let backgroundWorkItems: BackgroundProviderWorkItem[] = [];\n let backgroundWorkProvider: BackgroundWorkProviderHandle | undefined;\n const pendingOperations = new Set<Promise<unknown>>();\n const trackOperation = <T>(operation: Promise<T>): Promise<T> => {\n pendingOperations.add(operation);\n void operation.then(\n () => pendingOperations.delete(operation),\n () => pendingOperations.delete(operation),\n );\n return operation;\n };\n const waitForSessionReadiness = async (): Promise<void> => {\n await sessionInitialization;\n if (!active || !sessionReady || !sessionId) {\n throw new Error('doom-runner requires an active Pi session');\n }\n };\n const trackedBashRunService: IBashRunService = {\n run: async (request) => {\n await waitForSessionReadiness();\n return trackOperation(bashRunService.run(request));\n },\n };\n const isCurrent = (generation: number, expectedSessionId = sessionId): boolean =>\n active && !disposed && generation === sessionGeneration && expectedSessionId === sessionId;\n const getTelemetry = (ctx: ExtensionContext): DoomTelemetry => {\n telemetry ??= createDoomTelemetry({\n serviceName: 'doom-runner',\n packageName: '@agimon-ai/doompi-runner',\n cwd: ctx.cwd,\n env: environment,\n enableLogs: true,\n enableTraces: true,\n });\n return telemetry;\n };\n const publishBackgroundWork = (): void => {\n const activeSessionId = sessionId;\n const representedIds = new Set([...runners.map((record) => record.id), ...terminalRunners.keys()]);\n const next = activeSessionId\n ? [\n ...runners\n .filter((record) => record.sessionId === activeSessionId && record.promoted)\n .map((record) => ({\n id: record.id,\n sessionId: record.sessionId,\n label: record.name,\n status: record.state,\n })),\n ...[...terminalRunners.values()]\n .filter((record) => record.sessionId === activeSessionId)\n .map((record) => ({\n id: record.id,\n sessionId: record.sessionId,\n label: record.name,\n status: record.state,\n })),\n ...[...pendingPromotedRunnerIds]\n .filter((id) => !representedIds.has(id))\n .map((id) => ({ id, sessionId: activeSessionId, status: 'running' })),\n ]\n : [];\n if (JSON.stringify(next) === JSON.stringify(backgroundWorkItems)) return;\n backgroundWorkItems = next;\n backgroundWorkProvider?.update();\n };\n /** Performs one bounded pass over active state and explicitly monitored runners. */\n const refreshNow = async (shouldReconcile: boolean): Promise<void> => {\n const activeSessionId = sessionId;\n const generation = sessionGeneration;\n if (!activeSessionId || !isCurrent(generation, activeSessionId)) return;\n\n const activeRecords = await registry.list();\n if (!isCurrent(generation, activeSessionId)) return;\n let visibleActive = activeRecords;\n if (shouldReconcile) {\n const reconciled = await reconcileActiveRunners({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n startup: false,\n active: activeRecords,\n });\n for (const error of reconciled.errors) process.emitWarning(error);\n if (reconciled.reclaimed.length > 0) {\n const reclaimedIds = new Set(reconciled.reclaimed);\n visibleActive = activeRecords.filter((record) => !reclaimedIds.has(record.id));\n }\n }\n if (!isCurrent(generation, activeSessionId)) return;\n\n runners = visibleActive.filter((record) => record.sessionId === activeSessionId);\n const rootRunners = rootSessionId\n ? visibleActive.filter((record) => (record.rootSessionId ?? record.sessionId) === rootSessionId)\n : [];\n const runnerCount = rootRunners.length;\n if (lastRunnerCount !== runnerCount) {\n lastRunnerCount = runnerCount;\n footerContribution?.update(formatRunnerFooterContribution(runnerCount));\n if (sessionContext?.hasUI) sessionContext.ui.setStatus(RUNNER_STATUS_KEY, formatRunnerStatus(runnerCount));\n }\n\n const pendingIds = [...pendingPromotedRunnerIds];\n const monitored = await Promise.all(pendingIds.map((id) => registry.get(id, activeSessionId)));\n if (!isCurrent(generation, activeSessionId)) return;\n for (const [index, record] of monitored.entries()) {\n const id = pendingIds[index];\n if (!id) continue;\n if (!record || record.sessionId !== activeSessionId) {\n pendingPromotedRunnerIds.delete(id);\n terminalRunners.delete(id);\n runners = runners.filter((candidate) => candidate.id !== id);\n continue;\n }\n if (record.state === COMPLETED_STATE) {\n runners = runners.filter((candidate) => candidate.id !== record.id);\n terminalRunners.set(record.id, record);\n }\n }\n publishBackgroundWork();\n for (const record of monitored) {\n if (!record || record.sessionId !== activeSessionId || record.state !== COMPLETED_STATE) continue;\n if (notifiedRunnerIds.has(record.id)) continue;\n const outcome = record.exit?.reason ?? COMPLETED_STATE;\n const code =\n record.exit?.code === null || record.exit?.code === undefined ? '' : `, exit code ${record.exit.code}`;\n const content = [\n `Background runner ${record.name} exited: ${outcome}${code}.`,\n `Runner ID: ${record.id}`,\n `Log: ${record.logPath}`,\n `Inspect: doom-runner logs ${record.id}`,\n ].join('\\n');\n pi.sendMessage(\n { customType: RUNNER_FINISHED_MESSAGE, content, display: true },\n { triggerTurn: true, deliverAs: 'steer' },\n );\n notifiedRunnerIds.add(record.id);\n pendingPromotedRunnerIds.delete(record.id);\n terminalRunners.delete(record.id);\n publishBackgroundWork();\n if (sessionContext) {\n void trackOperation(\n getTelemetry(sessionContext).recordEvent('doom_runner.process_finished', {\n outcome: 'completed',\n 'runner.exit_code': record.exit?.code ?? 0,\n 'runner.backend': record.backend,\n ...(Number.isFinite(Date.parse(record.startedAt))\n ? { duration_ms: Math.max(0, Date.now() - Date.parse(record.startedAt)) }\n : {}),\n }),\n );\n }\n }\n };\n\n /** Coalesces timer and event triggers without losing a requested reconciliation pass. */\n const refresh = (shouldReconcile = true): Promise<void> => {\n if (!sessionId || !sessionReady || disposed) return Promise.resolve();\n if (refreshInFlight) {\n refreshQueued = true;\n queuedReconciliation ||= shouldReconcile;\n return refreshInFlight;\n }\n\n const execution = (async () => {\n let reconcileNext = shouldReconcile;\n do {\n refreshQueued = false;\n queuedReconciliation = false;\n await refreshNow(reconcileNext);\n reconcileNext = queuedReconciliation;\n } while (refreshQueued && !disposed);\n })().finally(() => {\n if (refreshInFlight === execution) refreshInFlight = undefined;\n });\n refreshInFlight = execution;\n return execution;\n };\n\n const reportRefreshError = (error: unknown): void => {\n if (disposed) return;\n if (sessionContext) {\n void trackOperation(getTelemetry(sessionContext).recordError('doom_runner.refresh_failed', error));\n }\n process.emitWarning(`Could not refresh doom-runner: ${String(error)}`);\n };\n const scheduleRefresh = (shouldReconcile: boolean): void => {\n void refresh(shouldReconcile).catch(reportRefreshError);\n };\n const scheduleHistorySweep = (): void => {\n if (historySweepTimer || historySweepInFlight || disposed) return;\n historySweepTimer = setImmediate(() => {\n historySweepTimer = undefined;\n if (disposed) return;\n const execution = (async () => {\n const sweep = paths.sweepHistoryAsync\n ? await paths.sweepHistoryAsync(getLogTtlMs())\n : paths.sweepHistory(getLogTtlMs());\n for (const error of sweep.errors) process.emitWarning(error);\n })()\n .catch((error) => process.emitWarning(`Could not sweep doom-runner history: ${String(error)}`))\n .finally(() => {\n if (historySweepInFlight === execution) historySweepInFlight = undefined;\n });\n historySweepInFlight = execution;\n });\n historySweepTimer.unref?.();\n };\n\n const runCleanup = async (label: string, cleanup: () => void | Promise<void>): Promise<void> => {\n try {\n await cleanup();\n } catch (error) {\n process.emitWarning(`Doom-runner cleanup could not ${label}: ${String(error)}`);\n }\n };\n\n const shutdownRuntime = async (): Promise<void> => {\n if (disposed) return;\n active = false;\n disposed = true;\n sessionGeneration += 1;\n sessionReady = false;\n if (statusPoll) clearInterval(statusPoll);\n statusPoll = undefined;\n if (historySweepPoll) clearInterval(historySweepPoll);\n historySweepPoll = undefined;\n if (historySweepTimer) clearImmediate(historySweepTimer);\n historySweepTimer = undefined;\n const unsubscribe = unsubscribeRegistry;\n unsubscribeRegistry = undefined;\n if (unsubscribe) await runCleanup('unsubscribe from the runner registry', unsubscribe);\n\n const ownedReadiness = fallbackReadiness;\n fallbackReadiness = undefined;\n if (ownedReadiness) await runCleanup('cancel standalone readiness work', () => ownedReadiness.dispose());\n await Promise.allSettled(pendingOperations);\n const activeRefresh = refreshInFlight;\n if (activeRefresh) await runCleanup('settle the runner refresh', () => activeRefresh);\n const activeHistorySweep = historySweepInFlight;\n if (activeHistorySweep) await runCleanup('settle runner history cleanup', () => activeHistorySweep);\n\n await runCleanup('dispose runner PTYs', () => ptyHost.disposeAll());\n\n let owned: RunnerRecord[] = [];\n if (sessionId) {\n try {\n owned = await registry.listBySession(sessionId);\n } catch (error) {\n process.emitWarning(`Could not list runners during doom-runner shutdown: ${String(error)}`);\n }\n }\n await Promise.all(\n owned.map(async (record) => {\n try {\n const stopped = await stopRunnerProcess(record, launcher, rmuxBackend);\n if (!stopped && processControl.isAlive(record.pid)) {\n process.emitWarning(`Could not stop runner ${record.id} during session shutdown`);\n return;\n }\n await registry.complete(\n record.id,\n {\n reason: STOPPED_REASON,\n code: null,\n signal: stopped ? 'SIGTERM' : null,\n stopReason: 'session ended',\n },\n record.sessionId,\n );\n } catch (error) {\n process.emitWarning(`Could not clean up runner ${record.id}: ${String(error)}`);\n }\n }),\n );\n\n const context = sessionContext;\n const ownedTelemetry = telemetry;\n telemetry = undefined;\n sessionContext = undefined;\n sessionId = undefined;\n rootSessionId = undefined;\n runners = [];\n notifiedRunnerIds.clear();\n pendingPromotedRunnerIds.clear();\n terminalRunners.clear();\n publishBackgroundWork();\n\n await Promise.all([\n runCleanup('dispose the runner lifeline', () => lifeline.dispose()),\n ...(context?.hasUI\n ? [runCleanup('clear the runner status', () => context.ui.setStatus(RUNNER_STATUS_KEY, undefined))]\n : []),\n ]);\n await runCleanup('close the runner registry', () => registry.close());\n if (ownedTelemetry) {\n await runCleanup('record the runner session finish', () =>\n ownedTelemetry.recordEvent('doom_runner.session_finished', { outcome: 'stopped' }),\n );\n await runCleanup('stop runner telemetry', () => ownedTelemetry.shutdown());\n }\n };\n\n /** Stops one of this session's runners; false when no such runner is active. */\n const stopSessionRunner = async (\n generation: number,\n activeSessionId: string,\n id: string,\n reason?: string,\n ): Promise<boolean> => {\n if (!isCurrent(generation, activeSessionId)) return false;\n const record = runners.find((candidate) => candidate.id === id);\n if (!record) return false;\n if (record.backend === RMUX_BACKEND && record.backendTarget) {\n await rmuxBackend.stop(record.backendTarget, record.pid);\n } else await launcher.stop(record.pid);\n if (!isCurrent(generation, activeSessionId)) return true;\n await registry.complete(\n record.id,\n { reason: STOPPED_REASON, code: null, signal: null, stopReason: reason },\n record.sessionId,\n );\n if (isCurrent(generation, activeSessionId)) await refresh();\n return true;\n };\n\n return {\n events: {\n session_compact: createRunnerCompactionRecovery(pi, {\n getSessionId: async () => {\n try {\n await waitForSessionReadiness();\n return sessionId;\n } catch {\n return undefined;\n }\n },\n listBySession: async (activeSessionId) => {\n try {\n await waitForSessionReadiness();\n } catch {\n return [];\n }\n return active ? registry.listBySession(activeSessionId) : [];\n },\n }),\n\n [SESSION_START_EVENT]: (_event, ctx) => {\n if (!active) return;\n unsubscribeRegistry?.();\n unsubscribeRegistry = undefined;\n const context = ctx as ExtensionContext;\n loadRunnerSettings(context);\n const activeSessionId = context.sessionManager.getSessionId();\n const previousSessionId = sessionId;\n const previousContext = sessionContext;\n const generation = ++sessionGeneration;\n sessionId = activeSessionId;\n rootSessionId = resolveRootSessionId(activeSessionId, environment);\n sessionContext = context;\n sessionReady = false;\n lastRunnerCount = undefined;\n runners = [];\n notifiedRunnerIds.clear();\n pendingPromotedRunnerIds.clear();\n terminalRunners.clear();\n publishBackgroundWork();\n\n const initializeSession = async (signal: AbortSignal): Promise<readonly string[]> => {\n const stillCurrent = (): boolean => !signal.aborted && isCurrent(generation, activeSessionId);\n if (!stillCurrent()) return [];\n if (previousSessionId && previousSessionId !== activeSessionId) {\n await runCleanup('dispose the previous session PTYs', () => ptyHost.disposeAll());\n await runCleanup('dispose the previous session lifeline', () => lifeline.dispose());\n if (previousContext?.hasUI) {\n await runCleanup('clear the previous session status', () =>\n previousContext.ui.setStatus(RUNNER_STATUS_KEY, undefined),\n );\n }\n const previousTelemetry = telemetry;\n telemetry = undefined;\n if (previousTelemetry) {\n await runCleanup('stop the previous session telemetry', () => previousTelemetry.shutdown());\n }\n if (!stillCurrent()) return [];\n }\n\n const activeTelemetry = getTelemetry(context);\n await activeTelemetry.recordEvent('doom_runner.session_started', { outcome: 'started' });\n if (!stillCurrent()) return [];\n paths.setSessionId(activeSessionId);\n unsubscribeRegistry = registry.subscribe(() => {\n if (isCurrent(generation, activeSessionId)) scheduleRefresh(false);\n }, activeSessionId);\n // Awaited before anything can launch, so every runner this session starts\n // finds a lifeline it can connect to rather than a socket that is not\n // listening yet, which would read as an owner that is already gone.\n await lifeline.arm(activeSessionId);\n if (!stillCurrent()) return [];\n\n const retained = await registry.listAll(activeSessionId);\n if (!stillCurrent()) return [];\n for (const record of retained) {\n if (record.state === COMPLETED_STATE) notifiedRunnerIds.add(record.id);\n else if (record.promoted) pendingPromotedRunnerIds.add(record.id);\n }\n const legacy = await cleanupLegacyRunnerStore({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n paths,\n });\n if (!stillCurrent()) return [];\n const reconciled = await reconcileActiveRunners({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n startup: true,\n });\n if (!stillCurrent()) return [];\n sessionReady = true;\n await refresh(false);\n if (!stillCurrent()) return [];\n scheduleHistorySweep();\n const errors = [...legacy.errors, ...reconciled.errors];\n const reclaimedCount = legacy.reclaimed.length + reconciled.reclaimed.length;\n if (reclaimedCount > 0 && context.hasUI) {\n context.ui.notify(`Reclaimed ${reclaimedCount} stale runner record(s)`, 'warning');\n }\n await activeTelemetry.recordEvent('doom_runner.reconciled', {\n 'runner.reclaimed_count': reclaimedCount,\n 'runner.error_count': errors.length,\n outcome: errors.length === 0 ? 'completed' : 'degraded',\n });\n return errors;\n };\n\n const previousInitialization = sessionInitialization.catch(() => undefined);\n const startReadiness = async (): Promise<void> => {\n await previousInitialization;\n if (!isCurrent(generation, activeSessionId)) return;\n const coordinator =\n (cordis ? readDoomReadinessCoordinator(cordis) : undefined) ??\n (fallbackReadiness ??= createDoomReadinessCoordinator({\n notify: (notification) => {\n process.emitWarning(\n `${notification.packageId} initialization ${notification.state}: ${notification.error?.message ?? notification.diagnostics.join('; ')}`,\n );\n },\n }));\n const handle = coordinator.start(LEADER_SOURCE, `${activeSessionId}:${generation}`, async (signal) => ({\n value: undefined,\n diagnostics: await initializeSession(signal),\n }));\n await handle.wait();\n };\n const operation = startReadiness();\n sessionInitialization = operation;\n // The coordinator reports a failed generation once; this branch only marks\n // the detached waiter handled so Pi is not held open by the notification path.\n void trackOperation(operation).catch(() => undefined);\n },\n },\n command: [\n COMMAND_NAME,\n {\n description: COMMAND_DESCRIPTION,\n handler: async (args, ctx) => {\n if (!active) return;\n const generation = sessionGeneration;\n const activeSessionId = sessionId;\n if (!activeSessionId) return;\n const request = parseRunnersCommand(args);\n // The stop verb is how a client without an overlay (the web cockpit)\n // controls a runner, so it must not need the interactive UI.\n if (request.kind === 'stop') {\n if (!request.id) {\n ctx.ui.notify(ERR_STOP_USAGE, 'error');\n return;\n }\n await waitForSessionReadiness();\n await refresh();\n if (!isCurrent(generation, activeSessionId)) return;\n const stopped = await stopSessionRunner(generation, activeSessionId, request.id, request.reason);\n if (!isCurrent(generation, activeSessionId)) return;\n if (stopped) ctx.ui.notify(`Stopped runner ${request.id}.`, 'info');\n else ctx.ui.notify(`No active runner ${request.id} in this session.`, 'error');\n return;\n }\n // Starting headlessly is how a client without the bash tool (the web\n // cockpit) puts a command up. It is background by construction: a\n // foreground wait has nobody here to wait for it.\n if (request.kind === 'start') {\n if (!request.command) {\n ctx.ui.notify(ERR_START_USAGE, 'error');\n return;\n }\n await waitForSessionReadiness();\n if (!isCurrent(generation, activeSessionId)) return;\n const started = await trackedBashRunService.run({\n command: request.command,\n sessionId: activeSessionId,\n background: true,\n ...(request.cwd ? { cwd: request.cwd } : {}),\n ...(request.name ? { name: request.name } : {}),\n ...(request.interactive ? { interactive: true } : {}),\n });\n if (!isCurrent(generation, activeSessionId)) return;\n await refresh();\n if (started.kind === 'failed') ctx.ui.notify(`Could not start a runner: ${started.error}`, 'error');\n else ctx.ui.notify(`Started runner ${started.name}.`, 'info');\n return;\n }\n if (!ctx.hasUI) {\n ctx.ui.notify(ERR_REQUIRES_INTERACTIVE, 'error');\n return;\n }\n await waitForSessionReadiness();\n await refresh();\n if (!activeSessionId || !isCurrent(generation, activeSessionId)) return;\n await openRunnerSpace(ctx, {\n getRunners: () => (isCurrent(generation, activeSessionId) ? runners : []),\n getPtyRun: (name) =>\n isCurrent(generation, activeSessionId) ? (rmuxBackend.get(name) ?? ptyHost.get(name)) : undefined,\n readLog: (logPath) =>\n isCurrent(generation, activeSessionId) ? logReader.read(logPath, { lines: 1_000 }).text : '',\n stopRunner: async (id, reason) => {\n await stopSessionRunner(generation, activeSessionId, id, reason);\n },\n });\n },\n },\n ],\n bashTool: {\n bashRunService: trackedBashRunService,\n getSessionId: async () => {\n await waitForSessionReadiness();\n if (!sessionId) throw new Error('doom-runner requires an active Pi session');\n return sessionId;\n },\n onRunnerStarted: (id) => {\n if (!active || !sessionReady) return;\n pendingPromotedRunnerIds.add(id);\n publishBackgroundWork();\n scheduleRefresh(false);\n },\n summarizeLog,\n },\n plugin(context) {\n cordis = context;\n context.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n const contribution = requireDoomUiHub(uiContext).registerFooter({\n source: LEADER_SOURCE,\n id: 'runner-count',\n order: RUNNER_FOOTER_ORDER,\n });\n footerContribution = contribution;\n return () => {\n contribution.dispose();\n if (footerContribution === contribution) footerContribution = undefined;\n };\n });\n context.inject([DOOM_BACKGROUND_WORK_SERVICE], (serviceContext) => {\n const service = readDoomBackgroundWorkService(serviceContext);\n if (!service) return undefined;\n const registration = service.register({\n provider: BACKGROUND_WORK_PROVIDER,\n listActiveWork: () => backgroundWorkItems,\n });\n backgroundWorkProvider = registration;\n return () => {\n registration.dispose();\n if (backgroundWorkProvider === registration) backgroundWorkProvider = undefined;\n };\n });\n context.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n const contribution = requireDoomUiHub(uiContext).registerLeader({\n source: LEADER_SOURCE,\n bindings: [\n {\n id: 'runners.open',\n path: [\n { key: 'r', label: 'runners', detail: 'background processes', order: LEADER_GROUP_ORDER },\n { key: 'l', label: 'list', detail: 'runners in this session' },\n ],\n command: { name: COMMAND_NAME },\n },\n ],\n });\n return () => contribution.dispose();\n });\n },\n start() {\n registry = container.runnerRegistry;\n launcher = container.launcher;\n rmuxBackend = container.rmuxBackend;\n logReader = container.logReader;\n ptyHost = container.ptyHost;\n bashRunService = container.bashRunService;\n paths = container.paths;\n processControl = container.processControl;\n lifeline = container.lifeline;\n initialized = true;\n statusPoll = setInterval(() => scheduleRefresh(true), RUNNER_STATUS_POLL_MS);\n statusPoll.unref?.();\n historySweepPoll = setInterval(() => scheduleHistorySweep(), HISTORY_SWEEP_INTERVAL_MS);\n historySweepPoll.unref?.();\n },\n async stop() {\n if (initialized) await shutdownRuntime();\n else registry?.close();\n cordis = undefined;\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"runnerRuntime.cjs","names":["RunnerSettingsLoader","RUNNER_SETTINGS_FILE","createRunnerDependencies","createDoomTelemetry","reconcileActiveRunners","formatRunnerFooterContribution","RUNNER_STATUS_KEY","formatRunnerStatus","RUNNER_FINISHED_MESSAGE","getLogTtlMs","stopRunnerProcess","STOPPED_REASON","createRunnerCompactionRecovery","SESSION_START_EVENT","resolveRootSessionId","cleanupLegacyRunnerStore","readDoomReadinessCoordinator","createDoomReadinessCoordinator","LEADER_SOURCE","COMMAND_NAME","COMMAND_DESCRIPTION","parseRunnersCommand","ERR_STOP_USAGE","ERR_START_USAGE","ERR_REQUIRES_INTERACTIVE","openRunnerSpace","DOOM_UI_HUB_SERVICE","requireDoomUiHub","DOOM_BACKGROUND_WORK_SERVICE","readDoomBackgroundWorkService","BACKGROUND_WORK_PROVIDER","HISTORY_SWEEP_INTERVAL_MS"],"sources":["../../../src/tui/runnerRuntime.ts"],"sourcesContent":["import {\n type BackgroundProviderWorkItem,\n type BackgroundWorkProviderHandle,\n DOOM_BACKGROUND_WORK_SERVICE,\n readDoomBackgroundWorkService,\n} from '@agimon-ai/doompi-core/background-work';\nimport { resolveRootSessionId } from '@agimon-ai/doompi-core/child-process';\nimport type { DoomFooterContributionHandle } from '@agimon-ai/doompi-core/footer';\nimport {\n createDoomReadinessCoordinator,\n type DoomReadinessCoordinator,\n readDoomReadinessCoordinator,\n} from '@agimon-ai/doompi-core/readiness';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/ui-hub';\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport {\n BACKGROUND_WORK_PROVIDER,\n COMPLETED_STATE,\n ERR_REQUIRES_INTERACTIVE,\n ERR_START_USAGE,\n ERR_STOP_USAGE,\n HISTORY_SWEEP_INTERVAL_MS,\n LEADER_GROUP_ORDER,\n LEADER_SOURCE,\n RMUX_BACKEND,\n RUNNER_FINISHED_MESSAGE,\n RUNNER_FOOTER_ORDER,\n RUNNER_STATUS_KEY,\n RUNNER_STATUS_POLL_MS,\n SESSION_START_EVENT,\n STOPPED_REASON,\n} from '../constants/runnerRuntime';\nimport { COMMAND_DESCRIPTION, COMMAND_NAME } from '../constants/runners';\nimport { RUNNER_SETTINGS_FILE } from '../constants/runnerSettings';\nimport { createRunnerCompactionRecovery } from '../services/compaction';\nimport { summarizeLog } from '../services/logReader';\nimport { cleanupLegacyRunnerStore, reconcileActiveRunners, stopRunnerProcess } from '../services/reconcile';\nimport { getLogTtlMs } from '../services/runnerConfig';\nimport { setRunnerSettings } from '../services/runnerConfig';\nimport { createRunnerDependencies } from '../services/runnerDependencies';\nimport type { RunnerDependencies } from '../services/runnerDependencies/type';\nimport { parseRunnersCommand } from '../services/runnersCommand';\nimport { RunnerSettingsLoader } from '../services/runnerSettings';\nimport type { IBashRunService } from '../types/bashRunService';\nimport type { RunnerRecord } from '../types/runnerRegistry';\n/** After doom-task's `t` (65) and before the core help group (70). */\nimport { formatRunnerFooterContribution, formatRunnerStatus } from './format';\nimport type { RunnerRuntime } from './runnerRuntimeType';\nimport { openRunnerSpace } from './runnerSpace';\n\n/**\n * How often a live session revisits its own runner history. Retention only\n * bounds a session that ends; a session open all day has to sweep itself.\n */\n\n/**\n * Project-local extension config, read the way Pi documents it: one JSON file\n * per extension under the config directory, and only for a trusted project.\n */\nfunction loadRunnerSettings(context: ExtensionContext): void {\n try {\n const trusted = context.isProjectTrusted?.() ?? false;\n const { settings, issues } = new RunnerSettingsLoader().load(context.cwd, trusted);\n setRunnerSettings(settings);\n // A rejected key is surfaced rather than dropped: silence reads as a\n // setting that simply does not work.\n for (const issue of issues) process.emitWarning(`${RUNNER_SETTINGS_FILE}: ${issue}`);\n } catch (error) {\n process.emitWarning(`Could not read ${RUNNER_SETTINGS_FILE}: ${String(error)}`);\n setRunnerSettings({});\n }\n}\n\n/**\n * doom-runner: replaces pi's `bash` tool with a supervised one and provides a\n * CLI for anything it leaves running.\n */\nexport function createRunnerRuntime(pi: ExtensionAPI): RunnerRuntime {\n let cordis: Context | undefined;\n let initialized = false;\n const environment = Object.freeze({ ...process.env });\n const container = createRunnerDependencies({ environment });\n let registry!: RunnerDependencies['runnerRegistry'];\n let launcher!: RunnerDependencies['launcher'];\n let rmuxBackend!: RunnerDependencies['rmuxBackend'];\n let logReader!: RunnerDependencies['logReader'];\n let ptyHost!: RunnerDependencies['ptyHost'];\n let bashRunService!: RunnerDependencies['bashRunService'];\n let paths!: RunnerDependencies['paths'];\n let processControl!: RunnerDependencies['processControl'];\n let lifeline!: RunnerDependencies['lifeline'];\n\n let active = true;\n let sessionGeneration = 0;\n let sessionId: string | undefined;\n let rootSessionId: string | undefined;\n let runners: RunnerRecord[] = [];\n let sessionContext: ExtensionContext | undefined;\n let footerContribution: DoomFooterContributionHandle | undefined;\n let telemetry: DoomTelemetry | undefined;\n let sessionReady = false;\n let disposed = false;\n let refreshInFlight: Promise<void> | undefined;\n let historySweepInFlight: Promise<void> | undefined;\n let historySweepTimer: ReturnType<typeof setImmediate> | undefined;\n let statusPoll: ReturnType<typeof setInterval> | undefined;\n let historySweepPoll: ReturnType<typeof setInterval> | undefined;\n let unsubscribeRegistry: (() => void) | undefined;\n let sessionInitialization: Promise<void> = Promise.resolve();\n let fallbackReadiness: DoomReadinessCoordinator | undefined;\n let refreshQueued = false;\n let queuedReconciliation = false;\n let lastRunnerCount: number | undefined;\n const notifiedRunnerIds = new Set<string>();\n const pendingPromotedRunnerIds = new Set<string>();\n const terminalRunners = new Map<string, RunnerRecord>();\n let backgroundWorkItems: BackgroundProviderWorkItem[] = [];\n let backgroundWorkProvider: BackgroundWorkProviderHandle | undefined;\n const pendingOperations = new Set<Promise<unknown>>();\n const trackOperation = <T>(operation: Promise<T>): Promise<T> => {\n pendingOperations.add(operation);\n void operation.then(\n () => pendingOperations.delete(operation),\n () => pendingOperations.delete(operation),\n );\n return operation;\n };\n const waitForSessionReadiness = async (): Promise<void> => {\n await sessionInitialization;\n if (!active || !sessionReady || !sessionId) {\n throw new Error('doom-runner requires an active Pi session');\n }\n };\n const trackedBashRunService: IBashRunService = {\n run: async (request) => {\n await waitForSessionReadiness();\n return trackOperation(bashRunService.run(request));\n },\n };\n const isCurrent = (generation: number, expectedSessionId = sessionId): boolean =>\n active && !disposed && generation === sessionGeneration && expectedSessionId === sessionId;\n const getTelemetry = (ctx: ExtensionContext): DoomTelemetry => {\n telemetry ??= createDoomTelemetry({\n serviceName: 'doom-runner',\n packageName: '@agimon-ai/doompi-runner',\n cwd: ctx.cwd,\n env: environment,\n enableLogs: true,\n enableTraces: true,\n });\n return telemetry;\n };\n const publishBackgroundWork = (): void => {\n const activeSessionId = sessionId;\n const representedIds = new Set([\n ...runners.filter((record) => record.promoted).map((record) => record.id),\n ...terminalRunners.keys(),\n ]);\n const next = activeSessionId\n ? [\n ...runners\n .filter((record) => record.sessionId === activeSessionId && record.promoted)\n .map((record) => ({\n id: record.id,\n sessionId: record.sessionId,\n label: record.name,\n status: record.state,\n })),\n ...[...terminalRunners.values()]\n .filter((record) => record.sessionId === activeSessionId)\n .map((record) => ({\n id: record.id,\n sessionId: record.sessionId,\n label: record.name,\n status: record.state,\n })),\n ...[...pendingPromotedRunnerIds]\n .filter((id) => !representedIds.has(id))\n .map((id) => ({ id, sessionId: activeSessionId, status: 'running' })),\n ]\n : [];\n if (JSON.stringify(next) === JSON.stringify(backgroundWorkItems)) return;\n backgroundWorkItems = next;\n backgroundWorkProvider?.update();\n };\n /** Performs one bounded pass over active state and explicitly monitored runners. */\n const refreshNow = async (shouldReconcile: boolean): Promise<void> => {\n const activeSessionId = sessionId;\n const generation = sessionGeneration;\n if (!activeSessionId || !isCurrent(generation, activeSessionId)) return;\n\n const activeRecords = await registry.list();\n if (!isCurrent(generation, activeSessionId)) return;\n let visibleActive = activeRecords;\n if (shouldReconcile) {\n const reconciled = await reconcileActiveRunners({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n startup: false,\n active: activeRecords,\n });\n for (const error of reconciled.errors) process.emitWarning(error);\n if (reconciled.reclaimed.length > 0) {\n const reclaimedIds = new Set(reconciled.reclaimed);\n visibleActive = activeRecords.filter((record) => !reclaimedIds.has(record.id));\n }\n }\n if (!isCurrent(generation, activeSessionId)) return;\n\n runners = visibleActive.filter((record) => record.sessionId === activeSessionId);\n const rootRunners = rootSessionId\n ? visibleActive.filter((record) => (record.rootSessionId ?? record.sessionId) === rootSessionId)\n : [];\n const runnerCount = rootRunners.length;\n if (lastRunnerCount !== runnerCount) {\n lastRunnerCount = runnerCount;\n footerContribution?.update(formatRunnerFooterContribution(runnerCount));\n if (sessionContext?.hasUI) sessionContext.ui.setStatus(RUNNER_STATUS_KEY, formatRunnerStatus(runnerCount));\n }\n\n const pendingIds = [...pendingPromotedRunnerIds];\n const monitored = await Promise.all(pendingIds.map((id) => registry.get(id, activeSessionId)));\n if (!isCurrent(generation, activeSessionId)) return;\n for (const [index, record] of monitored.entries()) {\n const id = pendingIds[index];\n if (!id) continue;\n if (!record || record.sessionId !== activeSessionId) {\n pendingPromotedRunnerIds.delete(id);\n terminalRunners.delete(id);\n runners = runners.filter((candidate) => candidate.id !== id);\n continue;\n }\n if (record.state === COMPLETED_STATE) {\n runners = runners.filter((candidate) => candidate.id !== record.id);\n terminalRunners.set(record.id, record);\n }\n }\n publishBackgroundWork();\n for (const record of monitored) {\n if (!record || record.sessionId !== activeSessionId || record.state !== COMPLETED_STATE) continue;\n if (notifiedRunnerIds.has(record.id)) continue;\n const outcome = record.exit?.reason ?? COMPLETED_STATE;\n const code =\n record.exit?.code === null || record.exit?.code === undefined ? '' : `, exit code ${record.exit.code}`;\n const content = [\n `Background runner ${record.name} exited: ${outcome}${code}.`,\n `Runner ID: ${record.id}`,\n `Log: ${record.logPath}`,\n `Inspect: doom-runner logs ${record.id}`,\n ].join('\\n');\n pi.sendMessage(\n { customType: RUNNER_FINISHED_MESSAGE, content, display: true },\n { triggerTurn: true, deliverAs: 'steer' },\n );\n notifiedRunnerIds.add(record.id);\n pendingPromotedRunnerIds.delete(record.id);\n terminalRunners.delete(record.id);\n publishBackgroundWork();\n if (sessionContext) {\n void trackOperation(\n getTelemetry(sessionContext).recordEvent('doom_runner.process_finished', {\n outcome: 'completed',\n 'runner.exit_code': record.exit?.code ?? 0,\n 'runner.backend': record.backend,\n ...(Number.isFinite(Date.parse(record.startedAt))\n ? { duration_ms: Math.max(0, Date.now() - Date.parse(record.startedAt)) }\n : {}),\n }),\n );\n }\n }\n };\n\n /** Coalesces timer and event triggers without losing a requested reconciliation pass. */\n const refresh = (shouldReconcile = true): Promise<void> => {\n if (!sessionId || !sessionReady || disposed) return Promise.resolve();\n if (refreshInFlight) {\n refreshQueued = true;\n queuedReconciliation ||= shouldReconcile;\n return refreshInFlight;\n }\n\n const execution = (async () => {\n let reconcileNext = shouldReconcile;\n do {\n refreshQueued = false;\n queuedReconciliation = false;\n await refreshNow(reconcileNext);\n reconcileNext = queuedReconciliation;\n } while (refreshQueued && !disposed);\n })().finally(() => {\n if (refreshInFlight === execution) refreshInFlight = undefined;\n });\n refreshInFlight = execution;\n return execution;\n };\n\n const reportRefreshError = (error: unknown): void => {\n if (disposed) return;\n if (sessionContext) {\n void trackOperation(getTelemetry(sessionContext).recordError('doom_runner.refresh_failed', error));\n }\n process.emitWarning(`Could not refresh doom-runner: ${String(error)}`);\n };\n const scheduleRefresh = (shouldReconcile: boolean): void => {\n void refresh(shouldReconcile).catch(reportRefreshError);\n };\n const scheduleHistorySweep = (): void => {\n if (historySweepTimer || historySweepInFlight || disposed) return;\n historySweepTimer = setImmediate(() => {\n historySweepTimer = undefined;\n if (disposed) return;\n const execution = (async () => {\n const sweep = paths.sweepHistoryAsync\n ? await paths.sweepHistoryAsync(getLogTtlMs())\n : paths.sweepHistory(getLogTtlMs());\n for (const error of sweep.errors) process.emitWarning(error);\n })()\n .catch((error) => process.emitWarning(`Could not sweep doom-runner history: ${String(error)}`))\n .finally(() => {\n if (historySweepInFlight === execution) historySweepInFlight = undefined;\n });\n historySweepInFlight = execution;\n });\n historySweepTimer.unref?.();\n };\n\n const runCleanup = async (label: string, cleanup: () => void | Promise<void>): Promise<void> => {\n try {\n await cleanup();\n } catch (error) {\n process.emitWarning(`Doom-runner cleanup could not ${label}: ${String(error)}`);\n }\n };\n\n const shutdownRuntime = async (): Promise<void> => {\n if (disposed) return;\n active = false;\n disposed = true;\n sessionGeneration += 1;\n sessionReady = false;\n if (statusPoll) clearInterval(statusPoll);\n statusPoll = undefined;\n if (historySweepPoll) clearInterval(historySweepPoll);\n historySweepPoll = undefined;\n if (historySweepTimer) clearImmediate(historySweepTimer);\n historySweepTimer = undefined;\n const unsubscribe = unsubscribeRegistry;\n unsubscribeRegistry = undefined;\n if (unsubscribe) await runCleanup('unsubscribe from the runner registry', unsubscribe);\n\n const ownedReadiness = fallbackReadiness;\n fallbackReadiness = undefined;\n if (ownedReadiness) await runCleanup('cancel standalone readiness work', () => ownedReadiness.dispose());\n await Promise.allSettled(pendingOperations);\n const activeRefresh = refreshInFlight;\n if (activeRefresh) await runCleanup('settle the runner refresh', () => activeRefresh);\n const activeHistorySweep = historySweepInFlight;\n if (activeHistorySweep) await runCleanup('settle runner history cleanup', () => activeHistorySweep);\n\n await runCleanup('dispose runner PTYs', () => ptyHost.disposeAll());\n\n let owned: RunnerRecord[] = [];\n if (sessionId) {\n try {\n owned = await registry.listBySession(sessionId);\n } catch (error) {\n process.emitWarning(`Could not list runners during doom-runner shutdown: ${String(error)}`);\n }\n }\n await Promise.all(\n owned.map(async (record) => {\n try {\n const stopped = await stopRunnerProcess(record, launcher, rmuxBackend);\n if (!stopped && processControl.isAlive(record.pid)) {\n process.emitWarning(`Could not stop runner ${record.id} during session shutdown`);\n return;\n }\n await registry.complete(\n record.id,\n {\n reason: STOPPED_REASON,\n code: null,\n signal: stopped ? 'SIGTERM' : null,\n stopReason: 'session ended',\n },\n record.sessionId,\n );\n } catch (error) {\n process.emitWarning(`Could not clean up runner ${record.id}: ${String(error)}`);\n }\n }),\n );\n\n const context = sessionContext;\n const ownedTelemetry = telemetry;\n telemetry = undefined;\n sessionContext = undefined;\n sessionId = undefined;\n rootSessionId = undefined;\n runners = [];\n notifiedRunnerIds.clear();\n pendingPromotedRunnerIds.clear();\n terminalRunners.clear();\n publishBackgroundWork();\n\n await Promise.all([\n runCleanup('dispose the runner lifeline', () => lifeline.dispose()),\n ...(context?.hasUI\n ? [runCleanup('clear the runner status', () => context.ui.setStatus(RUNNER_STATUS_KEY, undefined))]\n : []),\n ]);\n await runCleanup('close the runner registry', () => registry.close());\n if (ownedTelemetry) {\n await runCleanup('record the runner session finish', () =>\n ownedTelemetry.recordEvent('doom_runner.session_finished', { outcome: 'stopped' }),\n );\n await runCleanup('stop runner telemetry', () => ownedTelemetry.shutdown());\n }\n };\n\n /** Stops one of this session's runners; false when no such runner is active. */\n const stopSessionRunner = async (\n generation: number,\n activeSessionId: string,\n id: string,\n reason?: string,\n ): Promise<boolean> => {\n if (!isCurrent(generation, activeSessionId)) return false;\n const record = runners.find((candidate) => candidate.id === id);\n if (!record) return false;\n if (record.backend === RMUX_BACKEND && record.backendTarget) {\n await rmuxBackend.stop(record.backendTarget, record.pid);\n } else await launcher.stop(record.pid);\n if (!isCurrent(generation, activeSessionId)) return true;\n await registry.complete(\n record.id,\n { reason: STOPPED_REASON, code: null, signal: null, stopReason: reason },\n record.sessionId,\n );\n if (isCurrent(generation, activeSessionId)) await refresh();\n return true;\n };\n\n return {\n events: {\n session_compact: createRunnerCompactionRecovery(pi, {\n getSessionId: async () => {\n try {\n await waitForSessionReadiness();\n return sessionId;\n } catch {\n return undefined;\n }\n },\n listBySession: async (activeSessionId) => {\n try {\n await waitForSessionReadiness();\n } catch {\n return [];\n }\n return active ? registry.listBySession(activeSessionId) : [];\n },\n }),\n\n [SESSION_START_EVENT]: (_event, ctx) => {\n if (!active) return;\n unsubscribeRegistry?.();\n unsubscribeRegistry = undefined;\n const context = ctx as ExtensionContext;\n loadRunnerSettings(context);\n const activeSessionId = context.sessionManager.getSessionId();\n const previousSessionId = sessionId;\n const previousContext = sessionContext;\n const generation = ++sessionGeneration;\n sessionId = activeSessionId;\n rootSessionId = resolveRootSessionId(activeSessionId, environment);\n sessionContext = context;\n sessionReady = false;\n lastRunnerCount = undefined;\n runners = [];\n notifiedRunnerIds.clear();\n pendingPromotedRunnerIds.clear();\n terminalRunners.clear();\n publishBackgroundWork();\n\n const initializeSession = async (signal: AbortSignal): Promise<readonly string[]> => {\n const stillCurrent = (): boolean => !signal.aborted && isCurrent(generation, activeSessionId);\n if (!stillCurrent()) return [];\n if (previousSessionId && previousSessionId !== activeSessionId) {\n await runCleanup('dispose the previous session PTYs', () => ptyHost.disposeAll());\n await runCleanup('dispose the previous session lifeline', () => lifeline.dispose());\n if (previousContext?.hasUI) {\n await runCleanup('clear the previous session status', () =>\n previousContext.ui.setStatus(RUNNER_STATUS_KEY, undefined),\n );\n }\n const previousTelemetry = telemetry;\n telemetry = undefined;\n if (previousTelemetry) {\n await runCleanup('stop the previous session telemetry', () => previousTelemetry.shutdown());\n }\n if (!stillCurrent()) return [];\n }\n\n const activeTelemetry = getTelemetry(context);\n await activeTelemetry.recordEvent('doom_runner.session_started', { outcome: 'started' });\n if (!stillCurrent()) return [];\n paths.setSessionId(activeSessionId);\n unsubscribeRegistry = registry.subscribe(() => {\n if (isCurrent(generation, activeSessionId)) scheduleRefresh(false);\n }, activeSessionId);\n // Awaited before anything can launch, so every runner this session starts\n // finds a lifeline it can connect to rather than a socket that is not\n // listening yet, which would read as an owner that is already gone.\n await lifeline.arm(activeSessionId);\n if (!stillCurrent()) return [];\n\n const retained = await registry.listAll(activeSessionId);\n if (!stillCurrent()) return [];\n for (const record of retained) {\n if (record.state === COMPLETED_STATE) notifiedRunnerIds.add(record.id);\n else if (record.promoted) pendingPromotedRunnerIds.add(record.id);\n }\n const legacy = await cleanupLegacyRunnerStore({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n paths,\n });\n if (!stillCurrent()) return [];\n const reconciled = await reconcileActiveRunners({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n startup: true,\n });\n if (!stillCurrent()) return [];\n sessionReady = true;\n await refresh(false);\n if (!stillCurrent()) return [];\n scheduleHistorySweep();\n const errors = [...legacy.errors, ...reconciled.errors];\n const reclaimedCount = legacy.reclaimed.length + reconciled.reclaimed.length;\n if (reclaimedCount > 0 && context.hasUI) {\n context.ui.notify(`Reclaimed ${reclaimedCount} stale runner record(s)`, 'warning');\n }\n await activeTelemetry.recordEvent('doom_runner.reconciled', {\n 'runner.reclaimed_count': reclaimedCount,\n 'runner.error_count': errors.length,\n outcome: errors.length === 0 ? 'completed' : 'degraded',\n });\n return errors;\n };\n\n const previousInitialization = sessionInitialization.catch(() => undefined);\n const startReadiness = async (): Promise<void> => {\n await previousInitialization;\n if (!isCurrent(generation, activeSessionId)) return;\n const coordinator =\n (cordis ? readDoomReadinessCoordinator(cordis) : undefined) ??\n (fallbackReadiness ??= createDoomReadinessCoordinator({\n notify: (notification) => {\n process.emitWarning(\n `${notification.packageId} initialization ${notification.state}: ${notification.error?.message ?? notification.diagnostics.join('; ')}`,\n );\n },\n }));\n const handle = coordinator.start(LEADER_SOURCE, `${activeSessionId}:${generation}`, async (signal) => ({\n value: undefined,\n diagnostics: await initializeSession(signal),\n }));\n await handle.wait();\n };\n const operation = startReadiness();\n sessionInitialization = operation;\n // The coordinator reports a failed generation once; this branch only marks\n // the detached waiter handled so Pi is not held open by the notification path.\n void trackOperation(operation).catch(() => undefined);\n },\n },\n command: [\n COMMAND_NAME,\n {\n description: COMMAND_DESCRIPTION,\n handler: async (args, ctx) => {\n if (!active) return;\n const generation = sessionGeneration;\n const activeSessionId = sessionId;\n if (!activeSessionId) return;\n const request = parseRunnersCommand(args);\n // The stop verb is how a client without an overlay (the web cockpit)\n // controls a runner, so it must not need the interactive UI.\n if (request.kind === 'stop') {\n if (!request.id) {\n ctx.ui.notify(ERR_STOP_USAGE, 'error');\n return;\n }\n await waitForSessionReadiness();\n await refresh();\n if (!isCurrent(generation, activeSessionId)) return;\n const stopped = await stopSessionRunner(generation, activeSessionId, request.id, request.reason);\n if (!isCurrent(generation, activeSessionId)) return;\n if (stopped) ctx.ui.notify(`Stopped runner ${request.id}.`, 'info');\n else ctx.ui.notify(`No active runner ${request.id} in this session.`, 'error');\n return;\n }\n // Starting headlessly is how a client without the bash tool (the web\n // cockpit) puts a command up. It is background by construction: a\n // foreground wait has nobody here to wait for it.\n if (request.kind === 'start') {\n if (!request.command) {\n ctx.ui.notify(ERR_START_USAGE, 'error');\n return;\n }\n await waitForSessionReadiness();\n if (!isCurrent(generation, activeSessionId)) return;\n const started = await trackedBashRunService.run({\n command: request.command,\n sessionId: activeSessionId,\n background: true,\n ...(request.cwd ? { cwd: request.cwd } : {}),\n ...(request.name ? { name: request.name } : {}),\n ...(request.interactive ? { interactive: true } : {}),\n });\n if (!isCurrent(generation, activeSessionId)) return;\n await refresh();\n if (started.kind === 'failed') ctx.ui.notify(`Could not start a runner: ${started.error}`, 'error');\n else ctx.ui.notify(`Started runner ${started.name}.`, 'info');\n return;\n }\n if (!ctx.hasUI) {\n ctx.ui.notify(ERR_REQUIRES_INTERACTIVE, 'error');\n return;\n }\n await waitForSessionReadiness();\n await refresh();\n if (!activeSessionId || !isCurrent(generation, activeSessionId)) return;\n await openRunnerSpace(ctx, {\n getRunners: () => (isCurrent(generation, activeSessionId) ? runners : []),\n getPtyRun: (name) =>\n isCurrent(generation, activeSessionId) ? (rmuxBackend.get(name) ?? ptyHost.get(name)) : undefined,\n readLog: (logPath) =>\n isCurrent(generation, activeSessionId) ? logReader.read(logPath, { lines: 1_000 }).text : '',\n stopRunner: async (id, reason) => {\n await stopSessionRunner(generation, activeSessionId, id, reason);\n },\n });\n },\n },\n ],\n bashTool: {\n bashRunService: trackedBashRunService,\n getSessionId: async () => {\n await waitForSessionReadiness();\n if (!sessionId) throw new Error('doom-runner requires an active Pi session');\n return sessionId;\n },\n onRunnerStarted: (id) => {\n if (!active || !sessionReady) return;\n pendingPromotedRunnerIds.add(id);\n publishBackgroundWork();\n scheduleRefresh(false);\n },\n summarizeLog,\n },\n plugin(context) {\n cordis = context;\n context.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n const contribution = requireDoomUiHub(uiContext).registerFooter({\n source: LEADER_SOURCE,\n id: 'runner-count',\n order: RUNNER_FOOTER_ORDER,\n });\n footerContribution = contribution;\n return () => {\n contribution.dispose();\n if (footerContribution === contribution) footerContribution = undefined;\n };\n });\n context.inject([DOOM_BACKGROUND_WORK_SERVICE], (serviceContext) => {\n const service = readDoomBackgroundWorkService(serviceContext);\n if (!service) return undefined;\n const registration = service.register({\n provider: BACKGROUND_WORK_PROVIDER,\n listActiveWork: () => backgroundWorkItems,\n });\n backgroundWorkProvider = registration;\n return () => {\n registration.dispose();\n if (backgroundWorkProvider === registration) backgroundWorkProvider = undefined;\n };\n });\n context.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n const contribution = requireDoomUiHub(uiContext).registerLeader({\n source: LEADER_SOURCE,\n bindings: [\n {\n id: 'runners.open',\n path: [\n { key: 'r', label: 'runners', detail: 'background processes', order: LEADER_GROUP_ORDER },\n { key: 'l', label: 'list', detail: 'runners in this session' },\n ],\n command: { name: COMMAND_NAME },\n },\n ],\n });\n return () => contribution.dispose();\n });\n },\n start() {\n registry = container.runnerRegistry;\n launcher = container.launcher;\n rmuxBackend = container.rmuxBackend;\n logReader = container.logReader;\n ptyHost = container.ptyHost;\n bashRunService = container.bashRunService;\n paths = container.paths;\n processControl = container.processControl;\n lifeline = container.lifeline;\n initialized = true;\n statusPoll = setInterval(() => scheduleRefresh(true), RUNNER_STATUS_POLL_MS);\n statusPoll.unref?.();\n historySweepPoll = setInterval(() => scheduleHistorySweep(), HISTORY_SWEEP_INTERVAL_MS);\n historySweepPoll.unref?.();\n },\n async stop() {\n if (initialized) await shutdownRuntime();\n else registry?.close();\n cordis = undefined;\n },\n };\n}\n"],"mappings":"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"}
@@ -108,7 +108,7 @@ function createRunnerRuntime(pi) {
108
108
  };
109
109
  const publishBackgroundWork = () => {
110
110
  const activeSessionId = sessionId;
111
- const representedIds = /* @__PURE__ */ new Set([...runners.map((record) => record.id), ...terminalRunners.keys()]);
111
+ const representedIds = /* @__PURE__ */ new Set([...runners.filter((record) => record.promoted).map((record) => record.id), ...terminalRunners.keys()]);
112
112
  const next = activeSessionId ? [
113
113
  ...runners.filter((record) => record.sessionId === activeSessionId && record.promoted).map((record) => ({
114
114
  id: record.id,
@@ -1 +1 @@
1
- {"version":3,"file":"runnerRuntime.mjs","names":[],"sources":["../../../src/tui/runnerRuntime.ts"],"sourcesContent":["import {\n type BackgroundProviderWorkItem,\n type BackgroundWorkProviderHandle,\n DOOM_BACKGROUND_WORK_SERVICE,\n readDoomBackgroundWorkService,\n} from '@agimon-ai/doompi-core/background-work';\nimport { resolveRootSessionId } from '@agimon-ai/doompi-core/child-process';\nimport type { DoomFooterContributionHandle } from '@agimon-ai/doompi-core/footer';\nimport {\n createDoomReadinessCoordinator,\n type DoomReadinessCoordinator,\n readDoomReadinessCoordinator,\n} from '@agimon-ai/doompi-core/readiness';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/ui-hub';\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport {\n BACKGROUND_WORK_PROVIDER,\n COMPLETED_STATE,\n ERR_REQUIRES_INTERACTIVE,\n ERR_START_USAGE,\n ERR_STOP_USAGE,\n HISTORY_SWEEP_INTERVAL_MS,\n LEADER_GROUP_ORDER,\n LEADER_SOURCE,\n RMUX_BACKEND,\n RUNNER_FINISHED_MESSAGE,\n RUNNER_FOOTER_ORDER,\n RUNNER_STATUS_KEY,\n RUNNER_STATUS_POLL_MS,\n SESSION_START_EVENT,\n STOPPED_REASON,\n} from '../constants/runnerRuntime';\nimport { COMMAND_DESCRIPTION, COMMAND_NAME } from '../constants/runners';\nimport { RUNNER_SETTINGS_FILE } from '../constants/runnerSettings';\nimport { createRunnerCompactionRecovery } from '../services/compaction';\nimport { summarizeLog } from '../services/logReader';\nimport { cleanupLegacyRunnerStore, reconcileActiveRunners, stopRunnerProcess } from '../services/reconcile';\nimport { getLogTtlMs } from '../services/runnerConfig';\nimport { setRunnerSettings } from '../services/runnerConfig';\nimport { createRunnerDependencies } from '../services/runnerDependencies';\nimport type { RunnerDependencies } from '../services/runnerDependencies/type';\nimport { parseRunnersCommand } from '../services/runnersCommand';\nimport { RunnerSettingsLoader } from '../services/runnerSettings';\nimport type { IBashRunService } from '../types/bashRunService';\nimport type { RunnerRecord } from '../types/runnerRegistry';\n/** After doom-task's `t` (65) and before the core help group (70). */\nimport { formatRunnerFooterContribution, formatRunnerStatus } from './format';\nimport type { RunnerRuntime } from './runnerRuntimeType';\nimport { openRunnerSpace } from './runnerSpace';\n\n/**\n * How often a live session revisits its own runner history. Retention only\n * bounds a session that ends; a session open all day has to sweep itself.\n */\n\n/**\n * Project-local extension config, read the way Pi documents it: one JSON file\n * per extension under the config directory, and only for a trusted project.\n */\nfunction loadRunnerSettings(context: ExtensionContext): void {\n try {\n const trusted = context.isProjectTrusted?.() ?? false;\n const { settings, issues } = new RunnerSettingsLoader().load(context.cwd, trusted);\n setRunnerSettings(settings);\n // A rejected key is surfaced rather than dropped: silence reads as a\n // setting that simply does not work.\n for (const issue of issues) process.emitWarning(`${RUNNER_SETTINGS_FILE}: ${issue}`);\n } catch (error) {\n process.emitWarning(`Could not read ${RUNNER_SETTINGS_FILE}: ${String(error)}`);\n setRunnerSettings({});\n }\n}\n\n/**\n * doom-runner: replaces pi's `bash` tool with a supervised one and provides a\n * CLI for anything it leaves running.\n */\nexport function createRunnerRuntime(pi: ExtensionAPI): RunnerRuntime {\n let cordis: Context | undefined;\n let initialized = false;\n const environment = Object.freeze({ ...process.env });\n const container = createRunnerDependencies({ environment });\n let registry!: RunnerDependencies['runnerRegistry'];\n let launcher!: RunnerDependencies['launcher'];\n let rmuxBackend!: RunnerDependencies['rmuxBackend'];\n let logReader!: RunnerDependencies['logReader'];\n let ptyHost!: RunnerDependencies['ptyHost'];\n let bashRunService!: RunnerDependencies['bashRunService'];\n let paths!: RunnerDependencies['paths'];\n let processControl!: RunnerDependencies['processControl'];\n let lifeline!: RunnerDependencies['lifeline'];\n\n let active = true;\n let sessionGeneration = 0;\n let sessionId: string | undefined;\n let rootSessionId: string | undefined;\n let runners: RunnerRecord[] = [];\n let sessionContext: ExtensionContext | undefined;\n let footerContribution: DoomFooterContributionHandle | undefined;\n let telemetry: DoomTelemetry | undefined;\n let sessionReady = false;\n let disposed = false;\n let refreshInFlight: Promise<void> | undefined;\n let historySweepInFlight: Promise<void> | undefined;\n let historySweepTimer: ReturnType<typeof setImmediate> | undefined;\n let statusPoll: ReturnType<typeof setInterval> | undefined;\n let historySweepPoll: ReturnType<typeof setInterval> | undefined;\n let unsubscribeRegistry: (() => void) | undefined;\n let sessionInitialization: Promise<void> = Promise.resolve();\n let fallbackReadiness: DoomReadinessCoordinator | undefined;\n let refreshQueued = false;\n let queuedReconciliation = false;\n let lastRunnerCount: number | undefined;\n const notifiedRunnerIds = new Set<string>();\n const pendingPromotedRunnerIds = new Set<string>();\n const terminalRunners = new Map<string, RunnerRecord>();\n let backgroundWorkItems: BackgroundProviderWorkItem[] = [];\n let backgroundWorkProvider: BackgroundWorkProviderHandle | undefined;\n const pendingOperations = new Set<Promise<unknown>>();\n const trackOperation = <T>(operation: Promise<T>): Promise<T> => {\n pendingOperations.add(operation);\n void operation.then(\n () => pendingOperations.delete(operation),\n () => pendingOperations.delete(operation),\n );\n return operation;\n };\n const waitForSessionReadiness = async (): Promise<void> => {\n await sessionInitialization;\n if (!active || !sessionReady || !sessionId) {\n throw new Error('doom-runner requires an active Pi session');\n }\n };\n const trackedBashRunService: IBashRunService = {\n run: async (request) => {\n await waitForSessionReadiness();\n return trackOperation(bashRunService.run(request));\n },\n };\n const isCurrent = (generation: number, expectedSessionId = sessionId): boolean =>\n active && !disposed && generation === sessionGeneration && expectedSessionId === sessionId;\n const getTelemetry = (ctx: ExtensionContext): DoomTelemetry => {\n telemetry ??= createDoomTelemetry({\n serviceName: 'doom-runner',\n packageName: '@agimon-ai/doompi-runner',\n cwd: ctx.cwd,\n env: environment,\n enableLogs: true,\n enableTraces: true,\n });\n return telemetry;\n };\n const publishBackgroundWork = (): void => {\n const activeSessionId = sessionId;\n const representedIds = new Set([...runners.map((record) => record.id), ...terminalRunners.keys()]);\n const next = activeSessionId\n ? [\n ...runners\n .filter((record) => record.sessionId === activeSessionId && record.promoted)\n .map((record) => ({\n id: record.id,\n sessionId: record.sessionId,\n label: record.name,\n status: record.state,\n })),\n ...[...terminalRunners.values()]\n .filter((record) => record.sessionId === activeSessionId)\n .map((record) => ({\n id: record.id,\n sessionId: record.sessionId,\n label: record.name,\n status: record.state,\n })),\n ...[...pendingPromotedRunnerIds]\n .filter((id) => !representedIds.has(id))\n .map((id) => ({ id, sessionId: activeSessionId, status: 'running' })),\n ]\n : [];\n if (JSON.stringify(next) === JSON.stringify(backgroundWorkItems)) return;\n backgroundWorkItems = next;\n backgroundWorkProvider?.update();\n };\n /** Performs one bounded pass over active state and explicitly monitored runners. */\n const refreshNow = async (shouldReconcile: boolean): Promise<void> => {\n const activeSessionId = sessionId;\n const generation = sessionGeneration;\n if (!activeSessionId || !isCurrent(generation, activeSessionId)) return;\n\n const activeRecords = await registry.list();\n if (!isCurrent(generation, activeSessionId)) return;\n let visibleActive = activeRecords;\n if (shouldReconcile) {\n const reconciled = await reconcileActiveRunners({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n startup: false,\n active: activeRecords,\n });\n for (const error of reconciled.errors) process.emitWarning(error);\n if (reconciled.reclaimed.length > 0) {\n const reclaimedIds = new Set(reconciled.reclaimed);\n visibleActive = activeRecords.filter((record) => !reclaimedIds.has(record.id));\n }\n }\n if (!isCurrent(generation, activeSessionId)) return;\n\n runners = visibleActive.filter((record) => record.sessionId === activeSessionId);\n const rootRunners = rootSessionId\n ? visibleActive.filter((record) => (record.rootSessionId ?? record.sessionId) === rootSessionId)\n : [];\n const runnerCount = rootRunners.length;\n if (lastRunnerCount !== runnerCount) {\n lastRunnerCount = runnerCount;\n footerContribution?.update(formatRunnerFooterContribution(runnerCount));\n if (sessionContext?.hasUI) sessionContext.ui.setStatus(RUNNER_STATUS_KEY, formatRunnerStatus(runnerCount));\n }\n\n const pendingIds = [...pendingPromotedRunnerIds];\n const monitored = await Promise.all(pendingIds.map((id) => registry.get(id, activeSessionId)));\n if (!isCurrent(generation, activeSessionId)) return;\n for (const [index, record] of monitored.entries()) {\n const id = pendingIds[index];\n if (!id) continue;\n if (!record || record.sessionId !== activeSessionId) {\n pendingPromotedRunnerIds.delete(id);\n terminalRunners.delete(id);\n runners = runners.filter((candidate) => candidate.id !== id);\n continue;\n }\n if (record.state === COMPLETED_STATE) {\n runners = runners.filter((candidate) => candidate.id !== record.id);\n terminalRunners.set(record.id, record);\n }\n }\n publishBackgroundWork();\n for (const record of monitored) {\n if (!record || record.sessionId !== activeSessionId || record.state !== COMPLETED_STATE) continue;\n if (notifiedRunnerIds.has(record.id)) continue;\n const outcome = record.exit?.reason ?? COMPLETED_STATE;\n const code =\n record.exit?.code === null || record.exit?.code === undefined ? '' : `, exit code ${record.exit.code}`;\n const content = [\n `Background runner ${record.name} exited: ${outcome}${code}.`,\n `Runner ID: ${record.id}`,\n `Log: ${record.logPath}`,\n `Inspect: doom-runner logs ${record.id}`,\n ].join('\\n');\n pi.sendMessage(\n { customType: RUNNER_FINISHED_MESSAGE, content, display: true },\n { triggerTurn: true, deliverAs: 'steer' },\n );\n notifiedRunnerIds.add(record.id);\n pendingPromotedRunnerIds.delete(record.id);\n terminalRunners.delete(record.id);\n publishBackgroundWork();\n if (sessionContext) {\n void trackOperation(\n getTelemetry(sessionContext).recordEvent('doom_runner.process_finished', {\n outcome: 'completed',\n 'runner.exit_code': record.exit?.code ?? 0,\n 'runner.backend': record.backend,\n ...(Number.isFinite(Date.parse(record.startedAt))\n ? { duration_ms: Math.max(0, Date.now() - Date.parse(record.startedAt)) }\n : {}),\n }),\n );\n }\n }\n };\n\n /** Coalesces timer and event triggers without losing a requested reconciliation pass. */\n const refresh = (shouldReconcile = true): Promise<void> => {\n if (!sessionId || !sessionReady || disposed) return Promise.resolve();\n if (refreshInFlight) {\n refreshQueued = true;\n queuedReconciliation ||= shouldReconcile;\n return refreshInFlight;\n }\n\n const execution = (async () => {\n let reconcileNext = shouldReconcile;\n do {\n refreshQueued = false;\n queuedReconciliation = false;\n await refreshNow(reconcileNext);\n reconcileNext = queuedReconciliation;\n } while (refreshQueued && !disposed);\n })().finally(() => {\n if (refreshInFlight === execution) refreshInFlight = undefined;\n });\n refreshInFlight = execution;\n return execution;\n };\n\n const reportRefreshError = (error: unknown): void => {\n if (disposed) return;\n if (sessionContext) {\n void trackOperation(getTelemetry(sessionContext).recordError('doom_runner.refresh_failed', error));\n }\n process.emitWarning(`Could not refresh doom-runner: ${String(error)}`);\n };\n const scheduleRefresh = (shouldReconcile: boolean): void => {\n void refresh(shouldReconcile).catch(reportRefreshError);\n };\n const scheduleHistorySweep = (): void => {\n if (historySweepTimer || historySweepInFlight || disposed) return;\n historySweepTimer = setImmediate(() => {\n historySweepTimer = undefined;\n if (disposed) return;\n const execution = (async () => {\n const sweep = paths.sweepHistoryAsync\n ? await paths.sweepHistoryAsync(getLogTtlMs())\n : paths.sweepHistory(getLogTtlMs());\n for (const error of sweep.errors) process.emitWarning(error);\n })()\n .catch((error) => process.emitWarning(`Could not sweep doom-runner history: ${String(error)}`))\n .finally(() => {\n if (historySweepInFlight === execution) historySweepInFlight = undefined;\n });\n historySweepInFlight = execution;\n });\n historySweepTimer.unref?.();\n };\n\n const runCleanup = async (label: string, cleanup: () => void | Promise<void>): Promise<void> => {\n try {\n await cleanup();\n } catch (error) {\n process.emitWarning(`Doom-runner cleanup could not ${label}: ${String(error)}`);\n }\n };\n\n const shutdownRuntime = async (): Promise<void> => {\n if (disposed) return;\n active = false;\n disposed = true;\n sessionGeneration += 1;\n sessionReady = false;\n if (statusPoll) clearInterval(statusPoll);\n statusPoll = undefined;\n if (historySweepPoll) clearInterval(historySweepPoll);\n historySweepPoll = undefined;\n if (historySweepTimer) clearImmediate(historySweepTimer);\n historySweepTimer = undefined;\n const unsubscribe = unsubscribeRegistry;\n unsubscribeRegistry = undefined;\n if (unsubscribe) await runCleanup('unsubscribe from the runner registry', unsubscribe);\n\n const ownedReadiness = fallbackReadiness;\n fallbackReadiness = undefined;\n if (ownedReadiness) await runCleanup('cancel standalone readiness work', () => ownedReadiness.dispose());\n await Promise.allSettled(pendingOperations);\n const activeRefresh = refreshInFlight;\n if (activeRefresh) await runCleanup('settle the runner refresh', () => activeRefresh);\n const activeHistorySweep = historySweepInFlight;\n if (activeHistorySweep) await runCleanup('settle runner history cleanup', () => activeHistorySweep);\n\n await runCleanup('dispose runner PTYs', () => ptyHost.disposeAll());\n\n let owned: RunnerRecord[] = [];\n if (sessionId) {\n try {\n owned = await registry.listBySession(sessionId);\n } catch (error) {\n process.emitWarning(`Could not list runners during doom-runner shutdown: ${String(error)}`);\n }\n }\n await Promise.all(\n owned.map(async (record) => {\n try {\n const stopped = await stopRunnerProcess(record, launcher, rmuxBackend);\n if (!stopped && processControl.isAlive(record.pid)) {\n process.emitWarning(`Could not stop runner ${record.id} during session shutdown`);\n return;\n }\n await registry.complete(\n record.id,\n {\n reason: STOPPED_REASON,\n code: null,\n signal: stopped ? 'SIGTERM' : null,\n stopReason: 'session ended',\n },\n record.sessionId,\n );\n } catch (error) {\n process.emitWarning(`Could not clean up runner ${record.id}: ${String(error)}`);\n }\n }),\n );\n\n const context = sessionContext;\n const ownedTelemetry = telemetry;\n telemetry = undefined;\n sessionContext = undefined;\n sessionId = undefined;\n rootSessionId = undefined;\n runners = [];\n notifiedRunnerIds.clear();\n pendingPromotedRunnerIds.clear();\n terminalRunners.clear();\n publishBackgroundWork();\n\n await Promise.all([\n runCleanup('dispose the runner lifeline', () => lifeline.dispose()),\n ...(context?.hasUI\n ? [runCleanup('clear the runner status', () => context.ui.setStatus(RUNNER_STATUS_KEY, undefined))]\n : []),\n ]);\n await runCleanup('close the runner registry', () => registry.close());\n if (ownedTelemetry) {\n await runCleanup('record the runner session finish', () =>\n ownedTelemetry.recordEvent('doom_runner.session_finished', { outcome: 'stopped' }),\n );\n await runCleanup('stop runner telemetry', () => ownedTelemetry.shutdown());\n }\n };\n\n /** Stops one of this session's runners; false when no such runner is active. */\n const stopSessionRunner = async (\n generation: number,\n activeSessionId: string,\n id: string,\n reason?: string,\n ): Promise<boolean> => {\n if (!isCurrent(generation, activeSessionId)) return false;\n const record = runners.find((candidate) => candidate.id === id);\n if (!record) return false;\n if (record.backend === RMUX_BACKEND && record.backendTarget) {\n await rmuxBackend.stop(record.backendTarget, record.pid);\n } else await launcher.stop(record.pid);\n if (!isCurrent(generation, activeSessionId)) return true;\n await registry.complete(\n record.id,\n { reason: STOPPED_REASON, code: null, signal: null, stopReason: reason },\n record.sessionId,\n );\n if (isCurrent(generation, activeSessionId)) await refresh();\n return true;\n };\n\n return {\n events: {\n session_compact: createRunnerCompactionRecovery(pi, {\n getSessionId: async () => {\n try {\n await waitForSessionReadiness();\n return sessionId;\n } catch {\n return undefined;\n }\n },\n listBySession: async (activeSessionId) => {\n try {\n await waitForSessionReadiness();\n } catch {\n return [];\n }\n return active ? registry.listBySession(activeSessionId) : [];\n },\n }),\n\n [SESSION_START_EVENT]: (_event, ctx) => {\n if (!active) return;\n unsubscribeRegistry?.();\n unsubscribeRegistry = undefined;\n const context = ctx as ExtensionContext;\n loadRunnerSettings(context);\n const activeSessionId = context.sessionManager.getSessionId();\n const previousSessionId = sessionId;\n const previousContext = sessionContext;\n const generation = ++sessionGeneration;\n sessionId = activeSessionId;\n rootSessionId = resolveRootSessionId(activeSessionId, environment);\n sessionContext = context;\n sessionReady = false;\n lastRunnerCount = undefined;\n runners = [];\n notifiedRunnerIds.clear();\n pendingPromotedRunnerIds.clear();\n terminalRunners.clear();\n publishBackgroundWork();\n\n const initializeSession = async (signal: AbortSignal): Promise<readonly string[]> => {\n const stillCurrent = (): boolean => !signal.aborted && isCurrent(generation, activeSessionId);\n if (!stillCurrent()) return [];\n if (previousSessionId && previousSessionId !== activeSessionId) {\n await runCleanup('dispose the previous session PTYs', () => ptyHost.disposeAll());\n await runCleanup('dispose the previous session lifeline', () => lifeline.dispose());\n if (previousContext?.hasUI) {\n await runCleanup('clear the previous session status', () =>\n previousContext.ui.setStatus(RUNNER_STATUS_KEY, undefined),\n );\n }\n const previousTelemetry = telemetry;\n telemetry = undefined;\n if (previousTelemetry) {\n await runCleanup('stop the previous session telemetry', () => previousTelemetry.shutdown());\n }\n if (!stillCurrent()) return [];\n }\n\n const activeTelemetry = getTelemetry(context);\n await activeTelemetry.recordEvent('doom_runner.session_started', { outcome: 'started' });\n if (!stillCurrent()) return [];\n paths.setSessionId(activeSessionId);\n unsubscribeRegistry = registry.subscribe(() => {\n if (isCurrent(generation, activeSessionId)) scheduleRefresh(false);\n }, activeSessionId);\n // Awaited before anything can launch, so every runner this session starts\n // finds a lifeline it can connect to rather than a socket that is not\n // listening yet, which would read as an owner that is already gone.\n await lifeline.arm(activeSessionId);\n if (!stillCurrent()) return [];\n\n const retained = await registry.listAll(activeSessionId);\n if (!stillCurrent()) return [];\n for (const record of retained) {\n if (record.state === COMPLETED_STATE) notifiedRunnerIds.add(record.id);\n else if (record.promoted) pendingPromotedRunnerIds.add(record.id);\n }\n const legacy = await cleanupLegacyRunnerStore({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n paths,\n });\n if (!stillCurrent()) return [];\n const reconciled = await reconcileActiveRunners({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n startup: true,\n });\n if (!stillCurrent()) return [];\n sessionReady = true;\n await refresh(false);\n if (!stillCurrent()) return [];\n scheduleHistorySweep();\n const errors = [...legacy.errors, ...reconciled.errors];\n const reclaimedCount = legacy.reclaimed.length + reconciled.reclaimed.length;\n if (reclaimedCount > 0 && context.hasUI) {\n context.ui.notify(`Reclaimed ${reclaimedCount} stale runner record(s)`, 'warning');\n }\n await activeTelemetry.recordEvent('doom_runner.reconciled', {\n 'runner.reclaimed_count': reclaimedCount,\n 'runner.error_count': errors.length,\n outcome: errors.length === 0 ? 'completed' : 'degraded',\n });\n return errors;\n };\n\n const previousInitialization = sessionInitialization.catch(() => undefined);\n const startReadiness = async (): Promise<void> => {\n await previousInitialization;\n if (!isCurrent(generation, activeSessionId)) return;\n const coordinator =\n (cordis ? readDoomReadinessCoordinator(cordis) : undefined) ??\n (fallbackReadiness ??= createDoomReadinessCoordinator({\n notify: (notification) => {\n process.emitWarning(\n `${notification.packageId} initialization ${notification.state}: ${notification.error?.message ?? notification.diagnostics.join('; ')}`,\n );\n },\n }));\n const handle = coordinator.start(LEADER_SOURCE, `${activeSessionId}:${generation}`, async (signal) => ({\n value: undefined,\n diagnostics: await initializeSession(signal),\n }));\n await handle.wait();\n };\n const operation = startReadiness();\n sessionInitialization = operation;\n // The coordinator reports a failed generation once; this branch only marks\n // the detached waiter handled so Pi is not held open by the notification path.\n void trackOperation(operation).catch(() => undefined);\n },\n },\n command: [\n COMMAND_NAME,\n {\n description: COMMAND_DESCRIPTION,\n handler: async (args, ctx) => {\n if (!active) return;\n const generation = sessionGeneration;\n const activeSessionId = sessionId;\n if (!activeSessionId) return;\n const request = parseRunnersCommand(args);\n // The stop verb is how a client without an overlay (the web cockpit)\n // controls a runner, so it must not need the interactive UI.\n if (request.kind === 'stop') {\n if (!request.id) {\n ctx.ui.notify(ERR_STOP_USAGE, 'error');\n return;\n }\n await waitForSessionReadiness();\n await refresh();\n if (!isCurrent(generation, activeSessionId)) return;\n const stopped = await stopSessionRunner(generation, activeSessionId, request.id, request.reason);\n if (!isCurrent(generation, activeSessionId)) return;\n if (stopped) ctx.ui.notify(`Stopped runner ${request.id}.`, 'info');\n else ctx.ui.notify(`No active runner ${request.id} in this session.`, 'error');\n return;\n }\n // Starting headlessly is how a client without the bash tool (the web\n // cockpit) puts a command up. It is background by construction: a\n // foreground wait has nobody here to wait for it.\n if (request.kind === 'start') {\n if (!request.command) {\n ctx.ui.notify(ERR_START_USAGE, 'error');\n return;\n }\n await waitForSessionReadiness();\n if (!isCurrent(generation, activeSessionId)) return;\n const started = await trackedBashRunService.run({\n command: request.command,\n sessionId: activeSessionId,\n background: true,\n ...(request.cwd ? { cwd: request.cwd } : {}),\n ...(request.name ? { name: request.name } : {}),\n ...(request.interactive ? { interactive: true } : {}),\n });\n if (!isCurrent(generation, activeSessionId)) return;\n await refresh();\n if (started.kind === 'failed') ctx.ui.notify(`Could not start a runner: ${started.error}`, 'error');\n else ctx.ui.notify(`Started runner ${started.name}.`, 'info');\n return;\n }\n if (!ctx.hasUI) {\n ctx.ui.notify(ERR_REQUIRES_INTERACTIVE, 'error');\n return;\n }\n await waitForSessionReadiness();\n await refresh();\n if (!activeSessionId || !isCurrent(generation, activeSessionId)) return;\n await openRunnerSpace(ctx, {\n getRunners: () => (isCurrent(generation, activeSessionId) ? runners : []),\n getPtyRun: (name) =>\n isCurrent(generation, activeSessionId) ? (rmuxBackend.get(name) ?? ptyHost.get(name)) : undefined,\n readLog: (logPath) =>\n isCurrent(generation, activeSessionId) ? logReader.read(logPath, { lines: 1_000 }).text : '',\n stopRunner: async (id, reason) => {\n await stopSessionRunner(generation, activeSessionId, id, reason);\n },\n });\n },\n },\n ],\n bashTool: {\n bashRunService: trackedBashRunService,\n getSessionId: async () => {\n await waitForSessionReadiness();\n if (!sessionId) throw new Error('doom-runner requires an active Pi session');\n return sessionId;\n },\n onRunnerStarted: (id) => {\n if (!active || !sessionReady) return;\n pendingPromotedRunnerIds.add(id);\n publishBackgroundWork();\n scheduleRefresh(false);\n },\n summarizeLog,\n },\n plugin(context) {\n cordis = context;\n context.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n const contribution = requireDoomUiHub(uiContext).registerFooter({\n source: LEADER_SOURCE,\n id: 'runner-count',\n order: RUNNER_FOOTER_ORDER,\n });\n footerContribution = contribution;\n return () => {\n contribution.dispose();\n if (footerContribution === contribution) footerContribution = undefined;\n };\n });\n context.inject([DOOM_BACKGROUND_WORK_SERVICE], (serviceContext) => {\n const service = readDoomBackgroundWorkService(serviceContext);\n if (!service) return undefined;\n const registration = service.register({\n provider: BACKGROUND_WORK_PROVIDER,\n listActiveWork: () => backgroundWorkItems,\n });\n backgroundWorkProvider = registration;\n return () => {\n registration.dispose();\n if (backgroundWorkProvider === registration) backgroundWorkProvider = undefined;\n };\n });\n context.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n const contribution = requireDoomUiHub(uiContext).registerLeader({\n source: LEADER_SOURCE,\n bindings: [\n {\n id: 'runners.open',\n path: [\n { key: 'r', label: 'runners', detail: 'background processes', order: LEADER_GROUP_ORDER },\n { key: 'l', label: 'list', detail: 'runners in this session' },\n ],\n command: { name: COMMAND_NAME },\n },\n ],\n });\n return () => contribution.dispose();\n });\n },\n start() {\n registry = container.runnerRegistry;\n launcher = container.launcher;\n rmuxBackend = container.rmuxBackend;\n logReader = container.logReader;\n ptyHost = container.ptyHost;\n bashRunService = container.bashRunService;\n paths = container.paths;\n processControl = container.processControl;\n lifeline = container.lifeline;\n initialized = true;\n statusPoll = setInterval(() => scheduleRefresh(true), RUNNER_STATUS_POLL_MS);\n statusPoll.unref?.();\n historySweepPoll = setInterval(() => scheduleHistorySweep(), HISTORY_SWEEP_INTERVAL_MS);\n historySweepPoll.unref?.();\n },\n async stop() {\n if (initialized) await shutdownRuntime();\n else registry?.close();\n cordis = undefined;\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"runnerRuntime.mjs","names":[],"sources":["../../../src/tui/runnerRuntime.ts"],"sourcesContent":["import {\n type BackgroundProviderWorkItem,\n type BackgroundWorkProviderHandle,\n DOOM_BACKGROUND_WORK_SERVICE,\n readDoomBackgroundWorkService,\n} from '@agimon-ai/doompi-core/background-work';\nimport { resolveRootSessionId } from '@agimon-ai/doompi-core/child-process';\nimport type { DoomFooterContributionHandle } from '@agimon-ai/doompi-core/footer';\nimport {\n createDoomReadinessCoordinator,\n type DoomReadinessCoordinator,\n readDoomReadinessCoordinator,\n} from '@agimon-ai/doompi-core/readiness';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/ui-hub';\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport {\n BACKGROUND_WORK_PROVIDER,\n COMPLETED_STATE,\n ERR_REQUIRES_INTERACTIVE,\n ERR_START_USAGE,\n ERR_STOP_USAGE,\n HISTORY_SWEEP_INTERVAL_MS,\n LEADER_GROUP_ORDER,\n LEADER_SOURCE,\n RMUX_BACKEND,\n RUNNER_FINISHED_MESSAGE,\n RUNNER_FOOTER_ORDER,\n RUNNER_STATUS_KEY,\n RUNNER_STATUS_POLL_MS,\n SESSION_START_EVENT,\n STOPPED_REASON,\n} from '../constants/runnerRuntime';\nimport { COMMAND_DESCRIPTION, COMMAND_NAME } from '../constants/runners';\nimport { RUNNER_SETTINGS_FILE } from '../constants/runnerSettings';\nimport { createRunnerCompactionRecovery } from '../services/compaction';\nimport { summarizeLog } from '../services/logReader';\nimport { cleanupLegacyRunnerStore, reconcileActiveRunners, stopRunnerProcess } from '../services/reconcile';\nimport { getLogTtlMs } from '../services/runnerConfig';\nimport { setRunnerSettings } from '../services/runnerConfig';\nimport { createRunnerDependencies } from '../services/runnerDependencies';\nimport type { RunnerDependencies } from '../services/runnerDependencies/type';\nimport { parseRunnersCommand } from '../services/runnersCommand';\nimport { RunnerSettingsLoader } from '../services/runnerSettings';\nimport type { IBashRunService } from '../types/bashRunService';\nimport type { RunnerRecord } from '../types/runnerRegistry';\n/** After doom-task's `t` (65) and before the core help group (70). */\nimport { formatRunnerFooterContribution, formatRunnerStatus } from './format';\nimport type { RunnerRuntime } from './runnerRuntimeType';\nimport { openRunnerSpace } from './runnerSpace';\n\n/**\n * How often a live session revisits its own runner history. Retention only\n * bounds a session that ends; a session open all day has to sweep itself.\n */\n\n/**\n * Project-local extension config, read the way Pi documents it: one JSON file\n * per extension under the config directory, and only for a trusted project.\n */\nfunction loadRunnerSettings(context: ExtensionContext): void {\n try {\n const trusted = context.isProjectTrusted?.() ?? false;\n const { settings, issues } = new RunnerSettingsLoader().load(context.cwd, trusted);\n setRunnerSettings(settings);\n // A rejected key is surfaced rather than dropped: silence reads as a\n // setting that simply does not work.\n for (const issue of issues) process.emitWarning(`${RUNNER_SETTINGS_FILE}: ${issue}`);\n } catch (error) {\n process.emitWarning(`Could not read ${RUNNER_SETTINGS_FILE}: ${String(error)}`);\n setRunnerSettings({});\n }\n}\n\n/**\n * doom-runner: replaces pi's `bash` tool with a supervised one and provides a\n * CLI for anything it leaves running.\n */\nexport function createRunnerRuntime(pi: ExtensionAPI): RunnerRuntime {\n let cordis: Context | undefined;\n let initialized = false;\n const environment = Object.freeze({ ...process.env });\n const container = createRunnerDependencies({ environment });\n let registry!: RunnerDependencies['runnerRegistry'];\n let launcher!: RunnerDependencies['launcher'];\n let rmuxBackend!: RunnerDependencies['rmuxBackend'];\n let logReader!: RunnerDependencies['logReader'];\n let ptyHost!: RunnerDependencies['ptyHost'];\n let bashRunService!: RunnerDependencies['bashRunService'];\n let paths!: RunnerDependencies['paths'];\n let processControl!: RunnerDependencies['processControl'];\n let lifeline!: RunnerDependencies['lifeline'];\n\n let active = true;\n let sessionGeneration = 0;\n let sessionId: string | undefined;\n let rootSessionId: string | undefined;\n let runners: RunnerRecord[] = [];\n let sessionContext: ExtensionContext | undefined;\n let footerContribution: DoomFooterContributionHandle | undefined;\n let telemetry: DoomTelemetry | undefined;\n let sessionReady = false;\n let disposed = false;\n let refreshInFlight: Promise<void> | undefined;\n let historySweepInFlight: Promise<void> | undefined;\n let historySweepTimer: ReturnType<typeof setImmediate> | undefined;\n let statusPoll: ReturnType<typeof setInterval> | undefined;\n let historySweepPoll: ReturnType<typeof setInterval> | undefined;\n let unsubscribeRegistry: (() => void) | undefined;\n let sessionInitialization: Promise<void> = Promise.resolve();\n let fallbackReadiness: DoomReadinessCoordinator | undefined;\n let refreshQueued = false;\n let queuedReconciliation = false;\n let lastRunnerCount: number | undefined;\n const notifiedRunnerIds = new Set<string>();\n const pendingPromotedRunnerIds = new Set<string>();\n const terminalRunners = new Map<string, RunnerRecord>();\n let backgroundWorkItems: BackgroundProviderWorkItem[] = [];\n let backgroundWorkProvider: BackgroundWorkProviderHandle | undefined;\n const pendingOperations = new Set<Promise<unknown>>();\n const trackOperation = <T>(operation: Promise<T>): Promise<T> => {\n pendingOperations.add(operation);\n void operation.then(\n () => pendingOperations.delete(operation),\n () => pendingOperations.delete(operation),\n );\n return operation;\n };\n const waitForSessionReadiness = async (): Promise<void> => {\n await sessionInitialization;\n if (!active || !sessionReady || !sessionId) {\n throw new Error('doom-runner requires an active Pi session');\n }\n };\n const trackedBashRunService: IBashRunService = {\n run: async (request) => {\n await waitForSessionReadiness();\n return trackOperation(bashRunService.run(request));\n },\n };\n const isCurrent = (generation: number, expectedSessionId = sessionId): boolean =>\n active && !disposed && generation === sessionGeneration && expectedSessionId === sessionId;\n const getTelemetry = (ctx: ExtensionContext): DoomTelemetry => {\n telemetry ??= createDoomTelemetry({\n serviceName: 'doom-runner',\n packageName: '@agimon-ai/doompi-runner',\n cwd: ctx.cwd,\n env: environment,\n enableLogs: true,\n enableTraces: true,\n });\n return telemetry;\n };\n const publishBackgroundWork = (): void => {\n const activeSessionId = sessionId;\n const representedIds = new Set([\n ...runners.filter((record) => record.promoted).map((record) => record.id),\n ...terminalRunners.keys(),\n ]);\n const next = activeSessionId\n ? [\n ...runners\n .filter((record) => record.sessionId === activeSessionId && record.promoted)\n .map((record) => ({\n id: record.id,\n sessionId: record.sessionId,\n label: record.name,\n status: record.state,\n })),\n ...[...terminalRunners.values()]\n .filter((record) => record.sessionId === activeSessionId)\n .map((record) => ({\n id: record.id,\n sessionId: record.sessionId,\n label: record.name,\n status: record.state,\n })),\n ...[...pendingPromotedRunnerIds]\n .filter((id) => !representedIds.has(id))\n .map((id) => ({ id, sessionId: activeSessionId, status: 'running' })),\n ]\n : [];\n if (JSON.stringify(next) === JSON.stringify(backgroundWorkItems)) return;\n backgroundWorkItems = next;\n backgroundWorkProvider?.update();\n };\n /** Performs one bounded pass over active state and explicitly monitored runners. */\n const refreshNow = async (shouldReconcile: boolean): Promise<void> => {\n const activeSessionId = sessionId;\n const generation = sessionGeneration;\n if (!activeSessionId || !isCurrent(generation, activeSessionId)) return;\n\n const activeRecords = await registry.list();\n if (!isCurrent(generation, activeSessionId)) return;\n let visibleActive = activeRecords;\n if (shouldReconcile) {\n const reconciled = await reconcileActiveRunners({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n startup: false,\n active: activeRecords,\n });\n for (const error of reconciled.errors) process.emitWarning(error);\n if (reconciled.reclaimed.length > 0) {\n const reclaimedIds = new Set(reconciled.reclaimed);\n visibleActive = activeRecords.filter((record) => !reclaimedIds.has(record.id));\n }\n }\n if (!isCurrent(generation, activeSessionId)) return;\n\n runners = visibleActive.filter((record) => record.sessionId === activeSessionId);\n const rootRunners = rootSessionId\n ? visibleActive.filter((record) => (record.rootSessionId ?? record.sessionId) === rootSessionId)\n : [];\n const runnerCount = rootRunners.length;\n if (lastRunnerCount !== runnerCount) {\n lastRunnerCount = runnerCount;\n footerContribution?.update(formatRunnerFooterContribution(runnerCount));\n if (sessionContext?.hasUI) sessionContext.ui.setStatus(RUNNER_STATUS_KEY, formatRunnerStatus(runnerCount));\n }\n\n const pendingIds = [...pendingPromotedRunnerIds];\n const monitored = await Promise.all(pendingIds.map((id) => registry.get(id, activeSessionId)));\n if (!isCurrent(generation, activeSessionId)) return;\n for (const [index, record] of monitored.entries()) {\n const id = pendingIds[index];\n if (!id) continue;\n if (!record || record.sessionId !== activeSessionId) {\n pendingPromotedRunnerIds.delete(id);\n terminalRunners.delete(id);\n runners = runners.filter((candidate) => candidate.id !== id);\n continue;\n }\n if (record.state === COMPLETED_STATE) {\n runners = runners.filter((candidate) => candidate.id !== record.id);\n terminalRunners.set(record.id, record);\n }\n }\n publishBackgroundWork();\n for (const record of monitored) {\n if (!record || record.sessionId !== activeSessionId || record.state !== COMPLETED_STATE) continue;\n if (notifiedRunnerIds.has(record.id)) continue;\n const outcome = record.exit?.reason ?? COMPLETED_STATE;\n const code =\n record.exit?.code === null || record.exit?.code === undefined ? '' : `, exit code ${record.exit.code}`;\n const content = [\n `Background runner ${record.name} exited: ${outcome}${code}.`,\n `Runner ID: ${record.id}`,\n `Log: ${record.logPath}`,\n `Inspect: doom-runner logs ${record.id}`,\n ].join('\\n');\n pi.sendMessage(\n { customType: RUNNER_FINISHED_MESSAGE, content, display: true },\n { triggerTurn: true, deliverAs: 'steer' },\n );\n notifiedRunnerIds.add(record.id);\n pendingPromotedRunnerIds.delete(record.id);\n terminalRunners.delete(record.id);\n publishBackgroundWork();\n if (sessionContext) {\n void trackOperation(\n getTelemetry(sessionContext).recordEvent('doom_runner.process_finished', {\n outcome: 'completed',\n 'runner.exit_code': record.exit?.code ?? 0,\n 'runner.backend': record.backend,\n ...(Number.isFinite(Date.parse(record.startedAt))\n ? { duration_ms: Math.max(0, Date.now() - Date.parse(record.startedAt)) }\n : {}),\n }),\n );\n }\n }\n };\n\n /** Coalesces timer and event triggers without losing a requested reconciliation pass. */\n const refresh = (shouldReconcile = true): Promise<void> => {\n if (!sessionId || !sessionReady || disposed) return Promise.resolve();\n if (refreshInFlight) {\n refreshQueued = true;\n queuedReconciliation ||= shouldReconcile;\n return refreshInFlight;\n }\n\n const execution = (async () => {\n let reconcileNext = shouldReconcile;\n do {\n refreshQueued = false;\n queuedReconciliation = false;\n await refreshNow(reconcileNext);\n reconcileNext = queuedReconciliation;\n } while (refreshQueued && !disposed);\n })().finally(() => {\n if (refreshInFlight === execution) refreshInFlight = undefined;\n });\n refreshInFlight = execution;\n return execution;\n };\n\n const reportRefreshError = (error: unknown): void => {\n if (disposed) return;\n if (sessionContext) {\n void trackOperation(getTelemetry(sessionContext).recordError('doom_runner.refresh_failed', error));\n }\n process.emitWarning(`Could not refresh doom-runner: ${String(error)}`);\n };\n const scheduleRefresh = (shouldReconcile: boolean): void => {\n void refresh(shouldReconcile).catch(reportRefreshError);\n };\n const scheduleHistorySweep = (): void => {\n if (historySweepTimer || historySweepInFlight || disposed) return;\n historySweepTimer = setImmediate(() => {\n historySweepTimer = undefined;\n if (disposed) return;\n const execution = (async () => {\n const sweep = paths.sweepHistoryAsync\n ? await paths.sweepHistoryAsync(getLogTtlMs())\n : paths.sweepHistory(getLogTtlMs());\n for (const error of sweep.errors) process.emitWarning(error);\n })()\n .catch((error) => process.emitWarning(`Could not sweep doom-runner history: ${String(error)}`))\n .finally(() => {\n if (historySweepInFlight === execution) historySweepInFlight = undefined;\n });\n historySweepInFlight = execution;\n });\n historySweepTimer.unref?.();\n };\n\n const runCleanup = async (label: string, cleanup: () => void | Promise<void>): Promise<void> => {\n try {\n await cleanup();\n } catch (error) {\n process.emitWarning(`Doom-runner cleanup could not ${label}: ${String(error)}`);\n }\n };\n\n const shutdownRuntime = async (): Promise<void> => {\n if (disposed) return;\n active = false;\n disposed = true;\n sessionGeneration += 1;\n sessionReady = false;\n if (statusPoll) clearInterval(statusPoll);\n statusPoll = undefined;\n if (historySweepPoll) clearInterval(historySweepPoll);\n historySweepPoll = undefined;\n if (historySweepTimer) clearImmediate(historySweepTimer);\n historySweepTimer = undefined;\n const unsubscribe = unsubscribeRegistry;\n unsubscribeRegistry = undefined;\n if (unsubscribe) await runCleanup('unsubscribe from the runner registry', unsubscribe);\n\n const ownedReadiness = fallbackReadiness;\n fallbackReadiness = undefined;\n if (ownedReadiness) await runCleanup('cancel standalone readiness work', () => ownedReadiness.dispose());\n await Promise.allSettled(pendingOperations);\n const activeRefresh = refreshInFlight;\n if (activeRefresh) await runCleanup('settle the runner refresh', () => activeRefresh);\n const activeHistorySweep = historySweepInFlight;\n if (activeHistorySweep) await runCleanup('settle runner history cleanup', () => activeHistorySweep);\n\n await runCleanup('dispose runner PTYs', () => ptyHost.disposeAll());\n\n let owned: RunnerRecord[] = [];\n if (sessionId) {\n try {\n owned = await registry.listBySession(sessionId);\n } catch (error) {\n process.emitWarning(`Could not list runners during doom-runner shutdown: ${String(error)}`);\n }\n }\n await Promise.all(\n owned.map(async (record) => {\n try {\n const stopped = await stopRunnerProcess(record, launcher, rmuxBackend);\n if (!stopped && processControl.isAlive(record.pid)) {\n process.emitWarning(`Could not stop runner ${record.id} during session shutdown`);\n return;\n }\n await registry.complete(\n record.id,\n {\n reason: STOPPED_REASON,\n code: null,\n signal: stopped ? 'SIGTERM' : null,\n stopReason: 'session ended',\n },\n record.sessionId,\n );\n } catch (error) {\n process.emitWarning(`Could not clean up runner ${record.id}: ${String(error)}`);\n }\n }),\n );\n\n const context = sessionContext;\n const ownedTelemetry = telemetry;\n telemetry = undefined;\n sessionContext = undefined;\n sessionId = undefined;\n rootSessionId = undefined;\n runners = [];\n notifiedRunnerIds.clear();\n pendingPromotedRunnerIds.clear();\n terminalRunners.clear();\n publishBackgroundWork();\n\n await Promise.all([\n runCleanup('dispose the runner lifeline', () => lifeline.dispose()),\n ...(context?.hasUI\n ? [runCleanup('clear the runner status', () => context.ui.setStatus(RUNNER_STATUS_KEY, undefined))]\n : []),\n ]);\n await runCleanup('close the runner registry', () => registry.close());\n if (ownedTelemetry) {\n await runCleanup('record the runner session finish', () =>\n ownedTelemetry.recordEvent('doom_runner.session_finished', { outcome: 'stopped' }),\n );\n await runCleanup('stop runner telemetry', () => ownedTelemetry.shutdown());\n }\n };\n\n /** Stops one of this session's runners; false when no such runner is active. */\n const stopSessionRunner = async (\n generation: number,\n activeSessionId: string,\n id: string,\n reason?: string,\n ): Promise<boolean> => {\n if (!isCurrent(generation, activeSessionId)) return false;\n const record = runners.find((candidate) => candidate.id === id);\n if (!record) return false;\n if (record.backend === RMUX_BACKEND && record.backendTarget) {\n await rmuxBackend.stop(record.backendTarget, record.pid);\n } else await launcher.stop(record.pid);\n if (!isCurrent(generation, activeSessionId)) return true;\n await registry.complete(\n record.id,\n { reason: STOPPED_REASON, code: null, signal: null, stopReason: reason },\n record.sessionId,\n );\n if (isCurrent(generation, activeSessionId)) await refresh();\n return true;\n };\n\n return {\n events: {\n session_compact: createRunnerCompactionRecovery(pi, {\n getSessionId: async () => {\n try {\n await waitForSessionReadiness();\n return sessionId;\n } catch {\n return undefined;\n }\n },\n listBySession: async (activeSessionId) => {\n try {\n await waitForSessionReadiness();\n } catch {\n return [];\n }\n return active ? registry.listBySession(activeSessionId) : [];\n },\n }),\n\n [SESSION_START_EVENT]: (_event, ctx) => {\n if (!active) return;\n unsubscribeRegistry?.();\n unsubscribeRegistry = undefined;\n const context = ctx as ExtensionContext;\n loadRunnerSettings(context);\n const activeSessionId = context.sessionManager.getSessionId();\n const previousSessionId = sessionId;\n const previousContext = sessionContext;\n const generation = ++sessionGeneration;\n sessionId = activeSessionId;\n rootSessionId = resolveRootSessionId(activeSessionId, environment);\n sessionContext = context;\n sessionReady = false;\n lastRunnerCount = undefined;\n runners = [];\n notifiedRunnerIds.clear();\n pendingPromotedRunnerIds.clear();\n terminalRunners.clear();\n publishBackgroundWork();\n\n const initializeSession = async (signal: AbortSignal): Promise<readonly string[]> => {\n const stillCurrent = (): boolean => !signal.aborted && isCurrent(generation, activeSessionId);\n if (!stillCurrent()) return [];\n if (previousSessionId && previousSessionId !== activeSessionId) {\n await runCleanup('dispose the previous session PTYs', () => ptyHost.disposeAll());\n await runCleanup('dispose the previous session lifeline', () => lifeline.dispose());\n if (previousContext?.hasUI) {\n await runCleanup('clear the previous session status', () =>\n previousContext.ui.setStatus(RUNNER_STATUS_KEY, undefined),\n );\n }\n const previousTelemetry = telemetry;\n telemetry = undefined;\n if (previousTelemetry) {\n await runCleanup('stop the previous session telemetry', () => previousTelemetry.shutdown());\n }\n if (!stillCurrent()) return [];\n }\n\n const activeTelemetry = getTelemetry(context);\n await activeTelemetry.recordEvent('doom_runner.session_started', { outcome: 'started' });\n if (!stillCurrent()) return [];\n paths.setSessionId(activeSessionId);\n unsubscribeRegistry = registry.subscribe(() => {\n if (isCurrent(generation, activeSessionId)) scheduleRefresh(false);\n }, activeSessionId);\n // Awaited before anything can launch, so every runner this session starts\n // finds a lifeline it can connect to rather than a socket that is not\n // listening yet, which would read as an owner that is already gone.\n await lifeline.arm(activeSessionId);\n if (!stillCurrent()) return [];\n\n const retained = await registry.listAll(activeSessionId);\n if (!stillCurrent()) return [];\n for (const record of retained) {\n if (record.state === COMPLETED_STATE) notifiedRunnerIds.add(record.id);\n else if (record.promoted) pendingPromotedRunnerIds.add(record.id);\n }\n const legacy = await cleanupLegacyRunnerStore({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n paths,\n });\n if (!stillCurrent()) return [];\n const reconciled = await reconcileActiveRunners({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n startup: true,\n });\n if (!stillCurrent()) return [];\n sessionReady = true;\n await refresh(false);\n if (!stillCurrent()) return [];\n scheduleHistorySweep();\n const errors = [...legacy.errors, ...reconciled.errors];\n const reclaimedCount = legacy.reclaimed.length + reconciled.reclaimed.length;\n if (reclaimedCount > 0 && context.hasUI) {\n context.ui.notify(`Reclaimed ${reclaimedCount} stale runner record(s)`, 'warning');\n }\n await activeTelemetry.recordEvent('doom_runner.reconciled', {\n 'runner.reclaimed_count': reclaimedCount,\n 'runner.error_count': errors.length,\n outcome: errors.length === 0 ? 'completed' : 'degraded',\n });\n return errors;\n };\n\n const previousInitialization = sessionInitialization.catch(() => undefined);\n const startReadiness = async (): Promise<void> => {\n await previousInitialization;\n if (!isCurrent(generation, activeSessionId)) return;\n const coordinator =\n (cordis ? readDoomReadinessCoordinator(cordis) : undefined) ??\n (fallbackReadiness ??= createDoomReadinessCoordinator({\n notify: (notification) => {\n process.emitWarning(\n `${notification.packageId} initialization ${notification.state}: ${notification.error?.message ?? notification.diagnostics.join('; ')}`,\n );\n },\n }));\n const handle = coordinator.start(LEADER_SOURCE, `${activeSessionId}:${generation}`, async (signal) => ({\n value: undefined,\n diagnostics: await initializeSession(signal),\n }));\n await handle.wait();\n };\n const operation = startReadiness();\n sessionInitialization = operation;\n // The coordinator reports a failed generation once; this branch only marks\n // the detached waiter handled so Pi is not held open by the notification path.\n void trackOperation(operation).catch(() => undefined);\n },\n },\n command: [\n COMMAND_NAME,\n {\n description: COMMAND_DESCRIPTION,\n handler: async (args, ctx) => {\n if (!active) return;\n const generation = sessionGeneration;\n const activeSessionId = sessionId;\n if (!activeSessionId) return;\n const request = parseRunnersCommand(args);\n // The stop verb is how a client without an overlay (the web cockpit)\n // controls a runner, so it must not need the interactive UI.\n if (request.kind === 'stop') {\n if (!request.id) {\n ctx.ui.notify(ERR_STOP_USAGE, 'error');\n return;\n }\n await waitForSessionReadiness();\n await refresh();\n if (!isCurrent(generation, activeSessionId)) return;\n const stopped = await stopSessionRunner(generation, activeSessionId, request.id, request.reason);\n if (!isCurrent(generation, activeSessionId)) return;\n if (stopped) ctx.ui.notify(`Stopped runner ${request.id}.`, 'info');\n else ctx.ui.notify(`No active runner ${request.id} in this session.`, 'error');\n return;\n }\n // Starting headlessly is how a client without the bash tool (the web\n // cockpit) puts a command up. It is background by construction: a\n // foreground wait has nobody here to wait for it.\n if (request.kind === 'start') {\n if (!request.command) {\n ctx.ui.notify(ERR_START_USAGE, 'error');\n return;\n }\n await waitForSessionReadiness();\n if (!isCurrent(generation, activeSessionId)) return;\n const started = await trackedBashRunService.run({\n command: request.command,\n sessionId: activeSessionId,\n background: true,\n ...(request.cwd ? { cwd: request.cwd } : {}),\n ...(request.name ? { name: request.name } : {}),\n ...(request.interactive ? { interactive: true } : {}),\n });\n if (!isCurrent(generation, activeSessionId)) return;\n await refresh();\n if (started.kind === 'failed') ctx.ui.notify(`Could not start a runner: ${started.error}`, 'error');\n else ctx.ui.notify(`Started runner ${started.name}.`, 'info');\n return;\n }\n if (!ctx.hasUI) {\n ctx.ui.notify(ERR_REQUIRES_INTERACTIVE, 'error');\n return;\n }\n await waitForSessionReadiness();\n await refresh();\n if (!activeSessionId || !isCurrent(generation, activeSessionId)) return;\n await openRunnerSpace(ctx, {\n getRunners: () => (isCurrent(generation, activeSessionId) ? runners : []),\n getPtyRun: (name) =>\n isCurrent(generation, activeSessionId) ? (rmuxBackend.get(name) ?? ptyHost.get(name)) : undefined,\n readLog: (logPath) =>\n isCurrent(generation, activeSessionId) ? logReader.read(logPath, { lines: 1_000 }).text : '',\n stopRunner: async (id, reason) => {\n await stopSessionRunner(generation, activeSessionId, id, reason);\n },\n });\n },\n },\n ],\n bashTool: {\n bashRunService: trackedBashRunService,\n getSessionId: async () => {\n await waitForSessionReadiness();\n if (!sessionId) throw new Error('doom-runner requires an active Pi session');\n return sessionId;\n },\n onRunnerStarted: (id) => {\n if (!active || !sessionReady) return;\n pendingPromotedRunnerIds.add(id);\n publishBackgroundWork();\n scheduleRefresh(false);\n },\n summarizeLog,\n },\n plugin(context) {\n cordis = context;\n context.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n const contribution = requireDoomUiHub(uiContext).registerFooter({\n source: LEADER_SOURCE,\n id: 'runner-count',\n order: RUNNER_FOOTER_ORDER,\n });\n footerContribution = contribution;\n return () => {\n contribution.dispose();\n if (footerContribution === contribution) footerContribution = undefined;\n };\n });\n context.inject([DOOM_BACKGROUND_WORK_SERVICE], (serviceContext) => {\n const service = readDoomBackgroundWorkService(serviceContext);\n if (!service) return undefined;\n const registration = service.register({\n provider: BACKGROUND_WORK_PROVIDER,\n listActiveWork: () => backgroundWorkItems,\n });\n backgroundWorkProvider = registration;\n return () => {\n registration.dispose();\n if (backgroundWorkProvider === registration) backgroundWorkProvider = undefined;\n };\n });\n context.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n const contribution = requireDoomUiHub(uiContext).registerLeader({\n source: LEADER_SOURCE,\n bindings: [\n {\n id: 'runners.open',\n path: [\n { key: 'r', label: 'runners', detail: 'background processes', order: LEADER_GROUP_ORDER },\n { key: 'l', label: 'list', detail: 'runners in this session' },\n ],\n command: { name: COMMAND_NAME },\n },\n ],\n });\n return () => contribution.dispose();\n });\n },\n start() {\n registry = container.runnerRegistry;\n launcher = container.launcher;\n rmuxBackend = container.rmuxBackend;\n logReader = container.logReader;\n ptyHost = container.ptyHost;\n bashRunService = container.bashRunService;\n paths = container.paths;\n processControl = container.processControl;\n lifeline = container.lifeline;\n initialized = true;\n statusPoll = setInterval(() => scheduleRefresh(true), RUNNER_STATUS_POLL_MS);\n statusPoll.unref?.();\n historySweepPoll = setInterval(() => scheduleHistorySweep(), HISTORY_SWEEP_INTERVAL_MS);\n historySweepPoll.unref?.();\n },\n async stop() {\n if (initialized) await shutdownRuntime();\n else registry?.close();\n cordis = undefined;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DA,SAAS,mBAAmB,SAAiC;CAC3D,IAAI;EACF,MAAM,UAAU,QAAQ,mBAAmB,KAAK;EAChD,MAAM,EAAE,UAAU,WAAW,IAAI,qBAAqB,CAAC,CAAC,KAAK,QAAQ,KAAK,OAAO;EACjF,kBAAkB,QAAQ;EAG1B,KAAK,MAAM,SAAS,QAAQ,QAAQ,YAAY,GAAG,qBAAqB,IAAI,OAAO;CACrF,SAAS,OAAO;EACd,QAAQ,YAAY,kBAAkB,qBAAqB,IAAI,OAAO,KAAK,GAAG;EAC9E,kBAAkB,CAAC,CAAC;CACtB;AACF;;;;;AAMA,SAAgB,oBAAoB,IAAiC;CACnE,IAAI;CACJ,IAAI,cAAc;CAClB,MAAM,cAAc,OAAO,OAAO,EAAE,GAAG,QAAQ,IAAI,CAAC;CACpD,MAAM,YAAY,yBAAyB,EAAE,YAAY,CAAC;CAC1D,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,IAAI,SAAS;CACb,IAAI,oBAAoB;CACxB,IAAI;CACJ,IAAI;CACJ,IAAI,UAA0B,CAAC;CAC/B,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI,eAAe;CACnB,IAAI,WAAW;CACf,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI,wBAAuC,QAAQ,QAAQ;CAC3D,IAAI;CACJ,IAAI,gBAAgB;CACpB,IAAI,uBAAuB;CAC3B,IAAI;CACJ,MAAM,oCAAoB,IAAI,IAAY;CAC1C,MAAM,2CAA2B,IAAI,IAAY;CACjD,MAAM,kCAAkB,IAAI,IAA0B;CACtD,IAAI,sBAAoD,CAAC;CACzD,IAAI;CACJ,MAAM,oCAAoB,IAAI,IAAsB;CACpD,MAAM,kBAAqB,cAAsC;EAC/D,kBAAkB,IAAI,SAAS;EAC/B,UAAe,WACP,kBAAkB,OAAO,SAAS,SAClC,kBAAkB,OAAO,SAAS,CAC1C;EACA,OAAO;CACT;CACA,MAAM,0BAA0B,YAA2B;EACzD,MAAM;EACN,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,WAC/B,MAAM,IAAI,MAAM,2CAA2C;CAE/D;CACA,MAAM,wBAAyC,EAC7C,KAAK,OAAO,YAAY;EACtB,MAAM,wBAAwB;EAC9B,OAAO,eAAe,eAAe,IAAI,OAAO,CAAC;CACnD,EACF;CACA,MAAM,aAAa,YAAoB,oBAAoB,cACzD,UAAU,CAAC,YAAY,eAAe,qBAAqB,sBAAsB;CACnF,MAAM,gBAAgB,QAAyC;EAC7D,cAAc,oBAAoB;GAChC,aAAa;GACb,aAAa;GACb,KAAK,IAAI;GACT,KAAK;GACL,YAAY;GACZ,cAAc;EAChB,CAAC;EACD,OAAO;CACT;CACA,MAAM,8BAAoC;EACxC,MAAM,kBAAkB;EACxB,MAAM,iCAAiB,IAAI,IAAI,CAC7B,GAAG,QAAQ,QAAQ,WAAW,OAAO,QAAQ,CAAC,CAAC,KAAK,WAAW,OAAO,EAAE,GACxE,GAAG,gBAAgB,KAAK,CAC1B,CAAC;EACD,MAAM,OAAO,kBACT;GACE,GAAG,QACA,QAAQ,WAAW,OAAO,cAAc,mBAAmB,OAAO,QAAQ,CAAC,CAC3E,KAAK,YAAY;IAChB,IAAI,OAAO;IACX,WAAW,OAAO;IAClB,OAAO,OAAO;IACd,QAAQ,OAAO;GACjB,EAAE;GACJ,GAAG,CAAC,GAAG,gBAAgB,OAAO,CAAC,CAAC,CAC7B,QAAQ,WAAW,OAAO,cAAc,eAAe,CAAC,CACxD,KAAK,YAAY;IAChB,IAAI,OAAO;IACX,WAAW,OAAO;IAClB,OAAO,OAAO;IACd,QAAQ,OAAO;GACjB,EAAE;GACJ,GAAG,CAAC,GAAG,wBAAwB,CAAC,CAC7B,QAAQ,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,CACvC,KAAK,QAAQ;IAAE;IAAI,WAAW;IAAiB,QAAQ;GAAU,EAAE;EACxE,IACA,CAAC;EACL,IAAI,KAAK,UAAU,IAAI,MAAM,KAAK,UAAU,mBAAmB,GAAG;EAClE,sBAAsB;EACtB,wBAAwB,OAAO;CACjC;;CAEA,MAAM,aAAa,OAAO,oBAA4C;EACpE,MAAM,kBAAkB;EACxB,MAAM,aAAa;EACnB,IAAI,CAAC,mBAAmB,CAAC,UAAU,YAAY,eAAe,GAAG;EAEjE,MAAM,gBAAgB,MAAM,SAAS,KAAK;EAC1C,IAAI,CAAC,UAAU,YAAY,eAAe,GAAG;EAC7C,IAAI,gBAAgB;EACpB,IAAI,iBAAiB;GACnB,MAAM,aAAa,MAAM,uBAAuB;IAC9C;IACA;IACA;IACA;IACA,gBAAgB,QAAQ;IACxB,SAAS;IACT,QAAQ;GACV,CAAC;GACD,KAAK,MAAM,SAAS,WAAW,QAAQ,QAAQ,YAAY,KAAK;GAChE,IAAI,WAAW,UAAU,SAAS,GAAG;IACnC,MAAM,eAAe,IAAI,IAAI,WAAW,SAAS;IACjD,gBAAgB,cAAc,QAAQ,WAAW,CAAC,aAAa,IAAI,OAAO,EAAE,CAAC;GAC/E;EACF;EACA,IAAI,CAAC,UAAU,YAAY,eAAe,GAAG;EAE7C,UAAU,cAAc,QAAQ,WAAW,OAAO,cAAc,eAAe;EAI/E,MAAM,eAHc,gBAChB,cAAc,QAAQ,YAAY,OAAO,iBAAiB,OAAO,eAAe,aAAa,IAC7F,CAAC,EAAA,CAC2B;EAChC,IAAI,oBAAoB,aAAa;GACnC,kBAAkB;GAClB,oBAAoB,OAAO,+BAA+B,WAAW,CAAC;GACtE,IAAI,gBAAgB,OAAO,eAAe,GAAG,UAAU,mBAAmB,mBAAmB,WAAW,CAAC;EAC3G;EAEA,MAAM,aAAa,CAAC,GAAG,wBAAwB;EAC/C,MAAM,YAAY,MAAM,QAAQ,IAAI,WAAW,KAAK,OAAO,SAAS,IAAI,IAAI,eAAe,CAAC,CAAC;EAC7F,IAAI,CAAC,UAAU,YAAY,eAAe,GAAG;EAC7C,KAAK,MAAM,CAAC,OAAO,WAAW,UAAU,QAAQ,GAAG;GACjD,MAAM,KAAK,WAAW;GACtB,IAAI,CAAC,IAAI;GACT,IAAI,CAAC,UAAU,OAAO,cAAc,iBAAiB;IACnD,yBAAyB,OAAO,EAAE;IAClC,gBAAgB,OAAO,EAAE;IACzB,UAAU,QAAQ,QAAQ,cAAc,UAAU,OAAO,EAAE;IAC3D;GACF;GACA,IAAI,OAAO,UAAA,aAA2B;IACpC,UAAU,QAAQ,QAAQ,cAAc,UAAU,OAAO,OAAO,EAAE;IAClE,gBAAgB,IAAI,OAAO,IAAI,MAAM;GACvC;EACF;EACA,sBAAsB;EACtB,KAAK,MAAM,UAAU,WAAW;GAC9B,IAAI,CAAC,UAAU,OAAO,cAAc,mBAAmB,OAAO,UAAA,aAA2B;GACzF,IAAI,kBAAkB,IAAI,OAAO,EAAE,GAAG;GACtC,MAAM,UAAU,OAAO,MAAM,UAAA;GAC7B,MAAM,OACJ,OAAO,MAAM,SAAS,QAAQ,OAAO,MAAM,SAAS,KAAA,IAAY,KAAK,eAAe,OAAO,KAAK;GAClG,MAAM,UAAU;IACd,qBAAqB,OAAO,KAAK,WAAW,UAAU,KAAK;IAC3D,cAAc,OAAO;IACrB,QAAQ,OAAO;IACf,6BAA6B,OAAO;GACtC,CAAC,CAAC,KAAK,IAAI;GACX,GAAG,YACD;IAAE,YAAY;IAAyB;IAAS,SAAS;GAAK,GAC9D;IAAE,aAAa;IAAM,WAAW;GAAQ,CAC1C;GACA,kBAAkB,IAAI,OAAO,EAAE;GAC/B,yBAAyB,OAAO,OAAO,EAAE;GACzC,gBAAgB,OAAO,OAAO,EAAE;GAChC,sBAAsB;GACtB,IAAI,gBACF,eACE,aAAa,cAAc,CAAC,CAAC,YAAY,gCAAgC;IACvE,SAAS;IACT,oBAAoB,OAAO,MAAM,QAAQ;IACzC,kBAAkB,OAAO;IACzB,GAAI,OAAO,SAAS,KAAK,MAAM,OAAO,SAAS,CAAC,IAC5C,EAAE,aAAa,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,MAAM,OAAO,SAAS,CAAC,EAAE,IACtE,CAAC;GACP,CAAC,CACH;EAEJ;CACF;;CAGA,MAAM,WAAW,kBAAkB,SAAwB;EACzD,IAAI,CAAC,aAAa,CAAC,gBAAgB,UAAU,OAAO,QAAQ,QAAQ;EACpE,IAAI,iBAAiB;GACnB,gBAAgB;GAChB,yBAAyB;GACzB,OAAO;EACT;EAEA,MAAM,aAAa,YAAY;GAC7B,IAAI,gBAAgB;GACpB,GAAG;IACD,gBAAgB;IAChB,uBAAuB;IACvB,MAAM,WAAW,aAAa;IAC9B,gBAAgB;GAClB,SAAS,iBAAiB,CAAC;EAC7B,EAAA,CAAG,CAAC,CAAC,cAAc;GACjB,IAAI,oBAAoB,WAAW,kBAAkB,KAAA;EACvD,CAAC;EACD,kBAAkB;EAClB,OAAO;CACT;CAEA,MAAM,sBAAsB,UAAyB;EACnD,IAAI,UAAU;EACd,IAAI,gBACF,eAAoB,aAAa,cAAc,CAAC,CAAC,YAAY,8BAA8B,KAAK,CAAC;EAEnG,QAAQ,YAAY,kCAAkC,OAAO,KAAK,GAAG;CACvE;CACA,MAAM,mBAAmB,oBAAmC;EAC1D,QAAa,eAAe,CAAC,CAAC,MAAM,kBAAkB;CACxD;CACA,MAAM,6BAAmC;EACvC,IAAI,qBAAqB,wBAAwB,UAAU;EAC3D,oBAAoB,mBAAmB;GACrC,oBAAoB,KAAA;GACpB,IAAI,UAAU;GACd,MAAM,aAAa,YAAY;IAC7B,MAAM,QAAQ,MAAM,oBAChB,MAAM,MAAM,kBAAkB,YAAY,CAAC,IAC3C,MAAM,aAAa,YAAY,CAAC;IACpC,KAAK,MAAM,SAAS,MAAM,QAAQ,QAAQ,YAAY,KAAK;GAC7D,EAAA,CAAG,CAAC,CACD,OAAO,UAAU,QAAQ,YAAY,wCAAwC,OAAO,KAAK,GAAG,CAAC,CAAC,CAC9F,cAAc;IACb,IAAI,yBAAyB,WAAW,uBAAuB,KAAA;GACjE,CAAC;GACH,uBAAuB;EACzB,CAAC;EACD,kBAAkB,QAAQ;CAC5B;CAEA,MAAM,aAAa,OAAO,OAAe,YAAuD;EAC9F,IAAI;GACF,MAAM,QAAQ;EAChB,SAAS,OAAO;GACd,QAAQ,YAAY,iCAAiC,MAAM,IAAI,OAAO,KAAK,GAAG;EAChF;CACF;CAEA,MAAM,kBAAkB,YAA2B;EACjD,IAAI,UAAU;EACd,SAAS;EACT,WAAW;EACX,qBAAqB;EACrB,eAAe;EACf,IAAI,YAAY,cAAc,UAAU;EACxC,aAAa,KAAA;EACb,IAAI,kBAAkB,cAAc,gBAAgB;EACpD,mBAAmB,KAAA;EACnB,IAAI,mBAAmB,eAAe,iBAAiB;EACvD,oBAAoB,KAAA;EACpB,MAAM,cAAc;EACpB,sBAAsB,KAAA;EACtB,IAAI,aAAa,MAAM,WAAW,wCAAwC,WAAW;EAErF,MAAM,iBAAiB;EACvB,oBAAoB,KAAA;EACpB,IAAI,gBAAgB,MAAM,WAAW,0CAA0C,eAAe,QAAQ,CAAC;EACvG,MAAM,QAAQ,WAAW,iBAAiB;EAC1C,MAAM,gBAAgB;EACtB,IAAI,eAAe,MAAM,WAAW,mCAAmC,aAAa;EACpF,MAAM,qBAAqB;EAC3B,IAAI,oBAAoB,MAAM,WAAW,uCAAuC,kBAAkB;EAElG,MAAM,WAAW,6BAA6B,QAAQ,WAAW,CAAC;EAElE,IAAI,QAAwB,CAAC;EAC7B,IAAI,WACF,IAAI;GACF,QAAQ,MAAM,SAAS,cAAc,SAAS;EAChD,SAAS,OAAO;GACd,QAAQ,YAAY,uDAAuD,OAAO,KAAK,GAAG;EAC5F;EAEF,MAAM,QAAQ,IACZ,MAAM,IAAI,OAAO,WAAW;GAC1B,IAAI;IACF,MAAM,UAAU,MAAM,kBAAkB,QAAQ,UAAU,WAAW;IACrE,IAAI,CAAC,WAAW,eAAe,QAAQ,OAAO,GAAG,GAAG;KAClD,QAAQ,YAAY,yBAAyB,OAAO,GAAG,yBAAyB;KAChF;IACF;IACA,MAAM,SAAS,SACb,OAAO,IACP;KACE,QAAQ;KACR,MAAM;KACN,QAAQ,UAAU,YAAY;KAC9B,YAAY;IACd,GACA,OAAO,SACT;GACF,SAAS,OAAO;IACd,QAAQ,YAAY,6BAA6B,OAAO,GAAG,IAAI,OAAO,KAAK,GAAG;GAChF;EACF,CAAC,CACH;EAEA,MAAM,UAAU;EAChB,MAAM,iBAAiB;EACvB,YAAY,KAAA;EACZ,iBAAiB,KAAA;EACjB,YAAY,KAAA;EACZ,gBAAgB,KAAA;EAChB,UAAU,CAAC;EACX,kBAAkB,MAAM;EACxB,yBAAyB,MAAM;EAC/B,gBAAgB,MAAM;EACtB,sBAAsB;EAEtB,MAAM,QAAQ,IAAI,CAChB,WAAW,qCAAqC,SAAS,QAAQ,CAAC,GAClE,GAAI,SAAS,QACT,CAAC,WAAW,iCAAiC,QAAQ,GAAG,UAAU,mBAAmB,KAAA,CAAS,CAAC,CAAC,IAChG,CAAC,CACP,CAAC;EACD,MAAM,WAAW,mCAAmC,SAAS,MAAM,CAAC;EACpE,IAAI,gBAAgB;GAClB,MAAM,WAAW,0CACf,eAAe,YAAY,gCAAgC,EAAE,SAAS,UAAU,CAAC,CACnF;GACA,MAAM,WAAW,+BAA+B,eAAe,SAAS,CAAC;EAC3E;CACF;;CAGA,MAAM,oBAAoB,OACxB,YACA,iBACA,IACA,WACqB;EACrB,IAAI,CAAC,UAAU,YAAY,eAAe,GAAG,OAAO;EACpD,MAAM,SAAS,QAAQ,MAAM,cAAc,UAAU,OAAO,EAAE;EAC9D,IAAI,CAAC,QAAQ,OAAO;EACpB,IAAI,OAAO,YAAA,UAA4B,OAAO,eAC5C,MAAM,YAAY,KAAK,OAAO,eAAe,OAAO,GAAG;OAClD,MAAM,SAAS,KAAK,OAAO,GAAG;EACrC,IAAI,CAAC,UAAU,YAAY,eAAe,GAAG,OAAO;EACpD,MAAM,SAAS,SACb,OAAO,IACP;GAAE,QAAQ;GAAgB,MAAM;GAAM,QAAQ;GAAM,YAAY;EAAO,GACvE,OAAO,SACT;EACA,IAAI,UAAU,YAAY,eAAe,GAAG,MAAM,QAAQ;EAC1D,OAAO;CACT;CAEA,OAAO;EACL,QAAQ;GACN,iBAAiB,+BAA+B,IAAI;IAClD,cAAc,YAAY;KACxB,IAAI;MACF,MAAM,wBAAwB;MAC9B,OAAO;KACT,QAAQ;MACN;KACF;IACF;IACA,eAAe,OAAO,oBAAoB;KACxC,IAAI;MACF,MAAM,wBAAwB;KAChC,QAAQ;MACN,OAAO,CAAC;KACV;KACA,OAAO,SAAS,SAAS,cAAc,eAAe,IAAI,CAAC;IAC7D;GACF,CAAC;IAEA,uBAAuB,QAAQ,QAAQ;IACtC,IAAI,CAAC,QAAQ;IACb,sBAAsB;IACtB,sBAAsB,KAAA;IACtB,MAAM,UAAU;IAChB,mBAAmB,OAAO;IAC1B,MAAM,kBAAkB,QAAQ,eAAe,aAAa;IAC5D,MAAM,oBAAoB;IAC1B,MAAM,kBAAkB;IACxB,MAAM,aAAa,EAAE;IACrB,YAAY;IACZ,gBAAgB,qBAAqB,iBAAiB,WAAW;IACjE,iBAAiB;IACjB,eAAe;IACf,kBAAkB,KAAA;IAClB,UAAU,CAAC;IACX,kBAAkB,MAAM;IACxB,yBAAyB,MAAM;IAC/B,gBAAgB,MAAM;IACtB,sBAAsB;IAEtB,MAAM,oBAAoB,OAAO,WAAoD;KACnF,MAAM,qBAA8B,CAAC,OAAO,WAAW,UAAU,YAAY,eAAe;KAC5F,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;KAC7B,IAAI,qBAAqB,sBAAsB,iBAAiB;MAC9D,MAAM,WAAW,2CAA2C,QAAQ,WAAW,CAAC;MAChF,MAAM,WAAW,+CAA+C,SAAS,QAAQ,CAAC;MAClF,IAAI,iBAAiB,OACnB,MAAM,WAAW,2CACf,gBAAgB,GAAG,UAAU,mBAAmB,KAAA,CAAS,CAC3D;MAEF,MAAM,oBAAoB;MAC1B,YAAY,KAAA;MACZ,IAAI,mBACF,MAAM,WAAW,6CAA6C,kBAAkB,SAAS,CAAC;MAE5F,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;KAC/B;KAEA,MAAM,kBAAkB,aAAa,OAAO;KAC5C,MAAM,gBAAgB,YAAY,+BAA+B,EAAE,SAAS,UAAU,CAAC;KACvF,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;KAC7B,MAAM,aAAa,eAAe;KAClC,sBAAsB,SAAS,gBAAgB;MAC7C,IAAI,UAAU,YAAY,eAAe,GAAG,gBAAgB,KAAK;KACnE,GAAG,eAAe;KAIlB,MAAM,SAAS,IAAI,eAAe;KAClC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;KAE7B,MAAM,WAAW,MAAM,SAAS,QAAQ,eAAe;KACvD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;KAC7B,KAAK,MAAM,UAAU,UACnB,IAAI,OAAO,UAAA,aAA2B,kBAAkB,IAAI,OAAO,EAAE;UAChE,IAAI,OAAO,UAAU,yBAAyB,IAAI,OAAO,EAAE;KAElE,MAAM,SAAS,MAAM,yBAAyB;MAC5C;MACA;MACA;MACA;MACA,gBAAgB,QAAQ;MACxB;KACF,CAAC;KACD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;KAC7B,MAAM,aAAa,MAAM,uBAAuB;MAC9C;MACA;MACA;MACA;MACA,gBAAgB,QAAQ;MACxB,SAAS;KACX,CAAC;KACD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;KAC7B,eAAe;KACf,MAAM,QAAQ,KAAK;KACnB,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;KAC7B,qBAAqB;KACrB,MAAM,SAAS,CAAC,GAAG,OAAO,QAAQ,GAAG,WAAW,MAAM;KACtD,MAAM,iBAAiB,OAAO,UAAU,SAAS,WAAW,UAAU;KACtE,IAAI,iBAAiB,KAAK,QAAQ,OAChC,QAAQ,GAAG,OAAO,aAAa,eAAe,0BAA0B,SAAS;KAEnF,MAAM,gBAAgB,YAAY,0BAA0B;MAC1D,0BAA0B;MAC1B,sBAAsB,OAAO;MAC7B,SAAS,OAAO,WAAW,IAAI,cAAc;KAC/C,CAAC;KACD,OAAO;IACT;IAEA,MAAM,yBAAyB,sBAAsB,YAAY,KAAA,CAAS;IAC1E,MAAM,iBAAiB,YAA2B;KAChD,MAAM;KACN,IAAI,CAAC,UAAU,YAAY,eAAe,GAAG;KAc7C,QAZG,SAAS,6BAA6B,MAAM,IAAI,KAAA,OAChD,sBAAsB,+BAA+B,EACpD,SAAS,iBAAiB;MACxB,QAAQ,YACN,GAAG,aAAa,UAAU,kBAAkB,aAAa,MAAM,IAAI,aAAa,OAAO,WAAW,aAAa,YAAY,KAAK,IAAI,GACtI;KACF,EACF,CAAC,GAAA,CACwB,MAAM,eAAe,GAAG,gBAAgB,GAAG,cAAc,OAAO,YAAY;MACrG,OAAO,KAAA;MACP,aAAa,MAAM,kBAAkB,MAAM;KAC7C,EACW,CAAC,CAAC,KAAK;IACpB;IACA,MAAM,YAAY,eAAe;IACjC,wBAAwB;IAGxB,eAAoB,SAAS,CAAC,CAAC,YAAY,KAAA,CAAS;GACtD;EACF;EACA,SAAS,CACP,cACA;GACE,aAAa;GACb,SAAS,OAAO,MAAM,QAAQ;IAC5B,IAAI,CAAC,QAAQ;IACb,MAAM,aAAa;IACnB,MAAM,kBAAkB;IACxB,IAAI,CAAC,iBAAiB;IACtB,MAAM,UAAU,oBAAoB,IAAI;IAGxC,IAAI,QAAQ,SAAS,QAAQ;KAC3B,IAAI,CAAC,QAAQ,IAAI;MACf,IAAI,GAAG,OAAO,gBAAgB,OAAO;MACrC;KACF;KACA,MAAM,wBAAwB;KAC9B,MAAM,QAAQ;KACd,IAAI,CAAC,UAAU,YAAY,eAAe,GAAG;KAC7C,MAAM,UAAU,MAAM,kBAAkB,YAAY,iBAAiB,QAAQ,IAAI,QAAQ,MAAM;KAC/F,IAAI,CAAC,UAAU,YAAY,eAAe,GAAG;KAC7C,IAAI,SAAS,IAAI,GAAG,OAAO,kBAAkB,QAAQ,GAAG,IAAI,MAAM;UAC7D,IAAI,GAAG,OAAO,oBAAoB,QAAQ,GAAG,oBAAoB,OAAO;KAC7E;IACF;IAIA,IAAI,QAAQ,SAAS,SAAS;KAC5B,IAAI,CAAC,QAAQ,SAAS;MACpB,IAAI,GAAG,OAAO,iBAAiB,OAAO;MACtC;KACF;KACA,MAAM,wBAAwB;KAC9B,IAAI,CAAC,UAAU,YAAY,eAAe,GAAG;KAC7C,MAAM,UAAU,MAAM,sBAAsB,IAAI;MAC9C,SAAS,QAAQ;MACjB,WAAW;MACX,YAAY;MACZ,GAAI,QAAQ,MAAM,EAAE,KAAK,QAAQ,IAAI,IAAI,CAAC;MAC1C,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;MAC7C,GAAI,QAAQ,cAAc,EAAE,aAAa,KAAK,IAAI,CAAC;KACrD,CAAC;KACD,IAAI,CAAC,UAAU,YAAY,eAAe,GAAG;KAC7C,MAAM,QAAQ;KACd,IAAI,QAAQ,SAAS,UAAU,IAAI,GAAG,OAAO,6BAA6B,QAAQ,SAAS,OAAO;UAC7F,IAAI,GAAG,OAAO,kBAAkB,QAAQ,KAAK,IAAI,MAAM;KAC5D;IACF;IACA,IAAI,CAAC,IAAI,OAAO;KACd,IAAI,GAAG,OAAO,0BAA0B,OAAO;KAC/C;IACF;IACA,MAAM,wBAAwB;IAC9B,MAAM,QAAQ;IACd,IAAI,CAAC,mBAAmB,CAAC,UAAU,YAAY,eAAe,GAAG;IACjE,MAAM,gBAAgB,KAAK;KACzB,kBAAmB,UAAU,YAAY,eAAe,IAAI,UAAU,CAAC;KACvE,YAAY,SACV,UAAU,YAAY,eAAe,IAAK,YAAY,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,IAAK,KAAA;KAC1F,UAAU,YACR,UAAU,YAAY,eAAe,IAAI,UAAU,KAAK,SAAS,EAAE,OAAO,IAAM,CAAC,CAAC,CAAC,OAAO;KAC5F,YAAY,OAAO,IAAI,WAAW;MAChC,MAAM,kBAAkB,YAAY,iBAAiB,IAAI,MAAM;KACjE;IACF,CAAC;GACH;EACF,CACF;EACA,UAAU;GACR,gBAAgB;GAChB,cAAc,YAAY;IACxB,MAAM,wBAAwB;IAC9B,IAAI,CAAC,WAAW,MAAM,IAAI,MAAM,2CAA2C;IAC3E,OAAO;GACT;GACA,kBAAkB,OAAO;IACvB,IAAI,CAAC,UAAU,CAAC,cAAc;IAC9B,yBAAyB,IAAI,EAAE;IAC/B,sBAAsB;IACtB,gBAAgB,KAAK;GACvB;GACA;EACF;EACA,OAAO,SAAS;GACd,SAAS;GACT,QAAQ,OAAO,CAAC,mBAAmB,IAAI,cAAc;IACnD,MAAM,eAAe,iBAAiB,SAAS,CAAC,CAAC,eAAe;KAC9D,QAAQ;KACR,IAAI;KACJ,OAAA;IACF,CAAC;IACD,qBAAqB;IACrB,aAAa;KACX,aAAa,QAAQ;KACrB,IAAI,uBAAuB,cAAc,qBAAqB,KAAA;IAChE;GACF,CAAC;GACD,QAAQ,OAAO,CAAC,4BAA4B,IAAI,mBAAmB;IACjE,MAAM,UAAU,8BAA8B,cAAc;IAC5D,IAAI,CAAC,SAAS,OAAO,KAAA;IACrB,MAAM,eAAe,QAAQ,SAAS;KACpC,UAAU;KACV,sBAAsB;IACxB,CAAC;IACD,yBAAyB;IACzB,aAAa;KACX,aAAa,QAAQ;KACrB,IAAI,2BAA2B,cAAc,yBAAyB,KAAA;IACxE;GACF,CAAC;GACD,QAAQ,OAAO,CAAC,mBAAmB,IAAI,cAAc;IACnD,MAAM,eAAe,iBAAiB,SAAS,CAAC,CAAC,eAAe;KAC9D,QAAQ;KACR,UAAU,CACR;MACE,IAAI;MACJ,MAAM,CACJ;OAAE,KAAK;OAAK,OAAO;OAAW,QAAQ;OAAwB,OAAA;MAA0B,GACxF;OAAE,KAAK;OAAK,OAAO;OAAQ,QAAQ;MAA0B,CAC/D;MACA,SAAS,EAAE,MAAM,aAAa;KAChC,CACF;IACF,CAAC;IACD,aAAa,aAAa,QAAQ;GACpC,CAAC;EACH;EACA,QAAQ;GACN,WAAW,UAAU;GACrB,WAAW,UAAU;GACrB,cAAc,UAAU;GACxB,YAAY,UAAU;GACtB,UAAU,UAAU;GACpB,iBAAiB,UAAU;GAC3B,QAAQ,UAAU;GAClB,iBAAiB,UAAU;GAC3B,WAAW,UAAU;GACrB,cAAc;GACd,aAAa,kBAAkB,gBAAgB,IAAI,GAAA,GAAwB;GAC3E,WAAW,QAAQ;GACnB,mBAAmB,kBAAkB,qBAAqB,GAAG,yBAAyB;GACtF,iBAAiB,QAAQ;EAC3B;EACA,MAAM,OAAO;GACX,IAAI,aAAa,MAAM,gBAAgB;QAClC,UAAU,MAAM;GACrB,SAAS,KAAA;EACX;CACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/doompi-runner",
3
- "version": "0.0.1-alpha.76",
3
+ "version": "0.0.1-alpha.78",
4
4
  "description": "Supervised shell execution, background process control, and run logs for Pi coding agents.",
5
5
  "keywords": [
6
6
  "ai",
@@ -233,11 +233,11 @@
233
233
  "registry": "https://registry.npmjs.org/"
234
234
  },
235
235
  "dependencies": {
236
- "@agimon-ai/doompi-core": "0.0.1-alpha.76",
237
- "@agimon-ai/doompi-telemetry": "0.0.1-alpha.73",
238
- "@agimon-ai/doompi-ui": "0.0.1-alpha.76",
239
- "@agimon-ai/doompi-web-components": "0.0.1-alpha.34",
240
- "@agimon-ai/doompi-web-security": "0.0.1-alpha.36",
236
+ "@agimon-ai/doompi-core": "0.0.1-alpha.78",
237
+ "@agimon-ai/doompi-telemetry": "0.0.1-alpha.75",
238
+ "@agimon-ai/doompi-ui": "0.0.1-alpha.78",
239
+ "@agimon-ai/doompi-web-components": "0.0.1-alpha.36",
240
+ "@agimon-ai/doompi-web-security": "0.0.1-alpha.38",
241
241
  "@agimon-ai/foundation-process-registry": "0.29.25",
242
242
  "@deepseek-ai/cordis": "4.0.2",
243
243
  "@rmux/sdk": "0.6.5",
@@ -246,9 +246,9 @@
246
246
  "typebox": "1.3.30"
247
247
  },
248
248
  "devDependencies": {
249
- "@agimon-ai/doompi-build": "0.0.1-alpha.5",
250
- "@earendil-works/pi-coding-agent": "0.85.1",
251
- "@earendil-works/pi-tui": "0.85.1",
249
+ "@agimon-ai/doompi-build": "0.0.1-alpha.7",
250
+ "@earendil-works/pi-coding-agent": "0.86.0",
251
+ "@earendil-works/pi-tui": "0.86.0",
252
252
  "@tanstack/react-store": "0.11.1",
253
253
  "@tanstack/store": "0.11.1",
254
254
  "@types/node": "26.5.1",
@@ -261,8 +261,8 @@
261
261
  "vitest": "5.0.0"
262
262
  },
263
263
  "peerDependencies": {
264
- "@earendil-works/pi-coding-agent": "0.85.1",
265
- "@earendil-works/pi-tui": "0.85.1"
264
+ "@earendil-works/pi-coding-agent": "0.86.0",
265
+ "@earendil-works/pi-tui": "0.86.0"
266
266
  },
267
267
  "peerDependenciesMeta": {
268
268
  "@earendil-works/pi-coding-agent": {
@@ -273,18 +273,25 @@
273
273
  }
274
274
  },
275
275
  "optionalDependencies": {
276
- "@agimon-ai/doompi-runner-rmux-darwin-arm64": "0.0.1-alpha.71",
277
- "@agimon-ai/doompi-runner-rmux-darwin-x64": "0.0.1-alpha.71",
278
- "@agimon-ai/doompi-runner-rmux-linux-arm64": "0.0.1-alpha.71",
279
- "@agimon-ai/doompi-runner-rmux-linux-x64": "0.0.1-alpha.71",
280
- "@agimon-ai/doompi-runner-rtk-darwin-arm64": "0.0.1-alpha.71",
281
- "@agimon-ai/doompi-runner-rtk-darwin-x64": "0.0.1-alpha.71",
282
- "@agimon-ai/doompi-runner-rtk-linux-arm64": "0.0.1-alpha.71",
283
- "@agimon-ai/doompi-runner-rtk-linux-x64": "0.0.1-alpha.71"
276
+ "@agimon-ai/doompi-runner-rmux-darwin-arm64": "0.0.1-alpha.73",
277
+ "@agimon-ai/doompi-runner-rmux-darwin-x64": "0.0.1-alpha.73",
278
+ "@agimon-ai/doompi-runner-rmux-linux-arm64": "0.0.1-alpha.73",
279
+ "@agimon-ai/doompi-runner-rmux-linux-x64": "0.0.1-alpha.73",
280
+ "@agimon-ai/doompi-runner-rtk-darwin-arm64": "0.0.1-alpha.73",
281
+ "@agimon-ai/doompi-runner-rtk-darwin-x64": "0.0.1-alpha.73",
282
+ "@agimon-ai/doompi-runner-rtk-linux-arm64": "0.0.1-alpha.73",
283
+ "@agimon-ai/doompi-runner-rtk-linux-x64": "0.0.1-alpha.73"
284
284
  },
285
285
  "engines": {
286
286
  "node": ">=22.19.0"
287
287
  },
288
+ "doompiMcp": {
289
+ "entry": "./generated/mcp.ts",
290
+ "dist": "./dist/extensions/mcp.mjs",
291
+ "scopes": [
292
+ "session"
293
+ ]
294
+ },
288
295
  "doompiServer": {
289
296
  "entry": "./generated/server.ts",
290
297
  "dist": "./dist/extensions/server.mjs",
@@ -314,7 +321,8 @@
314
321
  ]
315
322
  },
316
323
  "scripts": {
317
- "build": "tsdown",
324
+ "build": "tsdown && tsdown --config tsdown.mcp.config.ts",
325
+ "build:mcp": "tsdown --config tsdown.mcp.config.ts",
318
326
  "test": "vitest --run",
319
327
  "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.web.json",
320
328
  "lint": "oxlint . && oxfmt . --check",