@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,180 @@
|
|
|
1
|
+
const require_runnerConfig = require("./runnerConfig-D2tGq5ZM.cjs");
|
|
2
|
+
const require_bashTool = require("./bashTool-CdgtqVFD.cjs");
|
|
3
|
+
const require_bashResult = require("./bashResult-DNgtahGR.cjs");
|
|
4
|
+
const require_reconcile = require("./reconcile-BugwYFbV.cjs");
|
|
5
|
+
//#region src/constants/headless.ts
|
|
6
|
+
const MS_PER_SECOND = 1e3;
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/constants/runners.ts
|
|
9
|
+
const COMMAND_NAME = "runners";
|
|
10
|
+
const SERVER_COMMAND_DESCRIPTION = "Start and stop supervised background runners without a terminal UI.";
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/services/runnersCommand/index.ts
|
|
13
|
+
/** Splits on whitespace but keeps a double-quoted run together, so a path with spaces survives. */
|
|
14
|
+
function tokenize(text) {
|
|
15
|
+
return text.match(/(?:"[^"]*"|\S)+/gu) ?? [];
|
|
16
|
+
}
|
|
17
|
+
function unquote(value) {
|
|
18
|
+
return value.length >= 2 && value.startsWith("\"") && value.endsWith("\"") ? value.slice(1, -1) : value;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Parses `start`'s tail: `key=value` pairs up to the separator, then the
|
|
22
|
+
* command verbatim.
|
|
23
|
+
*
|
|
24
|
+
* Without a separator the whole tail is the command, so typing
|
|
25
|
+
* `/runners start pnpm build` does what it looks like. Options are read only
|
|
26
|
+
* when a separator says where they end, which is what keeps a command such as
|
|
27
|
+
* `FOO=bar pnpm test` from being mistaken for one.
|
|
28
|
+
*/
|
|
29
|
+
function parseStart(tail) {
|
|
30
|
+
const tokens = tokenize(tail);
|
|
31
|
+
const separator = tokens.indexOf("--");
|
|
32
|
+
if (separator === -1) return {
|
|
33
|
+
kind: "start",
|
|
34
|
+
command: tail.trim(),
|
|
35
|
+
interactive: false
|
|
36
|
+
};
|
|
37
|
+
const request = {
|
|
38
|
+
kind: "start",
|
|
39
|
+
command: tail.slice(tail.indexOf("--") + 2).trim(),
|
|
40
|
+
interactive: false
|
|
41
|
+
};
|
|
42
|
+
for (const token of tokens.slice(0, separator)) {
|
|
43
|
+
const split = token.indexOf("=");
|
|
44
|
+
if (split <= 0) continue;
|
|
45
|
+
const value = unquote(token.slice(split + 1));
|
|
46
|
+
const key = token.slice(0, split);
|
|
47
|
+
if (key === "name" && value !== "") request.name = value;
|
|
48
|
+
if (key === "cwd" && value !== "") request.cwd = value;
|
|
49
|
+
if (key === "interactive") request.interactive = value === "true";
|
|
50
|
+
}
|
|
51
|
+
return request;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Parses `/runners` arguments. Anything other than a known verb opens Runner
|
|
55
|
+
* Space, which is what the bare command has always done.
|
|
56
|
+
*/
|
|
57
|
+
function parseRunnersCommand(args) {
|
|
58
|
+
const trimmed = args.trim();
|
|
59
|
+
const [verb = "", id = "", ...rest] = trimmed.split(/\s+/u).filter(Boolean);
|
|
60
|
+
if (verb === "start") return parseStart(trimmed.slice(verb.length).trim());
|
|
61
|
+
if (verb !== "stop") return { kind: "space" };
|
|
62
|
+
const reason = rest.join(" ").trim();
|
|
63
|
+
return {
|
|
64
|
+
kind: "stop",
|
|
65
|
+
id,
|
|
66
|
+
...reason ? { reason } : {}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/services/headless/index.ts
|
|
71
|
+
function createHeadlessBashTool(bashRunService, summarizeLog, settings, environment = process.env) {
|
|
72
|
+
return {
|
|
73
|
+
name: require_bashTool.BASH_TOOL_NAME,
|
|
74
|
+
label: require_bashTool.BASH_TOOL_LABEL,
|
|
75
|
+
description: "Execute one Bash command in the current working directory. Foreground commands return bounded output; commands that outlive the threshold return a supervised runner id and streaming log path.",
|
|
76
|
+
promptSnippet: "Execute shell commands with bounded foreground output and supervised background runners",
|
|
77
|
+
promptGuidelines: [
|
|
78
|
+
`A command still running after ${Math.round(require_runnerConfig.getBackgroundThresholdMs() / MS_PER_SECOND)} seconds remains active as a background runner with an id and streaming log path.`,
|
|
79
|
+
"Pass background: true for commands that should remain active, such as dev servers, watchers, and tails.",
|
|
80
|
+
"Stop background runners when they are no longer needed."
|
|
81
|
+
],
|
|
82
|
+
parameters: require_bashTool.BashParamsSchema,
|
|
83
|
+
executionMode: "serial",
|
|
84
|
+
execute: async (_toolCallId, params, signal, onUpdate, context) => {
|
|
85
|
+
const { command, timeout, background, interactive, name } = params;
|
|
86
|
+
if (signal?.aborted) throw new Error("Operation aborted");
|
|
87
|
+
if (onUpdate) onUpdate(require_bashResult.textResult(`Starting ${interactive === true ? "interactive runner" : background === true ? "background runner" : "command"}...`));
|
|
88
|
+
let onOutput;
|
|
89
|
+
if (background !== true && interactive !== true && onUpdate) onOutput = (output) => onUpdate(require_bashResult.textResult(output));
|
|
90
|
+
const result = await bashRunService.run({
|
|
91
|
+
command,
|
|
92
|
+
timeoutMs: timeout === void 0 ? void 0 : timeout * MS_PER_SECOND,
|
|
93
|
+
background,
|
|
94
|
+
interactive,
|
|
95
|
+
name,
|
|
96
|
+
...onOutput ? { onOutput } : {},
|
|
97
|
+
...signal ? { signal } : {},
|
|
98
|
+
cwd: context.cwd,
|
|
99
|
+
sessionId: context.sessionId
|
|
100
|
+
});
|
|
101
|
+
if (signal?.aborted) throw new Error("Operation aborted");
|
|
102
|
+
return require_bashResult.formatRunResult(result, require_bashResult.parseResultPragma(command), summarizeLog, settings, environment);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function createHeadlessRunnersCommand(dependencies) {
|
|
107
|
+
return {
|
|
108
|
+
name: COMMAND_NAME,
|
|
109
|
+
description: SERVER_COMMAND_DESCRIPTION,
|
|
110
|
+
async execute(args, context) {
|
|
111
|
+
const request = parseRunnersCommand(args);
|
|
112
|
+
if (request.kind === "space") {
|
|
113
|
+
const active = await dependencies.runnerRegistry.listBySession(context.sessionId);
|
|
114
|
+
await context.client.notify({
|
|
115
|
+
body: `${active.length} active runner${active.length === 1 ? "" : "s"}.`,
|
|
116
|
+
level: "info"
|
|
117
|
+
});
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (request.kind === "start") {
|
|
121
|
+
if (!request.command) throw new Error("Usage: /runners start [name=x] [cwd=y] [interactive=true] -- <command>");
|
|
122
|
+
const result = await dependencies.bashRunService.run({
|
|
123
|
+
command: request.command,
|
|
124
|
+
background: true,
|
|
125
|
+
sessionId: context.sessionId,
|
|
126
|
+
cwd: request.cwd === void 0 ? context.cwd : request.cwd,
|
|
127
|
+
...request.name ? { name: request.name } : {},
|
|
128
|
+
...request.interactive ? { interactive: true } : {}
|
|
129
|
+
});
|
|
130
|
+
await context.client.notify({
|
|
131
|
+
body: require_bashResult.formatRunResult(result, {}, void 0, dependencies.settings, dependencies.environment).content[0]?.text ?? "Runner started.",
|
|
132
|
+
level: "info"
|
|
133
|
+
});
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (!request.id) throw new Error("Usage: /runners stop <runner-id> [reason]");
|
|
137
|
+
const record = await dependencies.runnerRegistry.get(request.id, context.sessionId);
|
|
138
|
+
if (!record) {
|
|
139
|
+
await context.client.notify({
|
|
140
|
+
body: `No active runner ${request.id} in this session.`,
|
|
141
|
+
level: "warning"
|
|
142
|
+
});
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const stopped = await require_reconcile.stopRunnerProcess(record, dependencies.launcher, dependencies.rmuxBackend, {
|
|
146
|
+
registry: dependencies.runnerRegistry,
|
|
147
|
+
intent: {
|
|
148
|
+
reason: "stopped",
|
|
149
|
+
terminationReason: "user_stop",
|
|
150
|
+
...request.reason ? { stopReason: request.reason } : {}
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
if (stopped) await dependencies.runnerRegistry.complete(request.id, {
|
|
154
|
+
reason: "stopped",
|
|
155
|
+
code: null,
|
|
156
|
+
signal: null,
|
|
157
|
+
...request.reason ? { stopReason: request.reason } : {}
|
|
158
|
+
}, context.sessionId);
|
|
159
|
+
await context.client.notify({
|
|
160
|
+
body: stopped ? `Stopped runner ${request.id}.` : `Could not stop runner ${request.id}.`,
|
|
161
|
+
level: stopped ? "info" : "error"
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
//#endregion
|
|
167
|
+
Object.defineProperty(exports, "createHeadlessBashTool", {
|
|
168
|
+
enumerable: true,
|
|
169
|
+
get: function() {
|
|
170
|
+
return createHeadlessBashTool;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
Object.defineProperty(exports, "createHeadlessRunnersCommand", {
|
|
174
|
+
enumerable: true,
|
|
175
|
+
get: function() {
|
|
176
|
+
return createHeadlessRunnersCommand;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
//# sourceMappingURL=headless-CHUsBGhg.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headless-CHUsBGhg.cjs","names":["BASH_TOOL_NAME","BASH_TOOL_LABEL","getBackgroundThresholdMs","BashParamsSchema","textResult","formatRunResult","parseResultPragma","stopRunnerProcess"],"sources":["../src/constants/headless.ts","../src/constants/runners.ts","../src/constants/runnersCommand.ts","../src/services/runnersCommand/index.ts","../src/services/headless/index.ts"],"sourcesContent":["export const MS_PER_SECOND = 1000;\n","export const COMMAND_NAME = 'runners';\nexport const COMMAND_DESCRIPTION =\n 'Open Runner Space: background processes started by bash. `/runners stop <id> [reason]` stops one, `/runners start [name=x] [cwd=y] [interactive=true] -- <command>` starts one.';\nexport const SERVER_COMMAND_DESCRIPTION = 'Start and stop supervised background runners without a terminal UI.';\n","export const RUNNERS_STOP_VERB = 'stop';\nexport const RUNNERS_START_VERB = 'start';\nexport const RUNNERS_COMMAND_SEPARATOR = '--';\nexport const NAME_KEY = 'name';\nexport const CWD_KEY = 'cwd';\nexport const INTERACTIVE_KEY = 'interactive';\n","import {\n CWD_KEY,\n INTERACTIVE_KEY,\n NAME_KEY,\n RUNNERS_COMMAND_SEPARATOR,\n RUNNERS_START_VERB,\n RUNNERS_STOP_VERB,\n} from '../../constants/runnersCommand';\n/** The `/runners` verb that stops one runner without opening Runner Space. */\n/** The `/runners` verb that starts one, for a client that cannot call the bash tool. */\n/**\n * Ends the options and begins the command.\n *\n * A command is arbitrary shell: it may hold `=`, and it may hold flags of its\n * own (`pnpm test -- --watch`). Only the first of these is the separator, so\n * everything the reader typed survives intact after it.\n */\n\nexport interface RunnersStartRequest {\n kind: 'start';\n /** The shell command to run; empty when the reader gave none. */\n command: string;\n cwd?: string;\n name?: string;\n interactive: boolean;\n}\n\nexport type RunnersCommandRequest =\n /** No arguments: open Runner Space. */\n | { kind: 'space' }\n /** `stop <id> [reason]`: stop one runner headlessly; id is empty when it was left out. */\n | { kind: 'stop'; id: string; reason?: string }\n /** `start [key=value ...] -- <command>`: start one headlessly. */\n | RunnersStartRequest;\n\n/** Splits on whitespace but keeps a double-quoted run together, so a path with spaces survives. */\nfunction tokenize(text: string): string[] {\n return text.match(/(?:\"[^\"]*\"|\\S)+/gu) ?? [];\n}\n\nfunction unquote(value: string): string {\n return value.length >= 2 && value.startsWith('\"') && value.endsWith('\"') ? value.slice(1, -1) : value;\n}\n\n/**\n * Parses `start`'s tail: `key=value` pairs up to the separator, then the\n * command verbatim.\n *\n * Without a separator the whole tail is the command, so typing\n * `/runners start pnpm build` does what it looks like. Options are read only\n * when a separator says where they end, which is what keeps a command such as\n * `FOO=bar pnpm test` from being mistaken for one.\n */\nfunction parseStart(tail: string): RunnersStartRequest {\n const tokens = tokenize(tail);\n const separator = tokens.indexOf(RUNNERS_COMMAND_SEPARATOR);\n if (separator === -1) return { kind: 'start', command: tail.trim(), interactive: false };\n\n const request: RunnersStartRequest = {\n kind: 'start',\n // Sliced from the raw text rather than rejoined from tokens: rejoining\n // would collapse the spacing the reader wrote.\n command: tail.slice(tail.indexOf(RUNNERS_COMMAND_SEPARATOR) + RUNNERS_COMMAND_SEPARATOR.length).trim(),\n interactive: false,\n };\n for (const token of tokens.slice(0, separator)) {\n const split = token.indexOf('=');\n if (split <= 0) continue;\n const value = unquote(token.slice(split + 1));\n const key = token.slice(0, split);\n if (key === NAME_KEY && value !== '') request.name = value;\n if (key === CWD_KEY && value !== '') request.cwd = value;\n if (key === INTERACTIVE_KEY) request.interactive = value === 'true';\n }\n return request;\n}\n\n/**\n * Parses `/runners` arguments. Anything other than a known verb opens Runner\n * Space, which is what the bare command has always done.\n */\nexport function parseRunnersCommand(args: string): RunnersCommandRequest {\n const trimmed = args.trim();\n const [verb = '', id = '', ...rest] = trimmed.split(/\\s+/u).filter(Boolean);\n if (verb === RUNNERS_START_VERB) return parseStart(trimmed.slice(verb.length).trim());\n if (verb !== RUNNERS_STOP_VERB) return { kind: 'space' };\n const reason = rest.join(' ').trim();\n return { kind: 'stop', id, ...(reason ? { reason } : {}) };\n}\n","import type {\n DoomHeadlessCommand,\n DoomHeadlessExecutionContext,\n DoomHeadlessTool,\n DoomHeadlessToolResult,\n} from '@agimon-ai/po-core/headless';\n\nimport { BASH_TOOL_LABEL, BASH_TOOL_NAME } from '../../constants/bashTool';\nimport { MS_PER_SECOND } from '../../constants/headless';\nimport { COMMAND_NAME, SERVER_COMMAND_DESCRIPTION } from '../../constants/runners';\nimport { type BashParams, BashParamsSchema } from '../../schemas/bashTool';\nimport { formatRunResult, parseResultPragma, textResult } from '../../services/bashResult';\nimport { stopRunnerProcess } from '../../services/reconcile';\nimport { getBackgroundThresholdMs } from '../../services/runnerConfig';\nimport type { RunnerDependencies } from '../../services/runnerDependencies/type';\nimport { parseRunnersCommand } from '../../services/runnersCommand';\nimport { type LogSummarizer } from '../../types/bashResult';\nimport type { IBashRunService } from '../../types/bashRunService';\nimport type { RunnerSettings } from '../../types/runnerSettings';\n\nexport function createHeadlessBashTool(\n bashRunService: IBashRunService,\n summarizeLog?: LogSummarizer,\n settings?: RunnerSettings,\n environment: NodeJS.ProcessEnv = process.env,\n): DoomHeadlessTool<typeof BashParamsSchema> {\n return {\n name: BASH_TOOL_NAME,\n label: BASH_TOOL_LABEL,\n description:\n 'Execute one Bash command in the current working directory. Foreground commands return bounded output; commands that outlive the threshold return a supervised runner id and streaming log path.',\n promptSnippet: 'Execute shell commands with bounded foreground output and supervised background runners',\n promptGuidelines: [\n `A command still running after ${Math.round(getBackgroundThresholdMs() / MS_PER_SECOND)} seconds remains active as a background runner with an id and streaming log path.`,\n 'Pass background: true for commands that should remain active, such as dev servers, watchers, and tails.',\n 'Stop background runners when they are no longer needed.',\n ],\n parameters: BashParamsSchema,\n executionMode: 'serial',\n execute: async (\n _toolCallId: string,\n params: BashParams,\n signal: AbortSignal | undefined,\n onUpdate: ((result: DoomHeadlessToolResult) => void) | undefined,\n context: DoomHeadlessExecutionContext,\n ) => {\n const { command, timeout, background, interactive, name } = params;\n if (signal?.aborted) throw new Error('Operation aborted');\n if (onUpdate)\n onUpdate(\n textResult(\n `Starting ${interactive === true ? 'interactive runner' : background === true ? 'background runner' : 'command'}...`,\n ),\n );\n let onOutput: ((output: string) => void) | undefined;\n if (background !== true && interactive !== true && onUpdate) onOutput = (output) => onUpdate(textResult(output));\n const result = await bashRunService.run({\n command,\n timeoutMs: timeout === undefined ? undefined : timeout * MS_PER_SECOND,\n background,\n interactive,\n name,\n ...(onOutput ? { onOutput } : {}),\n ...(signal ? { signal } : {}),\n cwd: context.cwd,\n sessionId: context.sessionId,\n });\n if (signal?.aborted) throw new Error('Operation aborted');\n return formatRunResult(result, parseResultPragma(command), summarizeLog, settings, environment);\n },\n };\n}\n\nexport function createHeadlessRunnersCommand(dependencies: RunnerDependencies): DoomHeadlessCommand {\n return {\n name: COMMAND_NAME,\n description: SERVER_COMMAND_DESCRIPTION,\n async execute(args: string, context: DoomHeadlessExecutionContext) {\n const request = parseRunnersCommand(args);\n if (request.kind === 'space') {\n const active = await dependencies.runnerRegistry.listBySession(context.sessionId);\n await context.client.notify({\n body: `${active.length} active runner${active.length === 1 ? '' : 's'}.`,\n level: 'info',\n });\n return;\n }\n if (request.kind === 'start') {\n if (!request.command) throw new Error('Usage: /runners start [name=x] [cwd=y] [interactive=true] -- <command>');\n const result = await dependencies.bashRunService.run({\n command: request.command,\n background: true,\n sessionId: context.sessionId,\n cwd: request.cwd === undefined ? context.cwd : request.cwd,\n ...(request.name ? { name: request.name } : {}),\n ...(request.interactive ? { interactive: true } : {}),\n });\n await context.client.notify({\n body:\n formatRunResult(result, {}, undefined, dependencies.settings, dependencies.environment).content[0]?.text ??\n 'Runner started.',\n level: 'info',\n });\n return;\n }\n if (!request.id) throw new Error('Usage: /runners stop <runner-id> [reason]');\n const record = await dependencies.runnerRegistry.get(request.id, context.sessionId);\n if (!record) {\n await context.client.notify({ body: `No active runner ${request.id} in this session.`, level: 'warning' });\n return;\n }\n const stopped = await stopRunnerProcess(record, dependencies.launcher, dependencies.rmuxBackend, {\n registry: dependencies.runnerRegistry,\n intent: {\n reason: 'stopped',\n terminationReason: 'user_stop',\n ...(request.reason ? { stopReason: request.reason } : {}),\n },\n });\n if (stopped) {\n await dependencies.runnerRegistry.complete(\n request.id,\n {\n reason: 'stopped',\n code: null,\n signal: null,\n ...(request.reason ? { stopReason: request.reason } : {}),\n },\n context.sessionId,\n );\n }\n await context.client.notify({\n body: stopped ? `Stopped runner ${request.id}.` : `Could not stop runner ${request.id}.`,\n level: stopped ? 'info' : 'error',\n });\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { c as RtkProcessResult, o as RtkFilter, s as RtkProcessRequest, t as IRtkProcessor } from "./rtkProcessor-CVZvNhkJ.mjs";
|
|
2
|
+
import { t as RunnerSettings } from "./runnerSettings-DiV1lvzx.mjs";
|
|
3
|
+
//#region src/services/rtkProcessor/index.d.ts
|
|
4
|
+
type BinaryResolver = () => string | undefined;
|
|
5
|
+
declare class RtkProcessor implements IRtkProcessor {
|
|
6
|
+
private readonly resolveBinary;
|
|
7
|
+
private readonly timeoutMs;
|
|
8
|
+
private readonly env;
|
|
9
|
+
private readonly settings?;
|
|
10
|
+
/**
|
|
11
|
+
* Latched once a binary proves unrunnable on this host.
|
|
12
|
+
*
|
|
13
|
+
* A glibc build installed on a musl host satisfies os and cpu, so it
|
|
14
|
+
* resolves and then fails to exec. Without this the same doomed spawn is
|
|
15
|
+
* paid on every command, and each one is reported as a processing failure
|
|
16
|
+
* rather than the absence it actually is.
|
|
17
|
+
*/
|
|
18
|
+
private unrunnable;
|
|
19
|
+
constructor(resolveBinary?: BinaryResolver, timeoutMs?: number, env?: Readonly<Record<string, string | undefined>>, settings?: RunnerSettings | undefined);
|
|
20
|
+
process(request: RtkProcessRequest): Promise<RtkProcessResult>;
|
|
21
|
+
private pipe;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Classifies only whitespace-delimited single commands. Shell syntax, expansion,
|
|
25
|
+
* quoting, and globbing are rejected instead of being partially interpreted.
|
|
26
|
+
*/
|
|
27
|
+
declare function classifyRtkFilter(command: string): RtkFilter | undefined;
|
|
28
|
+
declare function rtkPackageForTarget(platform: string, architecture: string): string | undefined;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { classifyRtkFilter as n, rtkPackageForTarget as r, RtkProcessor as t };
|
|
31
|
+
//# sourceMappingURL=index-BZL7keVW.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BZL7keVW.d.mts","names":[],"sources":["../src/services/rtkProcessor/index.ts"],"mappings":";;;KA8EK;cAEQ,wBAAwB;mBAYhB;mBACA;mBACA;mBACA;;;;;;;;;UANX;EAER,YACmB,gBAAe,gBACf,oBACA,MAAK,SAAS,qCACd,WAAW;EAGxB,QAAQ,SAAS,oBAAoB,QAAQ;UA0B3C;;;;;;iBAwGM,kBAAkB,kBAAkB;iBAyDpC,oBAAoB,kBAAkB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { a as IBashRunService } from "./bashRunService-Ci0cGdYO.mjs";
|
|
2
|
+
import { n as BashParamsSchema } from "./bashTool-B1EwZLo_.mjs";
|
|
3
|
+
import { r as LogSummarizer } from "./bashResult-DcrRaBLv.mjs";
|
|
4
|
+
import { t as RunnerSettings } from "./runnerSettings-DiV1lvzx.mjs";
|
|
5
|
+
import { t as RunnerDependencies } from "./type-C31e1gla.mjs";
|
|
6
|
+
import { DoomHeadlessCommand, DoomHeadlessTool } from "@agimon-ai/po-core/headless";
|
|
7
|
+
//#region src/services/headless/index.d.ts
|
|
8
|
+
declare function createHeadlessBashTool(bashRunService: IBashRunService, summarizeLog?: LogSummarizer, settings?: RunnerSettings, environment?: NodeJS.ProcessEnv): DoomHeadlessTool<typeof BashParamsSchema>;
|
|
9
|
+
declare function createHeadlessRunnersCommand(dependencies: RunnerDependencies): DoomHeadlessCommand;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { createHeadlessRunnersCommand as n, createHeadlessBashTool as t };
|
|
12
|
+
//# sourceMappingURL=index-BwB_jTI9.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BwB_jTI9.d.mts","names":[],"sources":["../src/services/headless/index.ts"],"mappings":";;;;;;;iBAoBgB,uBACd,gBAAgB,iBAChB,eAAe,eACf,WAAW,gBACX,cAAa,OAAO,aACnB,wBAAwB;iBAgDX,6BAA6B,cAAc,qBAAqB"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { t as ExitResult } from "./spawner-CdrN_HNk.mjs";
|
|
2
|
+
import { r as RunHandle } from "./launcher-BG5t9nvG.mjs";
|
|
3
|
+
import { r as PtyRun } from "./ptyHost-DWWtRrGn.mjs";
|
|
4
|
+
import { n as RmuxLaunchRequest, t as IRmuxBackend } from "./rmuxBackend-CaEWooWn.mjs";
|
|
5
|
+
import { t as RunnerSettings } from "./runnerSettings-DiV1lvzx.mjs";
|
|
6
|
+
import { t as IRunnerPaths } from "./type-BXM03qSw.mjs";
|
|
7
|
+
//#region src/services/rmuxBackend/index.d.ts
|
|
8
|
+
declare class RmuxBackend implements IRmuxBackend {
|
|
9
|
+
private readonly paths;
|
|
10
|
+
private readonly env;
|
|
11
|
+
private readonly settings?;
|
|
12
|
+
private clientPromise;
|
|
13
|
+
private readonly runs;
|
|
14
|
+
private readonly completions;
|
|
15
|
+
constructor(paths: IRunnerPaths, env?: Readonly<Record<string, string | undefined>>, settings?: RunnerSettings | undefined);
|
|
16
|
+
launch(request: RmuxLaunchRequest): Promise<RunHandle | undefined>;
|
|
17
|
+
stop(target: string, expectedPid: number): Promise<boolean>;
|
|
18
|
+
watch(id: string, target: string, sessionId?: string): Promise<ExitResult | undefined>;
|
|
19
|
+
input(target: string, text: string): Promise<boolean>;
|
|
20
|
+
capture(target: string): Promise<string | undefined>;
|
|
21
|
+
get(name: string): PtyRun | undefined;
|
|
22
|
+
readOutcome(id: string, sessionId: string): ExitResult | undefined;
|
|
23
|
+
private trackCompletion;
|
|
24
|
+
private client;
|
|
25
|
+
private resolveClient;
|
|
26
|
+
private prepareFiles;
|
|
27
|
+
private auxPaths;
|
|
28
|
+
/**
|
|
29
|
+
* The sink the pane pipes into.
|
|
30
|
+
*
|
|
31
|
+
* An interactive run also asks for a raw copy: the scrubbed log it writes
|
|
32
|
+
* beside it has had cursor movement taken out, which is what a terminal
|
|
33
|
+
* needs most. Only interactive runs pay for it, because only they can be
|
|
34
|
+
* attached to.
|
|
35
|
+
*/
|
|
36
|
+
private logPipeCommand;
|
|
37
|
+
private monitor;
|
|
38
|
+
private interactiveRun;
|
|
39
|
+
}
|
|
40
|
+
declare function rmuxPackageForTarget(platform: string, architecture: string): string | undefined;
|
|
41
|
+
//#endregion
|
|
42
|
+
export { rmuxPackageForTarget as n, RmuxBackend as t };
|
|
43
|
+
//# sourceMappingURL=index-D9-IXax4.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-D9-IXax4.d.mts","names":[],"sources":["../src/services/rmuxBackend/index.ts"],"mappings":";;;;;;;cAoDa,uBAAuB;mBAMf;mBACA;mBACA;UAPX;mBACS;mBACA;EAEjB,YACmB,OAAO,cACP,MAAK,SAAS,qCACd,WAAW;EAGxB,OAAO,SAAS,oBAAoB,QAAQ;EAuF5C,KAAK,gBAAgB,sBAAsB;EA6B3C,MAAM,YAAY,gBAAgB,qBAAqB,QAAQ;EAe/D,MAAM,gBAAgB,eAAe;EAcrC,QAAQ,iBAAiB;EAa/B,IAAI,eAAe;EAInB,YAAY,YAAY,oBAAoB;UAIpC;UAOA;UAKM;UAkBN;UAUA;;;;;;;;;UAYA;UAaM;UA+BN;;iBA4CM,qBAAqB,kBAAkB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { a as RunnerTerminationIntent, i as RunnerRecord, n as IRunnerRegistry, r as RegisterRunnerInput, t as CompleteRunnerInput } from "./runnerRegistry-CtJiD02R.mjs";
|
|
2
|
+
import { t as IProcessControl } from "./processControl-BAOa3oo_.mjs";
|
|
3
|
+
import { t as IRunnerPaths } from "./type-BXM03qSw.mjs";
|
|
4
|
+
import { ProcessRegistryService } from "@agimon-ai/foundation-process-registry";
|
|
5
|
+
//#region src/services/runnerRegistry/index.d.ts
|
|
6
|
+
/** The slice of the shared registry service this wrapper depends on. */
|
|
7
|
+
type ProcessRegistryPort = Pick<ProcessRegistryService, 'registerProcess' | 'releaseProcess' | 'listProcesses' | 'close'>;
|
|
8
|
+
/** Opens the SQLite-backed registry the rest of the monorepo already shares. */
|
|
9
|
+
declare function createDefaultProcessRegistry(env?: Readonly<Record<string, string | undefined>>): ProcessRegistryPort;
|
|
10
|
+
declare class RunnerRegistry implements IRunnerRegistry {
|
|
11
|
+
private readonly paths;
|
|
12
|
+
private readonly processControl;
|
|
13
|
+
private readonly registry;
|
|
14
|
+
private readonly environment;
|
|
15
|
+
private readonly subscriptions;
|
|
16
|
+
constructor(paths: IRunnerPaths, processControl: IProcessControl, registry: ProcessRegistryPort, environment: Readonly<Record<string, string | undefined>>);
|
|
17
|
+
register(input: RegisterRunnerInput): Promise<RunnerRecord>;
|
|
18
|
+
list(): Promise<RunnerRecord[]>;
|
|
19
|
+
listAcrossRepositories(): Promise<RunnerRecord[]>;
|
|
20
|
+
listBySession(sessionId: string): Promise<RunnerRecord[]>;
|
|
21
|
+
listByRootSession(rootSessionId: string): Promise<RunnerRecord[]>;
|
|
22
|
+
listAll(sessionId?: string): Promise<RunnerRecord[]>;
|
|
23
|
+
get(id: string, sessionId?: string): Promise<RunnerRecord | undefined>;
|
|
24
|
+
markPromoted(id: string): Promise<RunnerRecord | undefined>;
|
|
25
|
+
requestTermination(id: string, intent: RunnerTerminationIntent | undefined, sessionId?: string): Promise<RunnerRecord | undefined>;
|
|
26
|
+
complete(id: string, outcome: CompleteRunnerInput, sessionId?: string): Promise<RunnerRecord | undefined>;
|
|
27
|
+
release(id: string, sessionId?: string): Promise<void>;
|
|
28
|
+
pruneDead(): Promise<string[]>;
|
|
29
|
+
subscribe(listener: () => void, sessionId: string): () => void;
|
|
30
|
+
close(): void;
|
|
31
|
+
private notify;
|
|
32
|
+
private removeSubscription;
|
|
33
|
+
private subscriptionKey;
|
|
34
|
+
private repositoryPath;
|
|
35
|
+
private writeRecord;
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { RunnerRegistry as n, createDefaultProcessRegistry as r, ProcessRegistryPort as t };
|
|
39
|
+
//# sourceMappingURL=index-DBz0DxnL.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-DBz0DxnL.d.mts","names":[],"sources":["../src/services/runnerRegistry/index.ts"],"mappings":";;;;;;KAoCY,sBAAsB,KAChC;;iBAKc,6BACd,MAAK,SAAS,sCACb;cA+CU,0BAA0B;mBAIlB;mBACA;mBACA;mBACA;mBANF;EAEjB,YACmB,OAAO,cACP,gBAAgB,iBAChB,UAAU,qBACV,aAAa,SAAS;EAGnC,SAAS,OAAO,sBAAsB,QAAQ;EAqD9C,QAAQ,QAAQ;EAShB,0BAA0B,QAAQ;EAQlC,cAAc,oBAAoB,QAAQ;EAK1C,kBAAkB,wBAAwB,QAAQ;EAKlD,QAAQ,qBAAqB,QAAQ;EAgBrC,IAAI,YAAY,qBAAqB,QAAQ;EAgB7C,aAAa,aAAa,QAAQ;EASlC,mBACJ,YACA,QAAQ,qCACR,qBACC,QAAQ;EAWL,SAAS,YAAY,SAAS,qBAAqB,qBAAqB,QAAQ;EAiChF,QAAQ,YAAY,qBAAqB;EAiBzC,aAAa;EAQnB,UAAU,sBAAsB;EAUhC;UAKQ;UAUA;UAOA;UAIA;UAIA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { c as TruncatedOutput, i as LogSummary } from "./bashResult-DcrRaBLv.mjs";
|
|
2
|
+
import { n as LogQuery, r as LogSlice, t as ILogReader } from "./logReader-MdW9ffvV.mjs";
|
|
3
|
+
import { t as RunnerSettings } from "./runnerSettings-DiV1lvzx.mjs";
|
|
4
|
+
//#region src/services/logReader/index.d.ts
|
|
5
|
+
declare class LogReader implements ILogReader {
|
|
6
|
+
read(logPath: string, query?: LogQuery): LogSlice;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Grep with context, matching the `product-stack logs` semantics so the two
|
|
10
|
+
* surfaces behave the same. Overlapping and adjacent context windows merge.
|
|
11
|
+
*/
|
|
12
|
+
declare function filterLogText(text: string, query: Pick<LogQuery, 'grep' | 'ignoreCase' | 'contextLines'>): string;
|
|
13
|
+
/** Reads a bounded head and tail plus exact metadata after the writer has flushed. */
|
|
14
|
+
declare function summarizeLog(path: string, maxLines?: number, maxBytes?: number, maxTokens?: number, settings?: RunnerSettings): LogSummary;
|
|
15
|
+
/**
|
|
16
|
+
* Keeps both ends of an oversized result and points at the file holding the rest.
|
|
17
|
+
*
|
|
18
|
+
* The notice states the file's real size and line count so the model does not
|
|
19
|
+
* guess at offsets when it goes on to read the file, which is the failure this
|
|
20
|
+
* whole policy exists to prevent.
|
|
21
|
+
*/
|
|
22
|
+
declare function truncateForResult(text: string, fullOutputPath: string, maxBytes?: number, maxLines?: number): TruncatedOutput;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { truncateForResult as i, filterLogText as n, summarizeLog as r, LogReader as t };
|
|
25
|
+
//# sourceMappingURL=index-DM7yJpMs.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-DM7yJpMs.d.mts","names":[],"sources":["../src/services/logReader/index.ts"],"mappings":";;;;cAuBa,qBAAqB;EAChC,KAAK,iBAAiB,QAAO,WAAgB;;;;;;iBA0G/B,cAAc,cAAc,OAAO,KAAK;;iBA8BxC,aACd,cACA,mBACA,mBACA,oBACA,WAAW,iBACV;;;;;;;;iBAmEa,kBACd,cACA,wBACA,mBACA,oBACC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { t as RunnerDependencies } from "./type-C31e1gla.mjs";
|
|
2
|
+
import { DoomHostExecutionBudget } from "@agimon-ai/po-core/packageApi";
|
|
3
|
+
//#region src/services/runnerDependencies/index.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Builds the extension's service graph.
|
|
6
|
+
*
|
|
7
|
+
* A factory rather than a module-level singleton: the extension owns one graph
|
|
8
|
+
* per session, and tests get a fresh one they can substitute ports on through
|
|
9
|
+
* `overrides` without leaking state between cases.
|
|
10
|
+
*
|
|
11
|
+
* Every slot resolves lazily and memoizes, which keeps the previous container's
|
|
12
|
+
* behaviour: nothing is constructed until it is asked for, so opening the SQLite
|
|
13
|
+
* process registry stays deferred until something actually needs a runner.
|
|
14
|
+
*/
|
|
15
|
+
declare function createRunnerDependencies(overrides: Partial<RunnerDependencies> & {
|
|
16
|
+
environment: Readonly<Record<string, string | undefined>>;
|
|
17
|
+
cwd?: string;
|
|
18
|
+
executionBudget?: DoomHostExecutionBudget;
|
|
19
|
+
}): RunnerDependencies;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { createRunnerDependencies as t };
|
|
22
|
+
//# sourceMappingURL=index-Dhi8asLH.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-Dhi8asLH.d.mts","names":[],"sources":["../src/services/runnerDependencies/index.ts"],"mappings":";;;;;;;;;;;;;;iBA4CgB,yBACd,WAAW,QAAQ;EACjB,aAAa,SAAS;EACtB;EACA,kBAAkB;IAEnB"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_runnerConfig = require("./runnerConfig-D2tGq5ZM.cjs");
|
|
3
|
+
const require_headless = require("./headless-CHUsBGhg.cjs");
|
|
4
|
+
const require_rmuxBackend = require("./rmuxBackend-DlxgqRZ1.cjs");
|
|
5
|
+
const require_rtkProcessor = require("./rtkProcessor-Bc4L4o_8.cjs");
|
|
6
|
+
const require_runnerDependencies = require("./runnerDependencies-KMZigIxB.cjs");
|
|
7
|
+
exports.DEFAULT_BG_THRESHOLD_MS = require_runnerConfig.DEFAULT_BG_THRESHOLD_MS;
|
|
8
|
+
exports.DEFAULT_LOG_MAX_BYTES = require_runnerConfig.DEFAULT_LOG_MAX_BYTES;
|
|
9
|
+
exports.DEFAULT_LOG_TTL_MS = require_runnerConfig.DEFAULT_LOG_TTL_MS;
|
|
10
|
+
exports.DEFAULT_RESULT_MAX_BYTES = require_runnerConfig.DEFAULT_RESULT_MAX_BYTES;
|
|
11
|
+
exports.RmuxBackend = require_rmuxBackend.RmuxBackend;
|
|
12
|
+
exports.createHeadlessBashTool = require_headless.createHeadlessBashTool;
|
|
13
|
+
exports.createHeadlessRunnersCommand = require_headless.createHeadlessRunnersCommand;
|
|
14
|
+
exports.createRunnerDependencies = require_runnerDependencies.createRunnerDependencies;
|
|
15
|
+
exports.getBackgroundThresholdMs = require_runnerConfig.getBackgroundThresholdMs;
|
|
16
|
+
exports.getLogMaxBytes = require_runnerConfig.getLogMaxBytes;
|
|
17
|
+
exports.getLogTtlMs = require_runnerConfig.getLogTtlMs;
|
|
18
|
+
exports.getResultMaxBytes = require_runnerConfig.getResultMaxBytes;
|
|
19
|
+
exports.rtkPackageForTarget = require_rtkProcessor.rtkPackageForTarget;
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { n as RmuxLaunchRequest, t as IRmuxBackend } from "./rmuxBackend-CaEWooWn.mjs";
|
|
2
|
+
import { n as createHeadlessRunnersCommand, t as createHeadlessBashTool } from "./index-BwB_jTI9.mjs";
|
|
3
|
+
import { A as getLogTtlMs, C as getBackgroundThresholdMs, M as getResultMaxBytes, c as DEFAULT_LOG_TTL_MS, k as getLogMaxBytes, n as DEFAULT_BG_THRESHOLD_MS, s as DEFAULT_LOG_MAX_BYTES, u as DEFAULT_RESULT_MAX_BYTES } from "./runnerConfig-BjtulXBI.mjs";
|
|
4
|
+
import { t as RmuxBackend } from "./index-D9-IXax4.mjs";
|
|
5
|
+
import { r as rtkPackageForTarget } from "./index-BZL7keVW.mjs";
|
|
6
|
+
import { t as createRunnerDependencies } from "./index-Dhi8asLH.mjs";
|
|
7
|
+
export { DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, type IRmuxBackend, RmuxBackend, type RmuxLaunchRequest, createHeadlessBashTool, createHeadlessRunnersCommand, createRunnerDependencies, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes, rtkPackageForTarget };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { D as DEFAULT_RESULT_MAX_BYTES, T as DEFAULT_LOG_TTL_MS, c as getLogTtlMs, s as getLogMaxBytes, t as getBackgroundThresholdMs, u as getResultMaxBytes, w as DEFAULT_LOG_MAX_BYTES, y as DEFAULT_BG_THRESHOLD_MS } from "./runnerConfig-BQBlVAXn.mjs";
|
|
2
|
+
import { n as createHeadlessRunnersCommand, t as createHeadlessBashTool } from "./headless-BGYfIlNk.mjs";
|
|
3
|
+
import { t as RmuxBackend } from "./rmuxBackend-DfyQwJrc.mjs";
|
|
4
|
+
import { r as rtkPackageForTarget } from "./rtkProcessor-B9KPdyzr.mjs";
|
|
5
|
+
import { t as createRunnerDependencies } from "./runnerDependencies-DruByBGS.mjs";
|
|
6
|
+
export { DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, RmuxBackend, createHeadlessBashTool, createHeadlessRunnersCommand, createRunnerDependencies, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes, rtkPackageForTarget };
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { g as noninteractiveEnvironment, u as getResultMaxBytes } from "./runnerConfig-BQBlVAXn.mjs";
|
|
2
|
+
import { t as PI_SESSION_ID_ENV } from "./session-DE2Acesp.mjs";
|
|
3
|
+
import { NO_TERMINAL_INPUT_ENV, cleanupSupervisorFiles, readExitMetadata, supervisorCommand, supervisorPaths, writeCommandSpec } from "./services/runnerSupervisor/index.mjs";
|
|
4
|
+
import { LIFELINE_ENV } from "./services/lifeline/client.mjs";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
//#region src/constants/launcher.ts
|
|
7
|
+
const NON_INTERACTIVE_ENV = {
|
|
8
|
+
FORCE_COLOR: "1",
|
|
9
|
+
CI: "1"
|
|
10
|
+
};
|
|
11
|
+
const TERM_GRACE_MS = 2e3;
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/services/launcher/index.ts
|
|
14
|
+
/**
|
|
15
|
+
* Prompts belong on a screen, not in a log file, so `CI` stays set.
|
|
16
|
+
*
|
|
17
|
+
* Colour is kept: the log is replayed into the transcript, and the scrub keeps
|
|
18
|
+
* SGR while still removing the cursor moves that made raw output unreadable.
|
|
19
|
+
*/
|
|
20
|
+
/** In-memory output is a multiple of the result ceiling; the log holds the rest. */
|
|
21
|
+
var Launcher = class {
|
|
22
|
+
spawner;
|
|
23
|
+
processControl;
|
|
24
|
+
logFile;
|
|
25
|
+
clock;
|
|
26
|
+
paths;
|
|
27
|
+
lifeline;
|
|
28
|
+
environment;
|
|
29
|
+
settings;
|
|
30
|
+
constructor(spawner, processControl, logFile, clock, paths, lifeline, environment = process.env, settings) {
|
|
31
|
+
this.spawner = spawner;
|
|
32
|
+
this.processControl = processControl;
|
|
33
|
+
this.logFile = logFile;
|
|
34
|
+
this.clock = clock;
|
|
35
|
+
this.paths = paths;
|
|
36
|
+
this.lifeline = lifeline;
|
|
37
|
+
this.environment = environment;
|
|
38
|
+
this.settings = settings;
|
|
39
|
+
}
|
|
40
|
+
launch(request) {
|
|
41
|
+
const writer = this.logFile.open(request.id);
|
|
42
|
+
const memoryLimit = getResultMaxBytes(this.environment, this.settings) * 2;
|
|
43
|
+
let buffer = "";
|
|
44
|
+
let buffering = true;
|
|
45
|
+
let settled = false;
|
|
46
|
+
let resolveCompletion = () => void 0;
|
|
47
|
+
let rejectCompletion = () => void 0;
|
|
48
|
+
const completion = new Promise((resolve, reject) => {
|
|
49
|
+
resolveCompletion = resolve;
|
|
50
|
+
rejectCompletion = reject;
|
|
51
|
+
});
|
|
52
|
+
this.paths.ensureDirectories(request.sessionId);
|
|
53
|
+
const supervisor = supervisorPaths(this.paths.stateDirectory(request.sessionId), request.id);
|
|
54
|
+
const { [LIFELINE_ENV]: _inheritedLifeline, ...environment } = this.environment;
|
|
55
|
+
const env = {
|
|
56
|
+
...environment,
|
|
57
|
+
...NON_INTERACTIVE_ENV,
|
|
58
|
+
...noninteractiveEnvironment(environment),
|
|
59
|
+
...NO_TERMINAL_INPUT_ENV,
|
|
60
|
+
[PI_SESSION_ID_ENV]: request.sessionId,
|
|
61
|
+
[LIFELINE_ENV]: this.lifeline?.path()
|
|
62
|
+
};
|
|
63
|
+
cleanupSupervisorFiles(supervisor);
|
|
64
|
+
writeCommandSpec(supervisor.spec, {
|
|
65
|
+
command: request.command,
|
|
66
|
+
cwd: request.cwd,
|
|
67
|
+
env: defined(env)
|
|
68
|
+
});
|
|
69
|
+
fs.writeFileSync(supervisor.gate, "", { mode: 384 });
|
|
70
|
+
const child = this.spawner.spawn({
|
|
71
|
+
command: supervisorCommand(supervisor),
|
|
72
|
+
cwd: request.cwd,
|
|
73
|
+
env,
|
|
74
|
+
detached: true
|
|
75
|
+
});
|
|
76
|
+
const failLaunch = (error) => {
|
|
77
|
+
if (settled) return;
|
|
78
|
+
settled = true;
|
|
79
|
+
writer.close();
|
|
80
|
+
cleanupSupervisorFiles(supervisor);
|
|
81
|
+
try {
|
|
82
|
+
child.kill("SIGTERM");
|
|
83
|
+
} catch (killError) {
|
|
84
|
+
process.emitWarning(`Could not stop runner after log failure: ${String(killError)}`);
|
|
85
|
+
}
|
|
86
|
+
rejectCompletion(error instanceof Error ? error : new Error(String(error)));
|
|
87
|
+
};
|
|
88
|
+
child.onOutput((chunk) => {
|
|
89
|
+
if (settled) return;
|
|
90
|
+
try {
|
|
91
|
+
writer.append(chunk);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
failLaunch(error);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (!buffering) return;
|
|
97
|
+
buffer += chunk;
|
|
98
|
+
if (buffer.length > memoryLimit) buffer = buffer.slice(-memoryLimit);
|
|
99
|
+
});
|
|
100
|
+
child.onError(failLaunch);
|
|
101
|
+
child.onExit((result) => {
|
|
102
|
+
if (settled) return;
|
|
103
|
+
settled = true;
|
|
104
|
+
writer.close();
|
|
105
|
+
const outcome = readExitMetadata(supervisor.exit) ?? result;
|
|
106
|
+
cleanupSupervisorFiles(supervisor);
|
|
107
|
+
resolveCompletion(outcome);
|
|
108
|
+
});
|
|
109
|
+
child.unref();
|
|
110
|
+
const stop = async () => child.pid === void 0 ? false : this.stop(child.pid);
|
|
111
|
+
return {
|
|
112
|
+
id: request.id,
|
|
113
|
+
name: request.name,
|
|
114
|
+
pid: child.pid,
|
|
115
|
+
logPath: writer.path,
|
|
116
|
+
backend: "native",
|
|
117
|
+
output: () => buffer,
|
|
118
|
+
completion: () => completion,
|
|
119
|
+
detach: () => {
|
|
120
|
+
buffering = false;
|
|
121
|
+
buffer = "";
|
|
122
|
+
},
|
|
123
|
+
stop
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
async stop(pid) {
|
|
127
|
+
if (!this.processControl.isAlive(pid)) return false;
|
|
128
|
+
this.processControl.signalGroup(pid, "SIGTERM");
|
|
129
|
+
const deadline = this.clock.now() + TERM_GRACE_MS;
|
|
130
|
+
while (this.clock.now() < deadline) {
|
|
131
|
+
if (!this.processControl.isAlive(pid)) return true;
|
|
132
|
+
await this.sleep(100);
|
|
133
|
+
}
|
|
134
|
+
this.processControl.signalGroup(pid, "SIGKILL");
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
sleep(ms) {
|
|
138
|
+
return new Promise((resolve) => {
|
|
139
|
+
this.clock.after(ms, resolve);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
/** The spec is JSON, which has no way to carry an unset variable. */
|
|
144
|
+
function defined(env) {
|
|
145
|
+
return Object.fromEntries(Object.entries(env).filter((entry) => entry[1] !== void 0));
|
|
146
|
+
}
|
|
147
|
+
//#endregion
|
|
148
|
+
export { Launcher as t };
|
|
149
|
+
|
|
150
|
+
//# sourceMappingURL=launcher-BDm6-DiQ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launcher-BDm6-DiQ.mjs","names":[],"sources":["../src/constants/launcher.ts","../src/services/launcher/index.ts"],"sourcesContent":["export const NON_INTERACTIVE_ENV = { FORCE_COLOR: '1', CI: '1' };\nexport const TERM_GRACE_MS = 2_000;\nexport const LIVENESS_POLL_MS = 100;\nexport const MEMORY_BUFFER_FACTOR = 2;\nexport const GATE_MODE = 0o600;\n","import fs from 'node:fs';\n\nimport {\n GATE_MODE,\n LIVENESS_POLL_MS,\n MEMORY_BUFFER_FACTOR,\n NON_INTERACTIVE_ENV,\n TERM_GRACE_MS,\n} from '../../constants/launcher';\nimport { PI_SESSION_ID_ENV } from '../../constants/session';\nimport type { IClock } from '../../types/clock';\nimport type { ILauncher, LaunchRequest, RunHandle } from '../../types/launcher';\nimport type { ILifeline } from '../../types/lifeline';\nimport type { ILogFile } from '../../types/logFile';\nimport type { IProcessControl } from '../../types/processControl';\nimport type { RunnerSettings } from '../../types/runnerSettings';\nimport type { ExitResult, ISpawner } from '../../types/spawner';\nimport { LIFELINE_ENV } from '../lifeline/client';\nimport { getResultMaxBytes, noninteractiveEnvironment } from '../runnerConfig';\nimport type { IRunnerPaths } from '../runnerPaths/type';\nimport {\n cleanupSupervisorFiles,\n NO_TERMINAL_INPUT_ENV,\n readExitMetadata,\n supervisorCommand,\n supervisorPaths,\n writeCommandSpec,\n} from '../runnerSupervisor';\n\n/**\n * Prompts belong on a screen, not in a log file, so `CI` stays set.\n *\n * Colour is kept: the log is replayed into the transcript, and the scrub keeps\n * SGR while still removing the cursor moves that made raw output unreadable.\n */\n/** In-memory output is a multiple of the result ceiling; the log holds the rest. */\n\nexport class Launcher implements ILauncher {\n constructor(\n private readonly spawner: ISpawner,\n private readonly processControl: IProcessControl,\n private readonly logFile: ILogFile,\n private readonly clock: IClock,\n private readonly paths: IRunnerPaths,\n private readonly lifeline?: ILifeline,\n private readonly environment: Readonly<Record<string, string | undefined>> = process.env,\n private readonly settings?: RunnerSettings,\n ) {}\n\n launch(request: LaunchRequest): RunHandle {\n const writer = this.logFile.open(request.id);\n const memoryLimit = getResultMaxBytes(this.environment, this.settings) * MEMORY_BUFFER_FACTOR;\n\n let buffer = '';\n let buffering = true;\n let settled = false;\n let resolveCompletion: (result: ExitResult) => void = () => undefined;\n let rejectCompletion: (error: Error) => void = () => undefined;\n const completion = new Promise<ExitResult>((resolve, reject) => {\n resolveCompletion = resolve;\n rejectCompletion = reject;\n });\n\n this.paths.ensureDirectories(request.sessionId);\n const supervisor = supervisorPaths(this.paths.stateDirectory(request.sessionId), request.id);\n const { [LIFELINE_ENV]: _inheritedLifeline, ...environment } = this.environment;\n const env = {\n ...environment,\n ...NON_INTERACTIVE_ENV,\n ...noninteractiveEnvironment(environment),\n ...NO_TERMINAL_INPUT_ENV,\n [PI_SESSION_ID_ENV]: request.sessionId,\n [LIFELINE_ENV]: this.lifeline?.path(),\n };\n cleanupSupervisorFiles(supervisor);\n writeCommandSpec(supervisor.spec, { command: request.command, cwd: request.cwd, env: defined(env) });\n // Nothing has to be attached before this runner starts, so its gate opens at once.\n fs.writeFileSync(supervisor.gate, '', { mode: GATE_MODE });\n\n const child = this.spawner.spawn({\n // runnerHost supervises the command: it forwards signals and, if the owning\n // pi dies without running its shutdown handler, kills the group itself.\n command: supervisorCommand(supervisor),\n cwd: request.cwd,\n env,\n // Its own process group, so stopping a runner takes the whole tree with it.\n detached: true,\n });\n\n const failLaunch = (error: unknown): void => {\n if (settled) return;\n settled = true;\n writer.close();\n cleanupSupervisorFiles(supervisor);\n try {\n child.kill('SIGTERM');\n } catch (killError) {\n process.emitWarning(`Could not stop runner after log failure: ${String(killError)}`);\n }\n rejectCompletion(error instanceof Error ? error : new Error(String(error)));\n };\n child.onOutput((chunk) => {\n if (settled) return;\n try {\n writer.append(chunk);\n } catch (error) {\n failLaunch(error);\n return;\n }\n if (!buffering) return;\n buffer += chunk;\n if (buffer.length > memoryLimit) buffer = buffer.slice(-memoryLimit);\n });\n\n child.onError(failLaunch);\n\n child.onExit((result) => {\n if (settled) return;\n settled = true;\n writer.close();\n // The supervisor collapses a signalled command into an exit code, so its\n // own sidecar is the only place the original signal survives.\n const outcome = readExitMetadata(supervisor.exit) ?? result;\n cleanupSupervisorFiles(supervisor);\n resolveCompletion(outcome);\n });\n\n // The launcher must never hold the pi process open on a runner's behalf.\n child.unref();\n\n const stop = async (): Promise<boolean> => (child.pid === undefined ? false : this.stop(child.pid));\n\n return {\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,\n };\n }\n\n async stop(pid: number): Promise<boolean> {\n if (!this.processControl.isAlive(pid)) return false;\n\n this.processControl.signalGroup(pid, 'SIGTERM');\n const deadline = this.clock.now() + TERM_GRACE_MS;\n while (this.clock.now() < deadline) {\n if (!this.processControl.isAlive(pid)) return true;\n await this.sleep(LIVENESS_POLL_MS);\n }\n\n this.processControl.signalGroup(pid, 'SIGKILL');\n return true;\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n this.clock.after(ms, resolve);\n });\n }\n}\n\n/** The spec is JSON, which has no way to carry an unset variable. */\nfunction defined(env: Readonly<Record<string, string | undefined>>): Record<string, string> {\n return Object.fromEntries(Object.entries(env).filter((entry): entry is [string, string] => entry[1] !== undefined));\n}\n"],"mappings":"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"}
|