@agimon-ai/doompi-runner 0.0.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (417) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +47 -0
  3. package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs +1 -0
  4. package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs +1 -0
  5. package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.cjs +1 -0
  6. package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.mjs +1 -0
  7. package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.cjs +1 -0
  8. package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.mjs +1 -0
  9. package/dist/_virtual/_rolldown/runtime.cjs +1 -0
  10. package/dist/bin/cli.cjs +5 -0
  11. package/dist/bin/cli.cjs.map +1 -0
  12. package/dist/bin/cli.d.cts +5 -0
  13. package/dist/bin/cli.d.cts.map +1 -0
  14. package/dist/bin/cli.d.mts +5 -0
  15. package/dist/bin/cli.d.mts.map +1 -0
  16. package/dist/bin/cli.mjs +5 -0
  17. package/dist/bin/cli.mjs.map +1 -0
  18. package/dist/bin/logSink.cjs +2 -0
  19. package/dist/bin/logSink.cjs.map +1 -0
  20. package/dist/bin/logSink.d.cts +5 -0
  21. package/dist/bin/logSink.d.cts.map +1 -0
  22. package/dist/bin/logSink.d.mts +5 -0
  23. package/dist/bin/logSink.d.mts.map +1 -0
  24. package/dist/bin/logSink.mjs +2 -0
  25. package/dist/bin/logSink.mjs.map +1 -0
  26. package/dist/bin/runnerHost.cjs +2 -0
  27. package/dist/bin/runnerHost.cjs.map +1 -0
  28. package/dist/bin/runnerHost.d.cts +5 -0
  29. package/dist/bin/runnerHost.d.cts.map +1 -0
  30. package/dist/bin/runnerHost.d.mts +5 -0
  31. package/dist/bin/runnerHost.d.mts.map +1 -0
  32. package/dist/bin/runnerHost.mjs +2 -0
  33. package/dist/bin/runnerHost.mjs.map +1 -0
  34. package/dist/cli/cliApp.cjs +6 -0
  35. package/dist/cli/cliApp.cjs.map +1 -0
  36. package/dist/cli/cliApp.d.cts +23 -0
  37. package/dist/cli/cliApp.d.cts.map +1 -0
  38. package/dist/cli/cliApp.d.mts +23 -0
  39. package/dist/cli/cliApp.d.mts.map +1 -0
  40. package/dist/cli/cliApp.mjs +6 -0
  41. package/dist/cli/cliApp.mjs.map +1 -0
  42. package/dist/compaction.cjs +4 -0
  43. package/dist/compaction.cjs.map +1 -0
  44. package/dist/compaction.d.cts +14 -0
  45. package/dist/compaction.d.cts.map +1 -0
  46. package/dist/compaction.d.mts +14 -0
  47. package/dist/compaction.d.mts.map +1 -0
  48. package/dist/compaction.mjs +4 -0
  49. package/dist/compaction.mjs.map +1 -0
  50. package/dist/config.cjs +2 -0
  51. package/dist/config.cjs.map +1 -0
  52. package/dist/config.d.cts +32 -0
  53. package/dist/config.d.cts.map +1 -0
  54. package/dist/config.d.mts +32 -0
  55. package/dist/config.d.mts.map +1 -0
  56. package/dist/config.mjs +2 -0
  57. package/dist/config.mjs.map +1 -0
  58. package/dist/container/index.cjs +2 -0
  59. package/dist/container/index.cjs.map +1 -0
  60. package/dist/container/index.d.cts +14 -0
  61. package/dist/container/index.d.cts.map +1 -0
  62. package/dist/container/index.d.mts +14 -0
  63. package/dist/container/index.d.mts.map +1 -0
  64. package/dist/container/index.mjs +2 -0
  65. package/dist/container/index.mjs.map +1 -0
  66. package/dist/extension.cjs +3 -0
  67. package/dist/extension.cjs.map +1 -0
  68. package/dist/extension.d.cts +10 -0
  69. package/dist/extension.d.cts.map +1 -0
  70. package/dist/extension.d.mts +10 -0
  71. package/dist/extension.d.mts.map +1 -0
  72. package/dist/extension.mjs +3 -0
  73. package/dist/extension.mjs.map +1 -0
  74. package/dist/extensions/pi.cjs +2 -0
  75. package/dist/extensions/pi.cjs.map +1 -0
  76. package/dist/extensions/pi.d.cts +2 -0
  77. package/dist/extensions/pi.d.mts +2 -0
  78. package/dist/extensions/pi.mjs +2 -0
  79. package/dist/extensions/pi.mjs.map +1 -0
  80. package/dist/index.cjs +1 -0
  81. package/dist/index.d.cts +7 -0
  82. package/dist/index.d.mts +7 -0
  83. package/dist/index.mjs +1 -0
  84. package/dist/ptyProvider.cjs +2 -0
  85. package/dist/ptyProvider.cjs.map +1 -0
  86. package/dist/ptyProvider.d.cts +13 -0
  87. package/dist/ptyProvider.d.cts.map +1 -0
  88. package/dist/ptyProvider.d.mts +13 -0
  89. package/dist/ptyProvider.d.mts.map +1 -0
  90. package/dist/ptyProvider.mjs +2 -0
  91. package/dist/ptyProvider.mjs.map +1 -0
  92. package/dist/reconcile.cjs +2 -0
  93. package/dist/reconcile.cjs.map +1 -0
  94. package/dist/reconcile.d.cts +37 -0
  95. package/dist/reconcile.d.cts.map +1 -0
  96. package/dist/reconcile.d.mts +37 -0
  97. package/dist/reconcile.d.mts.map +1 -0
  98. package/dist/reconcile.mjs +2 -0
  99. package/dist/reconcile.mjs.map +1 -0
  100. package/dist/runnerSpec.cjs +2 -0
  101. package/dist/runnerSpec.cjs.map +1 -0
  102. package/dist/runnerSpec.d.cts +50 -0
  103. package/dist/runnerSpec.d.cts.map +1 -0
  104. package/dist/runnerSpec.d.mts +50 -0
  105. package/dist/runnerSpec.d.mts.map +1 -0
  106. package/dist/runnerSpec.mjs +2 -0
  107. package/dist/runnerSpec.mjs.map +1 -0
  108. package/dist/services/AnsiScrub/ansiScrub.cjs +5 -0
  109. package/dist/services/AnsiScrub/ansiScrub.cjs.map +1 -0
  110. package/dist/services/AnsiScrub/ansiScrub.d.cts +34 -0
  111. package/dist/services/AnsiScrub/ansiScrub.d.cts.map +1 -0
  112. package/dist/services/AnsiScrub/ansiScrub.d.mts +34 -0
  113. package/dist/services/AnsiScrub/ansiScrub.d.mts.map +1 -0
  114. package/dist/services/AnsiScrub/ansiScrub.mjs +5 -0
  115. package/dist/services/AnsiScrub/ansiScrub.mjs.map +1 -0
  116. package/dist/services/AnsiScrub/index.cjs +1 -0
  117. package/dist/services/AnsiScrub/index.d.cts +2 -0
  118. package/dist/services/AnsiScrub/index.d.mts +2 -0
  119. package/dist/services/AnsiScrub/index.mjs +1 -0
  120. package/dist/services/BashRunService/BashRunService.cjs +2 -0
  121. package/dist/services/BashRunService/BashRunService.cjs.map +1 -0
  122. package/dist/services/BashRunService/BashRunService.d.cts +38 -0
  123. package/dist/services/BashRunService/BashRunService.d.cts.map +1 -0
  124. package/dist/services/BashRunService/BashRunService.d.mts +38 -0
  125. package/dist/services/BashRunService/BashRunService.d.mts.map +1 -0
  126. package/dist/services/BashRunService/BashRunService.mjs +2 -0
  127. package/dist/services/BashRunService/BashRunService.mjs.map +1 -0
  128. package/dist/services/BashRunService/index.cjs +1 -0
  129. package/dist/services/BashRunService/index.d.cts +3 -0
  130. package/dist/services/BashRunService/index.d.mts +3 -0
  131. package/dist/services/BashRunService/index.mjs +1 -0
  132. package/dist/services/BashRunService/types.d.cts +62 -0
  133. package/dist/services/BashRunService/types.d.cts.map +1 -0
  134. package/dist/services/BashRunService/types.d.mts +62 -0
  135. package/dist/services/BashRunService/types.d.mts.map +1 -0
  136. package/dist/services/Clock/SystemClock.cjs +2 -0
  137. package/dist/services/Clock/SystemClock.cjs.map +1 -0
  138. package/dist/services/Clock/SystemClock.d.cts +11 -0
  139. package/dist/services/Clock/SystemClock.d.cts.map +1 -0
  140. package/dist/services/Clock/SystemClock.d.mts +11 -0
  141. package/dist/services/Clock/SystemClock.d.mts.map +1 -0
  142. package/dist/services/Clock/SystemClock.mjs +2 -0
  143. package/dist/services/Clock/SystemClock.mjs.map +1 -0
  144. package/dist/services/Clock/index.cjs +1 -0
  145. package/dist/services/Clock/index.d.cts +3 -0
  146. package/dist/services/Clock/index.d.mts +3 -0
  147. package/dist/services/Clock/index.mjs +1 -0
  148. package/dist/services/Clock/types.d.cts +11 -0
  149. package/dist/services/Clock/types.d.cts.map +1 -0
  150. package/dist/services/Clock/types.d.mts +11 -0
  151. package/dist/services/Clock/types.d.mts.map +1 -0
  152. package/dist/services/Launcher/Launcher.cjs +2 -0
  153. package/dist/services/Launcher/Launcher.cjs.map +1 -0
  154. package/dist/services/Launcher/Launcher.d.cts +27 -0
  155. package/dist/services/Launcher/Launcher.d.cts.map +1 -0
  156. package/dist/services/Launcher/Launcher.d.mts +27 -0
  157. package/dist/services/Launcher/Launcher.d.mts.map +1 -0
  158. package/dist/services/Launcher/Launcher.mjs +2 -0
  159. package/dist/services/Launcher/Launcher.mjs.map +1 -0
  160. package/dist/services/Launcher/index.cjs +1 -0
  161. package/dist/services/Launcher/index.d.cts +3 -0
  162. package/dist/services/Launcher/index.d.mts +3 -0
  163. package/dist/services/Launcher/index.mjs +1 -0
  164. package/dist/services/Launcher/types.d.cts +40 -0
  165. package/dist/services/Launcher/types.d.cts.map +1 -0
  166. package/dist/services/Launcher/types.d.mts +40 -0
  167. package/dist/services/Launcher/types.d.mts.map +1 -0
  168. package/dist/services/Lifeline/NodeLifeline.cjs +2 -0
  169. package/dist/services/Lifeline/NodeLifeline.cjs.map +1 -0
  170. package/dist/services/Lifeline/NodeLifeline.d.cts +21 -0
  171. package/dist/services/Lifeline/NodeLifeline.d.cts.map +1 -0
  172. package/dist/services/Lifeline/NodeLifeline.d.mts +21 -0
  173. package/dist/services/Lifeline/NodeLifeline.d.mts.map +1 -0
  174. package/dist/services/Lifeline/NodeLifeline.mjs +2 -0
  175. package/dist/services/Lifeline/NodeLifeline.mjs.map +1 -0
  176. package/dist/services/Lifeline/client.cjs +2 -0
  177. package/dist/services/Lifeline/client.cjs.map +1 -0
  178. package/dist/services/Lifeline/client.d.cts +23 -0
  179. package/dist/services/Lifeline/client.d.cts.map +1 -0
  180. package/dist/services/Lifeline/client.d.mts +23 -0
  181. package/dist/services/Lifeline/client.d.mts.map +1 -0
  182. package/dist/services/Lifeline/client.mjs +2 -0
  183. package/dist/services/Lifeline/client.mjs.map +1 -0
  184. package/dist/services/Lifeline/index.cjs +1 -0
  185. package/dist/services/Lifeline/index.d.cts +4 -0
  186. package/dist/services/Lifeline/index.d.mts +4 -0
  187. package/dist/services/Lifeline/index.mjs +1 -0
  188. package/dist/services/Lifeline/types.d.cts +19 -0
  189. package/dist/services/Lifeline/types.d.cts.map +1 -0
  190. package/dist/services/Lifeline/types.d.mts +19 -0
  191. package/dist/services/Lifeline/types.d.mts.map +1 -0
  192. package/dist/services/LogFile/LogFile.cjs +2 -0
  193. package/dist/services/LogFile/LogFile.cjs.map +1 -0
  194. package/dist/services/LogFile/LogFile.d.cts +13 -0
  195. package/dist/services/LogFile/LogFile.d.cts.map +1 -0
  196. package/dist/services/LogFile/LogFile.d.mts +13 -0
  197. package/dist/services/LogFile/LogFile.d.mts.map +1 -0
  198. package/dist/services/LogFile/LogFile.mjs +2 -0
  199. package/dist/services/LogFile/LogFile.mjs.map +1 -0
  200. package/dist/services/LogFile/index.cjs +1 -0
  201. package/dist/services/LogFile/index.d.cts +3 -0
  202. package/dist/services/LogFile/index.d.mts +3 -0
  203. package/dist/services/LogFile/index.mjs +1 -0
  204. package/dist/services/LogFile/types.d.cts +16 -0
  205. package/dist/services/LogFile/types.d.cts.map +1 -0
  206. package/dist/services/LogFile/types.d.mts +16 -0
  207. package/dist/services/LogFile/types.d.mts.map +1 -0
  208. package/dist/services/LogReader/LogReader.cjs +10 -0
  209. package/dist/services/LogReader/LogReader.cjs.map +1 -0
  210. package/dist/services/LogReader/LogReader.d.cts +14 -0
  211. package/dist/services/LogReader/LogReader.d.cts.map +1 -0
  212. package/dist/services/LogReader/LogReader.d.mts +14 -0
  213. package/dist/services/LogReader/LogReader.d.mts.map +1 -0
  214. package/dist/services/LogReader/LogReader.mjs +10 -0
  215. package/dist/services/LogReader/LogReader.mjs.map +1 -0
  216. package/dist/services/LogReader/index.cjs +1 -0
  217. package/dist/services/LogReader/index.d.cts +3 -0
  218. package/dist/services/LogReader/index.d.mts +3 -0
  219. package/dist/services/LogReader/index.mjs +1 -0
  220. package/dist/services/LogReader/types.d.cts +27 -0
  221. package/dist/services/LogReader/types.d.cts.map +1 -0
  222. package/dist/services/LogReader/types.d.mts +27 -0
  223. package/dist/services/LogReader/types.d.mts.map +1 -0
  224. package/dist/services/ProcessControl/NodeProcessControl.cjs +2 -0
  225. package/dist/services/ProcessControl/NodeProcessControl.cjs.map +1 -0
  226. package/dist/services/ProcessControl/NodeProcessControl.d.cts +11 -0
  227. package/dist/services/ProcessControl/NodeProcessControl.d.cts.map +1 -0
  228. package/dist/services/ProcessControl/NodeProcessControl.d.mts +11 -0
  229. package/dist/services/ProcessControl/NodeProcessControl.d.mts.map +1 -0
  230. package/dist/services/ProcessControl/NodeProcessControl.mjs +2 -0
  231. package/dist/services/ProcessControl/NodeProcessControl.mjs.map +1 -0
  232. package/dist/services/ProcessControl/index.cjs +1 -0
  233. package/dist/services/ProcessControl/index.d.cts +3 -0
  234. package/dist/services/ProcessControl/index.d.mts +3 -0
  235. package/dist/services/ProcessControl/index.mjs +1 -0
  236. package/dist/services/ProcessControl/types.d.cts +14 -0
  237. package/dist/services/ProcessControl/types.d.cts.map +1 -0
  238. package/dist/services/ProcessControl/types.d.mts +14 -0
  239. package/dist/services/ProcessControl/types.d.mts.map +1 -0
  240. package/dist/services/PtyHost/PtyHost.cjs +5 -0
  241. package/dist/services/PtyHost/PtyHost.cjs.map +1 -0
  242. package/dist/services/PtyHost/PtyHost.d.cts +28 -0
  243. package/dist/services/PtyHost/PtyHost.d.cts.map +1 -0
  244. package/dist/services/PtyHost/PtyHost.d.mts +28 -0
  245. package/dist/services/PtyHost/PtyHost.d.mts.map +1 -0
  246. package/dist/services/PtyHost/PtyHost.mjs +5 -0
  247. package/dist/services/PtyHost/PtyHost.mjs.map +1 -0
  248. package/dist/services/PtyHost/index.cjs +1 -0
  249. package/dist/services/PtyHost/index.d.cts +3 -0
  250. package/dist/services/PtyHost/index.d.mts +3 -0
  251. package/dist/services/PtyHost/index.mjs +1 -0
  252. package/dist/services/PtyHost/types.d.cts +39 -0
  253. package/dist/services/PtyHost/types.d.cts.map +1 -0
  254. package/dist/services/PtyHost/types.d.mts +39 -0
  255. package/dist/services/PtyHost/types.d.mts.map +1 -0
  256. package/dist/services/PtySpawner/NodePtySpawner.cjs +2 -0
  257. package/dist/services/PtySpawner/NodePtySpawner.cjs.map +1 -0
  258. package/dist/services/PtySpawner/NodePtySpawner.d.cts +18 -0
  259. package/dist/services/PtySpawner/NodePtySpawner.d.cts.map +1 -0
  260. package/dist/services/PtySpawner/NodePtySpawner.d.mts +18 -0
  261. package/dist/services/PtySpawner/NodePtySpawner.d.mts.map +1 -0
  262. package/dist/services/PtySpawner/NodePtySpawner.mjs +2 -0
  263. package/dist/services/PtySpawner/NodePtySpawner.mjs.map +1 -0
  264. package/dist/services/PtySpawner/index.cjs +1 -0
  265. package/dist/services/PtySpawner/index.d.cts +3 -0
  266. package/dist/services/PtySpawner/index.d.mts +3 -0
  267. package/dist/services/PtySpawner/index.mjs +1 -0
  268. package/dist/services/PtySpawner/types.d.cts +28 -0
  269. package/dist/services/PtySpawner/types.d.cts.map +1 -0
  270. package/dist/services/PtySpawner/types.d.mts +28 -0
  271. package/dist/services/PtySpawner/types.d.mts.map +1 -0
  272. package/dist/services/RmuxBackend/RmuxBackend.cjs +2 -0
  273. package/dist/services/RmuxBackend/RmuxBackend.cjs.map +1 -0
  274. package/dist/services/RmuxBackend/RmuxBackend.d.cts +36 -0
  275. package/dist/services/RmuxBackend/RmuxBackend.d.cts.map +1 -0
  276. package/dist/services/RmuxBackend/RmuxBackend.d.mts +36 -0
  277. package/dist/services/RmuxBackend/RmuxBackend.d.mts.map +1 -0
  278. package/dist/services/RmuxBackend/RmuxBackend.mjs +2 -0
  279. package/dist/services/RmuxBackend/RmuxBackend.mjs.map +1 -0
  280. package/dist/services/RmuxBackend/index.cjs +1 -0
  281. package/dist/services/RmuxBackend/index.d.cts +3 -0
  282. package/dist/services/RmuxBackend/index.d.mts +3 -0
  283. package/dist/services/RmuxBackend/index.mjs +1 -0
  284. package/dist/services/RmuxBackend/types.d.cts +29 -0
  285. package/dist/services/RmuxBackend/types.d.cts.map +1 -0
  286. package/dist/services/RmuxBackend/types.d.mts +29 -0
  287. package/dist/services/RmuxBackend/types.d.mts.map +1 -0
  288. package/dist/services/RunnerNamer/RunnerNamer.cjs +2 -0
  289. package/dist/services/RunnerNamer/RunnerNamer.cjs.map +1 -0
  290. package/dist/services/RunnerNamer/RunnerNamer.d.cts +13 -0
  291. package/dist/services/RunnerNamer/RunnerNamer.d.cts.map +1 -0
  292. package/dist/services/RunnerNamer/RunnerNamer.d.mts +13 -0
  293. package/dist/services/RunnerNamer/RunnerNamer.d.mts.map +1 -0
  294. package/dist/services/RunnerNamer/RunnerNamer.mjs +2 -0
  295. package/dist/services/RunnerNamer/RunnerNamer.mjs.map +1 -0
  296. package/dist/services/RunnerNamer/index.cjs +1 -0
  297. package/dist/services/RunnerNamer/index.d.cts +3 -0
  298. package/dist/services/RunnerNamer/index.d.mts +3 -0
  299. package/dist/services/RunnerNamer/index.mjs +1 -0
  300. package/dist/services/RunnerNamer/types.d.cts +12 -0
  301. package/dist/services/RunnerNamer/types.d.cts.map +1 -0
  302. package/dist/services/RunnerNamer/types.d.mts +12 -0
  303. package/dist/services/RunnerNamer/types.d.mts.map +1 -0
  304. package/dist/services/RunnerPaths/RunnerPaths.cjs +2 -0
  305. package/dist/services/RunnerPaths/RunnerPaths.cjs.map +1 -0
  306. package/dist/services/RunnerPaths/RunnerPaths.d.cts +31 -0
  307. package/dist/services/RunnerPaths/RunnerPaths.d.cts.map +1 -0
  308. package/dist/services/RunnerPaths/RunnerPaths.d.mts +31 -0
  309. package/dist/services/RunnerPaths/RunnerPaths.d.mts.map +1 -0
  310. package/dist/services/RunnerPaths/RunnerPaths.mjs +2 -0
  311. package/dist/services/RunnerPaths/RunnerPaths.mjs.map +1 -0
  312. package/dist/services/RunnerPaths/index.cjs +1 -0
  313. package/dist/services/RunnerPaths/index.d.cts +3 -0
  314. package/dist/services/RunnerPaths/index.d.mts +3 -0
  315. package/dist/services/RunnerPaths/index.mjs +1 -0
  316. package/dist/services/RunnerPaths/types.d.cts +33 -0
  317. package/dist/services/RunnerPaths/types.d.cts.map +1 -0
  318. package/dist/services/RunnerPaths/types.d.mts +33 -0
  319. package/dist/services/RunnerPaths/types.d.mts.map +1 -0
  320. package/dist/services/RunnerRegistry/RunnerRegistry.cjs +2 -0
  321. package/dist/services/RunnerRegistry/RunnerRegistry.cjs.map +1 -0
  322. package/dist/services/RunnerRegistry/RunnerRegistry.d.cts +40 -0
  323. package/dist/services/RunnerRegistry/RunnerRegistry.d.cts.map +1 -0
  324. package/dist/services/RunnerRegistry/RunnerRegistry.d.mts +40 -0
  325. package/dist/services/RunnerRegistry/RunnerRegistry.d.mts.map +1 -0
  326. package/dist/services/RunnerRegistry/RunnerRegistry.mjs +2 -0
  327. package/dist/services/RunnerRegistry/RunnerRegistry.mjs.map +1 -0
  328. package/dist/services/RunnerRegistry/index.cjs +1 -0
  329. package/dist/services/RunnerRegistry/index.d.cts +3 -0
  330. package/dist/services/RunnerRegistry/index.d.mts +3 -0
  331. package/dist/services/RunnerRegistry/index.mjs +1 -0
  332. package/dist/services/RunnerRegistry/types.d.cts +98 -0
  333. package/dist/services/RunnerRegistry/types.d.cts.map +1 -0
  334. package/dist/services/RunnerRegistry/types.d.mts +98 -0
  335. package/dist/services/RunnerRegistry/types.d.mts.map +1 -0
  336. package/dist/services/Spawner/NodeSpawner.cjs +2 -0
  337. package/dist/services/Spawner/NodeSpawner.cjs.map +1 -0
  338. package/dist/services/Spawner/NodeSpawner.d.cts +10 -0
  339. package/dist/services/Spawner/NodeSpawner.d.cts.map +1 -0
  340. package/dist/services/Spawner/NodeSpawner.d.mts +10 -0
  341. package/dist/services/Spawner/NodeSpawner.d.mts.map +1 -0
  342. package/dist/services/Spawner/NodeSpawner.mjs +2 -0
  343. package/dist/services/Spawner/NodeSpawner.mjs.map +1 -0
  344. package/dist/services/Spawner/index.cjs +1 -0
  345. package/dist/services/Spawner/index.d.cts +3 -0
  346. package/dist/services/Spawner/index.d.mts +3 -0
  347. package/dist/services/Spawner/index.mjs +1 -0
  348. package/dist/services/Spawner/types.d.cts +31 -0
  349. package/dist/services/Spawner/types.d.cts.map +1 -0
  350. package/dist/services/Spawner/types.d.mts +31 -0
  351. package/dist/services/Spawner/types.d.mts.map +1 -0
  352. package/dist/session.cjs +2 -0
  353. package/dist/session.cjs.map +1 -0
  354. package/dist/session.d.cts +10 -0
  355. package/dist/session.d.cts.map +1 -0
  356. package/dist/session.d.mts +10 -0
  357. package/dist/session.d.mts.map +1 -0
  358. package/dist/session.mjs +2 -0
  359. package/dist/session.mjs.map +1 -0
  360. package/dist/tool/bashTool.cjs +7 -0
  361. package/dist/tool/bashTool.cjs.map +1 -0
  362. package/dist/tool/bashTool.d.cts +25 -0
  363. package/dist/tool/bashTool.d.cts.map +1 -0
  364. package/dist/tool/bashTool.d.mts +25 -0
  365. package/dist/tool/bashTool.d.mts.map +1 -0
  366. package/dist/tool/bashTool.mjs +7 -0
  367. package/dist/tool/bashTool.mjs.map +1 -0
  368. package/dist/tool/responseEnvelope.cjs +10 -0
  369. package/dist/tool/responseEnvelope.cjs.map +1 -0
  370. package/dist/tool/responseEnvelope.d.cts +45 -0
  371. package/dist/tool/responseEnvelope.d.cts.map +1 -0
  372. package/dist/tool/responseEnvelope.d.mts +45 -0
  373. package/dist/tool/responseEnvelope.d.mts.map +1 -0
  374. package/dist/tool/responseEnvelope.mjs +10 -0
  375. package/dist/tool/responseEnvelope.mjs.map +1 -0
  376. package/dist/tool/schema.cjs +2 -0
  377. package/dist/tool/schema.cjs.map +1 -0
  378. package/dist/tool/schema.d.cts +25 -0
  379. package/dist/tool/schema.d.cts.map +1 -0
  380. package/dist/tool/schema.d.mts +25 -0
  381. package/dist/tool/schema.d.mts.map +1 -0
  382. package/dist/tool/schema.mjs +2 -0
  383. package/dist/tool/schema.mjs.map +1 -0
  384. package/dist/tui/bashRender.cjs +8 -0
  385. package/dist/tui/bashRender.cjs.map +1 -0
  386. package/dist/tui/bashRender.d.cts +51 -0
  387. package/dist/tui/bashRender.d.cts.map +1 -0
  388. package/dist/tui/bashRender.d.mts +51 -0
  389. package/dist/tui/bashRender.d.mts.map +1 -0
  390. package/dist/tui/bashRender.mjs +8 -0
  391. package/dist/tui/bashRender.mjs.map +1 -0
  392. package/dist/tui/format.cjs +2 -0
  393. package/dist/tui/format.cjs.map +1 -0
  394. package/dist/tui/format.d.cts +25 -0
  395. package/dist/tui/format.d.cts.map +1 -0
  396. package/dist/tui/format.d.mts +25 -0
  397. package/dist/tui/format.d.mts.map +1 -0
  398. package/dist/tui/format.mjs +2 -0
  399. package/dist/tui/format.mjs.map +1 -0
  400. package/dist/tui/runnerSpace.cjs +6 -0
  401. package/dist/tui/runnerSpace.cjs.map +1 -0
  402. package/dist/tui/runnerSpace.d.cts +52 -0
  403. package/dist/tui/runnerSpace.d.cts.map +1 -0
  404. package/dist/tui/runnerSpace.d.mts +52 -0
  405. package/dist/tui/runnerSpace.d.mts.map +1 -0
  406. package/dist/tui/runnerSpace.mjs +6 -0
  407. package/dist/tui/runnerSpace.mjs.map +1 -0
  408. package/dist/types.cjs +2 -0
  409. package/dist/types.cjs.map +1 -0
  410. package/dist/types.d.cts +28 -0
  411. package/dist/types.d.cts.map +1 -0
  412. package/dist/types.d.mts +28 -0
  413. package/dist/types.d.mts.map +1 -0
  414. package/dist/types.mjs +2 -0
  415. package/dist/types.mjs.map +1 -0
  416. package/package.json +335 -0
  417. package/skills/doom-runner/SKILL.md +69 -0
@@ -0,0 +1,25 @@
1
+ import { BashRunResult, IBashRunService } from "../services/BashRunService/types.mjs";
2
+ import "../services/BashRunService/index.mjs";
3
+ import { ToolResult } from "./responseEnvelope.mjs";
4
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
5
+ //#region src/tool/bashTool.d.ts
6
+ declare const BASH_PROMPT_SNIPPET = "Execute bash commands, with long-running ones supervised in the background";
7
+ /** Written at registration time so the stated threshold matches the configured one. */
8
+ declare function bashPromptGuidelines(thresholdMs?: number): string[];
9
+ interface BashToolDependencies {
10
+ bashRunService: IBashRunService;
11
+ getSessionId(): string;
12
+ /** Called after a runner is promoted, so UI state can refresh. */
13
+ onRunnerStarted(id: string): void;
14
+ }
15
+ /**
16
+ * Registers a tool named `bash`, replacing pi's built-in.
17
+ *
18
+ * The name is deliberate: hooks, guardrails and doom-pi's dispatcher all key on
19
+ * `bash`, and they keep working only while the replacement keeps the name.
20
+ */
21
+ declare function registerBashTool(pi: ExtensionAPI, dependencies: BashToolDependencies): void;
22
+ declare function formatRunResult(result: BashRunResult): ToolResult;
23
+ //#endregion
24
+ export { BASH_PROMPT_SNIPPET, BashToolDependencies, bashPromptGuidelines, formatRunResult, registerBashTool };
25
+ //# sourceMappingURL=bashTool.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bashTool.d.mts","names":[],"sources":["../../src/tool/bashTool.ts"],"mappings":";;;;;cAiBa;;iBAGG,qBAAqB;UAUpB;EACf,gBAAgB;EAChB;;EAEA,gBAAgB;;;;;;;;iBASF,iBAAiB,IAAI,cAAc,cAAc;iBA+DjD,gBAAgB,QAAQ,gBAAgB"}
@@ -0,0 +1,7 @@
1
+ import{getBackgroundThresholdMs as e}from"../config.mjs";import{stripAnsi as t}from"../services/AnsiScrub/ansiScrub.mjs";import"../services/AnsiScrub/index.mjs";import{formatSize as n,summarizeLog as r,textResult as i}from"./responseEnvelope.mjs";import{renderBashCall as a,renderBashResult as o}from"../tui/bashRender.mjs";import{BASH_TOOL_LABEL as s,BASH_TOOL_NAME as c,BashParamsSchema as l}from"./schema.mjs";const u=1e3,d=`Options:`,f={requested:`Started in the background`,threshold:`Still running after the background threshold, so it was moved to the background`,interactive:`Started on a terminal so it can prompt, which means it runs in the background`},p=`Execute bash commands, with long-running ones supervised in the background`;function m(t=e()){return[`A command still running after ${Math.round(t/u)} seconds remains active as a background runner. You get its unique id and streaming log path, then inspect it with the doom-runner CLI.`,`Pass background: true for commands you already know will not finish on their own (dev servers, watchers, tails). Waiting the full threshold first wastes a turn.`,`Pass interactive: true only when the command will prompt for confirmation or input. Use Runner Space for terminal input. Interactive logs are noisier, so avoid it otherwise.`,`Do not re-run a command to recover output. Read its saved log with doom-runner logs <id>.`,`Stop runners you no longer need. Every runner is stopped automatically when the session ends.`]}function h(e,t){e.registerTool({name:c,label:s,description:`Execute a bash command in the current working directory. A command that outlives the background threshold keeps running under doom-runner and returns a unique id plus a streaming log path. Completed commands return a bounded log tail with exact file metadata. Optionally provide a timeout in seconds, background: true to background it immediately, or interactive: true if it will prompt.`,promptSnippet:p,promptGuidelines:m(),parameters:l,async execute(e,n,r,a,o){let{command:s,timeout:c,background:l,interactive:f,name:p}=n,m;a&&a(i(`Starting ${f===!0?`interactive runner`:l===!0?`background runner`:`command`}...`)),l!==!0&&f!==!0&&a&&(m=e=>a(i(e)));let h;try{h=await t.bashRunService.run({command:s,timeoutMs:c===void 0?void 0:c*u,background:l,interactive:f,name:p,...m?{onOutput:m}:{},sessionId:t.getSessionId()})}catch(e){let t=e instanceof Error?e.message:String(e);throw Error([`Could not execute the command: ${t}`,``,d,`- Check the command, runtime, and working directory, then retry once.`,`- Use a read-only diagnostic to confirm the missing dependency or environment value.`,`- Ask the user if recovery requires changing the requested approach.`].join(`
2
+ `),{cause:e})}return h.kind===`promoted`&&t.onRunnerStarted(h.id),g(h)},renderCall(e,t,n){return a(e,t)},renderResult(e,t,n,r){return o(e,t,n)}})}function g(e){if(e.kind===`failed`)throw Error([`Could not start runner "${e.name}": ${e.error}`,``,d,`- Correct the command or missing executable, then retry once.`,`- Use a read-only diagnostic to inspect the runtime environment.`,`- Ask the user if a different execution approach is required.`].join(`
3
+ `));if(e.kind===`promoted`){let t=[`${f[e.reason]} as runner "${e.name}".`,`Runner ID: ${e.id}`,`Backend: ${e.backend}`,`Log (streaming): ${e.logPath}`,`Inspect it with: doom-runner logs ${e.id}`].filter(e=>e.length>0).join(`
4
+ `);return{...i(t,{id:e.id,runner:e.name,pid:e.pid,logPath:e.logPath,promoted:!0,reason:e.reason})}}let a=r(e.logPath),o=[];e.timedOut?o.push(`Command stopped: it exceeded the requested timeout.`):e.exitCode===null?e.signal!==null&&o.push(`Terminated by ${e.signal}`):o.push(`Exit: completed with code ${e.exitCode}.`);let s=t(a.tail),c=[s.length>0?`Log tail (${a.tailLines} lines):\n${s}`:`Log tail: (no output)`,`Runner ID: ${e.id}`,...o,`Log: ${e.logPath}`,`File size: ${n(a.bytes)}`,`Lines: ${a.lines.toLocaleString(`en-US`)}`].join(`
5
+ `),l={id:e.id,runner:e.name,exitCode:e.exitCode,logPath:e.logPath,backend:e.backend,fileSize:a.bytes,lines:a.lines,tail:a.tail,tailLines:a.tailLines,...e.timedOut?{timedOut:!0}:{}};if(e.timedOut||e.signal!==null||e.exitCode!==null&&e.exitCode!==0)throw Error([c,``,d,`- Inspect the full log at ${e.logPath}, correct the cause, then retry once.`,`- Run a read-only diagnostic if the output does not explain the failure.`,`- Ask the user if the failure requires changing the requested approach.`].join(`
6
+ `));return i(c,l)}export{p as BASH_PROMPT_SNIPPET,m as bashPromptGuidelines,g as formatRunResult,h as registerBashTool};
7
+ //# sourceMappingURL=bashTool.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bashTool.mjs","names":[],"sources":["../../src/tool/bashTool.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { getBackgroundThresholdMs } from '../config.ts';\nimport { stripAnsi } from '../services/AnsiScrub/index.ts';\nimport type { BashRunResult, IBashRunService } from '../services/BashRunService/index.ts';\nimport { renderBashCall, renderBashResult } from '../tui/bashRender.ts';\nimport { formatSize, summarizeLog, textResult, type ToolResult } from './responseEnvelope.ts';\nimport { BASH_TOOL_LABEL, BASH_TOOL_NAME, type BashParams, BashParamsSchema } from './schema.ts';\n\nconst MS_PER_SECOND = 1000;\nconst ERROR_OPTIONS_HEADING = 'Options:';\n\nconst PROMOTION_REASONS: Record<'requested' | 'threshold' | 'interactive', string> = {\n requested: 'Started in the background',\n threshold: 'Still running after the background threshold, so it was moved to the background',\n interactive: 'Started on a terminal so it can prompt, which means it runs in the background',\n};\n\nexport const BASH_PROMPT_SNIPPET = 'Execute bash commands, with long-running ones supervised in the background';\n\n/** Written at registration time so the stated threshold matches the configured one. */\nexport function bashPromptGuidelines(thresholdMs = getBackgroundThresholdMs()): string[] {\n return [\n `A command still running after ${Math.round(thresholdMs / MS_PER_SECOND)} seconds remains active as a background runner. You get its unique id and streaming log path, then inspect it with the doom-runner CLI.`,\n 'Pass background: true for commands you already know will not finish on their own (dev servers, watchers, tails). Waiting the full threshold first wastes a turn.',\n 'Pass interactive: true only when the command will prompt for confirmation or input. Use Runner Space for terminal input. Interactive logs are noisier, so avoid it otherwise.',\n 'Do not re-run a command to recover output. Read its saved log with doom-runner logs <id>.',\n 'Stop runners you no longer need. Every runner is stopped automatically when the session ends.',\n ];\n}\n\nexport interface BashToolDependencies {\n bashRunService: IBashRunService;\n getSessionId(): string;\n /** Called after a runner is promoted, so UI state can refresh. */\n onRunnerStarted(id: string): void;\n}\n\n/**\n * Registers a tool named `bash`, replacing pi's built-in.\n *\n * The name is deliberate: hooks, guardrails and doom-pi's dispatcher all key on\n * `bash`, and they keep working only while the replacement keeps the name.\n */\nexport function registerBashTool(pi: ExtensionAPI, dependencies: BashToolDependencies): void {\n pi.registerTool({\n name: BASH_TOOL_NAME,\n label: BASH_TOOL_LABEL,\n description:\n 'Execute a bash command in the current working directory. A command that outlives the background threshold keeps running under doom-runner and returns a unique id plus a streaming log path. Completed commands return a bounded log tail with exact file metadata. Optionally provide a timeout in seconds, background: true to background it immediately, or interactive: true if it will prompt.',\n promptSnippet: BASH_PROMPT_SNIPPET,\n promptGuidelines: bashPromptGuidelines(),\n parameters: BashParamsSchema,\n\n async execute(_toolCallId, params, _signal, onUpdate, _ctx): Promise<ToolResult> {\n const { command, timeout, background, interactive, name } = params as BashParams;\n let onOutput: ((output: string) => void) | undefined;\n if (onUpdate) {\n const mode =\n interactive === true ? 'interactive runner' : background === true ? 'background runner' : 'command';\n onUpdate(textResult(`Starting ${mode}...`));\n }\n if (background !== true && interactive !== true && onUpdate) {\n onOutput = (output) => onUpdate(textResult(output));\n }\n let result: BashRunResult;\n try {\n result = await dependencies.bashRunService.run({\n command,\n timeoutMs: timeout === undefined ? undefined : timeout * MS_PER_SECOND,\n background,\n interactive,\n name,\n ...(onOutput ? { onOutput } : {}),\n sessionId: dependencies.getSessionId(),\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(\n [\n `Could not execute the command: ${message}`,\n '',\n ERROR_OPTIONS_HEADING,\n '- Check the command, runtime, and working directory, then retry once.',\n '- Use a read-only diagnostic to confirm the missing dependency or environment value.',\n '- Ask the user if recovery requires changing the requested approach.',\n ].join('\\n'),\n { cause: error },\n );\n }\n\n if (result.kind === 'promoted') dependencies.onRunnerStarted(result.id);\n return formatRunResult(result);\n },\n\n // Without these, pi falls back to echoing the raw command and the tail end of\n // the result text, which is the metadata footer rather than the log output.\n renderCall(args, theme, _context) {\n return renderBashCall(args as BashParams, theme);\n },\n\n renderResult(result, options, theme, _context) {\n return renderBashResult(result, options, theme);\n },\n });\n}\n\nexport function formatRunResult(result: BashRunResult): ToolResult {\n if (result.kind === 'failed') {\n throw new Error(\n [\n `Could not start runner \"${result.name}\": ${result.error}`,\n '',\n ERROR_OPTIONS_HEADING,\n '- Correct the command or missing executable, then retry once.',\n '- Use a read-only diagnostic to inspect the runtime environment.',\n '- Ask the user if a different execution approach is required.',\n ].join('\\n'),\n );\n }\n\n if (result.kind === 'promoted') {\n const reason = PROMOTION_REASONS[result.reason];\n const body = [\n `${reason} as runner \"${result.name}\".`,\n `Runner ID: ${result.id}`,\n `Backend: ${result.backend}`,\n `Log (streaming): ${result.logPath}`,\n `Inspect it with: doom-runner logs ${result.id}`,\n ]\n .filter((line) => line.length > 0)\n .join('\\n');\n\n return {\n ...textResult(body, {\n id: result.id,\n runner: result.name,\n pid: result.pid,\n logPath: result.logPath,\n promoted: true,\n reason: result.reason,\n }),\n };\n }\n\n const log = summarizeLog(result.logPath);\n const notes: string[] = [];\n if (result.timedOut) notes.push('Command stopped: it exceeded the requested timeout.');\n else if (result.exitCode !== null) notes.push(`Exit: completed with code ${result.exitCode}.`);\n else if (result.signal !== null) notes.push(`Terminated by ${result.signal}`);\n\n // The model reads plain text; only the renderer gets the coloured copy below.\n const plainTail = stripAnsi(log.tail);\n const text = [\n plainTail.length > 0 ? `Log tail (${log.tailLines} lines):\\n${plainTail}` : 'Log tail: (no output)',\n `Runner ID: ${result.id}`,\n ...notes,\n `Log: ${result.logPath}`,\n `File size: ${formatSize(log.bytes)}`,\n `Lines: ${log.lines.toLocaleString('en-US')}`,\n ].join('\\n');\n const details = {\n id: result.id,\n runner: result.name,\n exitCode: result.exitCode,\n logPath: result.logPath,\n backend: result.backend,\n fileSize: log.bytes,\n lines: log.lines,\n // Carried structurally so renderResult shows the output instead of the footer.\n tail: log.tail,\n tailLines: log.tailLines,\n ...(result.timedOut ? { timedOut: true } : {}),\n };\n if (result.timedOut || result.signal !== null || (result.exitCode !== null && result.exitCode !== 0)) {\n throw new Error(\n [\n text,\n '',\n ERROR_OPTIONS_HEADING,\n `- Inspect the full log at ${result.logPath}, correct the cause, then retry once.`,\n '- Run a read-only diagnostic if the output does not explain the failure.',\n '- Ask the user if the failure requires changing the requested approach.',\n ].join('\\n'),\n );\n }\n return textResult(text, details);\n}\n"],"mappings":"6ZAQA,MAAM,EAAgB,IAChB,EAAwB,WAExB,EAA+E,CACnF,UAAW,4BACX,UAAW,kFACX,YAAa,+EACf,EAEa,EAAsB,6EAGnC,SAAgB,EAAqB,EAAc,EAAyB,EAAa,CACvF,MAAO,CACL,iCAAiC,KAAK,MAAM,EAAc,CAAa,EAAE,yIACzE,mKACA,gLACA,4FACA,+FACF,CACF,CAeA,SAAgB,EAAiB,EAAkB,EAA0C,CAC3F,EAAG,aAAa,CACd,KAAM,EACN,MAAO,EACP,YACE,sYACF,cAAe,EACf,iBAAkB,EAAqB,EACvC,WAAY,EAEZ,MAAM,QAAQ,EAAa,EAAQ,EAAS,EAAU,EAA2B,CAC/E,GAAM,CAAE,UAAS,UAAS,aAAY,cAAa,QAAS,EACxD,EACA,GAGF,EAAS,EAAW,YADlB,IAAgB,GAAO,qBAAuB,IAAe,GAAO,oBAAsB,UACvD,IAAI,CAAC,EAExC,IAAe,IAAQ,IAAgB,IAAQ,IACjD,EAAY,GAAW,EAAS,EAAW,CAAM,CAAC,GAEpD,IAAI,EACJ,GAAI,CACF,EAAS,MAAM,EAAa,eAAe,IAAI,CAC7C,UACA,UAAW,IAAY,IAAA,GAAY,IAAA,GAAY,EAAU,EACzD,aACA,cACA,OACA,GAAI,EAAW,CAAE,UAAS,EAAI,CAAC,EAC/B,UAAW,EAAa,aAAa,CACvC,CAAC,CACH,OAAS,EAAO,CACd,IAAM,EAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACrE,MAAU,MACR,CACE,kCAAkC,IAClC,GACA,EACA,wEACA,uFACA,sEACF,CAAC,CAAC,KAAK;CAAI,EACX,CAAE,MAAO,CAAM,CACjB,CACF,CAGA,OADI,EAAO,OAAS,YAAY,EAAa,gBAAgB,EAAO,EAAE,EAC/D,EAAgB,CAAM,CAC/B,EAIA,WAAW,EAAM,EAAO,EAAU,CAChC,OAAO,EAAe,EAAoB,CAAK,CACjD,EAEA,aAAa,EAAQ,EAAS,EAAO,EAAU,CAC7C,OAAO,EAAiB,EAAQ,EAAS,CAAK,CAChD,CACF,CAAC,CACH,CAEA,SAAgB,EAAgB,EAAmC,CACjE,GAAI,EAAO,OAAS,SAClB,MAAU,MACR,CACE,2BAA2B,EAAO,KAAK,KAAK,EAAO,QACnD,GACA,EACA,gEACA,mEACA,+DACF,CAAC,CAAC,KAAK;CAAI,CACb,EAGF,GAAI,EAAO,OAAS,WAAY,CAE9B,IAAM,EAAO,CACX,GAFa,EAAkB,EAAO,QAE5B,cAAc,EAAO,KAAK,IACpC,cAAc,EAAO,KACrB,YAAY,EAAO,UACnB,oBAAoB,EAAO,UAC3B,qCAAqC,EAAO,IAC9C,CAAC,CACE,OAAQ,GAAS,EAAK,OAAS,CAAC,CAAC,CACjC,KAAK;CAAI,EAEZ,MAAO,CACL,GAAG,EAAW,EAAM,CAClB,GAAI,EAAO,GACX,OAAQ,EAAO,KACf,IAAK,EAAO,IACZ,QAAS,EAAO,QAChB,SAAU,GACV,OAAQ,EAAO,MACjB,CAAC,CACH,CACF,CAEA,IAAM,EAAM,EAAa,EAAO,OAAO,EACjC,EAAkB,CAAC,EACrB,EAAO,SAAU,EAAM,KAAK,qDAAqD,EAC5E,EAAO,WAAa,KACpB,EAAO,SAAW,MAAM,EAAM,KAAK,iBAAiB,EAAO,QAAQ,EADzC,EAAM,KAAK,6BAA6B,EAAO,SAAS,EAAE,EAI7F,IAAM,EAAY,EAAU,EAAI,IAAI,EAC9B,EAAO,CACX,EAAU,OAAS,EAAI,aAAa,EAAI,UAAU,YAAY,IAAc,wBAC5E,cAAc,EAAO,KACrB,GAAG,EACH,QAAQ,EAAO,UACf,cAAc,EAAW,EAAI,KAAK,IAClC,UAAU,EAAI,MAAM,eAAe,OAAO,GAC5C,CAAC,CAAC,KAAK;CAAI,EACL,EAAU,CACd,GAAI,EAAO,GACX,OAAQ,EAAO,KACf,SAAU,EAAO,SACjB,QAAS,EAAO,QAChB,QAAS,EAAO,QAChB,SAAU,EAAI,MACd,MAAO,EAAI,MAEX,KAAM,EAAI,KACV,UAAW,EAAI,UACf,GAAI,EAAO,SAAW,CAAE,SAAU,EAAK,EAAI,CAAC,CAC9C,EACA,GAAI,EAAO,UAAY,EAAO,SAAW,MAAS,EAAO,WAAa,MAAQ,EAAO,WAAa,EAChG,MAAU,MACR,CACE,EACA,GACA,EACA,6BAA6B,EAAO,QAAQ,uCAC5C,2EACA,yEACF,CAAC,CAAC,KAAK;CAAI,CACb,EAEF,OAAO,EAAW,EAAM,CAAO,CACjC"}
@@ -0,0 +1,10 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("../config.cjs");let n=require("node:fs");n=e.__toESM(n,1);const r=1024,i=r*r;function a(e,t={}){return{content:[{type:`text`,text:e}],details:t}}function o(e){return a(`Error: ${e}`,{error:e})}function s(e){return e<r?`${e} B`:e<i?`${(e/r).toFixed(1)} KB`:`${(e/i).toFixed(1)} MB`}function c(e){return e.toLocaleString(`en-US`)}function l(e){return e.length===0?0:e.endsWith(`
2
+ `)?e.split(`
3
+ `).length-1:e.split(`
4
+ `).length}function u(e,r=200,i=t.getResultMaxBytes()){try{let t=n.default.readFileSync(e,`utf8`),a=l(t),o=t.split(`
5
+ `).slice(-Math.max(1,r)-+!!t.endsWith(`
6
+ `)).join(`
7
+ `),s=Buffer.byteLength(o,`utf8`),c=s>i?Buffer.from(o,`utf8`).subarray(s-i).toString(`utf8`):o,u=s>i?c.indexOf(`
8
+ `):-1,d=u>=0?c.slice(u+1):c;return{tail:d,bytes:n.default.statSync(e).size,lines:a,tailLines:l(d)}}catch{return{tail:``,bytes:0,lines:0,tailLines:0}}}function d(e,n,r=t.getResultMaxBytes()){let i=Buffer.byteLength(e,`utf8`);if(i<=r)return{text:e,truncated:!1,outputLines:l(e)};let a=Buffer.from(e,`utf8`).subarray(i-r).toString(`utf8`),o=a.indexOf(`
9
+ `),s=o===-1?a:a.slice(o+1);return{text:`${s}\n${f(s,n,e,i)}`,truncated:!0,outputLines:l(s)}}function f(e,t,n,r){let i=l(e),a=p(t),o=a?.lines??l(n),u=a?.bytes??r;return[`[output truncated: showing the last ${c(i)} lines.`,`Full output is at ${t} (${s(u)}, ${c(o)} lines).`,`Inspect it with doom-runner logs, or read the file with an offset near line ${c(o)}.]`].join(` `)}function p(e){try{let t=n.default.readFileSync(e,`utf8`);return{bytes:n.default.statSync(e).size,lines:l(t)}}catch{return}}function m(e,t=Date.now()){let n=e.interactive?` interactive`:``;return`${e.name} pid ${e.pid} up ${h(e.startedAt,t)}${n} ${e.command}`}function h(e,t){let n=Date.parse(e);if(Number.isNaN(n))return`unknown`;let r=Math.max(0,Math.floor((t-n)/1e3));if(r<60)return`${r}s`;let i=Math.floor(r/60);if(i<60)return`${i}m`;let a=Math.floor(i/60);return a<24?`${a}h`:`${Math.floor(a/24)}d`}exports.countLines=l,exports.errorResult=o,exports.formatRunnerLine=m,exports.formatSize=s,exports.formatUptime=h,exports.summarizeLog=u,exports.textResult=a,exports.truncateForResult=d;
10
+ //# sourceMappingURL=responseEnvelope.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responseEnvelope.cjs","names":["getResultMaxBytes","fs"],"sources":["../../src/tool/responseEnvelope.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { getResultMaxBytes } from '../config.ts';\nimport type { RunnerRecord } from '../services/RunnerRegistry/index.ts';\n\nconst BYTES_PER_KB = 1024;\nconst BYTES_PER_MB = BYTES_PER_KB * BYTES_PER_KB;\n\nexport interface ToolResult {\n content: Array<{ type: 'text'; text: string }>;\n details: Record<string, unknown>;\n /** Tools this result makes available from here on in the transcript. */\n addedToolNames?: string[];\n}\n\nexport function textResult(text: string, details: Record<string, unknown> = {}): ToolResult {\n return { content: [{ type: 'text', text }], details };\n}\n\nexport function errorResult(message: string): ToolResult {\n return textResult(`Error: ${message}`, { error: message });\n}\n\n/** Human-readable byte count, matching how pi reports output sizes. */\nexport function formatSize(bytes: number): string {\n if (bytes < BYTES_PER_KB) return `${bytes} B`;\n if (bytes < BYTES_PER_MB) return `${(bytes / BYTES_PER_KB).toFixed(1)} KB`;\n return `${(bytes / BYTES_PER_MB).toFixed(1)} MB`;\n}\n\nfunction formatCount(value: number): string {\n return value.toLocaleString('en-US');\n}\n\nexport function countLines(text: string): number {\n if (text.length === 0) return 0;\n return text.endsWith('\\n') ? text.split('\\n').length - 1 : text.split('\\n').length;\n}\n\nexport interface TruncatedOutput {\n text: string;\n truncated: boolean;\n /** Lines returned, which is what the model actually received. */\n outputLines: number;\n}\n\nexport interface LogSummary {\n tail: string;\n bytes: number;\n lines: number;\n tailLines: number;\n}\n\n/** Reads a bounded tail plus exact metadata after the writer has flushed. */\nexport function summarizeLog(path: string, maxLines = 200, maxBytes = getResultMaxBytes()): LogSummary {\n try {\n const contents = fs.readFileSync(path, 'utf8');\n const lines = countLines(contents);\n const lineTail = contents\n .split('\\n')\n .slice(-Math.max(1, maxLines) - (contents.endsWith('\\n') ? 1 : 0))\n .join('\\n');\n const bytes = Buffer.byteLength(lineTail, 'utf8');\n const byteTail =\n bytes > maxBytes\n ? Buffer.from(lineTail, 'utf8')\n .subarray(bytes - maxBytes)\n .toString('utf8')\n : lineTail;\n const firstNewline = bytes > maxBytes ? byteTail.indexOf('\\n') : -1;\n const tail = firstNewline >= 0 ? byteTail.slice(firstNewline + 1) : byteTail;\n return { tail, bytes: fs.statSync(path).size, lines, tailLines: countLines(tail) };\n } catch {\n return { tail: '', bytes: 0, lines: 0, tailLines: 0 };\n }\n}\n\n/**\n * Keeps the tail of an oversized result and points at the file holding the rest.\n *\n * The notice states the file's real size and line count so the model does not\n * guess at offsets when it goes on to read the file, which is the failure this\n * whole policy exists to prevent.\n */\nexport function truncateForResult(\n text: string,\n fullOutputPath: string,\n maxBytes = getResultMaxBytes(),\n): TruncatedOutput {\n const totalBytes = Buffer.byteLength(text, 'utf8');\n if (totalBytes <= maxBytes) return { text, truncated: false, outputLines: countLines(text) };\n\n const kept = Buffer.from(text, 'utf8')\n .subarray(totalBytes - maxBytes)\n .toString('utf8');\n // Drop the leading partial line rather than hand back a fragment.\n const newline = kept.indexOf('\\n');\n const tail = newline === -1 ? kept : kept.slice(newline + 1);\n\n return {\n text: `${tail}\\n${truncationNotice(tail, fullOutputPath, text, totalBytes)}`,\n truncated: true,\n outputLines: countLines(tail),\n };\n}\n\nfunction truncationNotice(tail: string, fullOutputPath: string, text: string, totalBytes: number): string {\n const shown = countLines(tail);\n // Counted from the file, never from `text`. What the caller holds in memory\n // is itself capped, so using it here would understate the file by orders of\n // magnitude and send the reader looking past the end of a much longer file.\n const file = measureFile(fullOutputPath);\n const totalLines = file?.lines ?? countLines(text);\n const fileSize = file?.bytes ?? totalBytes;\n\n return [\n `[output truncated: showing the last ${formatCount(shown)} lines.`,\n `Full output is at ${fullOutputPath} (${formatSize(fileSize)}, ${formatCount(totalLines)} lines).`,\n `Inspect it with doom-runner logs, or read the file with an offset near line ${formatCount(totalLines)}.]`,\n ].join(' ');\n}\n\n/** Real size and line count of the file the notice points at. */\nfunction measureFile(path: string): { bytes: number; lines: number } | undefined {\n try {\n const contents = fs.readFileSync(path, 'utf8');\n return { bytes: fs.statSync(path).size, lines: countLines(contents) };\n } catch {\n return undefined;\n }\n}\n\n/** `name pid 1234 up 3m sleep 60` — one runner per line. */\nexport function formatRunnerLine(record: RunnerRecord, now = Date.now()): string {\n const mode = record.interactive ? ' interactive' : '';\n return `${record.name} pid ${record.pid} up ${formatUptime(record.startedAt, now)}${mode} ${record.command}`;\n}\n\nexport function formatUptime(startedAt: string, now: number): string {\n const started = Date.parse(startedAt);\n if (Number.isNaN(started)) return 'unknown';\n const seconds = Math.max(0, Math.floor((now - started) / 1000));\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;\n}\n"],"mappings":"6LAIA,MAAM,EAAe,KACf,EAAe,EAAe,EASpC,SAAgB,EAAW,EAAc,EAAmC,CAAC,EAAe,CAC1F,MAAO,CAAE,QAAS,CAAC,CAAE,KAAM,OAAQ,MAAK,CAAC,EAAG,SAAQ,CACtD,CAEA,SAAgB,EAAY,EAA6B,CACvD,OAAO,EAAW,UAAU,IAAW,CAAE,MAAO,CAAQ,CAAC,CAC3D,CAGA,SAAgB,EAAW,EAAuB,CAGhD,OAFI,EAAQ,EAAqB,GAAG,EAAM,IACtC,EAAQ,EAAqB,IAAI,EAAQ,EAAA,CAAc,QAAQ,CAAC,EAAE,KAC/D,IAAI,EAAQ,EAAA,CAAc,QAAQ,CAAC,EAAE,IAC9C,CAEA,SAAS,EAAY,EAAuB,CAC1C,OAAO,EAAM,eAAe,OAAO,CACrC,CAEA,SAAgB,EAAW,EAAsB,CAE/C,OADI,EAAK,SAAW,EAAU,EACvB,EAAK,SAAS;CAAI,EAAI,EAAK,MAAM;CAAI,CAAC,CAAC,OAAS,EAAI,EAAK,MAAM;CAAI,CAAC,CAAC,MAC9E,CAiBA,SAAgB,EAAa,EAAc,EAAW,IAAK,EAAWA,EAAAA,kBAAkB,EAAe,CACrG,GAAI,CACF,IAAM,EAAWC,EAAAA,QAAG,aAAa,EAAM,MAAM,EACvC,EAAQ,EAAW,CAAQ,EAC3B,EAAW,EACd,MAAM;CAAI,CAAC,CACX,MAAM,CAAC,KAAK,IAAI,EAAG,CAAQ,EAAK,KAAS,SAAS;CAAI,CAAU,CAAC,CACjE,KAAK;CAAI,EACN,EAAQ,OAAO,WAAW,EAAU,MAAM,EAC1C,EACJ,EAAQ,EACJ,OAAO,KAAK,EAAU,MAAM,CAAC,CAC1B,SAAS,EAAQ,CAAQ,CAAC,CAC1B,SAAS,MAAM,EAClB,EACA,EAAe,EAAQ,EAAW,EAAS,QAAQ;CAAI,EAAI,GAC3D,EAAO,GAAgB,EAAI,EAAS,MAAM,EAAe,CAAC,EAAI,EACpE,MAAO,CAAE,OAAM,MAAOA,EAAAA,QAAG,SAAS,CAAI,CAAC,CAAC,KAAM,QAAO,UAAW,EAAW,CAAI,CAAE,CACnF,MAAQ,CACN,MAAO,CAAE,KAAM,GAAI,MAAO,EAAG,MAAO,EAAG,UAAW,CAAE,CACtD,CACF,CASA,SAAgB,EACd,EACA,EACA,EAAWD,EAAAA,kBAAkB,EACZ,CACjB,IAAM,EAAa,OAAO,WAAW,EAAM,MAAM,EACjD,GAAI,GAAc,EAAU,MAAO,CAAE,OAAM,UAAW,GAAO,YAAa,EAAW,CAAI,CAAE,EAE3F,IAAM,EAAO,OAAO,KAAK,EAAM,MAAM,CAAC,CACnC,SAAS,EAAa,CAAQ,CAAC,CAC/B,SAAS,MAAM,EAEZ,EAAU,EAAK,QAAQ;CAAI,EAC3B,EAAO,IAAY,GAAK,EAAO,EAAK,MAAM,EAAU,CAAC,EAE3D,MAAO,CACL,KAAM,GAAG,EAAK,IAAI,EAAiB,EAAM,EAAgB,EAAM,CAAU,IACzE,UAAW,GACX,YAAa,EAAW,CAAI,CAC9B,CACF,CAEA,SAAS,EAAiB,EAAc,EAAwB,EAAc,EAA4B,CACxG,IAAM,EAAQ,EAAW,CAAI,EAIvB,EAAO,EAAY,CAAc,EACjC,EAAa,GAAM,OAAS,EAAW,CAAI,EAC3C,EAAW,GAAM,OAAS,EAEhC,MAAO,CACL,uCAAuC,EAAY,CAAK,EAAE,SAC1D,qBAAqB,EAAe,IAAI,EAAW,CAAQ,EAAE,IAAI,EAAY,CAAU,EAAE,UACzF,+EAA+E,EAAY,CAAU,EAAE,GACzG,CAAC,CAAC,KAAK,GAAG,CACZ,CAGA,SAAS,EAAY,EAA4D,CAC/E,GAAI,CACF,IAAM,EAAWC,EAAAA,QAAG,aAAa,EAAM,MAAM,EAC7C,MAAO,CAAE,MAAOA,EAAAA,QAAG,SAAS,CAAI,CAAC,CAAC,KAAM,MAAO,EAAW,CAAQ,CAAE,CACtE,MAAQ,CACN,MACF,CACF,CAGA,SAAgB,EAAiB,EAAsB,EAAM,KAAK,IAAI,EAAW,CAC/E,IAAM,EAAO,EAAO,YAAc,eAAiB,GACnD,MAAO,GAAG,EAAO,KAAK,QAAQ,EAAO,IAAI,OAAO,EAAa,EAAO,UAAW,CAAG,IAAI,EAAK,IAAI,EAAO,SACxG,CAEA,SAAgB,EAAa,EAAmB,EAAqB,CACnE,IAAM,EAAU,KAAK,MAAM,CAAS,EACpC,GAAI,OAAO,MAAM,CAAO,EAAG,MAAO,UAClC,IAAM,EAAU,KAAK,IAAI,EAAG,KAAK,OAAO,EAAM,GAAW,GAAI,CAAC,EAC9D,GAAI,EAAU,GAAI,MAAO,GAAG,EAAQ,GACpC,IAAM,EAAU,KAAK,MAAM,EAAU,EAAE,EACvC,GAAI,EAAU,GAAI,MAAO,GAAG,EAAQ,GACpC,IAAM,EAAQ,KAAK,MAAM,EAAU,EAAE,EACrC,OAAO,EAAQ,GAAK,GAAG,EAAM,GAAK,GAAG,KAAK,MAAM,EAAQ,EAAE,EAAE,EAC9D"}
@@ -0,0 +1,45 @@
1
+ import { RunnerRecord } from "../services/RunnerRegistry/types.cjs";
2
+ import "../services/RunnerRegistry/index.cjs";
3
+ //#region src/tool/responseEnvelope.d.ts
4
+ interface ToolResult {
5
+ content: Array<{
6
+ type: 'text';
7
+ text: string;
8
+ }>;
9
+ details: Record<string, unknown>;
10
+ /** Tools this result makes available from here on in the transcript. */
11
+ addedToolNames?: string[];
12
+ }
13
+ declare function textResult(text: string, details?: Record<string, unknown>): ToolResult;
14
+ declare function errorResult(message: string): ToolResult;
15
+ /** Human-readable byte count, matching how pi reports output sizes. */
16
+ declare function formatSize(bytes: number): string;
17
+ declare function countLines(text: string): number;
18
+ interface TruncatedOutput {
19
+ text: string;
20
+ truncated: boolean;
21
+ /** Lines returned, which is what the model actually received. */
22
+ outputLines: number;
23
+ }
24
+ interface LogSummary {
25
+ tail: string;
26
+ bytes: number;
27
+ lines: number;
28
+ tailLines: number;
29
+ }
30
+ /** Reads a bounded tail plus exact metadata after the writer has flushed. */
31
+ declare function summarizeLog(path: string, maxLines?: number, maxBytes?: number): LogSummary;
32
+ /**
33
+ * Keeps the tail of an oversized result and points at the file holding the rest.
34
+ *
35
+ * The notice states the file's real size and line count so the model does not
36
+ * guess at offsets when it goes on to read the file, which is the failure this
37
+ * whole policy exists to prevent.
38
+ */
39
+ declare function truncateForResult(text: string, fullOutputPath: string, maxBytes?: number): TruncatedOutput;
40
+ /** `name pid 1234 up 3m sleep 60` — one runner per line. */
41
+ declare function formatRunnerLine(record: RunnerRecord, now?: number): string;
42
+ declare function formatUptime(startedAt: string, now: number): string;
43
+ //#endregion
44
+ export { LogSummary, ToolResult, TruncatedOutput, countLines, errorResult, formatRunnerLine, formatSize, formatUptime, summarizeLog, textResult, truncateForResult };
45
+ //# sourceMappingURL=responseEnvelope.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responseEnvelope.d.cts","names":[],"sources":["../../src/tool/responseEnvelope.ts"],"mappings":";;;UAOiB;EACf,SAAS;IAAQ;IAAc;;EAC/B,SAAS;;EAET;;iBAGc,WAAW,cAAc,UAAS,0BAA+B;iBAIjE,YAAY,kBAAkB;;iBAK9B,WAAW;iBAUX,WAAW;UAKV;EACf;EACA;;EAEA;;UAGe;EACf;EACA;EACA;EACA;;;iBAIc,aAAa,cAAc,mBAAgB,oBAAiC;;;;;;;;iBA8B5E,kBACd,cACA,wBACA,oBACC;;iBA6Ca,iBAAiB,QAAQ,cAAc;iBAKvC,aAAa,mBAAmB"}
@@ -0,0 +1,45 @@
1
+ import { RunnerRecord } from "../services/RunnerRegistry/types.mjs";
2
+ import "../services/RunnerRegistry/index.mjs";
3
+ //#region src/tool/responseEnvelope.d.ts
4
+ interface ToolResult {
5
+ content: Array<{
6
+ type: 'text';
7
+ text: string;
8
+ }>;
9
+ details: Record<string, unknown>;
10
+ /** Tools this result makes available from here on in the transcript. */
11
+ addedToolNames?: string[];
12
+ }
13
+ declare function textResult(text: string, details?: Record<string, unknown>): ToolResult;
14
+ declare function errorResult(message: string): ToolResult;
15
+ /** Human-readable byte count, matching how pi reports output sizes. */
16
+ declare function formatSize(bytes: number): string;
17
+ declare function countLines(text: string): number;
18
+ interface TruncatedOutput {
19
+ text: string;
20
+ truncated: boolean;
21
+ /** Lines returned, which is what the model actually received. */
22
+ outputLines: number;
23
+ }
24
+ interface LogSummary {
25
+ tail: string;
26
+ bytes: number;
27
+ lines: number;
28
+ tailLines: number;
29
+ }
30
+ /** Reads a bounded tail plus exact metadata after the writer has flushed. */
31
+ declare function summarizeLog(path: string, maxLines?: number, maxBytes?: number): LogSummary;
32
+ /**
33
+ * Keeps the tail of an oversized result and points at the file holding the rest.
34
+ *
35
+ * The notice states the file's real size and line count so the model does not
36
+ * guess at offsets when it goes on to read the file, which is the failure this
37
+ * whole policy exists to prevent.
38
+ */
39
+ declare function truncateForResult(text: string, fullOutputPath: string, maxBytes?: number): TruncatedOutput;
40
+ /** `name pid 1234 up 3m sleep 60` — one runner per line. */
41
+ declare function formatRunnerLine(record: RunnerRecord, now?: number): string;
42
+ declare function formatUptime(startedAt: string, now: number): string;
43
+ //#endregion
44
+ export { LogSummary, ToolResult, TruncatedOutput, countLines, errorResult, formatRunnerLine, formatSize, formatUptime, summarizeLog, textResult, truncateForResult };
45
+ //# sourceMappingURL=responseEnvelope.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responseEnvelope.d.mts","names":[],"sources":["../../src/tool/responseEnvelope.ts"],"mappings":";;;UAOiB;EACf,SAAS;IAAQ;IAAc;;EAC/B,SAAS;;EAET;;iBAGc,WAAW,cAAc,UAAS,0BAA+B;iBAIjE,YAAY,kBAAkB;;iBAK9B,WAAW;iBAUX,WAAW;UAKV;EACf;EACA;;EAEA;;UAGe;EACf;EACA;EACA;EACA;;;iBAIc,aAAa,cAAc,mBAAgB,oBAAiC;;;;;;;;iBA8B5E,kBACd,cACA,wBACA,oBACC;;iBA6Ca,iBAAiB,QAAQ,cAAc;iBAKvC,aAAa,mBAAmB"}
@@ -0,0 +1,10 @@
1
+ import{getResultMaxBytes as e}from"../config.mjs";import t from"node:fs";const n=1024,r=n*n;function i(e,t={}){return{content:[{type:`text`,text:e}],details:t}}function a(e){return i(`Error: ${e}`,{error:e})}function o(e){return e<n?`${e} B`:e<r?`${(e/n).toFixed(1)} KB`:`${(e/r).toFixed(1)} MB`}function s(e){return e.toLocaleString(`en-US`)}function c(e){return e.length===0?0:e.endsWith(`
2
+ `)?e.split(`
3
+ `).length-1:e.split(`
4
+ `).length}function l(n,r=200,i=e()){try{let e=t.readFileSync(n,`utf8`),a=c(e),o=e.split(`
5
+ `).slice(-Math.max(1,r)-+!!e.endsWith(`
6
+ `)).join(`
7
+ `),s=Buffer.byteLength(o,`utf8`),l=s>i?Buffer.from(o,`utf8`).subarray(s-i).toString(`utf8`):o,u=s>i?l.indexOf(`
8
+ `):-1,d=u>=0?l.slice(u+1):l;return{tail:d,bytes:t.statSync(n).size,lines:a,tailLines:c(d)}}catch{return{tail:``,bytes:0,lines:0,tailLines:0}}}function u(t,n,r=e()){let i=Buffer.byteLength(t,`utf8`);if(i<=r)return{text:t,truncated:!1,outputLines:c(t)};let a=Buffer.from(t,`utf8`).subarray(i-r).toString(`utf8`),o=a.indexOf(`
9
+ `),s=o===-1?a:a.slice(o+1);return{text:`${s}\n${d(s,n,t,i)}`,truncated:!0,outputLines:c(s)}}function d(e,t,n,r){let i=c(e),a=f(t),l=a?.lines??c(n),u=a?.bytes??r;return[`[output truncated: showing the last ${s(i)} lines.`,`Full output is at ${t} (${o(u)}, ${s(l)} lines).`,`Inspect it with doom-runner logs, or read the file with an offset near line ${s(l)}.]`].join(` `)}function f(e){try{let n=t.readFileSync(e,`utf8`);return{bytes:t.statSync(e).size,lines:c(n)}}catch{return}}function p(e,t=Date.now()){let n=e.interactive?` interactive`:``;return`${e.name} pid ${e.pid} up ${m(e.startedAt,t)}${n} ${e.command}`}function m(e,t){let n=Date.parse(e);if(Number.isNaN(n))return`unknown`;let r=Math.max(0,Math.floor((t-n)/1e3));if(r<60)return`${r}s`;let i=Math.floor(r/60);if(i<60)return`${i}m`;let a=Math.floor(i/60);return a<24?`${a}h`:`${Math.floor(a/24)}d`}export{c as countLines,a as errorResult,p as formatRunnerLine,o as formatSize,m as formatUptime,l as summarizeLog,i as textResult,u as truncateForResult};
10
+ //# sourceMappingURL=responseEnvelope.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responseEnvelope.mjs","names":[],"sources":["../../src/tool/responseEnvelope.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { getResultMaxBytes } from '../config.ts';\nimport type { RunnerRecord } from '../services/RunnerRegistry/index.ts';\n\nconst BYTES_PER_KB = 1024;\nconst BYTES_PER_MB = BYTES_PER_KB * BYTES_PER_KB;\n\nexport interface ToolResult {\n content: Array<{ type: 'text'; text: string }>;\n details: Record<string, unknown>;\n /** Tools this result makes available from here on in the transcript. */\n addedToolNames?: string[];\n}\n\nexport function textResult(text: string, details: Record<string, unknown> = {}): ToolResult {\n return { content: [{ type: 'text', text }], details };\n}\n\nexport function errorResult(message: string): ToolResult {\n return textResult(`Error: ${message}`, { error: message });\n}\n\n/** Human-readable byte count, matching how pi reports output sizes. */\nexport function formatSize(bytes: number): string {\n if (bytes < BYTES_PER_KB) return `${bytes} B`;\n if (bytes < BYTES_PER_MB) return `${(bytes / BYTES_PER_KB).toFixed(1)} KB`;\n return `${(bytes / BYTES_PER_MB).toFixed(1)} MB`;\n}\n\nfunction formatCount(value: number): string {\n return value.toLocaleString('en-US');\n}\n\nexport function countLines(text: string): number {\n if (text.length === 0) return 0;\n return text.endsWith('\\n') ? text.split('\\n').length - 1 : text.split('\\n').length;\n}\n\nexport interface TruncatedOutput {\n text: string;\n truncated: boolean;\n /** Lines returned, which is what the model actually received. */\n outputLines: number;\n}\n\nexport interface LogSummary {\n tail: string;\n bytes: number;\n lines: number;\n tailLines: number;\n}\n\n/** Reads a bounded tail plus exact metadata after the writer has flushed. */\nexport function summarizeLog(path: string, maxLines = 200, maxBytes = getResultMaxBytes()): LogSummary {\n try {\n const contents = fs.readFileSync(path, 'utf8');\n const lines = countLines(contents);\n const lineTail = contents\n .split('\\n')\n .slice(-Math.max(1, maxLines) - (contents.endsWith('\\n') ? 1 : 0))\n .join('\\n');\n const bytes = Buffer.byteLength(lineTail, 'utf8');\n const byteTail =\n bytes > maxBytes\n ? Buffer.from(lineTail, 'utf8')\n .subarray(bytes - maxBytes)\n .toString('utf8')\n : lineTail;\n const firstNewline = bytes > maxBytes ? byteTail.indexOf('\\n') : -1;\n const tail = firstNewline >= 0 ? byteTail.slice(firstNewline + 1) : byteTail;\n return { tail, bytes: fs.statSync(path).size, lines, tailLines: countLines(tail) };\n } catch {\n return { tail: '', bytes: 0, lines: 0, tailLines: 0 };\n }\n}\n\n/**\n * Keeps the tail of an oversized result and points at the file holding the rest.\n *\n * The notice states the file's real size and line count so the model does not\n * guess at offsets when it goes on to read the file, which is the failure this\n * whole policy exists to prevent.\n */\nexport function truncateForResult(\n text: string,\n fullOutputPath: string,\n maxBytes = getResultMaxBytes(),\n): TruncatedOutput {\n const totalBytes = Buffer.byteLength(text, 'utf8');\n if (totalBytes <= maxBytes) return { text, truncated: false, outputLines: countLines(text) };\n\n const kept = Buffer.from(text, 'utf8')\n .subarray(totalBytes - maxBytes)\n .toString('utf8');\n // Drop the leading partial line rather than hand back a fragment.\n const newline = kept.indexOf('\\n');\n const tail = newline === -1 ? kept : kept.slice(newline + 1);\n\n return {\n text: `${tail}\\n${truncationNotice(tail, fullOutputPath, text, totalBytes)}`,\n truncated: true,\n outputLines: countLines(tail),\n };\n}\n\nfunction truncationNotice(tail: string, fullOutputPath: string, text: string, totalBytes: number): string {\n const shown = countLines(tail);\n // Counted from the file, never from `text`. What the caller holds in memory\n // is itself capped, so using it here would understate the file by orders of\n // magnitude and send the reader looking past the end of a much longer file.\n const file = measureFile(fullOutputPath);\n const totalLines = file?.lines ?? countLines(text);\n const fileSize = file?.bytes ?? totalBytes;\n\n return [\n `[output truncated: showing the last ${formatCount(shown)} lines.`,\n `Full output is at ${fullOutputPath} (${formatSize(fileSize)}, ${formatCount(totalLines)} lines).`,\n `Inspect it with doom-runner logs, or read the file with an offset near line ${formatCount(totalLines)}.]`,\n ].join(' ');\n}\n\n/** Real size and line count of the file the notice points at. */\nfunction measureFile(path: string): { bytes: number; lines: number } | undefined {\n try {\n const contents = fs.readFileSync(path, 'utf8');\n return { bytes: fs.statSync(path).size, lines: countLines(contents) };\n } catch {\n return undefined;\n }\n}\n\n/** `name pid 1234 up 3m sleep 60` — one runner per line. */\nexport function formatRunnerLine(record: RunnerRecord, now = Date.now()): string {\n const mode = record.interactive ? ' interactive' : '';\n return `${record.name} pid ${record.pid} up ${formatUptime(record.startedAt, now)}${mode} ${record.command}`;\n}\n\nexport function formatUptime(startedAt: string, now: number): string {\n const started = Date.parse(startedAt);\n if (Number.isNaN(started)) return 'unknown';\n const seconds = Math.max(0, Math.floor((now - started) / 1000));\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("typebox");const t=e.Type.Object({command:e.Type.String({description:`Bash command to execute`}),timeout:e.Type.Optional(e.Type.Number({description:`Timeout in seconds (optional, no default timeout)`})),background:e.Type.Optional(e.Type.Boolean({description:`Start the command in the background immediately instead of waiting. Use for dev servers, watchers and other commands you already know will not finish.`})),interactive:e.Type.Optional(e.Type.Boolean({description:`Run under a pseudo terminal so the command can prompt. Use only when the command asks for confirmation or input; answer it with doom-runner input. Logs from interactive runs are noisier.`})),name:e.Type.Optional(e.Type.String({description:`Preferred runner name if the command ends up in the background. A name in use gets a suffix.`})),alarm:e.Type.Optional(e.Type.Number({description:`Send you a snapshot of this runner every N seconds, so you never have to poll it. Implies background. Use it to watch a dev server or a long build, or to wake yourself on a schedule by backgrounding a sleep loop. Minimum 10 seconds. It stops on its own when the process exits, or early with doom-runner alarm stop <id>.`}))});exports.BASH_TOOL_LABEL=`bash`,exports.BASH_TOOL_NAME=`bash`,exports.BashParamsSchema=t,exports.MIN_ALARM_SECONDS=10;
2
+ //# sourceMappingURL=schema.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.cjs","names":["Type"],"sources":["../../src/tool/schema.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\n/** Replaces pi's built-in tool of the same name, so hooks keyed on `bash` keep working. */\nexport const BASH_TOOL_NAME = 'bash';\nexport const BASH_TOOL_LABEL = 'bash';\n\n/** Floor for `alarm`, so a short interval cannot flood the conversation. */\nexport const MIN_ALARM_SECONDS = 10;\n\n/**\n * Built-in bash parameters plus the backgrounding controls.\n *\n * `command` and `timeout` keep their original names and wording so the tool is\n * a drop-in replacement. Every `description` is prompt copy the model reads.\n */\nexport const BashParamsSchema = Type.Object({\n command: Type.String({ description: 'Bash command to execute' }),\n timeout: Type.Optional(Type.Number({ description: 'Timeout in seconds (optional, no default timeout)' })),\n background: Type.Optional(\n Type.Boolean({\n description:\n 'Start the command in the background immediately instead of waiting. Use for dev servers, watchers and other commands you already know will not finish.',\n }),\n ),\n interactive: Type.Optional(\n Type.Boolean({\n description:\n 'Run under a pseudo terminal so the command can prompt. Use only when the command asks for confirmation or input; answer it with doom-runner input. Logs from interactive runs are noisier.',\n }),\n ),\n name: Type.Optional(\n Type.String({\n description: 'Preferred runner name if the command ends up in the background. A name in use gets a suffix.',\n }),\n ),\n alarm: Type.Optional(\n Type.Number({\n description: `Send you a snapshot of this runner every N seconds, so you never have to poll it. Implies background. Use it to watch a dev server or a long build, or to wake yourself on a schedule by backgrounding a sleep loop. Minimum ${MIN_ALARM_SECONDS} seconds. It stops on its own when the process exits, or early with doom-runner alarm stop <id>.`,\n }),\n ),\n});\n\nexport type BashParams = Static<typeof BashParamsSchema>;\n"],"mappings":"4FAGA,MAYa,EAAmBA,EAAAA,KAAK,OAAO,CAC1C,QAASA,EAAAA,KAAK,OAAO,CAAE,YAAa,yBAA0B,CAAC,EAC/D,QAASA,EAAAA,KAAK,SAASA,EAAAA,KAAK,OAAO,CAAE,YAAa,mDAAoD,CAAC,CAAC,EACxG,WAAYA,EAAAA,KAAK,SACfA,EAAAA,KAAK,QAAQ,CACX,YACE,wJACJ,CAAC,CACH,EACA,YAAaA,EAAAA,KAAK,SAChBA,EAAAA,KAAK,QAAQ,CACX,YACE,4LACJ,CAAC,CACH,EACA,KAAMA,EAAAA,KAAK,SACTA,EAAAA,KAAK,OAAO,CACV,YAAa,8FACf,CAAC,CACH,EACA,MAAOA,EAAAA,KAAK,SACVA,EAAAA,KAAK,OAAO,CACV,YAAa,iUACf,CAAC,CACH,CACF,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { Static, Type } from "typebox";
2
+ //#region src/tool/schema.d.ts
3
+ /** Replaces pi's built-in tool of the same name, so hooks keyed on `bash` keep working. */
4
+ declare const BASH_TOOL_NAME = "bash";
5
+ declare const BASH_TOOL_LABEL = "bash";
6
+ /** Floor for `alarm`, so a short interval cannot flood the conversation. */
7
+ declare const MIN_ALARM_SECONDS = 10;
8
+ /**
9
+ * Built-in bash parameters plus the backgrounding controls.
10
+ *
11
+ * `command` and `timeout` keep their original names and wording so the tool is
12
+ * a drop-in replacement. Every `description` is prompt copy the model reads.
13
+ */
14
+ declare const BashParamsSchema: Type.TObject<{
15
+ command: Type.TString;
16
+ timeout: Type.TOptional<Type.TNumber>;
17
+ background: Type.TOptional<Type.TBoolean>;
18
+ interactive: Type.TOptional<Type.TBoolean>;
19
+ name: Type.TOptional<Type.TString>;
20
+ alarm: Type.TOptional<Type.TNumber>;
21
+ }>;
22
+ type BashParams = Static<typeof BashParamsSchema>;
23
+ //#endregion
24
+ export { BASH_TOOL_LABEL, BASH_TOOL_NAME, BashParams, BashParamsSchema, MIN_ALARM_SECONDS };
25
+ //# sourceMappingURL=schema.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.cts","names":[],"sources":["../../src/tool/schema.ts"],"mappings":";;;cAGa;cACA;;cAGA;;;;;;;cAQA,kBAAgB,KAAA;;;;;;;;KA2BjB,aAAa,cAAc"}
@@ -0,0 +1,25 @@
1
+ import { Static, Type } from "typebox";
2
+ //#region src/tool/schema.d.ts
3
+ /** Replaces pi's built-in tool of the same name, so hooks keyed on `bash` keep working. */
4
+ declare const BASH_TOOL_NAME = "bash";
5
+ declare const BASH_TOOL_LABEL = "bash";
6
+ /** Floor for `alarm`, so a short interval cannot flood the conversation. */
7
+ declare const MIN_ALARM_SECONDS = 10;
8
+ /**
9
+ * Built-in bash parameters plus the backgrounding controls.
10
+ *
11
+ * `command` and `timeout` keep their original names and wording so the tool is
12
+ * a drop-in replacement. Every `description` is prompt copy the model reads.
13
+ */
14
+ declare const BashParamsSchema: Type.TObject<{
15
+ command: Type.TString;
16
+ timeout: Type.TOptional<Type.TNumber>;
17
+ background: Type.TOptional<Type.TBoolean>;
18
+ interactive: Type.TOptional<Type.TBoolean>;
19
+ name: Type.TOptional<Type.TString>;
20
+ alarm: Type.TOptional<Type.TNumber>;
21
+ }>;
22
+ type BashParams = Static<typeof BashParamsSchema>;
23
+ //#endregion
24
+ export { BASH_TOOL_LABEL, BASH_TOOL_NAME, BashParams, BashParamsSchema, MIN_ALARM_SECONDS };
25
+ //# sourceMappingURL=schema.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.mts","names":[],"sources":["../../src/tool/schema.ts"],"mappings":";;;cAGa;cACA;;cAGA;;;;;;;cAQA,kBAAgB,KAAA;;;;;;;;KA2BjB,aAAa,cAAc"}
@@ -0,0 +1,2 @@
1
+ import{Type as e}from"typebox";const t=`bash`,n=`bash`,r=10,i=e.Object({command:e.String({description:`Bash command to execute`}),timeout:e.Optional(e.Number({description:`Timeout in seconds (optional, no default timeout)`})),background:e.Optional(e.Boolean({description:`Start the command in the background immediately instead of waiting. Use for dev servers, watchers and other commands you already know will not finish.`})),interactive:e.Optional(e.Boolean({description:`Run under a pseudo terminal so the command can prompt. Use only when the command asks for confirmation or input; answer it with doom-runner input. Logs from interactive runs are noisier.`})),name:e.Optional(e.String({description:`Preferred runner name if the command ends up in the background. A name in use gets a suffix.`})),alarm:e.Optional(e.Number({description:`Send you a snapshot of this runner every N seconds, so you never have to poll it. Implies background. Use it to watch a dev server or a long build, or to wake yourself on a schedule by backgrounding a sleep loop. Minimum 10 seconds. It stops on its own when the process exits, or early with doom-runner alarm stop <id>.`}))});export{n as BASH_TOOL_LABEL,t as BASH_TOOL_NAME,i as BashParamsSchema,r as MIN_ALARM_SECONDS};
2
+ //# sourceMappingURL=schema.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.mjs","names":[],"sources":["../../src/tool/schema.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\n/** Replaces pi's built-in tool of the same name, so hooks keyed on `bash` keep working. */\nexport const BASH_TOOL_NAME = 'bash';\nexport const BASH_TOOL_LABEL = 'bash';\n\n/** Floor for `alarm`, so a short interval cannot flood the conversation. */\nexport const MIN_ALARM_SECONDS = 10;\n\n/**\n * Built-in bash parameters plus the backgrounding controls.\n *\n * `command` and `timeout` keep their original names and wording so the tool is\n * a drop-in replacement. Every `description` is prompt copy the model reads.\n */\nexport const BashParamsSchema = Type.Object({\n command: Type.String({ description: 'Bash command to execute' }),\n timeout: Type.Optional(Type.Number({ description: 'Timeout in seconds (optional, no default timeout)' })),\n background: Type.Optional(\n Type.Boolean({\n description:\n 'Start the command in the background immediately instead of waiting. Use for dev servers, watchers and other commands you already know will not finish.',\n }),\n ),\n interactive: Type.Optional(\n Type.Boolean({\n description:\n 'Run under a pseudo terminal so the command can prompt. Use only when the command asks for confirmation or input; answer it with doom-runner input. Logs from interactive runs are noisier.',\n }),\n ),\n name: Type.Optional(\n Type.String({\n description: 'Preferred runner name if the command ends up in the background. A name in use gets a suffix.',\n }),\n ),\n alarm: Type.Optional(\n Type.Number({\n description: `Send you a snapshot of this runner every N seconds, so you never have to poll it. Implies background. Use it to watch a dev server or a long build, or to wake yourself on a schedule by backgrounding a sleep loop. Minimum ${MIN_ALARM_SECONDS} seconds. It stops on its own when the process exits, or early with doom-runner alarm stop <id>.`,\n }),\n ),\n});\n\nexport type BashParams = Static<typeof BashParamsSchema>;\n"],"mappings":"+BAGA,MAAa,EAAiB,OACjB,EAAkB,OAGlB,EAAoB,GAQpB,EAAmB,EAAK,OAAO,CAC1C,QAAS,EAAK,OAAO,CAAE,YAAa,yBAA0B,CAAC,EAC/D,QAAS,EAAK,SAAS,EAAK,OAAO,CAAE,YAAa,mDAAoD,CAAC,CAAC,EACxG,WAAY,EAAK,SACf,EAAK,QAAQ,CACX,YACE,wJACJ,CAAC,CACH,EACA,YAAa,EAAK,SAChB,EAAK,QAAQ,CACX,YACE,4LACJ,CAAC,CACH,EACA,KAAM,EAAK,SACT,EAAK,OAAO,CACV,YAAa,8FACf,CAAC,CACH,EACA,MAAO,EAAK,SACV,EAAK,OAAO,CACV,YAAa,iUACf,CAAC,CACH,CACF,CAAC"}
@@ -0,0 +1,8 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("../tool/responseEnvelope.cjs");let n=require("node:os");n=e.__toESM(n,1);let r=require("@earendil-works/pi-coding-agent"),i=require("@earendil-works/pi-tui");const a=/\[[0-9;]*m/;function o(e,t,n){return a.test(e)?e:n.fg(t,e)}function s(e,t=n.default.homedir()){return t.length>0?e.split(t).join(`~`):e}function c(e){let t=e.split(`
2
+ `).map(e=>e.trim()).filter(e=>e.length>0),n=t[0]??``;return t.length>1?`${n} … +${t.length-1} lines`:n}function l(e,t=160){if(e.length<=t)return e;let n=t-3,r=Math.ceil(n/2),i=e.slice(0,r),a=e.slice(e.length-(n-r)),o=i.lastIndexOf(` `);o>i.length/2&&(i=i.slice(0,o));let s=a.indexOf(` `);return s>=0&&s<a.length/2&&(a=a.slice(s+1)),`${i} … ${a}`}function u(e){return l(s(c(e)))}function d(e){let t=[];return e.background===!0&&t.push(`bg`),e.interactive===!0&&t.push(`tty`),e.alarm!==void 0&&t.push(`alarm ${e.alarm}s`),e.timeout!==void 0&&t.push(`${e.timeout}s`),e.name!==void 0&&e.name.length>0&&t.push(e.name),t}function f(e,t,n=r.highlightCode){let a=n(u(e.command),`bash`).join(` `),o=t.fg(`toolTitle`,t.bold(`bash `))+a,s=d(e);return s.length>0&&(o+=` ${t.fg(`muted`,`· ${s.join(` · `)}`)}`),new i.Text(o,0,0)}function p(e){let n=[];return e.lines!==void 0&&n.push(`${e.lines.toLocaleString(`en-US`)} lines`),e.fileSize!==void 0&&n.push(t.formatSize(e.fileSize)),e.runner!==void 0&&n.push(e.runner),n.join(` · `)}function m(e,t){let n=(e.tail??``).split(`
3
+ `);for(;n.length>0&&n[n.length-1]?.trim()===``;)n.pop();return t||n.length<=12?n:n.slice(-12)}function h(e){return(e.content??[]).map(e=>e.text??``).join(``)}function g(e,t){let n=e.split(`
4
+ `);for(;n.length>0&&n[n.length-1]?.trim()===``;)n.pop();return n.length<=t?n:n.slice(-t)}function _(e,t,n){let r=e.details??{};if(t.isPartial){let t=g(h(e),12),r=n.fg(`warning`,`◐`)+n.fg(`dim`,` running`);return new i.Text([...t.map(e=>o(e,`toolOutput`,n)),r].join(`
5
+ `),0,0)}if(e.isError===!0){let a=g(h(e),t.expanded?2**53-1:12),s=p(r),c=s.length>0?` ${s}`:``;return new i.Text([...a.map(e=>o(e,`toolOutput`,n)),n.fg(`error`,`✗`)+n.fg(`dim`,c)].join(`
6
+ `),0,0)}if(r.promoted===!0){let e=r.runner??r.id??`runner`,t=r.id===void 0?``:` · ${r.id}`;return new i.Text(n.fg(`accent`,`● ${e}`)+n.fg(`muted`,`${t} · background`),0,0)}let a=m(r,t.expanded),s=r.exitCode!==void 0&&r.exitCode!==null,c=r.timedOut===!0||s&&r.exitCode!==0,l=c?n.fg(`error`,`✗`):n.fg(`success`,`✓`),u=[];r.timedOut===!0?u.push(`timed out`):c&&u.push(`exit ${r.exitCode}`);let d=p(r);d.length>0&&u.push(d),!t.expanded&&(r.tailLines??0)>a.length&&u.push(`ctrl+o`);let f=a.map(e=>o(e,`toolOutput`,n));return f.push(l+n.fg(`dim`,u.length>0?` ${u.join(` · `)}`:``)),new i.Text(f.join(`
7
+ `),0,0)}exports.abbreviateHome=s,exports.collapseCommand=c,exports.formatBashCommand=u,exports.formatBashFlags=d,exports.formatResultSummary=p,exports.renderBashCall=f,exports.renderBashResult=_,exports.truncateMiddle=l;
8
+ //# sourceMappingURL=bashRender.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bashRender.cjs","names":["os","highlightCode","Text","formatSize"],"sources":["../../src/tui/bashRender.ts"],"sourcesContent":["import os from 'node:os';\nimport { highlightCode, type Theme, type ThemeColor } from '@earendil-works/pi-coding-agent';\nimport { Text } from '@earendil-works/pi-tui';\nimport { formatSize } from '../tool/responseEnvelope.ts';\nimport type { BashParams } from '../tool/schema.ts';\n\nconst ELLIPSIS = '…';\n/** Spaced so the join never glues two words into one unreadable token. */\nconst GAP = ' … ';\n/** Wide enough to keep a realistic command intact, short enough to stay under three wrapped rows. */\nconst MAX_COMMAND_LENGTH = 160;\n\n/**\n * Syntax highlighter for the command line.\n *\n * `highlightCode` reads Pi's global theme singleton rather than the theme passed\n * to a renderer, so it is injected here to keep these functions testable.\n */\nexport type Highlighter = (code: string, lang?: string) => string[];\n/** Lines of log kept in the collapsed result, before `ctrl+o` reveals the rest. */\nconst COLLAPSED_TAIL_LINES = 12;\n/** Live output is unbounded while a command runs, so the running state keeps only a window. */\nconst STREAM_TAIL_LINES = 12;\n\n/** An SGR colour sequence, the only escape the log pipeline is allowed to keep. */\nconst SGR_PATTERN = /\u001b\\[[0-9;]*m/;\n\n/**\n * Applies a theme colour only to lines that carry none of their own.\n *\n * A command that emits colour has already said how its output should look, and\n * wrapping it would reset to the terminal default at the first embedded escape.\n */\nfunction paint(line: string, color: ThemeColor, theme: Theme): string {\n return SGR_PATTERN.test(line) ? line : theme.fg(color, line);\n}\n\n/** Structured view of what `formatRunResult` reports, read only by the renderers. */\nexport interface BashResultDetails {\n id?: string;\n runner?: string;\n exitCode?: number | null;\n logPath?: string;\n fileSize?: number;\n lines?: number;\n timedOut?: boolean;\n promoted?: boolean;\n reason?: string;\n tail?: string;\n tailLines?: number;\n}\n\n/** `/Users/me/x` becomes `~/x`. Absolute home paths are what push these lines onto extra rows. */\nexport function abbreviateHome(text: string, home: string = os.homedir()): string {\n return home.length > 0 ? text.split(home).join('~') : text;\n}\n\n/** Collapse a heredoc or multi-line script to one scannable line plus a count. */\nexport function collapseCommand(command: string): string {\n const lines = command\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n const first = lines[0] ?? '';\n return lines.length > 1 ? `${first} ${ELLIPSIS} +${lines.length - 1} lines` : first;\n}\n\n/** Drop the middle rather than the end, so a long pipeline keeps both its source and its sink. */\nexport function truncateMiddle(text: string, max: number = MAX_COMMAND_LENGTH): string {\n if (text.length <= max) return text;\n const keep = max - GAP.length;\n const head = Math.ceil(keep / 2);\n let start = text.slice(0, head);\n let end = text.slice(text.length - (keep - head));\n\n // Snap both cuts to a token boundary, so neither side ends mid-word. Each is\n // only moved when a boundary exists in the half nearest the cut, otherwise a\n // single long argument would swallow the whole budget.\n const lastSpace = start.lastIndexOf(' ');\n if (lastSpace > start.length / 2) start = start.slice(0, lastSpace);\n const firstSpace = end.indexOf(' ');\n if (firstSpace >= 0 && firstSpace < end.length / 2) end = end.slice(firstSpace + 1);\n\n return `${start}${GAP}${end}`;\n}\n\nexport function formatBashCommand(command: string): string {\n return truncateMiddle(abbreviateHome(collapseCommand(command)));\n}\n\n/** Modifiers worth seeing at a glance, in the widget's `·` idiom. */\nexport function formatBashFlags(args: BashParams): string[] {\n const flags: string[] = [];\n if (args.background === true) flags.push('bg');\n if (args.interactive === true) flags.push('tty');\n if (args.alarm !== undefined) flags.push(`alarm ${args.alarm}s`);\n if (args.timeout !== undefined) flags.push(`${args.timeout}s`);\n if (args.name !== undefined && args.name.length > 0) flags.push(args.name);\n return flags;\n}\n\nexport function renderBashCall(args: BashParams, theme: Theme, highlight: Highlighter = highlightCode): Text {\n // Highlight after shortening: the ANSI codes would break any later slicing.\n const command = highlight(formatBashCommand(args.command), 'bash').join(' ');\n let text = theme.fg('toolTitle', theme.bold('bash ')) + command;\n const flags = formatBashFlags(args);\n if (flags.length > 0) text += ` ${theme.fg('muted', `· ${flags.join(' · ')}`)}`;\n return new Text(text, 0, 0);\n}\n\n/** The metadata footer, collapsed from five lines to one. */\nexport function formatResultSummary(details: BashResultDetails): string {\n const parts: string[] = [];\n if (details.lines !== undefined) parts.push(`${details.lines.toLocaleString('en-US')} lines`);\n if (details.fileSize !== undefined) parts.push(formatSize(details.fileSize));\n if (details.runner !== undefined) parts.push(details.runner);\n return parts.join(' · ');\n}\n\nfunction tailLines(details: BashResultDetails, expanded: boolean): string[] {\n const lines = (details.tail ?? '').split('\\n');\n while (lines.length > 0 && lines[lines.length - 1]?.trim() === '') lines.pop();\n if (expanded || lines.length <= COLLAPSED_TAIL_LINES) return lines;\n return lines.slice(-COLLAPSED_TAIL_LINES);\n}\n\n/** Concatenated text of a tool result, which is all a thrown failure leaves behind. */\nfunction contentText(result: { content?: Array<{ type: string; text?: string }> }): string {\n return (result.content ?? []).map((block) => block.text ?? '').join('');\n}\n\n/** Last `max` lines, so a chatty command cannot push the transcript off screen. */\nfunction lastLines(text: string, max: number): string[] {\n const all = text.split('\\n');\n while (all.length > 0 && all[all.length - 1]?.trim() === '') all.pop();\n return all.length <= max ? all : all.slice(-max);\n}\n\nexport function renderBashResult(\n result: { content?: Array<{ type: string; text?: string }>; details?: unknown; isError?: boolean },\n options: { expanded: boolean; isPartial: boolean },\n theme: Theme,\n): Text {\n const details = (result.details ?? {}) as BashResultDetails;\n\n // Running. Details do not exist yet, so the streamed text is the only source,\n // and it is bounded here because it grows without limit while the command runs.\n if (options.isPartial) {\n const streamed = lastLines(contentText(result), STREAM_TAIL_LINES);\n const label = theme.fg('warning', '◐') + theme.fg('dim', ' running');\n return new Text([...streamed.map((line) => paint(line, 'toolOutput', theme)), label].join('\\n'), 0, 0);\n }\n\n // Failed. formatRunResult throws on a bad exit, so Pi hands back the error\n // text with no details at all; without this the block would render a bare tick.\n if (result.isError === true) {\n const body = lastLines(contentText(result), options.expanded ? Number.MAX_SAFE_INTEGER : COLLAPSED_TAIL_LINES);\n const summary = formatResultSummary(details);\n const meta = summary.length > 0 ? ` ${summary}` : '';\n return new Text(\n [...body.map((line) => paint(line, 'toolOutput', theme)), theme.fg('error', '✗') + theme.fg('dim', meta)].join(\n '\\n',\n ),\n 0,\n 0,\n );\n }\n\n if (details.promoted === true) {\n const label = details.runner ?? details.id ?? 'runner';\n const suffix = details.id === undefined ? '' : ` · ${details.id}`;\n return new Text(theme.fg('accent', `● ${label}`) + theme.fg('muted', `${suffix} · background`), 0, 0);\n }\n\n const body = tailLines(details, options.expanded);\n // An absent exit code means the runner never reported one, which is not a failure.\n const exited = details.exitCode !== undefined && details.exitCode !== null;\n const failed = details.timedOut === true || (exited && details.exitCode !== 0);\n const glyph = failed ? theme.fg('error', '✗') : theme.fg('success', '✓');\n\n const meta: string[] = [];\n if (details.timedOut === true) meta.push('timed out');\n else if (failed) meta.push(`exit ${details.exitCode}`);\n const summary = formatResultSummary(details);\n if (summary.length > 0) meta.push(summary);\n if (!options.expanded && (details.tailLines ?? 0) > body.length) meta.push('ctrl+o');\n\n const lines = body.map((line) => paint(line, 'toolOutput', theme));\n // `dim`, not `muted`: muted sits too close to toolOutput to read as chrome.\n lines.push(glyph + theme.fg('dim', meta.length > 0 ? ` ${meta.join(' · ')}` : ''));\n return new Text(lines.join('\\n'), 0, 0);\n}\n"],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { BashParams } from "../tool/schema.cjs";
2
+ import { Theme } from "@earendil-works/pi-coding-agent";
3
+ import { Text } from "@earendil-works/pi-tui";
4
+ //#region src/tui/bashRender.d.ts
5
+ /**
6
+ * Syntax highlighter for the command line.
7
+ *
8
+ * `highlightCode` reads Pi's global theme singleton rather than the theme passed
9
+ * to a renderer, so it is injected here to keep these functions testable.
10
+ */
11
+ type Highlighter = (code: string, lang?: string) => string[];
12
+ /** Structured view of what `formatRunResult` reports, read only by the renderers. */
13
+ interface BashResultDetails {
14
+ id?: string;
15
+ runner?: string;
16
+ exitCode?: number | null;
17
+ logPath?: string;
18
+ fileSize?: number;
19
+ lines?: number;
20
+ timedOut?: boolean;
21
+ promoted?: boolean;
22
+ reason?: string;
23
+ tail?: string;
24
+ tailLines?: number;
25
+ }
26
+ /** `/Users/me/x` becomes `~/x`. Absolute home paths are what push these lines onto extra rows. */
27
+ declare function abbreviateHome(text: string, home?: string): string;
28
+ /** Collapse a heredoc or multi-line script to one scannable line plus a count. */
29
+ declare function collapseCommand(command: string): string;
30
+ /** Drop the middle rather than the end, so a long pipeline keeps both its source and its sink. */
31
+ declare function truncateMiddle(text: string, max?: number): string;
32
+ declare function formatBashCommand(command: string): string;
33
+ /** Modifiers worth seeing at a glance, in the widget's `·` idiom. */
34
+ declare function formatBashFlags(args: BashParams): string[];
35
+ declare function renderBashCall(args: BashParams, theme: Theme, highlight?: Highlighter): Text;
36
+ /** The metadata footer, collapsed from five lines to one. */
37
+ declare function formatResultSummary(details: BashResultDetails): string;
38
+ declare function renderBashResult(result: {
39
+ content?: Array<{
40
+ type: string;
41
+ text?: string;
42
+ }>;
43
+ details?: unknown;
44
+ isError?: boolean;
45
+ }, options: {
46
+ expanded: boolean;
47
+ isPartial: boolean;
48
+ }, theme: Theme): Text;
49
+ //#endregion
50
+ export { BashResultDetails, Highlighter, abbreviateHome, collapseCommand, formatBashCommand, formatBashFlags, formatResultSummary, renderBashCall, renderBashResult, truncateMiddle };
51
+ //# sourceMappingURL=bashRender.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bashRender.d.cts","names":[],"sources":["../../src/tui/bashRender.ts"],"mappings":";;;;;;;;;;KAkBY,eAAe,cAAc;;UAoBxB;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;iBAIc,eAAe,cAAc;;iBAK7B,gBAAgB;;iBAUhB,eAAe,cAAc;iBAkB7B,kBAAkB;;iBAKlB,gBAAgB,MAAM;iBAUtB,eAAe,MAAM,YAAY,OAAO,OAAO,YAAW,cAA8B;;iBAUxF,oBAAoB,SAAS;iBA2B7B,iBACd;EAAU,UAAU;IAAQ;IAAc;;EAAkB;EAAmB;GAC/E;EAAW;EAAmB;GAC9B,OAAO,QACN"}
@@ -0,0 +1,51 @@
1
+ import { BashParams } from "../tool/schema.mjs";
2
+ import { Theme } from "@earendil-works/pi-coding-agent";
3
+ import { Text } from "@earendil-works/pi-tui";
4
+ //#region src/tui/bashRender.d.ts
5
+ /**
6
+ * Syntax highlighter for the command line.
7
+ *
8
+ * `highlightCode` reads Pi's global theme singleton rather than the theme passed
9
+ * to a renderer, so it is injected here to keep these functions testable.
10
+ */
11
+ type Highlighter = (code: string, lang?: string) => string[];
12
+ /** Structured view of what `formatRunResult` reports, read only by the renderers. */
13
+ interface BashResultDetails {
14
+ id?: string;
15
+ runner?: string;
16
+ exitCode?: number | null;
17
+ logPath?: string;
18
+ fileSize?: number;
19
+ lines?: number;
20
+ timedOut?: boolean;
21
+ promoted?: boolean;
22
+ reason?: string;
23
+ tail?: string;
24
+ tailLines?: number;
25
+ }
26
+ /** `/Users/me/x` becomes `~/x`. Absolute home paths are what push these lines onto extra rows. */
27
+ declare function abbreviateHome(text: string, home?: string): string;
28
+ /** Collapse a heredoc or multi-line script to one scannable line plus a count. */
29
+ declare function collapseCommand(command: string): string;
30
+ /** Drop the middle rather than the end, so a long pipeline keeps both its source and its sink. */
31
+ declare function truncateMiddle(text: string, max?: number): string;
32
+ declare function formatBashCommand(command: string): string;
33
+ /** Modifiers worth seeing at a glance, in the widget's `·` idiom. */
34
+ declare function formatBashFlags(args: BashParams): string[];
35
+ declare function renderBashCall(args: BashParams, theme: Theme, highlight?: Highlighter): Text;
36
+ /** The metadata footer, collapsed from five lines to one. */
37
+ declare function formatResultSummary(details: BashResultDetails): string;
38
+ declare function renderBashResult(result: {
39
+ content?: Array<{
40
+ type: string;
41
+ text?: string;
42
+ }>;
43
+ details?: unknown;
44
+ isError?: boolean;
45
+ }, options: {
46
+ expanded: boolean;
47
+ isPartial: boolean;
48
+ }, theme: Theme): Text;
49
+ //#endregion
50
+ export { BashResultDetails, Highlighter, abbreviateHome, collapseCommand, formatBashCommand, formatBashFlags, formatResultSummary, renderBashCall, renderBashResult, truncateMiddle };
51
+ //# sourceMappingURL=bashRender.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bashRender.d.mts","names":[],"sources":["../../src/tui/bashRender.ts"],"mappings":";;;;;;;;;;KAkBY,eAAe,cAAc;;UAoBxB;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;iBAIc,eAAe,cAAc;;iBAK7B,gBAAgB;;iBAUhB,eAAe,cAAc;iBAkB7B,kBAAkB;;iBAKlB,gBAAgB,MAAM;iBAUtB,eAAe,MAAM,YAAY,OAAO,OAAO,YAAW,cAA8B;;iBAUxF,oBAAoB,SAAS;iBA2B7B,iBACd;EAAU,UAAU;IAAQ;IAAc;;EAAkB;EAAmB;GAC/E;EAAW;EAAmB;GAC9B,OAAO,QACN"}
@@ -0,0 +1,8 @@
1
+ import{formatSize as e}from"../tool/responseEnvelope.mjs";import t from"node:os";import{highlightCode as n}from"@earendil-works/pi-coding-agent";import{Text as r}from"@earendil-works/pi-tui";const i=/\[[0-9;]*m/;function a(e,t,n){return i.test(e)?e:n.fg(t,e)}function o(e,n=t.homedir()){return n.length>0?e.split(n).join(`~`):e}function s(e){let t=e.split(`
2
+ `).map(e=>e.trim()).filter(e=>e.length>0),n=t[0]??``;return t.length>1?`${n} … +${t.length-1} lines`:n}function c(e,t=160){if(e.length<=t)return e;let n=t-3,r=Math.ceil(n/2),i=e.slice(0,r),a=e.slice(e.length-(n-r)),o=i.lastIndexOf(` `);o>i.length/2&&(i=i.slice(0,o));let s=a.indexOf(` `);return s>=0&&s<a.length/2&&(a=a.slice(s+1)),`${i} … ${a}`}function l(e){return c(o(s(e)))}function u(e){let t=[];return e.background===!0&&t.push(`bg`),e.interactive===!0&&t.push(`tty`),e.alarm!==void 0&&t.push(`alarm ${e.alarm}s`),e.timeout!==void 0&&t.push(`${e.timeout}s`),e.name!==void 0&&e.name.length>0&&t.push(e.name),t}function d(e,t,i=n){let a=i(l(e.command),`bash`).join(` `),o=t.fg(`toolTitle`,t.bold(`bash `))+a,s=u(e);return s.length>0&&(o+=` ${t.fg(`muted`,`· ${s.join(` · `)}`)}`),new r(o,0,0)}function f(t){let n=[];return t.lines!==void 0&&n.push(`${t.lines.toLocaleString(`en-US`)} lines`),t.fileSize!==void 0&&n.push(e(t.fileSize)),t.runner!==void 0&&n.push(t.runner),n.join(` · `)}function p(e,t){let n=(e.tail??``).split(`
3
+ `);for(;n.length>0&&n[n.length-1]?.trim()===``;)n.pop();return t||n.length<=12?n:n.slice(-12)}function m(e){return(e.content??[]).map(e=>e.text??``).join(``)}function h(e,t){let n=e.split(`
4
+ `);for(;n.length>0&&n[n.length-1]?.trim()===``;)n.pop();return n.length<=t?n:n.slice(-t)}function g(e,t,n){let i=e.details??{};if(t.isPartial){let t=h(m(e),12),i=n.fg(`warning`,`◐`)+n.fg(`dim`,` running`);return new r([...t.map(e=>a(e,`toolOutput`,n)),i].join(`
5
+ `),0,0)}if(e.isError===!0){let o=h(m(e),t.expanded?2**53-1:12),s=f(i),c=s.length>0?` ${s}`:``;return new r([...o.map(e=>a(e,`toolOutput`,n)),n.fg(`error`,`✗`)+n.fg(`dim`,c)].join(`
6
+ `),0,0)}if(i.promoted===!0){let e=i.runner??i.id??`runner`,t=i.id===void 0?``:` · ${i.id}`;return new r(n.fg(`accent`,`● ${e}`)+n.fg(`muted`,`${t} · background`),0,0)}let o=p(i,t.expanded),s=i.exitCode!==void 0&&i.exitCode!==null,c=i.timedOut===!0||s&&i.exitCode!==0,l=c?n.fg(`error`,`✗`):n.fg(`success`,`✓`),u=[];i.timedOut===!0?u.push(`timed out`):c&&u.push(`exit ${i.exitCode}`);let d=f(i);d.length>0&&u.push(d),!t.expanded&&(i.tailLines??0)>o.length&&u.push(`ctrl+o`);let g=o.map(e=>a(e,`toolOutput`,n));return g.push(l+n.fg(`dim`,u.length>0?` ${u.join(` · `)}`:``)),new r(g.join(`
7
+ `),0,0)}export{o as abbreviateHome,s as collapseCommand,l as formatBashCommand,u as formatBashFlags,f as formatResultSummary,d as renderBashCall,g as renderBashResult,c as truncateMiddle};
8
+ //# sourceMappingURL=bashRender.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bashRender.mjs","names":[],"sources":["../../src/tui/bashRender.ts"],"sourcesContent":["import os from 'node:os';\nimport { highlightCode, type Theme, type ThemeColor } from '@earendil-works/pi-coding-agent';\nimport { Text } from '@earendil-works/pi-tui';\nimport { formatSize } from '../tool/responseEnvelope.ts';\nimport type { BashParams } from '../tool/schema.ts';\n\nconst ELLIPSIS = '…';\n/** Spaced so the join never glues two words into one unreadable token. */\nconst GAP = ' … ';\n/** Wide enough to keep a realistic command intact, short enough to stay under three wrapped rows. */\nconst MAX_COMMAND_LENGTH = 160;\n\n/**\n * Syntax highlighter for the command line.\n *\n * `highlightCode` reads Pi's global theme singleton rather than the theme passed\n * to a renderer, so it is injected here to keep these functions testable.\n */\nexport type Highlighter = (code: string, lang?: string) => string[];\n/** Lines of log kept in the collapsed result, before `ctrl+o` reveals the rest. */\nconst COLLAPSED_TAIL_LINES = 12;\n/** Live output is unbounded while a command runs, so the running state keeps only a window. */\nconst STREAM_TAIL_LINES = 12;\n\n/** An SGR colour sequence, the only escape the log pipeline is allowed to keep. */\nconst SGR_PATTERN = /\u001b\\[[0-9;]*m/;\n\n/**\n * Applies a theme colour only to lines that carry none of their own.\n *\n * A command that emits colour has already said how its output should look, and\n * wrapping it would reset to the terminal default at the first embedded escape.\n */\nfunction paint(line: string, color: ThemeColor, theme: Theme): string {\n return SGR_PATTERN.test(line) ? line : theme.fg(color, line);\n}\n\n/** Structured view of what `formatRunResult` reports, read only by the renderers. */\nexport interface BashResultDetails {\n id?: string;\n runner?: string;\n exitCode?: number | null;\n logPath?: string;\n fileSize?: number;\n lines?: number;\n timedOut?: boolean;\n promoted?: boolean;\n reason?: string;\n tail?: string;\n tailLines?: number;\n}\n\n/** `/Users/me/x` becomes `~/x`. Absolute home paths are what push these lines onto extra rows. */\nexport function abbreviateHome(text: string, home: string = os.homedir()): string {\n return home.length > 0 ? text.split(home).join('~') : text;\n}\n\n/** Collapse a heredoc or multi-line script to one scannable line plus a count. */\nexport function collapseCommand(command: string): string {\n const lines = command\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n const first = lines[0] ?? '';\n return lines.length > 1 ? `${first} ${ELLIPSIS} +${lines.length - 1} lines` : first;\n}\n\n/** Drop the middle rather than the end, so a long pipeline keeps both its source and its sink. */\nexport function truncateMiddle(text: string, max: number = MAX_COMMAND_LENGTH): string {\n if (text.length <= max) return text;\n const keep = max - GAP.length;\n const head = Math.ceil(keep / 2);\n let start = text.slice(0, head);\n let end = text.slice(text.length - (keep - head));\n\n // Snap both cuts to a token boundary, so neither side ends mid-word. Each is\n // only moved when a boundary exists in the half nearest the cut, otherwise a\n // single long argument would swallow the whole budget.\n const lastSpace = start.lastIndexOf(' ');\n if (lastSpace > start.length / 2) start = start.slice(0, lastSpace);\n const firstSpace = end.indexOf(' ');\n if (firstSpace >= 0 && firstSpace < end.length / 2) end = end.slice(firstSpace + 1);\n\n return `${start}${GAP}${end}`;\n}\n\nexport function formatBashCommand(command: string): string {\n return truncateMiddle(abbreviateHome(collapseCommand(command)));\n}\n\n/** Modifiers worth seeing at a glance, in the widget's `·` idiom. */\nexport function formatBashFlags(args: BashParams): string[] {\n const flags: string[] = [];\n if (args.background === true) flags.push('bg');\n if (args.interactive === true) flags.push('tty');\n if (args.alarm !== undefined) flags.push(`alarm ${args.alarm}s`);\n if (args.timeout !== undefined) flags.push(`${args.timeout}s`);\n if (args.name !== undefined && args.name.length > 0) flags.push(args.name);\n return flags;\n}\n\nexport function renderBashCall(args: BashParams, theme: Theme, highlight: Highlighter = highlightCode): Text {\n // Highlight after shortening: the ANSI codes would break any later slicing.\n const command = highlight(formatBashCommand(args.command), 'bash').join(' ');\n let text = theme.fg('toolTitle', theme.bold('bash ')) + command;\n const flags = formatBashFlags(args);\n if (flags.length > 0) text += ` ${theme.fg('muted', `· ${flags.join(' · ')}`)}`;\n return new Text(text, 0, 0);\n}\n\n/** The metadata footer, collapsed from five lines to one. */\nexport function formatResultSummary(details: BashResultDetails): string {\n const parts: string[] = [];\n if (details.lines !== undefined) parts.push(`${details.lines.toLocaleString('en-US')} lines`);\n if (details.fileSize !== undefined) parts.push(formatSize(details.fileSize));\n if (details.runner !== undefined) parts.push(details.runner);\n return parts.join(' · ');\n}\n\nfunction tailLines(details: BashResultDetails, expanded: boolean): string[] {\n const lines = (details.tail ?? '').split('\\n');\n while (lines.length > 0 && lines[lines.length - 1]?.trim() === '') lines.pop();\n if (expanded || lines.length <= COLLAPSED_TAIL_LINES) return lines;\n return lines.slice(-COLLAPSED_TAIL_LINES);\n}\n\n/** Concatenated text of a tool result, which is all a thrown failure leaves behind. */\nfunction contentText(result: { content?: Array<{ type: string; text?: string }> }): string {\n return (result.content ?? []).map((block) => block.text ?? '').join('');\n}\n\n/** Last `max` lines, so a chatty command cannot push the transcript off screen. */\nfunction lastLines(text: string, max: number): string[] {\n const all = text.split('\\n');\n while (all.length > 0 && all[all.length - 1]?.trim() === '') all.pop();\n return all.length <= max ? all : all.slice(-max);\n}\n\nexport function renderBashResult(\n result: { content?: Array<{ type: string; text?: string }>; details?: unknown; isError?: boolean },\n options: { expanded: boolean; isPartial: boolean },\n theme: Theme,\n): Text {\n const details = (result.details ?? {}) as BashResultDetails;\n\n // Running. Details do not exist yet, so the streamed text is the only source,\n // and it is bounded here because it grows without limit while the command runs.\n if (options.isPartial) {\n const streamed = lastLines(contentText(result), STREAM_TAIL_LINES);\n const label = theme.fg('warning', '◐') + theme.fg('dim', ' running');\n return new Text([...streamed.map((line) => paint(line, 'toolOutput', theme)), label].join('\\n'), 0, 0);\n }\n\n // Failed. formatRunResult throws on a bad exit, so Pi hands back the error\n // text with no details at all; without this the block would render a bare tick.\n if (result.isError === true) {\n const body = lastLines(contentText(result), options.expanded ? Number.MAX_SAFE_INTEGER : COLLAPSED_TAIL_LINES);\n const summary = formatResultSummary(details);\n const meta = summary.length > 0 ? ` ${summary}` : '';\n return new Text(\n [...body.map((line) => paint(line, 'toolOutput', theme)), theme.fg('error', '✗') + theme.fg('dim', meta)].join(\n '\\n',\n ),\n 0,\n 0,\n );\n }\n\n if (details.promoted === true) {\n const label = details.runner ?? details.id ?? 'runner';\n const suffix = details.id === undefined ? '' : ` · ${details.id}`;\n return new Text(theme.fg('accent', `● ${label}`) + theme.fg('muted', `${suffix} · background`), 0, 0);\n }\n\n const body = tailLines(details, options.expanded);\n // An absent exit code means the runner never reported one, which is not a failure.\n const exited = details.exitCode !== undefined && details.exitCode !== null;\n const failed = details.timedOut === true || (exited && details.exitCode !== 0);\n const glyph = failed ? theme.fg('error', '✗') : theme.fg('success', '✓');\n\n const meta: string[] = [];\n if (details.timedOut === true) meta.push('timed out');\n else if (failed) meta.push(`exit ${details.exitCode}`);\n const summary = formatResultSummary(details);\n if (summary.length > 0) meta.push(summary);\n if (!options.expanded && (details.tailLines ?? 0) > body.length) meta.push('ctrl+o');\n\n const lines = body.map((line) => paint(line, 'toolOutput', theme));\n // `dim`, not `muted`: muted sits too close to toolOutput to read as chrome.\n lines.push(glyph + theme.fg('dim', meta.length > 0 ? ` ${meta.join(' · ')}` : ''));\n return new Text(lines.join('\\n'), 0, 0);\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../tool/responseEnvelope.cjs"),t=`Runners`;function n(e){return e>0?`Runners ${e} ●`:void 0}function r(e){return e>0?{fullText:`Runner ${e}`,compactText:`R${e}`}:void 0}function i(t,n){let r=t.interactive?` · tty`:``;return`${t.name} · ${e.formatUptime(t.startedAt,n)}${r} · ${t.command}`}function a(t,n){return t.map(t=>({name:t.name,detail:`pid ${t.pid} · up ${e.formatUptime(t.startedAt,n)} · ${t.command}`,interactive:t.interactive}))}function o(e){return`${t} (${e})`}exports.OVERLAY_HEADING=t,exports.WIDGET_KEY=`doom-runners`,exports.formatRunnerFooterContribution=r,exports.formatRunnerStatus=n,exports.formatWidgetHeading=o,exports.formatWidgetLine=i,exports.toRunnerRows=a;
2
+ //# sourceMappingURL=format.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.cjs","names":["formatUptime"],"sources":["../../src/tui/format.ts"],"sourcesContent":["import type { RunnerRecord } from '../services/RunnerRegistry/index.ts';\nimport { formatUptime } from '../tool/responseEnvelope.ts';\n\nexport const WIDGET_KEY = 'doom-runners';\nexport const OVERLAY_HEADING = 'Runners';\n\n/** Compact footer text. An absent value removes the group entirely. */\nexport function formatRunnerStatus(count: number): string | undefined {\n return count > 0 ? `Runners ${count} ●` : undefined;\n}\n\nexport function formatRunnerFooterContribution(count: number): { fullText: string; compactText: string } | undefined {\n return count > 0 ? { fullText: `Runner ${count}`, compactText: `R${count}` } : undefined;\n}\n\n/** `api · 3m · nx dev-start api` — the widget's per-runner line. */\nexport function formatWidgetLine(record: RunnerRecord, now: number): string {\n const mode = record.interactive ? ' · tty' : '';\n return `${record.name} · ${formatUptime(record.startedAt, now)}${mode} · ${record.command}`;\n}\n\nexport interface RunnerRow {\n name: string;\n detail: string;\n interactive: boolean;\n}\n\n/** Rows for the Runner Space list, as plain values so they can be asserted as text. */\nexport function toRunnerRows(records: readonly RunnerRecord[], now: number): RunnerRow[] {\n return records.map((record) => ({\n name: record.name,\n detail: `pid ${record.pid} · up ${formatUptime(record.startedAt, now)} · ${record.command}`,\n interactive: record.interactive,\n }));\n}\n\n/** Heading text for the widget, hidden entirely when there is nothing running. */\nexport function formatWidgetHeading(count: number): string {\n return `${OVERLAY_HEADING} (${count})`;\n}\n"],"mappings":"mHAIa,EAAkB,UAG/B,SAAgB,EAAmB,EAAmC,CACpE,OAAO,EAAQ,EAAI,WAAW,EAAM,IAAM,IAAA,EAC5C,CAEA,SAAgB,EAA+B,EAAsE,CACnH,OAAO,EAAQ,EAAI,CAAE,SAAU,UAAU,IAAS,YAAa,IAAI,GAAQ,EAAI,IAAA,EACjF,CAGA,SAAgB,EAAiB,EAAsB,EAAqB,CAC1E,IAAM,EAAO,EAAO,YAAc,SAAW,GAC7C,MAAO,GAAG,EAAO,KAAK,KAAKA,EAAAA,aAAa,EAAO,UAAW,CAAG,IAAI,EAAK,KAAK,EAAO,SACpF,CASA,SAAgB,EAAa,EAAkC,EAA0B,CACvF,OAAO,EAAQ,IAAK,IAAY,CAC9B,KAAM,EAAO,KACb,OAAQ,OAAO,EAAO,IAAI,QAAQA,EAAAA,aAAa,EAAO,UAAW,CAAG,EAAE,KAAK,EAAO,UAClF,YAAa,EAAO,WACtB,EAAE,CACJ,CAGA,SAAgB,EAAoB,EAAuB,CACzD,MAAO,GAAG,EAAgB,IAAI,EAAM,EACtC"}
@@ -0,0 +1,25 @@
1
+ import { RunnerRecord } from "../services/RunnerRegistry/types.cjs";
2
+ import "../services/RunnerRegistry/index.cjs";
3
+ //#region src/tui/format.d.ts
4
+ declare const WIDGET_KEY = "doom-runners";
5
+ declare const OVERLAY_HEADING = "Runners";
6
+ /** Compact footer text. An absent value removes the group entirely. */
7
+ declare function formatRunnerStatus(count: number): string | undefined;
8
+ declare function formatRunnerFooterContribution(count: number): {
9
+ fullText: string;
10
+ compactText: string;
11
+ } | undefined;
12
+ /** `api · 3m · nx dev-start api` — the widget's per-runner line. */
13
+ declare function formatWidgetLine(record: RunnerRecord, now: number): string;
14
+ interface RunnerRow {
15
+ name: string;
16
+ detail: string;
17
+ interactive: boolean;
18
+ }
19
+ /** Rows for the Runner Space list, as plain values so they can be asserted as text. */
20
+ declare function toRunnerRows(records: readonly RunnerRecord[], now: number): RunnerRow[];
21
+ /** Heading text for the widget, hidden entirely when there is nothing running. */
22
+ declare function formatWidgetHeading(count: number): string;
23
+ //#endregion
24
+ export { OVERLAY_HEADING, RunnerRow, WIDGET_KEY, formatRunnerFooterContribution, formatRunnerStatus, formatWidgetHeading, formatWidgetLine, toRunnerRows };
25
+ //# sourceMappingURL=format.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.cts","names":[],"sources":["../../src/tui/format.ts"],"mappings":";;;cAGa;cACA;;iBAGG,mBAAmB;iBAInB,+BAA+B;EAAkB;EAAkB;;;iBAKnE,iBAAiB,QAAQ,cAAc;UAKtC;EACf;EACA;EACA;;;iBAIc,aAAa,kBAAkB,gBAAgB,cAAc;;iBAS7D,oBAAoB"}