@agimon-ai/po-runner 0.0.0-alpha.2 → 0.0.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +149 -21
- package/README.md +17 -17
- package/dist/ansiScrub.mjs +1 -2
- package/dist/apiContracts.cjs +1 -1
- package/dist/apiContracts.cjs.map +1 -1
- package/dist/apiContracts.mjs +1 -1
- package/dist/apiContracts.mjs.map +1 -1
- package/dist/{bashResult-bIVSzoj-.mjs → bashResult-BqDa7sbC.mjs} +10 -9
- package/dist/bashResult-BqDa7sbC.mjs.map +1 -0
- package/dist/{bashResult-DNgtahGR.cjs → bashResult-C2iKhHpD.cjs} +10 -9
- package/dist/bashResult-C2iKhHpD.cjs.map +1 -0
- package/dist/{bashRunService-CJ02XaAq.mjs → bashRunService-Cl3pYccr.mjs} +2 -2
- package/dist/bashRunService-Cl3pYccr.mjs.map +1 -0
- package/dist/{bashRunService-DyqxOSlx.cjs → bashRunService-DjOH5kye.cjs} +2 -2
- package/dist/bashRunService-DjOH5kye.cjs.map +1 -0
- package/dist/bashRunService.cjs +1 -1
- package/dist/bashRunService.d.mts +3 -3
- package/dist/bashRunService.mjs +1 -2
- package/dist/bashSchema.cjs +1 -1
- package/dist/bashSchema.mjs +1 -2
- package/dist/{bashTool-C-k7fmyh.mjs → bashTool-BvC3YOgG.mjs} +2 -2
- package/dist/{bashTool-C-k7fmyh.mjs.map → bashTool-BvC3YOgG.mjs.map} +1 -1
- package/dist/{bashTool-CdgtqVFD.cjs → bashTool-euL6zMDl.cjs} +2 -2
- package/dist/{bashTool-CdgtqVFD.cjs.map → bashTool-euL6zMDl.cjs.map} +1 -1
- package/dist/bashTool.cjs +3 -3
- package/dist/bashTool.d.mts +1 -1
- package/dist/bashTool.mjs +3 -3
- package/dist/bin/cli.cjs +6 -6
- package/dist/bin/cli.cjs.map +1 -1
- package/dist/bin/cli.mjs +7 -7
- package/dist/bin/cli.mjs.map +1 -1
- package/dist/bin/logSink.cjs +6 -6
- package/dist/bin/logSink.cjs.map +1 -1
- package/dist/bin/logSink.mjs +7 -7
- package/dist/bin/logSink.mjs.map +1 -1
- package/dist/bin/runnerHost.cjs +4 -4
- package/dist/bin/runnerHost.cjs.map +1 -1
- package/dist/bin/runnerHost.mjs +5 -5
- package/dist/bin/runnerHost.mjs.map +1 -1
- package/dist/{cliApp-Dj9nwaOv.cjs → cliApp-T8Fx_-1j.cjs} +6 -6
- package/dist/cliApp-T8Fx_-1j.cjs.map +1 -0
- package/dist/{cliApp-v8Z3rMCi.mjs → cliApp-q97eVh4E.mjs} +6 -6
- package/dist/cliApp-q97eVh4E.mjs.map +1 -0
- package/dist/cliApp.cjs +1 -1
- package/dist/cliApp.d.mts +1 -1
- package/dist/cliApp.mjs +1 -2
- package/dist/clock.mjs +1 -2
- package/dist/{compaction-4QSUsBxq.cjs → compaction-Cduebib_.cjs} +3 -3
- package/dist/compaction-Cduebib_.cjs.map +1 -0
- package/dist/{compaction-DCw80VZj.mjs → compaction-nNlE6e5I.mjs} +3 -3
- package/dist/compaction-nNlE6e5I.mjs.map +1 -0
- package/dist/compaction.cjs +1 -1
- package/dist/compaction.d.mts +1 -1
- package/dist/compaction.mjs +1 -2
- package/dist/config.cjs +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/config.mjs +1 -2
- package/dist/extensions/mcp-ui.mjs.map +1 -1
- package/dist/extensions/mcp.cjs +8 -7
- package/dist/extensions/mcp.cjs.map +1 -1
- package/dist/extensions/mcp.d.mts +1 -1
- package/dist/extensions/mcp.mjs +7 -6
- package/dist/extensions/mcp.mjs.map +1 -1
- package/dist/extensions/native.mjs +1 -1
- package/dist/extensions/native.mjs.map +1 -1
- package/dist/extensions/server.cjs +233 -119
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.mts +2 -2
- package/dist/extensions/server.d.mts.map +1 -1
- package/dist/extensions/server.mjs +233 -119
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/extensions/web.mjs +88 -62
- package/dist/extensions/web.mjs.map +1 -1
- package/dist/{headless-BGYfIlNk.mjs → headless-DOlCixyf.mjs} +5 -5
- package/dist/headless-DOlCixyf.mjs.map +1 -0
- package/dist/{headless-CHUsBGhg.cjs → headless-Dko_yBiy.cjs} +5 -5
- package/dist/headless-Dko_yBiy.cjs.map +1 -0
- package/dist/{index-Dhi8asLH.d.mts → index--xF7DvsE.d.mts} +4 -4
- package/dist/{index-Dhi8asLH.d.mts.map → index--xF7DvsE.d.mts.map} +1 -1
- package/dist/{index-BZL7keVW.d.mts → index-BCCF1sGD.d.mts} +2 -2
- package/dist/{index-BZL7keVW.d.mts.map → index-BCCF1sGD.d.mts.map} +1 -1
- package/dist/{index-BwB_jTI9.d.mts → index-BzeXJk6V.d.mts} +5 -5
- package/dist/index-BzeXJk6V.d.mts.map +1 -0
- package/dist/{index-D9-IXax4.d.mts → index-C-IC35d9.d.mts} +2 -2
- package/dist/{index-D9-IXax4.d.mts.map → index-C-IC35d9.d.mts.map} +1 -1
- package/dist/{index-DBz0DxnL.d.mts → index-CzCF_OP9.d.mts} +3 -4
- package/dist/index-CzCF_OP9.d.mts.map +1 -0
- package/dist/index.cjs +5 -5
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +5 -5
- package/dist/{launcher-BDm6-DiQ.mjs → launcher-CCYsFBM9.mjs} +3 -3
- package/dist/{launcher-BDm6-DiQ.mjs.map → launcher-CCYsFBM9.mjs.map} +1 -1
- package/dist/{launcher-SlyE8R3b.cjs → launcher-ZgDdyXpq.cjs} +8 -2
- package/dist/{launcher-SlyE8R3b.cjs.map → launcher-ZgDdyXpq.cjs.map} +1 -1
- package/dist/launcher.cjs +1 -1
- package/dist/launcher.d.mts +1 -1
- package/dist/launcher.mjs +1 -2
- package/dist/{lifeline-BZaQA0rm.mjs → lifeline-Bm-bHIjS.mjs} +6 -6
- package/dist/lifeline-Bm-bHIjS.mjs.map +1 -0
- package/dist/{lifeline-BuV_erib.cjs → lifeline-m7laIzIP.cjs} +6 -6
- package/dist/lifeline-m7laIzIP.cjs.map +1 -0
- package/dist/lifeline.cjs +1 -1
- package/dist/lifeline.d.mts +1 -1
- package/dist/lifeline.mjs +1 -1
- package/dist/{logFile-CNvepZh0.cjs → logFile-CnPKtxPy.cjs} +2 -2
- package/dist/{logFile-CNvepZh0.cjs.map → logFile-CnPKtxPy.cjs.map} +1 -1
- package/dist/{logFile-KKPbkC-a.mjs → logFile-XcDHBwu1.mjs} +2 -2
- package/dist/{logFile-KKPbkC-a.mjs.map → logFile-XcDHBwu1.mjs.map} +1 -1
- package/dist/logFile.cjs +1 -1
- package/dist/logFile.d.mts +1 -1
- package/dist/logFile.mjs +1 -2
- package/dist/{logReader-B6J7L7Ua.cjs → logReader-DHCK2BEr.cjs} +4 -4
- package/dist/{logReader-B6J7L7Ua.cjs.map → logReader-DHCK2BEr.cjs.map} +1 -1
- package/dist/{logReader-UfbDbwQl.mjs → logReader-mq9uVurh.mjs} +4 -4
- package/dist/{logReader-UfbDbwQl.mjs.map → logReader-mq9uVurh.mjs.map} +1 -1
- package/dist/logReader.cjs +1 -1
- package/dist/logReader.mjs +1 -2
- package/dist/processControl.mjs +1 -2
- package/dist/{ptyHost-DlQtTB8F.mjs → ptyHost-CwbLLr90.mjs} +2 -2
- package/dist/{ptyHost-DlQtTB8F.mjs.map → ptyHost-CwbLLr90.mjs.map} +1 -1
- package/dist/{ptyHost-MI2Z6WTG.cjs → ptyHost-D35hNmtd.cjs} +2 -2
- package/dist/{ptyHost-MI2Z6WTG.cjs.map → ptyHost-D35hNmtd.cjs.map} +1 -1
- package/dist/ptyHost.cjs +1 -1
- package/dist/ptyHost.mjs +1 -2
- package/dist/{ptySpawner-DEi1KOnd.mjs → ptySpawner-C375NJnj.mjs} +2 -2
- package/dist/ptySpawner-C375NJnj.mjs.map +1 -0
- package/dist/{ptySpawner-ijw0g5_T.cjs → ptySpawner-C39IzbRo.cjs} +2 -2
- package/dist/ptySpawner-C39IzbRo.cjs.map +1 -0
- package/dist/ptySpawner.cjs +1 -1
- package/dist/ptySpawner.d.mts +1 -1
- package/dist/ptySpawner.mjs +1 -2
- package/dist/{reconcile-DMeNSxwn.mjs → reconcile-5cZ11jSD.cjs} +12 -42
- package/dist/reconcile-5cZ11jSD.cjs.map +1 -0
- package/dist/{reconcile-BugwYFbV.cjs → reconcile-wNYQJZF-.mjs} +2 -62
- package/dist/reconcile-wNYQJZF-.mjs.map +1 -0
- package/dist/reconcile.cjs +1 -2
- package/dist/reconcile.d.mts +2 -9
- package/dist/reconcile.d.mts.map +1 -1
- package/dist/reconcile.mjs +1 -2
- package/dist/responseEnvelope.cjs +2 -2
- package/dist/responseEnvelope.d.mts +3 -3
- package/dist/responseEnvelope.mjs +2 -2
- package/dist/{rmuxBackend-DlxgqRZ1.cjs → rmuxBackend-Dh0CYVAL.cjs} +5 -5
- package/dist/rmuxBackend-Dh0CYVAL.cjs.map +1 -0
- package/dist/{rmuxBackend-DfyQwJrc.mjs → rmuxBackend-rjrVTG6K.mjs} +4 -4
- package/dist/rmuxBackend-rjrVTG6K.mjs.map +1 -0
- package/dist/rmuxBackend.cjs +1 -1
- package/dist/rmuxBackend.d.mts +1 -1
- package/dist/rmuxBackend.mjs +1 -2
- package/dist/{rtkProcessor-Bc4L4o_8.cjs → rtkProcessor-DSGbM-Cm.cjs} +4 -4
- package/dist/rtkProcessor-DSGbM-Cm.cjs.map +1 -0
- package/dist/{rtkProcessor-B9KPdyzr.mjs → rtkProcessor-Iw9gP5Xp.mjs} +3 -3
- package/dist/rtkProcessor-Iw9gP5Xp.mjs.map +1 -0
- package/dist/rtkProcessor.cjs +1 -1
- package/dist/rtkProcessor.d.mts +1 -1
- package/dist/rtkProcessor.mjs +1 -1
- package/dist/{runnerConfig-D2tGq5ZM.cjs → runnerConfig-BoLMinlx.cjs} +11 -11
- package/dist/runnerConfig-BoLMinlx.cjs.map +1 -0
- package/dist/{runnerConfig-BjtulXBI.d.mts → runnerConfig-DuWL6TJx.d.mts} +10 -10
- package/dist/{runnerConfig-BjtulXBI.d.mts.map → runnerConfig-DuWL6TJx.d.mts.map} +1 -1
- package/dist/{runnerConfig-BQBlVAXn.mjs → runnerConfig-XXMq4VQA.mjs} +11 -11
- package/dist/runnerConfig-XXMq4VQA.mjs.map +1 -0
- package/dist/{runnerDependencies-DruByBGS.mjs → runnerDependencies-7h_cxOva.mjs} +17 -17
- package/dist/runnerDependencies-7h_cxOva.mjs.map +1 -0
- package/dist/{runnerDependencies-KMZigIxB.cjs → runnerDependencies-DSun3xO-.cjs} +17 -17
- package/dist/runnerDependencies-DSun3xO-.cjs.map +1 -0
- package/dist/runnerDependencies.cjs +1 -1
- package/dist/runnerDependencies.d.mts +1 -1
- package/dist/runnerDependencies.mjs +1 -2
- package/dist/runnerNamer.d.mts +1 -1
- package/dist/runnerNamer.mjs +1 -2
- package/dist/{runnerPaths-BTEuzxw0.cjs → runnerPaths-B41rMOY6.cjs} +20 -38
- package/dist/runnerPaths-B41rMOY6.cjs.map +1 -0
- package/dist/{runnerPaths-B_dAAeco.mjs → runnerPaths-Dibbvyx_.mjs} +20 -38
- package/dist/runnerPaths-Dibbvyx_.mjs.map +1 -0
- package/dist/runnerPaths.cjs +1 -1
- package/dist/runnerPaths.d.mts +5 -7
- package/dist/runnerPaths.d.mts.map +1 -1
- package/dist/runnerPaths.mjs +1 -2
- package/dist/{runnerRegistry-CeOHEjBv.mjs → runnerRegistry-BgaR5O86.mjs} +12 -11
- package/dist/runnerRegistry-BgaR5O86.mjs.map +1 -0
- package/dist/{runnerRegistry-CtJiD02R.d.mts → runnerRegistry-V-Ocaf4N.d.mts} +1 -3
- package/dist/{runnerRegistry-CtJiD02R.d.mts.map → runnerRegistry-V-Ocaf4N.d.mts.map} +1 -1
- package/dist/{runnerRegistry-BmkZTJHi.cjs → runnerRegistry-dQYlMSpQ.cjs} +23 -10
- package/dist/runnerRegistry-dQYlMSpQ.cjs.map +1 -0
- package/dist/runnerRegistry.cjs +1 -1
- package/dist/runnerRegistry.d.mts +2 -2
- package/dist/runnerRegistry.mjs +1 -2
- package/dist/services/lifeline/client.cjs +2 -2
- package/dist/services/lifeline/client.cjs.map +1 -1
- package/dist/services/lifeline/client.d.mts +1 -1
- package/dist/services/lifeline/client.mjs +2 -2
- package/dist/services/lifeline/client.mjs.map +1 -1
- package/dist/{session-Chsb_Nh2.mjs → session-BKYnH4R6.mjs} +2 -2
- package/dist/{session-Chsb_Nh2.mjs.map → session-BKYnH4R6.mjs.map} +1 -1
- package/dist/{session-BC43uEyG.cjs → session-BvqzhXZY.cjs} +2 -2
- package/dist/{session-BC43uEyG.cjs.map → session-BvqzhXZY.cjs.map} +1 -1
- package/dist/session.cjs +1 -1
- package/dist/session.mjs +1 -1
- package/dist/spawner.mjs +1 -2
- package/dist/{type-C31e1gla.d.mts → type-Do0YxwVQ.d.mts} +4 -4
- package/dist/{type-C31e1gla.d.mts.map → type-Do0YxwVQ.d.mts.map} +1 -1
- package/dist/{type-BXM03qSw.d.mts → type-DwMZoINK.d.mts} +8 -8
- package/dist/{type-BXM03qSw.d.mts.map → type-DwMZoINK.d.mts.map} +1 -1
- package/dist/types.d.mts +1 -1
- package/package.json +31 -34
- package/skills/{doom-runner → po-runner}/SKILL.md +15 -15
- package/src/prompts/po-use-runner/SKILL.md +11 -11
- package/dist/bashResult-DNgtahGR.cjs.map +0 -1
- package/dist/bashResult-bIVSzoj-.mjs.map +0 -1
- package/dist/bashRunService-CJ02XaAq.mjs.map +0 -1
- package/dist/bashRunService-DyqxOSlx.cjs.map +0 -1
- package/dist/cliApp-Dj9nwaOv.cjs.map +0 -1
- package/dist/cliApp-v8Z3rMCi.mjs.map +0 -1
- package/dist/compaction-4QSUsBxq.cjs.map +0 -1
- package/dist/compaction-DCw80VZj.mjs.map +0 -1
- package/dist/headless-BGYfIlNk.mjs.map +0 -1
- package/dist/headless-CHUsBGhg.cjs.map +0 -1
- package/dist/index-BwB_jTI9.d.mts.map +0 -1
- package/dist/index-DBz0DxnL.d.mts.map +0 -1
- package/dist/lifeline-BZaQA0rm.mjs.map +0 -1
- package/dist/lifeline-BuV_erib.cjs.map +0 -1
- package/dist/ptySpawner-DEi1KOnd.mjs.map +0 -1
- package/dist/ptySpawner-ijw0g5_T.cjs.map +0 -1
- package/dist/reconcile-BugwYFbV.cjs.map +0 -1
- package/dist/reconcile-DMeNSxwn.mjs.map +0 -1
- package/dist/rmuxBackend-DfyQwJrc.mjs.map +0 -1
- package/dist/rmuxBackend-DlxgqRZ1.cjs.map +0 -1
- package/dist/rtkProcessor-B9KPdyzr.mjs.map +0 -1
- package/dist/rtkProcessor-Bc4L4o_8.cjs.map +0 -1
- package/dist/runnerConfig-BQBlVAXn.mjs.map +0 -1
- package/dist/runnerConfig-D2tGq5ZM.cjs.map +0 -1
- package/dist/runnerDependencies-DruByBGS.mjs.map +0 -1
- package/dist/runnerDependencies-KMZigIxB.cjs.map +0 -1
- package/dist/runnerPaths-BTEuzxw0.cjs.map +0 -1
- package/dist/runnerPaths-B_dAAeco.mjs.map +0 -1
- package/dist/runnerRegistry-BmkZTJHi.cjs.map +0 -1
- package/dist/runnerRegistry-CeOHEjBv.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reconcile-BugwYFbV.cjs","names":["path"],"sources":["../src/constants/reconcile.ts","../src/services/reconcile/index.ts"],"sourcesContent":["export const COMPLETED_STATE = 'completed';\n","import path from 'node:path';\n\nimport { COMPLETED_STATE } from '../../constants/reconcile';\nimport type { ILauncher } from '../../types/launcher';\nimport type { IProcessControl } from '../../types/processControl';\nimport type { IRmuxBackend } from '../../types/rmuxBackend';\nimport type { IRunnerRegistry, RunnerRecord, RunnerTerminationIntent } from '../../types/runnerRegistry';\nimport type { IRunnerPaths } from '../runnerPaths/type';\n\nconst MULTIPLEXER_BACKENDS = new Set(['rmux', 'tmux']);\n\ninterface ReconcileDependencies {\n registry: IRunnerRegistry;\n launcher: ILauncher;\n rmuxBackend: IRmuxBackend;\n processControl: IProcessControl;\n currentHostPid: number;\n startup: boolean;\n /** Same-host restart cleanup belongs only to this session. */\n startupSessionId?: string;\n active?: readonly RunnerRecord[];\n}\n\nexport interface RunnerReconcileResult {\n reclaimed: string[];\n errors: string[];\n}\n\nexport async function stopRunnerProcess(\n record: RunnerRecord,\n launcher: ILauncher,\n rmuxBackend: IRmuxBackend,\n termination?: { registry: IRunnerRegistry; intent: RunnerTerminationIntent },\n): Promise<boolean> {\n if (termination) await termination.registry.requestTermination(record.id, termination.intent, record.sessionId);\n const stopped =\n (MULTIPLEXER_BACKENDS.has(record.backend) && record.backendTarget\n ? await rmuxBackend.stop(record.backendTarget, record.pid)\n : false) || (await launcher.stop(record.pid));\n if (!stopped && termination) await termination.registry.requestTermination(record.id, undefined, record.sessionId);\n return stopped;\n}\n\n/** Repairs active registry entries that lost their original completion observer. */\nexport async function reconcileActiveRunners(dependencies: ReconcileDependencies): Promise<RunnerReconcileResult> {\n const result: RunnerReconcileResult = { reclaimed: [], errors: [] };\n const active = dependencies.active ?? (await dependencies.registry.list());\n for (const record of active) {\n try {\n const persisted = await dependencies.registry.get(record.id, record.sessionId);\n if (persisted?.state === COMPLETED_STATE) {\n await dependencies.registry.release(record.id, record.sessionId);\n result.reclaimed.push(record.id);\n continue;\n }\n\n const rmuxOutcome = MULTIPLEXER_BACKENDS.has(record.backend)\n ? dependencies.rmuxBackend.readOutcome(record.id, record.sessionId)\n : undefined;\n if (rmuxOutcome) {\n await dependencies.registry.complete(\n record.id,\n {\n reason:\n rmuxOutcome.reason ??\n (rmuxOutcome.signal ? 'signaled' : rmuxOutcome.code === 0 ? COMPLETED_STATE : 'failed'),\n code: rmuxOutcome.code,\n signal: rmuxOutcome.signal,\n ...(rmuxOutcome.terminationReason ? { terminationReason: rmuxOutcome.terminationReason } : {}),\n ...(rmuxOutcome.stopReason ? { stopReason: rmuxOutcome.stopReason } : {}),\n },\n record.sessionId,\n );\n result.reclaimed.push(record.id);\n continue;\n }\n\n if (!dependencies.processControl.isAlive(record.pid)) {\n await dependencies.registry.complete(\n record.id,\n { reason: 'backend_lost', code: null, signal: null },\n record.sessionId,\n );\n result.reclaimed.push(record.id);\n continue;\n }\n\n const previousRuntime =\n dependencies.startup &&\n record.hostPid === dependencies.currentHostPid &&\n record.sessionId === dependencies.startupSessionId;\n const ownerLost = !dependencies.processControl.isAlive(record.hostPid);\n if (!previousRuntime && !ownerLost) continue;\n\n const stopped = await stopRunnerProcess(record, dependencies.launcher, dependencies.rmuxBackend, {\n registry: dependencies.registry,\n intent: {\n reason: 'stopped',\n terminationReason: ownerLost ? 'owner_lost' : 'parent_session_cleanup',\n stopReason: 'owner session ended',\n },\n });\n if (!stopped && dependencies.processControl.isAlive(record.pid)) {\n result.errors.push(`Could not stop orphaned runner ${record.id}`);\n continue;\n }\n await dependencies.registry.complete(\n record.id,\n {\n reason: 'stopped',\n code: null,\n signal: 'SIGTERM',\n stopReason: 'owner session ended',\n },\n record.sessionId,\n );\n result.reclaimed.push(record.id);\n } catch (error) {\n result.errors.push(`Could not reconcile runner ${record.id}: ${String(error)}`);\n }\n }\n return result;\n}\n\nfunction isWithin(root: string, candidate: string): boolean {\n const relative = path.relative(path.resolve(root), path.resolve(candidate));\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));\n}\n\ninterface LegacyCleanupDependencies extends Omit<ReconcileDependencies, 'startup'> {\n paths: IRunnerPaths;\n}\n\n/** Deletes the legacy Git store only after no live foreign runner uses it. */\nexport async function cleanupLegacyRunnerStore(\n dependencies: LegacyCleanupDependencies,\n): Promise<RunnerReconcileResult & { removed?: string }> {\n const result: RunnerReconcileResult & { removed?: string } = { reclaimed: [], errors: [] };\n const legacyDirectory = dependencies.paths.legacyDirectory();\n if (!legacyDirectory) return result;\n\n const legacyRecords = (await dependencies.registry.list()).filter((record) =>\n isWithin(legacyDirectory, record.logPath),\n );\n for (const record of legacyRecords) {\n const childAlive = dependencies.processControl.isAlive(record.pid);\n const ownerAlive = dependencies.processControl.isAlive(record.hostPid);\n // Multiple sessions share the host PID; it does not establish ownership.\n if (childAlive && ownerAlive) continue;\n try {\n if (childAlive) {\n const stopped = await stopRunnerProcess(record, dependencies.launcher, dependencies.rmuxBackend);\n if (!stopped && dependencies.processControl.isAlive(record.pid)) {\n result.errors.push(`Could not stop legacy runner ${record.id}`);\n continue;\n }\n }\n await dependencies.registry.release(record.id, record.sessionId);\n result.reclaimed.push(record.id);\n } catch (error) {\n result.errors.push(`Could not reclaim legacy runner ${record.id}: ${String(error)}`);\n }\n }\n\n let liveDependencies: RunnerRecord[];\n try {\n liveDependencies = (await dependencies.registry.listAcrossRepositories()).filter(\n (record) => isWithin(legacyDirectory, record.logPath) && dependencies.processControl.isAlive(record.pid),\n );\n } catch (error) {\n result.errors.push(`Could not verify legacy runner dependencies: ${String(error)}`);\n return result;\n }\n // A failed stop or release leaves the store's ownership unverified. Never\n // recursively remove it merely because the registry no longer reports a pid.\n if (result.errors.length === 0 && liveDependencies.length === 0) {\n result.removed = dependencies.paths.removeLegacyStore();\n }\n return result;\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reconcile-DMeNSxwn.mjs","names":[],"sources":["../src/constants/reconcile.ts","../src/services/reconcile/index.ts"],"sourcesContent":["export const COMPLETED_STATE = 'completed';\n","import path from 'node:path';\n\nimport { COMPLETED_STATE } from '../../constants/reconcile';\nimport type { ILauncher } from '../../types/launcher';\nimport type { IProcessControl } from '../../types/processControl';\nimport type { IRmuxBackend } from '../../types/rmuxBackend';\nimport type { IRunnerRegistry, RunnerRecord, RunnerTerminationIntent } from '../../types/runnerRegistry';\nimport type { IRunnerPaths } from '../runnerPaths/type';\n\nconst MULTIPLEXER_BACKENDS = new Set(['rmux', 'tmux']);\n\ninterface ReconcileDependencies {\n registry: IRunnerRegistry;\n launcher: ILauncher;\n rmuxBackend: IRmuxBackend;\n processControl: IProcessControl;\n currentHostPid: number;\n startup: boolean;\n /** Same-host restart cleanup belongs only to this session. */\n startupSessionId?: string;\n active?: readonly RunnerRecord[];\n}\n\nexport interface RunnerReconcileResult {\n reclaimed: string[];\n errors: string[];\n}\n\nexport async function stopRunnerProcess(\n record: RunnerRecord,\n launcher: ILauncher,\n rmuxBackend: IRmuxBackend,\n termination?: { registry: IRunnerRegistry; intent: RunnerTerminationIntent },\n): Promise<boolean> {\n if (termination) await termination.registry.requestTermination(record.id, termination.intent, record.sessionId);\n const stopped =\n (MULTIPLEXER_BACKENDS.has(record.backend) && record.backendTarget\n ? await rmuxBackend.stop(record.backendTarget, record.pid)\n : false) || (await launcher.stop(record.pid));\n if (!stopped && termination) await termination.registry.requestTermination(record.id, undefined, record.sessionId);\n return stopped;\n}\n\n/** Repairs active registry entries that lost their original completion observer. */\nexport async function reconcileActiveRunners(dependencies: ReconcileDependencies): Promise<RunnerReconcileResult> {\n const result: RunnerReconcileResult = { reclaimed: [], errors: [] };\n const active = dependencies.active ?? (await dependencies.registry.list());\n for (const record of active) {\n try {\n const persisted = await dependencies.registry.get(record.id, record.sessionId);\n if (persisted?.state === COMPLETED_STATE) {\n await dependencies.registry.release(record.id, record.sessionId);\n result.reclaimed.push(record.id);\n continue;\n }\n\n const rmuxOutcome = MULTIPLEXER_BACKENDS.has(record.backend)\n ? dependencies.rmuxBackend.readOutcome(record.id, record.sessionId)\n : undefined;\n if (rmuxOutcome) {\n await dependencies.registry.complete(\n record.id,\n {\n reason:\n rmuxOutcome.reason ??\n (rmuxOutcome.signal ? 'signaled' : rmuxOutcome.code === 0 ? COMPLETED_STATE : 'failed'),\n code: rmuxOutcome.code,\n signal: rmuxOutcome.signal,\n ...(rmuxOutcome.terminationReason ? { terminationReason: rmuxOutcome.terminationReason } : {}),\n ...(rmuxOutcome.stopReason ? { stopReason: rmuxOutcome.stopReason } : {}),\n },\n record.sessionId,\n );\n result.reclaimed.push(record.id);\n continue;\n }\n\n if (!dependencies.processControl.isAlive(record.pid)) {\n await dependencies.registry.complete(\n record.id,\n { reason: 'backend_lost', code: null, signal: null },\n record.sessionId,\n );\n result.reclaimed.push(record.id);\n continue;\n }\n\n const previousRuntime =\n dependencies.startup &&\n record.hostPid === dependencies.currentHostPid &&\n record.sessionId === dependencies.startupSessionId;\n const ownerLost = !dependencies.processControl.isAlive(record.hostPid);\n if (!previousRuntime && !ownerLost) continue;\n\n const stopped = await stopRunnerProcess(record, dependencies.launcher, dependencies.rmuxBackend, {\n registry: dependencies.registry,\n intent: {\n reason: 'stopped',\n terminationReason: ownerLost ? 'owner_lost' : 'parent_session_cleanup',\n stopReason: 'owner session ended',\n },\n });\n if (!stopped && dependencies.processControl.isAlive(record.pid)) {\n result.errors.push(`Could not stop orphaned runner ${record.id}`);\n continue;\n }\n await dependencies.registry.complete(\n record.id,\n {\n reason: 'stopped',\n code: null,\n signal: 'SIGTERM',\n stopReason: 'owner session ended',\n },\n record.sessionId,\n );\n result.reclaimed.push(record.id);\n } catch (error) {\n result.errors.push(`Could not reconcile runner ${record.id}: ${String(error)}`);\n }\n }\n return result;\n}\n\nfunction isWithin(root: string, candidate: string): boolean {\n const relative = path.relative(path.resolve(root), path.resolve(candidate));\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));\n}\n\ninterface LegacyCleanupDependencies extends Omit<ReconcileDependencies, 'startup'> {\n paths: IRunnerPaths;\n}\n\n/** Deletes the legacy Git store only after no live foreign runner uses it. */\nexport async function cleanupLegacyRunnerStore(\n dependencies: LegacyCleanupDependencies,\n): Promise<RunnerReconcileResult & { removed?: string }> {\n const result: RunnerReconcileResult & { removed?: string } = { reclaimed: [], errors: [] };\n const legacyDirectory = dependencies.paths.legacyDirectory();\n if (!legacyDirectory) return result;\n\n const legacyRecords = (await dependencies.registry.list()).filter((record) =>\n isWithin(legacyDirectory, record.logPath),\n );\n for (const record of legacyRecords) {\n const childAlive = dependencies.processControl.isAlive(record.pid);\n const ownerAlive = dependencies.processControl.isAlive(record.hostPid);\n // Multiple sessions share the host PID; it does not establish ownership.\n if (childAlive && ownerAlive) continue;\n try {\n if (childAlive) {\n const stopped = await stopRunnerProcess(record, dependencies.launcher, dependencies.rmuxBackend);\n if (!stopped && dependencies.processControl.isAlive(record.pid)) {\n result.errors.push(`Could not stop legacy runner ${record.id}`);\n continue;\n }\n }\n await dependencies.registry.release(record.id, record.sessionId);\n result.reclaimed.push(record.id);\n } catch (error) {\n result.errors.push(`Could not reclaim legacy runner ${record.id}: ${String(error)}`);\n }\n }\n\n let liveDependencies: RunnerRecord[];\n try {\n liveDependencies = (await dependencies.registry.listAcrossRepositories()).filter(\n (record) => isWithin(legacyDirectory, record.logPath) && dependencies.processControl.isAlive(record.pid),\n );\n } catch (error) {\n result.errors.push(`Could not verify legacy runner dependencies: ${String(error)}`);\n return result;\n }\n // A failed stop or release leaves the store's ownership unverified. Never\n // recursively remove it merely because the registry no longer reports a pid.\n if (result.errors.length === 0 && liveDependencies.length === 0) {\n result.removed = dependencies.paths.removeLegacyStore();\n }\n return result;\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rmuxBackend-DfyQwJrc.mjs","names":[],"sources":["../src/constants/rmuxBackend.ts","../src/services/rmuxBackend/index.ts"],"sourcesContent":["export const RMUX_BINARY_ENV = 'PO_RMUX_BINARY';\nexport const POLL_MS = 100;\nexport const LOG_DRAIN_TIMEOUT_MS = 2_000;\n/**\n * Fallback interval for a missed log-completion event or a lost session.\n * The retained pane lets the sink write its marker before session cleanup.\n */\nexport const LOG_DRAIN_POLL_MS = 25;\nexport const PANE_STATE_FORMAT = '#{pane_dead}:#{pane_dead_status}:#{session_name}';\nexport const PANE_PID_FORMAT = '#{pane_pid}';\nexport const STOP_GRACE_MS = 3_000;\nexport const STOP_CLOSE_TIMEOUT_MS = 1_000;\nexport const EXECUTABLE_MODE = 0o755;\n/** The owner, group, and other execute bits, so an already runnable file is left alone. */\nexport const EXECUTABLE_BITS = 0o111;\nexport const VENDOR_DIRECTORY = 'vendor';\nexport const SESSION_PREFIX = 'doom-runner-';\nexport const OWNED_TARGET_PATTERN = /^doom-runner-[A-Za-z0-9_-]+$/;\nexport const SOCKET_HASH_LENGTH = 12;\nexport const NON_INTERACTIVE_ENV = { NO_COLOR: '1', CI: '1' };\n","import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\n\nimport { type Pane, RMUX, type Rmux } from '@rmux/sdk';\n\nimport {\n EXECUTABLE_BITS,\n EXECUTABLE_MODE,\n LOG_DRAIN_POLL_MS,\n LOG_DRAIN_TIMEOUT_MS,\n NON_INTERACTIVE_ENV,\n OWNED_TARGET_PATTERN,\n PANE_PID_FORMAT,\n PANE_STATE_FORMAT,\n POLL_MS,\n RMUX_BINARY_ENV,\n SESSION_PREFIX,\n SOCKET_HASH_LENGTH,\n STOP_CLOSE_TIMEOUT_MS,\n STOP_GRACE_MS,\n VENDOR_DIRECTORY,\n} from '../../constants/rmuxBackend';\nimport type { RunHandle } from '../../types/launcher';\nimport type { PtyRun } from '../../types/ptyHost';\nimport type { IRmuxBackend, RmuxLaunchRequest } from '../../types/rmuxBackend';\nimport type { RunnerSettings } from '../../types/runnerSettings';\nimport type { ExitResult } from '../../types/spawner';\nimport { getLogMaxBytes, getResultMaxBytes, noninteractiveEnvironment } from '../runnerConfig';\nimport type { IRunnerPaths } from '../runnerPaths/type';\nimport {\n cleanupSupervisorFiles,\n type CommandSpec,\n NO_TERMINAL_INPUT_ENV,\n readExitMetadata,\n runtimeEntry,\n shellJoin,\n type SupervisorPaths,\n supervisorPaths,\n watchForFile,\n writeCommandSpec,\n} from '../runnerSupervisor';\n\n/** Pane liveness, its exit status, and whether the session still exists, in one read. */\nconst PACKAGE_BY_PLATFORM: Readonly<Record<string, string>> = {\n 'darwin-arm64': '@agimon-ai/po-runner-rmux-darwin-arm64',\n 'darwin-x64': '@agimon-ai/po-runner-rmux-darwin-x64',\n 'linux-arm64': '@agimon-ai/po-runner-rmux-linux-arm64',\n 'linux-x64': '@agimon-ai/po-runner-rmux-linux-x64',\n};\n\nexport class RmuxBackend implements IRmuxBackend {\n private clientPromise: Promise<Rmux | undefined> | undefined;\n private readonly runs = new Map<string, PtyRun>();\n private readonly completions = new Map<string, Promise<ExitResult>>();\n\n constructor(\n private readonly paths: IRunnerPaths,\n private readonly env: Readonly<Record<string, string | undefined>> = process.env,\n private readonly settings?: RunnerSettings,\n ) {}\n\n async launch(request: RmuxLaunchRequest): Promise<RunHandle | undefined> {\n const rmux = await this.client();\n if (!rmux) return undefined;\n\n this.paths.ensureDirectories();\n const target = `${SESSION_PREFIX}${request.id}`;\n const logPath = this.paths.logPathFor(request.id);\n const aux = this.auxPaths(request.id, request.sessionId);\n let created = false;\n let released = false;\n\n try {\n this.prepareFiles(request, logPath, aux);\n // `-P -F` reports the pane pid from the call that creates the pane, so the\n // launch does not spend a second round trip asking for it.\n const opened = await rmux.cmd(\n 'new-session',\n '-d',\n '-P',\n '-F',\n PANE_PID_FORMAT,\n '-s',\n target,\n '-c',\n request.cwd,\n process.execPath,\n runtimeEntry('runnerHost'),\n aux.spec,\n aux.gate,\n aux.exit,\n { check: true },\n );\n created = true;\n // Keep the pane until the log reader drains. Otherwise a fast shell can\n // end the session before the reader starts, losing its final output.\n await rmux.cmd('set-option', '-t', target, 'remain-on-exit', 'on', { check: true });\n await rmux.cmd('pipe-pane', '-t', target, this.logPipeCommand(logPath, aux.logDone, request), { check: true });\n\n const pane = rmux.session(target).pane(0, 0);\n const pid = reportedPid(String(opened.stdout ?? '')) ?? (await panePid(rmux, target));\n fs.writeFileSync(aux.gate, '', { mode: 0o600 });\n released = true;\n\n let buffering = true;\n const completion = this.monitor(rmux, pane, target, aux);\n this.trackCompletion(target, completion);\n const stop = (): Promise<boolean> => this.stop(target, pid);\n const handle: RunHandle = {\n id: request.id,\n name: request.name,\n pid,\n logPath,\n backend: 'rmux',\n backendTarget: target,\n output: () => (buffering ? readTail(logPath, getResultMaxBytes(this.env, this.settings) * 2) : ''),\n completion: () => completion,\n detach: () => {\n buffering = false;\n },\n stop,\n };\n\n if (request.interactive) this.runs.set(request.name, this.interactiveRun(handle, pane, completion));\n void completion\n .finally(() => this.runs.delete(request.name))\n .catch((error: unknown) => process.emitWarning(`RMUX completion failed for ${target}: ${errorMessage(error)}`));\n return handle;\n } catch (error) {\n if (released) throw error;\n if (created) {\n await rmux\n .session(target)\n .kill()\n .catch((cleanupError: unknown) =>\n process.emitWarning(`Could not clean up failed RMUX launch ${target}: ${errorMessage(cleanupError)}`),\n );\n }\n cleanupSupervisorFiles(aux);\n process.emitWarning(\n request.interactive\n ? `RMUX launch unavailable for interactive runner: ${errorMessage(error)}`\n : `RMUX launch unavailable, using supervised subprocess: ${errorMessage(error)}`,\n );\n return undefined;\n }\n }\n\n async stop(target: string, expectedPid: number): Promise<boolean> {\n if (!OWNED_TARGET_PATTERN.test(target) || !Number.isInteger(expectedPid) || expectedPid <= 0) return false;\n\n const rmux = await this.client();\n if (!rmux) return false;\n try {\n // A session that already ended took its process group with it.\n if (await sessionMissing(rmux, target)) return true;\n\n const pid = await panePid(rmux, target);\n if (pid !== expectedPid) return false;\n const signalled = signalPane(pid, target);\n if (signalled === 'gone') return true;\n if (signalled === 'failed') return false;\n\n if (await waitForPaneStop(rmux, target, STOP_GRACE_MS)) return true;\n if (await sessionMissing(rmux, target)) return true;\n\n // Revalidate after the grace period so a replacement pane is never closed.\n const currentPid = await panePid(rmux, target);\n if (currentPid !== expectedPid) return false;\n\n return closeOwnedSession(rmux, target);\n } catch (error) {\n process.emitWarning(`Could not stop RMUX target ${target}: ${errorMessage(error)}`);\n return false;\n }\n }\n\n async watch(id: string, target: string, sessionId?: string): Promise<ExitResult | undefined> {\n const rmux = await this.client();\n if (!rmux) return undefined;\n const pane = rmux.session(target).pane(0, 0);\n try {\n await rmux.displayMessage('#{pane_id}', { target });\n } catch (error) {\n process.emitWarning(`Could not watch RMUX target ${target}: ${errorMessage(error)}`);\n return undefined;\n }\n const completion = this.monitor(rmux, pane, target, this.auxPaths(id, sessionId));\n this.trackCompletion(target, completion);\n return completion;\n }\n\n async input(target: string, text: string): Promise<boolean> {\n const rmux = await this.client();\n if (!rmux) return false;\n const result = await rmux\n .session(target)\n .pane(0, 0)\n .sendText(text)\n .catch((error: unknown) => {\n process.emitWarning(`Could not send input to RMUX target ${target}: ${errorMessage(error)}`);\n return undefined;\n });\n return result !== undefined;\n }\n\n async capture(target: string): Promise<string | undefined> {\n const rmux = await this.client();\n if (!rmux) return undefined;\n return rmux\n .session(target)\n .pane(0, 0)\n .captureText()\n .catch((error: unknown) => {\n process.emitWarning(`Could not capture RMUX target ${target}: ${errorMessage(error)}`);\n return undefined;\n });\n }\n\n get(name: string): PtyRun | undefined {\n return this.runs.get(name);\n }\n\n readOutcome(id: string, sessionId: string): ExitResult | undefined {\n return readExitMetadata(this.auxPaths(id, sessionId).exit);\n }\n\n private trackCompletion(target: string, completion: Promise<ExitResult>): void {\n this.completions.set(target, completion);\n void completion\n .finally(() => this.completions.delete(target))\n .catch((error: unknown) => process.emitWarning(`RMUX monitor failed for ${target}: ${errorMessage(error)}`));\n }\n\n private client(): Promise<Rmux | undefined> {\n this.clientPromise ??= this.resolveClient();\n return this.clientPromise;\n }\n\n private async resolveClient(): Promise<Rmux | undefined> {\n const binaries = [resolveBundledRmuxBinary(import.meta.url, this.env), 'rmux'].filter(\n (value): value is string => value !== undefined,\n );\n for (const binary of binaries) {\n try {\n if (binary !== 'rmux') ensureExecutablePayload(binary);\n const client = new RMUX({ binary, socketName: socketName(this.paths.repositoryPath()) });\n await client.capabilities();\n return client;\n } catch (error) {\n process.emitWarning(`RMUX candidate ${binary} is unavailable: ${errorMessage(error)}`);\n // Try the next compatible candidate. Non-interactive calls can use the subprocess launcher.\n }\n }\n return undefined;\n }\n\n private prepareFiles(request: RmuxLaunchRequest, logPath: string, aux: SupervisorPaths): void {\n cleanupSupervisorFiles(aux);\n fs.writeFileSync(logPath, '', { mode: 0o600 });\n const env = environment(request.sessionId, request.interactive, this.env);\n // runnerHost supervises the command and watches the lifeline itself, so an\n // owner that dies mid-run is handled inside the pane rather than around it.\n const spec: CommandSpec = { command: request.command, cwd: request.cwd, env };\n writeCommandSpec(aux.spec, spec);\n }\n\n private auxPaths(id: string, sessionId?: string): SupervisorPaths {\n return supervisorPaths(this.paths.stateDirectory(sessionId), id);\n }\n\n /**\n * The sink the pane pipes into.\n *\n * An interactive run also asks for a raw copy: the scrubbed log it writes\n * beside it has had cursor movement taken out, which is what a terminal\n * needs most. Only interactive runs pay for it, because only they can be\n * attached to.\n */\n private logPipeCommand(logPath: string, donePath: string, request: RmuxLaunchRequest): string {\n const id = path.basename(logPath, '.log');\n return shellJoin([\n process.execPath,\n runtimeEntry('logSink'),\n logPath,\n this.paths.rotatedLogPathFor(id),\n String(getLogMaxBytes(this.env)),\n donePath,\n ...(request.interactive ? [this.paths.rawLogPathFor(id)] : []),\n ]);\n }\n\n private async monitor(rmux: Rmux, pane: Pane, target: string, aux: SupervisorPaths): Promise<ExitResult> {\n try {\n const paneCode = await waitForRunEnd(rmux, target, aux.exit);\n await waitForLogDrain(rmux, target, aux.logDone);\n return readExitMetadata(aux.exit) ?? { code: paneCode, signal: null };\n } finally {\n // The pane stays alive for log capture. Remove its session after draining,\n // allowing the last completed run to shut down the mux server too.\n let timer: ReturnType<typeof setTimeout> | undefined;\n const cleanup = async (): Promise<void> => {\n if (!(await sessionMissing(rmux, target))) await pane.server.session(target).kill();\n };\n try {\n await Promise.race([\n cleanup().catch((error: unknown) =>\n process.emitWarning(`Could not clean up completed RMUX target ${target}: ${errorMessage(error)}`),\n ),\n new Promise<void>((resolve) => {\n timer = setTimeout(() => {\n process.emitWarning(`Timed out cleaning up RMUX target ${target} after ${STOP_CLOSE_TIMEOUT_MS}ms`);\n resolve();\n }, STOP_CLOSE_TIMEOUT_MS);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n cleanupSupervisorFiles(aux);\n }\n }\n }\n\n private interactiveRun(handle: RunHandle, pane: Pane, completion: Promise<ExitResult>): PtyRun {\n let screen = '';\n let active = true;\n const handlers = new Set<(data: string) => void>();\n const refresh = async (): Promise<void> => {\n while (active) {\n const next = await pane.captureText().catch((error: unknown) => {\n process.emitWarning(`Could not capture RMUX screen for ${handle.name}: ${errorMessage(error)}`);\n return screen;\n });\n if (next !== screen) {\n screen = next;\n for (const handler of handlers) handler(next);\n }\n await delay(POLL_MS);\n }\n };\n void refresh();\n void completion\n .finally(() => {\n active = false;\n })\n .catch((error: unknown) =>\n process.emitWarning(`RMUX interactive completion failed for ${handle.name}: ${errorMessage(error)}`),\n );\n return {\n ...handle,\n write: (text) => {\n void pane.sendText(text).catch((error: unknown) => process.emitWarning(errorMessage(error)));\n },\n screen: () => screen,\n onData: (handler) => {\n handlers.add(handler);\n return () => handlers.delete(handler);\n },\n resize: (cols, rows) => {\n void pane\n .resize({ width: cols, height: rows })\n .catch((error: unknown) => process.emitWarning(errorMessage(error)));\n },\n };\n }\n}\n\nexport function rmuxPackageForTarget(platform: string, architecture: string): string | undefined {\n const target = `${platform}-${architecture}`;\n const packageName = PACKAGE_BY_PLATFORM[target];\n if (!packageName) process.emitWarning(`Bundled RMUX binary is unavailable for unsupported target ${target}`);\n return packageName;\n}\n\nexport function resolveBundledRmuxBinary(\n moduleUrl = import.meta.url,\n env: Readonly<Record<string, string | undefined>> = process.env,\n): string | undefined {\n const configured = env[RMUX_BINARY_ENV];\n if (configured !== undefined && configured !== '') return configured;\n const packageName = rmuxPackageForTarget(process.platform, process.arch);\n if (!packageName) return undefined;\n try {\n const require = createRequire(moduleUrl);\n const manifest = require.resolve(`${packageName}/package.json`);\n return path.join(path.dirname(manifest), VENDOR_DIRECTORY, 'bin', 'rmux');\n } catch (error) {\n process.emitWarning(`Bundled RMUX binary is unavailable for ${packageName}: ${errorMessage(error)}`);\n return undefined;\n }\n}\n\n/**\n * Make the bundled payload runnable before the launcher is spawned.\n *\n * The prebuilt packages reach npm with plain 0644 files, so the executable bit\n * the build set is not what lands on a user machine. Restoring it on the one\n * binary we spawn is not enough: rmux execs two files of its own,\n * `bin/rmux-daemon` and `libexec/rmux/rmux`, and the launcher fails on that\n * first exec with a permission error. Every file the payload ships is restored\n * here instead, which also covers a helper a later rmux release adds.\n *\n * A configured override (PO_RMUX_BINARY) usually points at a stand-alone\n * binary, so only paths that really sit inside a package vendor tree get the\n * walk. Files that are already executable are left untouched, since chmod on a\n * binary owned by someone else would throw and drop an otherwise usable\n * candidate.\n */\nexport function ensureExecutablePayload(binary: string): void {\n const vendor = path.resolve(path.dirname(binary), '..');\n const payload =\n path.basename(vendor) === VENDOR_DIRECTORY\n ? fs\n .readdirSync(vendor, { recursive: true, withFileTypes: true })\n .filter((entry) => entry.isFile())\n .map((entry) => path.join(entry.parentPath, entry.name))\n : [binary];\n for (const file of payload) {\n if ((fs.statSync(file).mode & EXECUTABLE_BITS) === 0) fs.chmodSync(file, EXECUTABLE_MODE);\n }\n}\n\nfunction socketName(repositoryPath: string): string {\n const hash = createHash('sha256').update(repositoryPath).digest('hex').slice(0, SOCKET_HASH_LENGTH);\n return `${SESSION_PREFIX}${hash}`;\n}\n\nfunction environment(\n sessionId: string,\n interactive: boolean,\n env: Readonly<Record<string, string | undefined>>,\n): Record<string, string> {\n const values: NodeJS.ProcessEnv = {\n ...env,\n ...(interactive ? {} : { ...NON_INTERACTIVE_ENV, ...noninteractiveEnvironment(env) }),\n // Applied to interactive runs as well: a pane is a tty either way, and an\n // agent sending input to a prompt still has no way past a pager.\n ...NO_TERMINAL_INPUT_ENV,\n PI_SESSION_ID: sessionId,\n };\n if (!interactive) delete values['FORCE_COLOR'];\n return Object.fromEntries(\n Object.entries(values).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n}\n\nasync function panePid(rmux: Rmux, target: string): Promise<number> {\n const response = await rmux.displayMessage(PANE_PID_FORMAT, { target });\n const message = typeof response['message'] === 'string' ? response['message'] : '';\n const pid = reportedPid(message);\n if (pid === undefined) throw new Error(`RMUX did not report a pane pid for ${target}`);\n return pid;\n}\n\n/** A pane pid as rmux prints it, or nothing when the output holds no usable pid. */\nfunction reportedPid(output: string): number | undefined {\n const pid = Number(output.trim());\n return Number.isInteger(pid) && pid > 0 ? pid : undefined;\n}\n\n/**\n * Waits for the run to end, preferring the supervisor's own record of it.\n *\n * The sidecar is written before the command's pane can end, and it outlives the\n * server that the pane's exit takes down with it. Watching for it means a run\n * that finishes inside a poll interval is observed when it finishes rather than\n * on the next tick. Asking the server stays the fallback for a supervisor that\n * died without recording anything.\n */\nasync function waitForRunEnd(rmux: Rmux, target: string, exitPath: string): Promise<number | null> {\n const landed = watchForFile(exitPath);\n let active = true;\n const readEvidence = async (): Promise<null> => {\n while (active) {\n if (await landed.appeared(POLL_MS)) return null;\n }\n return null;\n };\n const probePane = async (): Promise<number | null> => {\n while (active) {\n await delay(POLL_MS);\n if (!active) return null;\n const state = await readPaneExit(rmux, target);\n if (state.exited) return state.code;\n }\n return null;\n };\n try {\n // A stalled SDK request must not block the supervisor's durable evidence.\n // Keep only one pane request in flight, even when it never answers.\n return await Promise.race([readEvidence(), probePane()]);\n } finally {\n active = false;\n landed.close();\n }\n}\n\n/**\n * Gives the log sink a moment to mark the log complete.\n *\n * Normal completion retains the session until the sink records its final\n * writes. A lost session cannot guarantee a later marker, so it ends the wait.\n */\nasync function waitForLogDrain(rmux: Rmux, target: string, donePath: string): Promise<void> {\n const deadline = Date.now() + LOG_DRAIN_TIMEOUT_MS;\n const landed = watchForFile(donePath);\n let active = true;\n const readEvidence = async (): Promise<void> => {\n while (active && Date.now() < deadline) {\n if (await landed.appeared(LOG_DRAIN_POLL_MS)) return;\n }\n };\n const probeSession = async (): Promise<void> => {\n while (active && Date.now() < deadline) {\n await delay(LOG_DRAIN_POLL_MS);\n if (!active) return;\n if (await sessionMissing(rmux, target)) return;\n }\n };\n try {\n // The file loop enforces the deadline while a session query is outstanding.\n await Promise.race([readEvidence(), probeSession()]);\n } finally {\n active = false;\n landed.close();\n }\n}\n\nasync function closeOwnedSession(rmux: Rmux, target: string): Promise<boolean> {\n return new Promise((resolve) => {\n let settled = false;\n const finish = (result: boolean): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n resolve(result);\n };\n const timer = setTimeout(() => {\n process.emitWarning(`Timed out closing RMUX target ${target} after ${STOP_CLOSE_TIMEOUT_MS}ms`);\n finish(false);\n }, STOP_CLOSE_TIMEOUT_MS);\n void rmux\n .session(target)\n .kill()\n .then(\n () => finish(true),\n (error: unknown) => {\n process.emitWarning(`Could not close RMUX target ${target}: ${errorMessage(error)}`);\n finish(false);\n },\n );\n });\n}\n\nasync function waitForPaneStop(rmux: Rmux, target: string, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n try {\n if ((await readPaneExit(rmux, target)).exited) return true;\n } catch (error) {\n process.emitWarning(`Could not verify RMUX target ${target} stopped: ${errorMessage(error)}`);\n return false;\n }\n await delay(POLL_MS);\n }\n return false;\n}\n\n/**\n * One formatted read answers both questions this poll asks, so watching a run\n * costs the same single rmux call it always did.\n */\nasync function readPaneExit(rmux: Rmux, target: string): Promise<{ exited: boolean; code: number | null }> {\n let message: string;\n try {\n const response = await rmux.displayMessage(PANE_STATE_FORMAT, { target });\n message = typeof response['message'] === 'string' ? response['message'] : '';\n } catch {\n // The last session ending stops the server, so a server that cannot be\n // reached is the ordinary end of the last run rather than a fault.\n return { exited: true, code: null };\n }\n const [dead, status, ...rest] = message.trim().split(':');\n // A missing session formats as a live pane with no name rather than failing,\n // so the name is what says whether there is still anything to watch.\n if (rest.join(':') === '') return { exited: true, code: null };\n if (dead === '1' || dead === 'true') {\n const code = Number(status);\n return { exited: true, code: Number.isInteger(code) ? code : null };\n }\n return { exited: false, code: null };\n}\n\n/** A session that cannot be found, on a server that may itself be gone. */\nasync function sessionMissing(rmux: Rmux, target: string): Promise<boolean> {\n try {\n const probe = await rmux.cmd('has-session', '-t', target);\n return probe.returnCode !== 0;\n } catch {\n // No server to ask means no session to find.\n return true;\n }\n}\n\n/**\n * A pane that was already gone and a signal that could not be delivered are\n * opposite answers to \"is it stopped\", so they are reported apart.\n */\nfunction signalPane(pid: number, target: string): 'signalled' | 'gone' | 'failed' {\n try {\n process.kill(pid, 'SIGTERM');\n return 'signalled';\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ESRCH') return 'gone';\n process.emitWarning(`Could not signal RMUX target ${target}: ${errorMessage(error)}`);\n return 'failed';\n }\n}\n\nfunction readTail(target: string, maxBytes: number): string {\n let handle: number | undefined;\n try {\n const size = fs.statSync(target).size;\n const bytes = Math.min(size, maxBytes);\n const buffer = Buffer.alloc(bytes);\n handle = fs.openSync(target, 'r');\n fs.readSync(handle, buffer, 0, bytes, size - bytes);\n return buffer.toString('utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n process.emitWarning(`Could not read RMUX log ${target}: ${errorMessage(error)}`);\n }\n return '';\n } finally {\n if (handle !== undefined) fs.closeSync(handle);\n }\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(resolve, ms);\n timer.unref?.();\n });\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rmuxBackend-DlxgqRZ1.cjs","names":["runtimeEntry","getResultMaxBytes","readExitMetadata","RMUX","supervisorPaths","path","shellJoin","getLogMaxBytes","createRequire","fs","createHash","noninteractiveEnvironment","NO_TERMINAL_INPUT_ENV","watchForFile"],"sources":["../src/constants/rmuxBackend.ts","../src/services/rmuxBackend/index.ts"],"sourcesContent":["export const RMUX_BINARY_ENV = 'PO_RMUX_BINARY';\nexport const POLL_MS = 100;\nexport const LOG_DRAIN_TIMEOUT_MS = 2_000;\n/**\n * Fallback interval for a missed log-completion event or a lost session.\n * The retained pane lets the sink write its marker before session cleanup.\n */\nexport const LOG_DRAIN_POLL_MS = 25;\nexport const PANE_STATE_FORMAT = '#{pane_dead}:#{pane_dead_status}:#{session_name}';\nexport const PANE_PID_FORMAT = '#{pane_pid}';\nexport const STOP_GRACE_MS = 3_000;\nexport const STOP_CLOSE_TIMEOUT_MS = 1_000;\nexport const EXECUTABLE_MODE = 0o755;\n/** The owner, group, and other execute bits, so an already runnable file is left alone. */\nexport const EXECUTABLE_BITS = 0o111;\nexport const VENDOR_DIRECTORY = 'vendor';\nexport const SESSION_PREFIX = 'doom-runner-';\nexport const OWNED_TARGET_PATTERN = /^doom-runner-[A-Za-z0-9_-]+$/;\nexport const SOCKET_HASH_LENGTH = 12;\nexport const NON_INTERACTIVE_ENV = { NO_COLOR: '1', CI: '1' };\n","import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\n\nimport { type Pane, RMUX, type Rmux } from '@rmux/sdk';\n\nimport {\n EXECUTABLE_BITS,\n EXECUTABLE_MODE,\n LOG_DRAIN_POLL_MS,\n LOG_DRAIN_TIMEOUT_MS,\n NON_INTERACTIVE_ENV,\n OWNED_TARGET_PATTERN,\n PANE_PID_FORMAT,\n PANE_STATE_FORMAT,\n POLL_MS,\n RMUX_BINARY_ENV,\n SESSION_PREFIX,\n SOCKET_HASH_LENGTH,\n STOP_CLOSE_TIMEOUT_MS,\n STOP_GRACE_MS,\n VENDOR_DIRECTORY,\n} from '../../constants/rmuxBackend';\nimport type { RunHandle } from '../../types/launcher';\nimport type { PtyRun } from '../../types/ptyHost';\nimport type { IRmuxBackend, RmuxLaunchRequest } from '../../types/rmuxBackend';\nimport type { RunnerSettings } from '../../types/runnerSettings';\nimport type { ExitResult } from '../../types/spawner';\nimport { getLogMaxBytes, getResultMaxBytes, noninteractiveEnvironment } from '../runnerConfig';\nimport type { IRunnerPaths } from '../runnerPaths/type';\nimport {\n cleanupSupervisorFiles,\n type CommandSpec,\n NO_TERMINAL_INPUT_ENV,\n readExitMetadata,\n runtimeEntry,\n shellJoin,\n type SupervisorPaths,\n supervisorPaths,\n watchForFile,\n writeCommandSpec,\n} from '../runnerSupervisor';\n\n/** Pane liveness, its exit status, and whether the session still exists, in one read. */\nconst PACKAGE_BY_PLATFORM: Readonly<Record<string, string>> = {\n 'darwin-arm64': '@agimon-ai/po-runner-rmux-darwin-arm64',\n 'darwin-x64': '@agimon-ai/po-runner-rmux-darwin-x64',\n 'linux-arm64': '@agimon-ai/po-runner-rmux-linux-arm64',\n 'linux-x64': '@agimon-ai/po-runner-rmux-linux-x64',\n};\n\nexport class RmuxBackend implements IRmuxBackend {\n private clientPromise: Promise<Rmux | undefined> | undefined;\n private readonly runs = new Map<string, PtyRun>();\n private readonly completions = new Map<string, Promise<ExitResult>>();\n\n constructor(\n private readonly paths: IRunnerPaths,\n private readonly env: Readonly<Record<string, string | undefined>> = process.env,\n private readonly settings?: RunnerSettings,\n ) {}\n\n async launch(request: RmuxLaunchRequest): Promise<RunHandle | undefined> {\n const rmux = await this.client();\n if (!rmux) return undefined;\n\n this.paths.ensureDirectories();\n const target = `${SESSION_PREFIX}${request.id}`;\n const logPath = this.paths.logPathFor(request.id);\n const aux = this.auxPaths(request.id, request.sessionId);\n let created = false;\n let released = false;\n\n try {\n this.prepareFiles(request, logPath, aux);\n // `-P -F` reports the pane pid from the call that creates the pane, so the\n // launch does not spend a second round trip asking for it.\n const opened = await rmux.cmd(\n 'new-session',\n '-d',\n '-P',\n '-F',\n PANE_PID_FORMAT,\n '-s',\n target,\n '-c',\n request.cwd,\n process.execPath,\n runtimeEntry('runnerHost'),\n aux.spec,\n aux.gate,\n aux.exit,\n { check: true },\n );\n created = true;\n // Keep the pane until the log reader drains. Otherwise a fast shell can\n // end the session before the reader starts, losing its final output.\n await rmux.cmd('set-option', '-t', target, 'remain-on-exit', 'on', { check: true });\n await rmux.cmd('pipe-pane', '-t', target, this.logPipeCommand(logPath, aux.logDone, request), { check: true });\n\n const pane = rmux.session(target).pane(0, 0);\n const pid = reportedPid(String(opened.stdout ?? '')) ?? (await panePid(rmux, target));\n fs.writeFileSync(aux.gate, '', { mode: 0o600 });\n released = true;\n\n let buffering = true;\n const completion = this.monitor(rmux, pane, target, aux);\n this.trackCompletion(target, completion);\n const stop = (): Promise<boolean> => this.stop(target, pid);\n const handle: RunHandle = {\n id: request.id,\n name: request.name,\n pid,\n logPath,\n backend: 'rmux',\n backendTarget: target,\n output: () => (buffering ? readTail(logPath, getResultMaxBytes(this.env, this.settings) * 2) : ''),\n completion: () => completion,\n detach: () => {\n buffering = false;\n },\n stop,\n };\n\n if (request.interactive) this.runs.set(request.name, this.interactiveRun(handle, pane, completion));\n void completion\n .finally(() => this.runs.delete(request.name))\n .catch((error: unknown) => process.emitWarning(`RMUX completion failed for ${target}: ${errorMessage(error)}`));\n return handle;\n } catch (error) {\n if (released) throw error;\n if (created) {\n await rmux\n .session(target)\n .kill()\n .catch((cleanupError: unknown) =>\n process.emitWarning(`Could not clean up failed RMUX launch ${target}: ${errorMessage(cleanupError)}`),\n );\n }\n cleanupSupervisorFiles(aux);\n process.emitWarning(\n request.interactive\n ? `RMUX launch unavailable for interactive runner: ${errorMessage(error)}`\n : `RMUX launch unavailable, using supervised subprocess: ${errorMessage(error)}`,\n );\n return undefined;\n }\n }\n\n async stop(target: string, expectedPid: number): Promise<boolean> {\n if (!OWNED_TARGET_PATTERN.test(target) || !Number.isInteger(expectedPid) || expectedPid <= 0) return false;\n\n const rmux = await this.client();\n if (!rmux) return false;\n try {\n // A session that already ended took its process group with it.\n if (await sessionMissing(rmux, target)) return true;\n\n const pid = await panePid(rmux, target);\n if (pid !== expectedPid) return false;\n const signalled = signalPane(pid, target);\n if (signalled === 'gone') return true;\n if (signalled === 'failed') return false;\n\n if (await waitForPaneStop(rmux, target, STOP_GRACE_MS)) return true;\n if (await sessionMissing(rmux, target)) return true;\n\n // Revalidate after the grace period so a replacement pane is never closed.\n const currentPid = await panePid(rmux, target);\n if (currentPid !== expectedPid) return false;\n\n return closeOwnedSession(rmux, target);\n } catch (error) {\n process.emitWarning(`Could not stop RMUX target ${target}: ${errorMessage(error)}`);\n return false;\n }\n }\n\n async watch(id: string, target: string, sessionId?: string): Promise<ExitResult | undefined> {\n const rmux = await this.client();\n if (!rmux) return undefined;\n const pane = rmux.session(target).pane(0, 0);\n try {\n await rmux.displayMessage('#{pane_id}', { target });\n } catch (error) {\n process.emitWarning(`Could not watch RMUX target ${target}: ${errorMessage(error)}`);\n return undefined;\n }\n const completion = this.monitor(rmux, pane, target, this.auxPaths(id, sessionId));\n this.trackCompletion(target, completion);\n return completion;\n }\n\n async input(target: string, text: string): Promise<boolean> {\n const rmux = await this.client();\n if (!rmux) return false;\n const result = await rmux\n .session(target)\n .pane(0, 0)\n .sendText(text)\n .catch((error: unknown) => {\n process.emitWarning(`Could not send input to RMUX target ${target}: ${errorMessage(error)}`);\n return undefined;\n });\n return result !== undefined;\n }\n\n async capture(target: string): Promise<string | undefined> {\n const rmux = await this.client();\n if (!rmux) return undefined;\n return rmux\n .session(target)\n .pane(0, 0)\n .captureText()\n .catch((error: unknown) => {\n process.emitWarning(`Could not capture RMUX target ${target}: ${errorMessage(error)}`);\n return undefined;\n });\n }\n\n get(name: string): PtyRun | undefined {\n return this.runs.get(name);\n }\n\n readOutcome(id: string, sessionId: string): ExitResult | undefined {\n return readExitMetadata(this.auxPaths(id, sessionId).exit);\n }\n\n private trackCompletion(target: string, completion: Promise<ExitResult>): void {\n this.completions.set(target, completion);\n void completion\n .finally(() => this.completions.delete(target))\n .catch((error: unknown) => process.emitWarning(`RMUX monitor failed for ${target}: ${errorMessage(error)}`));\n }\n\n private client(): Promise<Rmux | undefined> {\n this.clientPromise ??= this.resolveClient();\n return this.clientPromise;\n }\n\n private async resolveClient(): Promise<Rmux | undefined> {\n const binaries = [resolveBundledRmuxBinary(import.meta.url, this.env), 'rmux'].filter(\n (value): value is string => value !== undefined,\n );\n for (const binary of binaries) {\n try {\n if (binary !== 'rmux') ensureExecutablePayload(binary);\n const client = new RMUX({ binary, socketName: socketName(this.paths.repositoryPath()) });\n await client.capabilities();\n return client;\n } catch (error) {\n process.emitWarning(`RMUX candidate ${binary} is unavailable: ${errorMessage(error)}`);\n // Try the next compatible candidate. Non-interactive calls can use the subprocess launcher.\n }\n }\n return undefined;\n }\n\n private prepareFiles(request: RmuxLaunchRequest, logPath: string, aux: SupervisorPaths): void {\n cleanupSupervisorFiles(aux);\n fs.writeFileSync(logPath, '', { mode: 0o600 });\n const env = environment(request.sessionId, request.interactive, this.env);\n // runnerHost supervises the command and watches the lifeline itself, so an\n // owner that dies mid-run is handled inside the pane rather than around it.\n const spec: CommandSpec = { command: request.command, cwd: request.cwd, env };\n writeCommandSpec(aux.spec, spec);\n }\n\n private auxPaths(id: string, sessionId?: string): SupervisorPaths {\n return supervisorPaths(this.paths.stateDirectory(sessionId), id);\n }\n\n /**\n * The sink the pane pipes into.\n *\n * An interactive run also asks for a raw copy: the scrubbed log it writes\n * beside it has had cursor movement taken out, which is what a terminal\n * needs most. Only interactive runs pay for it, because only they can be\n * attached to.\n */\n private logPipeCommand(logPath: string, donePath: string, request: RmuxLaunchRequest): string {\n const id = path.basename(logPath, '.log');\n return shellJoin([\n process.execPath,\n runtimeEntry('logSink'),\n logPath,\n this.paths.rotatedLogPathFor(id),\n String(getLogMaxBytes(this.env)),\n donePath,\n ...(request.interactive ? [this.paths.rawLogPathFor(id)] : []),\n ]);\n }\n\n private async monitor(rmux: Rmux, pane: Pane, target: string, aux: SupervisorPaths): Promise<ExitResult> {\n try {\n const paneCode = await waitForRunEnd(rmux, target, aux.exit);\n await waitForLogDrain(rmux, target, aux.logDone);\n return readExitMetadata(aux.exit) ?? { code: paneCode, signal: null };\n } finally {\n // The pane stays alive for log capture. Remove its session after draining,\n // allowing the last completed run to shut down the mux server too.\n let timer: ReturnType<typeof setTimeout> | undefined;\n const cleanup = async (): Promise<void> => {\n if (!(await sessionMissing(rmux, target))) await pane.server.session(target).kill();\n };\n try {\n await Promise.race([\n cleanup().catch((error: unknown) =>\n process.emitWarning(`Could not clean up completed RMUX target ${target}: ${errorMessage(error)}`),\n ),\n new Promise<void>((resolve) => {\n timer = setTimeout(() => {\n process.emitWarning(`Timed out cleaning up RMUX target ${target} after ${STOP_CLOSE_TIMEOUT_MS}ms`);\n resolve();\n }, STOP_CLOSE_TIMEOUT_MS);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n cleanupSupervisorFiles(aux);\n }\n }\n }\n\n private interactiveRun(handle: RunHandle, pane: Pane, completion: Promise<ExitResult>): PtyRun {\n let screen = '';\n let active = true;\n const handlers = new Set<(data: string) => void>();\n const refresh = async (): Promise<void> => {\n while (active) {\n const next = await pane.captureText().catch((error: unknown) => {\n process.emitWarning(`Could not capture RMUX screen for ${handle.name}: ${errorMessage(error)}`);\n return screen;\n });\n if (next !== screen) {\n screen = next;\n for (const handler of handlers) handler(next);\n }\n await delay(POLL_MS);\n }\n };\n void refresh();\n void completion\n .finally(() => {\n active = false;\n })\n .catch((error: unknown) =>\n process.emitWarning(`RMUX interactive completion failed for ${handle.name}: ${errorMessage(error)}`),\n );\n return {\n ...handle,\n write: (text) => {\n void pane.sendText(text).catch((error: unknown) => process.emitWarning(errorMessage(error)));\n },\n screen: () => screen,\n onData: (handler) => {\n handlers.add(handler);\n return () => handlers.delete(handler);\n },\n resize: (cols, rows) => {\n void pane\n .resize({ width: cols, height: rows })\n .catch((error: unknown) => process.emitWarning(errorMessage(error)));\n },\n };\n }\n}\n\nexport function rmuxPackageForTarget(platform: string, architecture: string): string | undefined {\n const target = `${platform}-${architecture}`;\n const packageName = PACKAGE_BY_PLATFORM[target];\n if (!packageName) process.emitWarning(`Bundled RMUX binary is unavailable for unsupported target ${target}`);\n return packageName;\n}\n\nexport function resolveBundledRmuxBinary(\n moduleUrl = import.meta.url,\n env: Readonly<Record<string, string | undefined>> = process.env,\n): string | undefined {\n const configured = env[RMUX_BINARY_ENV];\n if (configured !== undefined && configured !== '') return configured;\n const packageName = rmuxPackageForTarget(process.platform, process.arch);\n if (!packageName) return undefined;\n try {\n const require = createRequire(moduleUrl);\n const manifest = require.resolve(`${packageName}/package.json`);\n return path.join(path.dirname(manifest), VENDOR_DIRECTORY, 'bin', 'rmux');\n } catch (error) {\n process.emitWarning(`Bundled RMUX binary is unavailable for ${packageName}: ${errorMessage(error)}`);\n return undefined;\n }\n}\n\n/**\n * Make the bundled payload runnable before the launcher is spawned.\n *\n * The prebuilt packages reach npm with plain 0644 files, so the executable bit\n * the build set is not what lands on a user machine. Restoring it on the one\n * binary we spawn is not enough: rmux execs two files of its own,\n * `bin/rmux-daemon` and `libexec/rmux/rmux`, and the launcher fails on that\n * first exec with a permission error. Every file the payload ships is restored\n * here instead, which also covers a helper a later rmux release adds.\n *\n * A configured override (PO_RMUX_BINARY) usually points at a stand-alone\n * binary, so only paths that really sit inside a package vendor tree get the\n * walk. Files that are already executable are left untouched, since chmod on a\n * binary owned by someone else would throw and drop an otherwise usable\n * candidate.\n */\nexport function ensureExecutablePayload(binary: string): void {\n const vendor = path.resolve(path.dirname(binary), '..');\n const payload =\n path.basename(vendor) === VENDOR_DIRECTORY\n ? fs\n .readdirSync(vendor, { recursive: true, withFileTypes: true })\n .filter((entry) => entry.isFile())\n .map((entry) => path.join(entry.parentPath, entry.name))\n : [binary];\n for (const file of payload) {\n if ((fs.statSync(file).mode & EXECUTABLE_BITS) === 0) fs.chmodSync(file, EXECUTABLE_MODE);\n }\n}\n\nfunction socketName(repositoryPath: string): string {\n const hash = createHash('sha256').update(repositoryPath).digest('hex').slice(0, SOCKET_HASH_LENGTH);\n return `${SESSION_PREFIX}${hash}`;\n}\n\nfunction environment(\n sessionId: string,\n interactive: boolean,\n env: Readonly<Record<string, string | undefined>>,\n): Record<string, string> {\n const values: NodeJS.ProcessEnv = {\n ...env,\n ...(interactive ? {} : { ...NON_INTERACTIVE_ENV, ...noninteractiveEnvironment(env) }),\n // Applied to interactive runs as well: a pane is a tty either way, and an\n // agent sending input to a prompt still has no way past a pager.\n ...NO_TERMINAL_INPUT_ENV,\n PI_SESSION_ID: sessionId,\n };\n if (!interactive) delete values['FORCE_COLOR'];\n return Object.fromEntries(\n Object.entries(values).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n}\n\nasync function panePid(rmux: Rmux, target: string): Promise<number> {\n const response = await rmux.displayMessage(PANE_PID_FORMAT, { target });\n const message = typeof response['message'] === 'string' ? response['message'] : '';\n const pid = reportedPid(message);\n if (pid === undefined) throw new Error(`RMUX did not report a pane pid for ${target}`);\n return pid;\n}\n\n/** A pane pid as rmux prints it, or nothing when the output holds no usable pid. */\nfunction reportedPid(output: string): number | undefined {\n const pid = Number(output.trim());\n return Number.isInteger(pid) && pid > 0 ? pid : undefined;\n}\n\n/**\n * Waits for the run to end, preferring the supervisor's own record of it.\n *\n * The sidecar is written before the command's pane can end, and it outlives the\n * server that the pane's exit takes down with it. Watching for it means a run\n * that finishes inside a poll interval is observed when it finishes rather than\n * on the next tick. Asking the server stays the fallback for a supervisor that\n * died without recording anything.\n */\nasync function waitForRunEnd(rmux: Rmux, target: string, exitPath: string): Promise<number | null> {\n const landed = watchForFile(exitPath);\n let active = true;\n const readEvidence = async (): Promise<null> => {\n while (active) {\n if (await landed.appeared(POLL_MS)) return null;\n }\n return null;\n };\n const probePane = async (): Promise<number | null> => {\n while (active) {\n await delay(POLL_MS);\n if (!active) return null;\n const state = await readPaneExit(rmux, target);\n if (state.exited) return state.code;\n }\n return null;\n };\n try {\n // A stalled SDK request must not block the supervisor's durable evidence.\n // Keep only one pane request in flight, even when it never answers.\n return await Promise.race([readEvidence(), probePane()]);\n } finally {\n active = false;\n landed.close();\n }\n}\n\n/**\n * Gives the log sink a moment to mark the log complete.\n *\n * Normal completion retains the session until the sink records its final\n * writes. A lost session cannot guarantee a later marker, so it ends the wait.\n */\nasync function waitForLogDrain(rmux: Rmux, target: string, donePath: string): Promise<void> {\n const deadline = Date.now() + LOG_DRAIN_TIMEOUT_MS;\n const landed = watchForFile(donePath);\n let active = true;\n const readEvidence = async (): Promise<void> => {\n while (active && Date.now() < deadline) {\n if (await landed.appeared(LOG_DRAIN_POLL_MS)) return;\n }\n };\n const probeSession = async (): Promise<void> => {\n while (active && Date.now() < deadline) {\n await delay(LOG_DRAIN_POLL_MS);\n if (!active) return;\n if (await sessionMissing(rmux, target)) return;\n }\n };\n try {\n // The file loop enforces the deadline while a session query is outstanding.\n await Promise.race([readEvidence(), probeSession()]);\n } finally {\n active = false;\n landed.close();\n }\n}\n\nasync function closeOwnedSession(rmux: Rmux, target: string): Promise<boolean> {\n return new Promise((resolve) => {\n let settled = false;\n const finish = (result: boolean): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n resolve(result);\n };\n const timer = setTimeout(() => {\n process.emitWarning(`Timed out closing RMUX target ${target} after ${STOP_CLOSE_TIMEOUT_MS}ms`);\n finish(false);\n }, STOP_CLOSE_TIMEOUT_MS);\n void rmux\n .session(target)\n .kill()\n .then(\n () => finish(true),\n (error: unknown) => {\n process.emitWarning(`Could not close RMUX target ${target}: ${errorMessage(error)}`);\n finish(false);\n },\n );\n });\n}\n\nasync function waitForPaneStop(rmux: Rmux, target: string, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n try {\n if ((await readPaneExit(rmux, target)).exited) return true;\n } catch (error) {\n process.emitWarning(`Could not verify RMUX target ${target} stopped: ${errorMessage(error)}`);\n return false;\n }\n await delay(POLL_MS);\n }\n return false;\n}\n\n/**\n * One formatted read answers both questions this poll asks, so watching a run\n * costs the same single rmux call it always did.\n */\nasync function readPaneExit(rmux: Rmux, target: string): Promise<{ exited: boolean; code: number | null }> {\n let message: string;\n try {\n const response = await rmux.displayMessage(PANE_STATE_FORMAT, { target });\n message = typeof response['message'] === 'string' ? response['message'] : '';\n } catch {\n // The last session ending stops the server, so a server that cannot be\n // reached is the ordinary end of the last run rather than a fault.\n return { exited: true, code: null };\n }\n const [dead, status, ...rest] = message.trim().split(':');\n // A missing session formats as a live pane with no name rather than failing,\n // so the name is what says whether there is still anything to watch.\n if (rest.join(':') === '') return { exited: true, code: null };\n if (dead === '1' || dead === 'true') {\n const code = Number(status);\n return { exited: true, code: Number.isInteger(code) ? code : null };\n }\n return { exited: false, code: null };\n}\n\n/** A session that cannot be found, on a server that may itself be gone. */\nasync function sessionMissing(rmux: Rmux, target: string): Promise<boolean> {\n try {\n const probe = await rmux.cmd('has-session', '-t', target);\n return probe.returnCode !== 0;\n } catch {\n // No server to ask means no session to find.\n return true;\n }\n}\n\n/**\n * A pane that was already gone and a signal that could not be delivered are\n * opposite answers to \"is it stopped\", so they are reported apart.\n */\nfunction signalPane(pid: number, target: string): 'signalled' | 'gone' | 'failed' {\n try {\n process.kill(pid, 'SIGTERM');\n return 'signalled';\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ESRCH') return 'gone';\n process.emitWarning(`Could not signal RMUX target ${target}: ${errorMessage(error)}`);\n return 'failed';\n }\n}\n\nfunction readTail(target: string, maxBytes: number): string {\n let handle: number | undefined;\n try {\n const size = fs.statSync(target).size;\n const bytes = Math.min(size, maxBytes);\n const buffer = Buffer.alloc(bytes);\n handle = fs.openSync(target, 'r');\n fs.readSync(handle, buffer, 0, bytes, size - bytes);\n return buffer.toString('utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n process.emitWarning(`Could not read RMUX log ${target}: ${errorMessage(error)}`);\n }\n return '';\n } finally {\n if (handle !== undefined) fs.closeSync(handle);\n }\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(resolve, ms);\n timer.unref?.();\n });\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rtkProcessor-B9KPdyzr.mjs","names":[],"sources":["../src/constants/rtkProcessor.ts","../src/services/rtkProcessor/index.ts"],"sourcesContent":["export const BYTES_PER_MIB = 1_048_576;\nexport const RTK_STDIN_MAX_BYTES = 10_485_760;\nexport const DEFAULT_RTK_TIMEOUT_MS = 10_000;\nexport const RTK_KILL_WAIT_MS = 1_000;\nexport const OUTPUT_BUFFER_FACTOR = 2;\nexport const EXECUTABLE_MODE = 0o755;\nexport const SIMPLE_TOKEN_PATTERN = /^[A-Za-z0-9_./:@%+=,-]+$/u;\nexport const SHELL_CONTROL_PATTERN = /[\\r\\n;&|<>`$\\\\'\"(){}*?!]/u;\nexport const RTK_BINARY_ENV = 'PO_RTK_BINARY';\n","import { type ChildProcessWithoutNullStreams, spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\n\nimport {\n DEFAULT_RTK_TIMEOUT_MS,\n EXECUTABLE_MODE,\n OUTPUT_BUFFER_FACTOR,\n RTK_BINARY_ENV,\n RTK_KILL_WAIT_MS,\n RTK_STDIN_MAX_BYTES,\n SHELL_CONTROL_PATTERN,\n SIMPLE_TOKEN_PATTERN,\n} from '../../constants/rtkProcessor';\nimport {\n type IRtkProcessor,\n RTK_FAILED_WARNING,\n RTK_OVERSIZED_WARNING,\n RTK_TIMEOUT_WARNING,\n RTK_UNAVAILABLE_WARNING,\n type RtkFilter,\n type RtkProcessRequest,\n type RtkProcessResult,\n} from '../../types/rtkProcessor';\nimport type { RunnerSettings } from '../../types/runnerSettings';\nimport { getResultMaxBytes } from '../runnerConfig';\n\nconst GIT_DIFF_INCOMPATIBLE_OPTIONS = [\n '-s',\n '-z',\n '--raw',\n '--numstat',\n '--shortstat',\n '--stat',\n '--dirstat',\n '--dirstat-by-file',\n '--summary',\n '--compact-summary',\n '--name-only',\n '--name-status',\n '--check',\n '--binary',\n '--word-diff',\n '--word-diff-regex',\n '--color',\n '--color-words',\n '--color-moved',\n '--color-moved-ws',\n '--line-prefix',\n '--no-patch',\n '--patch-with-raw',\n '--patch-with-stat',\n '--ext-diff',\n '--textconv',\n '--quiet',\n '--submodule',\n] as const;\nconst STRUCTURED_SEARCH_INCOMPATIBLE_OPTIONS = [\n '--json',\n '--null',\n '--null-data',\n '--color',\n '--colour',\n '--after-context',\n '--before-context',\n '--context',\n '--no-filename',\n '--no-line-number',\n '--heading',\n] as const;\nconst PACKAGE_BY_PLATFORM: Readonly<Record<string, string>> = {\n 'darwin-arm64': '@agimon-ai/po-runner-rtk-darwin-arm64',\n 'darwin-x64': '@agimon-ai/po-runner-rtk-darwin-x64',\n 'linux-arm64': '@agimon-ai/po-runner-rtk-linux-arm64',\n 'linux-x64': '@agimon-ai/po-runner-rtk-linux-x64',\n};\n\ntype BinaryResolver = () => string | undefined;\n\nexport class RtkProcessor implements IRtkProcessor {\n /**\n * Latched once a binary proves unrunnable on this host.\n *\n * A glibc build installed on a musl host satisfies os and cpu, so it\n * resolves and then fails to exec. Without this the same doomed spawn is\n * paid on every command, and each one is reported as a processing failure\n * rather than the absence it actually is.\n */\n private unrunnable = false;\n\n constructor(\n private readonly resolveBinary: BinaryResolver = bundledBinary,\n private readonly timeoutMs = DEFAULT_RTK_TIMEOUT_MS,\n private readonly env: Readonly<Record<string, string | undefined>> = process.env,\n private readonly settings?: RunnerSettings,\n ) {}\n\n async process(request: RtkProcessRequest): Promise<RtkProcessResult> {\n const filter = classifyRtkFilter(request.command);\n if (!filter) return { kind: 'skipped' };\n\n let inputBytes: number;\n try {\n inputBytes = fs.statSync(request.logPath).size;\n } catch {\n return { kind: 'fallback', warning: RTK_FAILED_WARNING };\n }\n if (inputBytes > RTK_STDIN_MAX_BYTES) return { kind: 'fallback', warning: RTK_OVERSIZED_WARNING };\n\n if (this.unrunnable) return { kind: 'fallback', warning: RTK_UNAVAILABLE_WARNING };\n\n let binary: string | undefined;\n try {\n binary = this.resolveBinary === bundledBinary ? bundledBinary(this.env) : this.resolveBinary();\n if (!binary) return { kind: 'fallback', warning: RTK_UNAVAILABLE_WARNING };\n if ((fs.statSync(binary).mode & 0o111) === 0) fs.chmodSync(binary, EXECUTABLE_MODE);\n } catch {\n return { kind: 'fallback', warning: RTK_UNAVAILABLE_WARNING };\n }\n\n return this.pipe(binary, filter, request.logPath, inputBytes);\n }\n\n private pipe(binary: string, filter: RtkFilter, logPath: string, inputBytes: number): Promise<RtkProcessResult> {\n return new Promise((resolve) => {\n let child: ChildProcessWithoutNullStreams;\n try {\n child = spawn(binary, ['pipe', '-f', filter], { stdio: 'pipe' });\n } catch {\n this.unrunnable = true;\n resolve({ kind: 'fallback', warning: RTK_UNAVAILABLE_WARNING });\n return;\n }\n\n const input = fs.createReadStream(logPath);\n const outputLimit = getResultMaxBytes(this.env, this.settings) * OUTPUT_BUFFER_FACTOR;\n let head: Buffer<ArrayBufferLike> = Buffer.alloc(0);\n let output: Buffer<ArrayBufferLike> = Buffer.alloc(0);\n let outputBytes = 0;\n let newlineCount = 0;\n let lastByte: number | undefined;\n let settled = false;\n let fallbackWarning: string | undefined;\n let killWaitTimer: ReturnType<typeof setTimeout> | undefined;\n\n const finish = (result: RtkProcessResult): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n if (killWaitTimer) clearTimeout(killWaitTimer);\n input.destroy();\n resolve(result);\n };\n const stop = (warning: string): void => {\n if (settled) return;\n fallbackWarning = warning;\n let killed = false;\n try {\n killed = child.kill('SIGKILL');\n } catch {\n finish({ kind: 'fallback', warning });\n return;\n }\n if (!killed) {\n finish({ kind: 'fallback', warning });\n return;\n }\n killWaitTimer ??= setTimeout(() => finish({ kind: 'fallback', warning }), RTK_KILL_WAIT_MS);\n };\n const timer = setTimeout(() => stop(RTK_TIMEOUT_WARNING), this.timeoutMs);\n\n child.stdout.on('data', (chunk: Buffer) => {\n outputBytes += chunk.byteLength;\n for (const byte of chunk) if (byte === 0x0a) newlineCount += 1;\n lastByte = chunk.at(-1);\n if (head.byteLength < outputLimit) {\n head = Buffer.concat([head, chunk.subarray(0, outputLimit - head.byteLength)]);\n }\n output = appendTail(output, chunk, outputLimit);\n });\n child.stderr.resume();\n child.once('error', (error: NodeJS.ErrnoException) => {\n // Reaching the process is a precondition, not part of processing, so a\n // failure to start reports absence and is not attempted again.\n if (error.code === 'ENOENT' || error.code === 'EACCES' || error.code === 'ENOEXEC') {\n this.unrunnable = true;\n stop(RTK_UNAVAILABLE_WARNING);\n return;\n }\n stop(RTK_FAILED_WARNING);\n });\n child.stdin.once('error', () => stop(RTK_FAILED_WARNING));\n input.once('error', () => stop(RTK_FAILED_WARNING));\n child.once('close', (code) => {\n if (fallbackWarning) {\n finish({ kind: 'fallback', warning: fallbackWarning });\n return;\n }\n const processedOutput = decodeUtf8Tail(output);\n if (code !== 0 || (inputBytes > 0 && processedOutput.trim().length === 0)) {\n finish({ kind: 'fallback', warning: RTK_FAILED_WARNING });\n return;\n }\n const lines = newlineCount + (outputBytes > 0 && lastByte !== 0x0a ? 1 : 0);\n finish({\n kind: 'processed',\n result: {\n filter,\n // Only meaningful once the stream outgrew the buffer; below that\n // `output` already starts at byte zero.\n head: outputBytes > output.byteLength ? head.toString('utf8') : '',\n output: processedOutput,\n bytes: outputBytes,\n lines,\n },\n });\n });\n\n input.pipe(child.stdin);\n });\n }\n}\n\n/**\n * Classifies only whitespace-delimited single commands. Shell syntax, expansion,\n * quoting, and globbing are rejected instead of being partially interpreted.\n */\nexport function classifyRtkFilter(command: string): RtkFilter | undefined {\n if (SHELL_CONTROL_PATTERN.test(command)) return undefined;\n const trimmed = command.trim();\n if (!trimmed) return undefined;\n const tokens = trimmed.split(/[ \\t]+/u);\n if (tokens.some((token) => !SIMPLE_TOKEN_PATTERN.test(token))) return undefined;\n\n if (tokens[0] === 'cargo' && tokens[1] === 'test') {\n if (tokens.includes('--') || tokens.some((token) => token.startsWith('--message-format') || token === '--json')) {\n return undefined;\n }\n return 'cargo-test';\n }\n if (tokens[0] === 'pytest') {\n if (tokens.some((token) => token.startsWith('--json-report'))) return undefined;\n return 'pytest';\n }\n if (tokens[0] === 'git' && tokens[1] === 'diff') {\n if (\n tokens.some((token) =>\n GIT_DIFF_INCOMPATIBLE_OPTIONS.some((option) => token === option || token.startsWith(`${option}=`)),\n )\n ) {\n return undefined;\n }\n return 'git-diff';\n }\n if (tokens[0] === 'grep') {\n if (tokens.length < 4 || incompatibleStructuredSearch(tokens)) return undefined;\n return hasShortOrLongOption(tokens, 'n', '--line-number') && hasShortOrLongOption(tokens, 'H', '--with-filename')\n ? 'grep'\n : undefined;\n }\n if (tokens[0] === 'rg') {\n if (tokens.length < 4 || incompatibleStructuredSearch(tokens) || !tokens.includes('--no-heading')) return undefined;\n return hasShortOrLongOption(tokens, 'n', '--line-number') && hasShortOrLongOption(tokens, 'H', '--with-filename')\n ? 'grep'\n : undefined;\n }\n if (tokens[0] === 'go' && tokens[1] === 'test') {\n let jsonOutput = false;\n for (const token of tokens.slice(2)) {\n if (token === '-json' || token === '-json=true') jsonOutput = true;\n if (token === '-json=false') jsonOutput = false;\n }\n return jsonOutput ? 'go-test' : undefined;\n }\n if (tokens[0] === 'ruff' && tokens[1] === 'check') {\n const jsonOutput = tokens.some(\n (token, index) =>\n token === '--output-format=json' || (token === '--output-format' && tokens[index + 1] === 'json'),\n );\n return jsonOutput ? 'ruff-check' : undefined;\n }\n return undefined;\n}\n\nexport function rtkPackageForTarget(platform: string, architecture: string): string | undefined {\n const target = `${platform}-${architecture}`;\n const packageName = PACKAGE_BY_PLATFORM[target];\n if (!packageName) process.emitWarning(`Bundled RTK binary is unavailable for unsupported target ${target}`);\n return packageName;\n}\n\nfunction bundledBinary(env: Readonly<Record<string, string | undefined>> = process.env): string | undefined {\n const configured = env[RTK_BINARY_ENV];\n if (configured !== undefined && configured !== '') return configured;\n const packageName = rtkPackageForTarget(process.platform, process.arch);\n if (!packageName) return undefined;\n try {\n const require = createRequire(import.meta.url);\n const manifest = require.resolve(`${packageName}/package.json`);\n return path.join(path.dirname(manifest), 'vendor', 'bin', 'rtk');\n } catch {\n return undefined;\n }\n}\n\nfunction appendTail(\n current: Buffer<ArrayBufferLike>,\n chunk: Buffer<ArrayBufferLike>,\n limit: number,\n): Buffer<ArrayBufferLike> {\n if (chunk.byteLength >= limit) return Buffer.from(chunk.subarray(chunk.byteLength - limit));\n const combined = Buffer.concat([current, chunk]);\n return combined.byteLength > limit ? Buffer.from(combined.subarray(combined.byteLength - limit)) : combined;\n}\n\nfunction decodeUtf8Tail(output: Buffer<ArrayBufferLike>): string {\n let start = 0;\n while (start < output.byteLength && (output[start]! & 0xc0) === 0x80) start += 1;\n return output.subarray(start).toString('utf8');\n}\nfunction hasShortOrLongOption(tokens: readonly string[], short: string, long: string): boolean {\n return tokens.some(\n (token) => token === long || (token.startsWith('-') && !token.startsWith('--') && token.slice(1).includes(short)),\n );\n}\n\nfunction incompatibleStructuredSearch(tokens: readonly string[]): boolean {\n return tokens.some(\n (token) =>\n (token.startsWith('-') && !token.startsWith('--') && /[0ABCILNchzZ]/u.test(token.slice(1))) ||\n STRUCTURED_SEARCH_INCOMPATIBLE_OPTIONS.some((option) => token === option || token.startsWith(`${option}=`)),\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rtkProcessor-Bc4L4o_8.cjs","names":["fs","RTK_FAILED_WARNING","RTK_OVERSIZED_WARNING","RTK_UNAVAILABLE_WARNING","spawn","getResultMaxBytes","RTK_TIMEOUT_WARNING","createRequire","path"],"sources":["../src/constants/rtkProcessor.ts","../src/services/rtkProcessor/index.ts"],"sourcesContent":["export const BYTES_PER_MIB = 1_048_576;\nexport const RTK_STDIN_MAX_BYTES = 10_485_760;\nexport const DEFAULT_RTK_TIMEOUT_MS = 10_000;\nexport const RTK_KILL_WAIT_MS = 1_000;\nexport const OUTPUT_BUFFER_FACTOR = 2;\nexport const EXECUTABLE_MODE = 0o755;\nexport const SIMPLE_TOKEN_PATTERN = /^[A-Za-z0-9_./:@%+=,-]+$/u;\nexport const SHELL_CONTROL_PATTERN = /[\\r\\n;&|<>`$\\\\'\"(){}*?!]/u;\nexport const RTK_BINARY_ENV = 'PO_RTK_BINARY';\n","import { type ChildProcessWithoutNullStreams, spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\n\nimport {\n DEFAULT_RTK_TIMEOUT_MS,\n EXECUTABLE_MODE,\n OUTPUT_BUFFER_FACTOR,\n RTK_BINARY_ENV,\n RTK_KILL_WAIT_MS,\n RTK_STDIN_MAX_BYTES,\n SHELL_CONTROL_PATTERN,\n SIMPLE_TOKEN_PATTERN,\n} from '../../constants/rtkProcessor';\nimport {\n type IRtkProcessor,\n RTK_FAILED_WARNING,\n RTK_OVERSIZED_WARNING,\n RTK_TIMEOUT_WARNING,\n RTK_UNAVAILABLE_WARNING,\n type RtkFilter,\n type RtkProcessRequest,\n type RtkProcessResult,\n} from '../../types/rtkProcessor';\nimport type { RunnerSettings } from '../../types/runnerSettings';\nimport { getResultMaxBytes } from '../runnerConfig';\n\nconst GIT_DIFF_INCOMPATIBLE_OPTIONS = [\n '-s',\n '-z',\n '--raw',\n '--numstat',\n '--shortstat',\n '--stat',\n '--dirstat',\n '--dirstat-by-file',\n '--summary',\n '--compact-summary',\n '--name-only',\n '--name-status',\n '--check',\n '--binary',\n '--word-diff',\n '--word-diff-regex',\n '--color',\n '--color-words',\n '--color-moved',\n '--color-moved-ws',\n '--line-prefix',\n '--no-patch',\n '--patch-with-raw',\n '--patch-with-stat',\n '--ext-diff',\n '--textconv',\n '--quiet',\n '--submodule',\n] as const;\nconst STRUCTURED_SEARCH_INCOMPATIBLE_OPTIONS = [\n '--json',\n '--null',\n '--null-data',\n '--color',\n '--colour',\n '--after-context',\n '--before-context',\n '--context',\n '--no-filename',\n '--no-line-number',\n '--heading',\n] as const;\nconst PACKAGE_BY_PLATFORM: Readonly<Record<string, string>> = {\n 'darwin-arm64': '@agimon-ai/po-runner-rtk-darwin-arm64',\n 'darwin-x64': '@agimon-ai/po-runner-rtk-darwin-x64',\n 'linux-arm64': '@agimon-ai/po-runner-rtk-linux-arm64',\n 'linux-x64': '@agimon-ai/po-runner-rtk-linux-x64',\n};\n\ntype BinaryResolver = () => string | undefined;\n\nexport class RtkProcessor implements IRtkProcessor {\n /**\n * Latched once a binary proves unrunnable on this host.\n *\n * A glibc build installed on a musl host satisfies os and cpu, so it\n * resolves and then fails to exec. Without this the same doomed spawn is\n * paid on every command, and each one is reported as a processing failure\n * rather than the absence it actually is.\n */\n private unrunnable = false;\n\n constructor(\n private readonly resolveBinary: BinaryResolver = bundledBinary,\n private readonly timeoutMs = DEFAULT_RTK_TIMEOUT_MS,\n private readonly env: Readonly<Record<string, string | undefined>> = process.env,\n private readonly settings?: RunnerSettings,\n ) {}\n\n async process(request: RtkProcessRequest): Promise<RtkProcessResult> {\n const filter = classifyRtkFilter(request.command);\n if (!filter) return { kind: 'skipped' };\n\n let inputBytes: number;\n try {\n inputBytes = fs.statSync(request.logPath).size;\n } catch {\n return { kind: 'fallback', warning: RTK_FAILED_WARNING };\n }\n if (inputBytes > RTK_STDIN_MAX_BYTES) return { kind: 'fallback', warning: RTK_OVERSIZED_WARNING };\n\n if (this.unrunnable) return { kind: 'fallback', warning: RTK_UNAVAILABLE_WARNING };\n\n let binary: string | undefined;\n try {\n binary = this.resolveBinary === bundledBinary ? bundledBinary(this.env) : this.resolveBinary();\n if (!binary) return { kind: 'fallback', warning: RTK_UNAVAILABLE_WARNING };\n if ((fs.statSync(binary).mode & 0o111) === 0) fs.chmodSync(binary, EXECUTABLE_MODE);\n } catch {\n return { kind: 'fallback', warning: RTK_UNAVAILABLE_WARNING };\n }\n\n return this.pipe(binary, filter, request.logPath, inputBytes);\n }\n\n private pipe(binary: string, filter: RtkFilter, logPath: string, inputBytes: number): Promise<RtkProcessResult> {\n return new Promise((resolve) => {\n let child: ChildProcessWithoutNullStreams;\n try {\n child = spawn(binary, ['pipe', '-f', filter], { stdio: 'pipe' });\n } catch {\n this.unrunnable = true;\n resolve({ kind: 'fallback', warning: RTK_UNAVAILABLE_WARNING });\n return;\n }\n\n const input = fs.createReadStream(logPath);\n const outputLimit = getResultMaxBytes(this.env, this.settings) * OUTPUT_BUFFER_FACTOR;\n let head: Buffer<ArrayBufferLike> = Buffer.alloc(0);\n let output: Buffer<ArrayBufferLike> = Buffer.alloc(0);\n let outputBytes = 0;\n let newlineCount = 0;\n let lastByte: number | undefined;\n let settled = false;\n let fallbackWarning: string | undefined;\n let killWaitTimer: ReturnType<typeof setTimeout> | undefined;\n\n const finish = (result: RtkProcessResult): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n if (killWaitTimer) clearTimeout(killWaitTimer);\n input.destroy();\n resolve(result);\n };\n const stop = (warning: string): void => {\n if (settled) return;\n fallbackWarning = warning;\n let killed = false;\n try {\n killed = child.kill('SIGKILL');\n } catch {\n finish({ kind: 'fallback', warning });\n return;\n }\n if (!killed) {\n finish({ kind: 'fallback', warning });\n return;\n }\n killWaitTimer ??= setTimeout(() => finish({ kind: 'fallback', warning }), RTK_KILL_WAIT_MS);\n };\n const timer = setTimeout(() => stop(RTK_TIMEOUT_WARNING), this.timeoutMs);\n\n child.stdout.on('data', (chunk: Buffer) => {\n outputBytes += chunk.byteLength;\n for (const byte of chunk) if (byte === 0x0a) newlineCount += 1;\n lastByte = chunk.at(-1);\n if (head.byteLength < outputLimit) {\n head = Buffer.concat([head, chunk.subarray(0, outputLimit - head.byteLength)]);\n }\n output = appendTail(output, chunk, outputLimit);\n });\n child.stderr.resume();\n child.once('error', (error: NodeJS.ErrnoException) => {\n // Reaching the process is a precondition, not part of processing, so a\n // failure to start reports absence and is not attempted again.\n if (error.code === 'ENOENT' || error.code === 'EACCES' || error.code === 'ENOEXEC') {\n this.unrunnable = true;\n stop(RTK_UNAVAILABLE_WARNING);\n return;\n }\n stop(RTK_FAILED_WARNING);\n });\n child.stdin.once('error', () => stop(RTK_FAILED_WARNING));\n input.once('error', () => stop(RTK_FAILED_WARNING));\n child.once('close', (code) => {\n if (fallbackWarning) {\n finish({ kind: 'fallback', warning: fallbackWarning });\n return;\n }\n const processedOutput = decodeUtf8Tail(output);\n if (code !== 0 || (inputBytes > 0 && processedOutput.trim().length === 0)) {\n finish({ kind: 'fallback', warning: RTK_FAILED_WARNING });\n return;\n }\n const lines = newlineCount + (outputBytes > 0 && lastByte !== 0x0a ? 1 : 0);\n finish({\n kind: 'processed',\n result: {\n filter,\n // Only meaningful once the stream outgrew the buffer; below that\n // `output` already starts at byte zero.\n head: outputBytes > output.byteLength ? head.toString('utf8') : '',\n output: processedOutput,\n bytes: outputBytes,\n lines,\n },\n });\n });\n\n input.pipe(child.stdin);\n });\n }\n}\n\n/**\n * Classifies only whitespace-delimited single commands. Shell syntax, expansion,\n * quoting, and globbing are rejected instead of being partially interpreted.\n */\nexport function classifyRtkFilter(command: string): RtkFilter | undefined {\n if (SHELL_CONTROL_PATTERN.test(command)) return undefined;\n const trimmed = command.trim();\n if (!trimmed) return undefined;\n const tokens = trimmed.split(/[ \\t]+/u);\n if (tokens.some((token) => !SIMPLE_TOKEN_PATTERN.test(token))) return undefined;\n\n if (tokens[0] === 'cargo' && tokens[1] === 'test') {\n if (tokens.includes('--') || tokens.some((token) => token.startsWith('--message-format') || token === '--json')) {\n return undefined;\n }\n return 'cargo-test';\n }\n if (tokens[0] === 'pytest') {\n if (tokens.some((token) => token.startsWith('--json-report'))) return undefined;\n return 'pytest';\n }\n if (tokens[0] === 'git' && tokens[1] === 'diff') {\n if (\n tokens.some((token) =>\n GIT_DIFF_INCOMPATIBLE_OPTIONS.some((option) => token === option || token.startsWith(`${option}=`)),\n )\n ) {\n return undefined;\n }\n return 'git-diff';\n }\n if (tokens[0] === 'grep') {\n if (tokens.length < 4 || incompatibleStructuredSearch(tokens)) return undefined;\n return hasShortOrLongOption(tokens, 'n', '--line-number') && hasShortOrLongOption(tokens, 'H', '--with-filename')\n ? 'grep'\n : undefined;\n }\n if (tokens[0] === 'rg') {\n if (tokens.length < 4 || incompatibleStructuredSearch(tokens) || !tokens.includes('--no-heading')) return undefined;\n return hasShortOrLongOption(tokens, 'n', '--line-number') && hasShortOrLongOption(tokens, 'H', '--with-filename')\n ? 'grep'\n : undefined;\n }\n if (tokens[0] === 'go' && tokens[1] === 'test') {\n let jsonOutput = false;\n for (const token of tokens.slice(2)) {\n if (token === '-json' || token === '-json=true') jsonOutput = true;\n if (token === '-json=false') jsonOutput = false;\n }\n return jsonOutput ? 'go-test' : undefined;\n }\n if (tokens[0] === 'ruff' && tokens[1] === 'check') {\n const jsonOutput = tokens.some(\n (token, index) =>\n token === '--output-format=json' || (token === '--output-format' && tokens[index + 1] === 'json'),\n );\n return jsonOutput ? 'ruff-check' : undefined;\n }\n return undefined;\n}\n\nexport function rtkPackageForTarget(platform: string, architecture: string): string | undefined {\n const target = `${platform}-${architecture}`;\n const packageName = PACKAGE_BY_PLATFORM[target];\n if (!packageName) process.emitWarning(`Bundled RTK binary is unavailable for unsupported target ${target}`);\n return packageName;\n}\n\nfunction bundledBinary(env: Readonly<Record<string, string | undefined>> = process.env): string | undefined {\n const configured = env[RTK_BINARY_ENV];\n if (configured !== undefined && configured !== '') return configured;\n const packageName = rtkPackageForTarget(process.platform, process.arch);\n if (!packageName) return undefined;\n try {\n const require = createRequire(import.meta.url);\n const manifest = require.resolve(`${packageName}/package.json`);\n return path.join(path.dirname(manifest), 'vendor', 'bin', 'rtk');\n } catch {\n return undefined;\n }\n}\n\nfunction appendTail(\n current: Buffer<ArrayBufferLike>,\n chunk: Buffer<ArrayBufferLike>,\n limit: number,\n): Buffer<ArrayBufferLike> {\n if (chunk.byteLength >= limit) return Buffer.from(chunk.subarray(chunk.byteLength - limit));\n const combined = Buffer.concat([current, chunk]);\n return combined.byteLength > limit ? Buffer.from(combined.subarray(combined.byteLength - limit)) : combined;\n}\n\nfunction decodeUtf8Tail(output: Buffer<ArrayBufferLike>): string {\n let start = 0;\n while (start < output.byteLength && (output[start]! & 0xc0) === 0x80) start += 1;\n return output.subarray(start).toString('utf8');\n}\nfunction hasShortOrLongOption(tokens: readonly string[], short: string, long: string): boolean {\n return tokens.some(\n (token) => token === long || (token.startsWith('-') && !token.startsWith('--') && token.slice(1).includes(short)),\n );\n}\n\nfunction incompatibleStructuredSearch(tokens: readonly string[]): boolean {\n return tokens.some(\n (token) =>\n (token.startsWith('-') && !token.startsWith('--') && /[0ABCILNchzZ]/u.test(token.slice(1))) ||\n STRUCTURED_SEARCH_INCOMPATIBLE_OPTIONS.some((option) => token === option || token.startsWith(`${option}=`)),\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runnerConfig-BQBlVAXn.mjs","names":[],"sources":["../src/constants/runnerConfig.ts","../src/models/runnerSettings.ts","../src/services/runnerConfig/index.ts"],"sourcesContent":["export const BG_THRESHOLD_MS_ENV = 'DOOM_RUNNER_BG_THRESHOLD_MS';\nexport const RESULT_MAX_BYTES_ENV = 'DOOM_RUNNER_RESULT_MAX_BYTES';\nexport const SUCCESS_RESULT_MAX_BYTES_ENV = 'DOOM_RUNNER_SUCCESS_RESULT_MAX_BYTES';\nexport const RESULT_MAX_TOKENS_ENV = 'DOOM_RUNNER_RESULT_MAX_TOKENS';\nexport const SUCCESS_RESULT_MAX_TOKENS_ENV = 'DOOM_RUNNER_SUCCESS_RESULT_MAX_TOKENS';\nexport const LOG_MAX_BYTES_ENV = 'DOOM_RUNNER_LOG_MAX_BYTES';\nexport const LOG_TTL_MS_ENV = 'DOOM_RUNNER_LOG_TTL_MS';\nexport const MAX_COMPLETED_RUNNERS_ENV = 'DOOM_RUNNER_MAX_COMPLETED_RUNNERS';\nexport const LOG_DIR_ENV = 'DOOM_RUNNER_LOG_DIR';\nexport const DEFAULT_BG_THRESHOLD_MS = 60_000;\nexport const DEFAULT_RESULT_MAX_BYTES = 8_192;\nexport const DEFAULT_RESULT_MAX_LINES = 120;\nexport const DEFAULT_SUCCESS_RESULT_MAX_BYTES = 2_048;\nexport const DEFAULT_RESULT_MAX_TOKENS = 2_048;\nexport const DEFAULT_SUCCESS_RESULT_MAX_TOKENS = 512;\nexport const DEFAULT_HEAD_RATIO = 0.2;\nexport const DEFAULT_ERROR_BUDGET_RATIO = 0.2;\nexport const DEFAULT_ERROR_MAX_ENTRIES = 10;\nexport const DEFAULT_ERROR_MAX_VARIANTS_JOINED = 6;\nexport const DEFAULT_LOG_MAX_BYTES = 5_242_880;\nexport const DEFAULT_LOG_TTL_MS = 604_800_000;\nexport const DEFAULT_MAX_COMPLETED_RUNNERS = 100;\n","import type { RunnerSettings } from '../types/runnerSettings';\nexport const runnerSettingsState: { value: RunnerSettings } = { value: {} };\n","import {\n BG_THRESHOLD_MS_ENV,\n DEFAULT_BG_THRESHOLD_MS,\n DEFAULT_ERROR_BUDGET_RATIO,\n DEFAULT_ERROR_MAX_ENTRIES,\n DEFAULT_ERROR_MAX_VARIANTS_JOINED,\n DEFAULT_HEAD_RATIO,\n DEFAULT_LOG_MAX_BYTES,\n DEFAULT_LOG_TTL_MS,\n DEFAULT_MAX_COMPLETED_RUNNERS,\n DEFAULT_RESULT_MAX_BYTES,\n DEFAULT_RESULT_MAX_LINES,\n DEFAULT_RESULT_MAX_TOKENS,\n DEFAULT_SUCCESS_RESULT_MAX_BYTES,\n DEFAULT_SUCCESS_RESULT_MAX_TOKENS,\n LOG_MAX_BYTES_ENV,\n LOG_TTL_MS_ENV,\n MAX_COMPLETED_RUNNERS_ENV,\n RESULT_MAX_BYTES_ENV,\n RESULT_MAX_TOKENS_ENV,\n SUCCESS_RESULT_MAX_BYTES_ENV,\n SUCCESS_RESULT_MAX_TOKENS_ENV,\n} from '../../constants/runnerConfig';\n/**\n * Extension configuration, read from the environment.\n *\n * Env rather than a config file, matching doom-task: po already carries\n * per-launch state to Pi through env vars.\n */\n/** Unscoped override for the runner log directory. */\nimport type { RunnerSettings } from '../../types/runnerSettings';\n\n/** A bash call still running at this point is promoted to a named runner. */\n/** Tool results past this size are excerpted and spilled to the log file. */\n/** Line ceiling for a single tool result, applied alongside the byte ceiling. */\n/**\n * A successful command gets a much smaller budget than a failing one. Exiting 0\n * has already reported the outcome, so its output buys far less than a failure's.\n */\n/**\n * Token ceilings sit alongside the byte ones because bytes do not track context\n * cost: 8 KiB of prose is roughly 2k tokens, while 8 KiB of base64 or CJK is\n * several times that. Whichever ceiling binds first wins.\n */\n/** Share of the budget spent on the leading excerpt; the remainder goes to the tail. */\n/** Share reserved for errors rescued from the elided middle, when any exist. */\n/** Distinct failures rescued from the elided middle. */\n/** Variants joined inside one bracket before the rest become a count. */\n/** Legacy rotation value retained so existing configuration imports remain compatible. */\n/** Retention window for logs with no live registry record. */\n/**\n * Completed runners a single session keeps on disk.\n *\n * A count bound, not just an age one, because a session that stays open for a\n * working day never ages its own records past the TTL: they would accumulate\n * for as long as the session lives.\n */\n\nfunction positiveNumber(raw: string | undefined, fallback: number): number {\n const value = Number(raw);\n return Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\n/** Age at which a bash call becomes a background runner. */\nexport function getBackgroundThresholdMs(env: NodeJS.ProcessEnv = process.env): number {\n return positiveNumber(env[BG_THRESHOLD_MS_ENV], DEFAULT_BG_THRESHOLD_MS);\n}\n\n/** Byte ceiling for a single tool result before tail truncation kicks in. */\nexport function getResultMaxBytes(\n env: NodeJS.ProcessEnv = process.env,\n settings: RunnerSettings = runnerSettingsState.value,\n): number {\n return positiveNumber(env[RESULT_MAX_BYTES_ENV], settings.maxResultBytes ?? DEFAULT_RESULT_MAX_BYTES);\n}\n\n/** Legacy rotation setting retained for public API compatibility. */\nexport function getLogMaxBytes(env: NodeJS.ProcessEnv = process.env): number {\n return positiveNumber(env[LOG_MAX_BYTES_ENV], DEFAULT_LOG_MAX_BYTES);\n}\n\n/** Retention window for orphaned runner logs. */\nexport function getLogTtlMs(env: NodeJS.ProcessEnv = process.env): number {\n return positiveNumber(env[LOG_TTL_MS_ENV], DEFAULT_LOG_TTL_MS);\n}\n\n/** Completed runners one session retains before the oldest are swept. */\nexport function getMaxCompletedRunners(env: NodeJS.ProcessEnv = process.env): number {\n return positiveNumber(env[MAX_COMPLETED_RUNNERS_ENV], DEFAULT_MAX_COMPLETED_RUNNERS);\n}\n\n/**\n * Project settings sit below the environment on purpose: a checked-in file is\n * the project's baseline, while an environment variable is set for one run.\n */\nimport { runnerSettingsState } from '../../models/runnerSettings';\n\nexport function setRunnerSettings(settings: RunnerSettings): void {\n runnerSettingsState.value = settings;\n}\n\nexport function getRunnerSettings(): RunnerSettings {\n return runnerSettingsState.value;\n}\n\n/** Byte ceiling for the result of a command that succeeded. */\nexport function getSuccessResultMaxBytes(\n env: NodeJS.ProcessEnv = process.env,\n settings: RunnerSettings = runnerSettingsState.value,\n): number {\n return positiveNumber(\n env[SUCCESS_RESULT_MAX_BYTES_ENV],\n settings.successMaxResultBytes ?? DEFAULT_SUCCESS_RESULT_MAX_BYTES,\n );\n}\n\n/** Token ceiling for a single tool result. */\nexport function getResultMaxTokens(\n env: NodeJS.ProcessEnv = process.env,\n settings: RunnerSettings = runnerSettingsState.value,\n): number {\n return positiveNumber(env[RESULT_MAX_TOKENS_ENV], settings.maxResultTokens ?? DEFAULT_RESULT_MAX_TOKENS);\n}\n\n/** Token ceiling for the result of a command that succeeded. */\nexport function getSuccessResultMaxTokens(\n env: NodeJS.ProcessEnv = process.env,\n settings: RunnerSettings = runnerSettingsState.value,\n): number {\n return positiveNumber(\n env[SUCCESS_RESULT_MAX_TOKENS_ENV],\n settings.successMaxResultTokens ?? DEFAULT_SUCCESS_RESULT_MAX_TOKENS,\n );\n}\n\n/** Line ceiling for a single tool result. */\nexport function getResultMaxLines(settings: RunnerSettings = runnerSettingsState.value): number {\n return settings.maxResultLines ?? DEFAULT_RESULT_MAX_LINES;\n}\n\nexport function getHeadRatio(settings: RunnerSettings = runnerSettingsState.value): number {\n return settings.headRatio ?? DEFAULT_HEAD_RATIO;\n}\n\nexport function getErrorBudgetRatio(settings: RunnerSettings = runnerSettingsState.value): number {\n return settings.errorBudgetRatio ?? DEFAULT_ERROR_BUDGET_RATIO;\n}\n\nexport function getErrorMaxEntries(settings: RunnerSettings = runnerSettingsState.value): number {\n return settings.errorMaxEntries ?? DEFAULT_ERROR_MAX_ENTRIES;\n}\n\nexport function getErrorMaxVariantsJoined(settings: RunnerSettings = runnerSettingsState.value): number {\n return settings.errorMaxVariantsJoined ?? DEFAULT_ERROR_MAX_VARIANTS_JOINED;\n}\n\n/** Extra severity patterns appended to the built-in matcher. */\nexport function getErrorPatterns(settings: RunnerSettings = runnerSettingsState.value): readonly string[] {\n return settings.errorPatterns ?? [];\n}\n\n/** Defaults for agent-owned, noninteractive child processes only. Explicit settings still win. */\nexport function noninteractiveEnvironment(\n environment: Readonly<Record<string, string | undefined>>,\n): Record<string, string> {\n return {\n NX_NATIVE_COMMAND_RUNNER: environment.NX_NATIVE_COMMAND_RUNNER ?? 'false',\n NX_TUI: environment.NX_TUI ?? 'false',\n NX_PARALLEL: environment.NX_PARALLEL ?? '1',\n DOOM_RUNNER_MAX_WORKERS: environment.DOOM_RUNNER_MAX_WORKERS ?? '2',\n PLAYWRIGHT_WORKERS: environment.PLAYWRIGHT_WORKERS ?? '1',\n VITEST_MAX_WORKERS: environment.VITEST_MAX_WORKERS ?? '2',\n };\n}\n"],"mappings":";AAAA,MAAa,sBAAsB;AACnC,MAAa,uBAAuB;AACpC,MAAa,+BAA+B;AAC5C,MAAa,wBAAwB;AACrC,MAAa,gCAAgC;AAC7C,MAAa,oBAAoB;AACjC,MAAa,iBAAiB;AAC9B,MAAa,4BAA4B;AACzC,MAAa,cAAc;AAC3B,MAAa,0BAA0B;AACvC,MAAa,2BAA2B;AACxC,MAAa,2BAA2B;AACxC,MAAa,mCAAmC;AAChD,MAAa,4BAA4B;AACzC,MAAa,oCAAoC;AACjD,MAAa,qBAAqB;AAClC,MAAa,6BAA6B;AAC1C,MAAa,4BAA4B;AACzC,MAAa,oCAAoC;AACjD,MAAa,wBAAwB;AACrC,MAAa,qBAAqB;AAClC,MAAa,gCAAgC;;;ACpB7C,MAAa,sBAAiD,EAAE,OAAO,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACyD1E,SAAS,eAAe,KAAyB,UAA0B;CACzE,MAAM,QAAQ,OAAO,GAAG;CACxB,OAAO,OAAO,SAAS,KAAK,KAAK,QAAQ,IAAI,QAAQ;AACvD;;AAGA,SAAgB,yBAAyB,MAAyB,QAAQ,KAAa;CACrF,OAAO,eAAe,IAAI,sBAAsB,uBAAuB;AACzE;;AAGA,SAAgB,kBACd,MAAyB,QAAQ,KACjC,WAA2B,oBAAoB,OACvC;CACR,OAAO,eAAe,IAAI,uBAAuB,SAAS,kBAAA,IAA0C;AACtG;;AAGA,SAAgB,eAAe,MAAyB,QAAQ,KAAa;CAC3E,OAAO,eAAe,IAAI,oBAAoB,qBAAqB;AACrE;;AAGA,SAAgB,YAAY,MAAyB,QAAQ,KAAa;CACxE,OAAO,eAAe,IAAI,iBAAiB,kBAAkB;AAC/D;;AAGA,SAAgB,uBAAuB,MAAyB,QAAQ,KAAa;CACnF,OAAO,eAAe,IAAI,4BAAA,GAAyD;AACrF;AAQA,SAAgB,kBAAkB,UAAgC;CAChE,oBAAoB,QAAQ;AAC9B;AAEA,SAAgB,oBAAoC;CAClD,OAAO,oBAAoB;AAC7B;;AAGA,SAAgB,yBACd,MAAyB,QAAQ,KACjC,WAA2B,oBAAoB,OACvC;CACR,OAAO,eACL,IAAI,+BACJ,SAAS,yBAAA,IACX;AACF;;AAGA,SAAgB,mBACd,MAAyB,QAAQ,KACjC,WAA2B,oBAAoB,OACvC;CACR,OAAO,eAAe,IAAI,wBAAwB,SAAS,mBAAA,IAA4C;AACzG;;AAGA,SAAgB,0BACd,MAAyB,QAAQ,KACjC,WAA2B,oBAAoB,OACvC;CACR,OAAO,eACL,IAAI,gCACJ,SAAS,0BAAA,GACX;AACF;;AAGA,SAAgB,kBAAkB,WAA2B,oBAAoB,OAAe;CAC9F,OAAO,SAAS,kBAAA;AAClB;AAEA,SAAgB,aAAa,WAA2B,oBAAoB,OAAe;CACzF,OAAO,SAAS,aAAA;AAClB;AAEA,SAAgB,oBAAoB,WAA2B,oBAAoB,OAAe;CAChG,OAAO,SAAS,oBAAA;AAClB;AAEA,SAAgB,mBAAmB,WAA2B,oBAAoB,OAAe;CAC/F,OAAO,SAAS,mBAAA;AAClB;AAEA,SAAgB,0BAA0B,WAA2B,oBAAoB,OAAe;CACtG,OAAO,SAAS,0BAAA;AAClB;;AAGA,SAAgB,iBAAiB,WAA2B,oBAAoB,OAA0B;CACxG,OAAO,SAAS,iBAAiB,CAAC;AACpC;;AAGA,SAAgB,0BACd,aACwB;CACxB,OAAO;EACL,0BAA0B,YAAY,4BAA4B;EAClE,QAAQ,YAAY,UAAU;EAC9B,aAAa,YAAY,eAAe;EACxC,yBAAyB,YAAY,2BAA2B;EAChE,oBAAoB,YAAY,sBAAsB;EACtD,oBAAoB,YAAY,sBAAsB;CACxD;AACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runnerConfig-D2tGq5ZM.cjs","names":[],"sources":["../src/constants/runnerConfig.ts","../src/models/runnerSettings.ts","../src/services/runnerConfig/index.ts"],"sourcesContent":["export const BG_THRESHOLD_MS_ENV = 'DOOM_RUNNER_BG_THRESHOLD_MS';\nexport const RESULT_MAX_BYTES_ENV = 'DOOM_RUNNER_RESULT_MAX_BYTES';\nexport const SUCCESS_RESULT_MAX_BYTES_ENV = 'DOOM_RUNNER_SUCCESS_RESULT_MAX_BYTES';\nexport const RESULT_MAX_TOKENS_ENV = 'DOOM_RUNNER_RESULT_MAX_TOKENS';\nexport const SUCCESS_RESULT_MAX_TOKENS_ENV = 'DOOM_RUNNER_SUCCESS_RESULT_MAX_TOKENS';\nexport const LOG_MAX_BYTES_ENV = 'DOOM_RUNNER_LOG_MAX_BYTES';\nexport const LOG_TTL_MS_ENV = 'DOOM_RUNNER_LOG_TTL_MS';\nexport const MAX_COMPLETED_RUNNERS_ENV = 'DOOM_RUNNER_MAX_COMPLETED_RUNNERS';\nexport const LOG_DIR_ENV = 'DOOM_RUNNER_LOG_DIR';\nexport const DEFAULT_BG_THRESHOLD_MS = 60_000;\nexport const DEFAULT_RESULT_MAX_BYTES = 8_192;\nexport const DEFAULT_RESULT_MAX_LINES = 120;\nexport const DEFAULT_SUCCESS_RESULT_MAX_BYTES = 2_048;\nexport const DEFAULT_RESULT_MAX_TOKENS = 2_048;\nexport const DEFAULT_SUCCESS_RESULT_MAX_TOKENS = 512;\nexport const DEFAULT_HEAD_RATIO = 0.2;\nexport const DEFAULT_ERROR_BUDGET_RATIO = 0.2;\nexport const DEFAULT_ERROR_MAX_ENTRIES = 10;\nexport const DEFAULT_ERROR_MAX_VARIANTS_JOINED = 6;\nexport const DEFAULT_LOG_MAX_BYTES = 5_242_880;\nexport const DEFAULT_LOG_TTL_MS = 604_800_000;\nexport const DEFAULT_MAX_COMPLETED_RUNNERS = 100;\n","import type { RunnerSettings } from '../types/runnerSettings';\nexport const runnerSettingsState: { value: RunnerSettings } = { value: {} };\n","import {\n BG_THRESHOLD_MS_ENV,\n DEFAULT_BG_THRESHOLD_MS,\n DEFAULT_ERROR_BUDGET_RATIO,\n DEFAULT_ERROR_MAX_ENTRIES,\n DEFAULT_ERROR_MAX_VARIANTS_JOINED,\n DEFAULT_HEAD_RATIO,\n DEFAULT_LOG_MAX_BYTES,\n DEFAULT_LOG_TTL_MS,\n DEFAULT_MAX_COMPLETED_RUNNERS,\n DEFAULT_RESULT_MAX_BYTES,\n DEFAULT_RESULT_MAX_LINES,\n DEFAULT_RESULT_MAX_TOKENS,\n DEFAULT_SUCCESS_RESULT_MAX_BYTES,\n DEFAULT_SUCCESS_RESULT_MAX_TOKENS,\n LOG_MAX_BYTES_ENV,\n LOG_TTL_MS_ENV,\n MAX_COMPLETED_RUNNERS_ENV,\n RESULT_MAX_BYTES_ENV,\n RESULT_MAX_TOKENS_ENV,\n SUCCESS_RESULT_MAX_BYTES_ENV,\n SUCCESS_RESULT_MAX_TOKENS_ENV,\n} from '../../constants/runnerConfig';\n/**\n * Extension configuration, read from the environment.\n *\n * Env rather than a config file, matching doom-task: po already carries\n * per-launch state to Pi through env vars.\n */\n/** Unscoped override for the runner log directory. */\nimport type { RunnerSettings } from '../../types/runnerSettings';\n\n/** A bash call still running at this point is promoted to a named runner. */\n/** Tool results past this size are excerpted and spilled to the log file. */\n/** Line ceiling for a single tool result, applied alongside the byte ceiling. */\n/**\n * A successful command gets a much smaller budget than a failing one. Exiting 0\n * has already reported the outcome, so its output buys far less than a failure's.\n */\n/**\n * Token ceilings sit alongside the byte ones because bytes do not track context\n * cost: 8 KiB of prose is roughly 2k tokens, while 8 KiB of base64 or CJK is\n * several times that. Whichever ceiling binds first wins.\n */\n/** Share of the budget spent on the leading excerpt; the remainder goes to the tail. */\n/** Share reserved for errors rescued from the elided middle, when any exist. */\n/** Distinct failures rescued from the elided middle. */\n/** Variants joined inside one bracket before the rest become a count. */\n/** Legacy rotation value retained so existing configuration imports remain compatible. */\n/** Retention window for logs with no live registry record. */\n/**\n * Completed runners a single session keeps on disk.\n *\n * A count bound, not just an age one, because a session that stays open for a\n * working day never ages its own records past the TTL: they would accumulate\n * for as long as the session lives.\n */\n\nfunction positiveNumber(raw: string | undefined, fallback: number): number {\n const value = Number(raw);\n return Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\n/** Age at which a bash call becomes a background runner. */\nexport function getBackgroundThresholdMs(env: NodeJS.ProcessEnv = process.env): number {\n return positiveNumber(env[BG_THRESHOLD_MS_ENV], DEFAULT_BG_THRESHOLD_MS);\n}\n\n/** Byte ceiling for a single tool result before tail truncation kicks in. */\nexport function getResultMaxBytes(\n env: NodeJS.ProcessEnv = process.env,\n settings: RunnerSettings = runnerSettingsState.value,\n): number {\n return positiveNumber(env[RESULT_MAX_BYTES_ENV], settings.maxResultBytes ?? DEFAULT_RESULT_MAX_BYTES);\n}\n\n/** Legacy rotation setting retained for public API compatibility. */\nexport function getLogMaxBytes(env: NodeJS.ProcessEnv = process.env): number {\n return positiveNumber(env[LOG_MAX_BYTES_ENV], DEFAULT_LOG_MAX_BYTES);\n}\n\n/** Retention window for orphaned runner logs. */\nexport function getLogTtlMs(env: NodeJS.ProcessEnv = process.env): number {\n return positiveNumber(env[LOG_TTL_MS_ENV], DEFAULT_LOG_TTL_MS);\n}\n\n/** Completed runners one session retains before the oldest are swept. */\nexport function getMaxCompletedRunners(env: NodeJS.ProcessEnv = process.env): number {\n return positiveNumber(env[MAX_COMPLETED_RUNNERS_ENV], DEFAULT_MAX_COMPLETED_RUNNERS);\n}\n\n/**\n * Project settings sit below the environment on purpose: a checked-in file is\n * the project's baseline, while an environment variable is set for one run.\n */\nimport { runnerSettingsState } from '../../models/runnerSettings';\n\nexport function setRunnerSettings(settings: RunnerSettings): void {\n runnerSettingsState.value = settings;\n}\n\nexport function getRunnerSettings(): RunnerSettings {\n return runnerSettingsState.value;\n}\n\n/** Byte ceiling for the result of a command that succeeded. */\nexport function getSuccessResultMaxBytes(\n env: NodeJS.ProcessEnv = process.env,\n settings: RunnerSettings = runnerSettingsState.value,\n): number {\n return positiveNumber(\n env[SUCCESS_RESULT_MAX_BYTES_ENV],\n settings.successMaxResultBytes ?? DEFAULT_SUCCESS_RESULT_MAX_BYTES,\n );\n}\n\n/** Token ceiling for a single tool result. */\nexport function getResultMaxTokens(\n env: NodeJS.ProcessEnv = process.env,\n settings: RunnerSettings = runnerSettingsState.value,\n): number {\n return positiveNumber(env[RESULT_MAX_TOKENS_ENV], settings.maxResultTokens ?? DEFAULT_RESULT_MAX_TOKENS);\n}\n\n/** Token ceiling for the result of a command that succeeded. */\nexport function getSuccessResultMaxTokens(\n env: NodeJS.ProcessEnv = process.env,\n settings: RunnerSettings = runnerSettingsState.value,\n): number {\n return positiveNumber(\n env[SUCCESS_RESULT_MAX_TOKENS_ENV],\n settings.successMaxResultTokens ?? DEFAULT_SUCCESS_RESULT_MAX_TOKENS,\n );\n}\n\n/** Line ceiling for a single tool result. */\nexport function getResultMaxLines(settings: RunnerSettings = runnerSettingsState.value): number {\n return settings.maxResultLines ?? DEFAULT_RESULT_MAX_LINES;\n}\n\nexport function getHeadRatio(settings: RunnerSettings = runnerSettingsState.value): number {\n return settings.headRatio ?? DEFAULT_HEAD_RATIO;\n}\n\nexport function getErrorBudgetRatio(settings: RunnerSettings = runnerSettingsState.value): number {\n return settings.errorBudgetRatio ?? DEFAULT_ERROR_BUDGET_RATIO;\n}\n\nexport function getErrorMaxEntries(settings: RunnerSettings = runnerSettingsState.value): number {\n return settings.errorMaxEntries ?? DEFAULT_ERROR_MAX_ENTRIES;\n}\n\nexport function getErrorMaxVariantsJoined(settings: RunnerSettings = runnerSettingsState.value): number {\n return settings.errorMaxVariantsJoined ?? DEFAULT_ERROR_MAX_VARIANTS_JOINED;\n}\n\n/** Extra severity patterns appended to the built-in matcher. */\nexport function getErrorPatterns(settings: RunnerSettings = runnerSettingsState.value): readonly string[] {\n return settings.errorPatterns ?? [];\n}\n\n/** Defaults for agent-owned, noninteractive child processes only. Explicit settings still win. */\nexport function noninteractiveEnvironment(\n environment: Readonly<Record<string, string | undefined>>,\n): Record<string, string> {\n return {\n NX_NATIVE_COMMAND_RUNNER: environment.NX_NATIVE_COMMAND_RUNNER ?? 'false',\n NX_TUI: environment.NX_TUI ?? 'false',\n NX_PARALLEL: environment.NX_PARALLEL ?? '1',\n DOOM_RUNNER_MAX_WORKERS: environment.DOOM_RUNNER_MAX_WORKERS ?? '2',\n PLAYWRIGHT_WORKERS: environment.PLAYWRIGHT_WORKERS ?? '1',\n VITEST_MAX_WORKERS: environment.VITEST_MAX_WORKERS ?? '2',\n };\n}\n"],"mappings":";AAAA,MAAa,sBAAsB;AACnC,MAAa,uBAAuB;AACpC,MAAa,+BAA+B;AAC5C,MAAa,wBAAwB;AACrC,MAAa,gCAAgC;AAC7C,MAAa,oBAAoB;AACjC,MAAa,iBAAiB;AAC9B,MAAa,4BAA4B;AACzC,MAAa,cAAc;AAC3B,MAAa,0BAA0B;AACvC,MAAa,2BAA2B;AACxC,MAAa,2BAA2B;AACxC,MAAa,mCAAmC;AAChD,MAAa,4BAA4B;AACzC,MAAa,oCAAoC;AACjD,MAAa,qBAAqB;AAClC,MAAa,6BAA6B;AAC1C,MAAa,4BAA4B;AACzC,MAAa,oCAAoC;AACjD,MAAa,wBAAwB;AACrC,MAAa,qBAAqB;AAClC,MAAa,gCAAgC;;;ACpB7C,MAAa,sBAAiD,EAAE,OAAO,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACyD1E,SAAS,eAAe,KAAyB,UAA0B;CACzE,MAAM,QAAQ,OAAO,GAAG;CACxB,OAAO,OAAO,SAAS,KAAK,KAAK,QAAQ,IAAI,QAAQ;AACvD;;AAGA,SAAgB,yBAAyB,MAAyB,QAAQ,KAAa;CACrF,OAAO,eAAe,IAAI,sBAAsB,uBAAuB;AACzE;;AAGA,SAAgB,kBACd,MAAyB,QAAQ,KACjC,WAA2B,oBAAoB,OACvC;CACR,OAAO,eAAe,IAAI,uBAAuB,SAAS,kBAAA,IAA0C;AACtG;;AAGA,SAAgB,eAAe,MAAyB,QAAQ,KAAa;CAC3E,OAAO,eAAe,IAAI,oBAAoB,qBAAqB;AACrE;;AAGA,SAAgB,YAAY,MAAyB,QAAQ,KAAa;CACxE,OAAO,eAAe,IAAI,iBAAiB,kBAAkB;AAC/D;;AAGA,SAAgB,uBAAuB,MAAyB,QAAQ,KAAa;CACnF,OAAO,eAAe,IAAI,4BAAA,GAAyD;AACrF;AAQA,SAAgB,kBAAkB,UAAgC;CAChE,oBAAoB,QAAQ;AAC9B;AAEA,SAAgB,oBAAoC;CAClD,OAAO,oBAAoB;AAC7B;;AAGA,SAAgB,yBACd,MAAyB,QAAQ,KACjC,WAA2B,oBAAoB,OACvC;CACR,OAAO,eACL,IAAI,+BACJ,SAAS,yBAAA,IACX;AACF;;AAGA,SAAgB,mBACd,MAAyB,QAAQ,KACjC,WAA2B,oBAAoB,OACvC;CACR,OAAO,eAAe,IAAI,wBAAwB,SAAS,mBAAA,IAA4C;AACzG;;AAGA,SAAgB,0BACd,MAAyB,QAAQ,KACjC,WAA2B,oBAAoB,OACvC;CACR,OAAO,eACL,IAAI,gCACJ,SAAS,0BAAA,GACX;AACF;;AAGA,SAAgB,kBAAkB,WAA2B,oBAAoB,OAAe;CAC9F,OAAO,SAAS,kBAAA;AAClB;AAEA,SAAgB,aAAa,WAA2B,oBAAoB,OAAe;CACzF,OAAO,SAAS,aAAA;AAClB;AAEA,SAAgB,oBAAoB,WAA2B,oBAAoB,OAAe;CAChG,OAAO,SAAS,oBAAA;AAClB;AAEA,SAAgB,mBAAmB,WAA2B,oBAAoB,OAAe;CAC/F,OAAO,SAAS,mBAAA;AAClB;AAEA,SAAgB,0BAA0B,WAA2B,oBAAoB,OAAe;CACtG,OAAO,SAAS,0BAAA;AAClB;;AAGA,SAAgB,iBAAiB,WAA2B,oBAAoB,OAA0B;CACxG,OAAO,SAAS,iBAAiB,CAAC;AACpC;;AAGA,SAAgB,0BACd,aACwB;CACxB,OAAO;EACL,0BAA0B,YAAY,4BAA4B;EAClE,QAAQ,YAAY,UAAU;EAC9B,aAAa,YAAY,eAAe;EACxC,yBAAyB,YAAY,2BAA2B;EAChE,oBAAoB,YAAY,sBAAsB;EACtD,oBAAoB,YAAY,sBAAsB;CACxD;AACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runnerDependencies-DruByBGS.mjs","names":[],"sources":["../src/constants/tmuxBackend.ts","../src/services/ptyBackendChain/index.ts","../src/services/tmuxBackend/TmuxClient.ts","../src/services/tmuxBackend/index.ts","../src/services/runnerDependencies/index.ts"],"sourcesContent":["export const POLL_MS = 100;\nexport const LOG_DRAIN_TIMEOUT_MS = 2_000;\nexport const LOG_DRAIN_POLL_MS = 25;\nexport const PANE_STATE_FORMAT = '#{pane_dead}:#{pane_dead_status}:#{session_name}';\nexport const STOP_GRACE_MS = 3_000;\nexport const SESSION_PREFIX = 'doom-tmux-';\nexport const OWNED_TARGET_PATTERN = /^doom-tmux-[A-Za-z0-9_-]+$/;\nexport const TMUX_TARGET_PREFIX = SESSION_PREFIX;\nexport const SOCKET_HASH_LENGTH = 12;\nexport const SOCKET_PREFIX = 'doom-tmux-';\nexport const NON_INTERACTIVE_ENV = { NO_COLOR: '1', CI: '1' };\n","import { TMUX_TARGET_PREFIX } from '../../constants/tmuxBackend';\nimport type { RunHandle } from '../../types/launcher';\nimport type { PtyRun } from '../../types/ptyHost';\nimport type { IRmuxBackend, RmuxLaunchRequest } from '../../types/rmuxBackend';\nimport type { ExitResult } from '../../types/spawner';\n\n/**\n * Presents the available PTY backends as one, preferring RMUX.\n *\n * A launch takes the first backend that accepts it, so a host without a\n * compatible RMUX binary still gets panes rather than falling through to the\n * plain subprocess launcher. Every later call routes on the target's prefix\n * instead of asking each backend in turn: a backend cannot tell \"this session\n * is gone\" from \"this session was never mine\", and guessing would let one\n * report success for the other's run.\n */\nexport class PtyBackendChain implements IRmuxBackend {\n constructor(\n private readonly rmux: IRmuxBackend,\n private readonly tmux: IRmuxBackend,\n ) {}\n\n async launch(request: RmuxLaunchRequest): Promise<RunHandle | undefined> {\n return (await this.rmux.launch(request)) ?? (await this.tmux.launch(request));\n }\n\n watch(id: string, target: string, sessionId?: string): Promise<ExitResult | undefined> {\n return this.owner(target).watch(id, target, sessionId);\n }\n\n stop(target: string, expectedPid: number): Promise<boolean> {\n return this.owner(target).stop(target, expectedPid);\n }\n\n input(target: string, text: string): Promise<boolean> {\n return this.owner(target).input(target, text);\n }\n\n capture(target: string): Promise<string | undefined> {\n return this.owner(target).capture(target);\n }\n\n /** Both backends persist terminal evidence at the same path, so either answers. */\n readOutcome(id: string, sessionId: string): ExitResult | undefined {\n return this.rmux.readOutcome(id, sessionId) ?? this.tmux.readOutcome(id, sessionId);\n }\n\n get(name: string): PtyRun | undefined {\n return this.rmux.get(name) ?? this.tmux.get(name);\n }\n\n private owner(target: string): IRmuxBackend {\n return target.startsWith(TMUX_TARGET_PREFIX) ? this.tmux : this.rmux;\n }\n}\n","import { execFile } from 'node:child_process';\n\nimport type { ITmuxClient, TmuxResult } from '../../types/tmuxClient';\n\nconst TMUX_BINARY = 'tmux';\nconst SOCKET_OPTION = '-L';\n/** Long enough for a loaded server, short enough that a hung tmux is not fatal. */\nconst COMMAND_TIMEOUT_MS = 10_000;\nconst MAX_OUTPUT_BYTES = 4 * 1024 * 1024;\n\nexport class TmuxClient implements ITmuxClient {\n constructor(\n private readonly socket: string,\n private readonly binary = TMUX_BINARY,\n ) {}\n\n run(args: readonly string[]): Promise<TmuxResult> {\n return new Promise((resolve, reject) => {\n execFile(\n this.binary,\n [SOCKET_OPTION, this.socket, ...args],\n { timeout: COMMAND_TIMEOUT_MS, maxBuffer: MAX_OUTPUT_BYTES, encoding: 'utf8' },\n (error, stdout, stderr) => {\n // A non-zero tmux exit is an answer, not a fault: `has-session`\n // reports absence that way. Only a missing or hung binary rejects.\n const code = (error as (Error & { code?: number | string }) | null)?.code;\n if (error && typeof code !== 'number') {\n reject(error);\n return;\n }\n resolve({ returnCode: typeof code === 'number' ? code : 0, stdout, stderr });\n },\n );\n });\n }\n\n async format(target: string, format: string): Promise<string | undefined> {\n const result = await this.run(['display-message', '-p', '-t', target, '-F', format]).catch(() => undefined);\n if (!result || result.returnCode !== 0) return undefined;\n return result.stdout.replace(/\\n$/, '');\n }\n\n async sessionMissing(target: string): Promise<boolean> {\n const result = await this.run(['has-session', '-t', target]).catch(() => undefined);\n return !result || result.returnCode !== 0;\n }\n}\n","import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport {\n LOG_DRAIN_POLL_MS,\n LOG_DRAIN_TIMEOUT_MS,\n NON_INTERACTIVE_ENV,\n OWNED_TARGET_PATTERN,\n PANE_STATE_FORMAT,\n POLL_MS,\n SESSION_PREFIX,\n SOCKET_HASH_LENGTH,\n SOCKET_PREFIX,\n STOP_GRACE_MS,\n} from '../../constants/tmuxBackend';\nimport type { RunHandle } from '../../types/launcher';\nimport type { PtyRun } from '../../types/ptyHost';\nimport type { IRmuxBackend, RmuxLaunchRequest } from '../../types/rmuxBackend';\nimport type { RunnerSettings } from '../../types/runnerSettings';\nimport type { ExitResult } from '../../types/spawner';\nimport type { ITmuxClient } from '../../types/tmuxClient';\nimport { getLogMaxBytes, getResultMaxBytes, noninteractiveEnvironment } from '../runnerConfig';\nimport type { IRunnerPaths } from '../runnerPaths/type';\nimport {\n type CommandSpec,\n type SupervisorPaths,\n cleanupSupervisorFiles,\n NO_TERMINAL_INPUT_ENV,\n readExitMetadata,\n runtimeEntry,\n shellJoin,\n supervisorPaths,\n writeCommandSpec,\n} from '../runnerSupervisor';\nimport { TmuxClient } from './TmuxClient';\n\n/** Pane liveness, its exit status, and whether the session still exists, in one read. */\n/** Distinct from the RMUX prefix so a target names the backend that owns it. */\n\n/**\n * Supervises runs in tmux panes, for hosts with no compatible RMUX binary.\n *\n * The pane runs the same runnerHost supervisor as the RMUX backend, so exit\n * metadata, log rotation, and lifeline handling are shared rather than\n * reimplemented: only the multiplexer differs. Kept beside the RMUX backend\n * rather than folded into it because that path has no unit coverage to\n * refactor against.\n */\nexport class TmuxBackend implements IRmuxBackend {\n private clientPromise: Promise<ITmuxClient | undefined> | undefined;\n private readonly runs = new Map<string, PtyRun>();\n private readonly completions = new Map<string, Promise<ExitResult>>();\n\n constructor(\n private readonly paths: IRunnerPaths,\n private readonly createClient: (socket: string) => ITmuxClient = (socket) => new TmuxClient(socket),\n private readonly env: Readonly<Record<string, string | undefined>> = process.env,\n private readonly settings?: RunnerSettings,\n ) {}\n\n async launch(request: RmuxLaunchRequest): Promise<RunHandle | undefined> {\n const tmux = await this.client();\n if (!tmux) return undefined;\n\n this.paths.ensureDirectories();\n const target = `${SESSION_PREFIX}${request.id}`;\n const logPath = this.paths.logPathFor(request.id);\n const aux = this.auxPaths(request.id, request.sessionId);\n let created = false;\n let released = false;\n\n try {\n this.prepareFiles(request, logPath, aux);\n // One quoted command rather than an argv: tmux takes shell-command as a\n // single word, and quoting here is what keeps a path with spaces intact.\n const supervisor = shellJoin([process.execPath, runtimeEntry('runnerHost'), aux.spec, aux.gate, aux.exit]);\n await this.checked(tmux, ['new-session', '-d', '-s', target, '-c', request.cwd, supervisor]);\n created = true;\n // Set before the gate opens, so it is in force by the time the command\n // can exit. A pane that vanishes on exit takes the log sink down with it\n // before Node has finished starting, losing the output of fast commands,\n // and leaves #{pane_dead} with nothing to report.\n await this.checked(tmux, ['set-option', '-t', target, 'remain-on-exit', 'on']);\n await this.checked(tmux, ['pipe-pane', '-t', target, this.logPipeCommand(logPath, aux.logDone, request)]);\n\n const pid = await panePid(tmux, target);\n fs.writeFileSync(aux.gate, '', { mode: 0o600 });\n released = true;\n\n let buffering = true;\n const completion = this.monitor(tmux, target, aux);\n this.trackCompletion(target, completion);\n const handle: RunHandle = {\n id: request.id,\n name: request.name,\n pid,\n logPath,\n backend: 'tmux',\n backendTarget: target,\n output: () => (buffering ? readTail(logPath, getResultMaxBytes(this.env, this.settings) * 2) : ''),\n completion: () => completion,\n detach: () => {\n buffering = false;\n },\n stop: () => this.stop(target, pid),\n };\n\n if (request.interactive) this.runs.set(request.name, this.interactiveRun(handle, tmux, target, completion));\n void completion\n .finally(() => this.runs.delete(request.name))\n .catch((error: unknown) => process.emitWarning(`tmux completion failed for ${target}: ${errorMessage(error)}`));\n return handle;\n } catch (error) {\n if (released) throw error;\n if (created) await killSession(tmux, target);\n cleanupSupervisorFiles(aux);\n process.emitWarning(\n request.interactive\n ? `tmux launch unavailable for interactive runner: ${errorMessage(error)}`\n : `tmux launch unavailable, using supervised subprocess: ${errorMessage(error)}`,\n );\n return undefined;\n }\n }\n\n async stop(target: string, expectedPid: number): Promise<boolean> {\n if (!OWNED_TARGET_PATTERN.test(target) || !Number.isInteger(expectedPid) || expectedPid <= 0) return false;\n\n const tmux = await this.client();\n if (!tmux) return false;\n try {\n if (await tmux.sessionMissing(target)) return true;\n\n const pid = await panePid(tmux, target);\n if (pid !== expectedPid) return false;\n const signalled = signalPane(pid, target);\n if (signalled === 'gone') return true;\n if (signalled === 'failed') return false;\n\n if (await waitForPaneStop(tmux, target, STOP_GRACE_MS)) return true;\n if (await tmux.sessionMissing(target)) return true;\n\n // Revalidate after the grace period so a replacement pane is never closed.\n const currentPid = await panePid(tmux, target).catch(() => undefined);\n if (currentPid !== expectedPid) return false;\n\n return killSession(tmux, target);\n } catch (error) {\n process.emitWarning(`Could not stop tmux target ${target}: ${errorMessage(error)}`);\n return false;\n }\n }\n\n async watch(id: string, target: string, sessionId?: string): Promise<ExitResult | undefined> {\n const tmux = await this.client();\n if (!tmux) return undefined;\n if (await tmux.sessionMissing(target)) return undefined;\n const completion = this.monitor(tmux, target, this.auxPaths(id, sessionId));\n this.trackCompletion(target, completion);\n return completion;\n }\n\n async input(target: string, text: string): Promise<boolean> {\n const tmux = await this.client();\n if (!tmux) return false;\n const result = await tmux.run(['send-keys', '-t', target, '-l', text]).catch((error: unknown) => {\n process.emitWarning(`Could not send input to tmux target ${target}: ${errorMessage(error)}`);\n return undefined;\n });\n return result?.returnCode === 0;\n }\n\n async capture(target: string): Promise<string | undefined> {\n const tmux = await this.client();\n if (!tmux) return undefined;\n const result = await tmux.run(['capture-pane', '-p', '-t', target]).catch((error: unknown) => {\n process.emitWarning(`Could not capture tmux target ${target}: ${errorMessage(error)}`);\n return undefined;\n });\n return result?.returnCode === 0 ? result.stdout : undefined;\n }\n\n get(name: string): PtyRun | undefined {\n return this.runs.get(name);\n }\n\n readOutcome(id: string, sessionId: string): ExitResult | undefined {\n return readExitMetadata(this.auxPaths(id, sessionId).exit);\n }\n\n private trackCompletion(target: string, completion: Promise<ExitResult>): void {\n this.completions.set(target, completion);\n void completion\n .finally(() => this.completions.delete(target))\n .catch((error: unknown) => process.emitWarning(`tmux monitor failed for ${target}: ${errorMessage(error)}`));\n }\n\n private client(): Promise<ITmuxClient | undefined> {\n this.clientPromise ??= this.resolveClient();\n return this.clientPromise;\n }\n\n private async resolveClient(): Promise<ITmuxClient | undefined> {\n const client = this.createClient(socketName(this.paths.repositoryPath()));\n try {\n const version = await client.run(['-V']);\n if (version.returnCode !== 0) throw new Error(version.stderr.trim() || 'tmux reported no version');\n return client;\n } catch (error) {\n process.emitWarning(`tmux is unavailable: ${errorMessage(error)}`);\n return undefined;\n }\n }\n\n private async checked(tmux: ITmuxClient, args: readonly string[]): Promise<void> {\n const result = await tmux.run(args);\n if (result.returnCode !== 0) {\n throw new Error(`tmux ${args[0] ?? ''} failed: ${result.stderr.trim() || `exit ${result.returnCode}`}`);\n }\n }\n\n private prepareFiles(request: RmuxLaunchRequest, logPath: string, aux: SupervisorPaths): void {\n cleanupSupervisorFiles(aux);\n fs.writeFileSync(logPath, '', { mode: 0o600 });\n const env = environment(request.sessionId, request.interactive, this.env);\n const spec: CommandSpec = { command: request.command, cwd: request.cwd, env };\n writeCommandSpec(aux.spec, spec);\n }\n\n private auxPaths(id: string, sessionId?: string): SupervisorPaths {\n return supervisorPaths(this.paths.stateDirectory(sessionId), id);\n }\n\n /**\n * The sink the pane pipes into.\n *\n * An interactive run also asks for a raw copy: the scrubbed log it writes\n * beside it has had cursor movement taken out, which is what a terminal\n * needs most. Only interactive runs pay for it, because only they can be\n * attached to.\n */\n private logPipeCommand(logPath: string, donePath: string, request: RmuxLaunchRequest): string {\n const id = path.basename(logPath, '.log');\n return shellJoin([\n process.execPath,\n runtimeEntry('logSink'),\n logPath,\n this.paths.rotatedLogPathFor(id),\n String(getLogMaxBytes(this.env)),\n donePath,\n ...(request.interactive ? [this.paths.rawLogPathFor(id)] : []),\n ]);\n }\n\n private async monitor(tmux: ITmuxClient, target: string, aux: SupervisorPaths): Promise<ExitResult> {\n try {\n const paneCode = await waitForRunEnd(tmux, target, aux.exit);\n await waitForLogDrain(tmux, target, aux.logDone);\n return readExitMetadata(aux.exit) ?? { code: paneCode, signal: null };\n } finally {\n if (!(await tmux.sessionMissing(target).catch(() => false))) await killSession(tmux, target);\n cleanupSupervisorFiles(aux);\n }\n }\n\n private interactiveRun(\n handle: RunHandle,\n tmux: ITmuxClient,\n target: string,\n completion: Promise<ExitResult>,\n ): PtyRun {\n let screen = '';\n let active = true;\n const handlers = new Set<(data: string) => void>();\n const refresh = async (): Promise<void> => {\n while (active) {\n const captured = await tmux.run(['capture-pane', '-p', '-t', target]).catch((error: unknown) => {\n process.emitWarning(`Could not capture tmux screen for ${handle.name}: ${errorMessage(error)}`);\n return undefined;\n });\n const next = captured?.returnCode === 0 ? captured.stdout : screen;\n if (next !== screen) {\n screen = next;\n for (const handler of handlers) handler(next);\n }\n await delay(POLL_MS);\n }\n };\n void refresh();\n void completion\n .finally(() => {\n active = false;\n })\n .catch((error: unknown) =>\n process.emitWarning(`tmux interactive completion failed for ${handle.name}: ${errorMessage(error)}`),\n );\n return {\n ...handle,\n write: (text) => {\n void tmux\n .run(['send-keys', '-t', target, '-l', text])\n .catch((error: unknown) => process.emitWarning(errorMessage(error)));\n },\n screen: () => screen,\n onData: (handler) => {\n handlers.add(handler);\n return () => handlers.delete(handler);\n },\n resize: (cols, rows) => {\n void tmux\n .run(['resize-window', '-t', target, '-x', String(cols), '-y', String(rows)])\n .catch((error: unknown) => process.emitWarning(errorMessage(error)));\n },\n };\n }\n}\n\nfunction socketName(repositoryPath: string): string {\n const hash = createHash('sha256').update(repositoryPath).digest('hex').slice(0, SOCKET_HASH_LENGTH);\n return `${SOCKET_PREFIX}${hash}`;\n}\n\nfunction environment(\n sessionId: string,\n interactive: boolean,\n env: Readonly<Record<string, string | undefined>>,\n): Record<string, string> {\n const values: NodeJS.ProcessEnv = {\n ...env,\n ...(interactive ? {} : { ...NON_INTERACTIVE_ENV, ...noninteractiveEnvironment(env) }),\n ...NO_TERMINAL_INPUT_ENV,\n PI_SESSION_ID: sessionId,\n };\n if (!interactive) delete values['FORCE_COLOR'];\n return Object.fromEntries(\n Object.entries(values).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n}\n\nasync function killSession(tmux: ITmuxClient, target: string): Promise<boolean> {\n const result = await tmux.run(['kill-session', '-t', target]).catch((error: unknown) => {\n process.emitWarning(`Could not close tmux target ${target}: ${errorMessage(error)}`);\n return undefined;\n });\n return result?.returnCode === 0;\n}\n\nasync function panePid(tmux: ITmuxClient, target: string): Promise<number> {\n const message = await tmux.format(target, '#{pane_pid}');\n const pid = Number(message);\n if (!Number.isInteger(pid) || pid <= 0) throw new Error(`tmux did not report a pane pid for ${target}`);\n return pid;\n}\n\n/**\n * Waits for the run to end, preferring the supervisor's own record of it.\n *\n * The sidecar is written before the pane can end and outlives the server the\n * pane's exit takes down, so asking tmux is the fallback for a supervisor that\n * died without recording anything.\n */\nasync function waitForRunEnd(tmux: ITmuxClient, target: string, exitPath: string): Promise<number | null> {\n for (;;) {\n if (fs.existsSync(exitPath)) return null;\n const state = await readPaneExit(tmux, target);\n if (state.exited) return state.code;\n await delay(POLL_MS);\n }\n}\n\nasync function waitForLogDrain(tmux: ITmuxClient, target: string, donePath: string): Promise<void> {\n const deadline = Date.now() + LOG_DRAIN_TIMEOUT_MS;\n while (Date.now() < deadline) {\n if (fs.existsSync(donePath)) return;\n if (await tmux.sessionMissing(target)) return;\n await delay(LOG_DRAIN_POLL_MS);\n }\n}\n\nasync function waitForPaneStop(tmux: ITmuxClient, target: string, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if ((await readPaneExit(tmux, target)).exited) return true;\n await delay(POLL_MS);\n }\n return false;\n}\n\n/** One formatted read answers both questions this poll asks. */\nasync function readPaneExit(tmux: ITmuxClient, target: string): Promise<{ exited: boolean; code: number | null }> {\n const message = await tmux.format(target, PANE_STATE_FORMAT);\n // An unreachable server is the ordinary end of the last run: the pane exiting\n // ends its session, and the last session ending stops the server.\n if (message === undefined) return { exited: true, code: null };\n const [dead, status, ...rest] = message.trim().split(':');\n if (rest.join(':') === '') return { exited: true, code: null };\n if (dead === '1' || dead === 'true') {\n const code = Number(status);\n return { exited: true, code: Number.isInteger(code) ? code : null };\n }\n return { exited: false, code: null };\n}\n\nfunction signalPane(pid: number, target: string): 'signalled' | 'gone' | 'failed' {\n try {\n process.kill(pid, 'SIGTERM');\n return 'signalled';\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ESRCH') return 'gone';\n process.emitWarning(`Could not signal tmux target ${target}: ${errorMessage(error)}`);\n return 'failed';\n }\n}\n\nfunction readTail(target: string, maxBytes: number): string {\n let handle: number | undefined;\n try {\n const size = fs.statSync(target).size;\n const bytes = Math.min(size, maxBytes);\n const buffer = Buffer.alloc(bytes);\n handle = fs.openSync(target, 'r');\n fs.readSync(handle, buffer, 0, bytes, size - bytes);\n return buffer.toString('utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n process.emitWarning(`Could not read tmux log ${target}: ${errorMessage(error)}`);\n }\n return '';\n } finally {\n if (handle !== undefined) fs.closeSync(handle);\n }\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(resolve, ms);\n timer.unref?.();\n });\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { sharedExecutionBudget, type DoomHostExecutionBudget } from '@agimon-ai/po-core/packageApi';\n\nimport { BashRunService } from '../bashRunService';\nimport { SystemClock } from '../clock';\nimport { Launcher } from '../launcher';\nimport { NodeLifeline } from '../lifeline';\nimport { LogFile } from '../logFile';\nimport { LogReader } from '../logReader';\nimport { NodeProcessControl } from '../processControl';\nimport { PtyBackendChain } from '../ptyBackendChain';\nimport { PtyHost } from '../ptyHost';\nimport { NodePtySpawner } from '../ptySpawner';\nimport { RmuxBackend } from '../rmuxBackend';\nimport { RtkProcessor } from '../rtkProcessor';\nimport { RunnerNamer } from '../runnerNamer';\nimport { RunnerPaths } from '../runnerPaths';\nimport { RunnerRegistry, createDefaultProcessRegistry } from '../runnerRegistry';\nimport { NodeSpawner } from '../spawner';\nimport { TmuxBackend } from '../tmuxBackend';\nimport type { RunnerDependencies } from './type';\n/** Build once on first access, then hand back the same instance. */\nfunction memoize<T>(build: () => T): () => T {\n let value: T | undefined;\n let built = false;\n return () => {\n if (!built) {\n value = build();\n built = true;\n }\n return value as T;\n };\n}\n\n/**\n * Builds the extension's service graph.\n *\n * A factory rather than a module-level singleton: the extension owns one graph\n * per session, and tests get a fresh one they can substitute ports on through\n * `overrides` without leaking state between cases.\n *\n * Every slot resolves lazily and memoizes, which keeps the previous container's\n * behaviour: nothing is constructed until it is asked for, so opening the SQLite\n * process registry stays deferred until something actually needs a runner.\n */\nexport function createRunnerDependencies(\n overrides: Partial<RunnerDependencies> & {\n environment: Readonly<Record<string, string | undefined>>;\n cwd?: string;\n executionBudget?: DoomHostExecutionBudget;\n },\n): RunnerDependencies {\n const settings =\n overrides.settings === undefined\n ? undefined\n : Object.freeze({\n ...overrides.settings,\n ...(overrides.settings?.errorPatterns\n ? { errorPatterns: Object.freeze([...overrides.settings.errorPatterns]) }\n : {}),\n });\n const environment = { ...overrides.environment };\n const cwd = overrides.cwd ?? process.cwd();\n const clock = memoize(() => overrides.clock ?? new SystemClock());\n const spawner = memoize(() => overrides.spawner ?? new NodeSpawner());\n const processControl = memoize(() => overrides.processControl ?? new NodeProcessControl());\n const ptySpawner = memoize(() => overrides.ptySpawner ?? new NodePtySpawner());\n const paths = memoize(() => overrides.paths ?? new RunnerPaths(cwd, environment));\n const lifeline = memoize(() => overrides.lifeline ?? new NodeLifeline(paths()));\n const processRegistry = memoize(() => overrides.processRegistry ?? createDefaultProcessRegistry(environment));\n const runnerRegistry = memoize(\n () => overrides.runnerRegistry ?? new RunnerRegistry(paths(), processControl(), processRegistry(), environment),\n );\n const namer = memoize(() => overrides.namer ?? new RunnerNamer(runnerRegistry()));\n const logFile = memoize(() => overrides.logFile ?? new LogFile(paths()));\n const logReader = memoize(() => overrides.logReader ?? new LogReader());\n const launcher = memoize(\n () =>\n overrides.launcher ??\n new Launcher(spawner(), processControl(), logFile(), clock(), paths(), lifeline(), environment, settings),\n );\n const rmuxBackend = memoize(\n () =>\n overrides.rmuxBackend ??\n new PtyBackendChain(\n new RmuxBackend(paths(), environment, settings),\n new TmuxBackend(paths(), undefined, environment, settings),\n ),\n );\n const rtkProcessor = memoize(\n () => overrides.rtkProcessor ?? new RtkProcessor(undefined, undefined, environment, settings),\n );\n const ptyHost = memoize(\n () => overrides.ptyHost ?? new PtyHost(ptySpawner(), logFile(), processControl(), clock(), environment, settings),\n );\n const bashRunService = memoize(\n () =>\n overrides.bashRunService ??\n new BashRunService(\n launcher(),\n rmuxBackend(),\n namer(),\n runnerRegistry(),\n clock(),\n rtkProcessor(),\n cwd,\n environment,\n overrides.executionBudget ?? sharedExecutionBudget(environment),\n ),\n );\n\n return {\n settings,\n environment,\n get clock() {\n return clock();\n },\n get spawner() {\n return spawner();\n },\n get processControl() {\n return processControl();\n },\n get ptySpawner() {\n return ptySpawner();\n },\n get paths() {\n return paths();\n },\n get lifeline() {\n return lifeline();\n },\n get processRegistry() {\n return processRegistry();\n },\n get runnerRegistry() {\n return runnerRegistry();\n },\n get namer() {\n return namer();\n },\n get logFile() {\n return logFile();\n },\n get logReader() {\n return logReader();\n },\n get launcher() {\n return launcher();\n },\n get rmuxBackend() {\n return rmuxBackend();\n },\n get rtkProcessor() {\n return rtkProcessor();\n },\n get ptyHost() {\n return ptyHost();\n },\n get bashRunService() {\n return bashRunService();\n },\n };\n}\n"],"mappings":"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"}
|