@agimon-ai/po-runner 0.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +257 -0
- package/dist/ansiScrub-CsqTSaVT.mjs +71 -0
- package/dist/ansiScrub-CsqTSaVT.mjs.map +1 -0
- package/dist/ansiScrub-D5gpHDch.cjs +100 -0
- package/dist/ansiScrub-D5gpHDch.cjs.map +1 -0
- package/dist/ansiScrub.cjs +7 -0
- package/dist/ansiScrub.d.mts +26 -0
- package/dist/ansiScrub.d.mts.map +1 -0
- package/dist/ansiScrub.mjs +2 -0
- package/dist/apiContracts.cjs +162 -0
- package/dist/apiContracts.cjs.map +1 -0
- package/dist/apiContracts.d.mts +53 -0
- package/dist/apiContracts.d.mts.map +1 -0
- package/dist/apiContracts.mjs +157 -0
- package/dist/apiContracts.mjs.map +1 -0
- package/dist/bashResult-DNgtahGR.cjs +629 -0
- package/dist/bashResult-DNgtahGR.cjs.map +1 -0
- package/dist/bashResult-DcrRaBLv.d.mts +49 -0
- package/dist/bashResult-DcrRaBLv.d.mts.map +1 -0
- package/dist/bashResult-bIVSzoj-.mjs +546 -0
- package/dist/bashResult-bIVSzoj-.mjs.map +1 -0
- package/dist/bashRunService-CJ02XaAq.mjs +440 -0
- package/dist/bashRunService-CJ02XaAq.mjs.map +1 -0
- package/dist/bashRunService-Ci0cGdYO.d.mts +71 -0
- package/dist/bashRunService-Ci0cGdYO.d.mts.map +1 -0
- package/dist/bashRunService-DyqxOSlx.cjs +445 -0
- package/dist/bashRunService-DyqxOSlx.cjs.map +1 -0
- package/dist/bashRunService.cjs +3 -0
- package/dist/bashRunService.d.mts +36 -0
- package/dist/bashRunService.d.mts.map +1 -0
- package/dist/bashRunService.mjs +2 -0
- package/dist/bashSchema.cjs +5 -0
- package/dist/bashSchema.d.mts +7 -0
- package/dist/bashSchema.d.mts.map +1 -0
- package/dist/bashSchema.mjs +2 -0
- package/dist/bashTool-B1EwZLo_.d.mts +20 -0
- package/dist/bashTool-B1EwZLo_.d.mts.map +1 -0
- package/dist/bashTool-C-k7fmyh.mjs +24 -0
- package/dist/bashTool-C-k7fmyh.mjs.map +1 -0
- package/dist/bashTool-CdgtqVFD.cjs +41 -0
- package/dist/bashTool-CdgtqVFD.cjs.map +1 -0
- package/dist/bashTool.cjs +13 -0
- package/dist/bashTool.cjs.map +1 -0
- package/dist/bashTool.d.mts +8 -0
- package/dist/bashTool.d.mts.map +1 -0
- package/dist/bashTool.mjs +11 -0
- package/dist/bashTool.mjs.map +1 -0
- package/dist/bin/cli.cjs +78 -0
- package/dist/bin/cli.cjs.map +1 -0
- package/dist/bin/cli.d.mts +4 -0
- package/dist/bin/cli.d.mts.map +1 -0
- package/dist/bin/cli.mjs +77 -0
- package/dist/bin/cli.mjs.map +1 -0
- package/dist/bin/logSink.cjs +102 -0
- package/dist/bin/logSink.cjs.map +1 -0
- package/dist/bin/logSink.d.mts +4 -0
- package/dist/bin/logSink.d.mts.map +1 -0
- package/dist/bin/logSink.mjs +99 -0
- package/dist/bin/logSink.mjs.map +1 -0
- package/dist/bin/runnerHost.cjs +131 -0
- package/dist/bin/runnerHost.cjs.map +1 -0
- package/dist/bin/runnerHost.d.mts +4 -0
- package/dist/bin/runnerHost.d.mts.map +1 -0
- package/dist/bin/runnerHost.mjs +127 -0
- package/dist/bin/runnerHost.mjs.map +1 -0
- package/dist/cliApp-Dj9nwaOv.cjs +244 -0
- package/dist/cliApp-Dj9nwaOv.cjs.map +1 -0
- package/dist/cliApp-v8Z3rMCi.mjs +237 -0
- package/dist/cliApp-v8Z3rMCi.mjs.map +1 -0
- package/dist/cliApp.cjs +3 -0
- package/dist/cliApp.d.mts +18 -0
- package/dist/cliApp.d.mts.map +1 -0
- package/dist/cliApp.mjs +2 -0
- package/dist/clock-Cv2pddgo.mjs +16 -0
- package/dist/clock-Cv2pddgo.mjs.map +1 -0
- package/dist/clock-euJkweLq.d.mts +11 -0
- package/dist/clock-euJkweLq.d.mts.map +1 -0
- package/dist/clock-jqnLWziT.cjs +21 -0
- package/dist/clock-jqnLWziT.cjs.map +1 -0
- package/dist/clock.cjs +3 -0
- package/dist/clock.d.mts +10 -0
- package/dist/clock.d.mts.map +1 -0
- package/dist/clock.mjs +2 -0
- package/dist/compaction-4QSUsBxq.cjs +40 -0
- package/dist/compaction-4QSUsBxq.cjs.map +1 -0
- package/dist/compaction-DCw80VZj.mjs +29 -0
- package/dist/compaction-DCw80VZj.mjs.map +1 -0
- package/dist/compaction.cjs +4 -0
- package/dist/compaction.d.mts +10 -0
- package/dist/compaction.d.mts.map +1 -0
- package/dist/compaction.mjs +2 -0
- package/dist/config.cjs +41 -0
- package/dist/config.d.mts +2 -0
- package/dist/config.mjs +2 -0
- package/dist/extensions/mcp-ui.mjs +23 -0
- package/dist/extensions/mcp-ui.mjs.map +1 -0
- package/dist/extensions/mcp.cjs +142 -0
- package/dist/extensions/mcp.cjs.map +1 -0
- package/dist/extensions/mcp.d.mts +5 -0
- package/dist/extensions/mcp.d.mts.map +1 -0
- package/dist/extensions/mcp.mjs +114 -0
- package/dist/extensions/mcp.mjs.map +1 -0
- package/dist/extensions/server.cjs +1156 -0
- package/dist/extensions/server.cjs.map +1 -0
- package/dist/extensions/server.d.mts +5 -0
- package/dist/extensions/server.d.mts.map +1 -0
- package/dist/extensions/server.mjs +1146 -0
- package/dist/extensions/server.mjs.map +1 -0
- package/dist/extensions/web.mjs +1785 -0
- package/dist/extensions/web.mjs.map +1 -0
- package/dist/headless-BGYfIlNk.mjs +169 -0
- package/dist/headless-BGYfIlNk.mjs.map +1 -0
- package/dist/headless-CHUsBGhg.cjs +180 -0
- package/dist/headless-CHUsBGhg.cjs.map +1 -0
- package/dist/index-BZL7keVW.d.mts +31 -0
- package/dist/index-BZL7keVW.d.mts.map +1 -0
- package/dist/index-BwB_jTI9.d.mts +12 -0
- package/dist/index-BwB_jTI9.d.mts.map +1 -0
- package/dist/index-D9-IXax4.d.mts +43 -0
- package/dist/index-D9-IXax4.d.mts.map +1 -0
- package/dist/index-DBz0DxnL.d.mts +39 -0
- package/dist/index-DBz0DxnL.d.mts.map +1 -0
- package/dist/index-DM7yJpMs.d.mts +25 -0
- package/dist/index-DM7yJpMs.d.mts.map +1 -0
- package/dist/index-Dhi8asLH.d.mts +22 -0
- package/dist/index-Dhi8asLH.d.mts.map +1 -0
- package/dist/index.cjs +19 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +6 -0
- package/dist/launcher-BDm6-DiQ.mjs +150 -0
- package/dist/launcher-BDm6-DiQ.mjs.map +1 -0
- package/dist/launcher-BG5t9nvG.d.mts +39 -0
- package/dist/launcher-BG5t9nvG.d.mts.map +1 -0
- package/dist/launcher-SlyE8R3b.cjs +157 -0
- package/dist/launcher-SlyE8R3b.cjs.map +1 -0
- package/dist/launcher.cjs +3 -0
- package/dist/launcher.d.mts +33 -0
- package/dist/launcher.d.mts.map +1 -0
- package/dist/launcher.mjs +2 -0
- package/dist/lifeline-BZaQA0rm.mjs +88 -0
- package/dist/lifeline-BZaQA0rm.mjs.map +1 -0
- package/dist/lifeline-BuV_erib.cjs +98 -0
- package/dist/lifeline-BuV_erib.cjs.map +1 -0
- package/dist/lifeline-eJdZV0nN.d.mts +19 -0
- package/dist/lifeline-eJdZV0nN.d.mts.map +1 -0
- package/dist/lifeline.cjs +6 -0
- package/dist/lifeline.d.mts +21 -0
- package/dist/lifeline.d.mts.map +1 -0
- package/dist/lifeline.mjs +3 -0
- package/dist/logFile-C7oQ_v-g.d.mts +16 -0
- package/dist/logFile-C7oQ_v-g.d.mts.map +1 -0
- package/dist/logFile-CNvepZh0.cjs +67 -0
- package/dist/logFile-CNvepZh0.cjs.map +1 -0
- package/dist/logFile-KKPbkC-a.mjs +60 -0
- package/dist/logFile-KKPbkC-a.mjs.map +1 -0
- package/dist/logFile.cjs +3 -0
- package/dist/logFile.d.mts +11 -0
- package/dist/logFile.d.mts.map +1 -0
- package/dist/logFile.mjs +2 -0
- package/dist/logReader-B6J7L7Ua.cjs +282 -0
- package/dist/logReader-B6J7L7Ua.cjs.map +1 -0
- package/dist/logReader-MdW9ffvV.d.mts +43 -0
- package/dist/logReader-MdW9ffvV.d.mts.map +1 -0
- package/dist/logReader-UfbDbwQl.mjs +257 -0
- package/dist/logReader-UfbDbwQl.mjs.map +1 -0
- package/dist/logReader.cjs +4 -0
- package/dist/logReader.d.mts +3 -0
- package/dist/logReader.mjs +2 -0
- package/dist/processControl-BAOa3oo_.d.mts +14 -0
- package/dist/processControl-BAOa3oo_.d.mts.map +1 -0
- package/dist/processControl-DApTpV16.mjs +26 -0
- package/dist/processControl-DApTpV16.mjs.map +1 -0
- package/dist/processControl-DNJ1WZ9N.cjs +31 -0
- package/dist/processControl-DNJ1WZ9N.cjs.map +1 -0
- package/dist/processControl.cjs +3 -0
- package/dist/processControl.d.mts +10 -0
- package/dist/processControl.d.mts.map +1 -0
- package/dist/processControl.mjs +2 -0
- package/dist/ptyHost-DWWtRrGn.d.mts +38 -0
- package/dist/ptyHost-DWWtRrGn.d.mts.map +1 -0
- package/dist/ptyHost-DlQtTB8F.mjs +150 -0
- package/dist/ptyHost-DlQtTB8F.mjs.map +1 -0
- package/dist/ptyHost-MI2Z6WTG.cjs +157 -0
- package/dist/ptyHost-MI2Z6WTG.cjs.map +1 -0
- package/dist/ptyHost.cjs +3 -0
- package/dist/ptyHost.d.mts +26 -0
- package/dist/ptyHost.d.mts.map +1 -0
- package/dist/ptyHost.mjs +2 -0
- package/dist/ptySpawner-B6GsueZd.d.mts +28 -0
- package/dist/ptySpawner-B6GsueZd.d.mts.map +1 -0
- package/dist/ptySpawner-DEi1KOnd.mjs +17 -0
- package/dist/ptySpawner-DEi1KOnd.mjs.map +1 -0
- package/dist/ptySpawner-ijw0g5_T.cjs +22 -0
- package/dist/ptySpawner-ijw0g5_T.cjs.map +1 -0
- package/dist/ptySpawner.cjs +3 -0
- package/dist/ptySpawner.d.mts +14 -0
- package/dist/ptySpawner.d.mts.map +1 -0
- package/dist/ptySpawner.mjs +2 -0
- package/dist/reconcile-BugwYFbV.cjs +133 -0
- package/dist/reconcile-BugwYFbV.cjs.map +1 -0
- package/dist/reconcile-DMeNSxwn.mjs +114 -0
- package/dist/reconcile-DMeNSxwn.mjs.map +1 -0
- package/dist/reconcile.cjs +5 -0
- package/dist/reconcile.d.mts +36 -0
- package/dist/reconcile.d.mts.map +1 -0
- package/dist/reconcile.mjs +2 -0
- package/dist/responseEnvelope.cjs +19 -0
- package/dist/responseEnvelope.d.mts +50 -0
- package/dist/responseEnvelope.d.mts.map +1 -0
- package/dist/responseEnvelope.mjs +3 -0
- package/dist/rmuxBackend-CaEWooWn.d.mts +36 -0
- package/dist/rmuxBackend-CaEWooWn.d.mts.map +1 -0
- package/dist/rmuxBackend-DfyQwJrc.mjs +509 -0
- package/dist/rmuxBackend-DfyQwJrc.mjs.map +1 -0
- package/dist/rmuxBackend-DlxgqRZ1.cjs +523 -0
- package/dist/rmuxBackend-DlxgqRZ1.cjs.map +1 -0
- package/dist/rmuxBackend.cjs +4 -0
- package/dist/rmuxBackend.d.mts +3 -0
- package/dist/rmuxBackend.mjs +2 -0
- package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
- package/dist/rtkProcessor-B4_urXQr.mjs +10 -0
- package/dist/rtkProcessor-B4_urXQr.mjs.map +1 -0
- package/dist/rtkProcessor-B9KPdyzr.mjs +309 -0
- package/dist/rtkProcessor-B9KPdyzr.mjs.map +1 -0
- package/dist/rtkProcessor-Bc4L4o_8.cjs +335 -0
- package/dist/rtkProcessor-Bc4L4o_8.cjs.map +1 -0
- package/dist/rtkProcessor-CVZvNhkJ.d.mts +35 -0
- package/dist/rtkProcessor-CVZvNhkJ.d.mts.map +1 -0
- package/dist/rtkProcessor-CsrCPyTQ.cjs +33 -0
- package/dist/rtkProcessor-CsrCPyTQ.cjs.map +1 -0
- package/dist/rtkProcessor.cjs +11 -0
- package/dist/rtkProcessor.d.mts +7 -0
- package/dist/rtkProcessor.d.mts.map +1 -0
- package/dist/rtkProcessor.mjs +3 -0
- package/dist/runnerConfig-BQBlVAXn.mjs +134 -0
- package/dist/runnerConfig-BQBlVAXn.mjs.map +1 -0
- package/dist/runnerConfig-BjtulXBI.d.mts +57 -0
- package/dist/runnerConfig-BjtulXBI.d.mts.map +1 -0
- package/dist/runnerConfig-D2tGq5ZM.cjs +367 -0
- package/dist/runnerConfig-D2tGq5ZM.cjs.map +1 -0
- package/dist/runnerDependencies-DruByBGS.mjs +647 -0
- package/dist/runnerDependencies-DruByBGS.mjs.map +1 -0
- package/dist/runnerDependencies-KMZigIxB.cjs +667 -0
- package/dist/runnerDependencies-KMZigIxB.cjs.map +1 -0
- package/dist/runnerDependencies.cjs +3 -0
- package/dist/runnerDependencies.d.mts +2 -0
- package/dist/runnerDependencies.mjs +2 -0
- package/dist/runnerNamer-B8FH7n2v.mjs +44 -0
- package/dist/runnerNamer-B8FH7n2v.mjs.map +1 -0
- package/dist/runnerNamer-we1XVYfM.cjs +49 -0
- package/dist/runnerNamer-we1XVYfM.cjs.map +1 -0
- package/dist/runnerNamer.cjs +3 -0
- package/dist/runnerNamer.d.mts +11 -0
- package/dist/runnerNamer.d.mts.map +1 -0
- package/dist/runnerNamer.mjs +2 -0
- package/dist/runnerPaths-BTEuzxw0.cjs +471 -0
- package/dist/runnerPaths-BTEuzxw0.cjs.map +1 -0
- package/dist/runnerPaths-B_dAAeco.mjs +451 -0
- package/dist/runnerPaths-B_dAAeco.mjs.map +1 -0
- package/dist/runnerPaths.cjs +3 -0
- package/dist/runnerPaths.d.mts +50 -0
- package/dist/runnerPaths.d.mts.map +1 -0
- package/dist/runnerPaths.mjs +2 -0
- package/dist/runnerRegistry-BmkZTJHi.cjs +371 -0
- package/dist/runnerRegistry-BmkZTJHi.cjs.map +1 -0
- package/dist/runnerRegistry-CeOHEjBv.mjs +339 -0
- package/dist/runnerRegistry-CeOHEjBv.mjs.map +1 -0
- package/dist/runnerRegistry-CtJiD02R.d.mts +88 -0
- package/dist/runnerRegistry-CtJiD02R.d.mts.map +1 -0
- package/dist/runnerRegistry.cjs +4 -0
- package/dist/runnerRegistry.d.mts +3 -0
- package/dist/runnerRegistry.mjs +2 -0
- package/dist/runnerSettings-DiV1lvzx.d.mts +34 -0
- package/dist/runnerSettings-DiV1lvzx.d.mts.map +1 -0
- package/dist/services/lifeline/client.cjs +52 -0
- package/dist/services/lifeline/client.cjs.map +1 -0
- package/dist/services/lifeline/client.d.mts +22 -0
- package/dist/services/lifeline/client.d.mts.map +1 -0
- package/dist/services/lifeline/client.mjs +48 -0
- package/dist/services/lifeline/client.mjs.map +1 -0
- package/dist/services/runnerSupervisor/index.cjs +207 -0
- package/dist/services/runnerSupervisor/index.cjs.map +1 -0
- package/dist/services/runnerSupervisor/index.d.mts +71 -0
- package/dist/services/runnerSupervisor/index.d.mts.map +1 -0
- package/dist/services/runnerSupervisor/index.mjs +195 -0
- package/dist/services/runnerSupervisor/index.mjs.map +1 -0
- package/dist/session-BC43uEyG.cjs +29 -0
- package/dist/session-BC43uEyG.cjs.map +1 -0
- package/dist/session-Chsb_Nh2.mjs +18 -0
- package/dist/session-Chsb_Nh2.mjs.map +1 -0
- package/dist/session-DE2Acesp.mjs +6 -0
- package/dist/session-DE2Acesp.mjs.map +1 -0
- package/dist/session-SfIPtdZO.cjs +11 -0
- package/dist/session-SfIPtdZO.cjs.map +1 -0
- package/dist/session.cjs +6 -0
- package/dist/session.d.mts +11 -0
- package/dist/session.d.mts.map +1 -0
- package/dist/session.mjs +3 -0
- package/dist/spawner-BxFsINXP.cjs +68 -0
- package/dist/spawner-BxFsINXP.cjs.map +1 -0
- package/dist/spawner-CdrN_HNk.d.mts +35 -0
- package/dist/spawner-CdrN_HNk.d.mts.map +1 -0
- package/dist/spawner-LoVsn55-.mjs +63 -0
- package/dist/spawner-LoVsn55-.mjs.map +1 -0
- package/dist/spawner.cjs +3 -0
- package/dist/spawner.d.mts +9 -0
- package/dist/spawner.d.mts.map +1 -0
- package/dist/spawner.mjs +2 -0
- package/dist/type-BXM03qSw.d.mts +44 -0
- package/dist/type-BXM03qSw.d.mts.map +1 -0
- package/dist/type-C31e1gla.d.mts +43 -0
- package/dist/type-C31e1gla.d.mts.map +1 -0
- package/dist/type-vWQNTahw.d.mts +12 -0
- package/dist/type-vWQNTahw.d.mts.map +1 -0
- package/dist/types.cjs +0 -0
- package/dist/types.d.mts +3 -0
- package/dist/types.mjs +1 -0
- package/llms.txt +9 -0
- package/package.json +303 -0
- package/skills/doom-runner/SKILL.md +78 -0
- package/src/prompts/po-use-runner/SKILL.md +47 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
|
|
2
|
+
const require_ansiScrub = require("./ansiScrub-D5gpHDch.cjs");
|
|
3
|
+
const require_runnerConfig = require("./runnerConfig-D2tGq5ZM.cjs");
|
|
4
|
+
const require_session = require("./session-SfIPtdZO.cjs");
|
|
5
|
+
const require_services_runnerSupervisor_index = require("./services/runnerSupervisor/index.cjs");
|
|
6
|
+
let _xterm_headless = require("@xterm/headless");
|
|
7
|
+
_xterm_headless = require_rolldown_runtime.__toESM(_xterm_headless, 1);
|
|
8
|
+
//#region src/constants/ptyHost.ts
|
|
9
|
+
const SCROLLBACK = 2e3;
|
|
10
|
+
const TERM_GRACE_MS = 2e3;
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/services/ptyHost/index.ts
|
|
13
|
+
/** Enough history for the overlay to scroll without holding a whole build. */
|
|
14
|
+
const { Terminal: HeadlessTerminal } = _xterm_headless.default;
|
|
15
|
+
var PtyHost = class {
|
|
16
|
+
spawner;
|
|
17
|
+
logFile;
|
|
18
|
+
processControl;
|
|
19
|
+
clock;
|
|
20
|
+
environment;
|
|
21
|
+
settings;
|
|
22
|
+
runs = /* @__PURE__ */ new Map();
|
|
23
|
+
constructor(spawner, logFile, processControl, clock, environment = process.env, settings) {
|
|
24
|
+
this.spawner = spawner;
|
|
25
|
+
this.logFile = logFile;
|
|
26
|
+
this.processControl = processControl;
|
|
27
|
+
this.clock = clock;
|
|
28
|
+
this.environment = environment;
|
|
29
|
+
this.settings = settings;
|
|
30
|
+
}
|
|
31
|
+
async launch(request) {
|
|
32
|
+
const cols = request.cols ?? 120;
|
|
33
|
+
const rows = request.rows ?? 30;
|
|
34
|
+
const writer = this.logFile.open(request.id);
|
|
35
|
+
const terminal = new HeadlessTerminal({
|
|
36
|
+
cols,
|
|
37
|
+
rows,
|
|
38
|
+
scrollback: SCROLLBACK,
|
|
39
|
+
allowProposedApi: true
|
|
40
|
+
});
|
|
41
|
+
const memoryLimit = require_runnerConfig.getResultMaxBytes(this.environment, this.settings) * 2;
|
|
42
|
+
const child = await this.spawner.spawn({
|
|
43
|
+
command: request.command,
|
|
44
|
+
cwd: request.cwd,
|
|
45
|
+
env: {
|
|
46
|
+
...this.environment,
|
|
47
|
+
...require_services_runnerSupervisor_index.NO_TERMINAL_INPUT_ENV,
|
|
48
|
+
[require_session.PI_SESSION_ID_ENV]: request.sessionId
|
|
49
|
+
},
|
|
50
|
+
cols,
|
|
51
|
+
rows
|
|
52
|
+
});
|
|
53
|
+
let buffer = "";
|
|
54
|
+
let buffering = true;
|
|
55
|
+
let settled = false;
|
|
56
|
+
let resolveCompletion = () => void 0;
|
|
57
|
+
const completion = new Promise((resolve) => {
|
|
58
|
+
resolveCompletion = resolve;
|
|
59
|
+
});
|
|
60
|
+
const dataHandlers = /* @__PURE__ */ new Set();
|
|
61
|
+
child.onData((data) => {
|
|
62
|
+
terminal.write(data);
|
|
63
|
+
const scrubbed = require_ansiScrub.scrubTerminalOutput(data);
|
|
64
|
+
writer.append(scrubbed);
|
|
65
|
+
if (buffering) {
|
|
66
|
+
buffer += scrubbed;
|
|
67
|
+
if (buffer.length > memoryLimit) buffer = buffer.slice(-memoryLimit);
|
|
68
|
+
}
|
|
69
|
+
for (const handler of dataHandlers) handler(data);
|
|
70
|
+
});
|
|
71
|
+
child.onExit((result) => {
|
|
72
|
+
if (settled) return;
|
|
73
|
+
settled = true;
|
|
74
|
+
this.runs.delete(request.name);
|
|
75
|
+
writer.close();
|
|
76
|
+
resolveCompletion({
|
|
77
|
+
code: result.exitCode,
|
|
78
|
+
signal: null
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
const run = {
|
|
82
|
+
id: request.id,
|
|
83
|
+
name: request.name,
|
|
84
|
+
pid: child.pid,
|
|
85
|
+
logPath: writer.path,
|
|
86
|
+
backend: "native",
|
|
87
|
+
output: () => buffer,
|
|
88
|
+
completion: () => completion,
|
|
89
|
+
detach: () => {
|
|
90
|
+
buffering = false;
|
|
91
|
+
buffer = "";
|
|
92
|
+
},
|
|
93
|
+
stop: () => this.stopChild(child, request.name),
|
|
94
|
+
write: (text) => child.write(text),
|
|
95
|
+
screen: () => renderScreen(terminal),
|
|
96
|
+
onData: (handler) => {
|
|
97
|
+
dataHandlers.add(handler);
|
|
98
|
+
return () => dataHandlers.delete(handler);
|
|
99
|
+
},
|
|
100
|
+
resize: (nextCols, nextRows) => {
|
|
101
|
+
child.resize(nextCols, nextRows);
|
|
102
|
+
terminal.resize(nextCols, nextRows);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
this.runs.set(request.name, run);
|
|
106
|
+
return run;
|
|
107
|
+
}
|
|
108
|
+
get(name) {
|
|
109
|
+
return this.runs.get(name);
|
|
110
|
+
}
|
|
111
|
+
write(name, text) {
|
|
112
|
+
const run = this.runs.get(name);
|
|
113
|
+
if (!run) return false;
|
|
114
|
+
run.write(text.endsWith("\n") ? text : `${text}
|
|
115
|
+
`);
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
list() {
|
|
119
|
+
return [...this.runs.values()];
|
|
120
|
+
}
|
|
121
|
+
async disposeAll() {
|
|
122
|
+
const runs = [...this.runs.values()];
|
|
123
|
+
this.runs.clear();
|
|
124
|
+
for (const run of runs) await run.stop();
|
|
125
|
+
}
|
|
126
|
+
async stopChild(child, name) {
|
|
127
|
+
this.runs.delete(name);
|
|
128
|
+
if (!this.processControl.isAlive(child.pid)) return false;
|
|
129
|
+
child.kill("SIGTERM");
|
|
130
|
+
const deadline = this.clock.now() + TERM_GRACE_MS;
|
|
131
|
+
while (this.clock.now() < deadline) {
|
|
132
|
+
if (!this.processControl.isAlive(child.pid)) return true;
|
|
133
|
+
await new Promise((resolve) => {
|
|
134
|
+
this.clock.after(100, resolve);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
child.kill("SIGKILL");
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
/** The visible rows, trimmed of trailing blanks, as plain text. */
|
|
142
|
+
function renderScreen(terminal) {
|
|
143
|
+
const buffer = terminal.buffer.active;
|
|
144
|
+
const lines = [];
|
|
145
|
+
for (let row = buffer.baseY; row < buffer.baseY + terminal.rows; row += 1) lines.push(buffer.getLine(row)?.translateToString(true) ?? "");
|
|
146
|
+
while (lines.length > 0 && lines.at(-1) === "") lines.pop();
|
|
147
|
+
return lines.join("\n");
|
|
148
|
+
}
|
|
149
|
+
//#endregion
|
|
150
|
+
Object.defineProperty(exports, "PtyHost", {
|
|
151
|
+
enumerable: true,
|
|
152
|
+
get: function() {
|
|
153
|
+
return PtyHost;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
//# sourceMappingURL=ptyHost-MI2Z6WTG.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ptyHost-MI2Z6WTG.cjs","names":["headless","getResultMaxBytes","NO_TERMINAL_INPUT_ENV","PI_SESSION_ID_ENV","scrubTerminalOutput"],"sources":["../src/constants/ptyHost.ts","../src/services/ptyHost/index.ts"],"sourcesContent":["export const DEFAULT_COLS = 120;\nexport const DEFAULT_ROWS = 30;\nexport const SCROLLBACK = 2_000;\nexport const MEMORY_BUFFER_FACTOR = 2;\nexport const TERM_GRACE_MS = 2_000;\nexport const LIVENESS_POLL_MS = 100;\nexport const NEWLINE = '\\n';\n","import headless, { type Terminal } from '@xterm/headless';\n\nimport {\n DEFAULT_COLS,\n DEFAULT_ROWS,\n LIVENESS_POLL_MS,\n MEMORY_BUFFER_FACTOR,\n NEWLINE,\n SCROLLBACK,\n TERM_GRACE_MS,\n} from '../../constants/ptyHost';\nimport { PI_SESSION_ID_ENV } from '../../constants/session';\nimport type { IClock } from '../../types/clock';\nimport type { ILogFile } from '../../types/logFile';\nimport type { IProcessControl } from '../../types/processControl';\nimport type { IPtyHost, PtyLaunchRequest, PtyRun } from '../../types/ptyHost';\nimport type { IPtySpawner, PtyProcess } from '../../types/ptySpawner';\nimport type { RunnerSettings } from '../../types/runnerSettings';\nimport type { ExitResult } from '../../types/spawner';\nimport { scrubTerminalOutput } from '../ansiScrub';\nimport { getResultMaxBytes } from '../runnerConfig';\nimport { NO_TERMINAL_INPUT_ENV } from '../runnerSupervisor';\n\n/** Enough history for the overlay to scroll without holding a whole build. */\n\n// Use the CommonJS default export: Node cannot detect this package's named exports.\n// A static import also lets server bundles include it without a live node_modules lookup.\nconst { Terminal: HeadlessTerminal } = headless;\n\nexport class PtyHost implements IPtyHost {\n private readonly runs = new Map<string, PtyRun>();\n\n constructor(\n private readonly spawner: IPtySpawner,\n private readonly logFile: ILogFile,\n private readonly processControl: IProcessControl,\n private readonly clock: IClock,\n private readonly environment: Readonly<Record<string, string | undefined>> = process.env,\n private readonly settings?: RunnerSettings,\n ) {}\n\n async launch(request: PtyLaunchRequest): Promise<PtyRun> {\n const cols = request.cols ?? DEFAULT_COLS;\n const rows = request.rows ?? DEFAULT_ROWS;\n const writer = this.logFile.open(request.id);\n const terminal = new HeadlessTerminal({ cols, rows, scrollback: SCROLLBACK, allowProposedApi: true });\n const memoryLimit = getResultMaxBytes(this.environment, this.settings) * MEMORY_BUFFER_FACTOR;\n\n const child = await this.spawner.spawn({\n command: request.command,\n cwd: request.cwd,\n env: { ...this.environment, ...NO_TERMINAL_INPUT_ENV, [PI_SESSION_ID_ENV]: request.sessionId },\n cols,\n rows,\n });\n\n let buffer = '';\n let buffering = true;\n let settled = false;\n let resolveCompletion: (result: ExitResult) => void = () => undefined;\n const completion = new Promise<ExitResult>((resolve) => {\n resolveCompletion = resolve;\n });\n const dataHandlers = new Set<(data: string) => void>();\n\n child.onData((data) => {\n // The terminal keeps the screen; the log keeps text worth grepping.\n terminal.write(data);\n const scrubbed = scrubTerminalOutput(data);\n writer.append(scrubbed);\n if (buffering) {\n buffer += scrubbed;\n if (buffer.length > memoryLimit) buffer = buffer.slice(-memoryLimit);\n }\n for (const handler of dataHandlers) handler(data);\n });\n\n child.onExit((result) => {\n if (settled) return;\n settled = true;\n this.runs.delete(request.name);\n writer.close();\n resolveCompletion({ code: result.exitCode, signal: null });\n });\n\n const run: PtyRun = {\n id: request.id,\n name: request.name,\n pid: child.pid,\n logPath: writer.path,\n backend: 'native',\n output: () => buffer,\n completion: () => completion,\n detach: () => {\n buffering = false;\n buffer = '';\n },\n stop: () => this.stopChild(child, request.name),\n write: (text) => child.write(text),\n screen: () => renderScreen(terminal),\n onData: (handler) => {\n dataHandlers.add(handler);\n return () => dataHandlers.delete(handler);\n },\n resize: (nextCols, nextRows) => {\n child.resize(nextCols, nextRows);\n terminal.resize(nextCols, nextRows);\n },\n };\n\n this.runs.set(request.name, run);\n return run;\n }\n\n get(name: string): PtyRun | undefined {\n return this.runs.get(name);\n }\n\n write(name: string, text: string): boolean {\n const run = this.runs.get(name);\n if (!run) return false;\n run.write(text.endsWith(NEWLINE) ? text : `${text}${NEWLINE}`);\n return true;\n }\n\n list(): PtyRun[] {\n return [...this.runs.values()];\n }\n\n async disposeAll(): Promise<void> {\n const runs = [...this.runs.values()];\n this.runs.clear();\n for (const run of runs) await run.stop();\n }\n\n private async stopChild(child: PtyProcess, name: string): Promise<boolean> {\n this.runs.delete(name);\n if (!this.processControl.isAlive(child.pid)) return false;\n\n child.kill('SIGTERM');\n const deadline = this.clock.now() + TERM_GRACE_MS;\n while (this.clock.now() < deadline) {\n if (!this.processControl.isAlive(child.pid)) return true;\n await new Promise<void>((resolve) => {\n this.clock.after(LIVENESS_POLL_MS, resolve);\n });\n }\n child.kill('SIGKILL');\n return true;\n }\n}\n\n/** The visible rows, trimmed of trailing blanks, as plain text. */\nfunction renderScreen(terminal: Terminal): string {\n const buffer = terminal.buffer.active;\n const lines: string[] = [];\n for (let row = buffer.baseY; row < buffer.baseY + terminal.rows; row += 1) {\n lines.push(buffer.getLine(row)?.translateToString(true) ?? '');\n }\n while (lines.length > 0 && lines.at(-1) === '') lines.pop();\n return lines.join(NEWLINE);\n}\n"],"mappings":"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"}
|
package/dist/ptyHost.cjs
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { t as IClock } from "./clock-euJkweLq.mjs";
|
|
2
|
+
import { n as PtyLaunchRequest, r as PtyRun, t as IPtyHost } from "./ptyHost-DWWtRrGn.mjs";
|
|
3
|
+
import { t as ILogFile } from "./logFile-C7oQ_v-g.mjs";
|
|
4
|
+
import { t as IProcessControl } from "./processControl-BAOa3oo_.mjs";
|
|
5
|
+
import { t as IPtySpawner } from "./ptySpawner-B6GsueZd.mjs";
|
|
6
|
+
import { t as RunnerSettings } from "./runnerSettings-DiV1lvzx.mjs";
|
|
7
|
+
//#region src/services/ptyHost/index.d.ts
|
|
8
|
+
export declare class PtyHost implements IPtyHost {
|
|
9
|
+
private readonly spawner;
|
|
10
|
+
private readonly logFile;
|
|
11
|
+
private readonly processControl;
|
|
12
|
+
private readonly clock;
|
|
13
|
+
private readonly environment;
|
|
14
|
+
private readonly settings?;
|
|
15
|
+
private readonly runs;
|
|
16
|
+
constructor(spawner: IPtySpawner, logFile: ILogFile, processControl: IProcessControl, clock: IClock, environment?: Readonly<Record<string, string | undefined>>, settings?: RunnerSettings | undefined);
|
|
17
|
+
launch(request: PtyLaunchRequest): Promise<PtyRun>;
|
|
18
|
+
get(name: string): PtyRun | undefined;
|
|
19
|
+
write(name: string, text: string): boolean;
|
|
20
|
+
list(): PtyRun[];
|
|
21
|
+
disposeAll(): Promise<void>;
|
|
22
|
+
private stopChild;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export type { IPtyHost, PtyLaunchRequest, PtyRun };
|
|
26
|
+
//# sourceMappingURL=ptyHost.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ptyHost.d.mts","names":[],"sources":["../src/services/ptyHost/index.ts"],"mappings":";;;;;;;qBA6Ba,mBAAmB;mBAIX;mBACA;mBACA;mBACA;mBACA;mBACA;mBARF;EAEjB,YACmB,SAAS,aACT,SAAS,UACT,gBAAgB,iBAChB,OAAO,QACP,cAAa,SAAS,qCACtB,WAAW;EAGxB,OAAO,SAAS,mBAAmB,QAAQ;EAyEjD,IAAI,eAAe;EAInB,MAAM,cAAc;EAOpB,QAAQ;EAIF,cAAc;UAMN"}
|
package/dist/ptyHost.mjs
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/types/ptySpawner.d.ts
|
|
2
|
+
interface PtyExitResult {
|
|
3
|
+
exitCode: number;
|
|
4
|
+
signal?: number;
|
|
5
|
+
}
|
|
6
|
+
interface PtySpawnRequest {
|
|
7
|
+
/** Shell command line, run under a pseudo terminal so it can prompt. */
|
|
8
|
+
command: string;
|
|
9
|
+
cwd: string;
|
|
10
|
+
env: NodeJS.ProcessEnv;
|
|
11
|
+
cols: number;
|
|
12
|
+
rows: number;
|
|
13
|
+
}
|
|
14
|
+
interface PtyProcess {
|
|
15
|
+
readonly pid: number;
|
|
16
|
+
write(data: string): void;
|
|
17
|
+
resize(cols: number, rows: number): void;
|
|
18
|
+
onData(handler: (data: string) => void): void;
|
|
19
|
+
onExit(handler: (result: PtyExitResult) => void): void;
|
|
20
|
+
kill(signal?: string): void;
|
|
21
|
+
}
|
|
22
|
+
/** Pseudo terminal creation retained as a compatibility port for custom hosts. */
|
|
23
|
+
interface IPtySpawner {
|
|
24
|
+
spawn(request: PtySpawnRequest): Promise<PtyProcess>;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { PtySpawnRequest as i, PtyExitResult as n, PtyProcess as r, IPtySpawner as t };
|
|
28
|
+
//# sourceMappingURL=ptySpawner-B6GsueZd.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ptySpawner-B6GsueZd.d.mts","names":[],"sources":["../src/types/ptySpawner.ts"],"mappings":";UAAiB;EACf;EACA;;UAGe;;EAEf;EACA;EACA,KAAK,OAAO;EACZ;EACA;;UAGe;WACN;EACT,MAAM;EACN,OAAO,cAAc;EACrB,OAAO,UAAU;EACjB,OAAO,UAAU,QAAQ;EACzB,KAAK;;;UAIU;EACf,MAAM,SAAS,kBAAkB,QAAQ"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/services/ptySpawner/index.ts
|
|
2
|
+
const RMUX_REQUIRED_ERROR = "The node-pty fallback has been removed. Interactive commands require a supported RMUX runtime.";
|
|
3
|
+
/**
|
|
4
|
+
* Compatibility stub for the published NodePtySpawner subpath.
|
|
5
|
+
*
|
|
6
|
+
* Doom Runner no longer starts interactive commands through node-pty. The class
|
|
7
|
+
* remains exportable so existing imports fail at launch with an actionable error.
|
|
8
|
+
*/
|
|
9
|
+
var NodePtySpawner = class {
|
|
10
|
+
async spawn(_request) {
|
|
11
|
+
throw new Error(RMUX_REQUIRED_ERROR);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
export { NodePtySpawner as t };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=ptySpawner-DEi1KOnd.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ptySpawner-DEi1KOnd.mjs","names":[],"sources":["../src/services/ptySpawner/index.ts"],"sourcesContent":["import type { IPtySpawner, PtyProcess, PtySpawnRequest } from '../../types/ptySpawner';\n\nconst RMUX_REQUIRED_ERROR =\n 'The node-pty fallback has been removed. Interactive commands require a supported RMUX runtime.';\n\n/**\n * Compatibility stub for the published NodePtySpawner subpath.\n *\n * Doom Runner no longer starts interactive commands through node-pty. The class\n * remains exportable so existing imports fail at launch with an actionable error.\n */\nexport class NodePtySpawner implements IPtySpawner {\n async spawn(_request: PtySpawnRequest): Promise<PtyProcess> {\n throw new Error(RMUX_REQUIRED_ERROR);\n }\n}\n"],"mappings":";AAEA,MAAM,sBACJ;;;;;;;AAQF,IAAa,iBAAb,MAAmD;CACjD,MAAM,MAAM,UAAgD;EAC1D,MAAM,IAAI,MAAM,mBAAmB;CACrC;AACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/services/ptySpawner/index.ts
|
|
2
|
+
const RMUX_REQUIRED_ERROR = "The node-pty fallback has been removed. Interactive commands require a supported RMUX runtime.";
|
|
3
|
+
/**
|
|
4
|
+
* Compatibility stub for the published NodePtySpawner subpath.
|
|
5
|
+
*
|
|
6
|
+
* Doom Runner no longer starts interactive commands through node-pty. The class
|
|
7
|
+
* remains exportable so existing imports fail at launch with an actionable error.
|
|
8
|
+
*/
|
|
9
|
+
var NodePtySpawner = class {
|
|
10
|
+
async spawn(_request) {
|
|
11
|
+
throw new Error(RMUX_REQUIRED_ERROR);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
Object.defineProperty(exports, "NodePtySpawner", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function() {
|
|
18
|
+
return NodePtySpawner;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=ptySpawner-ijw0g5_T.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ptySpawner-ijw0g5_T.cjs","names":[],"sources":["../src/services/ptySpawner/index.ts"],"sourcesContent":["import type { IPtySpawner, PtyProcess, PtySpawnRequest } from '../../types/ptySpawner';\n\nconst RMUX_REQUIRED_ERROR =\n 'The node-pty fallback has been removed. Interactive commands require a supported RMUX runtime.';\n\n/**\n * Compatibility stub for the published NodePtySpawner subpath.\n *\n * Doom Runner no longer starts interactive commands through node-pty. The class\n * remains exportable so existing imports fail at launch with an actionable error.\n */\nexport class NodePtySpawner implements IPtySpawner {\n async spawn(_request: PtySpawnRequest): Promise<PtyProcess> {\n throw new Error(RMUX_REQUIRED_ERROR);\n }\n}\n"],"mappings":";AAEA,MAAM,sBACJ;;;;;;;AAQF,IAAa,iBAAb,MAAmD;CACjD,MAAM,MAAM,UAAgD;EAC1D,MAAM,IAAI,MAAM,mBAAmB;CACrC;AACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { i as PtySpawnRequest, n as PtyExitResult, r as PtyProcess, t as IPtySpawner } from "./ptySpawner-B6GsueZd.mjs";
|
|
2
|
+
//#region src/services/ptySpawner/index.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Compatibility stub for the published NodePtySpawner subpath.
|
|
5
|
+
*
|
|
6
|
+
* Doom Runner no longer starts interactive commands through node-pty. The class
|
|
7
|
+
* remains exportable so existing imports fail at launch with an actionable error.
|
|
8
|
+
*/
|
|
9
|
+
export declare class NodePtySpawner implements IPtySpawner {
|
|
10
|
+
spawn(_request: PtySpawnRequest): Promise<PtyProcess>;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export type { IPtySpawner, PtyExitResult, PtyProcess, PtySpawnRequest };
|
|
14
|
+
//# sourceMappingURL=ptySpawner.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ptySpawner.d.mts","names":[],"sources":["../src/services/ptySpawner/index.ts"],"mappings":";;;;;;;;qBAWa,0BAA0B;EAC/B,MAAM,UAAU,kBAAkB,QAAQ"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
|
|
2
|
+
let node_path = require("node:path");
|
|
3
|
+
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/services/reconcile/index.ts
|
|
6
|
+
const MULTIPLEXER_BACKENDS = /* @__PURE__ */ new Set(["rmux", "tmux"]);
|
|
7
|
+
async function stopRunnerProcess(record, launcher, rmuxBackend, termination) {
|
|
8
|
+
if (termination) await termination.registry.requestTermination(record.id, termination.intent, record.sessionId);
|
|
9
|
+
const stopped = (MULTIPLEXER_BACKENDS.has(record.backend) && record.backendTarget ? await rmuxBackend.stop(record.backendTarget, record.pid) : false) || await launcher.stop(record.pid);
|
|
10
|
+
if (!stopped && termination) await termination.registry.requestTermination(record.id, void 0, record.sessionId);
|
|
11
|
+
return stopped;
|
|
12
|
+
}
|
|
13
|
+
/** Repairs active registry entries that lost their original completion observer. */
|
|
14
|
+
async function reconcileActiveRunners(dependencies) {
|
|
15
|
+
const result = {
|
|
16
|
+
reclaimed: [],
|
|
17
|
+
errors: []
|
|
18
|
+
};
|
|
19
|
+
const active = dependencies.active ?? await dependencies.registry.list();
|
|
20
|
+
for (const record of active) try {
|
|
21
|
+
if ((await dependencies.registry.get(record.id, record.sessionId))?.state === "completed") {
|
|
22
|
+
await dependencies.registry.release(record.id, record.sessionId);
|
|
23
|
+
result.reclaimed.push(record.id);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const rmuxOutcome = MULTIPLEXER_BACKENDS.has(record.backend) ? dependencies.rmuxBackend.readOutcome(record.id, record.sessionId) : void 0;
|
|
27
|
+
if (rmuxOutcome) {
|
|
28
|
+
await dependencies.registry.complete(record.id, {
|
|
29
|
+
reason: rmuxOutcome.reason ?? (rmuxOutcome.signal ? "signaled" : rmuxOutcome.code === 0 ? "completed" : "failed"),
|
|
30
|
+
code: rmuxOutcome.code,
|
|
31
|
+
signal: rmuxOutcome.signal,
|
|
32
|
+
...rmuxOutcome.terminationReason ? { terminationReason: rmuxOutcome.terminationReason } : {},
|
|
33
|
+
...rmuxOutcome.stopReason ? { stopReason: rmuxOutcome.stopReason } : {}
|
|
34
|
+
}, record.sessionId);
|
|
35
|
+
result.reclaimed.push(record.id);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (!dependencies.processControl.isAlive(record.pid)) {
|
|
39
|
+
await dependencies.registry.complete(record.id, {
|
|
40
|
+
reason: "backend_lost",
|
|
41
|
+
code: null,
|
|
42
|
+
signal: null
|
|
43
|
+
}, record.sessionId);
|
|
44
|
+
result.reclaimed.push(record.id);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const previousRuntime = dependencies.startup && record.hostPid === dependencies.currentHostPid && record.sessionId === dependencies.startupSessionId;
|
|
48
|
+
const ownerLost = !dependencies.processControl.isAlive(record.hostPid);
|
|
49
|
+
if (!previousRuntime && !ownerLost) continue;
|
|
50
|
+
if (!await stopRunnerProcess(record, dependencies.launcher, dependencies.rmuxBackend, {
|
|
51
|
+
registry: dependencies.registry,
|
|
52
|
+
intent: {
|
|
53
|
+
reason: "stopped",
|
|
54
|
+
terminationReason: ownerLost ? "owner_lost" : "parent_session_cleanup",
|
|
55
|
+
stopReason: "owner session ended"
|
|
56
|
+
}
|
|
57
|
+
}) && dependencies.processControl.isAlive(record.pid)) {
|
|
58
|
+
result.errors.push(`Could not stop orphaned runner ${record.id}`);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
await dependencies.registry.complete(record.id, {
|
|
62
|
+
reason: "stopped",
|
|
63
|
+
code: null,
|
|
64
|
+
signal: "SIGTERM",
|
|
65
|
+
stopReason: "owner session ended"
|
|
66
|
+
}, record.sessionId);
|
|
67
|
+
result.reclaimed.push(record.id);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
result.errors.push(`Could not reconcile runner ${record.id}: ${String(error)}`);
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
function isWithin(root, candidate) {
|
|
74
|
+
const relative = node_path.default.relative(node_path.default.resolve(root), node_path.default.resolve(candidate));
|
|
75
|
+
return relative === "" || !relative.startsWith("..") && !node_path.default.isAbsolute(relative);
|
|
76
|
+
}
|
|
77
|
+
/** Deletes the legacy Git store only after no live foreign runner uses it. */
|
|
78
|
+
async function cleanupLegacyRunnerStore(dependencies) {
|
|
79
|
+
const result = {
|
|
80
|
+
reclaimed: [],
|
|
81
|
+
errors: []
|
|
82
|
+
};
|
|
83
|
+
const legacyDirectory = dependencies.paths.legacyDirectory();
|
|
84
|
+
if (!legacyDirectory) return result;
|
|
85
|
+
const legacyRecords = (await dependencies.registry.list()).filter((record) => isWithin(legacyDirectory, record.logPath));
|
|
86
|
+
for (const record of legacyRecords) {
|
|
87
|
+
const childAlive = dependencies.processControl.isAlive(record.pid);
|
|
88
|
+
const ownerAlive = dependencies.processControl.isAlive(record.hostPid);
|
|
89
|
+
if (childAlive && ownerAlive) continue;
|
|
90
|
+
try {
|
|
91
|
+
if (childAlive) {
|
|
92
|
+
if (!await stopRunnerProcess(record, dependencies.launcher, dependencies.rmuxBackend) && dependencies.processControl.isAlive(record.pid)) {
|
|
93
|
+
result.errors.push(`Could not stop legacy runner ${record.id}`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
await dependencies.registry.release(record.id, record.sessionId);
|
|
98
|
+
result.reclaimed.push(record.id);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
result.errors.push(`Could not reclaim legacy runner ${record.id}: ${String(error)}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
let liveDependencies;
|
|
104
|
+
try {
|
|
105
|
+
liveDependencies = (await dependencies.registry.listAcrossRepositories()).filter((record) => isWithin(legacyDirectory, record.logPath) && dependencies.processControl.isAlive(record.pid));
|
|
106
|
+
} catch (error) {
|
|
107
|
+
result.errors.push(`Could not verify legacy runner dependencies: ${String(error)}`);
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
if (result.errors.length === 0 && liveDependencies.length === 0) result.removed = dependencies.paths.removeLegacyStore();
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
Object.defineProperty(exports, "cleanupLegacyRunnerStore", {
|
|
115
|
+
enumerable: true,
|
|
116
|
+
get: function() {
|
|
117
|
+
return cleanupLegacyRunnerStore;
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
Object.defineProperty(exports, "reconcileActiveRunners", {
|
|
121
|
+
enumerable: true,
|
|
122
|
+
get: function() {
|
|
123
|
+
return reconcileActiveRunners;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
Object.defineProperty(exports, "stopRunnerProcess", {
|
|
127
|
+
enumerable: true,
|
|
128
|
+
get: function() {
|
|
129
|
+
return stopRunnerProcess;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
//# sourceMappingURL=reconcile-BugwYFbV.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
//#endregion
|
|
3
|
+
//#region src/services/reconcile/index.ts
|
|
4
|
+
const MULTIPLEXER_BACKENDS = /* @__PURE__ */ new Set(["rmux", "tmux"]);
|
|
5
|
+
async function stopRunnerProcess(record, launcher, rmuxBackend, termination) {
|
|
6
|
+
if (termination) await termination.registry.requestTermination(record.id, termination.intent, record.sessionId);
|
|
7
|
+
const stopped = (MULTIPLEXER_BACKENDS.has(record.backend) && record.backendTarget ? await rmuxBackend.stop(record.backendTarget, record.pid) : false) || await launcher.stop(record.pid);
|
|
8
|
+
if (!stopped && termination) await termination.registry.requestTermination(record.id, void 0, record.sessionId);
|
|
9
|
+
return stopped;
|
|
10
|
+
}
|
|
11
|
+
/** Repairs active registry entries that lost their original completion observer. */
|
|
12
|
+
async function reconcileActiveRunners(dependencies) {
|
|
13
|
+
const result = {
|
|
14
|
+
reclaimed: [],
|
|
15
|
+
errors: []
|
|
16
|
+
};
|
|
17
|
+
const active = dependencies.active ?? await dependencies.registry.list();
|
|
18
|
+
for (const record of active) try {
|
|
19
|
+
if ((await dependencies.registry.get(record.id, record.sessionId))?.state === "completed") {
|
|
20
|
+
await dependencies.registry.release(record.id, record.sessionId);
|
|
21
|
+
result.reclaimed.push(record.id);
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const rmuxOutcome = MULTIPLEXER_BACKENDS.has(record.backend) ? dependencies.rmuxBackend.readOutcome(record.id, record.sessionId) : void 0;
|
|
25
|
+
if (rmuxOutcome) {
|
|
26
|
+
await dependencies.registry.complete(record.id, {
|
|
27
|
+
reason: rmuxOutcome.reason ?? (rmuxOutcome.signal ? "signaled" : rmuxOutcome.code === 0 ? "completed" : "failed"),
|
|
28
|
+
code: rmuxOutcome.code,
|
|
29
|
+
signal: rmuxOutcome.signal,
|
|
30
|
+
...rmuxOutcome.terminationReason ? { terminationReason: rmuxOutcome.terminationReason } : {},
|
|
31
|
+
...rmuxOutcome.stopReason ? { stopReason: rmuxOutcome.stopReason } : {}
|
|
32
|
+
}, record.sessionId);
|
|
33
|
+
result.reclaimed.push(record.id);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (!dependencies.processControl.isAlive(record.pid)) {
|
|
37
|
+
await dependencies.registry.complete(record.id, {
|
|
38
|
+
reason: "backend_lost",
|
|
39
|
+
code: null,
|
|
40
|
+
signal: null
|
|
41
|
+
}, record.sessionId);
|
|
42
|
+
result.reclaimed.push(record.id);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const previousRuntime = dependencies.startup && record.hostPid === dependencies.currentHostPid && record.sessionId === dependencies.startupSessionId;
|
|
46
|
+
const ownerLost = !dependencies.processControl.isAlive(record.hostPid);
|
|
47
|
+
if (!previousRuntime && !ownerLost) continue;
|
|
48
|
+
if (!await stopRunnerProcess(record, dependencies.launcher, dependencies.rmuxBackend, {
|
|
49
|
+
registry: dependencies.registry,
|
|
50
|
+
intent: {
|
|
51
|
+
reason: "stopped",
|
|
52
|
+
terminationReason: ownerLost ? "owner_lost" : "parent_session_cleanup",
|
|
53
|
+
stopReason: "owner session ended"
|
|
54
|
+
}
|
|
55
|
+
}) && dependencies.processControl.isAlive(record.pid)) {
|
|
56
|
+
result.errors.push(`Could not stop orphaned runner ${record.id}`);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
await dependencies.registry.complete(record.id, {
|
|
60
|
+
reason: "stopped",
|
|
61
|
+
code: null,
|
|
62
|
+
signal: "SIGTERM",
|
|
63
|
+
stopReason: "owner session ended"
|
|
64
|
+
}, record.sessionId);
|
|
65
|
+
result.reclaimed.push(record.id);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
result.errors.push(`Could not reconcile runner ${record.id}: ${String(error)}`);
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
function isWithin(root, candidate) {
|
|
72
|
+
const relative = path.relative(path.resolve(root), path.resolve(candidate));
|
|
73
|
+
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
74
|
+
}
|
|
75
|
+
/** Deletes the legacy Git store only after no live foreign runner uses it. */
|
|
76
|
+
async function cleanupLegacyRunnerStore(dependencies) {
|
|
77
|
+
const result = {
|
|
78
|
+
reclaimed: [],
|
|
79
|
+
errors: []
|
|
80
|
+
};
|
|
81
|
+
const legacyDirectory = dependencies.paths.legacyDirectory();
|
|
82
|
+
if (!legacyDirectory) return result;
|
|
83
|
+
const legacyRecords = (await dependencies.registry.list()).filter((record) => isWithin(legacyDirectory, record.logPath));
|
|
84
|
+
for (const record of legacyRecords) {
|
|
85
|
+
const childAlive = dependencies.processControl.isAlive(record.pid);
|
|
86
|
+
const ownerAlive = dependencies.processControl.isAlive(record.hostPid);
|
|
87
|
+
if (childAlive && ownerAlive) continue;
|
|
88
|
+
try {
|
|
89
|
+
if (childAlive) {
|
|
90
|
+
if (!await stopRunnerProcess(record, dependencies.launcher, dependencies.rmuxBackend) && dependencies.processControl.isAlive(record.pid)) {
|
|
91
|
+
result.errors.push(`Could not stop legacy runner ${record.id}`);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
await dependencies.registry.release(record.id, record.sessionId);
|
|
96
|
+
result.reclaimed.push(record.id);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
result.errors.push(`Could not reclaim legacy runner ${record.id}: ${String(error)}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
let liveDependencies;
|
|
102
|
+
try {
|
|
103
|
+
liveDependencies = (await dependencies.registry.listAcrossRepositories()).filter((record) => isWithin(legacyDirectory, record.logPath) && dependencies.processControl.isAlive(record.pid));
|
|
104
|
+
} catch (error) {
|
|
105
|
+
result.errors.push(`Could not verify legacy runner dependencies: ${String(error)}`);
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
if (result.errors.length === 0 && liveDependencies.length === 0) result.removed = dependencies.paths.removeLegacyStore();
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
export { reconcileActiveRunners as n, stopRunnerProcess as r, cleanupLegacyRunnerStore as t };
|
|
113
|
+
|
|
114
|
+
//# sourceMappingURL=reconcile-DMeNSxwn.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_reconcile = require("./reconcile-BugwYFbV.cjs");
|
|
3
|
+
exports.cleanupLegacyRunnerStore = require_reconcile.cleanupLegacyRunnerStore;
|
|
4
|
+
exports.reconcileActiveRunners = require_reconcile.reconcileActiveRunners;
|
|
5
|
+
exports.stopRunnerProcess = require_reconcile.stopRunnerProcess;
|