@agimon-ai/doompi-runner 0.0.1-alpha.53 → 0.0.1-alpha.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/adapters/pi/extension.cjs +2 -2
- package/dist/src/adapters/pi/extension.cjs.map +1 -1
- package/dist/src/adapters/pi/extension.d.cts.map +1 -1
- package/dist/src/adapters/pi/extension.d.mts.map +1 -1
- package/dist/src/adapters/pi/extension.mjs +2 -2
- package/dist/src/adapters/pi/extension.mjs.map +1 -1
- package/package.json +15 -15
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
const e=require("../../services/runs/compaction.cjs"),t=require("../../types/config.cjs"),n=require("../../container/index.cjs"),r=require("../../services/runs/reconcile.cjs"),i=require("../../commands/bash/bashTool.cjs"),a=require("../../services/runs/runnersCommand.cjs"),o=require("../../tui/format.cjs"),s=require("../../tui/runnerSpace.cjs"),c=require("../RunnerSettings/RunnerSettingsLoader.cjs");let l=require("@agimon-ai/doompi-extension-contracts/child-process"),u=require("@agimon-ai/doompi-extension-contracts/cordis-host"),
|
|
2
|
-
`);
|
|
1
|
+
const e=require("../../services/runs/compaction.cjs"),t=require("../../types/config.cjs"),n=require("../../container/index.cjs"),r=require("../../services/runs/reconcile.cjs"),i=require("../../commands/bash/bashTool.cjs"),a=require("../../services/runs/runnersCommand.cjs"),o=require("../../tui/format.cjs"),s=require("../../tui/runnerSpace.cjs"),c=require("../RunnerSettings/RunnerSettingsLoader.cjs");let l=require("@agimon-ai/doompi-extension-contracts/child-process"),u=require("@agimon-ai/doompi-extension-contracts/background-work"),d=require("@agimon-ai/doompi-extension-contracts/cordis-host"),f=require("@agimon-ai/doompi-extension-contracts/help"),p=require("@agimon-ai/doompi-extension-contracts/readiness"),m=require("@agimon-ai/doompi-extension-contracts/ui-hub"),ee=require("@agimon-ai/doompi-telemetry");const h=`@agimon-ai/doompi-runner`,te=`runners`,g=`completed`,ne=`stopped`,re=`doom-runner-runners`;function ie(e){try{let n=e.isProjectTrusted?.()??!1,{settings:r,issues:i}=new c.RunnerSettingsLoader().load(e.cwd,n);t.setRunnerSettings(r);for(let e of i)process.emitWarning(`${c.RUNNER_SETTINGS_FILE}: ${e}`)}catch(e){process.emitWarning(`Could not read ${c.RUNNER_SETTINGS_FILE}: ${String(e)}`),t.setRunnerSettings({})}}function _(c,d){let f=n.createRunnerContainer(),_=f.runnerRegistry,v=async()=>{try{_.close()}catch(e){process.emitWarning(`Could not close a partially installed doom-runner registry: ${String(e)}`)}};c.effect(()=>()=>v(),`${h}/runtime`);let y=f.launcher,b=f.rmuxBackend,ae=f.logReader,x=f.ptyHost,oe=f.bashRunService,S=f.paths,C=f.processControl,w=f.lifeline,T=!0,E=0,D,O,k=[],A,j,M,N=!1,P=!1,F,I,L,R,z,se,ce=Promise.resolve(),le,B=!1,V=!1,H,U=new Set,W=new Set,G=new Map,ue=[],K,q=new Set,J=e=>(q.add(e),e.then(()=>q.delete(e),()=>q.delete(e)),e),Y=async()=>{if(await ce,!T||!N||!D)throw Error(`doom-runner requires an active Pi session`)},de={run:async e=>(await Y(),J(oe.run(e)))},X=(e,t=D)=>T&&!P&&e===E&&t===D,fe=e=>(M??=(0,ee.createDoomTelemetry)({serviceName:`doom-runner`,packageName:`@agimon-ai/doompi-runner`,cwd:e.cwd,env:process.env,enableLogs:!0,enableTraces:!0}),M),Z=()=>{let e=D,t=new Set([...k.map(e=>e.id),...G.keys()]),n=e?[...k.filter(t=>t.sessionId===e&&t.promoted).map(e=>({id:e.id,sessionId:e.sessionId,label:e.name,status:e.state})),...[...G.values()].filter(t=>t.sessionId===e).map(e=>({id:e.id,sessionId:e.sessionId,label:e.name,status:e.state})),...[...W].filter(e=>!t.has(e)).map(t=>({id:t,sessionId:e,status:`running`}))]:[];JSON.stringify(n)!==JSON.stringify(ue)&&(ue=n,K?.update())},pe=async e=>{let t=D,n=E;if(!t||!X(n,t))return;let i=await _.list();if(!X(n,t))return;let a=i;if(e){let e=await r.reconcileActiveRunners({registry:_,launcher:y,rmuxBackend:b,processControl:C,currentHostPid:process.pid,startup:!1,active:i});for(let t of e.errors)process.emitWarning(t);if(e.reclaimed.length>0){let t=new Set(e.reclaimed);a=i.filter(e=>!t.has(e.id))}}if(!X(n,t))return;k=a.filter(e=>e.sessionId===t);let s=(O?a.filter(e=>(e.rootSessionId??e.sessionId)===O):[]).length;H!==s&&(H=s,j?.update(o.formatRunnerFooterContribution(s)),A?.hasUI&&A.ui.setStatus(re,o.formatRunnerStatus(s)));let c=[...W],l=await Promise.all(c.map(e=>_.get(e,t)));if(X(n,t)){for(let[e,n]of l.entries()){let r=c[e];if(r){if(!n||n.sessionId!==t){W.delete(r),G.delete(r),k=k.filter(e=>e.id!==r);continue}n.state===g&&(k=k.filter(e=>e.id!==n.id),G.set(n.id,n))}}Z();for(let e of l){if(!e||e.sessionId!==t||e.state!==g||U.has(e.id))continue;let n=e.exit?.reason??g,r=e.exit?.code===null||e.exit?.code===void 0?``:`, exit code ${e.exit.code}`,i=[`Background runner ${e.name} exited: ${n}${r}.`,`Runner ID: ${e.id}`,`Log: ${e.logPath}`,`Inspect: doom-runner logs ${e.id}`].join(`
|
|
2
|
+
`);d.sendMessage({customType:`doom-runner-finished`,content:i,display:!0},{triggerTurn:!0,deliverAs:`steer`}),U.add(e.id),W.delete(e.id),G.delete(e.id),Z(),A&&J(fe(A).recordEvent(`doom_runner.process_finished`,{outcome:`completed`,"runner.exit_code":e.exit?.code??0,"runner.backend":e.backend,...Number.isFinite(Date.parse(e.startedAt))?{duration_ms:Math.max(0,Date.now()-Date.parse(e.startedAt))}:{}}))}}},Q=(e=!0)=>{if(!D||!N||P)return Promise.resolve();if(F)return B=!0,V||=e,F;let t=(async()=>{let t=e;do B=!1,V=!1,await pe(t),t=V;while(B&&!P)})().finally(()=>{F===t&&(F=void 0)});return F=t,t},me=e=>{P||(A&&J(fe(A).recordError(`doom_runner.refresh_failed`,e)),process.emitWarning(`Could not refresh doom-runner: ${String(e)}`))},he=e=>{Q(e).catch(me)},ge=()=>{L||I||P||(L=setImmediate(()=>{if(L=void 0,P)return;let e=(async()=>{let e=S.sweepHistoryAsync?await S.sweepHistoryAsync(t.getLogTtlMs()):S.sweepHistory(t.getLogTtlMs());for(let t of e.errors)process.emitWarning(t)})().catch(e=>process.emitWarning(`Could not sweep doom-runner history: ${String(e)}`)).finally(()=>{I===e&&(I=void 0)});I=e}),L.unref?.())},$=async(e,t)=>{try{await t()}catch(t){process.emitWarning(`Doom-runner cleanup could not ${e}: ${String(t)}`)}};v=async()=>{if(P)return;T=!1,P=!0,E+=1,N=!1,R&&clearInterval(R),R=void 0,z&&clearInterval(z),z=void 0,L&&clearImmediate(L),L=void 0;let e=se;se=void 0,e&&await $(`unsubscribe from the runner registry`,e);let t=le;le=void 0,t&&await $(`cancel standalone readiness work`,()=>t.dispose()),await Promise.allSettled(q);let n=F;n&&await $(`settle the runner refresh`,()=>n);let i=I;i&&await $(`settle runner history cleanup`,()=>i),await $(`dispose runner PTYs`,()=>x.disposeAll());let a=[];if(D)try{a=await _.listBySession(D)}catch(e){process.emitWarning(`Could not list runners during doom-runner shutdown: ${String(e)}`)}await Promise.all(a.map(async e=>{try{let t=await r.stopRunnerProcess(e,y,b);if(!t&&C.isAlive(e.pid)){process.emitWarning(`Could not stop runner ${e.id} during session shutdown`);return}await _.complete(e.id,{reason:ne,code:null,signal:t?`SIGTERM`:null,stopReason:`session ended`},e.sessionId)}catch(t){process.emitWarning(`Could not clean up runner ${e.id}: ${String(t)}`)}}));let o=A,s=M;M=void 0,A=void 0,D=void 0,O=void 0,k=[],U.clear(),W.clear(),G.clear(),Z(),await Promise.all([$(`dispose the runner lifeline`,()=>w.dispose()),...o?.hasUI?[$(`clear the runner status`,()=>o.ui.setStatus(re,void 0))]:[]]),await $(`close the runner registry`,()=>_.close()),s&&(await $(`record the runner session finish`,()=>s.recordEvent(`doom_runner.session_finished`,{outcome:`stopped`})),await $(`stop runner telemetry`,()=>s.shutdown()))},c.inject([m.DOOM_UI_HUB_SERVICE],e=>{let t=(0,m.requireDoomUiHub)(e).registerFooter({source:h,id:`runner-count`,order:10});return j=t,()=>{t.dispose(),j===t&&(j=void 0)}}),c.inject([u.DOOM_BACKGROUND_WORK_SERVICE],e=>{let t=(0,u.readDoomBackgroundWorkService)(e);if(!t)return;let n=t.register({provider:`doom-runner`,listActiveWork:()=>ue});return K=n,()=>{n.dispose(),K===n&&(K=void 0)}}),se=_.subscribe(()=>he(!1)),R=setInterval(()=>he(!0),500),R.unref?.(),z=setInterval(()=>ge(),6e5),z.unref?.(),i.registerBashTool(d,{bashRunService:de,getSessionId:async()=>{if(await Y(),!D)throw Error(`doom-runner requires an active Pi session`);return D},onRunnerStarted:e=>{!T||!N||(W.add(e),Z(),he(!1))}}),e.registerRunnerCompactionRecovery(d,{getSessionId:async()=>{try{return await Y(),D}catch{return}},listBySession:async e=>{try{await Y()}catch{return[]}return T?_.listBySession(e):[]}});let _e=async(e,t,n,r)=>{if(!X(e,t))return!1;let i=k.find(e=>e.id===n);return i?(i.backend===`rmux`&&i.backendTarget?await b.stop(i.backendTarget,i.pid):await y.stop(i.pid),!X(e,t)||(await _.complete(i.id,{reason:ne,code:null,signal:null,stopReason:r},i.sessionId),X(e,t)&&await Q(),!0)):!1};d.registerCommand(te,{description:"Open Runner Space: background processes started by bash. `/runners stop <id> [reason]` stops one.",handler:async(e,t)=>{if(!T)return;let n=E,r=D;if(!r)return;let i=a.parseRunnersCommand(e);if(i.kind===`stop`){if(!i.id){t.ui.notify(`Usage: /runners stop <runner-id> [reason]`,`error`);return}if(await Y(),await Q(),!X(n,r))return;let e=await _e(n,r,i.id,i.reason);if(!X(n,r))return;e?t.ui.notify(`Stopped runner ${i.id}.`,`info`):t.ui.notify(`No active runner ${i.id} in this session.`,`error`);return}if(!t.hasUI){t.ui.notify(`/runners requires interactive mode`,`error`);return}await Y(),await Q(),!(!r||!X(n,r))&&await s.openRunnerSpace(t,{getRunners:()=>X(n,r)?k:[],getPtyRun:e=>X(n,r)?b.get(e)??x.get(e):void 0,readLog:e=>X(n,r)?ae.read(e,{lines:1e3}).text:``,stopRunner:async(e,t)=>{await _e(n,r,e,t)}})}}),c.inject([m.DOOM_UI_HUB_SERVICE],e=>{let t=(0,m.requireDoomUiHub)(e).registerLeader({source:h,bindings:[{id:`runners.open`,path:[{key:`r`,label:`runners`,detail:`background processes`,order:67},{key:`l`,label:`list`,detail:`runners in this session`}],command:{name:te}}]});return()=>t.dispose()}),d.on(`session_start`,(e,t)=>{if(!T)return;let n=t;ie(n);let i=n.sessionManager.getSessionId(),a=D,o=A,s=++E;D=i,O=(0,l.resolveRootSessionId)(i),A=n,N=!1,H=void 0,k=[],U.clear(),W.clear(),G.clear(),Z();let u=async e=>{let t=()=>!e.aborted&&X(s,i);if(!t())return[];if(a&&a!==i){await $(`dispose the previous session PTYs`,()=>x.disposeAll()),await $(`dispose the previous session lifeline`,()=>w.dispose()),o?.hasUI&&await $(`clear the previous session status`,()=>o.ui.setStatus(re,void 0));let e=M;if(M=void 0,e&&await $(`stop the previous session telemetry`,()=>e.shutdown()),!t())return[]}let c=fe(n);if(await c.recordEvent(`doom_runner.session_started`,{outcome:`started`}),!t()||(S.setSessionId(i),await w.arm(i),!t()))return[];let l=await _.listAll(i);if(!t())return[];for(let e of l)e.state===g?U.add(e.id):e.promoted&&W.add(e.id);let u=await r.cleanupLegacyRunnerStore({registry:_,launcher:y,rmuxBackend:b,processControl:C,currentHostPid:process.pid,paths:S});if(!t())return[];let d=await r.reconcileActiveRunners({registry:_,launcher:y,rmuxBackend:b,processControl:C,currentHostPid:process.pid,startup:!0});if(!t()||(N=!0,await Q(!1),!t()))return[];ge();let f=[...u.errors,...d.errors],p=u.reclaimed.length+d.reclaimed.length;return p>0&&n.hasUI&&n.ui.notify(`Reclaimed ${p} stale runner record(s)`,`warning`),await c.recordEvent(`doom_runner.reconciled`,{"runner.reclaimed_count":p,"runner.error_count":f.length,outcome:f.length===0?`completed`:`degraded`}),f},d=ce.catch(()=>void 0),f=(async()=>{await d,X(s,i)&&await((0,p.readDoomReadinessCoordinator)(c)??(le??=(0,p.createDoomReadinessCoordinator)({notify:e=>{process.emitWarning(`${e.packageId} initialization ${e.state}: ${e.error?.message??e.diagnostics.join(`; `)}`)}}))).start(h,`${i}:${s}`,async e=>({value:void 0,diagnostics:await u(e)})).wait()})();ce=f,J(f).catch(()=>void 0)})}async function v(e){let t=await(0,d.connectDoomCordisHost)(e,h),n=t.root.plugin(y,{pi:e});try{await n}catch(e){try{await n.dispose()}finally{await t.dispose()}throw e}let r;e.on(`session_shutdown`,()=>r??=(async()=>{try{await n.dispose()}finally{await t.dispose()}})())}function y(e,t){e.inject([f.DOOM_HELP_SERVICE],e=>{let t=(0,f.requireDoomHelpService)(e).register({source:h,moduleUrl:require("url").pathToFileURL(__filename).href,skills:[{name:`doompi-use-runner`,description:`Use Doom Pi Runner to supervise shell commands, inspect durable logs, provide interactive input, and stop background runs.`}]});return()=>t.dispose()}),_(e,t.pi)}exports.default=v,exports.runnerExtension=v,exports.installRunnerRuntime=_;
|
|
3
3
|
//# sourceMappingURL=extension.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.cjs","names":["RunnerSettingsLoader","RUNNER_SETTINGS_FILE","createRunnerContainer","createDoomTelemetry","reconcileActiveRunners","formatRunnerFooterContribution","formatRunnerStatus","getLogTtlMs","stopRunnerProcess","DOOM_UI_HUB_SERVICE","requireDoomUiHub","parseRunnersCommand","openRunnerSpace","resolveRootSessionId","cleanupLegacyRunnerStore","readDoomReadinessCoordinator","createDoomReadinessCoordinator","connectDoomCordisHost","DOOM_HELP_SERVICE","requireDoomHelpService"],"sources":["../../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { resolveRootSessionId } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport { connectDoomCordisHost } from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport { DOOM_HELP_SERVICE, requireDoomHelpService } from '@agimon-ai/doompi-extension-contracts/help';\nimport {\n createDoomReadinessCoordinator,\n type DoomReadinessCoordinator,\n readDoomReadinessCoordinator,\n} from '@agimon-ai/doompi-extension-contracts/readiness';\nimport type { DoomFooterContributionHandle } from '@agimon-ai/doompi-extension-contracts/footer';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-extension-contracts/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';\nimport { registerBashTool } from '../../commands/bash/bashTool.ts';\nimport { createRunnerContainer } from '../../container/index.ts';\nimport type { IBashRunService } from '../../types/bashRunService';\nimport type { RunnerRecord } from '../../types/runnerRegistry';\nimport { registerRunnerCompactionRecovery } from '../../services/runs/compaction.ts';\nimport { cleanupLegacyRunnerStore, reconcileActiveRunners, stopRunnerProcess } from '../../services/runs/reconcile.ts';\nimport { parseRunnersCommand } from '../../services/runs/runnersCommand.ts';\nimport { formatRunnerFooterContribution, formatRunnerStatus } from '../../tui/format.ts';\nimport { openRunnerSpace } from '../../tui/runnerSpace.ts';\nimport { getLogTtlMs } from '../../types/config.ts';\n\nconst LEADER_SOURCE = '@agimon-ai/doompi-runner';\n/** After doom-task's `t` (65) and before the core help group (70). */\nconst LEADER_GROUP_ORDER = 67;\nconst COMMAND_NAME = 'runners';\nconst ERR_REQUIRES_INTERACTIVE = '/runners requires interactive mode';\nconst ERR_STOP_USAGE = 'Usage: /runners stop <runner-id> [reason]';\n\nimport { RUNNER_SETTINGS_FILE, RunnerSettingsLoader } from '../RunnerSettings/RunnerSettingsLoader';\nimport { setRunnerSettings } from '../../types/config.ts';\n\nconst SESSION_START_EVENT = 'session_start';\nconst RUNNER_FINISHED_MESSAGE = 'doom-runner-finished';\nconst COMPLETED_STATE = 'completed';\nconst RMUX_BACKEND = 'rmux';\nconst STOPPED_REASON = 'stopped';\nconst RUNNER_STATUS_KEY = 'doom-runner-runners';\nconst RUNNER_FOOTER_ORDER = 10;\nconst RUNNER_STATUS_POLL_MS = 500;\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 */\nconst HISTORY_SWEEP_INTERVAL_MS = 10 * 60 * 1000;\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 installRunnerRuntime(cordis: Context, pi: ExtensionAPI): void {\n const container = createRunnerContainer();\n const registry = container.runnerRegistry;\n let disposeRuntime = async (): Promise<void> => {\n try {\n registry.close();\n } catch (error) {\n process.emitWarning(`Could not close a partially installed doom-runner registry: ${String(error)}`);\n }\n };\n cordis.effect(() => () => disposeRuntime(), `${LEADER_SOURCE}/runtime`);\n\n const launcher = container.launcher;\n const rmuxBackend = container.rmuxBackend;\n const logReader = container.logReader;\n const ptyHost = container.ptyHost;\n const bashRunService = container.bashRunService;\n const paths = container.paths;\n const processControl = container.processControl;\n const lifeline = container.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 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: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n return telemetry;\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 continue;\n }\n if (record.state !== COMPLETED_STATE) continue;\n pendingPromotedRunnerIds.delete(record.id);\n if (notifiedRunnerIds.has(record.id)) continue;\n notifiedRunnerIds.add(record.id);\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 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\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 disposeRuntime = shutdownRuntime;\n\n cordis.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 unsubscribeRegistry = registry.subscribe(() => scheduleRefresh(false));\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 registerBashTool(pi, {\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 scheduleRefresh(false);\n },\n });\n\n registerRunnerCompactionRecovery(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 /** 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 pi.registerCommand(COMMAND_NAME, {\n description: 'Open Runner Space: background processes started by bash. `/runners stop <id> [reason]` stops one.',\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 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 cordis.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 pi.on(SESSION_START_EVENT, (_event, ctx) => {\n if (!active) return;\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);\n sessionContext = context;\n sessionReady = false;\n lastRunnerCount = undefined;\n notifiedRunnerIds.clear();\n pendingPromotedRunnerIds.clear();\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 // 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 readDoomReadinessCoordinator(cordis) ??\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\n/** The package's sole Pi factory; Pi reloads it and Cordis owns all package resources. */\nexport async function runnerExtension(pi: ExtensionAPI): Promise<void> {\n const connection = await connectDoomCordisHost(pi, LEADER_SOURCE);\n const fiber = connection.root.plugin(runnerPlugin, { pi });\n try {\n await fiber;\n } catch (error) {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\ninterface RunnerPluginConfig {\n readonly pi: ExtensionAPI;\n}\n\nfunction runnerPlugin(cordis: Context, config: RunnerPluginConfig): void {\n cordis.inject([DOOM_HELP_SERVICE], (helpContext) => {\n const contribution = requireDoomHelpService(helpContext).register({\n source: LEADER_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-use-runner',\n description:\n 'Use Doom Pi Runner to supervise shell commands, inspect durable logs, provide interactive input, and stop background runs.',\n },\n ],\n });\n return () => contribution.dispose();\n });\n installRunnerRuntime(cordis, config.pi);\n}\n\nexport default runnerExtension;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extension.cjs","names":["RunnerSettingsLoader","RUNNER_SETTINGS_FILE","createRunnerContainer","createDoomTelemetry","reconcileActiveRunners","formatRunnerFooterContribution","formatRunnerStatus","getLogTtlMs","stopRunnerProcess","DOOM_UI_HUB_SERVICE","requireDoomUiHub","DOOM_BACKGROUND_WORK_SERVICE","readDoomBackgroundWorkService","parseRunnersCommand","openRunnerSpace","resolveRootSessionId","cleanupLegacyRunnerStore","readDoomReadinessCoordinator","createDoomReadinessCoordinator","connectDoomCordisHost","DOOM_HELP_SERVICE","requireDoomHelpService"],"sources":["../../../../src/adapters/pi/extension.ts"],"sourcesContent":["import {\n DOOM_BACKGROUND_WORK_SERVICE,\n type BackgroundProviderWorkItem,\n type BackgroundWorkProviderHandle,\n readDoomBackgroundWorkService,\n} from '@agimon-ai/doompi-extension-contracts/background-work';\nimport { resolveRootSessionId } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport { connectDoomCordisHost } from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport { DOOM_HELP_SERVICE, requireDoomHelpService } from '@agimon-ai/doompi-extension-contracts/help';\nimport {\n createDoomReadinessCoordinator,\n type DoomReadinessCoordinator,\n readDoomReadinessCoordinator,\n} from '@agimon-ai/doompi-extension-contracts/readiness';\nimport type { DoomFooterContributionHandle } from '@agimon-ai/doompi-extension-contracts/footer';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-extension-contracts/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';\nimport { registerBashTool } from '../../commands/bash/bashTool.ts';\nimport { createRunnerContainer } from '../../container/index.ts';\nimport type { IBashRunService } from '../../types/bashRunService';\nimport type { RunnerRecord } from '../../types/runnerRegistry';\nimport { registerRunnerCompactionRecovery } from '../../services/runs/compaction.ts';\nimport { cleanupLegacyRunnerStore, reconcileActiveRunners, stopRunnerProcess } from '../../services/runs/reconcile.ts';\nimport { parseRunnersCommand } from '../../services/runs/runnersCommand.ts';\nimport { formatRunnerFooterContribution, formatRunnerStatus } from '../../tui/format.ts';\nimport { openRunnerSpace } from '../../tui/runnerSpace.ts';\nimport { getLogTtlMs } from '../../types/config.ts';\n\nconst LEADER_SOURCE = '@agimon-ai/doompi-runner';\n/** After doom-task's `t` (65) and before the core help group (70). */\nconst LEADER_GROUP_ORDER = 67;\nconst COMMAND_NAME = 'runners';\nconst ERR_REQUIRES_INTERACTIVE = '/runners requires interactive mode';\nconst ERR_STOP_USAGE = 'Usage: /runners stop <runner-id> [reason]';\n\nimport { RUNNER_SETTINGS_FILE, RunnerSettingsLoader } from '../RunnerSettings/RunnerSettingsLoader';\nimport { setRunnerSettings } from '../../types/config.ts';\n\nconst SESSION_START_EVENT = 'session_start';\nconst RUNNER_FINISHED_MESSAGE = 'doom-runner-finished';\nconst COMPLETED_STATE = 'completed';\nconst RMUX_BACKEND = 'rmux';\nconst STOPPED_REASON = 'stopped';\nconst RUNNER_STATUS_KEY = 'doom-runner-runners';\nconst BACKGROUND_WORK_PROVIDER = 'doom-runner';\nconst RUNNER_FOOTER_ORDER = 10;\nconst RUNNER_STATUS_POLL_MS = 500;\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 */\nconst HISTORY_SWEEP_INTERVAL_MS = 10 * 60 * 1000;\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 installRunnerRuntime(cordis: Context, pi: ExtensionAPI): void {\n const container = createRunnerContainer();\n const registry = container.runnerRegistry;\n let disposeRuntime = async (): Promise<void> => {\n try {\n registry.close();\n } catch (error) {\n process.emitWarning(`Could not close a partially installed doom-runner registry: ${String(error)}`);\n }\n };\n cordis.effect(() => () => disposeRuntime(), `${LEADER_SOURCE}/runtime`);\n\n const launcher = container.launcher;\n const rmuxBackend = container.rmuxBackend;\n const logReader = container.logReader;\n const ptyHost = container.ptyHost;\n const bashRunService = container.bashRunService;\n const paths = container.paths;\n const processControl = container.processControl;\n const lifeline = container.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: process.env,\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 disposeRuntime = shutdownRuntime;\n\n cordis.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 cordis.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 unsubscribeRegistry = registry.subscribe(() => scheduleRefresh(false));\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 registerBashTool(pi, {\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 });\n\n registerRunnerCompactionRecovery(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 /** 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 pi.registerCommand(COMMAND_NAME, {\n description: 'Open Runner Space: background processes started by bash. `/runners stop <id> [reason]` stops one.',\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 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 cordis.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 pi.on(SESSION_START_EVENT, (_event, ctx) => {\n if (!active) return;\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);\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 // 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 readDoomReadinessCoordinator(cordis) ??\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\n/** The package's sole Pi factory; Pi reloads it and Cordis owns all package resources. */\nexport async function runnerExtension(pi: ExtensionAPI): Promise<void> {\n const connection = await connectDoomCordisHost(pi, LEADER_SOURCE);\n const fiber = connection.root.plugin(runnerPlugin, { pi });\n try {\n await fiber;\n } catch (error) {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\ninterface RunnerPluginConfig {\n readonly pi: ExtensionAPI;\n}\n\nfunction runnerPlugin(cordis: Context, config: RunnerPluginConfig): void {\n cordis.inject([DOOM_HELP_SERVICE], (helpContext) => {\n const contribution = requireDoomHelpService(helpContext).register({\n source: LEADER_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-use-runner',\n description:\n 'Use Doom Pi Runner to supervise shell commands, inspect durable logs, provide interactive input, and stop background runs.',\n },\n ],\n });\n return () => contribution.dispose();\n });\n installRunnerRuntime(cordis, config.pi);\n}\n\nexport default runnerExtension;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.cts","names":[],"sources":["../../../../src/adapters/pi/extension.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"extension.d.cts","names":[],"sources":["../../../../src/adapters/pi/extension.ts"],"mappings":";;;;iBAurBsB,gBAAgB,IAAI,eAAe"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.mts","names":[],"sources":["../../../../src/adapters/pi/extension.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"extension.d.mts","names":[],"sources":["../../../../src/adapters/pi/extension.ts"],"mappings":";;;;iBAurBsB,gBAAgB,IAAI,eAAe"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{registerRunnerCompactionRecovery as e}from"../../services/runs/compaction.mjs";import{getLogTtlMs as t,setRunnerSettings as n}from"../../types/config.mjs";import{createRunnerContainer as r}from"../../container/index.mjs";import{cleanupLegacyRunnerStore as i,reconcileActiveRunners as a,stopRunnerProcess as o}from"../../services/runs/reconcile.mjs";import{registerBashTool as s}from"../../commands/bash/bashTool.mjs";import{parseRunnersCommand as c}from"../../services/runs/runnersCommand.mjs";import{formatRunnerFooterContribution as l,formatRunnerStatus as
|
|
2
|
-
`);
|
|
1
|
+
import{registerRunnerCompactionRecovery as e}from"../../services/runs/compaction.mjs";import{getLogTtlMs as t,setRunnerSettings as n}from"../../types/config.mjs";import{createRunnerContainer as r}from"../../container/index.mjs";import{cleanupLegacyRunnerStore as i,reconcileActiveRunners as a,stopRunnerProcess as o}from"../../services/runs/reconcile.mjs";import{registerBashTool as s}from"../../commands/bash/bashTool.mjs";import{parseRunnersCommand as c}from"../../services/runs/runnersCommand.mjs";import{formatRunnerFooterContribution as l,formatRunnerStatus as ee}from"../../tui/format.mjs";import{openRunnerSpace as u}from"../../tui/runnerSpace.mjs";import{RUNNER_SETTINGS_FILE as d,RunnerSettingsLoader as f}from"../RunnerSettings/RunnerSettingsLoader.mjs";import{resolveRootSessionId as p}from"@agimon-ai/doompi-extension-contracts/child-process";import{DOOM_BACKGROUND_WORK_SERVICE as te,readDoomBackgroundWorkService as ne}from"@agimon-ai/doompi-extension-contracts/background-work";import{connectDoomCordisHost as m}from"@agimon-ai/doompi-extension-contracts/cordis-host";import{DOOM_HELP_SERVICE as re,requireDoomHelpService as h}from"@agimon-ai/doompi-extension-contracts/help";import{createDoomReadinessCoordinator as ie,readDoomReadinessCoordinator as ae}from"@agimon-ai/doompi-extension-contracts/readiness";import{DOOM_UI_HUB_SERVICE as oe,requireDoomUiHub as se}from"@agimon-ai/doompi-extension-contracts/ui-hub";import{createDoomTelemetry as ce}from"@agimon-ai/doompi-telemetry";const g=`@agimon-ai/doompi-runner`,le=`runners`,_=`completed`,ue=`stopped`,de=`doom-runner-runners`;function fe(e){try{let t=e.isProjectTrusted?.()??!1,{settings:r,issues:i}=new f().load(e.cwd,t);n(r);for(let e of i)process.emitWarning(`${d}: ${e}`)}catch(e){process.emitWarning(`Could not read ${d}: ${String(e)}`),n({})}}function v(n,d){let f=r(),m=f.runnerRegistry,re=async()=>{try{m.close()}catch(e){process.emitWarning(`Could not close a partially installed doom-runner registry: ${String(e)}`)}};n.effect(()=>()=>re(),`${g}/runtime`);let h=f.launcher,v=f.rmuxBackend,pe=f.logReader,y=f.ptyHost,me=f.bashRunService,b=f.paths,x=f.processControl,S=f.lifeline,C=!0,w=0,T,E,D=[],O,k,A,j=!1,M=!1,N,P,F,I,L,R,z=Promise.resolve(),B,V=!1,he=!1,ge,H=new Set,U=new Set,W=new Map,_e=[],G,K=new Set,q=e=>(K.add(e),e.then(()=>K.delete(e),()=>K.delete(e)),e),J=async()=>{if(await z,!C||!j||!T)throw Error(`doom-runner requires an active Pi session`)},ve={run:async e=>(await J(),q(me.run(e)))},Y=(e,t=T)=>C&&!M&&e===w&&t===T,ye=e=>(A??=ce({serviceName:`doom-runner`,packageName:`@agimon-ai/doompi-runner`,cwd:e.cwd,env:process.env,enableLogs:!0,enableTraces:!0}),A),X=()=>{let e=T,t=new Set([...D.map(e=>e.id),...W.keys()]),n=e?[...D.filter(t=>t.sessionId===e&&t.promoted).map(e=>({id:e.id,sessionId:e.sessionId,label:e.name,status:e.state})),...[...W.values()].filter(t=>t.sessionId===e).map(e=>({id:e.id,sessionId:e.sessionId,label:e.name,status:e.state})),...[...U].filter(e=>!t.has(e)).map(t=>({id:t,sessionId:e,status:`running`}))]:[];JSON.stringify(n)!==JSON.stringify(_e)&&(_e=n,G?.update())},be=async e=>{let t=T,n=w;if(!t||!Y(n,t))return;let r=await m.list();if(!Y(n,t))return;let i=r;if(e){let e=await a({registry:m,launcher:h,rmuxBackend:v,processControl:x,currentHostPid:process.pid,startup:!1,active:r});for(let t of e.errors)process.emitWarning(t);if(e.reclaimed.length>0){let t=new Set(e.reclaimed);i=r.filter(e=>!t.has(e.id))}}if(!Y(n,t))return;D=i.filter(e=>e.sessionId===t);let o=(E?i.filter(e=>(e.rootSessionId??e.sessionId)===E):[]).length;ge!==o&&(ge=o,k?.update(l(o)),O?.hasUI&&O.ui.setStatus(de,ee(o)));let s=[...U],c=await Promise.all(s.map(e=>m.get(e,t)));if(Y(n,t)){for(let[e,n]of c.entries()){let r=s[e];if(r){if(!n||n.sessionId!==t){U.delete(r),W.delete(r),D=D.filter(e=>e.id!==r);continue}n.state===_&&(D=D.filter(e=>e.id!==n.id),W.set(n.id,n))}}X();for(let e of c){if(!e||e.sessionId!==t||e.state!==_||H.has(e.id))continue;let n=e.exit?.reason??_,r=e.exit?.code===null||e.exit?.code===void 0?``:`, exit code ${e.exit.code}`,i=[`Background runner ${e.name} exited: ${n}${r}.`,`Runner ID: ${e.id}`,`Log: ${e.logPath}`,`Inspect: doom-runner logs ${e.id}`].join(`
|
|
2
|
+
`);d.sendMessage({customType:`doom-runner-finished`,content:i,display:!0},{triggerTurn:!0,deliverAs:`steer`}),H.add(e.id),U.delete(e.id),W.delete(e.id),X(),O&&q(ye(O).recordEvent(`doom_runner.process_finished`,{outcome:`completed`,"runner.exit_code":e.exit?.code??0,"runner.backend":e.backend,...Number.isFinite(Date.parse(e.startedAt))?{duration_ms:Math.max(0,Date.now()-Date.parse(e.startedAt))}:{}}))}}},Z=(e=!0)=>{if(!T||!j||M)return Promise.resolve();if(N)return V=!0,he||=e,N;let t=(async()=>{let t=e;do V=!1,he=!1,await be(t),t=he;while(V&&!M)})().finally(()=>{N===t&&(N=void 0)});return N=t,t},xe=e=>{M||(O&&q(ye(O).recordError(`doom_runner.refresh_failed`,e)),process.emitWarning(`Could not refresh doom-runner: ${String(e)}`))},Q=e=>{Z(e).catch(xe)},Se=()=>{F||P||M||(F=setImmediate(()=>{if(F=void 0,M)return;let e=(async()=>{let e=b.sweepHistoryAsync?await b.sweepHistoryAsync(t()):b.sweepHistory(t());for(let t of e.errors)process.emitWarning(t)})().catch(e=>process.emitWarning(`Could not sweep doom-runner history: ${String(e)}`)).finally(()=>{P===e&&(P=void 0)});P=e}),F.unref?.())},$=async(e,t)=>{try{await t()}catch(t){process.emitWarning(`Doom-runner cleanup could not ${e}: ${String(t)}`)}};re=async()=>{if(M)return;C=!1,M=!0,w+=1,j=!1,I&&clearInterval(I),I=void 0,L&&clearInterval(L),L=void 0,F&&clearImmediate(F),F=void 0;let e=R;R=void 0,e&&await $(`unsubscribe from the runner registry`,e);let t=B;B=void 0,t&&await $(`cancel standalone readiness work`,()=>t.dispose()),await Promise.allSettled(K);let n=N;n&&await $(`settle the runner refresh`,()=>n);let r=P;r&&await $(`settle runner history cleanup`,()=>r),await $(`dispose runner PTYs`,()=>y.disposeAll());let i=[];if(T)try{i=await m.listBySession(T)}catch(e){process.emitWarning(`Could not list runners during doom-runner shutdown: ${String(e)}`)}await Promise.all(i.map(async e=>{try{let t=await o(e,h,v);if(!t&&x.isAlive(e.pid)){process.emitWarning(`Could not stop runner ${e.id} during session shutdown`);return}await m.complete(e.id,{reason:ue,code:null,signal:t?`SIGTERM`:null,stopReason:`session ended`},e.sessionId)}catch(t){process.emitWarning(`Could not clean up runner ${e.id}: ${String(t)}`)}}));let a=O,s=A;A=void 0,O=void 0,T=void 0,E=void 0,D=[],H.clear(),U.clear(),W.clear(),X(),await Promise.all([$(`dispose the runner lifeline`,()=>S.dispose()),...a?.hasUI?[$(`clear the runner status`,()=>a.ui.setStatus(de,void 0))]:[]]),await $(`close the runner registry`,()=>m.close()),s&&(await $(`record the runner session finish`,()=>s.recordEvent(`doom_runner.session_finished`,{outcome:`stopped`})),await $(`stop runner telemetry`,()=>s.shutdown()))},n.inject([oe],e=>{let t=se(e).registerFooter({source:g,id:`runner-count`,order:10});return k=t,()=>{t.dispose(),k===t&&(k=void 0)}}),n.inject([te],e=>{let t=ne(e);if(!t)return;let n=t.register({provider:`doom-runner`,listActiveWork:()=>_e});return G=n,()=>{n.dispose(),G===n&&(G=void 0)}}),R=m.subscribe(()=>Q(!1)),I=setInterval(()=>Q(!0),500),I.unref?.(),L=setInterval(()=>Se(),6e5),L.unref?.(),s(d,{bashRunService:ve,getSessionId:async()=>{if(await J(),!T)throw Error(`doom-runner requires an active Pi session`);return T},onRunnerStarted:e=>{!C||!j||(U.add(e),X(),Q(!1))}}),e(d,{getSessionId:async()=>{try{return await J(),T}catch{return}},listBySession:async e=>{try{await J()}catch{return[]}return C?m.listBySession(e):[]}});let Ce=async(e,t,n,r)=>{if(!Y(e,t))return!1;let i=D.find(e=>e.id===n);return i?(i.backend===`rmux`&&i.backendTarget?await v.stop(i.backendTarget,i.pid):await h.stop(i.pid),!Y(e,t)||(await m.complete(i.id,{reason:ue,code:null,signal:null,stopReason:r},i.sessionId),Y(e,t)&&await Z(),!0)):!1};d.registerCommand(le,{description:"Open Runner Space: background processes started by bash. `/runners stop <id> [reason]` stops one.",handler:async(e,t)=>{if(!C)return;let n=w,r=T;if(!r)return;let i=c(e);if(i.kind===`stop`){if(!i.id){t.ui.notify(`Usage: /runners stop <runner-id> [reason]`,`error`);return}if(await J(),await Z(),!Y(n,r))return;let e=await Ce(n,r,i.id,i.reason);if(!Y(n,r))return;e?t.ui.notify(`Stopped runner ${i.id}.`,`info`):t.ui.notify(`No active runner ${i.id} in this session.`,`error`);return}if(!t.hasUI){t.ui.notify(`/runners requires interactive mode`,`error`);return}await J(),await Z(),!(!r||!Y(n,r))&&await u(t,{getRunners:()=>Y(n,r)?D:[],getPtyRun:e=>Y(n,r)?v.get(e)??y.get(e):void 0,readLog:e=>Y(n,r)?pe.read(e,{lines:1e3}).text:``,stopRunner:async(e,t)=>{await Ce(n,r,e,t)}})}}),n.inject([oe],e=>{let t=se(e).registerLeader({source:g,bindings:[{id:`runners.open`,path:[{key:`r`,label:`runners`,detail:`background processes`,order:67},{key:`l`,label:`list`,detail:`runners in this session`}],command:{name:le}}]});return()=>t.dispose()}),d.on(`session_start`,(e,t)=>{if(!C)return;let r=t;fe(r);let o=r.sessionManager.getSessionId(),s=T,c=O,l=++w;T=o,E=p(o),O=r,j=!1,ge=void 0,D=[],H.clear(),U.clear(),W.clear(),X();let ee=async e=>{let t=()=>!e.aborted&&Y(l,o);if(!t())return[];if(s&&s!==o){await $(`dispose the previous session PTYs`,()=>y.disposeAll()),await $(`dispose the previous session lifeline`,()=>S.dispose()),c?.hasUI&&await $(`clear the previous session status`,()=>c.ui.setStatus(de,void 0));let e=A;if(A=void 0,e&&await $(`stop the previous session telemetry`,()=>e.shutdown()),!t())return[]}let n=ye(r);if(await n.recordEvent(`doom_runner.session_started`,{outcome:`started`}),!t()||(b.setSessionId(o),await S.arm(o),!t()))return[];let ee=await m.listAll(o);if(!t())return[];for(let e of ee)e.state===_?H.add(e.id):e.promoted&&U.add(e.id);let u=await i({registry:m,launcher:h,rmuxBackend:v,processControl:x,currentHostPid:process.pid,paths:b});if(!t())return[];let d=await a({registry:m,launcher:h,rmuxBackend:v,processControl:x,currentHostPid:process.pid,startup:!0});if(!t()||(j=!0,await Z(!1),!t()))return[];Se();let f=[...u.errors,...d.errors],p=u.reclaimed.length+d.reclaimed.length;return p>0&&r.hasUI&&r.ui.notify(`Reclaimed ${p} stale runner record(s)`,`warning`),await n.recordEvent(`doom_runner.reconciled`,{"runner.reclaimed_count":p,"runner.error_count":f.length,outcome:f.length===0?`completed`:`degraded`}),f},u=z.catch(()=>void 0),d=(async()=>{await u,Y(l,o)&&await(ae(n)??(B??=ie({notify:e=>{process.emitWarning(`${e.packageId} initialization ${e.state}: ${e.error?.message??e.diagnostics.join(`; `)}`)}}))).start(g,`${o}:${l}`,async e=>({value:void 0,diagnostics:await ee(e)})).wait()})();z=d,q(d).catch(()=>void 0)})}async function pe(e){let t=await m(e,g),n=t.root.plugin(y,{pi:e});try{await n}catch(e){try{await n.dispose()}finally{await t.dispose()}throw e}let r;e.on(`session_shutdown`,()=>r??=(async()=>{try{await n.dispose()}finally{await t.dispose()}})())}function y(e,t){e.inject([re],e=>{let t=h(e).register({source:g,moduleUrl:import.meta.url,skills:[{name:`doompi-use-runner`,description:`Use Doom Pi Runner to supervise shell commands, inspect durable logs, provide interactive input, and stop background runs.`}]});return()=>t.dispose()}),v(e,t.pi)}export{pe as default,pe as runnerExtension,v as installRunnerRuntime};
|
|
3
3
|
//# sourceMappingURL=extension.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.mjs","names":[],"sources":["../../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { resolveRootSessionId } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport { connectDoomCordisHost } from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport { DOOM_HELP_SERVICE, requireDoomHelpService } from '@agimon-ai/doompi-extension-contracts/help';\nimport {\n createDoomReadinessCoordinator,\n type DoomReadinessCoordinator,\n readDoomReadinessCoordinator,\n} from '@agimon-ai/doompi-extension-contracts/readiness';\nimport type { DoomFooterContributionHandle } from '@agimon-ai/doompi-extension-contracts/footer';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-extension-contracts/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';\nimport { registerBashTool } from '../../commands/bash/bashTool.ts';\nimport { createRunnerContainer } from '../../container/index.ts';\nimport type { IBashRunService } from '../../types/bashRunService';\nimport type { RunnerRecord } from '../../types/runnerRegistry';\nimport { registerRunnerCompactionRecovery } from '../../services/runs/compaction.ts';\nimport { cleanupLegacyRunnerStore, reconcileActiveRunners, stopRunnerProcess } from '../../services/runs/reconcile.ts';\nimport { parseRunnersCommand } from '../../services/runs/runnersCommand.ts';\nimport { formatRunnerFooterContribution, formatRunnerStatus } from '../../tui/format.ts';\nimport { openRunnerSpace } from '../../tui/runnerSpace.ts';\nimport { getLogTtlMs } from '../../types/config.ts';\n\nconst LEADER_SOURCE = '@agimon-ai/doompi-runner';\n/** After doom-task's `t` (65) and before the core help group (70). */\nconst LEADER_GROUP_ORDER = 67;\nconst COMMAND_NAME = 'runners';\nconst ERR_REQUIRES_INTERACTIVE = '/runners requires interactive mode';\nconst ERR_STOP_USAGE = 'Usage: /runners stop <runner-id> [reason]';\n\nimport { RUNNER_SETTINGS_FILE, RunnerSettingsLoader } from '../RunnerSettings/RunnerSettingsLoader';\nimport { setRunnerSettings } from '../../types/config.ts';\n\nconst SESSION_START_EVENT = 'session_start';\nconst RUNNER_FINISHED_MESSAGE = 'doom-runner-finished';\nconst COMPLETED_STATE = 'completed';\nconst RMUX_BACKEND = 'rmux';\nconst STOPPED_REASON = 'stopped';\nconst RUNNER_STATUS_KEY = 'doom-runner-runners';\nconst RUNNER_FOOTER_ORDER = 10;\nconst RUNNER_STATUS_POLL_MS = 500;\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 */\nconst HISTORY_SWEEP_INTERVAL_MS = 10 * 60 * 1000;\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 installRunnerRuntime(cordis: Context, pi: ExtensionAPI): void {\n const container = createRunnerContainer();\n const registry = container.runnerRegistry;\n let disposeRuntime = async (): Promise<void> => {\n try {\n registry.close();\n } catch (error) {\n process.emitWarning(`Could not close a partially installed doom-runner registry: ${String(error)}`);\n }\n };\n cordis.effect(() => () => disposeRuntime(), `${LEADER_SOURCE}/runtime`);\n\n const launcher = container.launcher;\n const rmuxBackend = container.rmuxBackend;\n const logReader = container.logReader;\n const ptyHost = container.ptyHost;\n const bashRunService = container.bashRunService;\n const paths = container.paths;\n const processControl = container.processControl;\n const lifeline = container.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 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: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n return telemetry;\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 continue;\n }\n if (record.state !== COMPLETED_STATE) continue;\n pendingPromotedRunnerIds.delete(record.id);\n if (notifiedRunnerIds.has(record.id)) continue;\n notifiedRunnerIds.add(record.id);\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 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\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 disposeRuntime = shutdownRuntime;\n\n cordis.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 unsubscribeRegistry = registry.subscribe(() => scheduleRefresh(false));\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 registerBashTool(pi, {\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 scheduleRefresh(false);\n },\n });\n\n registerRunnerCompactionRecovery(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 /** 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 pi.registerCommand(COMMAND_NAME, {\n description: 'Open Runner Space: background processes started by bash. `/runners stop <id> [reason]` stops one.',\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 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 cordis.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 pi.on(SESSION_START_EVENT, (_event, ctx) => {\n if (!active) return;\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);\n sessionContext = context;\n sessionReady = false;\n lastRunnerCount = undefined;\n notifiedRunnerIds.clear();\n pendingPromotedRunnerIds.clear();\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 // 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 readDoomReadinessCoordinator(cordis) ??\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\n/** The package's sole Pi factory; Pi reloads it and Cordis owns all package resources. */\nexport async function runnerExtension(pi: ExtensionAPI): Promise<void> {\n const connection = await connectDoomCordisHost(pi, LEADER_SOURCE);\n const fiber = connection.root.plugin(runnerPlugin, { pi });\n try {\n await fiber;\n } catch (error) {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\ninterface RunnerPluginConfig {\n readonly pi: ExtensionAPI;\n}\n\nfunction runnerPlugin(cordis: Context, config: RunnerPluginConfig): void {\n cordis.inject([DOOM_HELP_SERVICE], (helpContext) => {\n const contribution = requireDoomHelpService(helpContext).register({\n source: LEADER_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-use-runner',\n description:\n 'Use Doom Pi Runner to supervise shell commands, inspect durable logs, provide interactive input, and stop background runs.',\n },\n ],\n });\n return () => contribution.dispose();\n });\n installRunnerRuntime(cordis, config.pi);\n}\n\nexport default runnerExtension;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extension.mjs","names":[],"sources":["../../../../src/adapters/pi/extension.ts"],"sourcesContent":["import {\n DOOM_BACKGROUND_WORK_SERVICE,\n type BackgroundProviderWorkItem,\n type BackgroundWorkProviderHandle,\n readDoomBackgroundWorkService,\n} from '@agimon-ai/doompi-extension-contracts/background-work';\nimport { resolveRootSessionId } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport { connectDoomCordisHost } from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport { DOOM_HELP_SERVICE, requireDoomHelpService } from '@agimon-ai/doompi-extension-contracts/help';\nimport {\n createDoomReadinessCoordinator,\n type DoomReadinessCoordinator,\n readDoomReadinessCoordinator,\n} from '@agimon-ai/doompi-extension-contracts/readiness';\nimport type { DoomFooterContributionHandle } from '@agimon-ai/doompi-extension-contracts/footer';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-extension-contracts/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';\nimport { registerBashTool } from '../../commands/bash/bashTool.ts';\nimport { createRunnerContainer } from '../../container/index.ts';\nimport type { IBashRunService } from '../../types/bashRunService';\nimport type { RunnerRecord } from '../../types/runnerRegistry';\nimport { registerRunnerCompactionRecovery } from '../../services/runs/compaction.ts';\nimport { cleanupLegacyRunnerStore, reconcileActiveRunners, stopRunnerProcess } from '../../services/runs/reconcile.ts';\nimport { parseRunnersCommand } from '../../services/runs/runnersCommand.ts';\nimport { formatRunnerFooterContribution, formatRunnerStatus } from '../../tui/format.ts';\nimport { openRunnerSpace } from '../../tui/runnerSpace.ts';\nimport { getLogTtlMs } from '../../types/config.ts';\n\nconst LEADER_SOURCE = '@agimon-ai/doompi-runner';\n/** After doom-task's `t` (65) and before the core help group (70). */\nconst LEADER_GROUP_ORDER = 67;\nconst COMMAND_NAME = 'runners';\nconst ERR_REQUIRES_INTERACTIVE = '/runners requires interactive mode';\nconst ERR_STOP_USAGE = 'Usage: /runners stop <runner-id> [reason]';\n\nimport { RUNNER_SETTINGS_FILE, RunnerSettingsLoader } from '../RunnerSettings/RunnerSettingsLoader';\nimport { setRunnerSettings } from '../../types/config.ts';\n\nconst SESSION_START_EVENT = 'session_start';\nconst RUNNER_FINISHED_MESSAGE = 'doom-runner-finished';\nconst COMPLETED_STATE = 'completed';\nconst RMUX_BACKEND = 'rmux';\nconst STOPPED_REASON = 'stopped';\nconst RUNNER_STATUS_KEY = 'doom-runner-runners';\nconst BACKGROUND_WORK_PROVIDER = 'doom-runner';\nconst RUNNER_FOOTER_ORDER = 10;\nconst RUNNER_STATUS_POLL_MS = 500;\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 */\nconst HISTORY_SWEEP_INTERVAL_MS = 10 * 60 * 1000;\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 installRunnerRuntime(cordis: Context, pi: ExtensionAPI): void {\n const container = createRunnerContainer();\n const registry = container.runnerRegistry;\n let disposeRuntime = async (): Promise<void> => {\n try {\n registry.close();\n } catch (error) {\n process.emitWarning(`Could not close a partially installed doom-runner registry: ${String(error)}`);\n }\n };\n cordis.effect(() => () => disposeRuntime(), `${LEADER_SOURCE}/runtime`);\n\n const launcher = container.launcher;\n const rmuxBackend = container.rmuxBackend;\n const logReader = container.logReader;\n const ptyHost = container.ptyHost;\n const bashRunService = container.bashRunService;\n const paths = container.paths;\n const processControl = container.processControl;\n const lifeline = container.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: process.env,\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 disposeRuntime = shutdownRuntime;\n\n cordis.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 cordis.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 unsubscribeRegistry = registry.subscribe(() => scheduleRefresh(false));\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 registerBashTool(pi, {\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 });\n\n registerRunnerCompactionRecovery(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 /** 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 pi.registerCommand(COMMAND_NAME, {\n description: 'Open Runner Space: background processes started by bash. `/runners stop <id> [reason]` stops one.',\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 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 cordis.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 pi.on(SESSION_START_EVENT, (_event, ctx) => {\n if (!active) return;\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);\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 // 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 readDoomReadinessCoordinator(cordis) ??\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\n/** The package's sole Pi factory; Pi reloads it and Cordis owns all package resources. */\nexport async function runnerExtension(pi: ExtensionAPI): Promise<void> {\n const connection = await connectDoomCordisHost(pi, LEADER_SOURCE);\n const fiber = connection.root.plugin(runnerPlugin, { pi });\n try {\n await fiber;\n } catch (error) {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\ninterface RunnerPluginConfig {\n readonly pi: ExtensionAPI;\n}\n\nfunction runnerPlugin(cordis: Context, config: RunnerPluginConfig): void {\n cordis.inject([DOOM_HELP_SERVICE], (helpContext) => {\n const contribution = requireDoomHelpService(helpContext).register({\n source: LEADER_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-use-runner',\n description:\n 'Use Doom Pi Runner to supervise shell commands, inspect durable logs, provide interactive input, and stop background runs.',\n },\n ],\n });\n return () => contribution.dispose();\n });\n installRunnerRuntime(cordis, config.pi);\n}\n\nexport default runnerExtension;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/doompi-runner",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.55",
|
|
4
4
|
"description": "Supervised shell execution, background process control, and run logs for Pi coding agents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -324,12 +324,12 @@
|
|
|
324
324
|
"@xterm/headless": "6.0.0",
|
|
325
325
|
"hono": "4.13.5",
|
|
326
326
|
"typebox": "1.3.19",
|
|
327
|
-
"@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.
|
|
328
|
-
"@agimon-ai/doompi-
|
|
329
|
-
"@agimon-ai/doompi-
|
|
330
|
-
"@agimon-ai/doompi-web-
|
|
331
|
-
"@agimon-ai/doompi-
|
|
332
|
-
"@agimon-ai/doompi-web-security": "0.0.1-alpha.
|
|
327
|
+
"@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.54",
|
|
328
|
+
"@agimon-ai/doompi-telemetry": "0.0.1-alpha.54",
|
|
329
|
+
"@agimon-ai/doompi-ui": "0.0.1-alpha.55",
|
|
330
|
+
"@agimon-ai/doompi-web-components": "0.0.1-alpha.15",
|
|
331
|
+
"@agimon-ai/doompi-web-contracts": "0.0.1-alpha.18",
|
|
332
|
+
"@agimon-ai/doompi-web-security": "0.0.1-alpha.16"
|
|
333
333
|
},
|
|
334
334
|
"devDependencies": {
|
|
335
335
|
"@earendil-works/pi-coding-agent": "0.84.4",
|
|
@@ -357,14 +357,14 @@
|
|
|
357
357
|
}
|
|
358
358
|
},
|
|
359
359
|
"optionalDependencies": {
|
|
360
|
-
"@agimon-ai/doompi-runner-rmux-darwin-arm64": "0.0.1-alpha.
|
|
361
|
-
"@agimon-ai/doompi-runner-rmux-darwin-x64": "0.0.1-alpha.
|
|
362
|
-
"@agimon-ai/doompi-runner-rmux-linux-arm64": "0.0.1-alpha.
|
|
363
|
-
"@agimon-ai/doompi-runner-
|
|
364
|
-
"@agimon-ai/doompi-runner-rtk-darwin-
|
|
365
|
-
"@agimon-ai/doompi-runner-
|
|
366
|
-
"@agimon-ai/doompi-runner-rtk-linux-arm64": "0.0.1-alpha.
|
|
367
|
-
"@agimon-ai/doompi-runner-rtk-linux-x64": "0.0.1-alpha.
|
|
360
|
+
"@agimon-ai/doompi-runner-rmux-darwin-arm64": "0.0.1-alpha.52",
|
|
361
|
+
"@agimon-ai/doompi-runner-rmux-darwin-x64": "0.0.1-alpha.52",
|
|
362
|
+
"@agimon-ai/doompi-runner-rmux-linux-arm64": "0.0.1-alpha.52",
|
|
363
|
+
"@agimon-ai/doompi-runner-rtk-darwin-arm64": "0.0.1-alpha.52",
|
|
364
|
+
"@agimon-ai/doompi-runner-rtk-darwin-x64": "0.0.1-alpha.52",
|
|
365
|
+
"@agimon-ai/doompi-runner-rmux-linux-x64": "0.0.1-alpha.52",
|
|
366
|
+
"@agimon-ai/doompi-runner-rtk-linux-arm64": "0.0.1-alpha.52",
|
|
367
|
+
"@agimon-ai/doompi-runner-rtk-linux-x64": "0.0.1-alpha.52"
|
|
368
368
|
},
|
|
369
369
|
"engines": {
|
|
370
370
|
"node": ">=22.19.0"
|