@agimon-ai/doompi-runner 0.0.1-alpha.30 → 0.0.1-alpha.32

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.
Files changed (149) hide show
  1. package/README.md +113 -15
  2. package/dist/bin/logSink.cjs +1 -1
  3. package/dist/bin/logSink.cjs.map +1 -1
  4. package/dist/bin/logSink.mjs +1 -1
  5. package/dist/bin/logSink.mjs.map +1 -1
  6. package/dist/config.cjs +1 -1
  7. package/dist/config.d.cts +2 -2
  8. package/dist/config.d.mts +2 -2
  9. package/dist/config.mjs +1 -1
  10. package/dist/index.cjs +1 -1
  11. package/dist/index.d.cts +2 -1
  12. package/dist/index.d.mts +2 -1
  13. package/dist/index.mjs +1 -1
  14. package/dist/services/RtkProcessor/RtkProcessor.cjs +1 -0
  15. package/dist/services/RtkProcessor/RtkProcessor.d.cts +2 -0
  16. package/dist/services/RtkProcessor/RtkProcessor.d.mts +2 -0
  17. package/dist/services/RtkProcessor/RtkProcessor.mjs +1 -0
  18. package/dist/services/RtkProcessor/index.cjs +1 -0
  19. package/dist/services/RtkProcessor/index.d.cts +3 -0
  20. package/dist/services/RtkProcessor/index.d.mts +3 -0
  21. package/dist/services/RtkProcessor/index.mjs +1 -0
  22. package/dist/src/adapters/BashRunService/BashRunService.cjs +1 -1
  23. package/dist/src/adapters/BashRunService/BashRunService.cjs.map +1 -1
  24. package/dist/src/adapters/BashRunService/BashRunService.d.cts +4 -3
  25. package/dist/src/adapters/BashRunService/BashRunService.d.cts.map +1 -1
  26. package/dist/src/adapters/BashRunService/BashRunService.d.mts +4 -3
  27. package/dist/src/adapters/BashRunService/BashRunService.d.mts.map +1 -1
  28. package/dist/src/adapters/BashRunService/BashRunService.mjs +1 -1
  29. package/dist/src/adapters/BashRunService/BashRunService.mjs.map +1 -1
  30. package/dist/src/adapters/Launcher/Launcher.cjs +1 -1
  31. package/dist/src/adapters/Launcher/Launcher.cjs.map +1 -1
  32. package/dist/src/adapters/Launcher/Launcher.d.cts.map +1 -1
  33. package/dist/src/adapters/Launcher/Launcher.d.mts.map +1 -1
  34. package/dist/src/adapters/Launcher/Launcher.mjs +1 -1
  35. package/dist/src/adapters/Launcher/Launcher.mjs.map +1 -1
  36. package/dist/src/adapters/LogFile/LogFile.cjs +1 -1
  37. package/dist/src/adapters/LogFile/LogFile.cjs.map +1 -1
  38. package/dist/src/adapters/LogFile/LogFile.d.cts.map +1 -1
  39. package/dist/src/adapters/LogFile/LogFile.d.mts.map +1 -1
  40. package/dist/src/adapters/LogFile/LogFile.mjs +1 -1
  41. package/dist/src/adapters/LogFile/LogFile.mjs.map +1 -1
  42. package/dist/src/adapters/LogReader/LogReader.cjs +6 -8
  43. package/dist/src/adapters/LogReader/LogReader.cjs.map +1 -1
  44. package/dist/src/adapters/LogReader/LogReader.d.cts.map +1 -1
  45. package/dist/src/adapters/LogReader/LogReader.d.mts.map +1 -1
  46. package/dist/src/adapters/LogReader/LogReader.mjs +6 -8
  47. package/dist/src/adapters/LogReader/LogReader.mjs.map +1 -1
  48. package/dist/src/adapters/PtySpawner/NodePtySpawner.cjs +1 -1
  49. package/dist/src/adapters/PtySpawner/NodePtySpawner.cjs.map +1 -1
  50. package/dist/src/adapters/PtySpawner/NodePtySpawner.d.cts +4 -7
  51. package/dist/src/adapters/PtySpawner/NodePtySpawner.d.cts.map +1 -1
  52. package/dist/src/adapters/PtySpawner/NodePtySpawner.d.mts +4 -7
  53. package/dist/src/adapters/PtySpawner/NodePtySpawner.d.mts.map +1 -1
  54. package/dist/src/adapters/PtySpawner/NodePtySpawner.mjs +1 -1
  55. package/dist/src/adapters/PtySpawner/NodePtySpawner.mjs.map +1 -1
  56. package/dist/src/adapters/RmuxBackend/RmuxBackend.cjs +1 -1
  57. package/dist/src/adapters/RmuxBackend/RmuxBackend.cjs.map +1 -1
  58. package/dist/src/adapters/RmuxBackend/RmuxBackend.d.cts.map +1 -1
  59. package/dist/src/adapters/RmuxBackend/RmuxBackend.d.mts.map +1 -1
  60. package/dist/src/adapters/RmuxBackend/RmuxBackend.mjs +1 -1
  61. package/dist/src/adapters/RmuxBackend/RmuxBackend.mjs.map +1 -1
  62. package/dist/src/adapters/RtkProcessor/RtkProcessor.cjs +2 -0
  63. package/dist/src/adapters/RtkProcessor/RtkProcessor.cjs.map +1 -0
  64. package/dist/src/adapters/RtkProcessor/RtkProcessor.d.cts +20 -0
  65. package/dist/src/adapters/RtkProcessor/RtkProcessor.d.cts.map +1 -0
  66. package/dist/src/adapters/RtkProcessor/RtkProcessor.d.mts +20 -0
  67. package/dist/src/adapters/RtkProcessor/RtkProcessor.d.mts.map +1 -0
  68. package/dist/src/adapters/RtkProcessor/RtkProcessor.mjs +2 -0
  69. package/dist/src/adapters/RtkProcessor/RtkProcessor.mjs.map +1 -0
  70. package/dist/src/adapters/RunnerSettings/RunnerSettingsLoader.cjs +2 -0
  71. package/dist/src/adapters/RunnerSettings/RunnerSettingsLoader.cjs.map +1 -0
  72. package/dist/src/adapters/RunnerSettings/RunnerSettingsLoader.mjs +2 -0
  73. package/dist/src/adapters/RunnerSettings/RunnerSettingsLoader.mjs.map +1 -0
  74. package/dist/src/adapters/pi/extension.cjs +2 -2
  75. package/dist/src/adapters/pi/extension.cjs.map +1 -1
  76. package/dist/src/adapters/pi/extension.d.cts.map +1 -1
  77. package/dist/src/adapters/pi/extension.d.mts.map +1 -1
  78. package/dist/src/adapters/pi/extension.mjs +2 -2
  79. package/dist/src/adapters/pi/extension.mjs.map +1 -1
  80. package/dist/src/commands/bash/bashTool.cjs +4 -4
  81. package/dist/src/commands/bash/bashTool.cjs.map +1 -1
  82. package/dist/src/commands/bash/bashTool.d.cts +2 -2
  83. package/dist/src/commands/bash/bashTool.d.cts.map +1 -1
  84. package/dist/src/commands/bash/bashTool.d.mts +2 -2
  85. package/dist/src/commands/bash/bashTool.d.mts.map +1 -1
  86. package/dist/src/commands/bash/bashTool.mjs +5 -5
  87. package/dist/src/commands/bash/bashTool.mjs.map +1 -1
  88. package/dist/src/commands/bash/responseEnvelope.cjs +11 -7
  89. package/dist/src/commands/bash/responseEnvelope.cjs.map +1 -1
  90. package/dist/src/commands/bash/responseEnvelope.d.cts +55 -5
  91. package/dist/src/commands/bash/responseEnvelope.d.cts.map +1 -1
  92. package/dist/src/commands/bash/responseEnvelope.d.mts +55 -5
  93. package/dist/src/commands/bash/responseEnvelope.d.mts.map +1 -1
  94. package/dist/src/commands/bash/responseEnvelope.mjs +11 -7
  95. package/dist/src/commands/bash/responseEnvelope.mjs.map +1 -1
  96. package/dist/src/container/index.cjs +1 -1
  97. package/dist/src/container/index.cjs.map +1 -1
  98. package/dist/src/container/index.d.cts.map +1 -1
  99. package/dist/src/container/index.d.mts.map +1 -1
  100. package/dist/src/container/index.mjs +1 -1
  101. package/dist/src/container/index.mjs.map +1 -1
  102. package/dist/src/container/types.d.cts +2 -0
  103. package/dist/src/container/types.d.cts.map +1 -1
  104. package/dist/src/container/types.d.mts +2 -0
  105. package/dist/src/container/types.d.mts.map +1 -1
  106. package/dist/src/services/RunnerPaths/types.d.cts +1 -1
  107. package/dist/src/services/RunnerPaths/types.d.mts +1 -1
  108. package/dist/src/services/TokenEstimate/tokenEstimate.cjs +2 -0
  109. package/dist/src/services/TokenEstimate/tokenEstimate.cjs.map +1 -0
  110. package/dist/src/services/TokenEstimate/tokenEstimate.mjs +2 -0
  111. package/dist/src/services/TokenEstimate/tokenEstimate.mjs.map +1 -0
  112. package/dist/src/types/bashRunService.d.cts +5 -0
  113. package/dist/src/types/bashRunService.d.cts.map +1 -1
  114. package/dist/src/types/bashRunService.d.mts +5 -0
  115. package/dist/src/types/bashRunService.d.mts.map +1 -1
  116. package/dist/src/types/config.cjs +1 -1
  117. package/dist/src/types/config.cjs.map +1 -1
  118. package/dist/src/types/config.d.cts +47 -5
  119. package/dist/src/types/config.d.cts.map +1 -1
  120. package/dist/src/types/config.d.mts +47 -5
  121. package/dist/src/types/config.d.mts.map +1 -1
  122. package/dist/src/types/config.mjs +1 -1
  123. package/dist/src/types/config.mjs.map +1 -1
  124. package/dist/src/types/logFile.d.cts +1 -1
  125. package/dist/src/types/logFile.d.mts +1 -1
  126. package/dist/src/types/logReader.d.cts +1 -1
  127. package/dist/src/types/logReader.d.mts +1 -1
  128. package/dist/src/types/ptySpawner.d.cts +1 -1
  129. package/dist/src/types/ptySpawner.d.mts +1 -1
  130. package/dist/src/types/rtkProcessor.cjs +2 -0
  131. package/dist/src/types/rtkProcessor.cjs.map +1 -0
  132. package/dist/src/types/rtkProcessor.d.cts +35 -0
  133. package/dist/src/types/rtkProcessor.d.cts.map +1 -0
  134. package/dist/src/types/rtkProcessor.d.mts +35 -0
  135. package/dist/src/types/rtkProcessor.d.mts.map +1 -0
  136. package/dist/src/types/rtkProcessor.mjs +2 -0
  137. package/dist/src/types/rtkProcessor.mjs.map +1 -0
  138. package/dist/src/types/runnerSettings.d.cts +34 -0
  139. package/dist/src/types/runnerSettings.d.cts.map +1 -0
  140. package/dist/src/types/runnerSettings.d.mts +34 -0
  141. package/dist/src/types/runnerSettings.d.mts.map +1 -0
  142. package/dist/tool/responseEnvelope.cjs +1 -1
  143. package/dist/tool/responseEnvelope.d.cts +2 -2
  144. package/dist/tool/responseEnvelope.d.mts +2 -2
  145. package/dist/tool/responseEnvelope.mjs +1 -1
  146. package/dist/types.d.cts +2 -1
  147. package/dist/types.d.mts +2 -1
  148. package/package.json +22 -9
  149. package/skills/doom-runner/SKILL.md +6 -3
package/README.md CHANGED
@@ -14,10 +14,10 @@ inline; long commands can be promoted to a background runner instead of blocking
14
14
  - Node.js 22.19.0 or newer
15
15
  - Pi 0.84.2 and Pi TUI 0.84.2
16
16
  - `/bin/bash`
17
- - macOS or Linux on arm64 or x64 for bundled RMUX support
17
+ - macOS or Linux on arm64 or x64 for bundled RMUX and RTK support
18
18
 
19
- Linux native loading also depends on a compatible system loader and libc. Runner uses a `node-pty`
20
- fallback when RMUX is unavailable.
19
+ Linux native loading also depends on a compatible system loader and libc. Non-interactive commands
20
+ fall back to a supervised subprocess when RMUX is unavailable. Interactive commands require RMUX.
21
21
 
22
22
  ## Install
23
23
 
@@ -48,6 +48,15 @@ needs terminal input.
48
48
  Runner requires `PI_SESSION_ID` for session ownership. Processes, controls, and logs remain
49
49
  addressable after transcript compaction because their identity is outside model context.
50
50
 
51
+ ### RTK result processing
52
+
53
+ Runner keeps the complete original log, then uses the matching RTK stdin filter only for
54
+ conservatively recognized single commands. Current safe mappings cover `cargo test`, `pytest`, plain
55
+ unified `git diff`, structured `grep` or `rg`, `go test -json`, and JSON-formatted `ruff check`.
56
+ Compound commands, pipelines, redirects, substitutions, incompatible formats, unsupported commands,
57
+ and logs above RTK's 10 MiB stdin limit return bounded raw output instead. An eligible RTK failure
58
+ also returns bounded raw output with a warning and does not change the command exit result.
59
+
51
60
  ## Inspect and control runs
52
61
 
53
62
  Use `/runners` or `SPC r r` in the TUI. The `doom-runner` CLI supports:
@@ -73,9 +82,97 @@ By default, session-scoped logs and registry data live under:
73
82
  ~/.pi/agent/doom-runner/<session>/
74
83
  ```
75
84
 
76
- Logs rotate at 5 MiB by default and are eligible for cleanup after seven days. Limits and the
77
- promotion threshold can be configured through Runner's exported configuration helpers and
78
- environment-backed runtime settings.
85
+ Logs remain complete until TTL cleanup and are eligible for cleanup after seven days by default. The
86
+ legacy log-size configuration exports remain available for compatibility but no longer rotate log
87
+ content. Result limits, retention, and the promotion threshold remain environment-configurable.
88
+
89
+ ### Result excerpts
90
+
91
+ A result that exceeds the ceiling is returned as an excerpt: roughly the first fifth of the budget
92
+ holds the opening lines, the rest holds the closing ones, and a marker between them states how many
93
+ lines were dropped.
94
+
95
+ The budget depends on the exit status. A command that **failed** gets 8 KiB and 120 lines, because
96
+ its output is the evidence. A command that **succeeded** gets 2 KiB, because exiting 0 has already
97
+ reported the outcome and the rest is mostly progress lines and repeated warnings:
98
+
99
+ ```text
100
+ Log excerpt (71 of 604 lines):
101
+ $ pnpm build
102
+ Compiling 1200 modules...
103
+ compiled src/module-0.ts
104
+ … [5 lines elided] …
105
+ compiled src/module-599.ts
106
+ Build succeeded in 12.4s
107
+ exit status 0
108
+ Full log: /path/to/run.log (17.0 KB, 604 lines); inspect with doom-runner logs run-a
109
+ ```
110
+
111
+ Three ceilings apply and whichever binds first wins: bytes, lines, and tokens. Tokens are there
112
+ because bytes do not track context cost. Measured against `gpt-tokenizer`, real text runs from about
113
+ 1.4 characters per token for base64 to 4.7 for English prose, so 8 KiB of one costs several times
114
+ what 8 KiB of the other does. The defaults are 2,048 tokens on failure and 512 on success.
115
+
116
+ Token counts are estimated rather than tokenized: truncation runs on every command and is
117
+ synchronous, so loading a vocabulary would charge every session for a table most never need. The
118
+ estimator models how BPE behaves, with punctuation forcing boundaries, natural words cheap, and
119
+ letter-digit runs expensive. Its worst error against `gpt-tokenizer` is a factor of about 1.46
120
+ either way, which is why the byte ceiling stays behind it as the hard bound.
121
+
122
+ `DOOM_RUNNER_RESULT_MAX_BYTES`, `DOOM_RUNNER_RESULT_MAX_TOKENS`, and their
123
+ `DOOM_RUNNER_SUCCESS_*` counterparts move these for one invocation. A pragma overrides all of
124
+ them, which is how one noisy successful command can still ask for the wider result. Raising only
125
+ `maxResultBytes` will not help when the token ceiling is the one binding.
126
+
127
+ Error lines found in the dropped span are rescued into that marker's block, up to ten entries.
128
+ Matching looks for a severity word in the first 60 characters, so `[widget] build: error TS2322`
129
+ and a line behind a timestamp both count, while `0 errors`, `no failures`, and `--error-format` do
130
+ not. Byte-identical lines collapse to one entry with an occurrence count. Lines that share a shape
131
+ but differ in detail keep every variant, joined inside brackets so nothing actionable is lost:
132
+
133
+ ```text
134
+ ERROR in [src/widget-100.ts:100:7|src/widget-200.ts:200:7] - Type mismatch
135
+ error: connection refused (×40)
136
+ ```
137
+
138
+ The complete raw log on disk is never truncated.
139
+
140
+ ### Configuration
141
+
142
+ Four layers, most specific first: a per-command pragma, then an environment variable, then project
143
+ configuration, then the built-in default. Project configuration is the project's baseline, so an
144
+ environment variable set for one invocation still wins over it.
145
+
146
+ One command that needs a wider result can say so on its first line. The pragma is a shell comment,
147
+ so it stays harmless to the command itself:
148
+
149
+ ```bash
150
+ # @doom: {"maxResultBytes": 32768, "maxResultTokens": 8192, "maxResultLines": 300}
151
+ pnpm build
152
+ ```
153
+
154
+ Project settings follow Pi's convention for extension configuration: one JSON file per extension
155
+ under the config directory, at `.pi/doompi-runner.json`. It is read only when the project is
156
+ trusted, and an unrecognized or out-of-range key is reported rather than silently ignored.
157
+
158
+ ```json
159
+ {
160
+ "maxResultBytes": 16384,
161
+ "maxResultLines": 200,
162
+ "successMaxResultBytes": 2048,
163
+ "maxResultTokens": 2048,
164
+ "successMaxResultTokens": 512,
165
+ "headRatio": 0.2,
166
+ "errorPatterns": ["^FEHLER", "^\\s*FAILED\\b"],
167
+ "errorMaxEntries": 10,
168
+ "errorMaxVariantsJoined": 6,
169
+ "errorBudgetRatio": 0.2
170
+ }
171
+ ```
172
+
173
+ `errorPatterns` extends the built-in matcher rather than replacing it, which is what makes output
174
+ it does not recognize reachable. Ceilings apply to every numeric key so a checked-in file cannot
175
+ flood the model's context.
79
176
 
80
177
  Commands inherit the DoomPi process environment and the operating system user's privileges. Logs
81
178
  may contain prompts, source, command output, credentials, or other secrets; restrict access and
@@ -83,17 +180,17 @@ retention accordingly.
83
180
 
84
181
  ## Native artifacts
85
182
 
86
- Runner selects one optional dependency automatically:
183
+ Runner selects the matching optional dependencies automatically:
87
184
 
88
- | Host | Package |
89
- | ----------- | -------------------------------------------- |
90
- | macOS arm64 | `@agimon-ai/doompi-runner-rmux-darwin-arm64` |
91
- | macOS x64 | `@agimon-ai/doompi-runner-rmux-darwin-x64` |
92
- | Linux arm64 | `@agimon-ai/doompi-runner-rmux-linux-arm64` |
93
- | Linux x64 | `@agimon-ai/doompi-runner-rmux-linux-x64` |
185
+ | Host | RMUX package | RTK package |
186
+ | ----------- | -------------------------------------------- | ------------------------------------------- |
187
+ | macOS arm64 | `@agimon-ai/doompi-runner-rmux-darwin-arm64` | `@agimon-ai/doompi-runner-rtk-darwin-arm64` |
188
+ | macOS x64 | `@agimon-ai/doompi-runner-rmux-darwin-x64` | `@agimon-ai/doompi-runner-rtk-darwin-x64` |
189
+ | Linux arm64 | `@agimon-ai/doompi-runner-rmux-linux-arm64` | `@agimon-ai/doompi-runner-rtk-linux-arm64` |
190
+ | Linux x64 | `@agimon-ai/doompi-runner-rmux-linux-x64` | `@agimon-ai/doompi-runner-rtk-linux-x64` |
94
191
 
95
- Do not install these platform packages directly. They contain native RMUX executables and export
96
- only package metadata.
192
+ Do not install platform packages directly. They contain native executables and export only package
193
+ metadata. RMUX is dual-licensed under MIT or Apache-2.0. RTK v0.45.0 is licensed under Apache-2.0.
97
194
 
98
195
  ## Public API
99
196
 
@@ -104,6 +201,7 @@ import {
104
201
  DEFAULT_LOG_MAX_BYTES,
105
202
  DEFAULT_LOG_TTL_MS,
106
203
  RmuxBackend,
204
+ rtkPackageForTarget,
107
205
  } from '@agimon-ai/doompi-runner';
108
206
  ```
109
207
 
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("../src/services/AnsiScrub/ansiScrub.cjs");let n=require("node:fs");n=e.__toESM(n,1);let r=require("node:url"),i=require("@agimon-ai/doompi-telemetry");async function a(e=process.argv.slice(2)){let r=Date.now(),a=(0,i.createDoomTelemetry)({serviceName:`doom-runner-log-sink`,packageName:`@agimon-ai/doompi-runner`,env:process.env,enableLogs:!0,enableTraces:!0}),[s,c,l,u]=e,d;try{if(!s||!c||!l||!u)throw Error(`logSink requires log, rotated log, max bytes, and completion paths`);if(d=Number(l),!Number.isFinite(d)||d<=0)throw Error(`logSink max bytes must be positive`)}catch(e){throw await a.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-r}),await a.shutdown(),e}let f,p;try{f=n.default.openSync(s,`a`),p=n.default.statSync(s).size}catch(e){throw await a.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-r}),await a.shutdown(),e}let m=0,h=0;try{process.stdin.setEncoding(`utf8`);for await(let e of process.stdin){let r=t.scrubTerminalOutput(String(e));if(!r)continue;let i=Buffer.from(r,`utf8`);p+i.byteLength>d&&(n.default.closeSync(f),n.default.renameSync(s,c),f=n.default.openSync(s,`w`),p=0,h+=1),n.default.writeSync(f,i),p+=i.byteLength,m+=1}return n.default.closeSync(f),o(u),await a.recordEvent(`doom_runner.file_sink_finished`,{outcome:`completed`,"runner.chunk_count":m,"runner.bytes_written":p,"runner.rotation_count":h,duration_ms:Date.now()-r}),0}catch(e){throw await a.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-r}),e}finally{await a.shutdown()}}function o(e){let t=`${e}.${process.pid}.tmp`;n.default.writeFileSync(t,``,{mode:384}),n.default.renameSync(t,e)}process.argv[1]&&require("url").pathToFileURL(__filename).href===(0,r.pathToFileURL)(process.argv[1]).href&&a().then(e=>{process.exitCode=e},e=>{process.stderr.write(`${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1}),exports.main=a;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("../src/services/AnsiScrub/ansiScrub.cjs");let n=require("node:fs");n=e.__toESM(n,1);let r=require("node:url"),i=require("@agimon-ai/doompi-telemetry");async function a(e=process.argv.slice(2)){let r=Date.now(),a=(0,i.createDoomTelemetry)({serviceName:`doom-runner-log-sink`,packageName:`@agimon-ai/doompi-runner`,env:process.env,enableLogs:!0,enableTraces:!0}),[s,c,l,u]=e;try{if(!s||!c||!l||!u)throw Error(`logSink requires log, rotated log, max bytes, and completion paths`)}catch(e){throw await a.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-r}),await a.shutdown(),e}let d,f;try{d=n.default.openSync(s,`a`),f=n.default.statSync(s).size}catch(e){throw await a.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-r}),await a.shutdown(),e}let p=0;try{process.stdin.setEncoding(`utf8`);for await(let e of process.stdin){let r=t.scrubTerminalOutput(String(e));if(!r)continue;let i=Buffer.from(r,`utf8`);n.default.writeSync(d,i),f+=i.byteLength,p+=1}return n.default.closeSync(d),o(u),await a.recordEvent(`doom_runner.file_sink_finished`,{outcome:`completed`,"runner.chunk_count":p,"runner.bytes_written":f,duration_ms:Date.now()-r}),0}catch(e){throw await a.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-r}),e}finally{await a.shutdown()}}function o(e){let t=`${e}.${process.pid}.tmp`;n.default.writeFileSync(t,``,{mode:384}),n.default.renameSync(t,e)}process.argv[1]&&require("url").pathToFileURL(__filename).href===(0,r.pathToFileURL)(process.argv[1]).href&&a().then(e=>{process.exitCode=e},e=>{process.stderr.write(`${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1}),exports.main=a;
2
2
  //# sourceMappingURL=logSink.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"logSink.cjs","names":["createDoomTelemetry","fs","scrubTerminalOutput","pathToFileURL"],"sources":["../../src/bin/logSink.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { pathToFileURL } from 'node:url';\nimport { createDoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport { scrubTerminalOutput } from '../services/AnsiScrub/ansiScrub';\n\nexport async function main(argv: readonly string[] = process.argv.slice(2)): Promise<number> {\n const startedAt = Date.now();\n const telemetry = createDoomTelemetry({\n serviceName: 'doom-runner-log-sink',\n packageName: '@agimon-ai/doompi-runner',\n env: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n const [logPath, rotatedPath, maxBytesRaw, donePath] = argv;\n let maxBytes: number;\n try {\n if (!logPath || !rotatedPath || !maxBytesRaw || !donePath) {\n throw new Error('logSink requires log, rotated log, max bytes, and completion paths');\n }\n maxBytes = Number(maxBytesRaw);\n if (!Number.isFinite(maxBytes) || maxBytes <= 0) throw new Error('logSink max bytes must be positive');\n } catch (error) {\n await telemetry.recordError('doom_runner.file_sink_failed', error, { duration_ms: Date.now() - startedAt });\n await telemetry.shutdown();\n throw error;\n }\n\n let handle: number;\n let written: number;\n try {\n handle = fs.openSync(logPath, 'a');\n written = fs.statSync(logPath).size;\n } catch (error) {\n await telemetry.recordError('doom_runner.file_sink_failed', error, { duration_ms: Date.now() - startedAt });\n await telemetry.shutdown();\n throw error;\n }\n let chunks = 0;\n let rotations = 0;\n try {\n process.stdin.setEncoding('utf8');\n for await (const chunk of process.stdin) {\n const text = scrubTerminalOutput(String(chunk));\n if (!text) continue;\n const bytes = Buffer.from(text, 'utf8');\n if (written + bytes.byteLength > maxBytes) {\n fs.closeSync(handle);\n fs.renameSync(logPath, rotatedPath);\n handle = fs.openSync(logPath, 'w');\n written = 0;\n rotations += 1;\n }\n fs.writeSync(handle, bytes);\n written += bytes.byteLength;\n chunks += 1;\n }\n fs.closeSync(handle);\n writeDone(donePath);\n await telemetry.recordEvent('doom_runner.file_sink_finished', {\n outcome: 'completed',\n 'runner.chunk_count': chunks,\n 'runner.bytes_written': written,\n 'runner.rotation_count': rotations,\n duration_ms: Date.now() - startedAt,\n });\n return 0;\n } catch (error) {\n await telemetry.recordError('doom_runner.file_sink_failed', error, { duration_ms: Date.now() - startedAt });\n throw error;\n } finally {\n await telemetry.shutdown();\n }\n}\n\nfunction writeDone(target: string): void {\n const temporary = `${target}.${process.pid}.tmp`;\n fs.writeFileSync(temporary, '', { mode: 0o600 });\n fs.renameSync(temporary, target);\n}\n\nif (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {\n main().then(\n (code) => {\n process.exitCode = code;\n },\n (error: unknown) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n },\n );\n}\n"],"mappings":"0RAKA,eAAsB,EAAK,EAA0B,QAAQ,KAAK,MAAM,CAAC,EAAoB,CAC3F,IAAM,EAAY,KAAK,IAAI,EACrB,GAAA,EAAYA,EAAAA,oBAAAA,CAAoB,CACpC,YAAa,uBACb,YAAa,2BACb,IAAK,QAAQ,IACb,WAAY,GACZ,aAAc,EAChB,CAAC,EACK,CAAC,EAAS,EAAa,EAAa,GAAY,EAClD,EACJ,GAAI,CACF,GAAI,CAAC,GAAW,CAAC,GAAe,CAAC,GAAe,CAAC,EAC/C,MAAU,MAAM,oEAAoE,EAGtF,GADA,EAAW,OAAO,CAAW,EACzB,CAAC,OAAO,SAAS,CAAQ,GAAK,GAAY,EAAG,MAAU,MAAM,oCAAoC,CACvG,OAAS,EAAO,CAGd,MAFA,MAAM,EAAU,YAAY,+BAAgC,EAAO,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,CAAC,EAC1G,MAAM,EAAU,SAAS,EACnB,CACR,CAEA,IAAI,EACA,EACJ,GAAI,CACF,EAASC,EAAAA,QAAG,SAAS,EAAS,GAAG,EACjC,EAAUA,EAAAA,QAAG,SAAS,CAAO,CAAC,CAAC,IACjC,OAAS,EAAO,CAGd,MAFA,MAAM,EAAU,YAAY,+BAAgC,EAAO,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,CAAC,EAC1G,MAAM,EAAU,SAAS,EACnB,CACR,CACA,IAAI,EAAS,EACT,EAAY,EAChB,GAAI,CACF,QAAQ,MAAM,YAAY,MAAM,EAChC,UAAW,IAAM,KAAS,QAAQ,MAAO,CACvC,IAAM,EAAOC,EAAAA,oBAAoB,OAAO,CAAK,CAAC,EAC9C,GAAI,CAAC,EAAM,SACX,IAAM,EAAQ,OAAO,KAAK,EAAM,MAAM,EAClC,EAAU,EAAM,WAAa,IAC/B,EAAA,QAAG,UAAU,CAAM,EACnB,EAAA,QAAG,WAAW,EAAS,CAAW,EAClC,EAASD,EAAAA,QAAG,SAAS,EAAS,GAAG,EACjC,EAAU,EACV,GAAa,GAEf,EAAA,QAAG,UAAU,EAAQ,CAAK,EAC1B,GAAW,EAAM,WACjB,GAAU,CACZ,CAUA,OATA,EAAA,QAAG,UAAU,CAAM,EACnB,EAAU,CAAQ,EAClB,MAAM,EAAU,YAAY,iCAAkC,CAC5D,QAAS,YACT,qBAAsB,EACtB,uBAAwB,EACxB,wBAAyB,EACzB,YAAa,KAAK,IAAI,EAAI,CAC5B,CAAC,EACM,CACT,OAAS,EAAO,CAEd,MADA,MAAM,EAAU,YAAY,+BAAgC,EAAO,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,CAAC,EACpG,CACR,QAAU,CACR,MAAM,EAAU,SAAS,CAC3B,CACF,CAEA,SAAS,EAAU,EAAsB,CACvC,IAAM,EAAY,GAAG,EAAO,GAAG,QAAQ,IAAI,MAC3C,EAAA,QAAG,cAAc,EAAW,GAAI,CAAE,KAAM,GAAM,CAAC,EAC/C,EAAA,QAAG,WAAW,EAAW,CAAM,CACjC,CAEI,QAAQ,KAAK,IAAA,QAAA,KAAA,CAAA,CAAA,cAAA,UAAA,CAAA,CAAA,QAAA,EAA0BE,EAAAA,cAAAA,CAAc,QAAQ,KAAK,EAAE,CAAC,CAAC,MACxE,EAAK,CAAC,CAAC,KACJ,GAAS,CACR,QAAQ,SAAW,CACrB,EACC,GAAmB,CAClB,QAAQ,OAAO,MAAM,GAAG,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EAAE,GAAG,EAClF,QAAQ,SAAW,CACrB,CACF"}
1
+ {"version":3,"file":"logSink.cjs","names":["createDoomTelemetry","fs","scrubTerminalOutput","pathToFileURL"],"sources":["../../src/bin/logSink.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { pathToFileURL } from 'node:url';\nimport { createDoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport { scrubTerminalOutput } from '../services/AnsiScrub/ansiScrub';\n\nexport async function main(argv: readonly string[] = process.argv.slice(2)): Promise<number> {\n const startedAt = Date.now();\n const telemetry = createDoomTelemetry({\n serviceName: 'doom-runner-log-sink',\n packageName: '@agimon-ai/doompi-runner',\n env: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n const [logPath, rotatedPath, maxBytesRaw, donePath] = argv;\n try {\n // Keep the legacy argument shape for the published executable subpath. Raw\n // logs are append-only now, so the former rotation path and ceiling are not used.\n if (!logPath || !rotatedPath || !maxBytesRaw || !donePath) {\n throw new Error('logSink requires log, rotated log, max bytes, and completion paths');\n }\n } catch (error) {\n await telemetry.recordError('doom_runner.file_sink_failed', error, { duration_ms: Date.now() - startedAt });\n await telemetry.shutdown();\n throw error;\n }\n\n let handle: number;\n let written: number;\n try {\n handle = fs.openSync(logPath, 'a');\n written = fs.statSync(logPath).size;\n } catch (error) {\n await telemetry.recordError('doom_runner.file_sink_failed', error, { duration_ms: Date.now() - startedAt });\n await telemetry.shutdown();\n throw error;\n }\n let chunks = 0;\n try {\n process.stdin.setEncoding('utf8');\n for await (const chunk of process.stdin) {\n const text = scrubTerminalOutput(String(chunk));\n if (!text) continue;\n const bytes = Buffer.from(text, 'utf8');\n fs.writeSync(handle, bytes);\n written += bytes.byteLength;\n chunks += 1;\n }\n fs.closeSync(handle);\n writeDone(donePath);\n await telemetry.recordEvent('doom_runner.file_sink_finished', {\n outcome: 'completed',\n 'runner.chunk_count': chunks,\n 'runner.bytes_written': written,\n duration_ms: Date.now() - startedAt,\n });\n return 0;\n } catch (error) {\n await telemetry.recordError('doom_runner.file_sink_failed', error, { duration_ms: Date.now() - startedAt });\n throw error;\n } finally {\n await telemetry.shutdown();\n }\n}\n\nfunction writeDone(target: string): void {\n const temporary = `${target}.${process.pid}.tmp`;\n fs.writeFileSync(temporary, '', { mode: 0o600 });\n fs.renameSync(temporary, target);\n}\n\nif (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {\n main().then(\n (code) => {\n process.exitCode = code;\n },\n (error: unknown) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n },\n );\n}\n"],"mappings":"0RAKA,eAAsB,EAAK,EAA0B,QAAQ,KAAK,MAAM,CAAC,EAAoB,CAC3F,IAAM,EAAY,KAAK,IAAI,EACrB,GAAA,EAAYA,EAAAA,oBAAAA,CAAoB,CACpC,YAAa,uBACb,YAAa,2BACb,IAAK,QAAQ,IACb,WAAY,GACZ,aAAc,EAChB,CAAC,EACK,CAAC,EAAS,EAAa,EAAa,GAAY,EACtD,GAAI,CAGF,GAAI,CAAC,GAAW,CAAC,GAAe,CAAC,GAAe,CAAC,EAC/C,MAAU,MAAM,oEAAoE,CAExF,OAAS,EAAO,CAGd,MAFA,MAAM,EAAU,YAAY,+BAAgC,EAAO,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,CAAC,EAC1G,MAAM,EAAU,SAAS,EACnB,CACR,CAEA,IAAI,EACA,EACJ,GAAI,CACF,EAASC,EAAAA,QAAG,SAAS,EAAS,GAAG,EACjC,EAAUA,EAAAA,QAAG,SAAS,CAAO,CAAC,CAAC,IACjC,OAAS,EAAO,CAGd,MAFA,MAAM,EAAU,YAAY,+BAAgC,EAAO,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,CAAC,EAC1G,MAAM,EAAU,SAAS,EACnB,CACR,CACA,IAAI,EAAS,EACb,GAAI,CACF,QAAQ,MAAM,YAAY,MAAM,EAChC,UAAW,IAAM,KAAS,QAAQ,MAAO,CACvC,IAAM,EAAOC,EAAAA,oBAAoB,OAAO,CAAK,CAAC,EAC9C,GAAI,CAAC,EAAM,SACX,IAAM,EAAQ,OAAO,KAAK,EAAM,MAAM,EACtC,EAAA,QAAG,UAAU,EAAQ,CAAK,EAC1B,GAAW,EAAM,WACjB,GAAU,CACZ,CASA,OARA,EAAA,QAAG,UAAU,CAAM,EACnB,EAAU,CAAQ,EAClB,MAAM,EAAU,YAAY,iCAAkC,CAC5D,QAAS,YACT,qBAAsB,EACtB,uBAAwB,EACxB,YAAa,KAAK,IAAI,EAAI,CAC5B,CAAC,EACM,CACT,OAAS,EAAO,CAEd,MADA,MAAM,EAAU,YAAY,+BAAgC,EAAO,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,CAAC,EACpG,CACR,QAAU,CACR,MAAM,EAAU,SAAS,CAC3B,CACF,CAEA,SAAS,EAAU,EAAsB,CACvC,IAAM,EAAY,GAAG,EAAO,GAAG,QAAQ,IAAI,MAC3C,EAAA,QAAG,cAAc,EAAW,GAAI,CAAE,KAAM,GAAM,CAAC,EAC/C,EAAA,QAAG,WAAW,EAAW,CAAM,CACjC,CAEI,QAAQ,KAAK,IAAA,QAAA,KAAA,CAAA,CAAA,cAAA,UAAA,CAAA,CAAA,QAAA,EAA0BC,EAAAA,cAAAA,CAAc,QAAQ,KAAK,EAAE,CAAC,CAAC,MACxE,EAAK,CAAC,CAAC,KACJ,GAAS,CACR,QAAQ,SAAW,CACrB,EACC,GAAmB,CAClB,QAAQ,OAAO,MAAM,GAAG,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EAAE,GAAG,EAClF,QAAQ,SAAW,CACrB,CACF"}
@@ -1,2 +1,2 @@
1
- import{scrubTerminalOutput as e}from"../src/services/AnsiScrub/ansiScrub.mjs";import t from"node:fs";import{pathToFileURL as n}from"node:url";import{createDoomTelemetry as r}from"@agimon-ai/doompi-telemetry";async function i(n=process.argv.slice(2)){let i=Date.now(),o=r({serviceName:`doom-runner-log-sink`,packageName:`@agimon-ai/doompi-runner`,env:process.env,enableLogs:!0,enableTraces:!0}),[s,c,l,u]=n,d;try{if(!s||!c||!l||!u)throw Error(`logSink requires log, rotated log, max bytes, and completion paths`);if(d=Number(l),!Number.isFinite(d)||d<=0)throw Error(`logSink max bytes must be positive`)}catch(e){throw await o.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-i}),await o.shutdown(),e}let f,p;try{f=t.openSync(s,`a`),p=t.statSync(s).size}catch(e){throw await o.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-i}),await o.shutdown(),e}let m=0,h=0;try{process.stdin.setEncoding(`utf8`);for await(let n of process.stdin){let r=e(String(n));if(!r)continue;let i=Buffer.from(r,`utf8`);p+i.byteLength>d&&(t.closeSync(f),t.renameSync(s,c),f=t.openSync(s,`w`),p=0,h+=1),t.writeSync(f,i),p+=i.byteLength,m+=1}return t.closeSync(f),a(u),await o.recordEvent(`doom_runner.file_sink_finished`,{outcome:`completed`,"runner.chunk_count":m,"runner.bytes_written":p,"runner.rotation_count":h,duration_ms:Date.now()-i}),0}catch(e){throw await o.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-i}),e}finally{await o.shutdown()}}function a(e){let n=`${e}.${process.pid}.tmp`;t.writeFileSync(n,``,{mode:384}),t.renameSync(n,e)}process.argv[1]&&import.meta.url===n(process.argv[1]).href&&i().then(e=>{process.exitCode=e},e=>{process.stderr.write(`${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1});export{i as main};
1
+ import{scrubTerminalOutput as e}from"../src/services/AnsiScrub/ansiScrub.mjs";import t from"node:fs";import{pathToFileURL as n}from"node:url";import{createDoomTelemetry as r}from"@agimon-ai/doompi-telemetry";async function i(n=process.argv.slice(2)){let i=Date.now(),o=r({serviceName:`doom-runner-log-sink`,packageName:`@agimon-ai/doompi-runner`,env:process.env,enableLogs:!0,enableTraces:!0}),[s,c,l,u]=n;try{if(!s||!c||!l||!u)throw Error(`logSink requires log, rotated log, max bytes, and completion paths`)}catch(e){throw await o.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-i}),await o.shutdown(),e}let d,f;try{d=t.openSync(s,`a`),f=t.statSync(s).size}catch(e){throw await o.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-i}),await o.shutdown(),e}let p=0;try{process.stdin.setEncoding(`utf8`);for await(let n of process.stdin){let r=e(String(n));if(!r)continue;let i=Buffer.from(r,`utf8`);t.writeSync(d,i),f+=i.byteLength,p+=1}return t.closeSync(d),a(u),await o.recordEvent(`doom_runner.file_sink_finished`,{outcome:`completed`,"runner.chunk_count":p,"runner.bytes_written":f,duration_ms:Date.now()-i}),0}catch(e){throw await o.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-i}),e}finally{await o.shutdown()}}function a(e){let n=`${e}.${process.pid}.tmp`;t.writeFileSync(n,``,{mode:384}),t.renameSync(n,e)}process.argv[1]&&import.meta.url===n(process.argv[1]).href&&i().then(e=>{process.exitCode=e},e=>{process.stderr.write(`${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1});export{i as main};
2
2
  //# sourceMappingURL=logSink.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"logSink.mjs","names":[],"sources":["../../src/bin/logSink.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { pathToFileURL } from 'node:url';\nimport { createDoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport { scrubTerminalOutput } from '../services/AnsiScrub/ansiScrub';\n\nexport async function main(argv: readonly string[] = process.argv.slice(2)): Promise<number> {\n const startedAt = Date.now();\n const telemetry = createDoomTelemetry({\n serviceName: 'doom-runner-log-sink',\n packageName: '@agimon-ai/doompi-runner',\n env: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n const [logPath, rotatedPath, maxBytesRaw, donePath] = argv;\n let maxBytes: number;\n try {\n if (!logPath || !rotatedPath || !maxBytesRaw || !donePath) {\n throw new Error('logSink requires log, rotated log, max bytes, and completion paths');\n }\n maxBytes = Number(maxBytesRaw);\n if (!Number.isFinite(maxBytes) || maxBytes <= 0) throw new Error('logSink max bytes must be positive');\n } catch (error) {\n await telemetry.recordError('doom_runner.file_sink_failed', error, { duration_ms: Date.now() - startedAt });\n await telemetry.shutdown();\n throw error;\n }\n\n let handle: number;\n let written: number;\n try {\n handle = fs.openSync(logPath, 'a');\n written = fs.statSync(logPath).size;\n } catch (error) {\n await telemetry.recordError('doom_runner.file_sink_failed', error, { duration_ms: Date.now() - startedAt });\n await telemetry.shutdown();\n throw error;\n }\n let chunks = 0;\n let rotations = 0;\n try {\n process.stdin.setEncoding('utf8');\n for await (const chunk of process.stdin) {\n const text = scrubTerminalOutput(String(chunk));\n if (!text) continue;\n const bytes = Buffer.from(text, 'utf8');\n if (written + bytes.byteLength > maxBytes) {\n fs.closeSync(handle);\n fs.renameSync(logPath, rotatedPath);\n handle = fs.openSync(logPath, 'w');\n written = 0;\n rotations += 1;\n }\n fs.writeSync(handle, bytes);\n written += bytes.byteLength;\n chunks += 1;\n }\n fs.closeSync(handle);\n writeDone(donePath);\n await telemetry.recordEvent('doom_runner.file_sink_finished', {\n outcome: 'completed',\n 'runner.chunk_count': chunks,\n 'runner.bytes_written': written,\n 'runner.rotation_count': rotations,\n duration_ms: Date.now() - startedAt,\n });\n return 0;\n } catch (error) {\n await telemetry.recordError('doom_runner.file_sink_failed', error, { duration_ms: Date.now() - startedAt });\n throw error;\n } finally {\n await telemetry.shutdown();\n }\n}\n\nfunction writeDone(target: string): void {\n const temporary = `${target}.${process.pid}.tmp`;\n fs.writeFileSync(temporary, '', { mode: 0o600 });\n fs.renameSync(temporary, target);\n}\n\nif (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {\n main().then(\n (code) => {\n process.exitCode = code;\n },\n (error: unknown) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n },\n );\n}\n"],"mappings":"gNAKA,eAAsB,EAAK,EAA0B,QAAQ,KAAK,MAAM,CAAC,EAAoB,CAC3F,IAAM,EAAY,KAAK,IAAI,EACrB,EAAY,EAAoB,CACpC,YAAa,uBACb,YAAa,2BACb,IAAK,QAAQ,IACb,WAAY,GACZ,aAAc,EAChB,CAAC,EACK,CAAC,EAAS,EAAa,EAAa,GAAY,EAClD,EACJ,GAAI,CACF,GAAI,CAAC,GAAW,CAAC,GAAe,CAAC,GAAe,CAAC,EAC/C,MAAU,MAAM,oEAAoE,EAGtF,GADA,EAAW,OAAO,CAAW,EACzB,CAAC,OAAO,SAAS,CAAQ,GAAK,GAAY,EAAG,MAAU,MAAM,oCAAoC,CACvG,OAAS,EAAO,CAGd,MAFA,MAAM,EAAU,YAAY,+BAAgC,EAAO,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,CAAC,EAC1G,MAAM,EAAU,SAAS,EACnB,CACR,CAEA,IAAI,EACA,EACJ,GAAI,CACF,EAAS,EAAG,SAAS,EAAS,GAAG,EACjC,EAAU,EAAG,SAAS,CAAO,CAAC,CAAC,IACjC,OAAS,EAAO,CAGd,MAFA,MAAM,EAAU,YAAY,+BAAgC,EAAO,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,CAAC,EAC1G,MAAM,EAAU,SAAS,EACnB,CACR,CACA,IAAI,EAAS,EACT,EAAY,EAChB,GAAI,CACF,QAAQ,MAAM,YAAY,MAAM,EAChC,UAAW,IAAM,KAAS,QAAQ,MAAO,CACvC,IAAM,EAAO,EAAoB,OAAO,CAAK,CAAC,EAC9C,GAAI,CAAC,EAAM,SACX,IAAM,EAAQ,OAAO,KAAK,EAAM,MAAM,EAClC,EAAU,EAAM,WAAa,IAC/B,EAAG,UAAU,CAAM,EACnB,EAAG,WAAW,EAAS,CAAW,EAClC,EAAS,EAAG,SAAS,EAAS,GAAG,EACjC,EAAU,EACV,GAAa,GAEf,EAAG,UAAU,EAAQ,CAAK,EAC1B,GAAW,EAAM,WACjB,GAAU,CACZ,CAUA,OATA,EAAG,UAAU,CAAM,EACnB,EAAU,CAAQ,EAClB,MAAM,EAAU,YAAY,iCAAkC,CAC5D,QAAS,YACT,qBAAsB,EACtB,uBAAwB,EACxB,wBAAyB,EACzB,YAAa,KAAK,IAAI,EAAI,CAC5B,CAAC,EACM,CACT,OAAS,EAAO,CAEd,MADA,MAAM,EAAU,YAAY,+BAAgC,EAAO,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,CAAC,EACpG,CACR,QAAU,CACR,MAAM,EAAU,SAAS,CAC3B,CACF,CAEA,SAAS,EAAU,EAAsB,CACvC,IAAM,EAAY,GAAG,EAAO,GAAG,QAAQ,IAAI,MAC3C,EAAG,cAAc,EAAW,GAAI,CAAE,KAAM,GAAM,CAAC,EAC/C,EAAG,WAAW,EAAW,CAAM,CACjC,CAEI,QAAQ,KAAK,IAAM,YAAY,MAAQ,EAAc,QAAQ,KAAK,EAAE,CAAC,CAAC,MACxE,EAAK,CAAC,CAAC,KACJ,GAAS,CACR,QAAQ,SAAW,CACrB,EACC,GAAmB,CAClB,QAAQ,OAAO,MAAM,GAAG,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EAAE,GAAG,EAClF,QAAQ,SAAW,CACrB,CACF"}
1
+ {"version":3,"file":"logSink.mjs","names":[],"sources":["../../src/bin/logSink.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { pathToFileURL } from 'node:url';\nimport { createDoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport { scrubTerminalOutput } from '../services/AnsiScrub/ansiScrub';\n\nexport async function main(argv: readonly string[] = process.argv.slice(2)): Promise<number> {\n const startedAt = Date.now();\n const telemetry = createDoomTelemetry({\n serviceName: 'doom-runner-log-sink',\n packageName: '@agimon-ai/doompi-runner',\n env: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n const [logPath, rotatedPath, maxBytesRaw, donePath] = argv;\n try {\n // Keep the legacy argument shape for the published executable subpath. Raw\n // logs are append-only now, so the former rotation path and ceiling are not used.\n if (!logPath || !rotatedPath || !maxBytesRaw || !donePath) {\n throw new Error('logSink requires log, rotated log, max bytes, and completion paths');\n }\n } catch (error) {\n await telemetry.recordError('doom_runner.file_sink_failed', error, { duration_ms: Date.now() - startedAt });\n await telemetry.shutdown();\n throw error;\n }\n\n let handle: number;\n let written: number;\n try {\n handle = fs.openSync(logPath, 'a');\n written = fs.statSync(logPath).size;\n } catch (error) {\n await telemetry.recordError('doom_runner.file_sink_failed', error, { duration_ms: Date.now() - startedAt });\n await telemetry.shutdown();\n throw error;\n }\n let chunks = 0;\n try {\n process.stdin.setEncoding('utf8');\n for await (const chunk of process.stdin) {\n const text = scrubTerminalOutput(String(chunk));\n if (!text) continue;\n const bytes = Buffer.from(text, 'utf8');\n fs.writeSync(handle, bytes);\n written += bytes.byteLength;\n chunks += 1;\n }\n fs.closeSync(handle);\n writeDone(donePath);\n await telemetry.recordEvent('doom_runner.file_sink_finished', {\n outcome: 'completed',\n 'runner.chunk_count': chunks,\n 'runner.bytes_written': written,\n duration_ms: Date.now() - startedAt,\n });\n return 0;\n } catch (error) {\n await telemetry.recordError('doom_runner.file_sink_failed', error, { duration_ms: Date.now() - startedAt });\n throw error;\n } finally {\n await telemetry.shutdown();\n }\n}\n\nfunction writeDone(target: string): void {\n const temporary = `${target}.${process.pid}.tmp`;\n fs.writeFileSync(temporary, '', { mode: 0o600 });\n fs.renameSync(temporary, target);\n}\n\nif (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {\n main().then(\n (code) => {\n process.exitCode = code;\n },\n (error: unknown) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n },\n );\n}\n"],"mappings":"gNAKA,eAAsB,EAAK,EAA0B,QAAQ,KAAK,MAAM,CAAC,EAAoB,CAC3F,IAAM,EAAY,KAAK,IAAI,EACrB,EAAY,EAAoB,CACpC,YAAa,uBACb,YAAa,2BACb,IAAK,QAAQ,IACb,WAAY,GACZ,aAAc,EAChB,CAAC,EACK,CAAC,EAAS,EAAa,EAAa,GAAY,EACtD,GAAI,CAGF,GAAI,CAAC,GAAW,CAAC,GAAe,CAAC,GAAe,CAAC,EAC/C,MAAU,MAAM,oEAAoE,CAExF,OAAS,EAAO,CAGd,MAFA,MAAM,EAAU,YAAY,+BAAgC,EAAO,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,CAAC,EAC1G,MAAM,EAAU,SAAS,EACnB,CACR,CAEA,IAAI,EACA,EACJ,GAAI,CACF,EAAS,EAAG,SAAS,EAAS,GAAG,EACjC,EAAU,EAAG,SAAS,CAAO,CAAC,CAAC,IACjC,OAAS,EAAO,CAGd,MAFA,MAAM,EAAU,YAAY,+BAAgC,EAAO,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,CAAC,EAC1G,MAAM,EAAU,SAAS,EACnB,CACR,CACA,IAAI,EAAS,EACb,GAAI,CACF,QAAQ,MAAM,YAAY,MAAM,EAChC,UAAW,IAAM,KAAS,QAAQ,MAAO,CACvC,IAAM,EAAO,EAAoB,OAAO,CAAK,CAAC,EAC9C,GAAI,CAAC,EAAM,SACX,IAAM,EAAQ,OAAO,KAAK,EAAM,MAAM,EACtC,EAAG,UAAU,EAAQ,CAAK,EAC1B,GAAW,EAAM,WACjB,GAAU,CACZ,CASA,OARA,EAAG,UAAU,CAAM,EACnB,EAAU,CAAQ,EAClB,MAAM,EAAU,YAAY,iCAAkC,CAC5D,QAAS,YACT,qBAAsB,EACtB,uBAAwB,EACxB,YAAa,KAAK,IAAI,EAAI,CAC5B,CAAC,EACM,CACT,OAAS,EAAO,CAEd,MADA,MAAM,EAAU,YAAY,+BAAgC,EAAO,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,CAAC,EACpG,CACR,QAAU,CACR,MAAM,EAAU,SAAS,CAC3B,CACF,CAEA,SAAS,EAAU,EAAsB,CACvC,IAAM,EAAY,GAAG,EAAO,GAAG,QAAQ,IAAI,MAC3C,EAAG,cAAc,EAAW,GAAI,CAAE,KAAM,GAAM,CAAC,EAC/C,EAAG,WAAW,EAAW,CAAM,CACjC,CAEI,QAAQ,KAAK,IAAM,YAAY,MAAQ,EAAc,QAAQ,KAAK,EAAE,CAAC,CAAC,MACxE,EAAK,CAAC,CAAC,KACJ,GAAS,CACR,QAAQ,SAAW,CACrB,EACC,GAAmB,CAClB,QAAQ,OAAO,MAAM,GAAG,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EAAE,GAAG,EAClF,QAAQ,SAAW,CACrB,CACF"}
package/dist/config.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./src/types/config.cjs");exports.BG_THRESHOLD_MS_ENV=e.BG_THRESHOLD_MS_ENV,exports.DEFAULT_BG_THRESHOLD_MS=e.DEFAULT_BG_THRESHOLD_MS,exports.DEFAULT_LOG_MAX_BYTES=e.DEFAULT_LOG_MAX_BYTES,exports.DEFAULT_LOG_TTL_MS=e.DEFAULT_LOG_TTL_MS,exports.DEFAULT_RESULT_MAX_BYTES=e.DEFAULT_RESULT_MAX_BYTES,exports.LOG_DIR_ENV=e.LOG_DIR_ENV,exports.LOG_MAX_BYTES_ENV=e.LOG_MAX_BYTES_ENV,exports.LOG_TTL_MS_ENV=e.LOG_TTL_MS_ENV,exports.RESULT_MAX_BYTES_ENV=e.RESULT_MAX_BYTES_ENV,exports.getBackgroundThresholdMs=e.getBackgroundThresholdMs,exports.getLogMaxBytes=e.getLogMaxBytes,exports.getLogTtlMs=e.getLogTtlMs,exports.getResultMaxBytes=e.getResultMaxBytes;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./src/types/config.cjs");exports.BG_THRESHOLD_MS_ENV=e.BG_THRESHOLD_MS_ENV,exports.DEFAULT_BG_THRESHOLD_MS=e.DEFAULT_BG_THRESHOLD_MS,exports.DEFAULT_ERROR_BUDGET_RATIO=e.DEFAULT_ERROR_BUDGET_RATIO,exports.DEFAULT_ERROR_MAX_ENTRIES=e.DEFAULT_ERROR_MAX_ENTRIES,exports.DEFAULT_ERROR_MAX_VARIANTS_JOINED=e.DEFAULT_ERROR_MAX_VARIANTS_JOINED,exports.DEFAULT_HEAD_RATIO=e.DEFAULT_HEAD_RATIO,exports.DEFAULT_LOG_MAX_BYTES=e.DEFAULT_LOG_MAX_BYTES,exports.DEFAULT_LOG_TTL_MS=e.DEFAULT_LOG_TTL_MS,exports.DEFAULT_RESULT_MAX_BYTES=e.DEFAULT_RESULT_MAX_BYTES,exports.DEFAULT_RESULT_MAX_LINES=e.DEFAULT_RESULT_MAX_LINES,exports.DEFAULT_RESULT_MAX_TOKENS=e.DEFAULT_RESULT_MAX_TOKENS,exports.DEFAULT_SUCCESS_RESULT_MAX_BYTES=e.DEFAULT_SUCCESS_RESULT_MAX_BYTES,exports.DEFAULT_SUCCESS_RESULT_MAX_TOKENS=e.DEFAULT_SUCCESS_RESULT_MAX_TOKENS,exports.LOG_DIR_ENV=e.LOG_DIR_ENV,exports.LOG_MAX_BYTES_ENV=e.LOG_MAX_BYTES_ENV,exports.LOG_TTL_MS_ENV=e.LOG_TTL_MS_ENV,exports.RESULT_MAX_BYTES_ENV=e.RESULT_MAX_BYTES_ENV,exports.RESULT_MAX_TOKENS_ENV=e.RESULT_MAX_TOKENS_ENV,exports.SUCCESS_RESULT_MAX_BYTES_ENV=e.SUCCESS_RESULT_MAX_BYTES_ENV,exports.SUCCESS_RESULT_MAX_TOKENS_ENV=e.SUCCESS_RESULT_MAX_TOKENS_ENV,exports.getBackgroundThresholdMs=e.getBackgroundThresholdMs,exports.getErrorBudgetRatio=e.getErrorBudgetRatio,exports.getErrorMaxEntries=e.getErrorMaxEntries,exports.getErrorMaxVariantsJoined=e.getErrorMaxVariantsJoined,exports.getErrorPatterns=e.getErrorPatterns,exports.getHeadRatio=e.getHeadRatio,exports.getLogMaxBytes=e.getLogMaxBytes,exports.getLogTtlMs=e.getLogTtlMs,exports.getResultMaxBytes=e.getResultMaxBytes,exports.getResultMaxLines=e.getResultMaxLines,exports.getResultMaxTokens=e.getResultMaxTokens,exports.getRunnerSettings=e.getRunnerSettings,exports.getSuccessResultMaxBytes=e.getSuccessResultMaxBytes,exports.getSuccessResultMaxTokens=e.getSuccessResultMaxTokens,exports.setRunnerSettings=e.setRunnerSettings;
package/dist/config.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { BG_THRESHOLD_MS_ENV, DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, LOG_DIR_ENV, LOG_MAX_BYTES_ENV, LOG_TTL_MS_ENV, RESULT_MAX_BYTES_ENV, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes } from "./src/types/config.cjs";
2
- export { BG_THRESHOLD_MS_ENV, DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, LOG_DIR_ENV, LOG_MAX_BYTES_ENV, LOG_TTL_MS_ENV, RESULT_MAX_BYTES_ENV, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes };
1
+ import { BG_THRESHOLD_MS_ENV, DEFAULT_BG_THRESHOLD_MS, DEFAULT_ERROR_BUDGET_RATIO, DEFAULT_ERROR_MAX_ENTRIES, DEFAULT_ERROR_MAX_VARIANTS_JOINED, DEFAULT_HEAD_RATIO, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, DEFAULT_RESULT_MAX_LINES, DEFAULT_RESULT_MAX_TOKENS, DEFAULT_SUCCESS_RESULT_MAX_BYTES, DEFAULT_SUCCESS_RESULT_MAX_TOKENS, LOG_DIR_ENV, LOG_MAX_BYTES_ENV, LOG_TTL_MS_ENV, RESULT_MAX_BYTES_ENV, RESULT_MAX_TOKENS_ENV, SUCCESS_RESULT_MAX_BYTES_ENV, SUCCESS_RESULT_MAX_TOKENS_ENV, getBackgroundThresholdMs, getErrorBudgetRatio, getErrorMaxEntries, getErrorMaxVariantsJoined, getErrorPatterns, getHeadRatio, getLogMaxBytes, getLogTtlMs, getResultMaxBytes, getResultMaxLines, getResultMaxTokens, getRunnerSettings, getSuccessResultMaxBytes, getSuccessResultMaxTokens, setRunnerSettings } from "./src/types/config.cjs";
2
+ export { BG_THRESHOLD_MS_ENV, DEFAULT_BG_THRESHOLD_MS, DEFAULT_ERROR_BUDGET_RATIO, DEFAULT_ERROR_MAX_ENTRIES, DEFAULT_ERROR_MAX_VARIANTS_JOINED, DEFAULT_HEAD_RATIO, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, DEFAULT_RESULT_MAX_LINES, DEFAULT_RESULT_MAX_TOKENS, DEFAULT_SUCCESS_RESULT_MAX_BYTES, DEFAULT_SUCCESS_RESULT_MAX_TOKENS, LOG_DIR_ENV, LOG_MAX_BYTES_ENV, LOG_TTL_MS_ENV, RESULT_MAX_BYTES_ENV, RESULT_MAX_TOKENS_ENV, SUCCESS_RESULT_MAX_BYTES_ENV, SUCCESS_RESULT_MAX_TOKENS_ENV, getBackgroundThresholdMs, getErrorBudgetRatio, getErrorMaxEntries, getErrorMaxVariantsJoined, getErrorPatterns, getHeadRatio, getLogMaxBytes, getLogTtlMs, getResultMaxBytes, getResultMaxLines, getResultMaxTokens, getRunnerSettings, getSuccessResultMaxBytes, getSuccessResultMaxTokens, setRunnerSettings };
package/dist/config.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { BG_THRESHOLD_MS_ENV, DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, LOG_DIR_ENV, LOG_MAX_BYTES_ENV, LOG_TTL_MS_ENV, RESULT_MAX_BYTES_ENV, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes } from "./src/types/config.mjs";
2
- export { BG_THRESHOLD_MS_ENV, DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, LOG_DIR_ENV, LOG_MAX_BYTES_ENV, LOG_TTL_MS_ENV, RESULT_MAX_BYTES_ENV, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes };
1
+ import { BG_THRESHOLD_MS_ENV, DEFAULT_BG_THRESHOLD_MS, DEFAULT_ERROR_BUDGET_RATIO, DEFAULT_ERROR_MAX_ENTRIES, DEFAULT_ERROR_MAX_VARIANTS_JOINED, DEFAULT_HEAD_RATIO, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, DEFAULT_RESULT_MAX_LINES, DEFAULT_RESULT_MAX_TOKENS, DEFAULT_SUCCESS_RESULT_MAX_BYTES, DEFAULT_SUCCESS_RESULT_MAX_TOKENS, LOG_DIR_ENV, LOG_MAX_BYTES_ENV, LOG_TTL_MS_ENV, RESULT_MAX_BYTES_ENV, RESULT_MAX_TOKENS_ENV, SUCCESS_RESULT_MAX_BYTES_ENV, SUCCESS_RESULT_MAX_TOKENS_ENV, getBackgroundThresholdMs, getErrorBudgetRatio, getErrorMaxEntries, getErrorMaxVariantsJoined, getErrorPatterns, getHeadRatio, getLogMaxBytes, getLogTtlMs, getResultMaxBytes, getResultMaxLines, getResultMaxTokens, getRunnerSettings, getSuccessResultMaxBytes, getSuccessResultMaxTokens, setRunnerSettings } from "./src/types/config.mjs";
2
+ export { BG_THRESHOLD_MS_ENV, DEFAULT_BG_THRESHOLD_MS, DEFAULT_ERROR_BUDGET_RATIO, DEFAULT_ERROR_MAX_ENTRIES, DEFAULT_ERROR_MAX_VARIANTS_JOINED, DEFAULT_HEAD_RATIO, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, DEFAULT_RESULT_MAX_LINES, DEFAULT_RESULT_MAX_TOKENS, DEFAULT_SUCCESS_RESULT_MAX_BYTES, DEFAULT_SUCCESS_RESULT_MAX_TOKENS, LOG_DIR_ENV, LOG_MAX_BYTES_ENV, LOG_TTL_MS_ENV, RESULT_MAX_BYTES_ENV, RESULT_MAX_TOKENS_ENV, SUCCESS_RESULT_MAX_BYTES_ENV, SUCCESS_RESULT_MAX_TOKENS_ENV, getBackgroundThresholdMs, getErrorBudgetRatio, getErrorMaxEntries, getErrorMaxVariantsJoined, getErrorPatterns, getHeadRatio, getLogMaxBytes, getLogTtlMs, getResultMaxBytes, getResultMaxLines, getResultMaxTokens, getRunnerSettings, getSuccessResultMaxBytes, getSuccessResultMaxTokens, setRunnerSettings };
package/dist/config.mjs CHANGED
@@ -1 +1 @@
1
- import{BG_THRESHOLD_MS_ENV as e,DEFAULT_BG_THRESHOLD_MS as t,DEFAULT_LOG_MAX_BYTES as n,DEFAULT_LOG_TTL_MS as r,DEFAULT_RESULT_MAX_BYTES as i,LOG_DIR_ENV as a,LOG_MAX_BYTES_ENV as o,LOG_TTL_MS_ENV as s,RESULT_MAX_BYTES_ENV as c,getBackgroundThresholdMs as l,getLogMaxBytes as u,getLogTtlMs as d,getResultMaxBytes as f}from"./src/types/config.mjs";export{e as BG_THRESHOLD_MS_ENV,t as DEFAULT_BG_THRESHOLD_MS,n as DEFAULT_LOG_MAX_BYTES,r as DEFAULT_LOG_TTL_MS,i as DEFAULT_RESULT_MAX_BYTES,a as LOG_DIR_ENV,o as LOG_MAX_BYTES_ENV,s as LOG_TTL_MS_ENV,c as RESULT_MAX_BYTES_ENV,l as getBackgroundThresholdMs,u as getLogMaxBytes,d as getLogTtlMs,f as getResultMaxBytes};
1
+ import{BG_THRESHOLD_MS_ENV as e,DEFAULT_BG_THRESHOLD_MS as t,DEFAULT_ERROR_BUDGET_RATIO as n,DEFAULT_ERROR_MAX_ENTRIES as r,DEFAULT_ERROR_MAX_VARIANTS_JOINED as i,DEFAULT_HEAD_RATIO as a,DEFAULT_LOG_MAX_BYTES as o,DEFAULT_LOG_TTL_MS as s,DEFAULT_RESULT_MAX_BYTES as c,DEFAULT_RESULT_MAX_LINES as l,DEFAULT_RESULT_MAX_TOKENS as u,DEFAULT_SUCCESS_RESULT_MAX_BYTES as d,DEFAULT_SUCCESS_RESULT_MAX_TOKENS as f,LOG_DIR_ENV as p,LOG_MAX_BYTES_ENV as m,LOG_TTL_MS_ENV as h,RESULT_MAX_BYTES_ENV as g,RESULT_MAX_TOKENS_ENV as _,SUCCESS_RESULT_MAX_BYTES_ENV as v,SUCCESS_RESULT_MAX_TOKENS_ENV as y,getBackgroundThresholdMs as b,getErrorBudgetRatio as x,getErrorMaxEntries as S,getErrorMaxVariantsJoined as C,getErrorPatterns as w,getHeadRatio as T,getLogMaxBytes as E,getLogTtlMs as D,getResultMaxBytes as O,getResultMaxLines as k,getResultMaxTokens as A,getRunnerSettings as j,getSuccessResultMaxBytes as M,getSuccessResultMaxTokens as N,setRunnerSettings as P}from"./src/types/config.mjs";export{e as BG_THRESHOLD_MS_ENV,t as DEFAULT_BG_THRESHOLD_MS,n as DEFAULT_ERROR_BUDGET_RATIO,r as DEFAULT_ERROR_MAX_ENTRIES,i as DEFAULT_ERROR_MAX_VARIANTS_JOINED,a as DEFAULT_HEAD_RATIO,o as DEFAULT_LOG_MAX_BYTES,s as DEFAULT_LOG_TTL_MS,c as DEFAULT_RESULT_MAX_BYTES,l as DEFAULT_RESULT_MAX_LINES,u as DEFAULT_RESULT_MAX_TOKENS,d as DEFAULT_SUCCESS_RESULT_MAX_BYTES,f as DEFAULT_SUCCESS_RESULT_MAX_TOKENS,p as LOG_DIR_ENV,m as LOG_MAX_BYTES_ENV,h as LOG_TTL_MS_ENV,g as RESULT_MAX_BYTES_ENV,_ as RESULT_MAX_TOKENS_ENV,v as SUCCESS_RESULT_MAX_BYTES_ENV,y as SUCCESS_RESULT_MAX_TOKENS_ENV,b as getBackgroundThresholdMs,x as getErrorBudgetRatio,S as getErrorMaxEntries,C as getErrorMaxVariantsJoined,w as getErrorPatterns,T as getHeadRatio,E as getLogMaxBytes,D as getLogTtlMs,O as getResultMaxBytes,k as getResultMaxLines,A as getResultMaxTokens,j as getRunnerSettings,M as getSuccessResultMaxBytes,N as getSuccessResultMaxTokens,P as setRunnerSettings};
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./src/types/config.cjs"),t=require("./src/adapters/RmuxBackend/RmuxBackend.cjs"),n=require("./src/container/index.cjs");exports.DEFAULT_BG_THRESHOLD_MS=e.DEFAULT_BG_THRESHOLD_MS,exports.DEFAULT_LOG_MAX_BYTES=e.DEFAULT_LOG_MAX_BYTES,exports.DEFAULT_LOG_TTL_MS=e.DEFAULT_LOG_TTL_MS,exports.DEFAULT_RESULT_MAX_BYTES=e.DEFAULT_RESULT_MAX_BYTES,exports.RmuxBackend=t.RmuxBackend,exports.createRunnerContainer=n.createRunnerContainer,exports.getBackgroundThresholdMs=e.getBackgroundThresholdMs,exports.getLogMaxBytes=e.getLogMaxBytes,exports.getLogTtlMs=e.getLogTtlMs,exports.getResultMaxBytes=e.getResultMaxBytes;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./src/types/config.cjs"),t=require("./src/adapters/RmuxBackend/RmuxBackend.cjs"),n=require("./src/adapters/RtkProcessor/RtkProcessor.cjs"),r=require("./src/container/index.cjs");exports.DEFAULT_BG_THRESHOLD_MS=e.DEFAULT_BG_THRESHOLD_MS,exports.DEFAULT_LOG_MAX_BYTES=e.DEFAULT_LOG_MAX_BYTES,exports.DEFAULT_LOG_TTL_MS=e.DEFAULT_LOG_TTL_MS,exports.DEFAULT_RESULT_MAX_BYTES=e.DEFAULT_RESULT_MAX_BYTES,exports.RmuxBackend=t.RmuxBackend,exports.createRunnerContainer=r.createRunnerContainer,exports.getBackgroundThresholdMs=e.getBackgroundThresholdMs,exports.getLogMaxBytes=e.getLogMaxBytes,exports.getLogTtlMs=e.getLogTtlMs,exports.getResultMaxBytes=e.getResultMaxBytes,exports.rtkPackageForTarget=n.rtkPackageForTarget;
package/dist/index.d.cts CHANGED
@@ -2,4 +2,5 @@ import { IRmuxBackend, RmuxLaunchRequest } from "./src/types/rmuxBackend.cjs";
2
2
  import { DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes } from "./src/types/config.cjs";
3
3
  import { createRunnerContainer } from "./src/container/index.cjs";
4
4
  import { RmuxBackend } from "./src/adapters/RmuxBackend/RmuxBackend.cjs";
5
- export { DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, type IRmuxBackend, RmuxBackend, type RmuxLaunchRequest, createRunnerContainer, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes };
5
+ import { rtkPackageForTarget } from "./src/adapters/RtkProcessor/RtkProcessor.cjs";
6
+ export { DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, type IRmuxBackend, RmuxBackend, type RmuxLaunchRequest, createRunnerContainer, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes, rtkPackageForTarget };
package/dist/index.d.mts CHANGED
@@ -2,4 +2,5 @@ import { IRmuxBackend, RmuxLaunchRequest } from "./src/types/rmuxBackend.mjs";
2
2
  import { DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes } from "./src/types/config.mjs";
3
3
  import { createRunnerContainer } from "./src/container/index.mjs";
4
4
  import { RmuxBackend } from "./src/adapters/RmuxBackend/RmuxBackend.mjs";
5
- export { DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, type IRmuxBackend, RmuxBackend, type RmuxLaunchRequest, createRunnerContainer, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes };
5
+ import { rtkPackageForTarget } from "./src/adapters/RtkProcessor/RtkProcessor.mjs";
6
+ export { DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, type IRmuxBackend, RmuxBackend, type RmuxLaunchRequest, createRunnerContainer, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes, rtkPackageForTarget };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{DEFAULT_BG_THRESHOLD_MS as e,DEFAULT_LOG_MAX_BYTES as t,DEFAULT_LOG_TTL_MS as n,DEFAULT_RESULT_MAX_BYTES as r,getBackgroundThresholdMs as i,getLogMaxBytes as a,getLogTtlMs as o,getResultMaxBytes as s}from"./src/types/config.mjs";import{RmuxBackend as c}from"./src/adapters/RmuxBackend/RmuxBackend.mjs";import{createRunnerContainer as l}from"./src/container/index.mjs";export{e as DEFAULT_BG_THRESHOLD_MS,t as DEFAULT_LOG_MAX_BYTES,n as DEFAULT_LOG_TTL_MS,r as DEFAULT_RESULT_MAX_BYTES,c as RmuxBackend,l as createRunnerContainer,i as getBackgroundThresholdMs,a as getLogMaxBytes,o as getLogTtlMs,s as getResultMaxBytes};
1
+ import{DEFAULT_BG_THRESHOLD_MS as e,DEFAULT_LOG_MAX_BYTES as t,DEFAULT_LOG_TTL_MS as n,DEFAULT_RESULT_MAX_BYTES as r,getBackgroundThresholdMs as i,getLogMaxBytes as a,getLogTtlMs as o,getResultMaxBytes as s}from"./src/types/config.mjs";import{RmuxBackend as c}from"./src/adapters/RmuxBackend/RmuxBackend.mjs";import{rtkPackageForTarget as l}from"./src/adapters/RtkProcessor/RtkProcessor.mjs";import{createRunnerContainer as u}from"./src/container/index.mjs";export{e as DEFAULT_BG_THRESHOLD_MS,t as DEFAULT_LOG_MAX_BYTES,n as DEFAULT_LOG_TTL_MS,r as DEFAULT_RESULT_MAX_BYTES,c as RmuxBackend,u as createRunnerContainer,i as getBackgroundThresholdMs,a as getLogMaxBytes,o as getLogTtlMs,s as getResultMaxBytes,l as rtkPackageForTarget};
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../src/adapters/RtkProcessor/RtkProcessor.cjs");exports.RTK_STDIN_MAX_BYTES=e.RTK_STDIN_MAX_BYTES,exports.RtkProcessor=e.RtkProcessor,exports.classifyRtkFilter=e.classifyRtkFilter,exports.rtkPackageForTarget=e.rtkPackageForTarget;
@@ -0,0 +1,2 @@
1
+ import { RTK_STDIN_MAX_BYTES, RtkProcessor, classifyRtkFilter, rtkPackageForTarget } from "../../src/adapters/RtkProcessor/RtkProcessor.cjs";
2
+ export { RTK_STDIN_MAX_BYTES, RtkProcessor, classifyRtkFilter, rtkPackageForTarget };
@@ -0,0 +1,2 @@
1
+ import { RTK_STDIN_MAX_BYTES, RtkProcessor, classifyRtkFilter, rtkPackageForTarget } from "../../src/adapters/RtkProcessor/RtkProcessor.mjs";
2
+ export { RTK_STDIN_MAX_BYTES, RtkProcessor, classifyRtkFilter, rtkPackageForTarget };
@@ -0,0 +1 @@
1
+ import{RTK_STDIN_MAX_BYTES as e,RtkProcessor as t,classifyRtkFilter as n,rtkPackageForTarget as r}from"../../src/adapters/RtkProcessor/RtkProcessor.mjs";export{e as RTK_STDIN_MAX_BYTES,t as RtkProcessor,n as classifyRtkFilter,r as rtkPackageForTarget};
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../src/types/rtkProcessor.cjs"),t=require("../../src/adapters/RtkProcessor/RtkProcessor.cjs");exports.RTK_FAILED_WARNING=e.RTK_FAILED_WARNING,exports.RTK_OVERSIZED_WARNING=e.RTK_OVERSIZED_WARNING,exports.RTK_STDIN_MAX_BYTES=t.RTK_STDIN_MAX_BYTES,exports.RTK_TIMEOUT_WARNING=e.RTK_TIMEOUT_WARNING,exports.RTK_UNAVAILABLE_WARNING=e.RTK_UNAVAILABLE_WARNING,exports.RtkProcessor=t.RtkProcessor,exports.classifyRtkFilter=t.classifyRtkFilter,exports.rtkPackageForTarget=t.rtkPackageForTarget;
@@ -0,0 +1,3 @@
1
+ import { IRtkProcessor, RTK_FAILED_WARNING, RTK_OVERSIZED_WARNING, RTK_TIMEOUT_WARNING, RTK_UNAVAILABLE_WARNING, RtkFilter, RtkProcessRequest, RtkProcessResult, RtkProcessedOutput } from "../../src/types/rtkProcessor.cjs";
2
+ import { RTK_STDIN_MAX_BYTES, RtkProcessor, classifyRtkFilter, rtkPackageForTarget } from "../../src/adapters/RtkProcessor/RtkProcessor.cjs";
3
+ export { type IRtkProcessor, RTK_FAILED_WARNING, RTK_OVERSIZED_WARNING, RTK_STDIN_MAX_BYTES, RTK_TIMEOUT_WARNING, RTK_UNAVAILABLE_WARNING, type RtkFilter, type RtkProcessRequest, type RtkProcessResult, type RtkProcessedOutput, RtkProcessor, classifyRtkFilter, rtkPackageForTarget };
@@ -0,0 +1,3 @@
1
+ import { IRtkProcessor, RTK_FAILED_WARNING, RTK_OVERSIZED_WARNING, RTK_TIMEOUT_WARNING, RTK_UNAVAILABLE_WARNING, RtkFilter, RtkProcessRequest, RtkProcessResult, RtkProcessedOutput } from "../../src/types/rtkProcessor.mjs";
2
+ import { RTK_STDIN_MAX_BYTES, RtkProcessor, classifyRtkFilter, rtkPackageForTarget } from "../../src/adapters/RtkProcessor/RtkProcessor.mjs";
3
+ export { type IRtkProcessor, RTK_FAILED_WARNING, RTK_OVERSIZED_WARNING, RTK_STDIN_MAX_BYTES, RTK_TIMEOUT_WARNING, RTK_UNAVAILABLE_WARNING, type RtkFilter, type RtkProcessRequest, type RtkProcessResult, type RtkProcessedOutput, RtkProcessor, classifyRtkFilter, rtkPackageForTarget };
@@ -0,0 +1 @@
1
+ import{RTK_FAILED_WARNING as e,RTK_OVERSIZED_WARNING as t,RTK_TIMEOUT_WARNING as n,RTK_UNAVAILABLE_WARNING as r}from"../../src/types/rtkProcessor.mjs";import{RTK_STDIN_MAX_BYTES as i,RtkProcessor as a,classifyRtkFilter as o,rtkPackageForTarget as s}from"../../src/adapters/RtkProcessor/RtkProcessor.mjs";export{e as RTK_FAILED_WARNING,t as RTK_OVERSIZED_WARNING,i as RTK_STDIN_MAX_BYTES,n as RTK_TIMEOUT_WARNING,r as RTK_UNAVAILABLE_WARNING,a as RtkProcessor,o as classifyRtkFilter,s as rtkPackageForTarget};
@@ -1,2 +1,2 @@
1
- const e=require("../../types/config.cjs");let t=require("node:crypto");const n=Symbol(`threshold-reached`),r=Symbol(`deadline-reached`),i=`completed`,a=`failed`,o=`launcher_error`,s=`signaled`;function c(){return`${Date.now().toString(36)}-${(0,t.randomBytes)(3).toString(`base64url`)}`}var l=class{launcher;rmuxBackend;ptyHost;namer;registry;clock;constructor(e,t,n,r,i,a){this.launcher=e,this.rmuxBackend=t,this.ptyHost=n,this.namer=r,this.registry=i,this.clock=a}async run(e){let t=c(),l=await this.namer.allocate(e.command,e.sessionId,e.name),u=e.cwd??process.cwd(),d=e.interactive===!0,f;try{f=await this.rmuxBackend.launch({id:t,name:l,command:e.command,cwd:u,sessionId:e.sessionId,interactive:d})??(d?await this.ptyHost.launch({id:t,name:l,command:e.command,cwd:u,sessionId:e.sessionId}):this.launcher.launch({id:t,name:l,command:e.command,cwd:u,sessionId:e.sessionId}))}catch(e){return{kind:a,id:t,name:l,error:e instanceof Error?e.message:String(e)}}if(f.pid===void 0)return{kind:a,id:t,name:l,error:`The command did not start, so it cannot be supervised`};try{await this.registry.register({id:t,name:l,pid:f.pid,command:e.command,cwd:u,logPath:f.logPath,interactive:d,sessionId:e.sessionId,backend:f.backend,...f.backendTarget?{backendTarget:f.backendTarget}:{}})}catch(e){return await f.stop(),{kind:a,id:t,name:l,error:e instanceof Error?e.message:String(e)}}if(e.background===!0||d)return this.promote(f,e.background===!0?`requested`:`interactive`);let p=e.onOutput?this.followOutput(f,e.onOutput):void 0;try{let c=await this.race(f,e.timeoutMs);return p?.flush(),c===n?this.promote(f,`threshold`):c===r?(await f.stop(),p?.flush(),await this.registry.complete(t,{reason:`timed_out`,code:null,signal:`SIGTERM`}),{kind:i,id:t,name:l,output:f.output(),exitCode:null,signal:`SIGTERM`,logPath:f.logPath,backend:f.backend,timedOut:!0}):c instanceof Error?(await this.registry.complete(t,{reason:o,code:null,signal:null}),{kind:a,id:t,name:l,error:c.message}):(await this.registry.complete(t,{reason:c.signal?s:c.code===0?i:a,code:c.code,signal:c.signal}),{kind:i,id:t,name:l,output:f.output(),exitCode:c.code,signal:c.signal,logPath:f.logPath,backend:f.backend})}finally{p?.dispose()}}followOutput(e,t){let n=!0,r=``,i,a=()=>{if(!n)return;let i=e.output();i!==r&&(r=i,t(i))},o=()=>{n&&(a(),n&&(i=this.clock.after(100,o)))};return i=this.clock.after(100,o),{flush:a,dispose:()=>{n=!1,i?.(),i=void 0}}}async race(t,i){let a=[],o=[t.completion().catch(e=>e)];o.push(new Promise(t=>{a.push(this.clock.after(e.getBackgroundThresholdMs(),()=>t(n)))})),i!==void 0&&i>0&&o.push(new Promise(e=>{a.push(this.clock.after(i,()=>e(r)))}));try{return await Promise.race(o)}finally{for(let e of a)e()}}async promote(e,t){return e.pid===void 0?{kind:a,id:e.id,name:e.name,error:`The command did not start`}:(await this.registry.markPromoted(e.id),e.detach(),e.completion().then(t=>this.registry.complete(e.id,{reason:t.signal?s:t.code===0?i:a,code:t.code,signal:t.signal}),()=>this.registry.complete(e.id,{reason:o,code:null,signal:null})).catch(t=>{let n=t instanceof Error?t.message:String(t);process.emitWarning(`Failed to complete runner ${e.id}: ${n}`)}),{kind:`promoted`,id:e.id,name:e.name,pid:e.pid,logPath:e.logPath,backend:e.backend,reason:t})}};exports.BashRunService=l;
1
+ const e=require("../../types/config.cjs"),t=require("../../types/rtkProcessor.cjs");let n=require("node:crypto");const r=Symbol(`threshold-reached`),i=Symbol(`deadline-reached`),a=`completed`,o=`failed`,s=`launcher_error`,c=`signaled`;function l(){return`${Date.now().toString(36)}-${(0,n.randomBytes)(3).toString(`base64url`)}`}var u=class{launcher;rmuxBackend;namer;registry;clock;rtkProcessor;constructor(e,t,n,r,i,a){this.launcher=e,this.rmuxBackend=t,this.namer=n,this.registry=r,this.clock=i,this.rtkProcessor=a}async run(e){let t=l(),n=await this.namer.allocate(e.command,e.sessionId,e.name),u=e.cwd??process.cwd(),d=e.interactive===!0,f;try{let r=await this.rmuxBackend.launch({id:t,name:n,command:e.command,cwd:u,sessionId:e.sessionId,interactive:d});if(d&&!r)return{kind:o,id:t,name:n,error:`RMUX is required for interactive commands but is unavailable`};f=r??this.launcher.launch({id:t,name:n,command:e.command,cwd:u,sessionId:e.sessionId})}catch(e){return{kind:o,id:t,name:n,error:e instanceof Error?e.message:String(e)}}if(f.pid===void 0)return{kind:o,id:t,name:n,error:`The command did not start, so it cannot be supervised`};try{await this.registry.register({id:t,name:n,pid:f.pid,command:e.command,cwd:u,logPath:f.logPath,interactive:d,sessionId:e.sessionId,backend:f.backend,...f.backendTarget?{backendTarget:f.backendTarget}:{}})}catch(e){return await f.stop(),{kind:o,id:t,name:n,error:e instanceof Error?e.message:String(e)}}if(e.background===!0||d)return this.promote(f,e.background===!0?`requested`:`interactive`);let p=e.onOutput?this.followOutput(f,e.onOutput):void 0;try{let l=await this.race(f,e.timeoutMs);return p?.flush(),l===r?this.promote(f,`threshold`):l===i?(await f.stop(),p?.flush(),await this.registry.complete(t,{reason:`timed_out`,code:null,signal:`SIGTERM`}),{kind:a,id:t,name:n,output:f.output(),exitCode:null,signal:`SIGTERM`,logPath:f.logPath,backend:f.backend,timedOut:!0}):l instanceof Error?(await this.registry.complete(t,{reason:s,code:null,signal:null}),{kind:o,id:t,name:n,error:l.message}):(await this.registry.complete(t,{reason:l.signal?c:l.code===0?a:o,code:l.code,signal:l.signal}),{kind:a,id:t,name:n,output:f.output(),exitCode:l.code,signal:l.signal,logPath:f.logPath,backend:f.backend,...await this.processLog(e.command,f.logPath)})}finally{p?.dispose()}}async processLog(e,n){try{let t=await this.rtkProcessor.process({command:e,logPath:n});return t.kind===`processed`?{rtkOutput:t.result}:t.kind===`fallback`?{rtkWarning:t.warning}:{}}catch{return{rtkWarning:t.RTK_FAILED_WARNING}}}followOutput(e,t){let n=!0,r=``,i,a=()=>{if(!n)return;let i=e.output();i!==r&&(r=i,t(i))},o=()=>{n&&(a(),n&&(i=this.clock.after(100,o)))};return i=this.clock.after(100,o),{flush:a,dispose:()=>{n=!1,i?.(),i=void 0}}}async race(t,n){let a=[],o=[t.completion().catch(e=>e)];o.push(new Promise(t=>{a.push(this.clock.after(e.getBackgroundThresholdMs(),()=>t(r)))})),n!==void 0&&n>0&&o.push(new Promise(e=>{a.push(this.clock.after(n,()=>e(i)))}));try{return await Promise.race(o)}finally{for(let e of a)e()}}async promote(e,t){return e.pid===void 0?{kind:o,id:e.id,name:e.name,error:`The command did not start`}:(await this.registry.markPromoted(e.id),e.detach(),e.completion().then(t=>this.registry.complete(e.id,{reason:t.signal?c:t.code===0?a:o,code:t.code,signal:t.signal}),()=>this.registry.complete(e.id,{reason:s,code:null,signal:null})).catch(t=>{let n=t instanceof Error?t.message:String(t);process.emitWarning(`Failed to complete runner ${e.id}: ${n}`)}),{kind:`promoted`,id:e.id,name:e.name,pid:e.pid,logPath:e.logPath,backend:e.backend,reason:t})}};exports.BashRunService=u;
2
2
  //# sourceMappingURL=BashRunService.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"BashRunService.cjs","names":["randomBytes","getBackgroundThresholdMs"],"sources":["../../../../src/adapters/BashRunService/BashRunService.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { getBackgroundThresholdMs } from '../../types/config.ts';\nimport type { IClock } from '../../types/clock';\nimport type { ILauncher, RunHandle } from '../../types/launcher';\nimport type { IPtyHost } from '../../types/ptyHost';\nimport type { IRmuxBackend } from '../../types/rmuxBackend';\nimport type { IRunnerNamer } from '../../services/RunnerNamer/types';\nimport type { IRunnerRegistry } from '../../types/runnerRegistry';\nimport type { BashRunRequest, BashRunResult, IBashRunService, PromotedRun } from '../../types/bashRunService';\n\n/** The command outlived the background threshold and should be promoted. */\nconst TIMED_OUT = Symbol('threshold-reached');\n/** The command outlived the caller's explicit timeout and should be stopped. */\nconst DEADLINE = Symbol('deadline-reached');\nconst RUNNER_ID_RANDOM_BYTES = 3;\nconst OUTPUT_UPDATE_POLL_MS = 100;\nconst COMPLETED = 'completed';\nconst FAILED = 'failed';\nconst LAUNCHER_ERROR = 'launcher_error';\nconst SIGNALED = 'signaled';\n\nfunction runnerId(): string {\n const timestamp = Date.now().toString(36);\n const random = randomBytes(RUNNER_ID_RANDOM_BYTES).toString('base64url');\n return `${timestamp}-${random}`;\n}\n\nexport class BashRunService implements IBashRunService {\n constructor(\n private readonly launcher: ILauncher,\n private readonly rmuxBackend: IRmuxBackend,\n private readonly ptyHost: IPtyHost,\n private readonly namer: IRunnerNamer,\n private readonly registry: IRunnerRegistry,\n private readonly clock: IClock,\n ) {}\n\n async run(request: BashRunRequest): Promise<BashRunResult> {\n const id = runnerId();\n const name = await this.namer.allocate(request.command, request.sessionId, request.name);\n const cwd = request.cwd ?? process.cwd();\n const interactive = request.interactive === true;\n\n let handle: RunHandle;\n try {\n const rmuxHandle = await this.rmuxBackend.launch({\n id,\n name,\n command: request.command,\n cwd,\n sessionId: request.sessionId,\n interactive,\n });\n handle =\n rmuxHandle ??\n (interactive\n ? await this.ptyHost.launch({ id, name, command: request.command, cwd, sessionId: request.sessionId })\n : this.launcher.launch({ id, name, command: request.command, cwd, sessionId: request.sessionId }));\n } catch (error) {\n // Loading node-pty is the one launch step that can fail before a process\n // exists, and it must not take the whole tool call down.\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n\n if (handle.pid === undefined) {\n return { kind: FAILED, id, name, error: 'The command did not start, so it cannot be supervised' };\n }\n\n try {\n await this.registry.register({\n id,\n name,\n pid: handle.pid,\n command: request.command,\n cwd,\n logPath: handle.logPath,\n interactive,\n sessionId: request.sessionId,\n backend: handle.backend,\n ...(handle.backendTarget ? { backendTarget: handle.backendTarget } : {}),\n });\n } catch (error) {\n await handle.stop();\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n\n // An interactive run has nothing to wait for: it is going to prompt, so\n // the model needs the runner name before it can answer.\n if (request.background === true || interactive) {\n return this.promote(handle, request.background === true ? 'requested' : 'interactive');\n }\n\n const outputUpdates = request.onOutput ? this.followOutput(handle, request.onOutput) : undefined;\n try {\n const outcome = await this.race(handle, request.timeoutMs);\n outputUpdates?.flush();\n if (outcome === TIMED_OUT) {\n return this.promote(handle, 'threshold');\n }\n if (outcome === DEADLINE) {\n // An explicit timeout means the caller wants the command dead, not\n // supervised, so it is stopped rather than promoted.\n await handle.stop();\n outputUpdates?.flush();\n await this.registry.complete(id, { reason: 'timed_out', code: null, signal: 'SIGTERM' });\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: null,\n signal: 'SIGTERM',\n logPath: handle.logPath,\n backend: handle.backend,\n timedOut: true,\n };\n }\n if (outcome instanceof Error) {\n await this.registry.complete(id, { reason: LAUNCHER_ERROR, code: null, signal: null });\n return { kind: FAILED, id, name, error: outcome.message };\n }\n\n await this.registry.complete(id, {\n reason: outcome.signal ? SIGNALED : outcome.code === 0 ? COMPLETED : FAILED,\n code: outcome.code,\n signal: outcome.signal,\n });\n\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: outcome.code,\n signal: outcome.signal,\n logPath: handle.logPath,\n backend: handle.backend,\n };\n } finally {\n outputUpdates?.dispose();\n }\n }\n\n private followOutput(\n handle: RunHandle,\n onOutput: NonNullable<BashRunRequest['onOutput']>,\n ): { flush(): void; dispose(): void } {\n let active = true;\n let previous = '';\n let cancelPoll: (() => void) | undefined;\n const flush = (): void => {\n if (!active) return;\n const output = handle.output();\n if (output === previous) return;\n previous = output;\n onOutput(output);\n };\n const poll = (): void => {\n if (!active) return;\n flush();\n if (active) cancelPoll = this.clock.after(OUTPUT_UPDATE_POLL_MS, poll);\n };\n cancelPoll = this.clock.after(OUTPUT_UPDATE_POLL_MS, poll);\n return {\n flush,\n dispose: () => {\n active = false;\n cancelPoll?.();\n cancelPoll = undefined;\n },\n };\n }\n\n /**\n * Waits for the command, giving up at the background threshold or at the\n * caller's timeout, whichever comes first.\n *\n * A rejected completion is returned rather than thrown so the caller can\n * report a start failure as a tool result instead of an exception.\n */\n private async race(\n handle: RunHandle,\n timeoutMs: number | undefined,\n ): Promise<Awaited<ReturnType<RunHandle['completion']>> | Error | typeof TIMED_OUT | typeof DEADLINE> {\n const cancels: Array<() => void> = [];\n const racers: Array<Promise<unknown>> = [handle.completion().catch((error: Error) => error)];\n\n racers.push(\n new Promise((resolve) => {\n cancels.push(this.clock.after(getBackgroundThresholdMs(), () => resolve(TIMED_OUT)));\n }),\n );\n if (timeoutMs !== undefined && timeoutMs > 0) {\n racers.push(\n new Promise((resolve) => {\n cancels.push(this.clock.after(timeoutMs, () => resolve(DEADLINE)));\n }),\n );\n }\n\n try {\n return (await Promise.race(racers)) as Awaited<ReturnType<RunHandle['completion']>> | Error | typeof TIMED_OUT;\n } finally {\n for (const cancel of cancels) cancel();\n }\n }\n\n private async promote(handle: RunHandle, reason: PromotedRun['reason']): Promise<BashRunResult> {\n if (handle.pid === undefined)\n return { kind: FAILED, id: handle.id, name: handle.name, error: 'The command did not start' };\n await this.registry.markPromoted(handle.id);\n // Registration first: an unregistered runner is invisible, and the handle\n // stops buffering the moment it is detached.\n handle.detach();\n void handle\n .completion()\n .then(\n (outcome) =>\n this.registry.complete(handle.id, {\n reason: outcome.signal ? SIGNALED : outcome.code === 0 ? COMPLETED : FAILED,\n code: outcome.code,\n signal: outcome.signal,\n }),\n () => this.registry.complete(handle.id, { reason: LAUNCHER_ERROR, code: null, signal: null }),\n )\n .catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.emitWarning(`Failed to complete runner ${handle.id}: ${message}`);\n });\n\n return {\n kind: 'promoted',\n id: handle.id,\n name: handle.name,\n pid: handle.pid,\n logPath: handle.logPath,\n backend: handle.backend,\n reason,\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"BashRunService.cjs","names":["randomBytes","RTK_FAILED_WARNING","getBackgroundThresholdMs"],"sources":["../../../../src/adapters/BashRunService/BashRunService.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { getBackgroundThresholdMs } from '../../types/config.ts';\nimport type { IClock } from '../../types/clock';\nimport type { ILauncher, RunHandle } from '../../types/launcher';\nimport type { IRmuxBackend } from '../../types/rmuxBackend';\nimport { type IRtkProcessor, RTK_FAILED_WARNING } from '../../types/rtkProcessor';\nimport type { IRunnerNamer } from '../../services/RunnerNamer/types';\nimport type { IRunnerRegistry } from '../../types/runnerRegistry';\nimport type {\n BashRunRequest,\n BashRunResult,\n CompletedRun,\n IBashRunService,\n PromotedRun,\n} from '../../types/bashRunService';\n\n/** The command outlived the background threshold and should be promoted. */\nconst TIMED_OUT = Symbol('threshold-reached');\n/** The command outlived the caller's explicit timeout and should be stopped. */\nconst DEADLINE = Symbol('deadline-reached');\nconst RUNNER_ID_RANDOM_BYTES = 3;\nconst OUTPUT_UPDATE_POLL_MS = 100;\nconst COMPLETED = 'completed';\nconst FAILED = 'failed';\nconst LAUNCHER_ERROR = 'launcher_error';\nconst SIGNALED = 'signaled';\n\nfunction runnerId(): string {\n const timestamp = Date.now().toString(36);\n const random = randomBytes(RUNNER_ID_RANDOM_BYTES).toString('base64url');\n return `${timestamp}-${random}`;\n}\n\nexport class BashRunService implements IBashRunService {\n constructor(\n private readonly launcher: ILauncher,\n private readonly rmuxBackend: IRmuxBackend,\n private readonly namer: IRunnerNamer,\n private readonly registry: IRunnerRegistry,\n private readonly clock: IClock,\n private readonly rtkProcessor: IRtkProcessor,\n ) {}\n\n async run(request: BashRunRequest): Promise<BashRunResult> {\n const id = runnerId();\n const name = await this.namer.allocate(request.command, request.sessionId, request.name);\n const cwd = request.cwd ?? process.cwd();\n const interactive = request.interactive === true;\n\n let handle: RunHandle;\n try {\n const rmuxHandle = await this.rmuxBackend.launch({\n id,\n name,\n command: request.command,\n cwd,\n sessionId: request.sessionId,\n interactive,\n });\n if (interactive && !rmuxHandle) {\n return { kind: FAILED, id, name, error: 'RMUX is required for interactive commands but is unavailable' };\n }\n handle =\n rmuxHandle ?? this.launcher.launch({ id, name, command: request.command, cwd, sessionId: request.sessionId });\n } catch (error) {\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n\n if (handle.pid === undefined) {\n return { kind: FAILED, id, name, error: 'The command did not start, so it cannot be supervised' };\n }\n\n try {\n await this.registry.register({\n id,\n name,\n pid: handle.pid,\n command: request.command,\n cwd,\n logPath: handle.logPath,\n interactive,\n sessionId: request.sessionId,\n backend: handle.backend,\n ...(handle.backendTarget ? { backendTarget: handle.backendTarget } : {}),\n });\n } catch (error) {\n await handle.stop();\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n\n // An interactive run has nothing to wait for: it is going to prompt, so\n // the model needs the runner name before it can answer.\n if (request.background === true || interactive) {\n return this.promote(handle, request.background === true ? 'requested' : 'interactive');\n }\n\n const outputUpdates = request.onOutput ? this.followOutput(handle, request.onOutput) : undefined;\n try {\n const outcome = await this.race(handle, request.timeoutMs);\n outputUpdates?.flush();\n if (outcome === TIMED_OUT) {\n return this.promote(handle, 'threshold');\n }\n if (outcome === DEADLINE) {\n // An explicit timeout means the caller wants the command dead, not\n // supervised, so it is stopped rather than promoted.\n await handle.stop();\n outputUpdates?.flush();\n await this.registry.complete(id, { reason: 'timed_out', code: null, signal: 'SIGTERM' });\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: null,\n signal: 'SIGTERM',\n logPath: handle.logPath,\n backend: handle.backend,\n timedOut: true,\n };\n }\n if (outcome instanceof Error) {\n await this.registry.complete(id, { reason: LAUNCHER_ERROR, code: null, signal: null });\n return { kind: FAILED, id, name, error: outcome.message };\n }\n\n await this.registry.complete(id, {\n reason: outcome.signal ? SIGNALED : outcome.code === 0 ? COMPLETED : FAILED,\n code: outcome.code,\n signal: outcome.signal,\n });\n\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: outcome.code,\n signal: outcome.signal,\n logPath: handle.logPath,\n backend: handle.backend,\n ...(await this.processLog(request.command, handle.logPath)),\n };\n } finally {\n outputUpdates?.dispose();\n }\n }\n\n private async processLog(command: string, logPath: string): Promise<Pick<CompletedRun, 'rtkOutput' | 'rtkWarning'>> {\n try {\n const result = await this.rtkProcessor.process({ command, logPath });\n if (result.kind === 'processed') return { rtkOutput: result.result };\n if (result.kind === 'fallback') return { rtkWarning: result.warning };\n return {};\n } catch {\n return { rtkWarning: RTK_FAILED_WARNING };\n }\n }\n\n private followOutput(\n handle: RunHandle,\n onOutput: NonNullable<BashRunRequest['onOutput']>,\n ): { flush(): void; dispose(): void } {\n let active = true;\n let previous = '';\n let cancelPoll: (() => void) | undefined;\n const flush = (): void => {\n if (!active) return;\n const output = handle.output();\n if (output === previous) return;\n previous = output;\n onOutput(output);\n };\n const poll = (): void => {\n if (!active) return;\n flush();\n if (active) cancelPoll = this.clock.after(OUTPUT_UPDATE_POLL_MS, poll);\n };\n cancelPoll = this.clock.after(OUTPUT_UPDATE_POLL_MS, poll);\n return {\n flush,\n dispose: () => {\n active = false;\n cancelPoll?.();\n cancelPoll = undefined;\n },\n };\n }\n\n /**\n * Waits for the command, giving up at the background threshold or at the\n * caller's timeout, whichever comes first.\n *\n * A rejected completion is returned rather than thrown so the caller can\n * report a start failure as a tool result instead of an exception.\n */\n private async race(\n handle: RunHandle,\n timeoutMs: number | undefined,\n ): Promise<Awaited<ReturnType<RunHandle['completion']>> | Error | typeof TIMED_OUT | typeof DEADLINE> {\n const cancels: Array<() => void> = [];\n const racers: Array<Promise<unknown>> = [handle.completion().catch((error: Error) => error)];\n\n racers.push(\n new Promise((resolve) => {\n cancels.push(this.clock.after(getBackgroundThresholdMs(), () => resolve(TIMED_OUT)));\n }),\n );\n if (timeoutMs !== undefined && timeoutMs > 0) {\n racers.push(\n new Promise((resolve) => {\n cancels.push(this.clock.after(timeoutMs, () => resolve(DEADLINE)));\n }),\n );\n }\n\n try {\n return (await Promise.race(racers)) as Awaited<ReturnType<RunHandle['completion']>> | Error | typeof TIMED_OUT;\n } finally {\n for (const cancel of cancels) cancel();\n }\n }\n\n private async promote(handle: RunHandle, reason: PromotedRun['reason']): Promise<BashRunResult> {\n if (handle.pid === undefined)\n return { kind: FAILED, id: handle.id, name: handle.name, error: 'The command did not start' };\n await this.registry.markPromoted(handle.id);\n // Registration first: an unregistered runner is invisible, and the handle\n // stops buffering the moment it is detached.\n handle.detach();\n void handle\n .completion()\n .then(\n (outcome) =>\n this.registry.complete(handle.id, {\n reason: outcome.signal ? SIGNALED : outcome.code === 0 ? COMPLETED : FAILED,\n code: outcome.code,\n signal: outcome.signal,\n }),\n () => this.registry.complete(handle.id, { reason: LAUNCHER_ERROR, code: null, signal: null }),\n )\n .catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.emitWarning(`Failed to complete runner ${handle.id}: ${message}`);\n });\n\n return {\n kind: 'promoted',\n id: handle.id,\n name: handle.name,\n pid: handle.pid,\n logPath: handle.logPath,\n backend: handle.backend,\n reason,\n };\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { ILauncher } from "../../types/launcher.cjs";
2
- import { IPtyHost } from "../../types/ptyHost.cjs";
3
2
  import { IRmuxBackend } from "../../types/rmuxBackend.cjs";
4
3
  import { IRunnerRegistry } from "../../types/runnerRegistry.cjs";
4
+ import { IRtkProcessor } from "../../types/rtkProcessor.cjs";
5
5
  import { BashRunRequest, BashRunResult, IBashRunService } from "../../types/bashRunService.cjs";
6
6
  import { IClock } from "../../types/clock.cjs";
7
7
  import { IRunnerNamer } from "../../services/RunnerNamer/types.cjs";
@@ -9,12 +9,13 @@ import { IRunnerNamer } from "../../services/RunnerNamer/types.cjs";
9
9
  declare class BashRunService implements IBashRunService {
10
10
  private readonly launcher;
11
11
  private readonly rmuxBackend;
12
- private readonly ptyHost;
13
12
  private readonly namer;
14
13
  private readonly registry;
15
14
  private readonly clock;
16
- constructor(launcher: ILauncher, rmuxBackend: IRmuxBackend, ptyHost: IPtyHost, namer: IRunnerNamer, registry: IRunnerRegistry, clock: IClock);
15
+ private readonly rtkProcessor;
16
+ constructor(launcher: ILauncher, rmuxBackend: IRmuxBackend, namer: IRunnerNamer, registry: IRunnerRegistry, clock: IClock, rtkProcessor: IRtkProcessor);
17
17
  run(request: BashRunRequest): Promise<BashRunResult>;
18
+ private processLog;
18
19
  private followOutput;
19
20
  /**
20
21
  * Waits for the command, giving up at the background threshold or at the
@@ -1 +1 @@
1
- {"version":3,"file":"BashRunService.d.cts","names":[],"sources":["../../../../src/adapters/BashRunService/BashRunService.ts"],"mappings":";;;;;;;;cA2Ba,0BAA0B;mBAElB;mBACA;mBACA;mBACA;mBACA;mBACA;EANnB,YACmB,UAAU,WACV,aAAa,cACb,SAAS,UACT,OAAO,cACP,UAAU,iBACV,OAAO;EAGpB,IAAI,SAAS,iBAAiB,QAAQ;UA0GpC;;;;;;;;UAqCM;UA2BA"}
1
+ {"version":3,"file":"BashRunService.d.cts","names":[],"sources":["../../../../src/adapters/BashRunService/BashRunService.ts"],"mappings":";;;;;;;;cAiCa,0BAA0B;mBAElB;mBACA;mBACA;mBACA;mBACA;mBACA;EANnB,YACmB,UAAU,WACV,aAAa,cACb,OAAO,cACP,UAAU,iBACV,OAAO,QACP,cAAc;EAG3B,IAAI,SAAS,iBAAiB,QAAQ;UAyG9B;UAWN;;;;;;;;UAqCM;UA2BA"}
@@ -1,7 +1,7 @@
1
1
  import { ILauncher } from "../../types/launcher.mjs";
2
- import { IPtyHost } from "../../types/ptyHost.mjs";
3
2
  import { IRmuxBackend } from "../../types/rmuxBackend.mjs";
4
3
  import { IRunnerRegistry } from "../../types/runnerRegistry.mjs";
4
+ import { IRtkProcessor } from "../../types/rtkProcessor.mjs";
5
5
  import { BashRunRequest, BashRunResult, IBashRunService } from "../../types/bashRunService.mjs";
6
6
  import { IClock } from "../../types/clock.mjs";
7
7
  import { IRunnerNamer } from "../../services/RunnerNamer/types.mjs";
@@ -9,12 +9,13 @@ import { IRunnerNamer } from "../../services/RunnerNamer/types.mjs";
9
9
  declare class BashRunService implements IBashRunService {
10
10
  private readonly launcher;
11
11
  private readonly rmuxBackend;
12
- private readonly ptyHost;
13
12
  private readonly namer;
14
13
  private readonly registry;
15
14
  private readonly clock;
16
- constructor(launcher: ILauncher, rmuxBackend: IRmuxBackend, ptyHost: IPtyHost, namer: IRunnerNamer, registry: IRunnerRegistry, clock: IClock);
15
+ private readonly rtkProcessor;
16
+ constructor(launcher: ILauncher, rmuxBackend: IRmuxBackend, namer: IRunnerNamer, registry: IRunnerRegistry, clock: IClock, rtkProcessor: IRtkProcessor);
17
17
  run(request: BashRunRequest): Promise<BashRunResult>;
18
+ private processLog;
18
19
  private followOutput;
19
20
  /**
20
21
  * Waits for the command, giving up at the background threshold or at the
@@ -1 +1 @@
1
- {"version":3,"file":"BashRunService.d.mts","names":[],"sources":["../../../../src/adapters/BashRunService/BashRunService.ts"],"mappings":";;;;;;;;cA2Ba,0BAA0B;mBAElB;mBACA;mBACA;mBACA;mBACA;mBACA;EANnB,YACmB,UAAU,WACV,aAAa,cACb,SAAS,UACT,OAAO,cACP,UAAU,iBACV,OAAO;EAGpB,IAAI,SAAS,iBAAiB,QAAQ;UA0GpC;;;;;;;;UAqCM;UA2BA"}
1
+ {"version":3,"file":"BashRunService.d.mts","names":[],"sources":["../../../../src/adapters/BashRunService/BashRunService.ts"],"mappings":";;;;;;;;cAiCa,0BAA0B;mBAElB;mBACA;mBACA;mBACA;mBACA;mBACA;EANnB,YACmB,UAAU,WACV,aAAa,cACb,OAAO,cACP,UAAU,iBACV,OAAO,QACP,cAAc;EAG3B,IAAI,SAAS,iBAAiB,QAAQ;UAyG9B;UAWN;;;;;;;;UAqCM;UA2BA"}
@@ -1,2 +1,2 @@
1
- import{getBackgroundThresholdMs as e}from"../../types/config.mjs";import{randomBytes as t}from"node:crypto";const n=Symbol(`threshold-reached`),r=Symbol(`deadline-reached`),i=`completed`,a=`failed`,o=`launcher_error`,s=`signaled`;function c(){return`${Date.now().toString(36)}-${t(3).toString(`base64url`)}`}var l=class{launcher;rmuxBackend;ptyHost;namer;registry;clock;constructor(e,t,n,r,i,a){this.launcher=e,this.rmuxBackend=t,this.ptyHost=n,this.namer=r,this.registry=i,this.clock=a}async run(e){let t=c(),l=await this.namer.allocate(e.command,e.sessionId,e.name),u=e.cwd??process.cwd(),d=e.interactive===!0,f;try{f=await this.rmuxBackend.launch({id:t,name:l,command:e.command,cwd:u,sessionId:e.sessionId,interactive:d})??(d?await this.ptyHost.launch({id:t,name:l,command:e.command,cwd:u,sessionId:e.sessionId}):this.launcher.launch({id:t,name:l,command:e.command,cwd:u,sessionId:e.sessionId}))}catch(e){return{kind:a,id:t,name:l,error:e instanceof Error?e.message:String(e)}}if(f.pid===void 0)return{kind:a,id:t,name:l,error:`The command did not start, so it cannot be supervised`};try{await this.registry.register({id:t,name:l,pid:f.pid,command:e.command,cwd:u,logPath:f.logPath,interactive:d,sessionId:e.sessionId,backend:f.backend,...f.backendTarget?{backendTarget:f.backendTarget}:{}})}catch(e){return await f.stop(),{kind:a,id:t,name:l,error:e instanceof Error?e.message:String(e)}}if(e.background===!0||d)return this.promote(f,e.background===!0?`requested`:`interactive`);let p=e.onOutput?this.followOutput(f,e.onOutput):void 0;try{let c=await this.race(f,e.timeoutMs);return p?.flush(),c===n?this.promote(f,`threshold`):c===r?(await f.stop(),p?.flush(),await this.registry.complete(t,{reason:`timed_out`,code:null,signal:`SIGTERM`}),{kind:i,id:t,name:l,output:f.output(),exitCode:null,signal:`SIGTERM`,logPath:f.logPath,backend:f.backend,timedOut:!0}):c instanceof Error?(await this.registry.complete(t,{reason:o,code:null,signal:null}),{kind:a,id:t,name:l,error:c.message}):(await this.registry.complete(t,{reason:c.signal?s:c.code===0?i:a,code:c.code,signal:c.signal}),{kind:i,id:t,name:l,output:f.output(),exitCode:c.code,signal:c.signal,logPath:f.logPath,backend:f.backend})}finally{p?.dispose()}}followOutput(e,t){let n=!0,r=``,i,a=()=>{if(!n)return;let i=e.output();i!==r&&(r=i,t(i))},o=()=>{n&&(a(),n&&(i=this.clock.after(100,o)))};return i=this.clock.after(100,o),{flush:a,dispose:()=>{n=!1,i?.(),i=void 0}}}async race(t,i){let a=[],o=[t.completion().catch(e=>e)];o.push(new Promise(t=>{a.push(this.clock.after(e(),()=>t(n)))})),i!==void 0&&i>0&&o.push(new Promise(e=>{a.push(this.clock.after(i,()=>e(r)))}));try{return await Promise.race(o)}finally{for(let e of a)e()}}async promote(e,t){return e.pid===void 0?{kind:a,id:e.id,name:e.name,error:`The command did not start`}:(await this.registry.markPromoted(e.id),e.detach(),e.completion().then(t=>this.registry.complete(e.id,{reason:t.signal?s:t.code===0?i:a,code:t.code,signal:t.signal}),()=>this.registry.complete(e.id,{reason:o,code:null,signal:null})).catch(t=>{let n=t instanceof Error?t.message:String(t);process.emitWarning(`Failed to complete runner ${e.id}: ${n}`)}),{kind:`promoted`,id:e.id,name:e.name,pid:e.pid,logPath:e.logPath,backend:e.backend,reason:t})}};export{l as BashRunService};
1
+ import{getBackgroundThresholdMs as e}from"../../types/config.mjs";import{RTK_FAILED_WARNING as t}from"../../types/rtkProcessor.mjs";import{randomBytes as n}from"node:crypto";const r=Symbol(`threshold-reached`),i=Symbol(`deadline-reached`),a=`completed`,o=`failed`,s=`launcher_error`,c=`signaled`;function l(){return`${Date.now().toString(36)}-${n(3).toString(`base64url`)}`}var u=class{launcher;rmuxBackend;namer;registry;clock;rtkProcessor;constructor(e,t,n,r,i,a){this.launcher=e,this.rmuxBackend=t,this.namer=n,this.registry=r,this.clock=i,this.rtkProcessor=a}async run(e){let t=l(),n=await this.namer.allocate(e.command,e.sessionId,e.name),u=e.cwd??process.cwd(),d=e.interactive===!0,f;try{let r=await this.rmuxBackend.launch({id:t,name:n,command:e.command,cwd:u,sessionId:e.sessionId,interactive:d});if(d&&!r)return{kind:o,id:t,name:n,error:`RMUX is required for interactive commands but is unavailable`};f=r??this.launcher.launch({id:t,name:n,command:e.command,cwd:u,sessionId:e.sessionId})}catch(e){return{kind:o,id:t,name:n,error:e instanceof Error?e.message:String(e)}}if(f.pid===void 0)return{kind:o,id:t,name:n,error:`The command did not start, so it cannot be supervised`};try{await this.registry.register({id:t,name:n,pid:f.pid,command:e.command,cwd:u,logPath:f.logPath,interactive:d,sessionId:e.sessionId,backend:f.backend,...f.backendTarget?{backendTarget:f.backendTarget}:{}})}catch(e){return await f.stop(),{kind:o,id:t,name:n,error:e instanceof Error?e.message:String(e)}}if(e.background===!0||d)return this.promote(f,e.background===!0?`requested`:`interactive`);let p=e.onOutput?this.followOutput(f,e.onOutput):void 0;try{let l=await this.race(f,e.timeoutMs);return p?.flush(),l===r?this.promote(f,`threshold`):l===i?(await f.stop(),p?.flush(),await this.registry.complete(t,{reason:`timed_out`,code:null,signal:`SIGTERM`}),{kind:a,id:t,name:n,output:f.output(),exitCode:null,signal:`SIGTERM`,logPath:f.logPath,backend:f.backend,timedOut:!0}):l instanceof Error?(await this.registry.complete(t,{reason:s,code:null,signal:null}),{kind:o,id:t,name:n,error:l.message}):(await this.registry.complete(t,{reason:l.signal?c:l.code===0?a:o,code:l.code,signal:l.signal}),{kind:a,id:t,name:n,output:f.output(),exitCode:l.code,signal:l.signal,logPath:f.logPath,backend:f.backend,...await this.processLog(e.command,f.logPath)})}finally{p?.dispose()}}async processLog(e,n){try{let t=await this.rtkProcessor.process({command:e,logPath:n});return t.kind===`processed`?{rtkOutput:t.result}:t.kind===`fallback`?{rtkWarning:t.warning}:{}}catch{return{rtkWarning:t}}}followOutput(e,t){let n=!0,r=``,i,a=()=>{if(!n)return;let i=e.output();i!==r&&(r=i,t(i))},o=()=>{n&&(a(),n&&(i=this.clock.after(100,o)))};return i=this.clock.after(100,o),{flush:a,dispose:()=>{n=!1,i?.(),i=void 0}}}async race(t,n){let a=[],o=[t.completion().catch(e=>e)];o.push(new Promise(t=>{a.push(this.clock.after(e(),()=>t(r)))})),n!==void 0&&n>0&&o.push(new Promise(e=>{a.push(this.clock.after(n,()=>e(i)))}));try{return await Promise.race(o)}finally{for(let e of a)e()}}async promote(e,t){return e.pid===void 0?{kind:o,id:e.id,name:e.name,error:`The command did not start`}:(await this.registry.markPromoted(e.id),e.detach(),e.completion().then(t=>this.registry.complete(e.id,{reason:t.signal?c:t.code===0?a:o,code:t.code,signal:t.signal}),()=>this.registry.complete(e.id,{reason:s,code:null,signal:null})).catch(t=>{let n=t instanceof Error?t.message:String(t);process.emitWarning(`Failed to complete runner ${e.id}: ${n}`)}),{kind:`promoted`,id:e.id,name:e.name,pid:e.pid,logPath:e.logPath,backend:e.backend,reason:t})}};export{u as BashRunService};
2
2
  //# sourceMappingURL=BashRunService.mjs.map