@agimon-ai/doompi-runner 0.0.1-alpha.58 → 0.0.1-alpha.64

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 (285) hide show
  1. package/dist/bin/cli.d.cts +1 -2
  2. package/dist/bin/cli.d.cts.map +1 -1
  3. package/dist/bin/cli.d.mts +1 -2
  4. package/dist/bin/cli.d.mts.map +1 -1
  5. package/dist/bin/logSink.cjs +1 -1
  6. package/dist/bin/logSink.cjs.map +1 -1
  7. package/dist/bin/logSink.d.cts +1 -2
  8. package/dist/bin/logSink.d.cts.map +1 -1
  9. package/dist/bin/logSink.d.mts +1 -2
  10. package/dist/bin/logSink.d.mts.map +1 -1
  11. package/dist/bin/logSink.mjs +1 -1
  12. package/dist/bin/logSink.mjs.map +1 -1
  13. package/dist/bin/runnerHost.d.cts +1 -2
  14. package/dist/bin/runnerHost.d.cts.map +1 -1
  15. package/dist/bin/runnerHost.d.mts +1 -2
  16. package/dist/bin/runnerHost.d.mts.map +1 -1
  17. package/dist/src/adapters/BashRunService/BashRunService.d.cts +1 -2
  18. package/dist/src/adapters/BashRunService/BashRunService.d.cts.map +1 -1
  19. package/dist/src/adapters/BashRunService/BashRunService.d.mts +1 -2
  20. package/dist/src/adapters/BashRunService/BashRunService.d.mts.map +1 -1
  21. package/dist/src/adapters/Clock/SystemClock.d.cts +1 -2
  22. package/dist/src/adapters/Clock/SystemClock.d.cts.map +1 -1
  23. package/dist/src/adapters/Clock/SystemClock.d.mts +1 -2
  24. package/dist/src/adapters/Clock/SystemClock.d.mts.map +1 -1
  25. package/dist/src/adapters/Launcher/Launcher.d.cts +1 -2
  26. package/dist/src/adapters/Launcher/Launcher.d.cts.map +1 -1
  27. package/dist/src/adapters/Launcher/Launcher.d.mts +1 -2
  28. package/dist/src/adapters/Launcher/Launcher.d.mts.map +1 -1
  29. package/dist/src/adapters/Lifeline/NodeLifeline.d.cts +1 -2
  30. package/dist/src/adapters/Lifeline/NodeLifeline.d.cts.map +1 -1
  31. package/dist/src/adapters/Lifeline/NodeLifeline.d.mts +1 -2
  32. package/dist/src/adapters/Lifeline/NodeLifeline.d.mts.map +1 -1
  33. package/dist/src/adapters/Lifeline/client.d.cts +2 -3
  34. package/dist/src/adapters/Lifeline/client.d.cts.map +1 -1
  35. package/dist/src/adapters/Lifeline/client.d.mts +2 -3
  36. package/dist/src/adapters/Lifeline/client.d.mts.map +1 -1
  37. package/dist/src/adapters/LogFile/LogFile.d.cts +1 -2
  38. package/dist/src/adapters/LogFile/LogFile.d.cts.map +1 -1
  39. package/dist/src/adapters/LogFile/LogFile.d.mts +1 -2
  40. package/dist/src/adapters/LogFile/LogFile.d.mts.map +1 -1
  41. package/dist/src/adapters/LogReader/LogReader.cjs +5 -5
  42. package/dist/src/adapters/LogReader/LogReader.cjs.map +1 -1
  43. package/dist/src/adapters/LogReader/LogReader.d.cts +2 -3
  44. package/dist/src/adapters/LogReader/LogReader.d.cts.map +1 -1
  45. package/dist/src/adapters/LogReader/LogReader.d.mts +2 -3
  46. package/dist/src/adapters/LogReader/LogReader.d.mts.map +1 -1
  47. package/dist/src/adapters/LogReader/LogReader.mjs +5 -5
  48. package/dist/src/adapters/LogReader/LogReader.mjs.map +1 -1
  49. package/dist/src/adapters/LogTail/LogTail.cjs +1 -1
  50. package/dist/src/adapters/LogTail/LogTail.cjs.map +1 -1
  51. package/dist/src/adapters/LogTail/LogTail.mjs +1 -1
  52. package/dist/src/adapters/LogTail/LogTail.mjs.map +1 -1
  53. package/dist/src/adapters/ProcessControl/NodeProcessControl.d.cts +1 -2
  54. package/dist/src/adapters/ProcessControl/NodeProcessControl.d.cts.map +1 -1
  55. package/dist/src/adapters/ProcessControl/NodeProcessControl.d.mts +1 -2
  56. package/dist/src/adapters/ProcessControl/NodeProcessControl.d.mts.map +1 -1
  57. package/dist/src/adapters/PtyBackendChain/PtyBackendChain.cjs +1 -1
  58. package/dist/src/adapters/PtyBackendChain/PtyBackendChain.cjs.map +1 -1
  59. package/dist/src/adapters/PtyBackendChain/PtyBackendChain.mjs +1 -1
  60. package/dist/src/adapters/PtyBackendChain/PtyBackendChain.mjs.map +1 -1
  61. package/dist/src/adapters/PtyHost/PtyHost.d.cts +1 -2
  62. package/dist/src/adapters/PtyHost/PtyHost.d.cts.map +1 -1
  63. package/dist/src/adapters/PtyHost/PtyHost.d.mts +1 -2
  64. package/dist/src/adapters/PtyHost/PtyHost.d.mts.map +1 -1
  65. package/dist/src/adapters/PtySpawner/NodePtySpawner.d.cts +1 -2
  66. package/dist/src/adapters/PtySpawner/NodePtySpawner.d.cts.map +1 -1
  67. package/dist/src/adapters/PtySpawner/NodePtySpawner.d.mts +1 -2
  68. package/dist/src/adapters/PtySpawner/NodePtySpawner.d.mts.map +1 -1
  69. package/dist/src/adapters/RmuxBackend/RmuxBackend.cjs +1 -1
  70. package/dist/src/adapters/RmuxBackend/RmuxBackend.cjs.map +1 -1
  71. package/dist/src/adapters/RmuxBackend/RmuxBackend.d.cts +11 -3
  72. package/dist/src/adapters/RmuxBackend/RmuxBackend.d.cts.map +1 -1
  73. package/dist/src/adapters/RmuxBackend/RmuxBackend.d.mts +11 -3
  74. package/dist/src/adapters/RmuxBackend/RmuxBackend.d.mts.map +1 -1
  75. package/dist/src/adapters/RmuxBackend/RmuxBackend.mjs +1 -1
  76. package/dist/src/adapters/RmuxBackend/RmuxBackend.mjs.map +1 -1
  77. package/dist/src/adapters/RtkProcessor/RtkProcessor.d.cts +4 -5
  78. package/dist/src/adapters/RtkProcessor/RtkProcessor.d.cts.map +1 -1
  79. package/dist/src/adapters/RtkProcessor/RtkProcessor.d.mts +4 -5
  80. package/dist/src/adapters/RtkProcessor/RtkProcessor.d.mts.map +1 -1
  81. package/dist/src/adapters/RunnerPaths.cjs +1 -1
  82. package/dist/src/adapters/RunnerPaths.cjs.map +1 -1
  83. package/dist/src/adapters/RunnerPaths.d.cts +2 -2
  84. package/dist/src/adapters/RunnerPaths.d.cts.map +1 -1
  85. package/dist/src/adapters/RunnerPaths.d.mts +2 -2
  86. package/dist/src/adapters/RunnerPaths.d.mts.map +1 -1
  87. package/dist/src/adapters/RunnerPaths.mjs +1 -1
  88. package/dist/src/adapters/RunnerPaths.mjs.map +1 -1
  89. package/dist/src/adapters/RunnerRegistry/RunnerRegistry.d.cts +3 -4
  90. package/dist/src/adapters/RunnerRegistry/RunnerRegistry.d.cts.map +1 -1
  91. package/dist/src/adapters/RunnerRegistry/RunnerRegistry.d.mts +3 -4
  92. package/dist/src/adapters/RunnerRegistry/RunnerRegistry.d.mts.map +1 -1
  93. package/dist/src/adapters/Spawner/NodeSpawner.d.cts +1 -2
  94. package/dist/src/adapters/Spawner/NodeSpawner.d.cts.map +1 -1
  95. package/dist/src/adapters/Spawner/NodeSpawner.d.mts +1 -2
  96. package/dist/src/adapters/Spawner/NodeSpawner.d.mts.map +1 -1
  97. package/dist/src/adapters/TmuxBackend/TmuxBackend.cjs +1 -1
  98. package/dist/src/adapters/TmuxBackend/TmuxBackend.cjs.map +1 -1
  99. package/dist/src/adapters/TmuxBackend/TmuxBackend.mjs +1 -1
  100. package/dist/src/adapters/TmuxBackend/TmuxBackend.mjs.map +1 -1
  101. package/dist/src/adapters/TmuxBackend/TmuxClient.cjs +1 -1
  102. package/dist/src/adapters/TmuxBackend/TmuxClient.cjs.map +1 -1
  103. package/dist/src/adapters/TmuxBackend/TmuxClient.mjs +1 -1
  104. package/dist/src/adapters/TmuxBackend/TmuxClient.mjs.map +1 -1
  105. package/dist/src/adapters/pi/extension.cjs +2 -2
  106. package/dist/src/adapters/pi/extension.cjs.map +1 -1
  107. package/dist/src/adapters/pi/extension.d.cts +2 -2
  108. package/dist/src/adapters/pi/extension.d.cts.map +1 -1
  109. package/dist/src/adapters/pi/extension.d.mts +2 -2
  110. package/dist/src/adapters/pi/extension.d.mts.map +1 -1
  111. package/dist/src/adapters/pi/extension.mjs +1 -1
  112. package/dist/src/adapters/pi/extension.mjs.map +1 -1
  113. package/dist/src/adapters/runnerLogApi.cjs +1 -1
  114. package/dist/src/adapters/runnerLogApi.cjs.map +1 -1
  115. package/dist/src/adapters/runnerLogApi.d.cts +13 -4
  116. package/dist/src/adapters/runnerLogApi.d.cts.map +1 -1
  117. package/dist/src/adapters/runnerLogApi.d.mts +13 -4
  118. package/dist/src/adapters/runnerLogApi.d.mts.map +1 -1
  119. package/dist/src/adapters/runnerLogApi.mjs +1 -1
  120. package/dist/src/adapters/runnerLogApi.mjs.map +1 -1
  121. package/dist/src/adapters/webRunnerWatcher.d.cts +4 -5
  122. package/dist/src/adapters/webRunnerWatcher.d.cts.map +1 -1
  123. package/dist/src/adapters/webRunnerWatcher.d.mts +4 -5
  124. package/dist/src/adapters/webRunnerWatcher.d.mts.map +1 -1
  125. package/dist/src/adapters/webRunnersChannel.d.cts +2 -3
  126. package/dist/src/adapters/webRunnersChannel.d.cts.map +1 -1
  127. package/dist/src/adapters/webRunnersChannel.d.mts +2 -3
  128. package/dist/src/adapters/webRunnersChannel.d.mts.map +1 -1
  129. package/dist/src/commands/bash/bashTool.d.cts +5 -6
  130. package/dist/src/commands/bash/bashTool.d.cts.map +1 -1
  131. package/dist/src/commands/bash/bashTool.d.mts +5 -6
  132. package/dist/src/commands/bash/bashTool.d.mts.map +1 -1
  133. package/dist/src/commands/bash/responseEnvelope.d.cts +20 -21
  134. package/dist/src/commands/bash/responseEnvelope.d.cts.map +1 -1
  135. package/dist/src/commands/bash/responseEnvelope.d.mts +20 -21
  136. package/dist/src/commands/bash/responseEnvelope.d.mts.map +1 -1
  137. package/dist/src/commands/cli/cliApp.d.cts +2 -3
  138. package/dist/src/commands/cli/cliApp.d.cts.map +1 -1
  139. package/dist/src/commands/cli/cliApp.d.mts +2 -3
  140. package/dist/src/commands/cli/cliApp.d.mts.map +1 -1
  141. package/dist/src/container/index.d.cts +1 -2
  142. package/dist/src/container/index.d.cts.map +1 -1
  143. package/dist/src/container/index.d.mts +1 -2
  144. package/dist/src/container/index.d.mts.map +1 -1
  145. package/dist/src/container/types.d.cts +1 -2
  146. package/dist/src/container/types.d.cts.map +1 -1
  147. package/dist/src/container/types.d.mts +1 -2
  148. package/dist/src/container/types.d.mts.map +1 -1
  149. package/dist/src/schemas/bashTool.d.cts +5 -6
  150. package/dist/src/schemas/bashTool.d.cts.map +1 -1
  151. package/dist/src/schemas/bashTool.d.mts +5 -6
  152. package/dist/src/schemas/bashTool.d.mts.map +1 -1
  153. package/dist/src/services/AnsiScrub/ansiScrub.d.cts +5 -6
  154. package/dist/src/services/AnsiScrub/ansiScrub.d.cts.map +1 -1
  155. package/dist/src/services/AnsiScrub/ansiScrub.d.mts +5 -6
  156. package/dist/src/services/AnsiScrub/ansiScrub.d.mts.map +1 -1
  157. package/dist/src/services/RunnerNamer/RunnerNamer.d.cts +1 -2
  158. package/dist/src/services/RunnerNamer/RunnerNamer.d.cts.map +1 -1
  159. package/dist/src/services/RunnerNamer/RunnerNamer.d.mts +1 -2
  160. package/dist/src/services/RunnerNamer/RunnerNamer.d.mts.map +1 -1
  161. package/dist/src/services/RunnerNamer/types.d.cts +1 -2
  162. package/dist/src/services/RunnerNamer/types.d.cts.map +1 -1
  163. package/dist/src/services/RunnerNamer/types.d.mts +1 -2
  164. package/dist/src/services/RunnerNamer/types.d.mts.map +1 -1
  165. package/dist/src/services/RunnerPaths/types.d.cts +11 -3
  166. package/dist/src/services/RunnerPaths/types.d.cts.map +1 -1
  167. package/dist/src/services/RunnerPaths/types.d.mts +11 -3
  168. package/dist/src/services/RunnerPaths/types.d.mts.map +1 -1
  169. package/dist/src/services/runs/compaction.d.cts +4 -5
  170. package/dist/src/services/runs/compaction.d.cts.map +1 -1
  171. package/dist/src/services/runs/compaction.d.mts +4 -5
  172. package/dist/src/services/runs/compaction.d.mts.map +1 -1
  173. package/dist/src/services/runs/reconcile.d.cts +4 -5
  174. package/dist/src/services/runs/reconcile.d.cts.map +1 -1
  175. package/dist/src/services/runs/reconcile.d.mts +4 -5
  176. package/dist/src/services/runs/reconcile.d.mts.map +1 -1
  177. package/dist/src/services/runs/runnersCommand.cjs +1 -1
  178. package/dist/src/services/runs/runnersCommand.cjs.map +1 -1
  179. package/dist/src/services/runs/runnersCommand.mjs +1 -1
  180. package/dist/src/services/runs/runnersCommand.mjs.map +1 -1
  181. package/dist/src/services/runs/session.d.cts +3 -4
  182. package/dist/src/services/runs/session.d.cts.map +1 -1
  183. package/dist/src/services/runs/session.d.mts +3 -4
  184. package/dist/src/services/runs/session.d.mts.map +1 -1
  185. package/dist/src/tui/bashRender.d.cts +10 -11
  186. package/dist/src/tui/bashRender.d.cts.map +1 -1
  187. package/dist/src/tui/bashRender.d.mts +10 -11
  188. package/dist/src/tui/bashRender.d.mts.map +1 -1
  189. package/dist/src/tui/format.d.cts +8 -9
  190. package/dist/src/tui/format.d.cts.map +1 -1
  191. package/dist/src/tui/format.d.mts +8 -9
  192. package/dist/src/tui/format.d.mts.map +1 -1
  193. package/dist/src/tui/runnerSpace.d.cts +4 -5
  194. package/dist/src/tui/runnerSpace.d.cts.map +1 -1
  195. package/dist/src/tui/runnerSpace.d.mts +4 -5
  196. package/dist/src/tui/runnerSpace.d.mts.map +1 -1
  197. package/dist/src/types/bashRunService.d.cts +6 -7
  198. package/dist/src/types/bashRunService.d.cts.map +1 -1
  199. package/dist/src/types/bashRunService.d.mts +6 -7
  200. package/dist/src/types/bashRunService.d.mts.map +1 -1
  201. package/dist/src/types/clock.d.cts +1 -2
  202. package/dist/src/types/clock.d.cts.map +1 -1
  203. package/dist/src/types/clock.d.mts +1 -2
  204. package/dist/src/types/clock.d.mts.map +1 -1
  205. package/dist/src/types/config.d.cts +38 -39
  206. package/dist/src/types/config.d.cts.map +1 -1
  207. package/dist/src/types/config.d.mts +38 -39
  208. package/dist/src/types/config.d.mts.map +1 -1
  209. package/dist/src/types/launcher.d.cts +3 -4
  210. package/dist/src/types/launcher.d.cts.map +1 -1
  211. package/dist/src/types/launcher.d.mts +3 -4
  212. package/dist/src/types/launcher.d.mts.map +1 -1
  213. package/dist/src/types/lifeline.d.cts +1 -2
  214. package/dist/src/types/lifeline.d.cts.map +1 -1
  215. package/dist/src/types/lifeline.d.mts +1 -2
  216. package/dist/src/types/lifeline.d.mts.map +1 -1
  217. package/dist/src/types/logFile.d.cts +2 -3
  218. package/dist/src/types/logFile.d.cts.map +1 -1
  219. package/dist/src/types/logFile.d.mts +2 -3
  220. package/dist/src/types/logFile.d.mts.map +1 -1
  221. package/dist/src/types/logReader.d.cts +19 -4
  222. package/dist/src/types/logReader.d.cts.map +1 -1
  223. package/dist/src/types/logReader.d.mts +19 -4
  224. package/dist/src/types/logReader.d.mts.map +1 -1
  225. package/dist/src/types/logTail.d.cts +10 -6
  226. package/dist/src/types/logTail.d.cts.map +1 -1
  227. package/dist/src/types/logTail.d.mts +10 -6
  228. package/dist/src/types/logTail.d.mts.map +1 -1
  229. package/dist/src/types/processControl.d.cts +1 -2
  230. package/dist/src/types/processControl.d.cts.map +1 -1
  231. package/dist/src/types/processControl.d.mts +1 -2
  232. package/dist/src/types/processControl.d.mts.map +1 -1
  233. package/dist/src/types/ptyHost.d.cts +3 -4
  234. package/dist/src/types/ptyHost.d.cts.map +1 -1
  235. package/dist/src/types/ptyHost.d.mts +3 -4
  236. package/dist/src/types/ptyHost.d.mts.map +1 -1
  237. package/dist/src/types/ptySpawner.d.cts +4 -5
  238. package/dist/src/types/ptySpawner.d.cts.map +1 -1
  239. package/dist/src/types/ptySpawner.d.mts +4 -5
  240. package/dist/src/types/ptySpawner.d.mts.map +1 -1
  241. package/dist/src/types/rmuxBackend.d.cts +12 -3
  242. package/dist/src/types/rmuxBackend.d.cts.map +1 -1
  243. package/dist/src/types/rmuxBackend.d.mts +12 -3
  244. package/dist/src/types/rmuxBackend.d.mts.map +1 -1
  245. package/dist/src/types/rtkProcessor.d.cts +9 -10
  246. package/dist/src/types/rtkProcessor.d.cts.map +1 -1
  247. package/dist/src/types/rtkProcessor.d.mts +9 -10
  248. package/dist/src/types/rtkProcessor.d.mts.map +1 -1
  249. package/dist/src/types/runnerRegistry.d.cts +9 -10
  250. package/dist/src/types/runnerRegistry.d.cts.map +1 -1
  251. package/dist/src/types/runnerRegistry.d.mts +9 -10
  252. package/dist/src/types/runnerRegistry.d.mts.map +1 -1
  253. package/dist/src/types/runnerSettings.d.cts +1 -2
  254. package/dist/src/types/runnerSettings.d.cts.map +1 -1
  255. package/dist/src/types/runnerSettings.d.mts +1 -2
  256. package/dist/src/types/runnerSettings.d.mts.map +1 -1
  257. package/dist/src/types/spawner.d.cts +5 -6
  258. package/dist/src/types/spawner.d.cts.map +1 -1
  259. package/dist/src/types/spawner.d.mts +5 -6
  260. package/dist/src/types/spawner.d.mts.map +1 -1
  261. package/dist/src/types/webRunnerLog.cjs +1 -1
  262. package/dist/src/types/webRunnerLog.cjs.map +1 -1
  263. package/dist/src/types/webRunnerLog.mjs +1 -1
  264. package/dist/src/types/webRunnerLog.mjs.map +1 -1
  265. package/dist/src/types/webRunners.d.cts +2 -3
  266. package/dist/src/types/webRunners.d.cts.map +1 -1
  267. package/dist/src/types/webRunners.d.mts +2 -3
  268. package/dist/src/types/webRunners.d.mts.map +1 -1
  269. package/package.json +25 -25
  270. package/src/types/webRunnerLog.ts +64 -0
  271. package/src/web/api/logApi.ts +127 -0
  272. package/src/web/api/screenApi.ts +107 -0
  273. package/src/web/{BashToolMessage.tsx → components/BashToolMessage.tsx} +2 -2
  274. package/src/web/components/LaunchRunnerDialog.tsx +161 -0
  275. package/src/web/{RunnerLogPanel.tsx → components/RunnerLogPanel.tsx} +148 -38
  276. package/src/web/components/RunnerShellPanel.tsx +130 -0
  277. package/src/web/{RunnersActivitySection.tsx → components/RunnersActivitySection.tsx} +21 -7
  278. package/src/web/components/RunnersPanel.tsx +252 -0
  279. package/src/web/{runnerTail.ts → hooks/runnerTail.ts} +6 -5
  280. package/src/web/index.ts +7 -3
  281. package/src/web/{format.ts → lib/format.ts} +37 -2
  282. package/src/web/lib/launchLine.ts +55 -0
  283. package/src/web/{runnersStore.ts → stores/runnersStore.ts} +14 -1
  284. package/src/web/logApi.ts +0 -82
  285. /package/src/web/{bashToolFormat.ts → lib/bashToolFormat.ts} +0 -0
@@ -1,5 +1,4 @@
1
1
  //#region src/bin/cli.d.ts
2
- declare function main(argv?: readonly string[]): Promise<number>;
2
+ export declare function main(argv?: readonly string[]): Promise<number>;
3
3
  //#endregion
4
- export { main };
5
4
  //# sourceMappingURL=cli.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.cts","names":[],"sources":["../../src/bin/cli.ts"],"mappings":";iBAasB,KAAK,2BAAkD"}
1
+ {"version":3,"file":"cli.d.cts","names":[],"sources":["../../src/bin/cli.ts"],"mappings":";wBAasB,KAAK,2BAAkD"}
@@ -1,5 +1,4 @@
1
1
  //#region src/bin/cli.d.ts
2
- declare function main(argv?: readonly string[]): Promise<number>;
2
+ export declare function main(argv?: readonly string[]): Promise<number>;
3
3
  //#endregion
4
- export { main };
5
4
  //# sourceMappingURL=cli.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.mts","names":[],"sources":["../../src/bin/cli.ts"],"mappings":";iBAasB,KAAK,2BAAkD"}
1
+ {"version":3,"file":"cli.d.mts","names":[],"sources":["../../src/bin/cli.ts"],"mappings":";wBAasB,KAAK,2BAAkD"}
@@ -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;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;
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}),[l,u,d,f,p]=e;try{if(!l||!u||!d||!f)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 m,h;try{m=n.default.openSync(l,`a`),h=n.default.statSync(l).size}catch(e){throw await a.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-r}),await a.shutdown(),e}let g=0,_=Number.parseInt(d,10),v=p===void 0||p===``?void 0:o(p),y=v===void 0?0:s(p);try{process.stdin.setEncoding(`utf8`);for await(let e of process.stdin){let r=String(e);if(v!==void 0){let e=Buffer.from(r,`utf8`);y+e.byteLength>_&&(n.default.ftruncateSync(v,0),y=0),n.default.writeSync(v,e),y+=e.byteLength}let i=t.scrubTerminalOutput(r);if(!i)continue;let a=Buffer.from(i,`utf8`);n.default.writeSync(m,a),h+=a.byteLength,g+=1}return n.default.closeSync(m),v!==void 0&&n.default.closeSync(v),c(f),await a.recordEvent(`doom_runner.file_sink_finished`,{outcome:`completed`,"runner.chunk_count":g,"runner.bytes_written":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){return n.default.openSync(e,`w`)}function s(e){try{return n.default.statSync(e).size}catch{return 0}}function c(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 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
+ {"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, rawPath] = argv;\n try {\n // Keep the legacy argument shape for the published executable subpath. The\n // scrubbed log is append-only, so the former rotation path is unused; the\n // ceiling now bounds the raw copy, which only interactive runs ask for.\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 // The pane's bytes before anything is taken out of them. Scrubbing exists so\n // the log stays worth grepping, and it is exactly what makes the log useless\n // to a terminal, so an attached view needs its own faithful copy.\n const rawCeiling = Number.parseInt(maxBytesRaw, 10);\n const raw = rawPath === undefined || rawPath === '' ? undefined : openRaw(rawPath);\n let rawWritten = raw === undefined ? 0 : rawSize(rawPath as string);\n try {\n process.stdin.setEncoding('utf8');\n for await (const chunk of process.stdin) {\n const source = String(chunk);\n if (raw !== undefined) {\n const rawBytes = Buffer.from(source, 'utf8');\n // A terminal that scrolls all day must not fill the disk. Past the\n // ceiling the copy starts over: a reader attaching later wants the\n // recent screen, and no part of this is the record of the run.\n if (rawWritten + rawBytes.byteLength > rawCeiling) {\n fs.ftruncateSync(raw, 0);\n rawWritten = 0;\n }\n fs.writeSync(raw, rawBytes);\n rawWritten += rawBytes.byteLength;\n }\n const text = scrubTerminalOutput(source);\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 if (raw !== undefined) fs.closeSync(raw);\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\n/** Truncating rather than appending: a stale pane from a previous run is not this one's. */\nfunction openRaw(target: string): number {\n return fs.openSync(target, 'w');\n}\n\nfunction rawSize(target: string): number {\n try {\n return fs.statSync(target).size;\n } catch {\n return 0;\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":"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"}
@@ -1,5 +1,4 @@
1
1
  //#region src/bin/logSink.d.ts
2
- declare function main(argv?: readonly string[]): Promise<number>;
2
+ export declare function main(argv?: readonly string[]): Promise<number>;
3
3
  //#endregion
4
- export { main };
5
4
  //# sourceMappingURL=logSink.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logSink.d.cts","names":[],"sources":["../../src/bin/logSink.ts"],"mappings":";iBAKsB,KAAK,2BAAkD"}
1
+ {"version":3,"file":"logSink.d.cts","names":[],"sources":["../../src/bin/logSink.ts"],"mappings":";wBAKsB,KAAK,2BAAkD"}
@@ -1,5 +1,4 @@
1
1
  //#region src/bin/logSink.d.ts
2
- declare function main(argv?: readonly string[]): Promise<number>;
2
+ export declare function main(argv?: readonly string[]): Promise<number>;
3
3
  //#endregion
4
- export { main };
5
4
  //# sourceMappingURL=logSink.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logSink.d.mts","names":[],"sources":["../../src/bin/logSink.ts"],"mappings":";iBAKsB,KAAK,2BAAkD"}
1
+ {"version":3,"file":"logSink.d.mts","names":[],"sources":["../../src/bin/logSink.ts"],"mappings":";wBAKsB,KAAK,2BAAkD"}
@@ -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;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};
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(),c=r({serviceName:`doom-runner-log-sink`,packageName:`@agimon-ai/doompi-runner`,env:process.env,enableLogs:!0,enableTraces:!0}),[l,u,d,f,p]=n;try{if(!l||!u||!d||!f)throw Error(`logSink requires log, rotated log, max bytes, and completion paths`)}catch(e){throw await c.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-i}),await c.shutdown(),e}let m,h;try{m=t.openSync(l,`a`),h=t.statSync(l).size}catch(e){throw await c.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-i}),await c.shutdown(),e}let g=0,_=Number.parseInt(d,10),v=p===void 0||p===``?void 0:a(p),y=v===void 0?0:o(p);try{process.stdin.setEncoding(`utf8`);for await(let n of process.stdin){let r=String(n);if(v!==void 0){let e=Buffer.from(r,`utf8`);y+e.byteLength>_&&(t.ftruncateSync(v,0),y=0),t.writeSync(v,e),y+=e.byteLength}let i=e(r);if(!i)continue;let a=Buffer.from(i,`utf8`);t.writeSync(m,a),h+=a.byteLength,g+=1}return t.closeSync(m),v!==void 0&&t.closeSync(v),s(f),await c.recordEvent(`doom_runner.file_sink_finished`,{outcome:`completed`,"runner.chunk_count":g,"runner.bytes_written":h,duration_ms:Date.now()-i}),0}catch(e){throw await c.recordError(`doom_runner.file_sink_failed`,e,{duration_ms:Date.now()-i}),e}finally{await c.shutdown()}}function a(e){return t.openSync(e,`w`)}function o(e){try{return t.statSync(e).size}catch{return 0}}function s(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 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"}
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, rawPath] = argv;\n try {\n // Keep the legacy argument shape for the published executable subpath. The\n // scrubbed log is append-only, so the former rotation path is unused; the\n // ceiling now bounds the raw copy, which only interactive runs ask for.\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 // The pane's bytes before anything is taken out of them. Scrubbing exists so\n // the log stays worth grepping, and it is exactly what makes the log useless\n // to a terminal, so an attached view needs its own faithful copy.\n const rawCeiling = Number.parseInt(maxBytesRaw, 10);\n const raw = rawPath === undefined || rawPath === '' ? undefined : openRaw(rawPath);\n let rawWritten = raw === undefined ? 0 : rawSize(rawPath as string);\n try {\n process.stdin.setEncoding('utf8');\n for await (const chunk of process.stdin) {\n const source = String(chunk);\n if (raw !== undefined) {\n const rawBytes = Buffer.from(source, 'utf8');\n // A terminal that scrolls all day must not fill the disk. Past the\n // ceiling the copy starts over: a reader attaching later wants the\n // recent screen, and no part of this is the record of the run.\n if (rawWritten + rawBytes.byteLength > rawCeiling) {\n fs.ftruncateSync(raw, 0);\n rawWritten = 0;\n }\n fs.writeSync(raw, rawBytes);\n rawWritten += rawBytes.byteLength;\n }\n const text = scrubTerminalOutput(source);\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 if (raw !== undefined) fs.closeSync(raw);\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\n/** Truncating rather than appending: a stale pane from a previous run is not this one's. */\nfunction openRaw(target: string): number {\n return fs.openSync(target, 'w');\n}\n\nfunction rawSize(target: string): number {\n try {\n return fs.statSync(target).size;\n } catch {\n return 0;\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,EAAU,GAAW,EAC/D,GAAI,CAIF,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,EAIP,EAAa,OAAO,SAAS,EAAa,EAAE,EAC5C,EAAM,IAAY,IAAA,IAAa,IAAY,GAAK,IAAA,GAAY,EAAQ,CAAO,EAC7E,EAAa,IAAQ,IAAA,GAAY,EAAI,EAAQ,CAAiB,EAClE,GAAI,CACF,QAAQ,MAAM,YAAY,MAAM,EAChC,UAAW,IAAM,KAAS,QAAQ,MAAO,CACvC,IAAM,EAAS,OAAO,CAAK,EAC3B,GAAI,IAAQ,IAAA,GAAW,CACrB,IAAM,EAAW,OAAO,KAAK,EAAQ,MAAM,EAIvC,EAAa,EAAS,WAAa,IACrC,EAAG,cAAc,EAAK,CAAC,EACvB,EAAa,GAEf,EAAG,UAAU,EAAK,CAAQ,EAC1B,GAAc,EAAS,UACzB,CACA,IAAM,EAAO,EAAoB,CAAM,EACvC,GAAI,CAAC,EAAM,SACX,IAAM,EAAQ,OAAO,KAAK,EAAM,MAAM,EACtC,EAAG,UAAU,EAAQ,CAAK,EAC1B,GAAW,EAAM,WACjB,GAAU,CACZ,CAUA,OATA,EAAG,UAAU,CAAM,EACf,IAAQ,IAAA,IAAW,EAAG,UAAU,CAAG,EACvC,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,CAGA,SAAS,EAAQ,EAAwB,CACvC,OAAO,EAAG,SAAS,EAAQ,GAAG,CAChC,CAEA,SAAS,EAAQ,EAAwB,CACvC,GAAI,CACF,OAAO,EAAG,SAAS,CAAM,CAAC,CAAC,IAC7B,MAAQ,CACN,MAAO,EACT,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,5 +1,4 @@
1
1
  //#region src/bin/runnerHost.d.ts
2
- declare function main(argv?: readonly string[]): Promise<number>;
2
+ export declare function main(argv?: readonly string[]): Promise<number>;
3
3
  //#endregion
4
- export { main };
5
4
  //# sourceMappingURL=runnerHost.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runnerHost.d.cts","names":[],"sources":["../../src/bin/runnerHost.ts"],"mappings":";iBAkBsB,KAAK,2BAAkD"}
1
+ {"version":3,"file":"runnerHost.d.cts","names":[],"sources":["../../src/bin/runnerHost.ts"],"mappings":";wBAkBsB,KAAK,2BAAkD"}
@@ -1,5 +1,4 @@
1
1
  //#region src/bin/runnerHost.d.ts
2
- declare function main(argv?: readonly string[]): Promise<number>;
2
+ export declare function main(argv?: readonly string[]): Promise<number>;
3
3
  //#endregion
4
- export { main };
5
4
  //# sourceMappingURL=runnerHost.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runnerHost.d.mts","names":[],"sources":["../../src/bin/runnerHost.ts"],"mappings":";iBAkBsB,KAAK,2BAAkD"}
1
+ {"version":3,"file":"runnerHost.d.mts","names":[],"sources":["../../src/bin/runnerHost.ts"],"mappings":";wBAkBsB,KAAK,2BAAkD"}
@@ -6,7 +6,7 @@ import { BashRunRequest, BashRunResult, IBashRunService } from "../../types/bash
6
6
  import { IClock } from "../../types/clock.cjs";
7
7
  import { IRunnerNamer } from "../../services/RunnerNamer/types.cjs";
8
8
  //#region src/adapters/BashRunService/BashRunService.d.ts
9
- declare class BashRunService implements IBashRunService {
9
+ export declare class BashRunService implements IBashRunService {
10
10
  private readonly launcher;
11
11
  private readonly rmuxBackend;
12
12
  private readonly namer;
@@ -28,5 +28,4 @@ declare class BashRunService implements IBashRunService {
28
28
  private promote;
29
29
  }
30
30
  //#endregion
31
- export { BashRunService };
32
31
  //# sourceMappingURL=BashRunService.d.cts.map
@@ -1 +1 @@
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
+ {"version":3,"file":"BashRunService.d.cts","names":[],"sources":["../../../../src/adapters/BashRunService/BashRunService.ts"],"mappings":";;;;;;;;qBAiCa,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"}
@@ -6,7 +6,7 @@ import { BashRunRequest, BashRunResult, IBashRunService } from "../../types/bash
6
6
  import { IClock } from "../../types/clock.mjs";
7
7
  import { IRunnerNamer } from "../../services/RunnerNamer/types.mjs";
8
8
  //#region src/adapters/BashRunService/BashRunService.d.ts
9
- declare class BashRunService implements IBashRunService {
9
+ export declare class BashRunService implements IBashRunService {
10
10
  private readonly launcher;
11
11
  private readonly rmuxBackend;
12
12
  private readonly namer;
@@ -28,5 +28,4 @@ declare class BashRunService implements IBashRunService {
28
28
  private promote;
29
29
  }
30
30
  //#endregion
31
- export { BashRunService };
32
31
  //# sourceMappingURL=BashRunService.d.mts.map
@@ -1 +1 @@
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
+ {"version":3,"file":"BashRunService.d.mts","names":[],"sources":["../../../../src/adapters/BashRunService/BashRunService.ts"],"mappings":";;;;;;;;qBAiCa,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,10 +1,9 @@
1
1
  import { IClock } from "../../types/clock.cjs";
2
2
  //#region src/adapters/Clock/SystemClock.d.ts
3
3
  /** Real wall clock and timers. */
4
- declare class SystemClock implements IClock {
4
+ export declare class SystemClock implements IClock {
5
5
  now(): number;
6
6
  after(ms: number, handler: () => void): () => void;
7
7
  }
8
8
  //#endregion
9
- export { SystemClock };
10
9
  //# sourceMappingURL=SystemClock.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SystemClock.d.cts","names":[],"sources":["../../../../src/adapters/Clock/SystemClock.ts"],"mappings":";;;cAGa,uBAAuB;EAClC;EAIA,MAAM,YAAY"}
1
+ {"version":3,"file":"SystemClock.d.cts","names":[],"sources":["../../../../src/adapters/Clock/SystemClock.ts"],"mappings":";;;qBAGa,uBAAuB;EAClC;EAIA,MAAM,YAAY"}
@@ -1,10 +1,9 @@
1
1
  import { IClock } from "../../types/clock.mjs";
2
2
  //#region src/adapters/Clock/SystemClock.d.ts
3
3
  /** Real wall clock and timers. */
4
- declare class SystemClock implements IClock {
4
+ export declare class SystemClock implements IClock {
5
5
  now(): number;
6
6
  after(ms: number, handler: () => void): () => void;
7
7
  }
8
8
  //#endregion
9
- export { SystemClock };
10
9
  //# sourceMappingURL=SystemClock.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SystemClock.d.mts","names":[],"sources":["../../../../src/adapters/Clock/SystemClock.ts"],"mappings":";;;cAGa,uBAAuB;EAClC;EAIA,MAAM,YAAY"}
1
+ {"version":3,"file":"SystemClock.d.mts","names":[],"sources":["../../../../src/adapters/Clock/SystemClock.ts"],"mappings":";;;qBAGa,uBAAuB;EAClC;EAIA,MAAM,YAAY"}
@@ -5,7 +5,7 @@ import { ILogFile } from "../../types/logFile.cjs";
5
5
  import { IProcessControl } from "../../types/processControl.cjs";
6
6
  import { IRunnerPaths } from "../../services/RunnerPaths/types.cjs";
7
7
  //#region src/adapters/Launcher/Launcher.d.ts
8
- declare class Launcher implements ILauncher {
8
+ export declare class Launcher implements ILauncher {
9
9
  private readonly spawner;
10
10
  private readonly processControl;
11
11
  private readonly logFile;
@@ -17,5 +17,4 @@ declare class Launcher implements ILauncher {
17
17
  private sleep;
18
18
  }
19
19
  //#endregion
20
- export { Launcher };
21
20
  //# sourceMappingURL=Launcher.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Launcher.d.cts","names":[],"sources":["../../../../src/adapters/Launcher/Launcher.ts"],"mappings":";;;;;;;cA+Ba,oBAAoB;mBAEZ;mBACA;mBACA;mBACA;mBACA;EALnB,YACmB,SAAS,UACT,gBAAgB,iBAChB,SAAS,UACT,OAAO,QACP,OAAO;EAG1B,OAAO,SAAS,gBAAgB;EAgG1B,KAAK,cAAc;UAcjB"}
1
+ {"version":3,"file":"Launcher.d.cts","names":[],"sources":["../../../../src/adapters/Launcher/Launcher.ts"],"mappings":";;;;;;;qBA+Ba,oBAAoB;mBAEZ;mBACA;mBACA;mBACA;mBACA;EALnB,YACmB,SAAS,UACT,gBAAgB,iBAChB,SAAS,UACT,OAAO,QACP,OAAO;EAG1B,OAAO,SAAS,gBAAgB;EAgG1B,KAAK,cAAc;UAcjB"}
@@ -5,7 +5,7 @@ import { ILogFile } from "../../types/logFile.mjs";
5
5
  import { IProcessControl } from "../../types/processControl.mjs";
6
6
  import { IRunnerPaths } from "../../services/RunnerPaths/types.mjs";
7
7
  //#region src/adapters/Launcher/Launcher.d.ts
8
- declare class Launcher implements ILauncher {
8
+ export declare class Launcher implements ILauncher {
9
9
  private readonly spawner;
10
10
  private readonly processControl;
11
11
  private readonly logFile;
@@ -17,5 +17,4 @@ declare class Launcher implements ILauncher {
17
17
  private sleep;
18
18
  }
19
19
  //#endregion
20
- export { Launcher };
21
20
  //# sourceMappingURL=Launcher.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Launcher.d.mts","names":[],"sources":["../../../../src/adapters/Launcher/Launcher.ts"],"mappings":";;;;;;;cA+Ba,oBAAoB;mBAEZ;mBACA;mBACA;mBACA;mBACA;EALnB,YACmB,SAAS,UACT,gBAAgB,iBAChB,SAAS,UACT,OAAO,QACP,OAAO;EAG1B,OAAO,SAAS,gBAAgB;EAgG1B,KAAK,cAAc;UAcjB"}
1
+ {"version":3,"file":"Launcher.d.mts","names":[],"sources":["../../../../src/adapters/Launcher/Launcher.ts"],"mappings":";;;;;;;qBA+Ba,oBAAoB;mBAEZ;mBACA;mBACA;mBACA;mBACA;EALnB,YACmB,SAAS,UACT,gBAAgB,iBAChB,SAAS,UACT,OAAO,QACP,OAAO;EAG1B,OAAO,SAAS,gBAAgB;EAgG1B,KAAK,cAAc;UAcjB"}
@@ -1,7 +1,7 @@
1
1
  import { ILifeline } from "../../types/lifeline.cjs";
2
2
  import { IRunnerPaths } from "../../services/RunnerPaths/types.cjs";
3
3
  //#region src/adapters/Lifeline/NodeLifeline.d.ts
4
- declare class NodeLifeline implements ILifeline {
4
+ export declare class NodeLifeline implements ILifeline {
5
5
  private readonly paths;
6
6
  private server;
7
7
  private target;
@@ -15,5 +15,4 @@ declare class NodeLifeline implements ILifeline {
15
15
  private socketPath;
16
16
  }
17
17
  //#endregion
18
- export { NodeLifeline };
19
18
  //# sourceMappingURL=NodeLifeline.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NodeLifeline.d.cts","names":[],"sources":["../../../../src/adapters/Lifeline/NodeLifeline.ts"],"mappings":";;;cAea,wBAAwB;mBAMN;UALrB;UACA;;mBAES;EAEjB,YAA6B,OAAO;EAE9B,IAAI,oBAAoB;EA8B9B;EAIA;;UAyBQ"}
1
+ {"version":3,"file":"NodeLifeline.d.cts","names":[],"sources":["../../../../src/adapters/Lifeline/NodeLifeline.ts"],"mappings":";;;qBAea,wBAAwB;mBAMN;UALrB;UACA;;mBAES;EAEjB,YAA6B,OAAO;EAE9B,IAAI,oBAAoB;EA8B9B;EAIA;;UAyBQ"}
@@ -1,7 +1,7 @@
1
1
  import { ILifeline } from "../../types/lifeline.mjs";
2
2
  import { IRunnerPaths } from "../../services/RunnerPaths/types.mjs";
3
3
  //#region src/adapters/Lifeline/NodeLifeline.d.ts
4
- declare class NodeLifeline implements ILifeline {
4
+ export declare class NodeLifeline implements ILifeline {
5
5
  private readonly paths;
6
6
  private server;
7
7
  private target;
@@ -15,5 +15,4 @@ declare class NodeLifeline implements ILifeline {
15
15
  private socketPath;
16
16
  }
17
17
  //#endregion
18
- export { NodeLifeline };
19
18
  //# sourceMappingURL=NodeLifeline.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NodeLifeline.d.mts","names":[],"sources":["../../../../src/adapters/Lifeline/NodeLifeline.ts"],"mappings":";;;cAea,wBAAwB;mBAMN;UALrB;UACA;;mBAES;EAEjB,YAA6B,OAAO;EAE9B,IAAI,oBAAoB;EA8B9B;EAIA;;UAyBQ"}
1
+ {"version":3,"file":"NodeLifeline.d.mts","names":[],"sources":["../../../../src/adapters/Lifeline/NodeLifeline.ts"],"mappings":";;;qBAea,wBAAwB;mBAMN;UALrB;UACA;;mBAES;EAEjB,YAA6B,OAAO;EAE9B,IAAI,oBAAoB;EA8B9B;EAIA;;UAyBQ"}
@@ -1,6 +1,6 @@
1
1
  //#region src/adapters/Lifeline/client.d.ts
2
2
  /** Environment variable carrying the lifeline socket path to every runner supervisor. */
3
- declare const LIFELINE_ENV = "DOOM_RUNNER_LIFELINE";
3
+ export declare const LIFELINE_ENV = "DOOM_RUNNER_LIFELINE";
4
4
  /**
5
5
  * Reports the owning pi process dying to a runner's supervisor.
6
6
  *
@@ -17,7 +17,6 @@ declare const LIFELINE_ENV = "DOOM_RUNNER_LIFELINE";
17
17
  * Runners run unwatched when no lifeline is armed, so a missing environment
18
18
  * variable can never be mistaken for a dead owner.
19
19
  */
20
- declare function watchOwner(onOwnerLost: () => void, target?: string | undefined): () => void;
20
+ export declare function watchOwner(onOwnerLost: () => void, target?: string | undefined): () => void;
21
21
  //#endregion
22
- export { LIFELINE_ENV, watchOwner };
23
22
  //# sourceMappingURL=client.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.cts","names":[],"sources":["../../../../src/adapters/Lifeline/client.ts"],"mappings":";;cAGa;;;;;;;;;;;;;;;;;iBAkBG,WACd,yBACA"}
1
+ {"version":3,"file":"client.d.cts","names":[],"sources":["../../../../src/adapters/Lifeline/client.ts"],"mappings":";;qBAGa;;;;;;;;;;;;;;;;;wBAkBG,WACd,yBACA"}
@@ -1,6 +1,6 @@
1
1
  //#region src/adapters/Lifeline/client.d.ts
2
2
  /** Environment variable carrying the lifeline socket path to every runner supervisor. */
3
- declare const LIFELINE_ENV = "DOOM_RUNNER_LIFELINE";
3
+ export declare const LIFELINE_ENV = "DOOM_RUNNER_LIFELINE";
4
4
  /**
5
5
  * Reports the owning pi process dying to a runner's supervisor.
6
6
  *
@@ -17,7 +17,6 @@ declare const LIFELINE_ENV = "DOOM_RUNNER_LIFELINE";
17
17
  * Runners run unwatched when no lifeline is armed, so a missing environment
18
18
  * variable can never be mistaken for a dead owner.
19
19
  */
20
- declare function watchOwner(onOwnerLost: () => void, target?: string | undefined): () => void;
20
+ export declare function watchOwner(onOwnerLost: () => void, target?: string | undefined): () => void;
21
21
  //#endregion
22
- export { LIFELINE_ENV, watchOwner };
23
22
  //# sourceMappingURL=client.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.mts","names":[],"sources":["../../../../src/adapters/Lifeline/client.ts"],"mappings":";;cAGa;;;;;;;;;;;;;;;;;iBAkBG,WACd,yBACA"}
1
+ {"version":3,"file":"client.d.mts","names":[],"sources":["../../../../src/adapters/Lifeline/client.ts"],"mappings":";;qBAGa;;;;;;;;;;;;;;;;;wBAkBG,WACd,yBACA"}
@@ -1,11 +1,10 @@
1
1
  import { ILogFile, LogWriter } from "../../types/logFile.cjs";
2
2
  import { IRunnerPaths } from "../../services/RunnerPaths/types.cjs";
3
3
  //#region src/adapters/LogFile/LogFile.d.ts
4
- declare class LogFile implements ILogFile {
4
+ export declare class LogFile implements ILogFile {
5
5
  private readonly paths;
6
6
  constructor(paths: IRunnerPaths);
7
7
  open(id: string): LogWriter;
8
8
  }
9
9
  //#endregion
10
- export { LogFile };
11
10
  //# sourceMappingURL=LogFile.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LogFile.d.cts","names":[],"sources":["../../../../src/adapters/LogFile/LogFile.ts"],"mappings":";;;cAKa,mBAAmB;mBACD;EAA7B,YAA6B,OAAO;EAEpC,KAAK,aAAa"}
1
+ {"version":3,"file":"LogFile.d.cts","names":[],"sources":["../../../../src/adapters/LogFile/LogFile.ts"],"mappings":";;;qBAKa,mBAAmB;mBACD;EAA7B,YAA6B,OAAO;EAEpC,KAAK,aAAa"}
@@ -1,11 +1,10 @@
1
1
  import { ILogFile, LogWriter } from "../../types/logFile.mjs";
2
2
  import { IRunnerPaths } from "../../services/RunnerPaths/types.mjs";
3
3
  //#region src/adapters/LogFile/LogFile.d.ts
4
- declare class LogFile implements ILogFile {
4
+ export declare class LogFile implements ILogFile {
5
5
  private readonly paths;
6
6
  constructor(paths: IRunnerPaths);
7
7
  open(id: string): LogWriter;
8
8
  }
9
9
  //#endregion
10
- export { LogFile };
11
10
  //# sourceMappingURL=LogFile.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LogFile.d.mts","names":[],"sources":["../../../../src/adapters/LogFile/LogFile.ts"],"mappings":";;;cAKa,mBAAmB;mBACD;EAA7B,YAA6B,OAAO;EAEpC,KAAK,aAAa"}
1
+ {"version":3,"file":"LogFile.d.mts","names":[],"sources":["../../../../src/adapters/LogFile/LogFile.ts"],"mappings":";;;qBAKa,mBAAmB;mBACD;EAA7B,YAA6B,OAAO;EAEpC,KAAK,aAAa"}
@@ -1,8 +1,8 @@
1
- const e=require("../../../_virtual/_rolldown/runtime.cjs");let t=require("node:fs");t=e.__toESM(t,1);let n=require("node:string_decoder");var r=class{read(e,n={}){let r;try{return r=t.default.openSync(e,`r`),{...i(r,n),fileSize:t.default.fstatSync(r).size,path:e,exists:!0}}catch(t){if(t.code!==`ENOENT`)throw t;return{text:``,lineCount:0,totalLines:0,fileSize:0,path:e,exists:!1}}finally{r!==void 0&&t.default.closeSync(r)}}};function i(e,r){let i=Math.max(0,Math.floor(r.lines??200)),a=r.grep?r.ignoreCase?r.grep.toLowerCase():r.grep:void 0,o=Math.max(0,Math.floor(r.contextLines??0)),s=new n.StringDecoder(`utf8`),c=Buffer.alloc(65536),l=[],u=[],d=``,f=0,p=-1,m=-1,h,g=e=>{i!==0&&(u.push(e),u.length>i&&u.shift())},_=e=>{e.index<=m||(m=e.index,g(e.text))},v=e=>{let t={index:f,text:e};if(f+=1,!a){g(e);return}if((r.ignoreCase?e.toLowerCase():e).includes(a)){for(let e of l)_(e);_(t),p=Math.max(p,t.index+o)}else t.index<=p&&_(t);l.push(t),l.length>o&&l.shift()};for(;;){let n=t.default.readSync(e,c,0,c.byteLength,null);if(n===0)break;h=c[n-1],d+=s.write(c.subarray(0,n));let r=d.indexOf(`
2
- `);for(;r>=0;)v(d.slice(0,r)),d=d.slice(r+1),r=d.indexOf(`
3
- `)}d+=s.end(),d.length>0&&v(d);let y=h===10;return{text:`${u.join(`
4
- `)}${!a&&y&&u.length>0?`
5
- `:``}`,lineCount:u.length,totalLines:f}}function a(e,t){if(!t.grep)return e;let n=e.split(`
1
+ const e=require("../../../_virtual/_rolldown/runtime.cjs");let t=require("node:fs");t=e.__toESM(t,1);let n=require("node:string_decoder");var r=class{read(e,n={}){let r;try{return r=t.default.openSync(e,`r`),{...i(r,n),fileSize:t.default.fstatSync(r).size,path:e,exists:!0}}catch(t){if(t.code!==`ENOENT`)throw t;return{text:``,lineCount:0,totalLines:0,fileSize:0,completeBytes:0,path:e,exists:!1}}finally{r!==void 0&&t.default.closeSync(r)}}};function i(e,r){let i=Math.max(0,Math.floor(r.lines??200)),a=r.grep?r.ignoreCase?r.grep.toLowerCase():r.grep:void 0,o=Math.max(0,Math.floor(r.contextLines??0)),s=new n.StringDecoder(`utf8`),c=Buffer.alloc(65536),l=[],u=[],d=``,f=0,p=-1,m=-1,h,g=0,_=0,v=e=>{i!==0&&(u.push(e),u.length>i&&u.shift())},y=e=>{e.index<=m||(m=e.index,v(e))},b=e=>{let t={index:f,text:e};if(f+=1,!a){v(t);return}if((r.ignoreCase?e.toLowerCase():e).includes(a)){for(let e of l)y(e);y(t),p=Math.max(p,t.index+o)}else t.index<=p&&y(t);l.push(t),l.length>o&&l.shift()};for(;;){let n=t.default.readSync(e,c,0,c.byteLength,null);if(n===0)break;h=c[n-1];let r=c.subarray(0,n).lastIndexOf(10);r>=0&&(_=g+r+1),g+=n,d+=s.write(c.subarray(0,n));let i=d.indexOf(`
2
+ `);for(;i>=0;)b(d.slice(0,i)),d=d.slice(i+1),i=d.indexOf(`
3
+ `)}d+=s.end(),d.length>0&&b(d);let x=h===10,S={text:`${u.map(e=>e.text).join(`
4
+ `)}${!a&&x&&u.length>0?`
5
+ `:``}`,lineCount:u.length,totalLines:f,completeBytes:_};return a?{...S,lineNumbers:u.map(e=>e.index+1)}:S}function a(e,t){if(!t.grep)return e;let n=e.split(`
6
6
  `),r=t.ignoreCase?t.grep.toLowerCase():t.grep,i=Math.max(0,t.contextLines??0),a=[];if(n.forEach((e,o)=>{(t.ignoreCase?e.toLowerCase():e).includes(r)&&a.push({start:Math.max(0,o-i),end:Math.min(n.length-1,o+i)})}),a.length===0)return``;let o=[];for(let e of a){let t=o.at(-1);t&&e.start<=t.end+1?t.end=Math.max(t.end,e.end):o.push({...e})}return o.flatMap(e=>n.slice(e.start,e.end+1)).join(`
7
7
  `)}exports.LogReader=r,exports.filterLogText=a;
8
8
  //# sourceMappingURL=LogReader.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"LogReader.cjs","names":["fs","StringDecoder"],"sources":["../../../../src/adapters/LogReader/LogReader.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { StringDecoder } from 'node:string_decoder';\nimport type { ILogReader, LogQuery, LogSlice } from '../../types/logReader';\n\nconst DEFAULT_LINES = 200;\nconst READ_CHUNK_BYTES = 64 * 1024;\n\ninterface IndexedLine {\n readonly index: number;\n readonly text: string;\n}\n\ninterface ScannedLog {\n readonly text: string;\n readonly lineCount: number;\n readonly totalLines: number;\n}\n\nexport class LogReader implements ILogReader {\n read(logPath: string, query: LogQuery = {}): LogSlice {\n let handle: number | undefined;\n try {\n handle = fs.openSync(logPath, 'r');\n const scanned = scanLog(handle, query);\n return {\n ...scanned,\n fileSize: fs.fstatSync(handle).size,\n path: logPath,\n exists: true,\n };\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n return { text: '', lineCount: 0, totalLines: 0, fileSize: 0, path: logPath, exists: false };\n } finally {\n if (handle !== undefined) fs.closeSync(handle);\n }\n }\n}\n\nfunction scanLog(handle: number, query: LogQuery): ScannedLog {\n const limit = Math.max(0, Math.floor(query.lines ?? DEFAULT_LINES));\n const needle = query.grep ? (query.ignoreCase ? query.grep.toLowerCase() : query.grep) : undefined;\n const contextLines = Math.max(0, Math.floor(query.contextLines ?? 0));\n const decoder = new StringDecoder('utf8');\n const buffer = Buffer.alloc(READ_CHUNK_BYTES);\n const before: IndexedLine[] = [];\n const output: string[] = [];\n let pending = '';\n let totalLines = 0;\n let afterThrough = -1;\n let lastEmitted = -1;\n let lastByte: number | undefined;\n\n const retain = (line: string): void => {\n if (limit === 0) return;\n output.push(line);\n if (output.length > limit) output.shift();\n };\n const emit = (line: IndexedLine): void => {\n if (line.index <= lastEmitted) return;\n lastEmitted = line.index;\n retain(line.text);\n };\n const consume = (text: string): void => {\n const line = { index: totalLines, text };\n totalLines += 1;\n if (!needle) {\n retain(text);\n return;\n }\n\n const haystack = query.ignoreCase ? text.toLowerCase() : text;\n if (haystack.includes(needle)) {\n for (const previous of before) emit(previous);\n emit(line);\n afterThrough = Math.max(afterThrough, line.index + contextLines);\n } else if (line.index <= afterThrough) {\n emit(line);\n }\n before.push(line);\n if (before.length > contextLines) before.shift();\n };\n\n for (;;) {\n const bytesRead = fs.readSync(handle, buffer, 0, buffer.byteLength, null);\n if (bytesRead === 0) break;\n lastByte = buffer[bytesRead - 1];\n pending += decoder.write(buffer.subarray(0, bytesRead));\n let newline = pending.indexOf('\\n');\n while (newline >= 0) {\n consume(pending.slice(0, newline));\n pending = pending.slice(newline + 1);\n newline = pending.indexOf('\\n');\n }\n }\n pending += decoder.end();\n if (pending.length > 0) consume(pending);\n\n const trailingNewline = lastByte === 0x0a;\n const text = `${output.join('\\n')}${!needle && trailingNewline && output.length > 0 ? '\\n' : ''}`;\n return { text, lineCount: output.length, totalLines };\n}\n\n/**\n * Grep with context, matching the `product-stack logs` semantics so the two\n * surfaces behave the same. Overlapping and adjacent context windows merge.\n */\nexport function filterLogText(text: string, query: Pick<LogQuery, 'grep' | 'ignoreCase' | 'contextLines'>): string {\n if (!query.grep) return text;\n const lines = text.split('\\n');\n const needle = query.ignoreCase ? query.grep.toLowerCase() : query.grep;\n const contextLines = Math.max(0, query.contextLines ?? 0);\n const ranges: Array<{ start: number; end: number }> = [];\n\n lines.forEach((line, index) => {\n const haystack = query.ignoreCase ? line.toLowerCase() : line;\n if (!haystack.includes(needle)) return;\n ranges.push({\n start: Math.max(0, index - contextLines),\n end: Math.min(lines.length - 1, index + contextLines),\n });\n });\n\n if (ranges.length === 0) return '';\n const merged: Array<{ start: number; end: number }> = [];\n for (const range of ranges) {\n const previous = merged.at(-1);\n if (previous && range.start <= previous.end + 1) {\n previous.end = Math.max(previous.end, range.end);\n } else {\n merged.push({ ...range });\n }\n }\n return merged.flatMap((range) => lines.slice(range.start, range.end + 1)).join('\\n');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"LogReader.cjs","names":["fs","StringDecoder"],"sources":["../../../../src/adapters/LogReader/LogReader.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { StringDecoder } from 'node:string_decoder';\nimport type { ILogReader, LogQuery, LogSlice } from '../../types/logReader';\n\nconst DEFAULT_LINES = 200;\nconst READ_CHUNK_BYTES = 64 * 1024;\n\ninterface IndexedLine {\n readonly index: number;\n readonly text: string;\n}\n\ninterface ScannedLog {\n readonly text: string;\n readonly lineCount: number;\n readonly totalLines: number;\n readonly completeBytes: number;\n readonly lineNumbers?: number[];\n}\n\nexport class LogReader implements ILogReader {\n read(logPath: string, query: LogQuery = {}): LogSlice {\n let handle: number | undefined;\n try {\n handle = fs.openSync(logPath, 'r');\n const scanned = scanLog(handle, query);\n return {\n ...scanned,\n fileSize: fs.fstatSync(handle).size,\n path: logPath,\n exists: true,\n };\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n return {\n text: '',\n lineCount: 0,\n totalLines: 0,\n fileSize: 0,\n completeBytes: 0,\n path: logPath,\n exists: false,\n };\n } finally {\n if (handle !== undefined) fs.closeSync(handle);\n }\n }\n}\n\nfunction scanLog(handle: number, query: LogQuery): ScannedLog {\n const limit = Math.max(0, Math.floor(query.lines ?? DEFAULT_LINES));\n const needle = query.grep ? (query.ignoreCase ? query.grep.toLowerCase() : query.grep) : undefined;\n const contextLines = Math.max(0, Math.floor(query.contextLines ?? 0));\n const decoder = new StringDecoder('utf8');\n const buffer = Buffer.alloc(READ_CHUNK_BYTES);\n const before: IndexedLine[] = [];\n const output: IndexedLine[] = [];\n let pending = '';\n let totalLines = 0;\n let afterThrough = -1;\n let lastEmitted = -1;\n let lastByte: number | undefined;\n let bytesSeen = 0;\n let completeBytes = 0;\n\n const retain = (line: IndexedLine): void => {\n if (limit === 0) return;\n output.push(line);\n if (output.length > limit) output.shift();\n };\n const emit = (line: IndexedLine): void => {\n if (line.index <= lastEmitted) return;\n lastEmitted = line.index;\n retain(line);\n };\n const consume = (text: string): void => {\n const line = { index: totalLines, text };\n totalLines += 1;\n if (!needle) {\n retain(line);\n return;\n }\n\n const haystack = query.ignoreCase ? text.toLowerCase() : text;\n if (haystack.includes(needle)) {\n for (const previous of before) emit(previous);\n emit(line);\n afterThrough = Math.max(afterThrough, line.index + contextLines);\n } else if (line.index <= afterThrough) {\n emit(line);\n }\n before.push(line);\n if (before.length > contextLines) before.shift();\n };\n\n for (;;) {\n const bytesRead = fs.readSync(handle, buffer, 0, buffer.byteLength, null);\n if (bytesRead === 0) break;\n lastByte = buffer[bytesRead - 1];\n // A newline is a single byte in UTF-8 and never a continuation byte, so the\n // last one in this chunk ends the last complete line seen so far.\n const lastNewline = buffer.subarray(0, bytesRead).lastIndexOf(0x0a);\n if (lastNewline >= 0) completeBytes = bytesSeen + lastNewline + 1;\n bytesSeen += bytesRead;\n pending += decoder.write(buffer.subarray(0, bytesRead));\n let newline = pending.indexOf('\\n');\n while (newline >= 0) {\n consume(pending.slice(0, newline));\n pending = pending.slice(newline + 1);\n newline = pending.indexOf('\\n');\n }\n }\n pending += decoder.end();\n if (pending.length > 0) consume(pending);\n\n const trailingNewline = lastByte === 0x0a;\n const body = output.map((line) => line.text).join('\\n');\n const text = `${body}${!needle && trailingNewline && output.length > 0 ? '\\n' : ''}`;\n const scanned: ScannedLog = { text, lineCount: output.length, totalLines, completeBytes };\n if (!needle) return scanned;\n return { ...scanned, lineNumbers: output.map((line) => line.index + 1) };\n}\n\n/**\n * Grep with context, matching the `product-stack logs` semantics so the two\n * surfaces behave the same. Overlapping and adjacent context windows merge.\n */\nexport function filterLogText(text: string, query: Pick<LogQuery, 'grep' | 'ignoreCase' | 'contextLines'>): string {\n if (!query.grep) return text;\n const lines = text.split('\\n');\n const needle = query.ignoreCase ? query.grep.toLowerCase() : query.grep;\n const contextLines = Math.max(0, query.contextLines ?? 0);\n const ranges: Array<{ start: number; end: number }> = [];\n\n lines.forEach((line, index) => {\n const haystack = query.ignoreCase ? line.toLowerCase() : line;\n if (!haystack.includes(needle)) return;\n ranges.push({\n start: Math.max(0, index - contextLines),\n end: Math.min(lines.length - 1, index + contextLines),\n });\n });\n\n if (ranges.length === 0) return '';\n const merged: Array<{ start: number; end: number }> = [];\n for (const range of ranges) {\n const previous = merged.at(-1);\n if (previous && range.start <= previous.end + 1) {\n previous.end = Math.max(previous.end, range.end);\n } else {\n merged.push({ ...range });\n }\n }\n return merged.flatMap((range) => lines.slice(range.start, range.end + 1)).join('\\n');\n}\n"],"mappings":"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"}
@@ -1,13 +1,12 @@
1
1
  import { ILogReader, LogQuery, LogSlice } from "../../types/logReader.cjs";
2
2
  //#region src/adapters/LogReader/LogReader.d.ts
3
- declare class LogReader implements ILogReader {
3
+ export declare class LogReader implements ILogReader {
4
4
  read(logPath: string, query?: LogQuery): LogSlice;
5
5
  }
6
6
  /**
7
7
  * Grep with context, matching the `product-stack logs` semantics so the two
8
8
  * surfaces behave the same. Overlapping and adjacent context windows merge.
9
9
  */
10
- declare function filterLogText(text: string, query: Pick<LogQuery, 'grep' | 'ignoreCase' | 'contextLines'>): string;
10
+ export declare function filterLogText(text: string, query: Pick<LogQuery, 'grep' | 'ignoreCase' | 'contextLines'>): string;
11
11
  //#endregion
12
- export { LogReader, filterLogText };
13
12
  //# sourceMappingURL=LogReader.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LogReader.d.cts","names":[],"sources":["../../../../src/adapters/LogReader/LogReader.ts"],"mappings":";;cAkBa,qBAAqB;EAChC,KAAK,iBAAiB,QAAO,WAAgB;;;;;;iBAwF/B,cAAc,cAAc,OAAO,KAAK"}
1
+ {"version":3,"file":"LogReader.d.cts","names":[],"sources":["../../../../src/adapters/LogReader/LogReader.ts"],"mappings":";;qBAoBa,qBAAqB;EAChC,KAAK,iBAAiB,QAAO,WAAgB;;;;;;wBA0G/B,cAAc,cAAc,OAAO,KAAK"}
@@ -1,13 +1,12 @@
1
1
  import { ILogReader, LogQuery, LogSlice } from "../../types/logReader.mjs";
2
2
  //#region src/adapters/LogReader/LogReader.d.ts
3
- declare class LogReader implements ILogReader {
3
+ export declare class LogReader implements ILogReader {
4
4
  read(logPath: string, query?: LogQuery): LogSlice;
5
5
  }
6
6
  /**
7
7
  * Grep with context, matching the `product-stack logs` semantics so the two
8
8
  * surfaces behave the same. Overlapping and adjacent context windows merge.
9
9
  */
10
- declare function filterLogText(text: string, query: Pick<LogQuery, 'grep' | 'ignoreCase' | 'contextLines'>): string;
10
+ export declare function filterLogText(text: string, query: Pick<LogQuery, 'grep' | 'ignoreCase' | 'contextLines'>): string;
11
11
  //#endregion
12
- export { LogReader, filterLogText };
13
12
  //# sourceMappingURL=LogReader.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LogReader.d.mts","names":[],"sources":["../../../../src/adapters/LogReader/LogReader.ts"],"mappings":";;cAkBa,qBAAqB;EAChC,KAAK,iBAAiB,QAAO,WAAgB;;;;;;iBAwF/B,cAAc,cAAc,OAAO,KAAK"}
1
+ {"version":3,"file":"LogReader.d.mts","names":[],"sources":["../../../../src/adapters/LogReader/LogReader.ts"],"mappings":";;qBAoBa,qBAAqB;EAChC,KAAK,iBAAiB,QAAO,WAAgB;;;;;;wBA0G/B,cAAc,cAAc,OAAO,KAAK"}
@@ -1,8 +1,8 @@
1
- import e from"node:fs";import{StringDecoder as t}from"node:string_decoder";var n=class{read(t,n={}){let i;try{return i=e.openSync(t,`r`),{...r(i,n),fileSize:e.fstatSync(i).size,path:t,exists:!0}}catch(e){if(e.code!==`ENOENT`)throw e;return{text:``,lineCount:0,totalLines:0,fileSize:0,path:t,exists:!1}}finally{i!==void 0&&e.closeSync(i)}}};function r(n,r){let i=Math.max(0,Math.floor(r.lines??200)),a=r.grep?r.ignoreCase?r.grep.toLowerCase():r.grep:void 0,o=Math.max(0,Math.floor(r.contextLines??0)),s=new t(`utf8`),c=Buffer.alloc(65536),l=[],u=[],d=``,f=0,p=-1,m=-1,h,g=e=>{i!==0&&(u.push(e),u.length>i&&u.shift())},_=e=>{e.index<=m||(m=e.index,g(e.text))},v=e=>{let t={index:f,text:e};if(f+=1,!a){g(e);return}if((r.ignoreCase?e.toLowerCase():e).includes(a)){for(let e of l)_(e);_(t),p=Math.max(p,t.index+o)}else t.index<=p&&_(t);l.push(t),l.length>o&&l.shift()};for(;;){let t=e.readSync(n,c,0,c.byteLength,null);if(t===0)break;h=c[t-1],d+=s.write(c.subarray(0,t));let r=d.indexOf(`
2
- `);for(;r>=0;)v(d.slice(0,r)),d=d.slice(r+1),r=d.indexOf(`
3
- `)}d+=s.end(),d.length>0&&v(d);let y=h===10;return{text:`${u.join(`
4
- `)}${!a&&y&&u.length>0?`
5
- `:``}`,lineCount:u.length,totalLines:f}}function i(e,t){if(!t.grep)return e;let n=e.split(`
1
+ import e from"node:fs";import{StringDecoder as t}from"node:string_decoder";var n=class{read(t,n={}){let i;try{return i=e.openSync(t,`r`),{...r(i,n),fileSize:e.fstatSync(i).size,path:t,exists:!0}}catch(e){if(e.code!==`ENOENT`)throw e;return{text:``,lineCount:0,totalLines:0,fileSize:0,completeBytes:0,path:t,exists:!1}}finally{i!==void 0&&e.closeSync(i)}}};function r(n,r){let i=Math.max(0,Math.floor(r.lines??200)),a=r.grep?r.ignoreCase?r.grep.toLowerCase():r.grep:void 0,o=Math.max(0,Math.floor(r.contextLines??0)),s=new t(`utf8`),c=Buffer.alloc(65536),l=[],u=[],d=``,f=0,p=-1,m=-1,h,g=0,_=0,v=e=>{i!==0&&(u.push(e),u.length>i&&u.shift())},y=e=>{e.index<=m||(m=e.index,v(e))},b=e=>{let t={index:f,text:e};if(f+=1,!a){v(t);return}if((r.ignoreCase?e.toLowerCase():e).includes(a)){for(let e of l)y(e);y(t),p=Math.max(p,t.index+o)}else t.index<=p&&y(t);l.push(t),l.length>o&&l.shift()};for(;;){let t=e.readSync(n,c,0,c.byteLength,null);if(t===0)break;h=c[t-1];let r=c.subarray(0,t).lastIndexOf(10);r>=0&&(_=g+r+1),g+=t,d+=s.write(c.subarray(0,t));let i=d.indexOf(`
2
+ `);for(;i>=0;)b(d.slice(0,i)),d=d.slice(i+1),i=d.indexOf(`
3
+ `)}d+=s.end(),d.length>0&&b(d);let x=h===10,S={text:`${u.map(e=>e.text).join(`
4
+ `)}${!a&&x&&u.length>0?`
5
+ `:``}`,lineCount:u.length,totalLines:f,completeBytes:_};return a?{...S,lineNumbers:u.map(e=>e.index+1)}:S}function i(e,t){if(!t.grep)return e;let n=e.split(`
6
6
  `),r=t.ignoreCase?t.grep.toLowerCase():t.grep,i=Math.max(0,t.contextLines??0),a=[];if(n.forEach((e,o)=>{(t.ignoreCase?e.toLowerCase():e).includes(r)&&a.push({start:Math.max(0,o-i),end:Math.min(n.length-1,o+i)})}),a.length===0)return``;let o=[];for(let e of a){let t=o.at(-1);t&&e.start<=t.end+1?t.end=Math.max(t.end,e.end):o.push({...e})}return o.flatMap(e=>n.slice(e.start,e.end+1)).join(`
7
7
  `)}export{n as LogReader,i as filterLogText};
8
8
  //# sourceMappingURL=LogReader.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"LogReader.mjs","names":[],"sources":["../../../../src/adapters/LogReader/LogReader.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { StringDecoder } from 'node:string_decoder';\nimport type { ILogReader, LogQuery, LogSlice } from '../../types/logReader';\n\nconst DEFAULT_LINES = 200;\nconst READ_CHUNK_BYTES = 64 * 1024;\n\ninterface IndexedLine {\n readonly index: number;\n readonly text: string;\n}\n\ninterface ScannedLog {\n readonly text: string;\n readonly lineCount: number;\n readonly totalLines: number;\n}\n\nexport class LogReader implements ILogReader {\n read(logPath: string, query: LogQuery = {}): LogSlice {\n let handle: number | undefined;\n try {\n handle = fs.openSync(logPath, 'r');\n const scanned = scanLog(handle, query);\n return {\n ...scanned,\n fileSize: fs.fstatSync(handle).size,\n path: logPath,\n exists: true,\n };\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n return { text: '', lineCount: 0, totalLines: 0, fileSize: 0, path: logPath, exists: false };\n } finally {\n if (handle !== undefined) fs.closeSync(handle);\n }\n }\n}\n\nfunction scanLog(handle: number, query: LogQuery): ScannedLog {\n const limit = Math.max(0, Math.floor(query.lines ?? DEFAULT_LINES));\n const needle = query.grep ? (query.ignoreCase ? query.grep.toLowerCase() : query.grep) : undefined;\n const contextLines = Math.max(0, Math.floor(query.contextLines ?? 0));\n const decoder = new StringDecoder('utf8');\n const buffer = Buffer.alloc(READ_CHUNK_BYTES);\n const before: IndexedLine[] = [];\n const output: string[] = [];\n let pending = '';\n let totalLines = 0;\n let afterThrough = -1;\n let lastEmitted = -1;\n let lastByte: number | undefined;\n\n const retain = (line: string): void => {\n if (limit === 0) return;\n output.push(line);\n if (output.length > limit) output.shift();\n };\n const emit = (line: IndexedLine): void => {\n if (line.index <= lastEmitted) return;\n lastEmitted = line.index;\n retain(line.text);\n };\n const consume = (text: string): void => {\n const line = { index: totalLines, text };\n totalLines += 1;\n if (!needle) {\n retain(text);\n return;\n }\n\n const haystack = query.ignoreCase ? text.toLowerCase() : text;\n if (haystack.includes(needle)) {\n for (const previous of before) emit(previous);\n emit(line);\n afterThrough = Math.max(afterThrough, line.index + contextLines);\n } else if (line.index <= afterThrough) {\n emit(line);\n }\n before.push(line);\n if (before.length > contextLines) before.shift();\n };\n\n for (;;) {\n const bytesRead = fs.readSync(handle, buffer, 0, buffer.byteLength, null);\n if (bytesRead === 0) break;\n lastByte = buffer[bytesRead - 1];\n pending += decoder.write(buffer.subarray(0, bytesRead));\n let newline = pending.indexOf('\\n');\n while (newline >= 0) {\n consume(pending.slice(0, newline));\n pending = pending.slice(newline + 1);\n newline = pending.indexOf('\\n');\n }\n }\n pending += decoder.end();\n if (pending.length > 0) consume(pending);\n\n const trailingNewline = lastByte === 0x0a;\n const text = `${output.join('\\n')}${!needle && trailingNewline && output.length > 0 ? '\\n' : ''}`;\n return { text, lineCount: output.length, totalLines };\n}\n\n/**\n * Grep with context, matching the `product-stack logs` semantics so the two\n * surfaces behave the same. Overlapping and adjacent context windows merge.\n */\nexport function filterLogText(text: string, query: Pick<LogQuery, 'grep' | 'ignoreCase' | 'contextLines'>): string {\n if (!query.grep) return text;\n const lines = text.split('\\n');\n const needle = query.ignoreCase ? query.grep.toLowerCase() : query.grep;\n const contextLines = Math.max(0, query.contextLines ?? 0);\n const ranges: Array<{ start: number; end: number }> = [];\n\n lines.forEach((line, index) => {\n const haystack = query.ignoreCase ? line.toLowerCase() : line;\n if (!haystack.includes(needle)) return;\n ranges.push({\n start: Math.max(0, index - contextLines),\n end: Math.min(lines.length - 1, index + contextLines),\n });\n });\n\n if (ranges.length === 0) return '';\n const merged: Array<{ start: number; end: number }> = [];\n for (const range of ranges) {\n const previous = merged.at(-1);\n if (previous && range.start <= previous.end + 1) {\n previous.end = Math.max(previous.end, range.end);\n } else {\n merged.push({ ...range });\n }\n }\n return merged.flatMap((range) => lines.slice(range.start, range.end + 1)).join('\\n');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"LogReader.mjs","names":[],"sources":["../../../../src/adapters/LogReader/LogReader.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { StringDecoder } from 'node:string_decoder';\nimport type { ILogReader, LogQuery, LogSlice } from '../../types/logReader';\n\nconst DEFAULT_LINES = 200;\nconst READ_CHUNK_BYTES = 64 * 1024;\n\ninterface IndexedLine {\n readonly index: number;\n readonly text: string;\n}\n\ninterface ScannedLog {\n readonly text: string;\n readonly lineCount: number;\n readonly totalLines: number;\n readonly completeBytes: number;\n readonly lineNumbers?: number[];\n}\n\nexport class LogReader implements ILogReader {\n read(logPath: string, query: LogQuery = {}): LogSlice {\n let handle: number | undefined;\n try {\n handle = fs.openSync(logPath, 'r');\n const scanned = scanLog(handle, query);\n return {\n ...scanned,\n fileSize: fs.fstatSync(handle).size,\n path: logPath,\n exists: true,\n };\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n return {\n text: '',\n lineCount: 0,\n totalLines: 0,\n fileSize: 0,\n completeBytes: 0,\n path: logPath,\n exists: false,\n };\n } finally {\n if (handle !== undefined) fs.closeSync(handle);\n }\n }\n}\n\nfunction scanLog(handle: number, query: LogQuery): ScannedLog {\n const limit = Math.max(0, Math.floor(query.lines ?? DEFAULT_LINES));\n const needle = query.grep ? (query.ignoreCase ? query.grep.toLowerCase() : query.grep) : undefined;\n const contextLines = Math.max(0, Math.floor(query.contextLines ?? 0));\n const decoder = new StringDecoder('utf8');\n const buffer = Buffer.alloc(READ_CHUNK_BYTES);\n const before: IndexedLine[] = [];\n const output: IndexedLine[] = [];\n let pending = '';\n let totalLines = 0;\n let afterThrough = -1;\n let lastEmitted = -1;\n let lastByte: number | undefined;\n let bytesSeen = 0;\n let completeBytes = 0;\n\n const retain = (line: IndexedLine): void => {\n if (limit === 0) return;\n output.push(line);\n if (output.length > limit) output.shift();\n };\n const emit = (line: IndexedLine): void => {\n if (line.index <= lastEmitted) return;\n lastEmitted = line.index;\n retain(line);\n };\n const consume = (text: string): void => {\n const line = { index: totalLines, text };\n totalLines += 1;\n if (!needle) {\n retain(line);\n return;\n }\n\n const haystack = query.ignoreCase ? text.toLowerCase() : text;\n if (haystack.includes(needle)) {\n for (const previous of before) emit(previous);\n emit(line);\n afterThrough = Math.max(afterThrough, line.index + contextLines);\n } else if (line.index <= afterThrough) {\n emit(line);\n }\n before.push(line);\n if (before.length > contextLines) before.shift();\n };\n\n for (;;) {\n const bytesRead = fs.readSync(handle, buffer, 0, buffer.byteLength, null);\n if (bytesRead === 0) break;\n lastByte = buffer[bytesRead - 1];\n // A newline is a single byte in UTF-8 and never a continuation byte, so the\n // last one in this chunk ends the last complete line seen so far.\n const lastNewline = buffer.subarray(0, bytesRead).lastIndexOf(0x0a);\n if (lastNewline >= 0) completeBytes = bytesSeen + lastNewline + 1;\n bytesSeen += bytesRead;\n pending += decoder.write(buffer.subarray(0, bytesRead));\n let newline = pending.indexOf('\\n');\n while (newline >= 0) {\n consume(pending.slice(0, newline));\n pending = pending.slice(newline + 1);\n newline = pending.indexOf('\\n');\n }\n }\n pending += decoder.end();\n if (pending.length > 0) consume(pending);\n\n const trailingNewline = lastByte === 0x0a;\n const body = output.map((line) => line.text).join('\\n');\n const text = `${body}${!needle && trailingNewline && output.length > 0 ? '\\n' : ''}`;\n const scanned: ScannedLog = { text, lineCount: output.length, totalLines, completeBytes };\n if (!needle) return scanned;\n return { ...scanned, lineNumbers: output.map((line) => line.index + 1) };\n}\n\n/**\n * Grep with context, matching the `product-stack logs` semantics so the two\n * surfaces behave the same. Overlapping and adjacent context windows merge.\n */\nexport function filterLogText(text: string, query: Pick<LogQuery, 'grep' | 'ignoreCase' | 'contextLines'>): string {\n if (!query.grep) return text;\n const lines = text.split('\\n');\n const needle = query.ignoreCase ? query.grep.toLowerCase() : query.grep;\n const contextLines = Math.max(0, query.contextLines ?? 0);\n const ranges: Array<{ start: number; end: number }> = [];\n\n lines.forEach((line, index) => {\n const haystack = query.ignoreCase ? line.toLowerCase() : line;\n if (!haystack.includes(needle)) return;\n ranges.push({\n start: Math.max(0, index - contextLines),\n end: Math.min(lines.length - 1, index + contextLines),\n });\n });\n\n if (ranges.length === 0) return '';\n const merged: Array<{ start: number; end: number }> = [];\n for (const range of ranges) {\n const previous = merged.at(-1);\n if (previous && range.start <= previous.end + 1) {\n previous.end = Math.max(previous.end, range.end);\n } else {\n merged.push({ ...range });\n }\n }\n return merged.flatMap((range) => lines.slice(range.start, range.end + 1)).join('\\n');\n}\n"],"mappings":"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"}