@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,257 @@
|
|
|
1
|
+
import { d as getResultMaxLines, f as getResultMaxTokens, r as getErrorMaxEntries, u as getResultMaxBytes } from "./runnerConfig-BQBlVAXn.mjs";
|
|
2
|
+
import { a as countLines, i as composeExcerpt, o as createErrorScanner, t as boundExcerpt, u as formatSize } from "./bashResult-bIVSzoj-.mjs";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { StringDecoder } from "node:string_decoder";
|
|
5
|
+
//#region src/constants/logReader.ts
|
|
6
|
+
const READ_CHUNK_BYTES = 65536;
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/services/logReader/index.ts
|
|
9
|
+
var LogReader = class {
|
|
10
|
+
read(logPath, query = {}) {
|
|
11
|
+
let handle;
|
|
12
|
+
try {
|
|
13
|
+
handle = fs.openSync(logPath, "r");
|
|
14
|
+
return {
|
|
15
|
+
...scanLog(handle, query),
|
|
16
|
+
fileSize: fs.fstatSync(handle).size,
|
|
17
|
+
path: logPath,
|
|
18
|
+
exists: true
|
|
19
|
+
};
|
|
20
|
+
} catch (error) {
|
|
21
|
+
if (error.code !== "ENOENT") throw error;
|
|
22
|
+
return {
|
|
23
|
+
text: "",
|
|
24
|
+
lineCount: 0,
|
|
25
|
+
totalLines: 0,
|
|
26
|
+
fileSize: 0,
|
|
27
|
+
completeBytes: 0,
|
|
28
|
+
path: logPath,
|
|
29
|
+
exists: false
|
|
30
|
+
};
|
|
31
|
+
} finally {
|
|
32
|
+
if (handle !== void 0) fs.closeSync(handle);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
function scanLog(handle, query) {
|
|
37
|
+
const limit = Math.max(0, Math.floor(query.lines ?? 200));
|
|
38
|
+
const needle = query.grep ? query.ignoreCase ? query.grep.toLowerCase() : query.grep : void 0;
|
|
39
|
+
const contextLines = Math.max(0, Math.floor(query.contextLines ?? 0));
|
|
40
|
+
const decoder = new StringDecoder("utf8");
|
|
41
|
+
const buffer = Buffer.alloc(READ_CHUNK_BYTES);
|
|
42
|
+
const before = [];
|
|
43
|
+
const output = [];
|
|
44
|
+
let pending = "";
|
|
45
|
+
let totalLines = 0;
|
|
46
|
+
let afterThrough = -1;
|
|
47
|
+
let lastEmitted = -1;
|
|
48
|
+
let lastByte;
|
|
49
|
+
let bytesSeen = 0;
|
|
50
|
+
let completeBytes = 0;
|
|
51
|
+
const retain = (line) => {
|
|
52
|
+
if (limit === 0) return;
|
|
53
|
+
output.push(line);
|
|
54
|
+
if (output.length > limit) output.shift();
|
|
55
|
+
};
|
|
56
|
+
const emit = (line) => {
|
|
57
|
+
if (line.index <= lastEmitted) return;
|
|
58
|
+
lastEmitted = line.index;
|
|
59
|
+
retain(line);
|
|
60
|
+
};
|
|
61
|
+
const consume = (text) => {
|
|
62
|
+
const line = {
|
|
63
|
+
index: totalLines,
|
|
64
|
+
text
|
|
65
|
+
};
|
|
66
|
+
totalLines += 1;
|
|
67
|
+
if (!needle) {
|
|
68
|
+
retain(line);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if ((query.ignoreCase ? text.toLowerCase() : text).includes(needle)) {
|
|
72
|
+
for (const previous of before) emit(previous);
|
|
73
|
+
emit(line);
|
|
74
|
+
afterThrough = Math.max(afterThrough, line.index + contextLines);
|
|
75
|
+
} else if (line.index <= afterThrough) emit(line);
|
|
76
|
+
before.push(line);
|
|
77
|
+
if (before.length > contextLines) before.shift();
|
|
78
|
+
};
|
|
79
|
+
for (;;) {
|
|
80
|
+
const bytesRead = fs.readSync(handle, buffer, 0, buffer.byteLength, null);
|
|
81
|
+
if (bytesRead === 0) break;
|
|
82
|
+
lastByte = buffer[bytesRead - 1];
|
|
83
|
+
const lastNewline = buffer.subarray(0, bytesRead).lastIndexOf(10);
|
|
84
|
+
if (lastNewline >= 0) completeBytes = bytesSeen + lastNewline + 1;
|
|
85
|
+
bytesSeen += bytesRead;
|
|
86
|
+
pending += decoder.write(buffer.subarray(0, bytesRead));
|
|
87
|
+
let newline = pending.indexOf("\n");
|
|
88
|
+
while (newline >= 0) {
|
|
89
|
+
consume(pending.slice(0, newline));
|
|
90
|
+
pending = pending.slice(newline + 1);
|
|
91
|
+
newline = pending.indexOf("\n");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
pending += decoder.end();
|
|
95
|
+
if (pending.length > 0) consume(pending);
|
|
96
|
+
const trailingNewline = lastByte === 10;
|
|
97
|
+
const scanned = {
|
|
98
|
+
text: `${output.map((line) => line.text).join("\n")}${!needle && trailingNewline && output.length > 0 ? "\n" : ""}`,
|
|
99
|
+
lineCount: output.length,
|
|
100
|
+
totalLines,
|
|
101
|
+
completeBytes
|
|
102
|
+
};
|
|
103
|
+
if (!needle) return scanned;
|
|
104
|
+
return {
|
|
105
|
+
...scanned,
|
|
106
|
+
lineNumbers: output.map((line) => line.index + 1)
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Grep with context, matching the `product-stack logs` semantics so the two
|
|
111
|
+
* surfaces behave the same. Overlapping and adjacent context windows merge.
|
|
112
|
+
*/
|
|
113
|
+
function filterLogText(text, query) {
|
|
114
|
+
if (!query.grep) return text;
|
|
115
|
+
const lines = text.split("\n");
|
|
116
|
+
const needle = query.ignoreCase ? query.grep.toLowerCase() : query.grep;
|
|
117
|
+
const contextLines = Math.max(0, query.contextLines ?? 0);
|
|
118
|
+
const ranges = [];
|
|
119
|
+
lines.forEach((line, index) => {
|
|
120
|
+
if (!(query.ignoreCase ? line.toLowerCase() : line).includes(needle)) return;
|
|
121
|
+
ranges.push({
|
|
122
|
+
start: Math.max(0, index - contextLines),
|
|
123
|
+
end: Math.min(lines.length - 1, index + contextLines)
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
if (ranges.length === 0) return "";
|
|
127
|
+
const merged = [];
|
|
128
|
+
for (const range of ranges) {
|
|
129
|
+
const previous = merged.at(-1);
|
|
130
|
+
if (previous && range.start <= previous.end + 1) previous.end = Math.max(previous.end, range.end);
|
|
131
|
+
else merged.push({ ...range });
|
|
132
|
+
}
|
|
133
|
+
return merged.flatMap((range) => lines.slice(range.start, range.end + 1)).join("\n");
|
|
134
|
+
}
|
|
135
|
+
/** Reads a bounded head and tail plus exact metadata after the writer has flushed. */
|
|
136
|
+
function summarizeLog(path, maxLines = getResultMaxLines(), maxBytes = getResultMaxBytes(), maxTokens = getResultMaxTokens(), settings) {
|
|
137
|
+
let handle;
|
|
138
|
+
try {
|
|
139
|
+
const size = fs.statSync(path).size;
|
|
140
|
+
handle = fs.openSync(path, "r");
|
|
141
|
+
const readBuffer = Buffer.alloc(READ_CHUNK_BYTES);
|
|
142
|
+
const endLimit = Math.max(1, maxBytes + 1);
|
|
143
|
+
let headBuffer = Buffer.alloc(0);
|
|
144
|
+
let tailBuffer = Buffer.alloc(0);
|
|
145
|
+
let newlineCount = 0;
|
|
146
|
+
let lastByte;
|
|
147
|
+
const decoder = new StringDecoder("utf8");
|
|
148
|
+
const scanned = createErrorScanner(getErrorMaxEntries(settings), settings);
|
|
149
|
+
let pending = "";
|
|
150
|
+
for (;;) {
|
|
151
|
+
const bytesRead = fs.readSync(handle, readBuffer, 0, readBuffer.byteLength, null);
|
|
152
|
+
if (bytesRead === 0) break;
|
|
153
|
+
const chunk = readBuffer.subarray(0, bytesRead);
|
|
154
|
+
for (const byte of chunk) if (byte === 10) newlineCount += 1;
|
|
155
|
+
lastByte = chunk.at(-1);
|
|
156
|
+
if (headBuffer.byteLength < endLimit) headBuffer = Buffer.concat([headBuffer, chunk.subarray(0, endLimit - headBuffer.byteLength)]);
|
|
157
|
+
tailBuffer = appendBufferTail(tailBuffer, chunk, endLimit);
|
|
158
|
+
pending += decoder.write(chunk);
|
|
159
|
+
let newline = pending.indexOf("\n");
|
|
160
|
+
while (newline >= 0) {
|
|
161
|
+
scanned.push(pending.slice(0, newline));
|
|
162
|
+
pending = pending.slice(newline + 1);
|
|
163
|
+
newline = pending.indexOf("\n");
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
pending += decoder.end();
|
|
167
|
+
if (pending.length > 0) scanned.push(pending);
|
|
168
|
+
const lines = newlineCount + (size > 0 && lastByte !== 10 ? 1 : 0);
|
|
169
|
+
const excerpt = size <= tailBuffer.byteLength ? boundExcerpt(utf8Tail(tailBuffer, tailBuffer.byteLength), maxLines, maxBytes, maxTokens, settings) : composeExcerpt(headBuffer.toString("utf8"), utf8Tail(tailBuffer, tailBuffer.byteLength), lines, maxLines, maxBytes, scanned.entries(), maxTokens, settings);
|
|
170
|
+
return {
|
|
171
|
+
tail: excerpt.text,
|
|
172
|
+
bytes: size,
|
|
173
|
+
lines,
|
|
174
|
+
tailLines: excerpt.lines
|
|
175
|
+
};
|
|
176
|
+
} catch {
|
|
177
|
+
return {
|
|
178
|
+
tail: "",
|
|
179
|
+
bytes: 0,
|
|
180
|
+
lines: 0,
|
|
181
|
+
tailLines: 0
|
|
182
|
+
};
|
|
183
|
+
} finally {
|
|
184
|
+
if (handle !== void 0) fs.closeSync(handle);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Keeps both ends of an oversized result and points at the file holding the rest.
|
|
189
|
+
*
|
|
190
|
+
* The notice states the file's real size and line count so the model does not
|
|
191
|
+
* guess at offsets when it goes on to read the file, which is the failure this
|
|
192
|
+
* whole policy exists to prevent.
|
|
193
|
+
*/
|
|
194
|
+
function truncateForResult(text, fullOutputPath, maxBytes = getResultMaxBytes(), maxLines = getResultMaxLines()) {
|
|
195
|
+
const excerpt = boundExcerpt(text, maxLines, maxBytes);
|
|
196
|
+
if (!excerpt.truncated) return {
|
|
197
|
+
text,
|
|
198
|
+
truncated: false,
|
|
199
|
+
outputLines: excerpt.lines
|
|
200
|
+
};
|
|
201
|
+
return {
|
|
202
|
+
text: `${excerpt.text}\n${truncationNotice(excerpt, fullOutputPath, text)}`,
|
|
203
|
+
truncated: true,
|
|
204
|
+
outputLines: excerpt.lines
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function truncationNotice(excerpt, fullOutputPath, text) {
|
|
208
|
+
const file = measureFile(fullOutputPath);
|
|
209
|
+
const totalLines = file?.lines ?? countLines(text);
|
|
210
|
+
const fileSize = file?.bytes ?? Buffer.byteLength(text, "utf8");
|
|
211
|
+
return [
|
|
212
|
+
`[output truncated: showing ${excerpt.lines.toLocaleString("en-US")} of ${totalLines.toLocaleString("en-US")} lines,`,
|
|
213
|
+
`${excerpt.elidedLines.toLocaleString("en-US")} elided from the middle.`,
|
|
214
|
+
`Full output is at ${fullOutputPath} (${formatSize(fileSize)}, ${totalLines.toLocaleString("en-US")} lines).`,
|
|
215
|
+
`Inspect it with doom-runner logs, or read the file with an offset near line ${totalLines.toLocaleString("en-US")}.]`
|
|
216
|
+
].join(" ");
|
|
217
|
+
}
|
|
218
|
+
/** Real size and line count of the file the notice points at. */
|
|
219
|
+
function measureFile(path) {
|
|
220
|
+
let handle;
|
|
221
|
+
try {
|
|
222
|
+
const bytes = fs.statSync(path).size;
|
|
223
|
+
handle = fs.openSync(path, "r");
|
|
224
|
+
const buffer = Buffer.alloc(READ_CHUNK_BYTES);
|
|
225
|
+
let newlineCount = 0;
|
|
226
|
+
let lastByte;
|
|
227
|
+
for (;;) {
|
|
228
|
+
const bytesRead = fs.readSync(handle, buffer, 0, buffer.byteLength, null);
|
|
229
|
+
if (bytesRead === 0) break;
|
|
230
|
+
const chunk = buffer.subarray(0, bytesRead);
|
|
231
|
+
for (const byte of chunk) if (byte === 10) newlineCount += 1;
|
|
232
|
+
lastByte = chunk.at(-1);
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
bytes,
|
|
236
|
+
lines: newlineCount + (bytes > 0 && lastByte !== 10 ? 1 : 0)
|
|
237
|
+
};
|
|
238
|
+
} catch {
|
|
239
|
+
return;
|
|
240
|
+
} finally {
|
|
241
|
+
if (handle !== void 0) fs.closeSync(handle);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function utf8Tail(encoded, maxBytes) {
|
|
245
|
+
let start = Math.max(0, encoded.byteLength - maxBytes);
|
|
246
|
+
while (start < encoded.byteLength && (encoded[start] & 192) === 128) start += 1;
|
|
247
|
+
return encoded.subarray(start).toString("utf8");
|
|
248
|
+
}
|
|
249
|
+
function appendBufferTail(current, chunk, limit) {
|
|
250
|
+
if (chunk.byteLength >= limit) return Buffer.from(chunk.subarray(chunk.byteLength - limit));
|
|
251
|
+
const combined = Buffer.concat([current, chunk]);
|
|
252
|
+
return combined.byteLength > limit ? Buffer.from(combined.subarray(combined.byteLength - limit)) : combined;
|
|
253
|
+
}
|
|
254
|
+
//#endregion
|
|
255
|
+
export { truncateForResult as i, filterLogText as n, summarizeLog as r, LogReader as t };
|
|
256
|
+
|
|
257
|
+
//# sourceMappingURL=logReader-UfbDbwQl.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logReader-UfbDbwQl.mjs","names":[],"sources":["../src/constants/logReader.ts","../src/services/logReader/index.ts"],"sourcesContent":["export const DEFAULT_LINES = 200;\nexport const READ_CHUNK_BYTES = 65_536;\n","import fs from 'node:fs';\nimport { StringDecoder } from 'node:string_decoder';\n\nimport { DEFAULT_LINES, READ_CHUNK_BYTES } from '../../constants/logReader';\nimport { type Excerpt, type LogSummary, type TruncatedOutput } from '../../types/bashResult';\nimport type { ILogReader, LogQuery, LogSlice } from '../../types/logReader';\nimport type { RunnerSettings } from '../../types/runnerSettings';\nimport { boundExcerpt, composeExcerpt, countLines, createErrorScanner, formatSize } from '../bashResult';\nimport { getErrorMaxEntries, getResultMaxBytes, getResultMaxLines, getResultMaxTokens } from '../runnerConfig';\n\ninterface IndexedLine {\n readonly index: number;\n readonly text: string;\n}\n\ninterface ScannedLog {\n readonly text: string;\n readonly lineCount: number;\n readonly totalLines: number;\n readonly completeBytes: number;\n readonly lineNumbers?: number[];\n}\n\nexport class LogReader implements ILogReader {\n read(logPath: string, query: LogQuery = {}): LogSlice {\n let handle: number | undefined;\n try {\n handle = fs.openSync(logPath, 'r');\n const scanned = scanLog(handle, query);\n return {\n ...scanned,\n fileSize: fs.fstatSync(handle).size,\n path: logPath,\n exists: true,\n };\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n return {\n text: '',\n lineCount: 0,\n totalLines: 0,\n fileSize: 0,\n completeBytes: 0,\n path: logPath,\n exists: false,\n };\n } finally {\n if (handle !== undefined) fs.closeSync(handle);\n }\n }\n}\n\nfunction scanLog(handle: number, query: LogQuery): ScannedLog {\n const limit = Math.max(0, Math.floor(query.lines ?? DEFAULT_LINES));\n const needle = query.grep ? (query.ignoreCase ? query.grep.toLowerCase() : query.grep) : undefined;\n const contextLines = Math.max(0, Math.floor(query.contextLines ?? 0));\n const decoder = new StringDecoder('utf8');\n const buffer = Buffer.alloc(READ_CHUNK_BYTES);\n const before: IndexedLine[] = [];\n const output: IndexedLine[] = [];\n let pending = '';\n let totalLines = 0;\n let afterThrough = -1;\n let lastEmitted = -1;\n let lastByte: number | undefined;\n let bytesSeen = 0;\n let completeBytes = 0;\n\n const retain = (line: IndexedLine): void => {\n if (limit === 0) return;\n output.push(line);\n if (output.length > limit) output.shift();\n };\n const emit = (line: IndexedLine): void => {\n if (line.index <= lastEmitted) return;\n lastEmitted = line.index;\n retain(line);\n };\n const consume = (text: string): void => {\n const line = { index: totalLines, text };\n totalLines += 1;\n if (!needle) {\n retain(line);\n return;\n }\n\n const haystack = query.ignoreCase ? text.toLowerCase() : text;\n if (haystack.includes(needle)) {\n for (const previous of before) emit(previous);\n emit(line);\n afterThrough = Math.max(afterThrough, line.index + contextLines);\n } else if (line.index <= afterThrough) {\n emit(line);\n }\n before.push(line);\n if (before.length > contextLines) before.shift();\n };\n\n for (;;) {\n const bytesRead = fs.readSync(handle, buffer, 0, buffer.byteLength, null);\n if (bytesRead === 0) break;\n lastByte = buffer[bytesRead - 1];\n // A newline is a single byte in UTF-8 and never a continuation byte, so the\n // last one in this chunk ends the last complete line seen so far.\n const lastNewline = buffer.subarray(0, bytesRead).lastIndexOf(0x0a);\n if (lastNewline >= 0) completeBytes = bytesSeen + lastNewline + 1;\n bytesSeen += bytesRead;\n pending += decoder.write(buffer.subarray(0, bytesRead));\n let newline = pending.indexOf('\\n');\n while (newline >= 0) {\n consume(pending.slice(0, newline));\n pending = pending.slice(newline + 1);\n newline = pending.indexOf('\\n');\n }\n }\n pending += decoder.end();\n if (pending.length > 0) consume(pending);\n\n const trailingNewline = lastByte === 0x0a;\n const body = output.map((line) => line.text).join('\\n');\n const text = `${body}${!needle && trailingNewline && output.length > 0 ? '\\n' : ''}`;\n const scanned: ScannedLog = { text, lineCount: output.length, totalLines, completeBytes };\n if (!needle) return scanned;\n return { ...scanned, lineNumbers: output.map((line) => line.index + 1) };\n}\n\n/**\n * Grep with context, matching the `product-stack logs` semantics so the two\n * surfaces behave the same. Overlapping and adjacent context windows merge.\n */\nexport function filterLogText(text: string, query: Pick<LogQuery, 'grep' | 'ignoreCase' | 'contextLines'>): string {\n if (!query.grep) return text;\n const lines = text.split('\\n');\n const needle = query.ignoreCase ? query.grep.toLowerCase() : query.grep;\n const contextLines = Math.max(0, query.contextLines ?? 0);\n const ranges: Array<{ start: number; end: number }> = [];\n\n lines.forEach((line, index) => {\n const haystack = query.ignoreCase ? line.toLowerCase() : line;\n if (!haystack.includes(needle)) return;\n ranges.push({\n start: Math.max(0, index - contextLines),\n end: Math.min(lines.length - 1, index + contextLines),\n });\n });\n\n if (ranges.length === 0) return '';\n const merged: Array<{ start: number; end: number }> = [];\n for (const range of ranges) {\n const previous = merged.at(-1);\n if (previous && range.start <= previous.end + 1) {\n previous.end = Math.max(previous.end, range.end);\n } else {\n merged.push({ ...range });\n }\n }\n return merged.flatMap((range) => lines.slice(range.start, range.end + 1)).join('\\n');\n}\n\n/** Reads a bounded head and tail plus exact metadata after the writer has flushed. */\nexport function summarizeLog(\n path: string,\n maxLines = getResultMaxLines(),\n maxBytes = getResultMaxBytes(),\n maxTokens = getResultMaxTokens(),\n settings?: RunnerSettings,\n): LogSummary {\n let handle: number | undefined;\n try {\n const size = fs.statSync(path).size;\n handle = fs.openSync(path, 'r');\n const readBuffer = Buffer.alloc(READ_CHUNK_BYTES);\n // Both ends are captured at the full budget; the line trim decides the split.\n const endLimit = Math.max(1, maxBytes + 1);\n let headBuffer: Buffer<ArrayBufferLike> = Buffer.alloc(0);\n let tailBuffer: Buffer<ArrayBufferLike> = Buffer.alloc(0);\n let newlineCount = 0;\n let lastByte: number | undefined;\n const decoder = new StringDecoder('utf8');\n const scanned = createErrorScanner(getErrorMaxEntries(settings), settings);\n let pending = '';\n for (;;) {\n const bytesRead = fs.readSync(handle, readBuffer, 0, readBuffer.byteLength, null);\n if (bytesRead === 0) break;\n const chunk = readBuffer.subarray(0, bytesRead);\n for (const byte of chunk) if (byte === 0x0a) newlineCount += 1;\n lastByte = chunk.at(-1);\n if (headBuffer.byteLength < endLimit) {\n headBuffer = Buffer.concat([headBuffer, chunk.subarray(0, endLimit - headBuffer.byteLength)]);\n }\n tailBuffer = appendBufferTail(tailBuffer, chunk, endLimit);\n pending += decoder.write(chunk);\n let newline = pending.indexOf('\\n');\n while (newline >= 0) {\n scanned.push(pending.slice(0, newline));\n pending = pending.slice(newline + 1);\n newline = pending.indexOf('\\n');\n }\n }\n pending += decoder.end();\n if (pending.length > 0) scanned.push(pending);\n const lines = newlineCount + (size > 0 && lastByte !== 0x0a ? 1 : 0);\n // The tail capture holds the whole file only while the file fits inside one\n // buffer. Past that the start is already gone from it, so the two ends have\n // to be composed instead.\n const excerpt =\n size <= tailBuffer.byteLength\n ? boundExcerpt(utf8Tail(tailBuffer, tailBuffer.byteLength), maxLines, maxBytes, maxTokens, settings)\n : composeExcerpt(\n headBuffer.toString('utf8'),\n utf8Tail(tailBuffer, tailBuffer.byteLength),\n lines,\n maxLines,\n maxBytes,\n scanned.entries(),\n maxTokens,\n settings,\n );\n return { tail: excerpt.text, bytes: size, lines, tailLines: excerpt.lines };\n } catch {\n return { tail: '', bytes: 0, lines: 0, tailLines: 0 };\n } finally {\n if (handle !== undefined) fs.closeSync(handle);\n }\n}\n\n/**\n * Keeps both ends of an oversized result and points at the file holding the rest.\n *\n * The notice states the file's real size and line count so the model does not\n * guess at offsets when it goes on to read the file, which is the failure this\n * whole policy exists to prevent.\n */\nexport function truncateForResult(\n text: string,\n fullOutputPath: string,\n maxBytes = getResultMaxBytes(),\n maxLines = getResultMaxLines(),\n): TruncatedOutput {\n const excerpt = boundExcerpt(text, maxLines, maxBytes);\n if (!excerpt.truncated) return { text, truncated: false, outputLines: excerpt.lines };\n\n return {\n text: `${excerpt.text}\\n${truncationNotice(excerpt, fullOutputPath, text)}`,\n truncated: true,\n outputLines: excerpt.lines,\n };\n}\n\nfunction truncationNotice(excerpt: Excerpt, fullOutputPath: string, text: string): string {\n // Counted from the file, never from `text`. What the caller holds in memory\n // is itself capped, so using it here would understate the file by orders of\n // magnitude and send the reader looking past the end of a much longer file.\n const file = measureFile(fullOutputPath);\n const totalLines = file?.lines ?? countLines(text);\n const fileSize = file?.bytes ?? Buffer.byteLength(text, 'utf8');\n\n return [\n `[output truncated: showing ${excerpt.lines.toLocaleString('en-US')} of ${totalLines.toLocaleString('en-US')} lines,`,\n `${excerpt.elidedLines.toLocaleString('en-US')} elided from the middle.`,\n `Full output is at ${fullOutputPath} (${formatSize(fileSize)}, ${totalLines.toLocaleString('en-US')} lines).`,\n `Inspect it with doom-runner logs, or read the file with an offset near line ${totalLines.toLocaleString('en-US')}.]`,\n ].join(' ');\n}\n\n/** Real size and line count of the file the notice points at. */\nfunction measureFile(path: string): { bytes: number; lines: number } | undefined {\n let handle: number | undefined;\n try {\n const bytes = fs.statSync(path).size;\n handle = fs.openSync(path, 'r');\n const buffer = Buffer.alloc(READ_CHUNK_BYTES);\n let newlineCount = 0;\n let lastByte: number | undefined;\n for (;;) {\n const bytesRead = fs.readSync(handle, buffer, 0, buffer.byteLength, null);\n if (bytesRead === 0) break;\n const chunk = buffer.subarray(0, bytesRead);\n for (const byte of chunk) if (byte === 0x0a) newlineCount += 1;\n lastByte = chunk.at(-1);\n }\n return { bytes, lines: newlineCount + (bytes > 0 && lastByte !== 0x0a ? 1 : 0) };\n } catch {\n return undefined;\n } finally {\n if (handle !== undefined) fs.closeSync(handle);\n }\n}\n\nfunction utf8Tail(encoded: Buffer<ArrayBufferLike>, maxBytes: number): string {\n let start = Math.max(0, encoded.byteLength - maxBytes);\n while (start < encoded.byteLength && (encoded[start]! & 0xc0) === 0x80) start += 1;\n return encoded.subarray(start).toString('utf8');\n}\n\nfunction appendBufferTail(\n current: Buffer<ArrayBufferLike>,\n chunk: Buffer<ArrayBufferLike>,\n limit: number,\n): Buffer<ArrayBufferLike> {\n if (chunk.byteLength >= limit) return Buffer.from(chunk.subarray(chunk.byteLength - limit));\n const combined = Buffer.concat([current, chunk]);\n return combined.byteLength > limit ? Buffer.from(combined.subarray(combined.byteLength - limit)) : combined;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/types/processControl.d.ts
|
|
2
|
+
/** Liveness and signalling for processes this extension did not spawn itself. */
|
|
3
|
+
interface IProcessControl {
|
|
4
|
+
/** True when a process with this pid is still running. */
|
|
5
|
+
isAlive(pid: number): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Signals the whole process group led by `pid`.
|
|
8
|
+
* Returns false when the group is already gone.
|
|
9
|
+
*/
|
|
10
|
+
signalGroup(pid: number, signal: NodeJS.Signals): boolean;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { IProcessControl as t };
|
|
14
|
+
//# sourceMappingURL=processControl-BAOa3oo_.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processControl-BAOa3oo_.d.mts","names":[],"sources":["../src/types/processControl.ts"],"mappings":";;UACiB;;EAEf,QAAQ;;;;;EAKR,YAAY,aAAa,QAAQ,OAAO"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/services/processControl/index.ts
|
|
2
|
+
/** Wraps `process.kill`, which doubles as the liveness probe on POSIX. */
|
|
3
|
+
var NodeProcessControl = class {
|
|
4
|
+
isAlive(pid) {
|
|
5
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
6
|
+
try {
|
|
7
|
+
process.kill(pid, 0);
|
|
8
|
+
return true;
|
|
9
|
+
} catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
signalGroup(pid, signal) {
|
|
14
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
15
|
+
try {
|
|
16
|
+
process.kill(-pid, signal);
|
|
17
|
+
return true;
|
|
18
|
+
} catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
//#endregion
|
|
24
|
+
export { NodeProcessControl as t };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=processControl-DApTpV16.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processControl-DApTpV16.mjs","names":[],"sources":["../src/services/processControl/index.ts"],"sourcesContent":["import { LIVENESS_PROBE } from '../../constants/processControl';\nimport type { IProcessControl } from '../../types/processControl';\n\n/** Wraps `process.kill`, which doubles as the liveness probe on POSIX. */\nexport class NodeProcessControl implements IProcessControl {\n isAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, LIVENESS_PROBE);\n return true;\n } catch {\n // EPERM would also land here, but a process we cannot signal is not one\n // this extension can manage, so treating it as gone is the safe answer.\n return false;\n }\n }\n\n signalGroup(pid: number, signal: NodeJS.Signals): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(-pid, signal);\n return true;\n } catch {\n return false;\n }\n }\n}\n"],"mappings":";;AAIA,IAAa,qBAAb,MAA2D;CACzD,QAAQ,KAAsB;EAC5B,IAAI,CAAC,OAAO,UAAU,GAAG,KAAK,OAAO,GAAG,OAAO;EAC/C,IAAI;GACF,QAAQ,KAAK,KAAA,CAAmB;GAChC,OAAO;EACT,QAAQ;GAGN,OAAO;EACT;CACF;CAEA,YAAY,KAAa,QAAiC;EACxD,IAAI,CAAC,OAAO,UAAU,GAAG,KAAK,OAAO,GAAG,OAAO;EAC/C,IAAI;GACF,QAAQ,KAAK,CAAC,KAAK,MAAM;GACzB,OAAO;EACT,QAAQ;GACN,OAAO;EACT;CACF;AACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/services/processControl/index.ts
|
|
2
|
+
/** Wraps `process.kill`, which doubles as the liveness probe on POSIX. */
|
|
3
|
+
var NodeProcessControl = class {
|
|
4
|
+
isAlive(pid) {
|
|
5
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
6
|
+
try {
|
|
7
|
+
process.kill(pid, 0);
|
|
8
|
+
return true;
|
|
9
|
+
} catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
signalGroup(pid, signal) {
|
|
14
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
15
|
+
try {
|
|
16
|
+
process.kill(-pid, signal);
|
|
17
|
+
return true;
|
|
18
|
+
} catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
//#endregion
|
|
24
|
+
Object.defineProperty(exports, "NodeProcessControl", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function() {
|
|
27
|
+
return NodeProcessControl;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=processControl-DNJ1WZ9N.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processControl-DNJ1WZ9N.cjs","names":[],"sources":["../src/services/processControl/index.ts"],"sourcesContent":["import { LIVENESS_PROBE } from '../../constants/processControl';\nimport type { IProcessControl } from '../../types/processControl';\n\n/** Wraps `process.kill`, which doubles as the liveness probe on POSIX. */\nexport class NodeProcessControl implements IProcessControl {\n isAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, LIVENESS_PROBE);\n return true;\n } catch {\n // EPERM would also land here, but a process we cannot signal is not one\n // this extension can manage, so treating it as gone is the safe answer.\n return false;\n }\n }\n\n signalGroup(pid: number, signal: NodeJS.Signals): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(-pid, signal);\n return true;\n } catch {\n return false;\n }\n }\n}\n"],"mappings":";;AAIA,IAAa,qBAAb,MAA2D;CACzD,QAAQ,KAAsB;EAC5B,IAAI,CAAC,OAAO,UAAU,GAAG,KAAK,OAAO,GAAG,OAAO;EAC/C,IAAI;GACF,QAAQ,KAAK,KAAA,CAAmB;GAChC,OAAO;EACT,QAAQ;GAGN,OAAO;EACT;CACF;CAEA,YAAY,KAAa,QAAiC;EACxD,IAAI,CAAC,OAAO,UAAU,GAAG,KAAK,OAAO,GAAG,OAAO;EAC/C,IAAI;GACF,QAAQ,KAAK,CAAC,KAAK,MAAM;GACzB,OAAO;EACT,QAAQ;GACN,OAAO;EACT;CACF;AACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { t as IProcessControl } from "./processControl-BAOa3oo_.mjs";
|
|
2
|
+
//#region src/services/processControl/index.d.ts
|
|
3
|
+
/** Wraps `process.kill`, which doubles as the liveness probe on POSIX. */
|
|
4
|
+
export declare class NodeProcessControl implements IProcessControl {
|
|
5
|
+
isAlive(pid: number): boolean;
|
|
6
|
+
signalGroup(pid: number, signal: NodeJS.Signals): boolean;
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export type { IProcessControl };
|
|
10
|
+
//# sourceMappingURL=processControl.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processControl.d.mts","names":[],"sources":["../src/services/processControl/index.ts"],"mappings":";;;qBAIa,8BAA8B;EACzC,QAAQ;EAYR,YAAY,aAAa,QAAQ,OAAO"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { r as RunHandle } from "./launcher-BG5t9nvG.mjs";
|
|
2
|
+
//#region src/types/ptyHost.d.ts
|
|
3
|
+
/** A background run hosted on a pseudo terminal, so it can be typed at. */
|
|
4
|
+
interface PtyRun extends RunHandle {
|
|
5
|
+
/** Sends text to the terminal. A newline is appended by the caller. */
|
|
6
|
+
write(text: string): void;
|
|
7
|
+
/** The visible screen, as plain text, for the overlay. */
|
|
8
|
+
screen(): string;
|
|
9
|
+
/** Subscribes to raw terminal output. Returns an unsubscribe function. */
|
|
10
|
+
onData(handler: (data: string) => void): () => void;
|
|
11
|
+
resize(cols: number, rows: number): void;
|
|
12
|
+
}
|
|
13
|
+
interface PtyLaunchRequest {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
command: string;
|
|
17
|
+
cwd: string;
|
|
18
|
+
sessionId: string;
|
|
19
|
+
cols?: number;
|
|
20
|
+
rows?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Owns every pseudo terminal this session started.
|
|
24
|
+
*
|
|
25
|
+
* A PTY cannot outlive its host process, so unlike detached subprocesses these
|
|
26
|
+
* runs are only reachable from the session that launched them.
|
|
27
|
+
*/
|
|
28
|
+
interface IPtyHost {
|
|
29
|
+
launch(request: PtyLaunchRequest): Promise<PtyRun>;
|
|
30
|
+
get(name: string): PtyRun | undefined;
|
|
31
|
+
/** Writes a line to a runner. False when this session does not host it. */
|
|
32
|
+
write(name: string, text: string): boolean;
|
|
33
|
+
list(): PtyRun[];
|
|
34
|
+
disposeAll(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { PtyLaunchRequest as n, PtyRun as r, IPtyHost as t };
|
|
38
|
+
//# sourceMappingURL=ptyHost-DWWtRrGn.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ptyHost-DWWtRrGn.d.mts","names":[],"sources":["../src/types/ptyHost.ts"],"mappings":";;;UAGiB,eAAe;;EAE9B,MAAM;;EAEN;;EAEA,OAAO,UAAU;EACjB,OAAO,cAAc;;UAGN;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;;;UASe;EACf,OAAO,SAAS,mBAAmB,QAAQ;EAC3C,IAAI,eAAe;;EAEnB,MAAM,cAAc;EACpB,QAAQ;EACR,cAAc"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { n as scrubTerminalOutput } from "./ansiScrub-CsqTSaVT.mjs";
|
|
2
|
+
import { u as getResultMaxBytes } from "./runnerConfig-BQBlVAXn.mjs";
|
|
3
|
+
import { t as PI_SESSION_ID_ENV } from "./session-DE2Acesp.mjs";
|
|
4
|
+
import { NO_TERMINAL_INPUT_ENV } from "./services/runnerSupervisor/index.mjs";
|
|
5
|
+
import headless from "@xterm/headless";
|
|
6
|
+
//#region src/constants/ptyHost.ts
|
|
7
|
+
const SCROLLBACK = 2e3;
|
|
8
|
+
const TERM_GRACE_MS = 2e3;
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/services/ptyHost/index.ts
|
|
11
|
+
/** Enough history for the overlay to scroll without holding a whole build. */
|
|
12
|
+
const { Terminal: HeadlessTerminal } = headless;
|
|
13
|
+
var PtyHost = class {
|
|
14
|
+
spawner;
|
|
15
|
+
logFile;
|
|
16
|
+
processControl;
|
|
17
|
+
clock;
|
|
18
|
+
environment;
|
|
19
|
+
settings;
|
|
20
|
+
runs = /* @__PURE__ */ new Map();
|
|
21
|
+
constructor(spawner, logFile, processControl, clock, environment = process.env, settings) {
|
|
22
|
+
this.spawner = spawner;
|
|
23
|
+
this.logFile = logFile;
|
|
24
|
+
this.processControl = processControl;
|
|
25
|
+
this.clock = clock;
|
|
26
|
+
this.environment = environment;
|
|
27
|
+
this.settings = settings;
|
|
28
|
+
}
|
|
29
|
+
async launch(request) {
|
|
30
|
+
const cols = request.cols ?? 120;
|
|
31
|
+
const rows = request.rows ?? 30;
|
|
32
|
+
const writer = this.logFile.open(request.id);
|
|
33
|
+
const terminal = new HeadlessTerminal({
|
|
34
|
+
cols,
|
|
35
|
+
rows,
|
|
36
|
+
scrollback: SCROLLBACK,
|
|
37
|
+
allowProposedApi: true
|
|
38
|
+
});
|
|
39
|
+
const memoryLimit = getResultMaxBytes(this.environment, this.settings) * 2;
|
|
40
|
+
const child = await this.spawner.spawn({
|
|
41
|
+
command: request.command,
|
|
42
|
+
cwd: request.cwd,
|
|
43
|
+
env: {
|
|
44
|
+
...this.environment,
|
|
45
|
+
...NO_TERMINAL_INPUT_ENV,
|
|
46
|
+
[PI_SESSION_ID_ENV]: request.sessionId
|
|
47
|
+
},
|
|
48
|
+
cols,
|
|
49
|
+
rows
|
|
50
|
+
});
|
|
51
|
+
let buffer = "";
|
|
52
|
+
let buffering = true;
|
|
53
|
+
let settled = false;
|
|
54
|
+
let resolveCompletion = () => void 0;
|
|
55
|
+
const completion = new Promise((resolve) => {
|
|
56
|
+
resolveCompletion = resolve;
|
|
57
|
+
});
|
|
58
|
+
const dataHandlers = /* @__PURE__ */ new Set();
|
|
59
|
+
child.onData((data) => {
|
|
60
|
+
terminal.write(data);
|
|
61
|
+
const scrubbed = scrubTerminalOutput(data);
|
|
62
|
+
writer.append(scrubbed);
|
|
63
|
+
if (buffering) {
|
|
64
|
+
buffer += scrubbed;
|
|
65
|
+
if (buffer.length > memoryLimit) buffer = buffer.slice(-memoryLimit);
|
|
66
|
+
}
|
|
67
|
+
for (const handler of dataHandlers) handler(data);
|
|
68
|
+
});
|
|
69
|
+
child.onExit((result) => {
|
|
70
|
+
if (settled) return;
|
|
71
|
+
settled = true;
|
|
72
|
+
this.runs.delete(request.name);
|
|
73
|
+
writer.close();
|
|
74
|
+
resolveCompletion({
|
|
75
|
+
code: result.exitCode,
|
|
76
|
+
signal: null
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
const run = {
|
|
80
|
+
id: request.id,
|
|
81
|
+
name: request.name,
|
|
82
|
+
pid: child.pid,
|
|
83
|
+
logPath: writer.path,
|
|
84
|
+
backend: "native",
|
|
85
|
+
output: () => buffer,
|
|
86
|
+
completion: () => completion,
|
|
87
|
+
detach: () => {
|
|
88
|
+
buffering = false;
|
|
89
|
+
buffer = "";
|
|
90
|
+
},
|
|
91
|
+
stop: () => this.stopChild(child, request.name),
|
|
92
|
+
write: (text) => child.write(text),
|
|
93
|
+
screen: () => renderScreen(terminal),
|
|
94
|
+
onData: (handler) => {
|
|
95
|
+
dataHandlers.add(handler);
|
|
96
|
+
return () => dataHandlers.delete(handler);
|
|
97
|
+
},
|
|
98
|
+
resize: (nextCols, nextRows) => {
|
|
99
|
+
child.resize(nextCols, nextRows);
|
|
100
|
+
terminal.resize(nextCols, nextRows);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
this.runs.set(request.name, run);
|
|
104
|
+
return run;
|
|
105
|
+
}
|
|
106
|
+
get(name) {
|
|
107
|
+
return this.runs.get(name);
|
|
108
|
+
}
|
|
109
|
+
write(name, text) {
|
|
110
|
+
const run = this.runs.get(name);
|
|
111
|
+
if (!run) return false;
|
|
112
|
+
run.write(text.endsWith("\n") ? text : `${text}
|
|
113
|
+
`);
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
list() {
|
|
117
|
+
return [...this.runs.values()];
|
|
118
|
+
}
|
|
119
|
+
async disposeAll() {
|
|
120
|
+
const runs = [...this.runs.values()];
|
|
121
|
+
this.runs.clear();
|
|
122
|
+
for (const run of runs) await run.stop();
|
|
123
|
+
}
|
|
124
|
+
async stopChild(child, name) {
|
|
125
|
+
this.runs.delete(name);
|
|
126
|
+
if (!this.processControl.isAlive(child.pid)) return false;
|
|
127
|
+
child.kill("SIGTERM");
|
|
128
|
+
const deadline = this.clock.now() + TERM_GRACE_MS;
|
|
129
|
+
while (this.clock.now() < deadline) {
|
|
130
|
+
if (!this.processControl.isAlive(child.pid)) return true;
|
|
131
|
+
await new Promise((resolve) => {
|
|
132
|
+
this.clock.after(100, resolve);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
child.kill("SIGKILL");
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
/** The visible rows, trimmed of trailing blanks, as plain text. */
|
|
140
|
+
function renderScreen(terminal) {
|
|
141
|
+
const buffer = terminal.buffer.active;
|
|
142
|
+
const lines = [];
|
|
143
|
+
for (let row = buffer.baseY; row < buffer.baseY + terminal.rows; row += 1) lines.push(buffer.getLine(row)?.translateToString(true) ?? "");
|
|
144
|
+
while (lines.length > 0 && lines.at(-1) === "") lines.pop();
|
|
145
|
+
return lines.join("\n");
|
|
146
|
+
}
|
|
147
|
+
//#endregion
|
|
148
|
+
export { PtyHost as t };
|
|
149
|
+
|
|
150
|
+
//# sourceMappingURL=ptyHost-DlQtTB8F.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ptyHost-DlQtTB8F.mjs","names":[],"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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"}
|