@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,629 @@
|
|
|
1
|
+
const require_ansiScrub = require("./ansiScrub-D5gpHDch.cjs");
|
|
2
|
+
const require_runnerConfig = require("./runnerConfig-D2tGq5ZM.cjs");
|
|
3
|
+
//#region src/constants/bashResult.ts
|
|
4
|
+
const BYTES_PER_KB = 1024;
|
|
5
|
+
const BYTES_PER_MB = 1048576;
|
|
6
|
+
const PRAGMA_PATTERN = /^\s*(?:#|\/\/)\s*@doom:\s*(\{.*\})\s*$/u;
|
|
7
|
+
const PRAGMA_BYTES_CEILING = 262144;
|
|
8
|
+
const PRAGMA_LINES_CEILING = 5e3;
|
|
9
|
+
const PRAGMA_TOKENS_CEILING = 1e5;
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/constants/tokenEstimate.ts
|
|
12
|
+
const MIXED_CHARS_PER_TOKEN = 2.1;
|
|
13
|
+
const ALPHANUMERIC_RUN = /([^\p{L}\p{N}]+)/u;
|
|
14
|
+
const HAS_ALPHANUMERIC = /[\p{L}\p{N}]/u;
|
|
15
|
+
const HAS_DIGIT = /\d/u;
|
|
16
|
+
const HAS_LETTER = /[A-Za-z]/u;
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/services/tokenEstimate/index.ts
|
|
19
|
+
/**
|
|
20
|
+
* Estimates BPE tokens without carrying a vocabulary.
|
|
21
|
+
*
|
|
22
|
+
* Bytes are a poor proxy for what a result costs: measured against
|
|
23
|
+
* `gpt-tokenizer`, real text ranges from 1.4 characters per token for base64 to
|
|
24
|
+
* 4.7 for English prose, a spread of more than three. Truncation runs on every
|
|
25
|
+
* command and is synchronous, so loading a real tokenizer here would charge
|
|
26
|
+
* every session for a table most of them never need.
|
|
27
|
+
*
|
|
28
|
+
* The shape below follows how BPE actually behaves: punctuation forces token
|
|
29
|
+
* boundaries, natural words are cheap, and runs mixing letters with digits are
|
|
30
|
+
* expensive. Calibrated against `gpt-tokenizer` over build logs, source, JSON,
|
|
31
|
+
* stack traces, CJK, base64, hex, and UUIDs, the worst error is a factor of
|
|
32
|
+
* 1.46 either way. It stays an estimate, so the byte ceiling remains the hard
|
|
33
|
+
* bound behind it.
|
|
34
|
+
*/
|
|
35
|
+
/** Characters per token for a natural word. */
|
|
36
|
+
/** Characters per token for a run mixing letters and digits, which tokenizes poorly. */
|
|
37
|
+
/** Characters per token for a run of punctuation or whitespace. */
|
|
38
|
+
/** Dense scripts such as CJK cost about one token per character. */
|
|
39
|
+
function estimateTokens(text) {
|
|
40
|
+
let tokens = 0;
|
|
41
|
+
for (const run of text.split(ALPHANUMERIC_RUN)) {
|
|
42
|
+
if (run.length === 0) continue;
|
|
43
|
+
if (!HAS_ALPHANUMERIC.test(run)) {
|
|
44
|
+
tokens += run.length / 2;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
let ascii = 0;
|
|
48
|
+
let dense = 0;
|
|
49
|
+
let astral = 0;
|
|
50
|
+
for (const character of run) {
|
|
51
|
+
const code = character.codePointAt(0) ?? 0;
|
|
52
|
+
if (code > 65535) astral += 1;
|
|
53
|
+
else if (code > 12287) dense += 1;
|
|
54
|
+
else ascii += 1;
|
|
55
|
+
}
|
|
56
|
+
tokens += astral * 2 + dense;
|
|
57
|
+
if (ascii > 0) {
|
|
58
|
+
const mixed = HAS_DIGIT.test(run) && HAS_LETTER.test(run);
|
|
59
|
+
tokens += Math.max(1, ascii / (mixed ? MIXED_CHARS_PER_TOKEN : 5));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return Math.ceil(tokens);
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/services/bashResult/index.ts
|
|
66
|
+
/** Variants retained per group while scanning; the rest only add to the count. */
|
|
67
|
+
/** Below this much shared text, joining reads worse than separate lines. */
|
|
68
|
+
/**
|
|
69
|
+
* Severity anywhere in the opening of the line, not only at its start. Real
|
|
70
|
+
* tooling buries it behind a tag or a timestamp: `[widget] build: error TS2322`.
|
|
71
|
+
*/
|
|
72
|
+
const SEVERITY_TOKEN = /(?<![\w\-/=.])(?:errors?|fatal|panic|exception|traceback|assertion|assert|fail(?:ed|ure|ures)?)\b/iu;
|
|
73
|
+
/** `0 errors` and `no failures` are the success case wearing the same words. */
|
|
74
|
+
const NEGATED_SEVERITY = /\b(?:no|not|without|zero|0)\s+$/iu;
|
|
75
|
+
function textResult(text, details = {}) {
|
|
76
|
+
return {
|
|
77
|
+
content: [{
|
|
78
|
+
type: "text",
|
|
79
|
+
text
|
|
80
|
+
}],
|
|
81
|
+
details
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function errorResult(message) {
|
|
85
|
+
return textResult(`Error: ${message}`, { error: message });
|
|
86
|
+
}
|
|
87
|
+
/** Human-readable byte count, matching how pi reports output sizes. */
|
|
88
|
+
function formatSize(bytes) {
|
|
89
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
90
|
+
if (bytes < 1048576) return `${(bytes / BYTES_PER_KB).toFixed(1)} KB`;
|
|
91
|
+
return `${(bytes / BYTES_PER_MB).toFixed(1)} MB`;
|
|
92
|
+
}
|
|
93
|
+
function formatCount(value) {
|
|
94
|
+
return value.toLocaleString("en-US");
|
|
95
|
+
}
|
|
96
|
+
function countLines(text) {
|
|
97
|
+
if (text.length === 0) return 0;
|
|
98
|
+
return text.endsWith("\n") ? text.split("\n").length - 1 : text.split("\n").length;
|
|
99
|
+
}
|
|
100
|
+
/** Accumulates grouped error lines while a log streams past, without holding it. */
|
|
101
|
+
var ErrorScan = class {
|
|
102
|
+
maxEntries;
|
|
103
|
+
settings;
|
|
104
|
+
byKey = /* @__PURE__ */ new Map();
|
|
105
|
+
constructor(maxEntries = require_runnerConfig.getErrorMaxEntries(), settings) {
|
|
106
|
+
this.maxEntries = maxEntries;
|
|
107
|
+
this.settings = settings;
|
|
108
|
+
}
|
|
109
|
+
push(line) {
|
|
110
|
+
if (!isErrorLine(line, this.settings)) return;
|
|
111
|
+
const trimmed = line.trim();
|
|
112
|
+
const key = normalizeErrorLine(line);
|
|
113
|
+
const existing = this.byKey.get(key);
|
|
114
|
+
if (existing) {
|
|
115
|
+
existing.count += 1;
|
|
116
|
+
if (!existing.variants.includes(trimmed) && existing.variants.length < 12) existing.variants.push(trimmed);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (this.byKey.size >= this.maxEntries) return;
|
|
120
|
+
this.byKey.set(key, {
|
|
121
|
+
variants: [trimmed],
|
|
122
|
+
count: 1
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
entries() {
|
|
126
|
+
return [...this.byKey.values()];
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
function createErrorScanner(maxEntries = require_runnerConfig.getErrorMaxEntries(), settings) {
|
|
130
|
+
return new ErrorScan(maxEntries, settings);
|
|
131
|
+
}
|
|
132
|
+
/** Codex-style first-line pragma, for the one command that needs a wider result. */
|
|
133
|
+
function positiveInteger(value) {
|
|
134
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : void 0;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Reads `# @doom: {"maxResultBytes": 32768}` from the command's first line.
|
|
138
|
+
*
|
|
139
|
+
* The pragma is a shell comment, so it stays harmless if this parse is ever
|
|
140
|
+
* skipped, and it survives verbatim into the log where a wider result can be
|
|
141
|
+
* explained after the fact.
|
|
142
|
+
*/
|
|
143
|
+
function parseResultPragma(command) {
|
|
144
|
+
const match = PRAGMA_PATTERN.exec(command.split("\n", 1)[0] ?? "");
|
|
145
|
+
if (!match?.[1]) return {};
|
|
146
|
+
let parsed;
|
|
147
|
+
try {
|
|
148
|
+
parsed = JSON.parse(match[1]);
|
|
149
|
+
} catch {
|
|
150
|
+
return {};
|
|
151
|
+
}
|
|
152
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
|
|
153
|
+
const source = parsed;
|
|
154
|
+
const maxBytes = positiveInteger(source.maxResultBytes);
|
|
155
|
+
const maxLines = positiveInteger(source.maxResultLines);
|
|
156
|
+
const maxTokens = positiveInteger(source.maxResultTokens);
|
|
157
|
+
return {
|
|
158
|
+
...maxBytes === void 0 ? {} : { maxBytes: Math.min(maxBytes, PRAGMA_BYTES_CEILING) },
|
|
159
|
+
...maxLines === void 0 ? {} : { maxLines: Math.min(maxLines, PRAGMA_LINES_CEILING) },
|
|
160
|
+
...maxTokens === void 0 ? {} : { maxTokens: Math.min(maxTokens, PRAGMA_TOKENS_CEILING) }
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function isErrorLine(line, settings) {
|
|
164
|
+
const opening = line.slice(0, 60);
|
|
165
|
+
const match = SEVERITY_TOKEN.exec(opening);
|
|
166
|
+
if (match && !NEGATED_SEVERITY.test(opening.slice(0, match.index))) return true;
|
|
167
|
+
return require_runnerConfig.getErrorPatterns(settings).some((pattern) => matchesCustomPattern(pattern, line));
|
|
168
|
+
}
|
|
169
|
+
const customPatterns = /* @__PURE__ */ new Map();
|
|
170
|
+
function matchesCustomPattern(pattern, line) {
|
|
171
|
+
if (!customPatterns.has(pattern)) try {
|
|
172
|
+
customPatterns.set(pattern, new RegExp(pattern, "iu"));
|
|
173
|
+
} catch {
|
|
174
|
+
customPatterns.set(pattern, void 0);
|
|
175
|
+
}
|
|
176
|
+
return customPatterns.get(pattern)?.test(line) ?? false;
|
|
177
|
+
}
|
|
178
|
+
/** Masks the parts that differ between repeats of the same underlying failure. */
|
|
179
|
+
function normalizeErrorLine(line) {
|
|
180
|
+
return line.replace(/0x[0-9a-f]+/giu, "0x#").replace(/\/[^\s:,)]+/gu, "/#").replace(/\d+/gu, "#").trim().toLowerCase();
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Collapses repeats so one failure repeated two hundred times costs one slot.
|
|
184
|
+
* Counting continues past the entry cap so the tallies stay honest.
|
|
185
|
+
*/
|
|
186
|
+
function collectErrorLines(lines, maxEntries = require_runnerConfig.getErrorMaxEntries(), settings) {
|
|
187
|
+
const scan = new ErrorScan(maxEntries, settings);
|
|
188
|
+
for (const line of lines) scan.push(line);
|
|
189
|
+
return scan.entries();
|
|
190
|
+
}
|
|
191
|
+
function commonAffixLengths(values) {
|
|
192
|
+
const shortest = values.reduce((min, value) => Math.min(min, value.length), Infinity);
|
|
193
|
+
let prefix = 0;
|
|
194
|
+
while (prefix < shortest && values.every((value) => value[prefix] === values[0][prefix])) prefix += 1;
|
|
195
|
+
let suffix = 0;
|
|
196
|
+
while (suffix < shortest - prefix && values.every((value) => value[value.length - 1 - suffix] === values[0][values[0].length - 1 - suffix])) suffix += 1;
|
|
197
|
+
return {
|
|
198
|
+
prefix,
|
|
199
|
+
suffix
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/** Back off to a whitespace boundary so the brackets hold whole tokens. */
|
|
203
|
+
function retreatToBoundary(value, length) {
|
|
204
|
+
const boundary = value.lastIndexOf(" ", Math.max(0, length - 1));
|
|
205
|
+
return boundary >= 0 ? boundary + 1 : 0;
|
|
206
|
+
}
|
|
207
|
+
function advanceToBoundary(value, length) {
|
|
208
|
+
const cut = value.length - length;
|
|
209
|
+
const boundary = value.indexOf(" ", cut);
|
|
210
|
+
return boundary >= 0 ? value.length - boundary : 0;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* One line per distinct failure would be ideal, but repeats of one failure
|
|
214
|
+
* across many files are the common case. Sharing the fixed text and joining
|
|
215
|
+
* only the parts that differ keeps every file name without paying for the
|
|
216
|
+
* message N times.
|
|
217
|
+
*/
|
|
218
|
+
function renderGroup(group, settings) {
|
|
219
|
+
const [first] = group.variants;
|
|
220
|
+
if (first === void 0) return "";
|
|
221
|
+
if (group.variants.length === 1) return group.count > 1 ? `${first} (\u00d7${formatCount(group.count)})` : first;
|
|
222
|
+
const shown = group.variants.slice(0, require_runnerConfig.getErrorMaxVariantsJoined(settings));
|
|
223
|
+
const { prefix, suffix } = commonAffixLengths(shown);
|
|
224
|
+
const head = first.slice(0, retreatToBoundary(first, prefix));
|
|
225
|
+
const tailLength = advanceToBoundary(first, suffix);
|
|
226
|
+
const tail = tailLength > 0 ? first.slice(first.length - tailLength) : "";
|
|
227
|
+
if (head.length + tail.length < 8) return shown.join("\n");
|
|
228
|
+
const middles = shown.map((value) => value.slice(head.length, value.length - tail.length));
|
|
229
|
+
const overflow = group.variants.length - shown.length;
|
|
230
|
+
return `${head}[${overflow > 0 ? `${middles.join("|")}|+${formatCount(overflow)}` : middles.join("|")}]${tail}`;
|
|
231
|
+
}
|
|
232
|
+
function renderSalvaged(errors, maxBytes, settings) {
|
|
233
|
+
const rendered = [];
|
|
234
|
+
let used = 0;
|
|
235
|
+
for (const group of errors) {
|
|
236
|
+
const text = renderGroup(group, settings);
|
|
237
|
+
if (text.length === 0) continue;
|
|
238
|
+
const cost = Buffer.byteLength(text, "utf8") + 1;
|
|
239
|
+
if (used + cost > maxBytes) break;
|
|
240
|
+
rendered.push(text);
|
|
241
|
+
used += cost;
|
|
242
|
+
}
|
|
243
|
+
return rendered;
|
|
244
|
+
}
|
|
245
|
+
function elisionMarker(elidedLines, salvagedCount = 0) {
|
|
246
|
+
const unit = elidedLines === 1 ? "line" : "lines";
|
|
247
|
+
const errors = salvagedCount > 0 ? `, ${formatCount(salvagedCount)} shown below` : "";
|
|
248
|
+
return `\u2026 [${formatCount(elidedLines)} ${unit} elided${errors}] \u2026`;
|
|
249
|
+
}
|
|
250
|
+
function splitTextLines(text) {
|
|
251
|
+
const trailingNewline = text.endsWith("\n");
|
|
252
|
+
const lines = text.split("\n");
|
|
253
|
+
if (trailingNewline) lines.pop();
|
|
254
|
+
return {
|
|
255
|
+
lines,
|
|
256
|
+
trailingNewline
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
/** Whole lines only: a fragment of a line reads as data that was never there. */
|
|
260
|
+
function takeSide(lines, maxCount, maxBytes, fromEnd, maxTokens = Number.POSITIVE_INFINITY) {
|
|
261
|
+
if (maxBytes <= 0 || maxCount <= 0) return {
|
|
262
|
+
text: "",
|
|
263
|
+
count: 0
|
|
264
|
+
};
|
|
265
|
+
const ordered = fromEnd ? [...lines].reverse() : [...lines];
|
|
266
|
+
const taken = [];
|
|
267
|
+
let used = 0;
|
|
268
|
+
let tokens = 0;
|
|
269
|
+
for (const line of ordered) {
|
|
270
|
+
if (taken.length >= maxCount) break;
|
|
271
|
+
const cost = Buffer.byteLength(line, "utf8") + (taken.length > 0 ? 1 : 0);
|
|
272
|
+
const lineTokens = estimateTokens(line) + (taken.length > 0 ? 1 : 0);
|
|
273
|
+
if (used + cost > maxBytes || tokens + lineTokens > maxTokens) break;
|
|
274
|
+
taken.push(line);
|
|
275
|
+
used += cost;
|
|
276
|
+
tokens += lineTokens;
|
|
277
|
+
}
|
|
278
|
+
if (taken.length === 0) return {
|
|
279
|
+
text: "",
|
|
280
|
+
count: 0
|
|
281
|
+
};
|
|
282
|
+
const restored = fromEnd ? taken.reverse() : taken;
|
|
283
|
+
return {
|
|
284
|
+
text: restored.join("\n"),
|
|
285
|
+
count: restored.length
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Used only when no whole line fits either side, which means the source has no
|
|
290
|
+
* usable line boundary. A clamped fragment beats returning nothing at all.
|
|
291
|
+
*/
|
|
292
|
+
function clampedFragment(text, limitBytes) {
|
|
293
|
+
const clamped = utf8Tail(Buffer.from(text, "utf8"), limitBytes);
|
|
294
|
+
const newline = clamped.indexOf("\n");
|
|
295
|
+
const whole = newline >= 0 ? clamped.slice(newline + 1) : clamped;
|
|
296
|
+
return {
|
|
297
|
+
text: whole,
|
|
298
|
+
count: whole.length > 0 ? 1 : 0
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
/** Charged against the budget so the composed excerpt still honours the ceiling. */
|
|
302
|
+
function markerReservation(totalLines) {
|
|
303
|
+
return Buffer.byteLength(elisionMarker(totalLines), "utf8") + 2;
|
|
304
|
+
}
|
|
305
|
+
function assembleSides(head, tail, elidedLines, trailingNewline, limitBytes, salvaged = []) {
|
|
306
|
+
const opening = elidedLines > 0 ? [elisionMarker(elidedLines, salvaged.length)] : [];
|
|
307
|
+
const closing = elidedLines > 0 && salvaged.length > 0 ? ["…"] : [];
|
|
308
|
+
const body = [
|
|
309
|
+
head.text,
|
|
310
|
+
...opening,
|
|
311
|
+
...salvaged,
|
|
312
|
+
...closing,
|
|
313
|
+
tail.text
|
|
314
|
+
].filter((part) => part.length > 0).join("\n");
|
|
315
|
+
const withNewline = trailingNewline && body.length > 0 ? `${body}\n` : body;
|
|
316
|
+
const encoded = Buffer.from(withNewline, "utf8");
|
|
317
|
+
return {
|
|
318
|
+
text: encoded.byteLength > limitBytes ? utf8Tail(encoded, limitBytes) : withNewline,
|
|
319
|
+
lines: head.count + tail.count,
|
|
320
|
+
truncated: true,
|
|
321
|
+
elidedLines: Math.max(0, elidedLines)
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
function budgetFor(maxLines, maxBytes, totalLines, maxTokens, settings) {
|
|
325
|
+
const limitLines = Math.max(1, Math.floor(maxLines));
|
|
326
|
+
const usable = Math.max(0, maxBytes - markerReservation(totalLines));
|
|
327
|
+
const tokens = Math.max(1, Math.floor(maxTokens) - estimateTokens(elisionMarker(totalLines)));
|
|
328
|
+
return {
|
|
329
|
+
limitLines,
|
|
330
|
+
headLines: Math.max(1, Math.floor(limitLines * require_runnerConfig.getHeadRatio(settings))),
|
|
331
|
+
headBytes: Math.max(0, Math.floor(usable * require_runnerConfig.getHeadRatio(settings))),
|
|
332
|
+
headTokens: Math.max(1, Math.floor(tokens * require_runnerConfig.getHeadRatio(settings))),
|
|
333
|
+
usable,
|
|
334
|
+
tokens
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Bounds text to the budget, keeping a leading excerpt as well as the tail.
|
|
339
|
+
*
|
|
340
|
+
* Failures announce themselves at both ends: a command that could not start
|
|
341
|
+
* says so on line one, and a command that died says so on the last. Keeping
|
|
342
|
+
* only the tail loses the first kind entirely.
|
|
343
|
+
*/
|
|
344
|
+
function boundExcerpt(text, maxLines = require_runnerConfig.getResultMaxLines(), maxBytes = require_runnerConfig.getResultMaxBytes(), maxTokens = require_runnerConfig.getResultMaxTokens(), settings) {
|
|
345
|
+
if (text.length === 0) return {
|
|
346
|
+
text: "",
|
|
347
|
+
lines: 0,
|
|
348
|
+
truncated: false,
|
|
349
|
+
elidedLines: 0
|
|
350
|
+
};
|
|
351
|
+
const { lines, trailingNewline } = splitTextLines(text);
|
|
352
|
+
const totalBytes = Buffer.byteLength(text, "utf8");
|
|
353
|
+
const limitBytes = Number.isFinite(maxBytes) ? Math.max(0, Math.floor(maxBytes)) : totalBytes;
|
|
354
|
+
const limitLines = Math.max(1, Math.floor(maxLines));
|
|
355
|
+
if (lines.length <= limitLines && totalBytes <= limitBytes && estimateTokens(text) <= maxTokens) return {
|
|
356
|
+
text,
|
|
357
|
+
lines: lines.length,
|
|
358
|
+
truncated: false,
|
|
359
|
+
elidedLines: 0
|
|
360
|
+
};
|
|
361
|
+
const budget = budgetFor(maxLines, limitBytes, lines.length, maxTokens, settings);
|
|
362
|
+
const head = takeSide(lines, budget.headLines, budget.headBytes, false, budget.headTokens);
|
|
363
|
+
const rest = lines.slice(head.count);
|
|
364
|
+
const errorBytes = rest.some((line) => isErrorLine(line, settings)) ? Math.floor(budget.usable * require_runnerConfig.getErrorBudgetRatio(settings)) : 0;
|
|
365
|
+
const tailBytes = budget.usable - Buffer.byteLength(head.text, "utf8") - errorBytes;
|
|
366
|
+
const tailTokens = budget.tokens - estimateTokens(head.text);
|
|
367
|
+
const tail = takeSide(rest, Math.max(1, budget.limitLines - head.count), tailBytes, true, tailTokens);
|
|
368
|
+
if (head.count === 0 && tail.count === 0) {
|
|
369
|
+
const fragment = clampedFragment(text, limitBytes);
|
|
370
|
+
return {
|
|
371
|
+
text: fragment.text,
|
|
372
|
+
lines: fragment.count,
|
|
373
|
+
truncated: true,
|
|
374
|
+
elidedLines: lines.length - fragment.count
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
const middle = lines.slice(head.count, lines.length - tail.count);
|
|
378
|
+
const salvaged = errorBytes > 0 ? renderSalvaged(collectErrorLines(middle, require_runnerConfig.getErrorMaxEntries(settings), settings), errorBytes, settings) : [];
|
|
379
|
+
return assembleSides(head, tail, lines.length - head.count - tail.count, trailingNewline, limitBytes, salvaged);
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Same budget as `boundExcerpt`, for callers that streamed the two ends
|
|
383
|
+
* separately and never held the middle. `totalLines` counts the whole source,
|
|
384
|
+
* so the marker states what was dropped rather than what was captured.
|
|
385
|
+
*/
|
|
386
|
+
function composeExcerpt(headSource, tailSource, totalLines, maxLines = require_runnerConfig.getResultMaxLines(), maxBytes = require_runnerConfig.getResultMaxBytes(), errors = [], maxTokens = require_runnerConfig.getResultMaxTokens(), settings) {
|
|
387
|
+
const limitBytes = Number.isFinite(maxBytes) ? Math.max(0, Math.floor(maxBytes)) : Number.MAX_SAFE_INTEGER;
|
|
388
|
+
const budget = budgetFor(maxLines, limitBytes, totalLines, maxTokens, settings);
|
|
389
|
+
const headLines = splitTextLines(headSource).lines;
|
|
390
|
+
const { lines: tailLines, trailingNewline } = splitTextLines(tailSource);
|
|
391
|
+
const head = takeSide(headLines.slice(0, Math.max(0, headLines.length - 1)), budget.headLines, budget.headBytes, false, budget.headTokens);
|
|
392
|
+
const errorBytes = errors.length > 0 ? Math.floor(budget.usable * require_runnerConfig.getErrorBudgetRatio(settings)) : 0;
|
|
393
|
+
const tailBytes = budget.usable - Buffer.byteLength(head.text, "utf8") - errorBytes;
|
|
394
|
+
const tailTokens = budget.tokens - estimateTokens(head.text);
|
|
395
|
+
const tail = takeSide(tailLines.slice(1), Math.max(1, budget.limitLines - head.count), tailBytes, true, tailTokens);
|
|
396
|
+
if (head.count === 0 && tail.count === 0) {
|
|
397
|
+
const fragment = clampedFragment(tailSource, limitBytes);
|
|
398
|
+
return {
|
|
399
|
+
text: fragment.text,
|
|
400
|
+
lines: fragment.count,
|
|
401
|
+
truncated: true,
|
|
402
|
+
elidedLines: Math.max(0, totalLines - fragment.count)
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
const salvaged = errorBytes > 0 ? renderSalvaged(errors, errorBytes, settings) : [];
|
|
406
|
+
return assembleSides(head, tail, Math.max(0, totalLines - head.count - tail.count), trailingNewline, limitBytes, salvaged);
|
|
407
|
+
}
|
|
408
|
+
/** Applies Doom's line and byte ceilings to text already held in memory. */
|
|
409
|
+
function summarizeText(text, maxLines = require_runnerConfig.getResultMaxLines(), maxBytes = require_runnerConfig.getResultMaxBytes()) {
|
|
410
|
+
const excerpt = boundExcerpt(text, maxLines, maxBytes);
|
|
411
|
+
return {
|
|
412
|
+
tail: excerpt.text,
|
|
413
|
+
tailLines: excerpt.lines
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
/** Bounds the complete model-facing result after status and recovery text are attached. */
|
|
417
|
+
function boundResultText(text, maxBytes = require_runnerConfig.getResultMaxBytes(), settings, maxTokens = require_runnerConfig.getResultMaxTokens()) {
|
|
418
|
+
return boundExcerpt(text, require_runnerConfig.getResultMaxLines(settings), maxBytes, maxTokens, settings).text;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Keeps both ends of an oversized result and points at the file holding the rest.
|
|
422
|
+
*
|
|
423
|
+
* The notice states the file's real size and line count so the model does not
|
|
424
|
+
* guess at offsets when it goes on to read the file, which is the failure this
|
|
425
|
+
* whole policy exists to prevent.
|
|
426
|
+
*/
|
|
427
|
+
function utf8Tail(encoded, maxBytes) {
|
|
428
|
+
let start = Math.max(0, encoded.byteLength - maxBytes);
|
|
429
|
+
while (start < encoded.byteLength && (encoded[start] & 192) === 128) start += 1;
|
|
430
|
+
return encoded.subarray(start).toString("utf8");
|
|
431
|
+
}
|
|
432
|
+
/** `name pid 1234 up 3m sleep 60` — one runner per line. */
|
|
433
|
+
function formatRunnerLine(record, now = Date.now()) {
|
|
434
|
+
const mode = record.interactive ? " interactive" : "";
|
|
435
|
+
return `${record.name} pid ${record.pid} up ${formatUptime(record.startedAt, now)}${mode} ${record.command}`;
|
|
436
|
+
}
|
|
437
|
+
function formatUptime(startedAt, now) {
|
|
438
|
+
const started = Date.parse(startedAt);
|
|
439
|
+
if (Number.isNaN(started)) return "unknown";
|
|
440
|
+
const seconds = Math.max(0, Math.floor((now - started) / 1e3));
|
|
441
|
+
if (seconds < 60) return `${seconds}s`;
|
|
442
|
+
const minutes = Math.floor(seconds / 60);
|
|
443
|
+
if (minutes < 60) return `${minutes}m`;
|
|
444
|
+
const hours = Math.floor(minutes / 60);
|
|
445
|
+
return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;
|
|
446
|
+
}
|
|
447
|
+
const PROMOTION_REASONS = {
|
|
448
|
+
requested: "Started in the background",
|
|
449
|
+
threshold: "Still running after the background threshold",
|
|
450
|
+
interactive: "Started interactively"
|
|
451
|
+
};
|
|
452
|
+
function completionFailed(result) {
|
|
453
|
+
return result.timedOut === true || result.signal !== null || result.exitCode !== null && result.exitCode !== 0;
|
|
454
|
+
}
|
|
455
|
+
function completionStatus(result) {
|
|
456
|
+
if (result.timedOut === true) return "Timed out: exceeded the requested timeout.";
|
|
457
|
+
if (result.signal !== null) return `Signal: ${result.signal}`;
|
|
458
|
+
if (result.exitCode === null) return "Exit status unavailable.";
|
|
459
|
+
if (result.exitCode !== 0) return `Exit: ${result.exitCode}`;
|
|
460
|
+
}
|
|
461
|
+
const emptyLogSummary = () => ({
|
|
462
|
+
tail: "",
|
|
463
|
+
bytes: 0,
|
|
464
|
+
lines: 0,
|
|
465
|
+
tailLines: 0
|
|
466
|
+
});
|
|
467
|
+
function formatRunResult(result, budget = {}, summarizeLog = emptyLogSummary, settings, environment = process.env) {
|
|
468
|
+
if (result.kind === "failed") throw new Error([`Could not start runner "${result.name}": ${result.error}`, "Next: correct the reported launch or supervision problem. Retry only after changing the command or environment."].join("\n"));
|
|
469
|
+
if (result.kind === "promoted") return textResult([
|
|
470
|
+
`${PROMOTION_REASONS[result.reason]}: runner "${result.name}" (${result.id}).`,
|
|
471
|
+
`Streaming log: ${result.logPath}`,
|
|
472
|
+
`Inspect: doom-runner logs ${result.id}`
|
|
473
|
+
].join("\n"), {
|
|
474
|
+
id: result.id,
|
|
475
|
+
runner: result.name,
|
|
476
|
+
pid: result.pid,
|
|
477
|
+
logPath: result.logPath,
|
|
478
|
+
promoted: true,
|
|
479
|
+
reason: result.reason
|
|
480
|
+
});
|
|
481
|
+
const succeeded = !completionFailed(result);
|
|
482
|
+
const maxLines = budget.maxLines ?? require_runnerConfig.getResultMaxLines(settings);
|
|
483
|
+
const maxBytes = budget.maxBytes ?? (succeeded ? require_runnerConfig.getSuccessResultMaxBytes(environment, settings) : require_runnerConfig.getResultMaxBytes(environment, settings));
|
|
484
|
+
const maxTokens = budget.maxTokens ?? (succeeded ? require_runnerConfig.getSuccessResultMaxTokens(environment, settings) : require_runnerConfig.getResultMaxTokens(environment, settings));
|
|
485
|
+
const log = summarizeLog(result.logPath, maxLines, maxBytes, maxTokens);
|
|
486
|
+
const useCapturedOutput = !result.rtkOutput && log.tail.length === 0 && result.output.length > 0;
|
|
487
|
+
let tail;
|
|
488
|
+
let tailLines;
|
|
489
|
+
let outputLines;
|
|
490
|
+
let outputBytes;
|
|
491
|
+
let truncated;
|
|
492
|
+
if (result.rtkOutput) {
|
|
493
|
+
const bounded = Buffer.byteLength(result.rtkOutput.output, "utf8") < result.rtkOutput.bytes ? composeExcerpt(result.rtkOutput.head, result.rtkOutput.output, result.rtkOutput.lines, maxLines, maxBytes, [], maxTokens, settings) : boundExcerpt(result.rtkOutput.output, maxLines, maxBytes, maxTokens, settings);
|
|
494
|
+
tail = bounded.text;
|
|
495
|
+
tailLines = bounded.lines;
|
|
496
|
+
outputLines = result.rtkOutput.lines;
|
|
497
|
+
outputBytes = result.rtkOutput.bytes;
|
|
498
|
+
truncated = outputLines > tailLines || outputBytes > Buffer.byteLength(tail, "utf8");
|
|
499
|
+
} else {
|
|
500
|
+
tail = useCapturedOutput ? result.output : log.tail;
|
|
501
|
+
tailLines = useCapturedOutput ? countLines(tail) : log.tailLines;
|
|
502
|
+
outputLines = Math.max(log.lines, tailLines);
|
|
503
|
+
outputBytes = useCapturedOutput ? Buffer.byteLength(tail, "utf8") : log.bytes;
|
|
504
|
+
truncated = !useCapturedOutput && (outputLines > tailLines || outputBytes > Buffer.byteLength(tail, "utf8"));
|
|
505
|
+
}
|
|
506
|
+
const plainTail = require_ansiScrub.stripAnsi(tail).replace(/\r?\n$/u, "");
|
|
507
|
+
const failed = completionFailed(result);
|
|
508
|
+
const status = completionStatus(result);
|
|
509
|
+
const textLines = [];
|
|
510
|
+
if (plainTail.length === 0) textLines.push(status === void 0 ? "Completed with no output." : "No output.");
|
|
511
|
+
else if (truncated) {
|
|
512
|
+
const label = result.rtkOutput ? `RTK ${result.rtkOutput.filter} excerpt` : "Log excerpt";
|
|
513
|
+
textLines.push(`${label} (${tailLines.toLocaleString("en-US")} of ${outputLines.toLocaleString("en-US")} lines):\n${plainTail}`);
|
|
514
|
+
} else textLines.push(plainTail);
|
|
515
|
+
if (status !== void 0) textLines.push(status);
|
|
516
|
+
if (result.rtkWarning) textLines.push(result.rtkWarning);
|
|
517
|
+
if (truncated) {
|
|
518
|
+
const label = result.rtkOutput ? "Complete raw log" : "Full log";
|
|
519
|
+
textLines.push(`${label}: ${result.logPath} (${formatSize(log.bytes)}, ${log.lines.toLocaleString("en-US")} lines); inspect with doom-runner logs ${result.id}`);
|
|
520
|
+
} else if (failed && plainTail.length === 0) textLines.push(`Log: ${result.logPath}`, "Next: run one read-only diagnostic; retry only after correcting the cause.");
|
|
521
|
+
const text = boundResultText(textLines.join("\n"), maxBytes, settings, settings === void 0 ? void 0 : maxTokens);
|
|
522
|
+
const details = {
|
|
523
|
+
id: result.id,
|
|
524
|
+
runner: result.name,
|
|
525
|
+
exitCode: result.exitCode,
|
|
526
|
+
logPath: result.logPath,
|
|
527
|
+
backend: result.backend,
|
|
528
|
+
fileSize: log.bytes,
|
|
529
|
+
lines: useCapturedOutput ? tailLines : log.lines,
|
|
530
|
+
tail,
|
|
531
|
+
tailLines,
|
|
532
|
+
...result.rtkOutput ? {
|
|
533
|
+
rtkFilter: result.rtkOutput.filter,
|
|
534
|
+
rtkOutputBytes: result.rtkOutput.bytes,
|
|
535
|
+
rtkOutputLines: result.rtkOutput.lines
|
|
536
|
+
} : {},
|
|
537
|
+
...result.rtkWarning ? { rtkWarning: result.rtkWarning } : {},
|
|
538
|
+
...result.timedOut ? { timedOut: true } : {}
|
|
539
|
+
};
|
|
540
|
+
if (failed) throw new Error(text);
|
|
541
|
+
return textResult(text, details);
|
|
542
|
+
}
|
|
543
|
+
//#endregion
|
|
544
|
+
Object.defineProperty(exports, "boundExcerpt", {
|
|
545
|
+
enumerable: true,
|
|
546
|
+
get: function() {
|
|
547
|
+
return boundExcerpt;
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
Object.defineProperty(exports, "boundResultText", {
|
|
551
|
+
enumerable: true,
|
|
552
|
+
get: function() {
|
|
553
|
+
return boundResultText;
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
Object.defineProperty(exports, "collectErrorLines", {
|
|
557
|
+
enumerable: true,
|
|
558
|
+
get: function() {
|
|
559
|
+
return collectErrorLines;
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
Object.defineProperty(exports, "composeExcerpt", {
|
|
563
|
+
enumerable: true,
|
|
564
|
+
get: function() {
|
|
565
|
+
return composeExcerpt;
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
Object.defineProperty(exports, "countLines", {
|
|
569
|
+
enumerable: true,
|
|
570
|
+
get: function() {
|
|
571
|
+
return countLines;
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
Object.defineProperty(exports, "createErrorScanner", {
|
|
575
|
+
enumerable: true,
|
|
576
|
+
get: function() {
|
|
577
|
+
return createErrorScanner;
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
Object.defineProperty(exports, "errorResult", {
|
|
581
|
+
enumerable: true,
|
|
582
|
+
get: function() {
|
|
583
|
+
return errorResult;
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
Object.defineProperty(exports, "formatRunResult", {
|
|
587
|
+
enumerable: true,
|
|
588
|
+
get: function() {
|
|
589
|
+
return formatRunResult;
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
Object.defineProperty(exports, "formatRunnerLine", {
|
|
593
|
+
enumerable: true,
|
|
594
|
+
get: function() {
|
|
595
|
+
return formatRunnerLine;
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
Object.defineProperty(exports, "formatSize", {
|
|
599
|
+
enumerable: true,
|
|
600
|
+
get: function() {
|
|
601
|
+
return formatSize;
|
|
602
|
+
}
|
|
603
|
+
});
|
|
604
|
+
Object.defineProperty(exports, "formatUptime", {
|
|
605
|
+
enumerable: true,
|
|
606
|
+
get: function() {
|
|
607
|
+
return formatUptime;
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
Object.defineProperty(exports, "parseResultPragma", {
|
|
611
|
+
enumerable: true,
|
|
612
|
+
get: function() {
|
|
613
|
+
return parseResultPragma;
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
Object.defineProperty(exports, "summarizeText", {
|
|
617
|
+
enumerable: true,
|
|
618
|
+
get: function() {
|
|
619
|
+
return summarizeText;
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
Object.defineProperty(exports, "textResult", {
|
|
623
|
+
enumerable: true,
|
|
624
|
+
get: function() {
|
|
625
|
+
return textResult;
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
//# sourceMappingURL=bashResult-DNgtahGR.cjs.map
|