@cavelang/cli 0.35.0 → 0.36.1

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 (327) hide show
  1. package/README.md +224 -12
  2. package/dist/internal/act/action.js +2 -1
  3. package/dist/internal/act/action.js.map +1 -1
  4. package/dist/internal/act/declare.d.ts.map +1 -1
  5. package/dist/internal/act/declare.js +82 -53
  6. package/dist/internal/act/declare.js.map +1 -1
  7. package/dist/internal/act/engine.d.ts +4 -3
  8. package/dist/internal/act/engine.d.ts.map +1 -1
  9. package/dist/internal/act/engine.js +121 -32
  10. package/dist/internal/act/engine.js.map +1 -1
  11. package/dist/internal/automate/cancellation.d.ts +3 -0
  12. package/dist/internal/automate/cancellation.d.ts.map +1 -0
  13. package/dist/internal/automate/cancellation.js +38 -0
  14. package/dist/internal/automate/cancellation.js.map +1 -0
  15. package/dist/internal/automate/declare.d.ts.map +1 -1
  16. package/dist/internal/automate/declare.js +49 -24
  17. package/dist/internal/automate/declare.js.map +1 -1
  18. package/dist/internal/automate/engine.d.ts +7 -3
  19. package/dist/internal/automate/engine.d.ts.map +1 -1
  20. package/dist/internal/automate/engine.js +196 -93
  21. package/dist/internal/automate/engine.js.map +1 -1
  22. package/dist/internal/automate/error-message.d.ts +3 -0
  23. package/dist/internal/automate/error-message.d.ts.map +1 -0
  24. package/dist/internal/automate/error-message.js +10 -0
  25. package/dist/internal/automate/error-message.js.map +1 -0
  26. package/dist/internal/automate/main.d.ts.map +1 -1
  27. package/dist/internal/automate/main.js +238 -35
  28. package/dist/internal/automate/main.js.map +1 -1
  29. package/dist/internal/automate/options.d.ts +4 -0
  30. package/dist/internal/automate/options.d.ts.map +1 -0
  31. package/dist/internal/automate/options.js +19 -0
  32. package/dist/internal/automate/options.js.map +1 -0
  33. package/dist/internal/connect/declared.d.ts +6 -27
  34. package/dist/internal/connect/declared.d.ts.map +1 -1
  35. package/dist/internal/connect/declared.js +165 -76
  36. package/dist/internal/connect/declared.js.map +1 -1
  37. package/dist/internal/connect/error-message.d.ts +3 -0
  38. package/dist/internal/connect/error-message.d.ts.map +1 -0
  39. package/dist/internal/connect/error-message.js +10 -0
  40. package/dist/internal/connect/error-message.js.map +1 -0
  41. package/dist/internal/connect/federation.d.ts +9 -0
  42. package/dist/internal/connect/federation.d.ts.map +1 -0
  43. package/dist/internal/connect/federation.js +19 -0
  44. package/dist/internal/connect/federation.js.map +1 -0
  45. package/dist/internal/connect/fetch-failure.d.ts +3 -0
  46. package/dist/internal/connect/fetch-failure.d.ts.map +1 -0
  47. package/dist/internal/connect/fetch-failure.js +36 -0
  48. package/dist/internal/connect/fetch-failure.js.map +1 -0
  49. package/dist/internal/connect/main.d.ts +1 -0
  50. package/dist/internal/connect/main.d.ts.map +1 -1
  51. package/dist/internal/connect/main.js +288 -114
  52. package/dist/internal/connect/main.js.map +1 -1
  53. package/dist/internal/connect/options.d.ts +3 -0
  54. package/dist/internal/connect/options.d.ts.map +1 -0
  55. package/dist/internal/connect/options.js +9 -0
  56. package/dist/internal/connect/options.js.map +1 -0
  57. package/dist/internal/connect/records.d.ts +3 -0
  58. package/dist/internal/connect/records.d.ts.map +1 -0
  59. package/dist/internal/connect/records.js +21 -0
  60. package/dist/internal/connect/records.js.map +1 -0
  61. package/dist/internal/connect/run.d.ts +1 -18
  62. package/dist/internal/connect/run.d.ts.map +1 -1
  63. package/dist/internal/connect/run.js +115 -55
  64. package/dist/internal/connect/run.js.map +1 -1
  65. package/dist/internal/connect/source.d.ts +3 -1
  66. package/dist/internal/connect/source.d.ts.map +1 -1
  67. package/dist/internal/connect/source.js +226 -47
  68. package/dist/internal/connect/source.js.map +1 -1
  69. package/dist/internal/connect/template.d.ts +2 -2
  70. package/dist/internal/connect/template.d.ts.map +1 -1
  71. package/dist/internal/connect/template.js +25 -9
  72. package/dist/internal/connect/template.js.map +1 -1
  73. package/dist/internal/connect/utf8.d.ts +3 -0
  74. package/dist/internal/connect/utf8.d.ts.map +1 -0
  75. package/dist/internal/connect/utf8.js +12 -0
  76. package/dist/internal/connect/utf8.js.map +1 -0
  77. package/dist/internal/eval/cleanup.d.ts +5 -0
  78. package/dist/internal/eval/cleanup.d.ts.map +1 -0
  79. package/dist/internal/eval/cleanup.js +50 -0
  80. package/dist/internal/eval/cleanup.js.map +1 -0
  81. package/dist/internal/eval/error-message.d.ts +3 -0
  82. package/dist/internal/eval/error-message.d.ts.map +1 -0
  83. package/dist/internal/eval/error-message.js +10 -0
  84. package/dist/internal/eval/error-message.js.map +1 -0
  85. package/dist/internal/eval/judge.d.ts.map +1 -1
  86. package/dist/internal/eval/judge.js +3 -31
  87. package/dist/internal/eval/judge.js.map +1 -1
  88. package/dist/internal/eval/loop.d.ts.map +1 -1
  89. package/dist/internal/eval/loop.js +18 -4
  90. package/dist/internal/eval/loop.js.map +1 -1
  91. package/dist/internal/eval/main.d.ts.map +1 -1
  92. package/dist/internal/eval/main.js +22 -10
  93. package/dist/internal/eval/main.js.map +1 -1
  94. package/dist/internal/eval/options.d.ts +6 -0
  95. package/dist/internal/eval/options.d.ts.map +1 -0
  96. package/dist/internal/eval/options.js +31 -0
  97. package/dist/internal/eval/options.js.map +1 -0
  98. package/dist/internal/eval/queries.d.ts.map +1 -1
  99. package/dist/internal/eval/queries.js +9 -6
  100. package/dist/internal/eval/queries.js.map +1 -1
  101. package/dist/internal/eval/run.d.ts.map +1 -1
  102. package/dist/internal/eval/run.js +112 -24
  103. package/dist/internal/eval/run.js.map +1 -1
  104. package/dist/internal/eval/score.d.ts.map +1 -1
  105. package/dist/internal/eval/score.js +9 -2
  106. package/dist/internal/eval/score.js.map +1 -1
  107. package/dist/internal/eval/suite.d.ts.map +1 -1
  108. package/dist/internal/eval/suite.js +14 -2
  109. package/dist/internal/eval/suite.js.map +1 -1
  110. package/dist/internal/ingest/cleanup.d.ts +5 -0
  111. package/dist/internal/ingest/cleanup.d.ts.map +1 -0
  112. package/dist/internal/ingest/cleanup.js +50 -0
  113. package/dist/internal/ingest/cleanup.js.map +1 -0
  114. package/dist/internal/ingest/content.d.ts +6 -0
  115. package/dist/internal/ingest/content.d.ts.map +1 -0
  116. package/dist/internal/ingest/content.js +25 -0
  117. package/dist/internal/ingest/content.js.map +1 -0
  118. package/dist/internal/ingest/context.d.ts.map +1 -1
  119. package/dist/internal/ingest/context.js +25 -7
  120. package/dist/internal/ingest/context.js.map +1 -1
  121. package/dist/internal/ingest/error-message.d.ts +3 -0
  122. package/dist/internal/ingest/error-message.d.ts.map +1 -0
  123. package/dist/internal/ingest/error-message.js +10 -0
  124. package/dist/internal/ingest/error-message.js.map +1 -0
  125. package/dist/internal/ingest/files.d.ts +4 -12
  126. package/dist/internal/ingest/files.d.ts.map +1 -1
  127. package/dist/internal/ingest/files.js +22 -10
  128. package/dist/internal/ingest/files.js.map +1 -1
  129. package/dist/internal/ingest/main.d.ts.map +1 -1
  130. package/dist/internal/ingest/main.js +46 -16
  131. package/dist/internal/ingest/main.js.map +1 -1
  132. package/dist/internal/ingest/options.d.ts +6 -0
  133. package/dist/internal/ingest/options.d.ts.map +1 -0
  134. package/dist/internal/ingest/options.js +27 -0
  135. package/dist/internal/ingest/options.js.map +1 -0
  136. package/dist/internal/ingest/prompt.d.ts.map +1 -1
  137. package/dist/internal/ingest/prompt.js +14 -10
  138. package/dist/internal/ingest/prompt.js.map +1 -1
  139. package/dist/internal/ingest/run.d.ts +9 -2
  140. package/dist/internal/ingest/run.d.ts.map +1 -1
  141. package/dist/internal/ingest/run.js +206 -62
  142. package/dist/internal/ingest/run.js.map +1 -1
  143. package/dist/internal/ingest/timeout.d.ts +3 -0
  144. package/dist/internal/ingest/timeout.d.ts.map +1 -0
  145. package/dist/internal/ingest/timeout.js +14 -0
  146. package/dist/internal/ingest/timeout.js.map +1 -0
  147. package/dist/internal/ingest/web.d.ts +2 -11
  148. package/dist/internal/ingest/web.d.ts.map +1 -1
  149. package/dist/internal/ingest/web.js +131 -25
  150. package/dist/internal/ingest/web.js.map +1 -1
  151. package/dist/internal/loop/budgets.d.ts +3 -0
  152. package/dist/internal/loop/budgets.d.ts.map +1 -0
  153. package/dist/internal/loop/budgets.js +10 -0
  154. package/dist/internal/loop/budgets.js.map +1 -0
  155. package/dist/internal/loop/index.d.ts +2 -0
  156. package/dist/internal/loop/index.d.ts.map +1 -1
  157. package/dist/internal/loop/index.js +2 -0
  158. package/dist/internal/loop/index.js.map +1 -1
  159. package/dist/internal/loop/json-answer.d.ts +7 -0
  160. package/dist/internal/loop/json-answer.d.ts.map +1 -0
  161. package/dist/internal/loop/json-answer.js +79 -0
  162. package/dist/internal/loop/json-answer.js.map +1 -0
  163. package/dist/internal/loop/json-spans.d.ts +3 -0
  164. package/dist/internal/loop/json-spans.d.ts.map +1 -0
  165. package/dist/internal/loop/json-spans.js +88 -0
  166. package/dist/internal/loop/json-spans.js.map +1 -0
  167. package/dist/internal/loop/llm.d.ts +3 -2
  168. package/dist/internal/loop/llm.d.ts.map +1 -1
  169. package/dist/internal/loop/llm.js +115 -32
  170. package/dist/internal/loop/llm.js.map +1 -1
  171. package/dist/internal/loop/process.d.ts +3 -1
  172. package/dist/internal/loop/process.d.ts.map +1 -1
  173. package/dist/internal/loop/process.js +159 -59
  174. package/dist/internal/loop/process.js.map +1 -1
  175. package/dist/internal/loop/read-snapshot.d.ts +4 -0
  176. package/dist/internal/loop/read-snapshot.d.ts.map +1 -0
  177. package/dist/internal/loop/read-snapshot.js +29 -0
  178. package/dist/internal/loop/read-snapshot.js.map +1 -0
  179. package/dist/internal/loop/reconstruct.d.ts +6 -5
  180. package/dist/internal/loop/reconstruct.d.ts.map +1 -1
  181. package/dist/internal/loop/reconstruct.js +19 -8
  182. package/dist/internal/loop/reconstruct.js.map +1 -1
  183. package/dist/internal/loop/score-settings.d.ts +5 -0
  184. package/dist/internal/loop/score-settings.d.ts.map +1 -0
  185. package/dist/internal/loop/score-settings.js +14 -0
  186. package/dist/internal/loop/score-settings.js.map +1 -0
  187. package/dist/internal/loop/sqlite.d.ts.map +1 -1
  188. package/dist/internal/loop/sqlite.js +15 -7
  189. package/dist/internal/loop/sqlite.js.map +1 -1
  190. package/dist/internal/loop/store.d.ts.map +1 -1
  191. package/dist/internal/loop/store.js +11 -7
  192. package/dist/internal/loop/store.js.map +1 -1
  193. package/dist/internal/loop/timeout.d.ts +3 -0
  194. package/dist/internal/loop/timeout.d.ts.map +1 -0
  195. package/dist/internal/loop/timeout.js +13 -0
  196. package/dist/internal/loop/timeout.js.map +1 -0
  197. package/dist/internal/mcp/error-message.d.ts +3 -0
  198. package/dist/internal/mcp/error-message.d.ts.map +1 -0
  199. package/dist/internal/mcp/error-message.js +10 -0
  200. package/dist/internal/mcp/error-message.js.map +1 -0
  201. package/dist/internal/mcp/main.d.ts.map +1 -1
  202. package/dist/internal/mcp/main.js +42 -27
  203. package/dist/internal/mcp/main.js.map +1 -1
  204. package/dist/internal/mcp/read-snapshot.d.ts +4 -0
  205. package/dist/internal/mcp/read-snapshot.d.ts.map +1 -0
  206. package/dist/internal/mcp/read-snapshot.js +22 -0
  207. package/dist/internal/mcp/read-snapshot.js.map +1 -0
  208. package/dist/internal/mcp/server.d.ts.map +1 -1
  209. package/dist/internal/mcp/server.js +181 -21
  210. package/dist/internal/mcp/server.js.map +1 -1
  211. package/dist/internal/mcp/source.d.ts +3 -0
  212. package/dist/internal/mcp/source.d.ts.map +1 -0
  213. package/dist/internal/mcp/source.js +13 -0
  214. package/dist/internal/mcp/source.js.map +1 -0
  215. package/dist/internal/mcp/tools.d.ts.map +1 -1
  216. package/dist/internal/mcp/tools.js +135 -72
  217. package/dist/internal/mcp/tools.js.map +1 -1
  218. package/dist/internal/rules/declarations.d.ts +6 -0
  219. package/dist/internal/rules/declarations.d.ts.map +1 -0
  220. package/dist/internal/rules/declarations.js +14 -0
  221. package/dist/internal/rules/declarations.js.map +1 -0
  222. package/dist/internal/rules/declare.d.ts.map +1 -1
  223. package/dist/internal/rules/declare.js +30 -16
  224. package/dist/internal/rules/declare.js.map +1 -1
  225. package/dist/internal/rules/engine.d.ts +8 -7
  226. package/dist/internal/rules/engine.d.ts.map +1 -1
  227. package/dist/internal/rules/engine.js +150 -44
  228. package/dist/internal/rules/engine.js.map +1 -1
  229. package/dist/internal/shape/alias-root.d.ts +3 -0
  230. package/dist/internal/shape/alias-root.d.ts.map +1 -0
  231. package/dist/internal/shape/alias-root.js +13 -0
  232. package/dist/internal/shape/alias-root.js.map +1 -0
  233. package/dist/internal/shape/check.d.ts +15 -3
  234. package/dist/internal/shape/check.d.ts.map +1 -1
  235. package/dist/internal/shape/check.js +230 -100
  236. package/dist/internal/shape/check.js.map +1 -1
  237. package/dist/internal/shape/client.d.ts.map +1 -1
  238. package/dist/internal/shape/client.js +42 -20
  239. package/dist/internal/shape/client.js.map +1 -1
  240. package/dist/internal/shape/constraints.d.ts +8 -0
  241. package/dist/internal/shape/constraints.d.ts.map +1 -0
  242. package/dist/internal/shape/constraints.js +17 -0
  243. package/dist/internal/shape/constraints.js.map +1 -0
  244. package/dist/internal/shape/edit-distance.d.ts +3 -0
  245. package/dist/internal/shape/edit-distance.d.ts.map +1 -0
  246. package/dist/internal/shape/edit-distance.js +33 -0
  247. package/dist/internal/shape/edit-distance.js.map +1 -0
  248. package/dist/internal/shape/gate.d.ts.map +1 -1
  249. package/dist/internal/shape/gate.js +0 -0
  250. package/dist/internal/shape/gate.js.map +1 -1
  251. package/dist/internal/shape/snapshot.d.ts +4 -0
  252. package/dist/internal/shape/snapshot.d.ts.map +1 -0
  253. package/dist/internal/shape/snapshot.js +20 -0
  254. package/dist/internal/shape/snapshot.js.map +1 -0
  255. package/dist/internal/shape/suggest.d.ts +8 -6
  256. package/dist/internal/shape/suggest.d.ts.map +1 -1
  257. package/dist/internal/shape/suggest.js +208 -92
  258. package/dist/internal/shape/suggest.js.map +1 -1
  259. package/dist/internal/sync/error-message.d.ts +3 -0
  260. package/dist/internal/sync/error-message.d.ts.map +1 -0
  261. package/dist/internal/sync/error-message.js +10 -0
  262. package/dist/internal/sync/error-message.js.map +1 -0
  263. package/dist/internal/sync/index.d.ts +3 -2
  264. package/dist/internal/sync/index.d.ts.map +1 -1
  265. package/dist/internal/sync/index.js +3 -2
  266. package/dist/internal/sync/index.js.map +1 -1
  267. package/dist/internal/sync/sync.d.ts +8 -5
  268. package/dist/internal/sync/sync.d.ts.map +1 -1
  269. package/dist/internal/sync/sync.js +322 -65
  270. package/dist/internal/sync/sync.js.map +1 -1
  271. package/dist/internal/view/api.d.ts +3 -1
  272. package/dist/internal/view/api.d.ts.map +1 -1
  273. package/dist/internal/view/api.js +154 -90
  274. package/dist/internal/view/api.js.map +1 -1
  275. package/dist/internal/view/error-message.d.ts +3 -0
  276. package/dist/internal/view/error-message.d.ts.map +1 -0
  277. package/dist/internal/view/error-message.js +10 -0
  278. package/dist/internal/view/error-message.js.map +1 -0
  279. package/dist/internal/view/main.d.ts.map +1 -1
  280. package/dist/internal/view/main.js +61 -8
  281. package/dist/internal/view/main.js.map +1 -1
  282. package/dist/internal/view/page.d.ts.map +1 -1
  283. package/dist/internal/view/page.js +119 -20
  284. package/dist/internal/view/page.js.map +1 -1
  285. package/dist/internal/view/report.d.ts.map +1 -1
  286. package/dist/internal/view/report.js +180 -145
  287. package/dist/internal/view/report.js.map +1 -1
  288. package/dist/internal/view/scope.d.ts +6 -2
  289. package/dist/internal/view/scope.d.ts.map +1 -1
  290. package/dist/internal/view/scope.js +107 -24
  291. package/dist/internal/view/scope.js.map +1 -1
  292. package/dist/internal/view/sensitivity.d.ts +4 -0
  293. package/dist/internal/view/sensitivity.d.ts.map +1 -0
  294. package/dist/internal/view/sensitivity.js +11 -0
  295. package/dist/internal/view/sensitivity.js.map +1 -0
  296. package/dist/internal/view/server.d.ts.map +1 -1
  297. package/dist/internal/view/server.js +57 -20
  298. package/dist/internal/view/server.js.map +1 -1
  299. package/dist/src/atomic-output.d.ts +3 -0
  300. package/dist/src/atomic-output.d.ts.map +1 -0
  301. package/dist/src/atomic-output.js +67 -0
  302. package/dist/src/atomic-output.js.map +1 -0
  303. package/dist/src/cli.d.ts +3 -2
  304. package/dist/src/cli.d.ts.map +1 -1
  305. package/dist/src/cli.js +188 -173
  306. package/dist/src/cli.js.map +1 -1
  307. package/dist/src/dispatch.d.ts.map +1 -1
  308. package/dist/src/dispatch.js +3 -2
  309. package/dist/src/dispatch.js.map +1 -1
  310. package/dist/src/doctor.d.ts.map +1 -1
  311. package/dist/src/doctor.js +178 -102
  312. package/dist/src/doctor.js.map +1 -1
  313. package/dist/src/error-message.d.ts +3 -0
  314. package/dist/src/error-message.d.ts.map +1 -0
  315. package/dist/src/error-message.js +20 -0
  316. package/dist/src/error-message.js.map +1 -0
  317. package/dist/src/hooks-config.d.ts +3 -0
  318. package/dist/src/hooks-config.d.ts.map +1 -0
  319. package/dist/src/hooks-config.js +23 -0
  320. package/dist/src/hooks-config.js.map +1 -0
  321. package/package.json +23 -20
  322. package/src/atomic-output.ts +47 -0
  323. package/src/cli.ts +170 -147
  324. package/src/dispatch.ts +3 -2
  325. package/src/doctor.ts +192 -111
  326. package/src/error-message.ts +13 -0
  327. package/src/hooks-config.ts +22 -0
@@ -11,7 +11,7 @@
11
11
  * model twice per step (select, then "are we done?"). Both decisions fit
12
12
  * one prompt: the model replies with the next cue to expand *or* `STOP`,
13
13
  * and the loop already treats an `undefined` selection as the stop
14
- * signal. `done` then only enforces the hard budgets, for free.
14
+ * signal. `done` then only checks the stopping budgets, for free.
15
15
  * - **Scoring stays local.** Models are better spent on select/stop than
16
16
  * on per-edge arithmetic; `score` is the same parent × confidence ×
17
17
  * decay the heuristic uses, so the scores shown in the prompt mean the
@@ -34,11 +34,25 @@ import { tmpdir } from 'node:os';
34
34
  import { join } from 'node:path';
35
35
  import { emitClaim } from '@cavelang/canonical';
36
36
  import { runProcess, shellCommand } from "./process.js";
37
+ import { validateBudgets } from "./budgets.js";
38
+ import { propagatedScore, validateScoreSetting } from "./score-settings.js";
39
+ import { completionTimeoutMs } from "./timeout.js";
37
40
  /** The reply that ends the reconstruction. */
38
41
  export const stopToken = 'STOP';
39
42
  const defaultMaxCues = 16;
43
+ const cueLimit = (maxCues = defaultMaxCues) => {
44
+ if (!Number.isSafeInteger(maxCues) || maxCues < 1) {
45
+ throw new TypeError('maxCues must be a positive safe integer');
46
+ }
47
+ return maxCues;
48
+ };
40
49
  /** Strongest first; stable sort keeps FIFO order on ties, like the heuristic. */
41
50
  const strongestFirst = (frontier) => [...frontier].sort((a, b) => b.score - a.score);
51
+ /** Keep familiar hundredths when exact without erasing distinctions used by selection. */
52
+ const scoreText = (score) => {
53
+ const rounded = score.toFixed(2);
54
+ return Number(rounded) === score ? rounded : String(score);
55
+ };
42
56
  /**
43
57
  * The single per-step prompt: the query, the claims collected so far as
44
58
  * canonical CAVE lines, the strongest frontier cues with their scores, and
@@ -46,17 +60,20 @@ const strongestFirst = (frontier) => [...frontier].sort((a, b) => b.score - a.sc
46
60
  * the same rendering under a different transport.
47
61
  */
48
62
  export const selectPrompt = (state, options = {}) => {
49
- const cues = strongestFirst(state.frontier).slice(0, options.maxCues ?? defaultMaxCues);
63
+ const maxCues = cueLimit(options.maxCues);
64
+ const query = options.query;
65
+ const instructions = options.instructions;
66
+ const cues = strongestFirst(state.frontier).slice(0, maxCues);
50
67
  return [
51
68
  'You are driving memory reconstruction over a CAVE claim graph, one step at a time.',
52
- ...options.query === undefined ? [] : ['', `Query: ${options.query}`],
69
+ ...query === undefined ? [] : ['', `Query: ${query}`],
53
70
  '',
54
71
  'Claims collected so far (canonical CAVE):',
55
72
  ...state.collected.length === 0 ? ['(none yet)'] : state.collected.map(claim => emitClaim(claim)),
56
73
  '',
57
74
  'Frontier cues (entity @ score); expanding a cue collects its claims and its neighbors:',
58
- ...cues.map(cue => `${cue.entity} @ ${cue.score.toFixed(2)}`),
59
- ...options.instructions === undefined ? [] : ['', options.instructions],
75
+ ...cues.map(cue => `${cue.entity} @ ${scoreText(cue.score)}`),
76
+ ...instructions === undefined ? [] : ['', instructions],
60
77
  '',
61
78
  'Reply with exactly one line: the name of the single frontier cue to expand next, ' +
62
79
  `or ${stopToken} when the collected claims already answer the query ` +
@@ -64,22 +81,39 @@ export const selectPrompt = (state, options = {}) => {
64
81
  ].join('\n');
65
82
  };
66
83
  /** List markers, punctuation, quotes and backticks around a model's answer. */
67
- const stripped = (line) => line.trim()
68
- .replace(/^[-*\d.)\s]+/, '')
84
+ const unlisted = (line) => line.trim().replace(/^(?:[-*]|\d+[.)])\s+/, '');
85
+ const stripped = (line) => unlisted(line)
69
86
  .replace(/[.!,;:]+$/, '')
70
87
  .replace(/^[`'"]+|[`'"]+$/g, '')
71
88
  .trim();
72
- const wordChar = /[A-Za-z0-9_/-]/;
89
+ const wordChars = String.raw `[\p{L}\p{M}\p{N}_/-]`;
90
+ const startsWithWord = new RegExp(`^${wordChars}`, 'u');
91
+ // Dots and colons connect name segments only when another word character
92
+ // follows on that side; sentence punctuation such as `api. ` stays a boundary.
93
+ const continuesName = (reply, boundary, direction) => {
94
+ let index = boundary;
95
+ while (/[.:]/.test(reply[direction === -1 ? index - 1 : index] ?? '')) {
96
+ index += direction;
97
+ }
98
+ // Two code units preserve an adjacent astral code point on either side.
99
+ const adjacent = direction === -1
100
+ ? [...reply.slice(Math.max(0, index - 2), index)].at(-1) ?? ''
101
+ : reply.slice(index, index + 2);
102
+ return startsWithWord.test(adjacent);
103
+ };
73
104
  /** First occurrence of `entity` in `reply` not embedded in a larger word. */
74
105
  const mentionAt = (reply, entity) => {
106
+ // Empty names can match exact replies, but cannot be mentioned in prose.
107
+ // indexOf('', from) clamps to reply.length, so advancing from never ends.
108
+ if (entity === '')
109
+ return -1;
75
110
  for (let from = 0;;) {
76
111
  const index = reply.indexOf(entity, from);
77
112
  if (index === -1) {
78
113
  return -1;
79
114
  }
80
- const before = index === 0 ? undefined : reply[index - 1];
81
- const after = index + entity.length >= reply.length ? undefined : reply[index + entity.length];
82
- if ((before === undefined || !wordChar.test(before)) && (after === undefined || !wordChar.test(after))) {
115
+ const end = index + entity.length;
116
+ if (!continuesName(reply, index, -1) && !continuesName(reply, end, 1)) {
83
117
  return index;
84
118
  }
85
119
  from = index + 1;
@@ -90,6 +124,7 @@ const mentionAt = (reply, entity) => {
90
124
  *
91
125
  * 1. the trimmed reply, its last non-empty line, or either with list
92
126
  * markers/quotes stripped, is exactly a frontier entity → that cue;
127
+ * trailing sentence punctuation prefers the longest matching literal name;
93
128
  * 2. the reply's first word is the stop token (any case) → stop;
94
129
  * 3. the earliest frontier entity mentioned anywhere in the reply → that
95
130
  * cue (ties at one position go to the longer name; occurrences inside
@@ -104,13 +139,23 @@ export const parseSelection = (reply, frontier) => {
104
139
  }
105
140
  const byEntity = new Map(frontier.map(cue => [cue.entity, cue]));
106
141
  const lastLine = reply.split('\n').map(line => line.trim()).filter(line => line !== '').at(-1) ?? '';
107
- for (const candidate of [reply.trim(), lastLine, stripped(lastLine), stripped(reply)]) {
108
- const exact = byEntity.get(candidate);
142
+ for (const candidate of [reply.trim(), lastLine, unlisted(lastLine), unlisted(reply), stripped(lastLine), stripped(reply)]) {
143
+ let exact = byEntity.get(candidate);
144
+ if (exact === undefined) {
145
+ // Prefer a complete literal name before treating its suffix as punctuation.
146
+ for (const cue of frontier) {
147
+ if (candidate.startsWith(cue.entity) && /^[.!,;:]+$/.test(candidate.slice(cue.entity.length)) &&
148
+ (exact === undefined || cue.entity.length > exact.entity.length))
149
+ exact = cue;
150
+ }
151
+ }
109
152
  if (exact !== undefined) {
110
153
  return exact;
111
154
  }
112
155
  }
113
- if (new RegExp(`^${stopToken}\\b`, 'i').test(reply.trim())) {
156
+ // Normalize only ASCII STOP spellings so case folding cannot move offsets.
157
+ const stopAt = mentionAt(reply.trim().replace(/stop/gi, stopToken), stopToken);
158
+ if (stopAt === 0) {
114
159
  return undefined;
115
160
  }
116
161
  let mentioned;
@@ -127,7 +172,7 @@ export const parseSelection = (reply, frontier) => {
127
172
  if (mentioned !== undefined) {
128
173
  return mentioned.cue;
129
174
  }
130
- if (new RegExp(`\\b${stopToken}\\b`, 'i').test(reply)) {
175
+ if (stopAt !== -1) {
131
176
  return undefined;
132
177
  }
133
178
  return strongestFirst(frontier)[0];
@@ -143,15 +188,23 @@ export const llmPolicy = (complete, options = {}) => {
143
188
  const decay = options.decay ?? 0.8;
144
189
  const maxSteps = options.maxSteps ?? 16;
145
190
  const maxClaims = options.maxClaims ?? Number.POSITIVE_INFINITY;
191
+ validateBudgets(maxSteps, maxClaims);
192
+ validateScoreSetting('decay', decay);
193
+ const promptOptions = {
194
+ query: options.query,
195
+ instructions: options.instructions,
196
+ maxCues: cueLimit(options.maxCues)
197
+ };
146
198
  return {
147
199
  async select(state) {
148
- if (state.frontier.length === 0) {
200
+ const frontier = state.frontier.map(({ entity, score, depth }) => ({ entity, score, depth }));
201
+ if (frontier.length === 0) {
149
202
  return undefined;
150
203
  }
151
- return parseSelection(await complete(selectPrompt(state, options)), state.frontier);
204
+ return parseSelection(await complete(selectPrompt({ ...state, frontier }, promptOptions)), frontier);
152
205
  },
153
206
  async score(edge, from) {
154
- return from.score * edge.conf * decay;
207
+ return propagatedScore(from.score, edge.conf, decay);
155
208
  },
156
209
  async done(state) {
157
210
  return state.steps >= maxSteps || state.collected.length >= maxClaims;
@@ -171,33 +224,63 @@ export const llmPolicy = (complete, options = {}) => {
171
224
  * ```
172
225
  */
173
226
  export const shellComplete = (template, options = {}) => {
174
- const timeoutSeconds = options.timeoutSeconds ?? 120;
227
+ const timeoutMs = completionTimeoutMs(options.timeoutSeconds ?? 120);
228
+ const cwd = options.cwd;
229
+ const signal = options.signal;
230
+ const maxStdoutBytes = options.maxStdoutBytes;
231
+ const maxStderrBytes = options.maxStderrBytes;
175
232
  return async (prompt) => {
233
+ signal?.throwIfAborted();
234
+ if (/[\uD800-\uDFFF]/u.test(prompt)) {
235
+ throw new TypeError('agent prompt must contain well-formed Unicode');
236
+ }
176
237
  let dir;
238
+ const failures = [];
177
239
  const substitutions = {};
178
- if (template.includes('{prompt-file}')) {
179
- dir = mkdtempSync(join(tmpdir(), 'cave-loop-'));
180
- const file = join(dir, 'prompt.md');
181
- writeFileSync(file, prompt);
182
- substitutions['prompt-file'] = file;
183
- }
184
240
  try {
241
+ if (template.includes('{prompt-file}')) {
242
+ dir = mkdtempSync(join(tmpdir(), 'cave-loop-'));
243
+ const file = join(dir, 'prompt.md');
244
+ writeFileSync(file, prompt);
245
+ substitutions['prompt-file'] = file;
246
+ }
185
247
  const result = await runProcess(shellCommand(template, substitutions), {
248
+ strictStdoutUtf8: true,
186
249
  input: prompt,
187
- timeoutMs: timeoutSeconds * 1000,
188
- ...options.cwd === undefined ? {} : { cwd: options.cwd },
189
- ...options.signal === undefined ? {} : { signal: options.signal },
190
- ...options.maxStdoutBytes === undefined ? {} : { maxStdoutBytes: options.maxStdoutBytes },
191
- ...options.maxStderrBytes === undefined ? {} : { maxStderrBytes: options.maxStderrBytes }
250
+ timeoutMs,
251
+ ...cwd === undefined ? {} : { cwd },
252
+ ...signal === undefined ? {} : { signal },
253
+ ...maxStdoutBytes === undefined ? {} : { maxStdoutBytes },
254
+ ...maxStderrBytes === undefined ? {} : { maxStderrBytes }
192
255
  });
193
256
  if (result.code !== 0) {
194
257
  throw new Error(`agent exited with ${result.code ?? `signal ${result.signal}`}`);
195
258
  }
196
259
  return result.stdout;
197
260
  }
261
+ catch (error) {
262
+ failures.push(error);
263
+ throw error;
264
+ }
198
265
  finally {
199
- if (dir !== undefined)
200
- rmSync(dir, { recursive: true, force: true });
266
+ if (dir !== undefined) {
267
+ try {
268
+ rmSync(dir, { recursive: true, force: true });
269
+ }
270
+ catch (error) {
271
+ if (failures.length === 0)
272
+ throw error;
273
+ const describe = (value) => {
274
+ try {
275
+ return value instanceof Error ? String(value.message) : String(value);
276
+ }
277
+ catch {
278
+ return '[unprintable thrown value]';
279
+ }
280
+ };
281
+ throw new AggregateError([failures[0], error], `${describe(failures[0])}; prompt cleanup also failed: ${describe(error)}`, { cause: failures[0] });
282
+ }
283
+ }
201
284
  }
202
285
  };
203
286
  };
@@ -1 +1 @@
1
- {"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/llm.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/llm.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@ export type ProcessResult = {
10
10
  readonly stdout: string;
11
11
  readonly stderr: string;
12
12
  };
13
- export type ProcessFailureKind = 'spawn' | 'timeout' | 'aborted' | 'stdout-limit' | 'stderr-limit';
13
+ export type ProcessFailureKind = 'spawn' | 'timeout' | 'aborted' | 'stdout-limit' | 'stderr-limit' | 'stdout-encoding';
14
14
  export type ProcessFailureRecord = {
15
15
  readonly kind: ProcessFailureKind;
16
16
  readonly message: string;
@@ -36,6 +36,8 @@ export type ProcessOptions = {
36
36
  readonly signal?: AbortSignal;
37
37
  readonly maxStdoutBytes?: number;
38
38
  readonly maxStderrBytes?: number;
39
+ /** Reject malformed UTF-8 stdout before structured consumers interpret it. */
40
+ readonly strictStdoutUtf8?: boolean;
39
41
  };
40
42
  export type SyncProcessOptions = Omit<ProcessOptions, 'signal'>;
41
43
  export declare const defaultMaxStdoutBytes: number;
@@ -1 +1 @@
1
- {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/process.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/process.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  /** Portable, bounded external-process execution for CAVE integrations. */
2
2
  import { spawn, spawnSync } from 'node:child_process';
3
+ import { isUtf8 } from 'node:buffer';
3
4
  import { fileURLToPath } from 'node:url';
4
5
  /** Typed, command-redacted failure for resource and lifecycle errors. */
5
6
  export class ProcessFailure extends Error {
@@ -62,12 +63,29 @@ export const shellCommand = (template, substitutions = {}, platform = process.pl
62
63
  };
63
64
  const emptyResult = () => ({ code: null, signal: null, stdout: '', stderr: '' });
64
65
  const positiveLimit = (value, fallback, name) => {
65
- const result = value ?? fallback;
66
+ const result = value === undefined ? fallback : value;
66
67
  if (!Number.isSafeInteger(result) || result < 0) {
67
68
  throw new TypeError(`${name} must be a non-negative safe integer`);
68
69
  }
69
70
  return result;
70
71
  };
72
+ const stdoutUtf8Mode = (value) => {
73
+ if (value !== undefined && typeof value !== 'boolean')
74
+ throw new TypeError('strictStdoutUtf8 must be a boolean');
75
+ return value === true;
76
+ };
77
+ const processInput = (value) => {
78
+ if (value !== undefined && typeof value !== 'string')
79
+ throw new TypeError('input must be a string');
80
+ return value;
81
+ };
82
+ const timeoutLimit = (value) => {
83
+ const timeoutMs = positiveLimit(value, 0, 'timeoutMs');
84
+ if (timeoutMs > 2147483647) {
85
+ throw new TypeError('timeoutMs must be in 0..2147483647');
86
+ }
87
+ return timeoutMs;
88
+ };
71
89
  const killTree = (child) => {
72
90
  const pid = child.pid;
73
91
  if (pid === undefined)
@@ -107,14 +125,18 @@ const failureMessage = (kind, timeoutMs, limit) => {
107
125
  case 'aborted': return 'process was cancelled';
108
126
  case 'stdout-limit': return `process stdout exceeded ${limit} bytes`;
109
127
  case 'stderr-limit': return `process stderr exceeded ${limit} bytes`;
128
+ case 'stdout-encoding': return 'process stdout contains invalid UTF-8';
110
129
  }
111
130
  };
112
131
  /** Run an executable plus argument array with bounded output and tree cleanup. */
113
132
  export const runProcess = (command, options = {}) => {
114
133
  const stdoutLimit = positiveLimit(options.maxStdoutBytes, defaultMaxStdoutBytes, 'maxStdoutBytes');
115
134
  const stderrLimit = positiveLimit(options.maxStderrBytes, defaultMaxStderrBytes, 'maxStderrBytes');
116
- const timeoutMs = positiveLimit(options.timeoutMs, 0, 'timeoutMs');
117
- if (options.signal?.aborted === true) {
135
+ const timeoutMs = timeoutLimit(options.timeoutMs);
136
+ const strictStdoutUtf8 = stdoutUtf8Mode(options.strictStdoutUtf8);
137
+ const input = processInput(options.input);
138
+ const signal = options.signal;
139
+ if (signal?.aborted === true) {
118
140
  return Promise.reject(new ProcessFailure({
119
141
  kind: 'aborted', message: failureMessage('aborted', timeoutMs), result: emptyResult()
120
142
  }));
@@ -130,33 +152,66 @@ export const runProcess = (command, options = {}) => {
130
152
  let terminating = false;
131
153
  let timer;
132
154
  let spawnErrorCode;
133
- const child = spawn(command.executable, [...command.args], {
134
- shell: false,
135
- detached: process.platform !== 'win32',
136
- windowsHide: true,
137
- stdio: ['pipe', 'pipe', 'pipe'],
138
- ...options.cwd === undefined ? {} : { cwd: options.cwd },
139
- ...options.env === undefined ? {} : { env: options.env }
140
- });
155
+ let child;
156
+ try {
157
+ const cwd = options.cwd;
158
+ const env = options.env;
159
+ child = spawn(command.executable, [...command.args], {
160
+ shell: false,
161
+ detached: process.platform !== 'win32',
162
+ windowsHide: true,
163
+ stdio: ['pipe', 'pipe', 'pipe'],
164
+ ...cwd === undefined ? {} : { cwd },
165
+ ...env === undefined ? {} : { env }
166
+ });
167
+ }
168
+ catch {
169
+ reject(new ProcessFailure({
170
+ kind: 'spawn',
171
+ message: failureMessage('spawn', timeoutMs),
172
+ result: emptyResult()
173
+ }));
174
+ return;
175
+ }
141
176
  const result = () => ({
142
177
  code,
143
178
  signal: exitSignal,
144
179
  stdout: Buffer.concat(stdout).toString('utf8'),
145
180
  stderr: Buffer.concat(stderr).toString('utf8')
146
181
  });
147
- const cleanup = () => {
148
- if (timer !== undefined)
149
- clearTimeout(timer);
150
- options.signal?.removeEventListener('abort', abort);
151
- };
152
- const finish = (failure) => {
182
+ const finish = (failure, cleanupErrors = []) => {
153
183
  if (settled)
154
184
  return;
155
185
  settled = true;
156
- cleanup();
157
- child.stdin?.destroy();
158
- child.stdout?.destroy();
159
- child.stderr?.destroy();
186
+ if (failure === undefined && strictStdoutUtf8 && !isUtf8(Buffer.concat(stdout))) {
187
+ failure = new ProcessFailure({ kind: 'stdout-encoding', message: failureMessage('stdout-encoding', timeoutMs), result: result() });
188
+ }
189
+ for (const cleanup of [
190
+ () => { if (timer !== undefined)
191
+ clearTimeout(timer); },
192
+ () => signal?.removeEventListener('abort', abort),
193
+ () => child.stdin?.destroy(),
194
+ () => child.stdout?.destroy(),
195
+ () => child.stderr?.destroy()
196
+ ]) {
197
+ try {
198
+ cleanup();
199
+ }
200
+ catch (error) {
201
+ cleanupErrors.push(error);
202
+ }
203
+ }
204
+ if (cleanupErrors.length > 0) {
205
+ const cleanup = new AggregateError(cleanupErrors, 'process cleanup failed', { cause: cleanupErrors[0] });
206
+ if (failure === undefined) {
207
+ reject(cleanup);
208
+ return;
209
+ }
210
+ // Preserve the typed process outcome and captured output for callers.
211
+ // Raw cleanup details stay in cause, outside command-redacted messages.
212
+ failure.cause = cleanup;
213
+ failure.message += '; process cleanup also failed';
214
+ }
160
215
  if (failure === undefined)
161
216
  resolve(result());
162
217
  else
@@ -166,12 +221,13 @@ export const runProcess = (command, options = {}) => {
166
221
  if (settled || terminating)
167
222
  return;
168
223
  terminating = true;
169
- void killTree(child).finally(() => finish(new ProcessFailure({
224
+ const complete = (errors = []) => finish(new ProcessFailure({
170
225
  kind,
171
226
  message: failureMessage(kind, timeoutMs, limit),
172
227
  result: result(),
173
228
  ...limit === undefined ? {} : { limit }
174
- })));
229
+ }), errors);
230
+ void killTree(child).then(() => complete(), error => complete([error]));
175
231
  };
176
232
  const abort = () => terminate('aborted');
177
233
  const collect = (stream, chunk) => {
@@ -190,42 +246,74 @@ export const runProcess = (command, options = {}) => {
190
246
  if (bytes.length > remaining)
191
247
  terminate(stream === 'stdout' ? 'stdout-limit' : 'stderr-limit', limit);
192
248
  };
193
- child.stdout?.on('data', chunk => collect('stdout', chunk));
194
- child.stderr?.on('data', chunk => collect('stderr', chunk));
195
- child.on('error', (error) => {
196
- if (terminating)
197
- return;
198
- spawnErrorCode = error.code;
199
- finish(new ProcessFailure({
200
- kind: 'spawn',
201
- message: failureMessage('spawn', timeoutMs),
202
- result: result(),
203
- ...spawnErrorCode === undefined ? {} : { errorCode: spawnErrorCode }
204
- }));
205
- });
206
- child.on('exit', (observedCode, observedSignal) => {
207
- code = observedCode;
208
- exitSignal = observedSignal;
209
- });
210
- child.on('close', (observedCode, observedSignal) => {
211
- code = observedCode;
212
- exitSignal = observedSignal;
213
- if (!terminating)
214
- finish();
215
- });
216
- child.stdin?.on('error', () => { });
217
- if (options.input !== undefined)
218
- child.stdin?.end(options.input);
219
- else
220
- child.stdin?.end();
221
- if (timeoutMs > 0)
222
- timer = setTimeout(() => terminate('timeout'), timeoutMs);
223
- options.signal?.addEventListener('abort', abort, { once: true });
224
- // Close the check/listener race if cancellation landed during spawn setup.
225
- if (options.signal?.aborted === true)
226
- abort();
249
+ try {
250
+ child.stdout?.on('data', chunk => collect('stdout', chunk));
251
+ child.stderr?.on('data', chunk => collect('stderr', chunk));
252
+ child.on('error', (error) => {
253
+ if (terminating)
254
+ return;
255
+ spawnErrorCode = error.code;
256
+ finish(new ProcessFailure({
257
+ kind: 'spawn',
258
+ message: failureMessage('spawn', timeoutMs),
259
+ result: result(),
260
+ ...spawnErrorCode === undefined ? {} : { errorCode: spawnErrorCode }
261
+ }));
262
+ });
263
+ child.on('exit', (observedCode, observedSignal) => {
264
+ code = observedCode;
265
+ exitSignal = observedSignal;
266
+ });
267
+ child.on('close', (observedCode, observedSignal) => {
268
+ code = observedCode;
269
+ exitSignal = observedSignal;
270
+ if (!terminating)
271
+ finish();
272
+ });
273
+ child.stdin?.on('error', () => { });
274
+ if (input !== undefined)
275
+ child.stdin?.end(input);
276
+ else
277
+ child.stdin?.end();
278
+ if (timeoutMs > 0)
279
+ timer = setTimeout(() => terminate('timeout'), timeoutMs);
280
+ signal?.addEventListener('abort', abort, { once: true });
281
+ // Close the check/listener race if cancellation landed during spawn setup.
282
+ if (signal?.aborted === true)
283
+ abort();
284
+ }
285
+ catch {
286
+ // Startup owns the child as soon as spawn returns, including partial
287
+ // listener registration and stdin setup. Keep startup diagnostics redacted.
288
+ terminate('spawn');
289
+ }
227
290
  });
228
291
  };
292
+ /** Capture Node's enumerable environment entries without JSON object hooks. */
293
+ const workerEnvironment = (env) => {
294
+ if (env == null)
295
+ return undefined;
296
+ let keys = [];
297
+ for (const key in env)
298
+ keys.push(key);
299
+ if (process.platform === 'win32') {
300
+ const seen = new Set();
301
+ keys = keys.sort().filter(key => {
302
+ const upper = key.toUpperCase();
303
+ if (seen.has(upper))
304
+ return false;
305
+ seen.add(upper);
306
+ return true;
307
+ });
308
+ }
309
+ const captured = Object.create(null);
310
+ for (const key of keys) {
311
+ const value = env[key];
312
+ if (value !== undefined)
313
+ captured[key] = `${value}`;
314
+ }
315
+ return captured;
316
+ };
229
317
  /**
230
318
  * Synchronous bridge for compatibility-sensitive APIs. A short-lived Node
231
319
  * worker owns the asynchronous tree cleanup, then returns one bounded result.
@@ -233,14 +321,26 @@ export const runProcess = (command, options = {}) => {
233
321
  export const runProcessSync = (command, options = {}) => {
234
322
  const stdoutLimit = positiveLimit(options.maxStdoutBytes, defaultMaxStdoutBytes, 'maxStdoutBytes');
235
323
  const stderrLimit = positiveLimit(options.maxStderrBytes, defaultMaxStderrBytes, 'maxStderrBytes');
236
- const timeoutMs = positiveLimit(options.timeoutMs, 0, 'timeoutMs');
324
+ const timeoutMs = timeoutLimit(options.timeoutMs);
325
+ const strictStdoutUtf8 = stdoutUtf8Mode(options.strictStdoutUtf8);
326
+ const input = processInput(options.input);
327
+ let request;
328
+ try {
329
+ const cwd = options.cwd;
330
+ const env = workerEnvironment(options.env);
331
+ const capturedCommand = { executable: command.executable, args: [...command.args] };
332
+ request = JSON.stringify({ command: capturedCommand, options: { timeoutMs, input, cwd, env, maxStdoutBytes: stdoutLimit, maxStderrBytes: stderrLimit, strictStdoutUtf8 } });
333
+ }
334
+ catch {
335
+ throw new ProcessFailure({ kind: 'spawn', message: failureMessage('spawn', timeoutMs), result: emptyResult() });
336
+ }
237
337
  const extension = import.meta.url.endsWith('.ts') ? 'ts' : 'js';
238
338
  const worker = fileURLToPath(new URL(`./process-worker.${extension}`, import.meta.url));
239
339
  const result = spawnSync(process.execPath, ['--disable-warning=ExperimentalWarning', worker], {
240
340
  shell: false,
241
341
  windowsHide: true,
242
342
  encoding: 'utf8',
243
- input: JSON.stringify({ command, options: { ...options, maxStdoutBytes: stdoutLimit, maxStderrBytes: stderrLimit } }),
343
+ input: request,
244
344
  // JSON can expand a captured control byte to a six-byte `\\u00xx` escape.
245
345
  maxBuffer: Math.max(1024 * 1024, (stdoutLimit + stderrLimit) * 7 + 1024 * 1024),
246
346
  timeout: timeoutMs > 0 ? timeoutMs + 5_000 : undefined