@averyyy/pi-agent-core 0.84.4-piclient.2 → 0.85.1-piclient.2

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 (343) hide show
  1. package/README.md +4 -0
  2. package/dist/agent-loop.d.ts.map +1 -1
  3. package/dist/agent-loop.js +9 -0
  4. package/dist/agent-loop.js.map +1 -1
  5. package/dist/harness/agent-harness.d.ts +639 -384
  6. package/dist/harness/agent-harness.d.ts.map +1 -1
  7. package/dist/harness/agent-harness.js +5 -251
  8. package/dist/harness/agent-harness.js.map +1 -1
  9. package/dist/harness/compaction/branch-summarization.d.ts +12 -6
  10. package/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
  11. package/dist/harness/compaction/branch-summarization.js +33 -26
  12. package/dist/harness/compaction/branch-summarization.js.map +1 -1
  13. package/dist/harness/compaction/compaction.d.ts +30 -8
  14. package/dist/harness/compaction/compaction.d.ts.map +1 -1
  15. package/dist/harness/compaction/compaction.js +73 -79
  16. package/dist/harness/compaction/compaction.js.map +1 -1
  17. package/dist/harness/config.d.ts +9 -0
  18. package/dist/harness/config.d.ts.map +1 -0
  19. package/dist/harness/config.js +27 -0
  20. package/dist/harness/config.js.map +1 -0
  21. package/dist/harness/context.d.ts +9 -0
  22. package/dist/harness/context.d.ts.map +1 -0
  23. package/dist/harness/context.js +13 -0
  24. package/dist/harness/context.js.map +1 -0
  25. package/dist/harness/env/nodejs.d.ts +24 -28
  26. package/dist/harness/env/nodejs.d.ts.map +1 -1
  27. package/dist/harness/env/nodejs.js +239 -86
  28. package/dist/harness/env/nodejs.js.map +1 -1
  29. package/dist/harness/events.d.ts +20 -38
  30. package/dist/harness/events.d.ts.map +1 -1
  31. package/dist/harness/events.js +240 -55
  32. package/dist/harness/events.js.map +1 -1
  33. package/dist/harness/execution/assistant.d.ts +42 -0
  34. package/dist/harness/execution/assistant.d.ts.map +1 -0
  35. package/dist/harness/execution/assistant.js +82 -0
  36. package/dist/harness/execution/assistant.js.map +1 -0
  37. package/dist/harness/execution/effect-gate.d.ts +22 -0
  38. package/dist/harness/execution/effect-gate.d.ts.map +1 -0
  39. package/dist/harness/execution/effect-gate.js +49 -0
  40. package/dist/harness/execution/effect-gate.js.map +1 -0
  41. package/dist/harness/execution/tools.d.ts +67 -0
  42. package/dist/harness/execution/tools.d.ts.map +1 -0
  43. package/dist/harness/execution/tools.js +121 -0
  44. package/dist/harness/execution/tools.js.map +1 -0
  45. package/dist/harness/hooks.d.ts +38 -0
  46. package/dist/harness/hooks.d.ts.map +1 -0
  47. package/dist/harness/hooks.js +406 -0
  48. package/dist/harness/hooks.js.map +1 -0
  49. package/dist/harness/messages.d.ts +2 -2
  50. package/dist/harness/messages.d.ts.map +1 -1
  51. package/dist/harness/messages.js.map +1 -1
  52. package/dist/harness/prompt-templates.d.ts +3 -2
  53. package/dist/harness/prompt-templates.d.ts.map +1 -1
  54. package/dist/harness/prompt-templates.js +17 -17
  55. package/dist/harness/prompt-templates.js.map +1 -1
  56. package/dist/harness/result.d.ts +93 -0
  57. package/dist/harness/result.d.ts.map +1 -1
  58. package/dist/harness/result.js +40 -0
  59. package/dist/harness/result.js.map +1 -1
  60. package/dist/harness/runtime/drive/boundary.d.ts +28 -0
  61. package/dist/harness/runtime/drive/boundary.d.ts.map +1 -0
  62. package/dist/harness/runtime/drive/boundary.js +170 -0
  63. package/dist/harness/runtime/drive/boundary.js.map +1 -0
  64. package/dist/harness/runtime/drive/checkpoint.d.ts +8 -0
  65. package/dist/harness/runtime/drive/checkpoint.d.ts.map +1 -0
  66. package/dist/harness/runtime/drive/checkpoint.js +133 -0
  67. package/dist/harness/runtime/drive/checkpoint.js.map +1 -0
  68. package/dist/harness/runtime/drive/deferred.d.ts +15 -0
  69. package/dist/harness/runtime/drive/deferred.d.ts.map +1 -0
  70. package/dist/harness/runtime/drive/deferred.js +179 -0
  71. package/dist/harness/runtime/drive/deferred.js.map +1 -0
  72. package/dist/harness/runtime/drive/generation.d.ts +8 -0
  73. package/dist/harness/runtime/drive/generation.d.ts.map +1 -0
  74. package/dist/harness/runtime/drive/generation.js +205 -0
  75. package/dist/harness/runtime/drive/generation.js.map +1 -0
  76. package/dist/harness/runtime/drive/reconcile.d.ts +5 -0
  77. package/dist/harness/runtime/drive/reconcile.d.ts.map +1 -0
  78. package/dist/harness/runtime/drive/reconcile.js +140 -0
  79. package/dist/harness/runtime/drive/reconcile.js.map +1 -0
  80. package/dist/harness/runtime/drive/recovery.d.ts +8 -0
  81. package/dist/harness/runtime/drive/recovery.d.ts.map +1 -0
  82. package/dist/harness/runtime/drive/recovery.js +85 -0
  83. package/dist/harness/runtime/drive/recovery.js.map +1 -0
  84. package/dist/harness/runtime/drive/response.d.ts +23 -0
  85. package/dist/harness/runtime/drive/response.d.ts.map +1 -0
  86. package/dist/harness/runtime/drive/response.js +394 -0
  87. package/dist/harness/runtime/drive/response.js.map +1 -0
  88. package/dist/harness/runtime/drive/retry.d.ts +4 -0
  89. package/dist/harness/runtime/drive/retry.d.ts.map +1 -0
  90. package/dist/harness/runtime/drive/retry.js +37 -0
  91. package/dist/harness/runtime/drive/retry.js.map +1 -0
  92. package/dist/harness/runtime/drive/structural.d.ts +32 -0
  93. package/dist/harness/runtime/drive/structural.d.ts.map +1 -0
  94. package/dist/harness/runtime/drive/structural.js +929 -0
  95. package/dist/harness/runtime/drive/structural.js.map +1 -0
  96. package/dist/harness/runtime/drive/terminal.d.ts +7 -0
  97. package/dist/harness/runtime/drive/terminal.d.ts.map +1 -0
  98. package/dist/harness/runtime/drive/terminal.js +49 -0
  99. package/dist/harness/runtime/drive/terminal.js.map +1 -0
  100. package/dist/harness/runtime/drive/tool-placement.d.ts +14 -0
  101. package/dist/harness/runtime/drive/tool-placement.d.ts.map +1 -0
  102. package/dist/harness/runtime/drive/tool-placement.js +244 -0
  103. package/dist/harness/runtime/drive/tool-placement.js.map +1 -0
  104. package/dist/harness/runtime/drive/tools.d.ts +6 -0
  105. package/dist/harness/runtime/drive/tools.d.ts.map +1 -0
  106. package/dist/harness/runtime/drive/tools.js +449 -0
  107. package/dist/harness/runtime/drive/tools.js.map +1 -0
  108. package/dist/harness/runtime/drive.d.ts +6 -0
  109. package/dist/harness/runtime/drive.d.ts.map +1 -0
  110. package/dist/harness/runtime/drive.js +93 -0
  111. package/dist/harness/runtime/drive.js.map +1 -0
  112. package/dist/harness/runtime/harness.d.ts +59 -0
  113. package/dist/harness/runtime/harness.d.ts.map +1 -0
  114. package/dist/harness/runtime/harness.js +311 -0
  115. package/dist/harness/runtime/harness.js.map +1 -0
  116. package/dist/harness/runtime/index.d.ts +2 -0
  117. package/dist/harness/runtime/index.d.ts.map +1 -0
  118. package/dist/harness/runtime/index.js +2 -0
  119. package/dist/harness/runtime/index.js.map +1 -0
  120. package/dist/harness/runtime/lane.d.ts +101 -0
  121. package/dist/harness/runtime/lane.d.ts.map +1 -0
  122. package/dist/harness/runtime/lane.js +1575 -0
  123. package/dist/harness/runtime/lane.js.map +1 -0
  124. package/dist/harness/runtime/progress.d.ts +15 -0
  125. package/dist/harness/runtime/progress.d.ts.map +1 -0
  126. package/dist/harness/runtime/progress.js +66 -0
  127. package/dist/harness/runtime/progress.js.map +1 -0
  128. package/dist/harness/runtime/reducer.d.ts +5 -0
  129. package/dist/harness/runtime/reducer.d.ts.map +1 -0
  130. package/dist/harness/runtime/reducer.js +240 -0
  131. package/dist/harness/runtime/reducer.js.map +1 -0
  132. package/dist/harness/runtime/restore.d.ts +24 -0
  133. package/dist/harness/runtime/restore.d.ts.map +1 -0
  134. package/dist/harness/runtime/restore.js +117 -0
  135. package/dist/harness/runtime/restore.js.map +1 -0
  136. package/dist/harness/runtime/transcript.d.ts +21 -0
  137. package/dist/harness/runtime/transcript.d.ts.map +1 -0
  138. package/dist/harness/runtime/transcript.js +72 -0
  139. package/dist/harness/runtime/transcript.js.map +1 -0
  140. package/dist/harness/runtime/types.d.ts +105 -0
  141. package/dist/harness/runtime/types.d.ts.map +1 -0
  142. package/dist/harness/runtime/types.js +61 -0
  143. package/dist/harness/runtime/types.js.map +1 -0
  144. package/dist/harness/session/commit.d.ts +53 -0
  145. package/dist/harness/session/commit.d.ts.map +1 -0
  146. package/dist/harness/session/commit.js +57 -0
  147. package/dist/harness/session/commit.js.map +1 -0
  148. package/dist/harness/session/context.d.ts +6 -18
  149. package/dist/harness/session/context.d.ts.map +1 -1
  150. package/dist/harness/session/context.js +31 -49
  151. package/dist/harness/session/context.js.map +1 -1
  152. package/dist/harness/session/fork-policy.d.ts +13 -0
  153. package/dist/harness/session/fork-policy.d.ts.map +1 -0
  154. package/dist/harness/session/fork-policy.js +22 -0
  155. package/dist/harness/session/fork-policy.js.map +1 -0
  156. package/dist/harness/session/fork.d.ts +18 -0
  157. package/dist/harness/session/fork.d.ts.map +1 -0
  158. package/dist/harness/session/fork.js +127 -0
  159. package/dist/harness/session/fork.js.map +1 -0
  160. package/dist/harness/session/in-memory-storage-state.d.ts +39 -0
  161. package/dist/harness/session/in-memory-storage-state.d.ts.map +1 -0
  162. package/dist/harness/session/in-memory-storage-state.js +216 -0
  163. package/dist/harness/session/in-memory-storage-state.js.map +1 -0
  164. package/dist/harness/session/index.d.ts +9 -5
  165. package/dist/harness/session/index.d.ts.map +1 -1
  166. package/dist/harness/session/index.js +7 -4
  167. package/dist/harness/session/index.js.map +1 -1
  168. package/dist/harness/session/jsonl/codec.d.ts +19 -8
  169. package/dist/harness/session/jsonl/codec.d.ts.map +1 -1
  170. package/dist/harness/session/jsonl/codec.js +34 -218
  171. package/dist/harness/session/jsonl/codec.js.map +1 -1
  172. package/dist/harness/session/jsonl/index.d.ts +4 -0
  173. package/dist/harness/session/jsonl/index.d.ts.map +1 -0
  174. package/dist/harness/session/jsonl/index.js +4 -0
  175. package/dist/harness/session/jsonl/index.js.map +1 -0
  176. package/dist/harness/session/jsonl/legacy-v3.d.ts +18 -0
  177. package/dist/harness/session/jsonl/legacy-v3.d.ts.map +1 -0
  178. package/dist/harness/session/jsonl/legacy-v3.js +383 -0
  179. package/dist/harness/session/jsonl/legacy-v3.js.map +1 -0
  180. package/dist/harness/session/jsonl/repo.d.ts +26 -19
  181. package/dist/harness/session/jsonl/repo.d.ts.map +1 -1
  182. package/dist/harness/session/jsonl/repo.js +266 -156
  183. package/dist/harness/session/jsonl/repo.js.map +1 -1
  184. package/dist/harness/session/jsonl/storage.d.ts +39 -41
  185. package/dist/harness/session/jsonl/storage.d.ts.map +1 -1
  186. package/dist/harness/session/jsonl/storage.js +238 -181
  187. package/dist/harness/session/jsonl/storage.js.map +1 -1
  188. package/dist/harness/session/jsonl/types.d.ts +23 -22
  189. package/dist/harness/session/jsonl/types.d.ts.map +1 -1
  190. package/dist/harness/session/jsonl/types.js +2 -1
  191. package/dist/harness/session/jsonl/types.js.map +1 -1
  192. package/dist/harness/session/memory.d.ts +46 -40
  193. package/dist/harness/session/memory.d.ts.map +1 -1
  194. package/dist/harness/session/memory.js +346 -113
  195. package/dist/harness/session/memory.js.map +1 -1
  196. package/dist/harness/session/mutation-line.d.ts +8 -0
  197. package/dist/harness/session/mutation-line.d.ts.map +1 -0
  198. package/dist/harness/session/mutation-line.js +21 -0
  199. package/dist/harness/session/mutation-line.js.map +1 -0
  200. package/dist/harness/session/session.d.ts +78 -46
  201. package/dist/harness/session/session.d.ts.map +1 -1
  202. package/dist/harness/session/session.js +343 -209
  203. package/dist/harness/session/session.js.map +1 -1
  204. package/dist/harness/session/testing/benchmark/datasets.d.ts +12 -0
  205. package/dist/harness/session/testing/benchmark/datasets.d.ts.map +1 -0
  206. package/dist/harness/session/testing/benchmark/datasets.js +24 -0
  207. package/dist/harness/session/testing/benchmark/datasets.js.map +1 -0
  208. package/dist/harness/session/testing/benchmark/session-repo.d.ts +42 -0
  209. package/dist/harness/session/testing/benchmark/session-repo.d.ts.map +1 -0
  210. package/dist/harness/session/testing/benchmark/session-repo.js +127 -0
  211. package/dist/harness/session/testing/benchmark/session-repo.js.map +1 -0
  212. package/dist/harness/session/testing/benchmark/storage.d.ts +25 -0
  213. package/dist/harness/session/testing/benchmark/storage.d.ts.map +1 -0
  214. package/dist/harness/session/testing/benchmark/storage.js +114 -0
  215. package/dist/harness/session/testing/benchmark/storage.js.map +1 -0
  216. package/dist/harness/session/testing/conformance/session-repo.d.ts +21 -0
  217. package/dist/harness/session/testing/conformance/session-repo.d.ts.map +1 -0
  218. package/dist/harness/session/testing/conformance/session-repo.js +590 -0
  219. package/dist/harness/session/testing/conformance/session-repo.js.map +1 -0
  220. package/dist/harness/session/testing/conformance/storage.d.ts +4 -0
  221. package/dist/harness/session/testing/conformance/storage.d.ts.map +1 -0
  222. package/dist/harness/session/testing/conformance/storage.js +600 -0
  223. package/dist/harness/session/testing/conformance/storage.js.map +1 -0
  224. package/dist/harness/session/testing/gating-storage.d.ts +26 -0
  225. package/dist/harness/session/testing/gating-storage.d.ts.map +1 -0
  226. package/dist/harness/session/testing/gating-storage.js +100 -0
  227. package/dist/harness/session/testing/gating-storage.js.map +1 -0
  228. package/dist/harness/session/testing/index.d.ts +9 -2
  229. package/dist/harness/session/testing/index.d.ts.map +1 -1
  230. package/dist/harness/session/testing/index.js +8 -1
  231. package/dist/harness/session/testing/index.js.map +1 -1
  232. package/dist/harness/session/testing/instrumented-storage.d.ts +11 -0
  233. package/dist/harness/session/testing/instrumented-storage.d.ts.map +1 -0
  234. package/dist/harness/session/testing/instrumented-storage.js +16 -0
  235. package/dist/harness/session/testing/instrumented-storage.js.map +1 -0
  236. package/dist/harness/session/testing/storage-decorator.d.ts +20 -0
  237. package/dist/harness/session/testing/storage-decorator.d.ts.map +1 -0
  238. package/dist/harness/session/testing/storage-decorator.js +41 -0
  239. package/dist/harness/session/testing/storage-decorator.js.map +1 -0
  240. package/dist/harness/session/testing/types.d.ts +5 -7
  241. package/dist/harness/session/testing/types.d.ts.map +1 -1
  242. package/dist/harness/session/testing/types.js.map +1 -1
  243. package/dist/harness/session/types.d.ts +424 -259
  244. package/dist/harness/session/types.d.ts.map +1 -1
  245. package/dist/harness/session/types.js +7 -8
  246. package/dist/harness/session/types.js.map +1 -1
  247. package/dist/harness/session/values.d.ts +95 -0
  248. package/dist/harness/session/values.d.ts.map +1 -0
  249. package/dist/harness/session/values.js +81 -0
  250. package/dist/harness/session/values.js.map +1 -0
  251. package/dist/harness/skills.d.ts +3 -2
  252. package/dist/harness/skills.d.ts.map +1 -1
  253. package/dist/harness/skills.js +29 -26
  254. package/dist/harness/skills.js.map +1 -1
  255. package/dist/harness/telemetry.d.ts +64 -43
  256. package/dist/harness/telemetry.d.ts.map +1 -1
  257. package/dist/harness/telemetry.js +45 -26
  258. package/dist/harness/telemetry.js.map +1 -1
  259. package/dist/harness/tools/bash.d.ts +4 -4
  260. package/dist/harness/tools/bash.d.ts.map +1 -1
  261. package/dist/harness/tools/bash.js +66 -93
  262. package/dist/harness/tools/bash.js.map +1 -1
  263. package/dist/harness/tools/edit.d.ts.map +1 -1
  264. package/dist/harness/tools/edit.js +10 -10
  265. package/dist/harness/tools/edit.js.map +1 -1
  266. package/dist/harness/tools/file-mutation-queue.d.ts +2 -1
  267. package/dist/harness/tools/file-mutation-queue.d.ts.map +1 -1
  268. package/dist/harness/tools/file-mutation-queue.js +5 -5
  269. package/dist/harness/tools/file-mutation-queue.js.map +1 -1
  270. package/dist/harness/tools/path-utils.d.ts +3 -2
  271. package/dist/harness/tools/path-utils.d.ts.map +1 -1
  272. package/dist/harness/tools/path-utils.js +5 -5
  273. package/dist/harness/tools/path-utils.js.map +1 -1
  274. package/dist/harness/tools/read.d.ts +2 -1
  275. package/dist/harness/tools/read.d.ts.map +1 -1
  276. package/dist/harness/tools/read.js +4 -6
  277. package/dist/harness/tools/read.js.map +1 -1
  278. package/dist/harness/tools/write.d.ts.map +1 -1
  279. package/dist/harness/tools/write.js +7 -7
  280. package/dist/harness/tools/write.js.map +1 -1
  281. package/dist/harness/types.d.ts +108 -45
  282. package/dist/harness/types.d.ts.map +1 -1
  283. package/dist/harness/types.js.map +1 -1
  284. package/dist/harness/utils/adaptive-publisher.d.ts +24 -0
  285. package/dist/harness/utils/adaptive-publisher.d.ts.map +1 -0
  286. package/dist/harness/utils/adaptive-publisher.js +79 -0
  287. package/dist/harness/utils/adaptive-publisher.js.map +1 -0
  288. package/dist/harness/utils/output-capture.d.ts +31 -0
  289. package/dist/harness/utils/output-capture.d.ts.map +1 -0
  290. package/dist/harness/utils/output-capture.js +217 -0
  291. package/dist/harness/utils/output-capture.js.map +1 -0
  292. package/dist/harness/utils/shell-output.d.ts +12 -5
  293. package/dist/harness/utils/shell-output.d.ts.map +1 -1
  294. package/dist/harness/utils/shell-output.js +64 -174
  295. package/dist/harness/utils/shell-output.js.map +1 -1
  296. package/dist/harness/utils/truncate.d.ts +1 -0
  297. package/dist/harness/utils/truncate.d.ts.map +1 -1
  298. package/dist/harness/utils/truncate.js +1 -1
  299. package/dist/harness/utils/truncate.js.map +1 -1
  300. package/dist/harness/utils/usage.d.ts +4 -0
  301. package/dist/harness/utils/usage.d.ts.map +1 -0
  302. package/dist/harness/utils/usage.js +33 -0
  303. package/dist/harness/utils/usage.js.map +1 -0
  304. package/dist/index.d.ts +4 -1
  305. package/dist/index.d.ts.map +1 -1
  306. package/dist/index.js +3 -6
  307. package/dist/index.js.map +1 -1
  308. package/dist/proxy.d.ts +2 -0
  309. package/dist/proxy.d.ts.map +1 -1
  310. package/dist/proxy.js +40 -10
  311. package/dist/proxy.js.map +1 -1
  312. package/dist/search/index.d.ts +24 -16
  313. package/dist/search/index.d.ts.map +1 -1
  314. package/dist/search/index.js +1 -1
  315. package/dist/search/index.js.map +1 -1
  316. package/dist/types.d.ts +2 -0
  317. package/dist/types.d.ts.map +1 -1
  318. package/dist/types.js.map +1 -1
  319. package/package.json +25 -4
  320. package/dist/harness/reducer.d.ts +0 -100
  321. package/dist/harness/reducer.d.ts.map +0 -1
  322. package/dist/harness/reducer.js +0 -415
  323. package/dist/harness/reducer.js.map +0 -1
  324. package/dist/harness/session/jsonl/errors.d.ts +0 -9
  325. package/dist/harness/session/jsonl/errors.d.ts.map +0 -1
  326. package/dist/harness/session/jsonl/errors.js +0 -19
  327. package/dist/harness/session/jsonl/errors.js.map +0 -1
  328. package/dist/harness/session/jsonl.d.ts +0 -3
  329. package/dist/harness/session/jsonl.d.ts.map +0 -1
  330. package/dist/harness/session/jsonl.js +0 -2
  331. package/dist/harness/session/jsonl.js.map +0 -1
  332. package/dist/harness/session/state.d.ts +0 -65
  333. package/dist/harness/session/state.d.ts.map +0 -1
  334. package/dist/harness/session/state.js +0 -319
  335. package/dist/harness/session/state.js.map +0 -1
  336. package/dist/harness/session/testing/conformance.d.ts +0 -4
  337. package/dist/harness/session/testing/conformance.d.ts.map +0 -1
  338. package/dist/harness/session/testing/conformance.js +0 -762
  339. package/dist/harness/session/testing/conformance.js.map +0 -1
  340. package/dist/search/scanning.d.ts +0 -29
  341. package/dist/search/scanning.d.ts.map +0 -1
  342. package/dist/search/scanning.js +0 -103
  343. package/dist/search/scanning.js.map +0 -1
@@ -1,15 +1,17 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { randomUUID } from "node:crypto";
3
- import { constants, createReadStream } from "node:fs";
3
+ import { constants, createReadStream, createWriteStream } from "node:fs";
4
4
  import { access, appendFile, lstat, mkdir, mkdtemp, readdir, readFile, realpath, rename, rm, writeFile, } from "node:fs/promises";
5
- import { homedir, tmpdir } from "node:os";
5
+ import { homedir, constants as osConstants, tmpdir } from "node:os";
6
6
  import { isAbsolute, join, resolve } from "node:path";
7
7
  import { createInterface } from "node:readline";
8
8
  import { fileURLToPath } from "node:url";
9
9
  import { ExecutionError, err, FileError, ok, toError, } from "../types.js";
10
+ import { OutputCapture } from "../utils/output-capture.js";
10
11
  const MAX_TIMEOUT_MS = 2_147_483_647;
11
12
  const MAX_TIMEOUT_SECONDS = MAX_TIMEOUT_MS / 1000;
12
13
  const EXIT_STDIO_GRACE_MS = 100;
14
+ const SPILL_HIGH_WATER_MARK = 8 * 1024 * 1024;
13
15
  function resolveTimeoutMs(timeout) {
14
16
  if (timeout === undefined)
15
17
  return ok(undefined);
@@ -229,11 +231,12 @@ function killProcessTree(pid) {
229
231
  }
230
232
  }
231
233
  }
232
- function waitForChildProcess(child) {
234
+ function waitForChildProcess(child, spillIsDraining) {
233
235
  return new Promise((resolvePromise, reject) => {
234
236
  let settled = false;
235
237
  let exited = false;
236
238
  let exitCode = null;
239
+ let exitSignal = null;
237
240
  let postExitTimer;
238
241
  let stdoutEnded = child.stdout === null;
239
242
  let stderrEnded = child.stderr === null;
@@ -248,23 +251,28 @@ function waitForChildProcess(child) {
248
251
  child.stdout?.removeListener("data", onData);
249
252
  child.stderr?.removeListener("data", onData);
250
253
  };
251
- const finalize = (code) => {
254
+ const finalize = () => {
252
255
  if (settled)
253
256
  return;
254
257
  settled = true;
255
258
  cleanup();
256
259
  child.stdout?.destroy();
257
260
  child.stderr?.destroy();
258
- resolvePromise(code);
261
+ resolvePromise({ code: exitCode, signal: exitSignal });
259
262
  };
260
263
  const maybeFinalizeAfterExit = () => {
261
264
  if (exited && stdoutEnded && stderrEnded)
262
- finalize(exitCode);
265
+ finalize();
263
266
  };
264
267
  const armIdleTimer = () => {
265
268
  if (postExitTimer)
266
269
  clearTimeout(postExitTimer);
267
- postExitTimer = setTimeout(() => finalize(exitCode), EXIT_STDIO_GRACE_MS);
270
+ postExitTimer = setTimeout(() => {
271
+ if (spillIsDraining())
272
+ armIdleTimer();
273
+ else
274
+ finalize();
275
+ }, EXIT_STDIO_GRACE_MS);
268
276
  };
269
277
  const onData = () => {
270
278
  if (exited && !settled)
@@ -285,14 +293,19 @@ function waitForChildProcess(child) {
285
293
  cleanup();
286
294
  reject(error);
287
295
  };
288
- const onExit = (code) => {
296
+ const onExit = (code, signal) => {
289
297
  exited = true;
290
298
  exitCode = code;
299
+ exitSignal = signal;
291
300
  maybeFinalizeAfterExit();
292
301
  if (!settled)
293
302
  armIdleTimer();
294
303
  };
295
- const onClose = (code) => finalize(code);
304
+ const onClose = (code, signal) => {
305
+ exitCode = code;
306
+ exitSignal = signal;
307
+ finalize();
308
+ };
296
309
  child.stdout?.once("end", onStdoutEnd);
297
310
  child.stderr?.once("end", onStderrEnd);
298
311
  child.stdout?.on("data", onData);
@@ -312,14 +325,15 @@ export class NodeExecutionEnv {
312
325
  this.shellPath = options.shellPath;
313
326
  this.shellEnv = options.shellEnv;
314
327
  }
315
- async absolutePath(path) {
328
+ async absolutePath(path, _context) {
316
329
  return ok(resolvePath(this.cwd, path));
317
330
  }
318
- async joinPath(parts) {
331
+ async joinPath(parts, _context) {
319
332
  return ok(join(...parts));
320
333
  }
321
- async exec(command, options) {
322
- if (options?.abortSignal?.aborted)
334
+ async exec(command, options, context) {
335
+ const signal = context.abortSignal;
336
+ if (signal?.aborted)
323
337
  return err(new ExecutionError("aborted", "aborted"));
324
338
  const timeoutMsResult = resolveTimeoutMs(options?.timeout);
325
339
  if (!timeoutMsResult.ok)
@@ -337,30 +351,119 @@ export class NodeExecutionEnv {
337
351
  return err(new ExecutionError("spawn_error", `Working directory does not exist: ${cwd}\nCannot execute bash commands.`, cause));
338
352
  }
339
353
  return await new Promise((resolvePromise) => {
340
- let stdout = "";
341
- let stderr = "";
342
354
  let settled = false;
343
355
  let timedOut = false;
344
356
  let callbackError;
357
+ let spillError;
345
358
  let child;
346
359
  let timeoutId;
360
+ const spillPrefix = [];
361
+ let spillPath;
362
+ const spillQueue = [];
363
+ let spillStart;
364
+ let spillStream;
365
+ let spillBackpressured = false;
347
366
  const onAbort = () => {
348
- if (child?.pid) {
367
+ if (child?.pid)
349
368
  killProcessTree(child.pid);
350
- }
351
369
  };
370
+ const failCallback = (error) => {
371
+ if (callbackError !== undefined)
372
+ return;
373
+ const cause = toError(error);
374
+ callbackError = new ExecutionError("callback_error", cause.message, cause);
375
+ onAbort();
376
+ };
377
+ let capture;
378
+ try {
379
+ capture = new OutputCapture(options?.capture, context, {
380
+ onUpdate: options?.onUpdate,
381
+ onError: failCallback,
382
+ });
383
+ }
384
+ catch (error) {
385
+ const cause = toError(error);
386
+ resolvePromise(err(new ExecutionError("unknown", cause.message, cause)));
387
+ return;
388
+ }
352
389
  const settle = (result) => {
390
+ if (settled)
391
+ return;
392
+ settled = true;
353
393
  if (timeoutId)
354
394
  clearTimeout(timeoutId);
355
- if (options?.abortSignal)
356
- options.abortSignal.removeEventListener("abort", onAbort);
395
+ if (signal)
396
+ signal.removeEventListener("abort", onAbort);
357
397
  if (child?.pid)
358
398
  this.activeChildPids.delete(child.pid);
359
- if (settled)
360
- return;
361
- settled = true;
399
+ capture.dispose();
362
400
  resolvePromise(result);
363
401
  };
402
+ const pauseOutput = () => {
403
+ child?.stdout?.pause();
404
+ child?.stderr?.pause();
405
+ };
406
+ const resumeOutput = () => {
407
+ if (callbackError || spillError || timedOut || signal?.aborted || spillBackpressured)
408
+ return;
409
+ child?.stdout?.resume();
410
+ child?.stderr?.resume();
411
+ };
412
+ const failSpill = (error) => {
413
+ if (spillError !== undefined)
414
+ return;
415
+ const cause = toError(error);
416
+ spillError = new ExecutionError("unknown", `Failed to preserve complete shell output: ${cause.message}`, cause);
417
+ spillBackpressured = false;
418
+ onAbort();
419
+ };
420
+ const writeSpill = (chunk) => {
421
+ if (spillStream === undefined || chunk.length === 0)
422
+ return;
423
+ if (spillStream.write(chunk) || spillBackpressured)
424
+ return;
425
+ spillBackpressured = true;
426
+ pauseOutput();
427
+ spillStream.once("drain", () => {
428
+ spillBackpressured = false;
429
+ resumeOutput();
430
+ });
431
+ };
432
+ const startSpill = (chunk) => {
433
+ if (spillStream !== undefined) {
434
+ writeSpill(chunk);
435
+ return;
436
+ }
437
+ spillQueue.push(chunk);
438
+ if (spillStart !== undefined)
439
+ return;
440
+ pauseOutput();
441
+ spillStart = (async () => {
442
+ const created = await this.createTempFile({ prefix: "pi-output-", suffix: ".log" }, context);
443
+ if (!created.ok)
444
+ throw created.error;
445
+ spillPath = created.value;
446
+ capture.setSpillPath(spillPath);
447
+ spillStream = createWriteStream(spillPath, { flags: "a", highWaterMark: SPILL_HIGH_WATER_MARK });
448
+ spillStream.on("error", failSpill);
449
+ for (const queued of spillQueue)
450
+ writeSpill(queued);
451
+ spillQueue.length = 0;
452
+ })()
453
+ .catch(failSpill)
454
+ .finally(resumeOutput);
455
+ };
456
+ const finishSpill = async () => {
457
+ await spillStart;
458
+ const stream = spillStream;
459
+ if (stream === undefined || spillError !== undefined || stream.destroyed)
460
+ return;
461
+ await new Promise((resolveFinish) => {
462
+ stream.once("error", () => resolveFinish());
463
+ stream.once("finish", resolveFinish);
464
+ stream.end();
465
+ });
466
+ };
364
467
  try {
365
468
  const commandFromStdin = shellConfig.value.commandTransport === "stdin";
366
469
  child = spawn(shellConfig.value.shell, commandFromStdin ? shellConfig.value.args : [...shellConfig.value.args, command], {
@@ -383,47 +486,54 @@ export class NodeExecutionEnv {
383
486
  return;
384
487
  }
385
488
  timeoutId =
386
- timeoutMs !== undefined
387
- ? setTimeout(() => {
489
+ timeoutMs === undefined
490
+ ? undefined
491
+ : setTimeout(() => {
388
492
  timedOut = true;
389
- if (child?.pid) {
390
- killProcessTree(child.pid);
391
- }
392
- }, timeoutMs)
393
- : undefined;
394
- if (options?.abortSignal) {
395
- if (options.abortSignal.aborted) {
493
+ onAbort();
494
+ }, timeoutMs);
495
+ if (signal) {
496
+ if (signal.aborted)
396
497
  onAbort();
397
- }
398
- else {
399
- options.abortSignal.addEventListener("abort", onAbort, { once: true });
400
- }
498
+ else
499
+ signal.addEventListener("abort", onAbort, { once: true });
401
500
  }
402
- child.stdout?.setEncoding("utf8");
403
- child.stderr?.setEncoding("utf8");
404
- child.stdout?.on("data", (chunk) => {
405
- stdout += chunk;
501
+ const feed = (chunk) => {
406
502
  try {
407
- options?.onStdout?.(chunk);
503
+ const wasTruncated = capture.truncated;
504
+ capture.push(chunk);
505
+ if (!options?.capture?.spill || chunk.length === 0)
506
+ return;
507
+ if (spillPath !== undefined || wasTruncated) {
508
+ startSpill(chunk);
509
+ }
510
+ else if (capture.truncated) {
511
+ for (const prefix of spillPrefix)
512
+ startSpill(prefix);
513
+ spillPrefix.length = 0;
514
+ startSpill(chunk);
515
+ }
516
+ else {
517
+ spillPrefix.push(chunk);
518
+ }
408
519
  }
409
520
  catch (error) {
410
- const cause = toError(error);
411
- callbackError = new ExecutionError("callback_error", cause.message, cause);
412
- onAbort();
521
+ failCallback(error);
413
522
  }
414
- });
415
- child.stderr?.on("data", (chunk) => {
416
- stderr += chunk;
523
+ };
524
+ child.stdout?.on("data", feed);
525
+ child.stderr?.on("data", feed);
526
+ void waitForChildProcess(child, () => spillError === undefined &&
527
+ spillStart !== undefined &&
528
+ (spillStream === undefined || spillBackpressured)).then(async ({ code, signal: exitSignal }) => {
529
+ await finishSpill();
417
530
  try {
418
- options?.onStderr?.(chunk);
531
+ capture.finish();
532
+ capture.flush();
419
533
  }
420
534
  catch (error) {
421
- const cause = toError(error);
422
- callbackError = new ExecutionError("callback_error", cause.message, cause);
423
- onAbort();
535
+ failCallback(error);
424
536
  }
425
- });
426
- void waitForChildProcess(child).then((code) => {
427
537
  if (callbackError) {
428
538
  settle(err(callbackError));
429
539
  return;
@@ -432,29 +542,45 @@ export class NodeExecutionEnv {
432
542
  settle(err(new ExecutionError("timeout", `timeout:${options?.timeout}`)));
433
543
  return;
434
544
  }
435
- if (options?.abortSignal?.aborted) {
545
+ if (signal?.aborted) {
436
546
  settle(err(new ExecutionError("aborted", "aborted")));
437
547
  return;
438
548
  }
439
- settle(ok({ stdout, stderr, exitCode: code ?? 0 }));
549
+ if (spillError) {
550
+ settle(err(spillError));
551
+ return;
552
+ }
553
+ const output = capture.snapshot();
554
+ // A process killed by a signal (e.g. OOM killer) has no exit code; map it
555
+ // to the conventional 128 + signal number so callers do not mistake it
556
+ // for a successful exit.
557
+ const exitCode = code ?? (exitSignal ? 128 + (osConstants.signals[exitSignal] ?? 0) : 1);
558
+ settle(ok({
559
+ exitCode,
560
+ truncation: output.truncation,
561
+ ...(output.spillPath === undefined ? {} : { spillPath: output.spillPath }),
562
+ ...(output.lastLineBytes === undefined ? {} : { lastLineBytes: output.lastLineBytes }),
563
+ }));
440
564
  }, (error) => settle(err(new ExecutionError("spawn_error", error.message, error))));
441
565
  });
442
566
  }
443
- async readTextFile(path, abortSignal) {
567
+ async readTextFile(path, context) {
444
568
  const resolved = resolvePath(this.cwd, path);
445
- const aborted = abortResult(abortSignal, resolved);
569
+ const signal = context.abortSignal;
570
+ const aborted = abortResult(signal, resolved);
446
571
  if (aborted)
447
572
  return aborted;
448
573
  try {
449
- return ok(await readFile(resolved, { encoding: "utf8", signal: abortSignal }));
574
+ return ok(await readFile(resolved, { encoding: "utf8", signal }));
450
575
  }
451
576
  catch (error) {
452
577
  return err(toFileError(error, resolved));
453
578
  }
454
579
  }
455
- async readTextLines(path, options) {
580
+ async readTextLines(path, options, context) {
456
581
  const resolved = resolvePath(this.cwd, path);
457
- const aborted = abortResult(options?.abortSignal, resolved);
582
+ const signal = context.abortSignal;
583
+ const aborted = abortResult(signal, resolved);
458
584
  if (aborted)
459
585
  return aborted;
460
586
  if (options?.maxLines !== undefined && options.maxLines <= 0)
@@ -462,18 +588,18 @@ export class NodeExecutionEnv {
462
588
  let stream;
463
589
  let lineReader;
464
590
  try {
465
- stream = createReadStream(resolved, { encoding: "utf8", signal: options?.abortSignal });
591
+ stream = createReadStream(resolved, { encoding: "utf8", signal });
466
592
  lineReader = createInterface({ input: stream, crlfDelay: Infinity });
467
593
  const lines = [];
468
594
  for await (const line of lineReader) {
469
- const loopAbort = abortResult(options?.abortSignal, resolved);
595
+ const loopAbort = abortResult(signal, resolved);
470
596
  if (loopAbort)
471
597
  return loopAbort;
472
598
  lines.push(line);
473
599
  if (options?.maxLines !== undefined && lines.length >= options.maxLines)
474
600
  break;
475
601
  }
476
- const afterReadAbort = abortResult(options?.abortSignal, resolved);
602
+ const afterReadAbort = abortResult(signal, resolved);
477
603
  if (afterReadAbort)
478
604
  return afterReadAbort;
479
605
  return ok(lines);
@@ -486,50 +612,60 @@ export class NodeExecutionEnv {
486
612
  stream?.destroy();
487
613
  }
488
614
  }
489
- async readBinaryFile(path, abortSignal) {
615
+ async readBinaryFile(path, context) {
490
616
  const resolved = resolvePath(this.cwd, path);
491
- const aborted = abortResult(abortSignal, resolved);
617
+ const signal = context.abortSignal;
618
+ const aborted = abortResult(signal, resolved);
492
619
  if (aborted)
493
620
  return aborted;
494
621
  try {
495
- return ok(await readFile(resolved, { signal: abortSignal }));
622
+ return ok(await readFile(resolved, { signal }));
496
623
  }
497
624
  catch (error) {
498
625
  return err(toFileError(error, resolved));
499
626
  }
500
627
  }
501
- async writeFile(path, content, abortSignal) {
628
+ async writeFile(path, content, context) {
502
629
  const resolved = resolvePath(this.cwd, path);
503
- const aborted = abortResult(abortSignal, resolved);
630
+ const signal = context.abortSignal;
631
+ const aborted = abortResult(signal, resolved);
504
632
  if (aborted)
505
633
  return aborted;
506
634
  try {
507
635
  await mkdir(resolve(resolved, ".."), { recursive: true });
508
- const afterMkdirAbort = abortResult(abortSignal, resolved);
636
+ const afterMkdirAbort = abortResult(signal, resolved);
509
637
  if (afterMkdirAbort)
510
638
  return afterMkdirAbort;
511
- await writeFile(resolved, content, { signal: abortSignal });
639
+ await writeFile(resolved, content, { signal });
512
640
  return ok(undefined);
513
641
  }
514
642
  catch (error) {
515
643
  return err(toFileError(error, resolved));
516
644
  }
517
645
  }
518
- async appendFile(path, content) {
646
+ async appendFile(path, content, context) {
519
647
  const resolved = resolvePath(this.cwd, path);
648
+ const signal = context.abortSignal;
649
+ const aborted = abortResult(signal, resolved);
650
+ if (aborted)
651
+ return aborted;
520
652
  try {
521
653
  await mkdir(resolve(resolved, ".."), { recursive: true });
654
+ const afterMkdirAbort = abortResult(signal, resolved);
655
+ if (afterMkdirAbort)
656
+ return afterMkdirAbort;
522
657
  await appendFile(resolved, content);
523
- return ok(undefined);
658
+ const afterAppendAbort = abortResult(signal, resolved);
659
+ return afterAppendAbort ?? ok(undefined);
524
660
  }
525
661
  catch (error) {
526
662
  return err(toFileError(error, resolved));
527
663
  }
528
664
  }
529
- async renameFile(sourcePath, destinationPath, abortSignal) {
665
+ async renameFile(sourcePath, destinationPath, context) {
530
666
  const source = resolvePath(this.cwd, sourcePath);
531
667
  const destination = resolvePath(this.cwd, destinationPath);
532
- const aborted = abortResult(abortSignal, destination);
668
+ const aborted = abortResult(context.abortSignal, destination);
533
669
  if (aborted)
534
670
  return aborted;
535
671
  try {
@@ -540,8 +676,11 @@ export class NodeExecutionEnv {
540
676
  return err(toFileError(error, source));
541
677
  }
542
678
  }
543
- async fileInfo(path) {
679
+ async fileInfo(path, context) {
544
680
  const resolved = resolvePath(this.cwd, path);
681
+ const aborted = abortResult(context.abortSignal, resolved);
682
+ if (aborted)
683
+ return aborted;
545
684
  try {
546
685
  return fileInfoFromStats(resolved, await lstat(resolved));
547
686
  }
@@ -549,16 +688,17 @@ export class NodeExecutionEnv {
549
688
  return err(toFileError(error, resolved));
550
689
  }
551
690
  }
552
- async listDir(path, abortSignal) {
691
+ async listDir(path, context) {
553
692
  const resolved = resolvePath(this.cwd, path);
554
- const aborted = abortResult(abortSignal, resolved);
693
+ const signal = context.abortSignal;
694
+ const aborted = abortResult(signal, resolved);
555
695
  if (aborted)
556
696
  return aborted;
557
697
  try {
558
698
  const entries = await readdir(resolved, { withFileTypes: true });
559
699
  const infos = [];
560
700
  for (const entry of entries) {
561
- const loopAbort = abortResult(abortSignal, resolved);
701
+ const loopAbort = abortResult(signal, resolved);
562
702
  if (loopAbort)
563
703
  return loopAbort;
564
704
  const entryPath = resolve(resolved, entry.name);
@@ -577,8 +717,11 @@ export class NodeExecutionEnv {
577
717
  return err(toFileError(error, resolved));
578
718
  }
579
719
  }
580
- async canonicalPath(path) {
720
+ async canonicalPath(path, context) {
581
721
  const resolved = resolvePath(this.cwd, path);
722
+ const aborted = abortResult(context.abortSignal, resolved);
723
+ if (aborted)
724
+ return aborted;
582
725
  try {
583
726
  return ok(await realpath(resolved));
584
727
  }
@@ -586,16 +729,19 @@ export class NodeExecutionEnv {
586
729
  return err(toFileError(error, resolved));
587
730
  }
588
731
  }
589
- async exists(path) {
590
- const result = await this.fileInfo(path);
732
+ async exists(path, context) {
733
+ const result = await this.fileInfo(path, context);
591
734
  if (result.ok)
592
735
  return ok(true);
593
736
  if (result.error.code === "not_found")
594
737
  return ok(false);
595
738
  return err(result.error);
596
739
  }
597
- async createDir(path, options) {
740
+ async createDir(path, options, context) {
598
741
  const resolved = resolvePath(this.cwd, path);
742
+ const aborted = abortResult(context.abortSignal, resolved);
743
+ if (aborted)
744
+ return aborted;
599
745
  try {
600
746
  await mkdir(resolved, { recursive: options?.recursive ?? true });
601
747
  return ok(undefined);
@@ -604,8 +750,11 @@ export class NodeExecutionEnv {
604
750
  return err(toFileError(error, resolved));
605
751
  }
606
752
  }
607
- async remove(path, options) {
753
+ async remove(path, options, context) {
608
754
  const resolved = resolvePath(this.cwd, path);
755
+ const aborted = abortResult(context.abortSignal, resolved);
756
+ if (aborted)
757
+ return aborted;
609
758
  try {
610
759
  await rm(resolved, { recursive: options?.recursive ?? false, force: options?.force ?? false });
611
760
  return ok(undefined);
@@ -614,16 +763,20 @@ export class NodeExecutionEnv {
614
763
  return err(toFileError(error, resolved));
615
764
  }
616
765
  }
617
- async createTempDir(prefix = "tmp-") {
766
+ async createTempDir(prefix, context) {
767
+ const aborted = abortResult(context.abortSignal);
768
+ if (aborted)
769
+ return aborted;
618
770
  try {
771
+ prefix ??= "tmp-";
619
772
  return ok(await mkdtemp(join(tmpdir(), prefix)));
620
773
  }
621
774
  catch (error) {
622
775
  return err(toFileError(error));
623
776
  }
624
777
  }
625
- async createTempFile(options) {
626
- const dir = await this.createTempDir("tmp-");
778
+ async createTempFile(options, context) {
779
+ const dir = await this.createTempDir("tmp-", context);
627
780
  if (!dir.ok)
628
781
  return dir;
629
782
  const filePath = join(dir.value, `${options?.prefix ?? ""}${randomUUID()}${options?.suffix ?? ""}`);
@@ -635,7 +788,7 @@ export class NodeExecutionEnv {
635
788
  return err(toFileError(error, filePath));
636
789
  }
637
790
  }
638
- async cleanup() {
791
+ async cleanup(_context) {
639
792
  for (const pid of this.activeChildPids)
640
793
  killProcessTree(pid);
641
794
  this.activeChildPids.clear();