@animalabs/agent-framework 0.23.3 → 0.24.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 (355) hide show
  1. package/README.md +212 -42
  2. package/dist/src/agent.d.ts +65 -9
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +98 -12
  5. package/dist/src/agent.js.map +1 -1
  6. package/dist/src/api/server.d.ts.map +1 -1
  7. package/dist/src/api/server.js +14 -12
  8. package/dist/src/api/server.js.map +1 -1
  9. package/dist/src/clock-rows.d.ts +115 -0
  10. package/dist/src/clock-rows.d.ts.map +1 -0
  11. package/dist/src/clock-rows.js +222 -0
  12. package/dist/src/clock-rows.js.map +1 -0
  13. package/dist/src/code-execution/engine.d.ts +177 -0
  14. package/dist/src/code-execution/engine.d.ts.map +1 -0
  15. package/dist/src/code-execution/engine.js +494 -0
  16. package/dist/src/code-execution/engine.js.map +1 -0
  17. package/dist/src/code-execution/index.d.ts +5 -10
  18. package/dist/src/code-execution/index.d.ts.map +1 -1
  19. package/dist/src/code-execution/index.js +5 -9
  20. package/dist/src/code-execution/index.js.map +1 -1
  21. package/dist/src/code-execution/isolate/calls.d.ts +114 -0
  22. package/dist/src/code-execution/isolate/calls.d.ts.map +1 -0
  23. package/dist/src/code-execution/isolate/calls.js +145 -0
  24. package/dist/src/code-execution/isolate/calls.js.map +1 -0
  25. package/dist/src/code-execution/isolate/child-entry.d.ts +2 -0
  26. package/dist/src/code-execution/isolate/child-entry.d.ts.map +1 -0
  27. package/dist/src/code-execution/isolate/child-entry.js +5 -0
  28. package/dist/src/code-execution/isolate/child-entry.js.map +1 -0
  29. package/dist/src/code-execution/isolate/child-main.d.ts +26 -0
  30. package/dist/src/code-execution/isolate/child-main.d.ts.map +1 -0
  31. package/dist/src/code-execution/isolate/child-main.js +132 -0
  32. package/dist/src/code-execution/isolate/child-main.js.map +1 -0
  33. package/dist/src/code-execution/isolate/child.d.ts +44 -0
  34. package/dist/src/code-execution/isolate/child.d.ts.map +1 -0
  35. package/dist/src/code-execution/isolate/child.js +315 -0
  36. package/dist/src/code-execution/isolate/child.js.map +1 -0
  37. package/dist/src/code-execution/isolate/frames.d.ts +80 -0
  38. package/dist/src/code-execution/isolate/frames.d.ts.map +1 -0
  39. package/dist/src/code-execution/isolate/frames.js +210 -0
  40. package/dist/src/code-execution/isolate/frames.js.map +1 -0
  41. package/dist/src/code-execution/isolate/output.d.ts +68 -0
  42. package/dist/src/code-execution/isolate/output.d.ts.map +1 -0
  43. package/dist/src/code-execution/isolate/output.js +143 -0
  44. package/dist/src/code-execution/isolate/output.js.map +1 -0
  45. package/dist/src/code-execution/isolate/prelude.d.ts +109 -0
  46. package/dist/src/code-execution/isolate/prelude.d.ts.map +1 -0
  47. package/dist/src/code-execution/isolate/prelude.js +401 -0
  48. package/dist/src/code-execution/isolate/prelude.js.map +1 -0
  49. package/dist/src/code-execution/isolate/protocol.d.ts +151 -0
  50. package/dist/src/code-execution/isolate/protocol.d.ts.map +1 -0
  51. package/dist/src/code-execution/isolate/protocol.js +150 -0
  52. package/dist/src/code-execution/isolate/protocol.js.map +1 -0
  53. package/dist/src/code-execution/isolate/render.d.ts +57 -0
  54. package/dist/src/code-execution/isolate/render.d.ts.map +1 -0
  55. package/dist/src/code-execution/isolate/render.js +214 -0
  56. package/dist/src/code-execution/isolate/render.js.map +1 -0
  57. package/dist/src/code-execution/isolate/runner.d.ts +250 -0
  58. package/dist/src/code-execution/isolate/runner.d.ts.map +1 -0
  59. package/dist/src/code-execution/isolate/runner.js +854 -0
  60. package/dist/src/code-execution/isolate/runner.js.map +1 -0
  61. package/dist/src/code-execution/isolate/scripts.d.ts +175 -0
  62. package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -0
  63. package/dist/src/code-execution/isolate/scripts.js +357 -0
  64. package/dist/src/code-execution/isolate/scripts.js.map +1 -0
  65. package/dist/src/code-execution/quickjs.wasm +0 -0
  66. package/dist/src/code-execution/tool-definition.d.ts +93 -43
  67. package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
  68. package/dist/src/code-execution/tool-definition.js +176 -142
  69. package/dist/src/code-execution/tool-definition.js.map +1 -1
  70. package/dist/src/deadline-timer.d.ts +3 -0
  71. package/dist/src/deadline-timer.d.ts.map +1 -1
  72. package/dist/src/deadline-timer.js +1 -1
  73. package/dist/src/deadline-timer.js.map +1 -1
  74. package/dist/src/framework.d.ts +1120 -457
  75. package/dist/src/framework.d.ts.map +1 -1
  76. package/dist/src/framework.js +4635 -2505
  77. package/dist/src/framework.js.map +1 -1
  78. package/dist/src/gate/event-gate.d.ts +28 -4
  79. package/dist/src/gate/event-gate.d.ts.map +1 -1
  80. package/dist/src/gate/event-gate.js +89 -13
  81. package/dist/src/gate/event-gate.js.map +1 -1
  82. package/dist/src/held-writes.d.ts +16 -3
  83. package/dist/src/held-writes.d.ts.map +1 -1
  84. package/dist/src/held-writes.js +16 -3
  85. package/dist/src/held-writes.js.map +1 -1
  86. package/dist/src/index.d.ts +8 -6
  87. package/dist/src/index.d.ts.map +1 -1
  88. package/dist/src/index.js +10 -8
  89. package/dist/src/index.js.map +1 -1
  90. package/dist/src/mcpl/channel-registry.d.ts +483 -115
  91. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  92. package/dist/src/mcpl/channel-registry.js +1735 -425
  93. package/dist/src/mcpl/channel-registry.js.map +1 -1
  94. package/dist/src/mcpl/conversation-router.d.ts +19 -39
  95. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  96. package/dist/src/mcpl/conversation-router.js +27 -59
  97. package/dist/src/mcpl/conversation-router.js.map +1 -1
  98. package/dist/src/mcpl/convert-block.d.ts.map +1 -1
  99. package/dist/src/mcpl/convert-block.js +9 -5
  100. package/dist/src/mcpl/convert-block.js.map +1 -1
  101. package/dist/src/mcpl/inbound-source.d.ts +50 -0
  102. package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
  103. package/dist/src/mcpl/inbound-source.js +130 -0
  104. package/dist/src/mcpl/inbound-source.js.map +1 -1
  105. package/dist/src/mcpl/index.d.ts +2 -1
  106. package/dist/src/mcpl/index.d.ts.map +1 -1
  107. package/dist/src/mcpl/index.js +3 -2
  108. package/dist/src/mcpl/index.js.map +1 -1
  109. package/dist/src/mcpl/log-value.d.ts +6 -0
  110. package/dist/src/mcpl/log-value.d.ts.map +1 -1
  111. package/dist/src/mcpl/log-value.js +8 -0
  112. package/dist/src/mcpl/log-value.js.map +1 -1
  113. package/dist/src/mcpl/modern-connection.d.ts +15 -6
  114. package/dist/src/mcpl/modern-connection.d.ts.map +1 -1
  115. package/dist/src/mcpl/modern-connection.js +168 -53
  116. package/dist/src/mcpl/modern-connection.js.map +1 -1
  117. package/dist/src/mcpl/prose-grammar.d.ts +4 -5
  118. package/dist/src/mcpl/prose-grammar.d.ts.map +1 -1
  119. package/dist/src/mcpl/prose-grammar.js +4 -5
  120. package/dist/src/mcpl/prose-grammar.js.map +1 -1
  121. package/dist/src/mcpl/protocol-family.d.ts +97 -10
  122. package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
  123. package/dist/src/mcpl/protocol-family.js +174 -17
  124. package/dist/src/mcpl/protocol-family.js.map +1 -1
  125. package/dist/src/mcpl/push-coalescer.d.ts +132 -14
  126. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  127. package/dist/src/mcpl/push-coalescer.js +227 -50
  128. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  129. package/dist/src/mcpl/push-handler.d.ts +9 -20
  130. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  131. package/dist/src/mcpl/push-handler.js +7 -49
  132. package/dist/src/mcpl/push-handler.js.map +1 -1
  133. package/dist/src/mcpl/reference-fetcher.d.ts +2 -2
  134. package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
  135. package/dist/src/mcpl/reference-fetcher.js +4 -4
  136. package/dist/src/mcpl/reference-fetcher.js.map +1 -1
  137. package/dist/src/mcpl/server-connection.d.ts +50 -21
  138. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  139. package/dist/src/mcpl/server-connection.js +158 -74
  140. package/dist/src/mcpl/server-connection.js.map +1 -1
  141. package/dist/src/mcpl/tags.d.ts +24 -0
  142. package/dist/src/mcpl/tags.d.ts.map +1 -1
  143. package/dist/src/mcpl/tags.js +33 -0
  144. package/dist/src/mcpl/tags.js.map +1 -1
  145. package/dist/src/mcpl/tool-result-normalize.d.ts +2 -1
  146. package/dist/src/mcpl/tool-result-normalize.d.ts.map +1 -1
  147. package/dist/src/mcpl/tool-result-normalize.js.map +1 -1
  148. package/dist/src/mcpl/transport.d.ts +55 -7
  149. package/dist/src/mcpl/transport.d.ts.map +1 -1
  150. package/dist/src/mcpl/transport.js +163 -34
  151. package/dist/src/mcpl/transport.js.map +1 -1
  152. package/dist/src/mcpl/types.d.ts +22 -6
  153. package/dist/src/mcpl/types.d.ts.map +1 -1
  154. package/dist/src/mcpl/types.js.map +1 -1
  155. package/dist/src/module-registry.d.ts +4 -2
  156. package/dist/src/module-registry.d.ts.map +1 -1
  157. package/dist/src/module-registry.js +100 -13
  158. package/dist/src/module-registry.js.map +1 -1
  159. package/dist/src/modules/discord/index.d.ts.map +1 -1
  160. package/dist/src/modules/discord/index.js +8 -13
  161. package/dist/src/modules/discord/index.js.map +1 -1
  162. package/dist/src/modules/history/index.d.ts.map +1 -1
  163. package/dist/src/modules/history/index.js +27 -4
  164. package/dist/src/modules/history/index.js.map +1 -1
  165. package/dist/src/modules/history/semantic.d.ts +15 -3
  166. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  167. package/dist/src/modules/history/semantic.js +27 -5
  168. package/dist/src/modules/history/semantic.js.map +1 -1
  169. package/dist/src/modules/index.d.ts +1 -1
  170. package/dist/src/modules/index.d.ts.map +1 -1
  171. package/dist/src/modules/index.js.map +1 -1
  172. package/dist/src/modules/unknown-tool.d.ts +4 -1
  173. package/dist/src/modules/unknown-tool.d.ts.map +1 -1
  174. package/dist/src/modules/unknown-tool.js +4 -1
  175. package/dist/src/modules/unknown-tool.js.map +1 -1
  176. package/dist/src/modules/workspace/branch-intent.d.ts +3 -1
  177. package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
  178. package/dist/src/modules/workspace/branch-intent.js +3 -1
  179. package/dist/src/modules/workspace/branch-intent.js.map +1 -1
  180. package/dist/src/modules/workspace/edit-plan.d.ts +265 -0
  181. package/dist/src/modules/workspace/edit-plan.d.ts.map +1 -0
  182. package/dist/src/modules/workspace/edit-plan.js +794 -0
  183. package/dist/src/modules/workspace/edit-plan.js.map +1 -0
  184. package/dist/src/modules/workspace/edit-text.d.ts +117 -0
  185. package/dist/src/modules/workspace/edit-text.d.ts.map +1 -0
  186. package/dist/src/modules/workspace/edit-text.js +584 -0
  187. package/dist/src/modules/workspace/edit-text.js.map +1 -0
  188. package/dist/src/modules/workspace/effects.d.ts +5 -4
  189. package/dist/src/modules/workspace/effects.d.ts.map +1 -1
  190. package/dist/src/modules/workspace/effects.js +78 -25
  191. package/dist/src/modules/workspace/effects.js.map +1 -1
  192. package/dist/src/modules/workspace/index.d.ts +493 -62
  193. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  194. package/dist/src/modules/workspace/index.js +2216 -652
  195. package/dist/src/modules/workspace/index.js.map +1 -1
  196. package/dist/src/modules/workspace/observe.d.ts +213 -38
  197. package/dist/src/modules/workspace/observe.d.ts.map +1 -1
  198. package/dist/src/modules/workspace/observe.js +416 -36
  199. package/dist/src/modules/workspace/observe.js.map +1 -1
  200. package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
  201. package/dist/src/modules/workspace/reconcile.js +15 -8
  202. package/dist/src/modules/workspace/reconcile.js.map +1 -1
  203. package/dist/src/modules/workspace/text.d.ts +32 -0
  204. package/dist/src/modules/workspace/text.d.ts.map +1 -0
  205. package/dist/src/modules/workspace/text.js +67 -0
  206. package/dist/src/modules/workspace/text.js.map +1 -0
  207. package/dist/src/modules/workspace/types.d.ts +210 -6
  208. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  209. package/dist/src/modules/workspace/types.js.map +1 -1
  210. package/dist/src/modules/workspace/watcher.d.ts +3 -2
  211. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  212. package/dist/src/modules/workspace/watcher.js.map +1 -1
  213. package/dist/src/operator-log.d.ts +52 -24
  214. package/dist/src/operator-log.d.ts.map +1 -1
  215. package/dist/src/operator-log.js.map +1 -1
  216. package/dist/src/recovery/discord-awareness-outbox.d.ts +496 -72
  217. package/dist/src/recovery/discord-awareness-outbox.d.ts.map +1 -1
  218. package/dist/src/recovery/discord-awareness-outbox.js +1196 -289
  219. package/dist/src/recovery/discord-awareness-outbox.js.map +1 -1
  220. package/dist/src/recovery/offline-branch.d.ts +26 -1
  221. package/dist/src/recovery/offline-branch.d.ts.map +1 -1
  222. package/dist/src/recovery/offline-branch.js +164 -39
  223. package/dist/src/recovery/offline-branch.js.map +1 -1
  224. package/dist/src/recovery/recover-cli.js +23 -4
  225. package/dist/src/recovery/recover-cli.js.map +1 -1
  226. package/dist/src/send-tools.d.ts +11 -0
  227. package/dist/src/send-tools.d.ts.map +1 -0
  228. package/dist/src/send-tools.js +11 -0
  229. package/dist/src/send-tools.js.map +1 -0
  230. package/dist/src/timezone.d.ts +4 -2
  231. package/dist/src/timezone.d.ts.map +1 -1
  232. package/dist/src/timezone.js +4 -2
  233. package/dist/src/timezone.js.map +1 -1
  234. package/dist/src/tool-image-ledger.d.ts +46 -7
  235. package/dist/src/tool-image-ledger.d.ts.map +1 -1
  236. package/dist/src/tool-image-ledger.js +60 -7
  237. package/dist/src/tool-image-ledger.js.map +1 -1
  238. package/dist/src/tool-result-guard.d.ts +14 -11
  239. package/dist/src/tool-result-guard.d.ts.map +1 -1
  240. package/dist/src/tool-result-guard.js +17 -14
  241. package/dist/src/tool-result-guard.js.map +1 -1
  242. package/dist/src/tool-result-history.d.ts +3 -2
  243. package/dist/src/tool-result-history.d.ts.map +1 -1
  244. package/dist/src/tool-result-history.js +3 -2
  245. package/dist/src/tool-result-history.js.map +1 -1
  246. package/dist/src/tune-out/coordinator.d.ts +21 -0
  247. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  248. package/dist/src/tune-out/coordinator.js +142 -40
  249. package/dist/src/tune-out/coordinator.js.map +1 -1
  250. package/dist/src/types/agent.d.ts +31 -6
  251. package/dist/src/types/agent.d.ts.map +1 -1
  252. package/dist/src/types/events.d.ts +66 -9
  253. package/dist/src/types/events.d.ts.map +1 -1
  254. package/dist/src/types/framework.d.ts +69 -62
  255. package/dist/src/types/framework.d.ts.map +1 -1
  256. package/dist/src/types/module.d.ts +40 -8
  257. package/dist/src/types/module.d.ts.map +1 -1
  258. package/dist/src/types/trace.d.ts +111 -10
  259. package/dist/src/types/trace.d.ts.map +1 -1
  260. package/dist/src/usage/types.d.ts +16 -0
  261. package/dist/src/usage/types.d.ts.map +1 -1
  262. package/dist/src/usage/usage-tracker.d.ts +14 -1
  263. package/dist/src/usage/usage-tracker.d.ts.map +1 -1
  264. package/dist/src/usage/usage-tracker.js +81 -41
  265. package/dist/src/usage/usage-tracker.js.map +1 -1
  266. package/package.json +6 -8
  267. package/src/agent.ts +99 -12
  268. package/src/api/server.ts +14 -12
  269. package/src/clock-rows.ts +302 -0
  270. package/src/code-execution/engine.ts +595 -0
  271. package/src/code-execution/index.ts +5 -17
  272. package/src/code-execution/isolate/calls.ts +199 -0
  273. package/src/code-execution/isolate/child-entry.ts +5 -0
  274. package/src/code-execution/isolate/child-main.ts +132 -0
  275. package/src/code-execution/isolate/child.ts +327 -0
  276. package/src/code-execution/isolate/frames.ts +209 -0
  277. package/src/code-execution/isolate/output.ts +161 -0
  278. package/src/code-execution/isolate/prelude.ts +409 -0
  279. package/src/code-execution/isolate/protocol.ts +240 -0
  280. package/src/code-execution/isolate/render.ts +230 -0
  281. package/src/code-execution/isolate/runner.ts +911 -0
  282. package/src/code-execution/isolate/scripts.ts +479 -0
  283. package/src/code-execution/quickjs.wasm +0 -0
  284. package/src/code-execution/quickjs.wasm.LICENSES +149 -0
  285. package/src/code-execution/tool-definition.ts +236 -167
  286. package/src/deadline-timer.ts +1 -1
  287. package/src/framework.ts +4978 -2671
  288. package/src/gate/event-gate.ts +79 -17
  289. package/src/held-writes.ts +17 -3
  290. package/src/index.ts +32 -22
  291. package/src/mcpl/channel-registry.ts +1892 -471
  292. package/src/mcpl/conversation-router.ts +26 -72
  293. package/src/mcpl/convert-block.ts +9 -5
  294. package/src/mcpl/inbound-source.ts +131 -0
  295. package/src/mcpl/index.ts +4 -2
  296. package/src/mcpl/log-value.ts +9 -0
  297. package/src/mcpl/modern-connection.ts +162 -53
  298. package/src/mcpl/prose-grammar.ts +4 -5
  299. package/src/mcpl/protocol-family.ts +200 -22
  300. package/src/mcpl/push-coalescer.ts +306 -62
  301. package/src/mcpl/push-handler.ts +12 -54
  302. package/src/mcpl/reference-fetcher.ts +4 -4
  303. package/src/mcpl/server-connection.ts +180 -79
  304. package/src/mcpl/tags.ts +36 -0
  305. package/src/mcpl/tool-result-normalize.ts +2 -1
  306. package/src/mcpl/transport.ts +162 -33
  307. package/src/mcpl/types.ts +23 -6
  308. package/src/module-registry.ts +92 -13
  309. package/src/modules/discord/index.ts +8 -13
  310. package/src/modules/history/index.ts +25 -3
  311. package/src/modules/history/semantic.ts +29 -6
  312. package/src/modules/index.ts +1 -0
  313. package/src/modules/unknown-tool.ts +4 -1
  314. package/src/modules/workspace/branch-intent.ts +3 -1
  315. package/src/modules/workspace/edit-plan.ts +954 -0
  316. package/src/modules/workspace/edit-text.ts +618 -0
  317. package/src/modules/workspace/effects.ts +70 -19
  318. package/src/modules/workspace/index.ts +2293 -650
  319. package/src/modules/workspace/observe.ts +465 -56
  320. package/src/modules/workspace/reconcile.ts +14 -7
  321. package/src/modules/workspace/text.ts +68 -0
  322. package/src/modules/workspace/types.ts +211 -6
  323. package/src/modules/workspace/watcher.ts +3 -2
  324. package/src/operator-log.ts +47 -19
  325. package/src/recovery/discord-awareness-outbox.ts +1500 -356
  326. package/src/recovery/offline-branch.ts +189 -55
  327. package/src/recovery/recover-cli.ts +25 -4
  328. package/src/send-tools.ts +11 -0
  329. package/src/timezone.ts +4 -2
  330. package/src/tool-image-ledger.ts +62 -8
  331. package/src/tool-result-guard.ts +18 -15
  332. package/src/tool-result-history.ts +3 -2
  333. package/src/tune-out/coordinator.ts +166 -45
  334. package/src/types/agent.ts +32 -6
  335. package/src/types/events.ts +66 -9
  336. package/src/types/framework.ts +69 -62
  337. package/src/types/module.ts +40 -8
  338. package/src/types/trace.ts +121 -15
  339. package/src/usage/types.ts +16 -0
  340. package/src/usage/usage-tracker.ts +86 -43
  341. package/dist/src/code-execution/py-runner.d.ts +0 -191
  342. package/dist/src/code-execution/py-runner.d.ts.map +0 -1
  343. package/dist/src/code-execution/py-runner.js +0 -655
  344. package/dist/src/code-execution/py-runner.js.map +0 -1
  345. package/dist/src/code-execution/runtime-py.d.ts +0 -50
  346. package/dist/src/code-execution/runtime-py.d.ts.map +0 -1
  347. package/dist/src/code-execution/runtime-py.js +0 -677
  348. package/dist/src/code-execution/runtime-py.js.map +0 -1
  349. package/dist/src/mcpl/prose-stream-router.d.ts +0 -88
  350. package/dist/src/mcpl/prose-stream-router.d.ts.map +0 -1
  351. package/dist/src/mcpl/prose-stream-router.js +0 -291
  352. package/dist/src/mcpl/prose-stream-router.js.map +0 -1
  353. package/src/code-execution/py-runner.ts +0 -791
  354. package/src/code-execution/runtime-py.ts +0 -677
  355. package/src/mcpl/prose-stream-router.ts +0 -268
@@ -0,0 +1,315 @@
1
+ /**
2
+ * A script's child: one process per script, which runs it in the engine and
3
+ * answers the engine's four imports. It takes its start from the parent's
4
+ * first frame, sends each tool call to the parent and settles it with the
5
+ * parent's answer, flushes the output in bounded batches, and reports how the
6
+ * script ended. A crash it can't report: the parent sees that the child ended
7
+ * without saying how.
8
+ *
9
+ * Stopping: the parent creates the stop file and sends a stop frame. A
10
+ * computing guest's interrupt import sees the file, checked at most every few
11
+ * milliseconds, so a stop reaches a spinning guest without its event loop; an
12
+ * idle guest's child reads the frame. Why the stop was asked is the parent's
13
+ * to say, so the child reports only that the script stopped.
14
+ */
15
+ import { existsSync } from 'node:fs';
16
+ import { MAX_RESULT_DEPTH } from '../engine.js';
17
+ import { argumentsRefusal, MAX_CALLS_IN_FLIGHT, RESULT_TOO_LARGE, wakeLimitRefusal, wakeRefusal } from './protocol.js';
18
+ import { OutputBatch } from './output.js';
19
+ import { bounded, glimpse, NAME_CHARS, VALUE_CHARS } from './render.js';
20
+ import { preludeSource, scriptCall, scriptFrames, WAKE_CALL_NAME } from './prelude.js';
21
+ /** How often, at most, the interrupt import looks for the stop file. */
22
+ export const STOP_CHECK_MS = 3;
23
+ /**
24
+ * The filename of the one line that starts the script, `await __run(...)`.
25
+ * The script's own frames carry `<input>`, the source name QuickJS gives the
26
+ * async function it's compiled into (SCRIPT_LINE_OFFSET).
27
+ */
28
+ const SCRIPT_FILENAME = 'script.js';
29
+ /** The value's JSON from the engine's JSON of the prelude's text: a string, so one parse gives it, and anything else is given as it came. */
30
+ function valueJson(json) {
31
+ try {
32
+ const text = JSON.parse(json);
33
+ return typeof text === 'string' ? text : json;
34
+ }
35
+ catch {
36
+ return json;
37
+ }
38
+ }
39
+ /** Run the script `start` names to its end. Resolves once its ending is sent, or when the parent closes the channel. */
40
+ export async function runChild(io, start, loadEngine) {
41
+ const batch = new OutputBatch();
42
+ /** The calls the guest waits on, by id: their tools' names. */
43
+ const outstanding = new Map();
44
+ /** Calls answered here, without going out: their arguments were too large to send. */
45
+ const local = [];
46
+ /**
47
+ * While a result settles, the calls the guest's jobs make are held, and go
48
+ * out after that result's `seen`, which says whether the result fit: the
49
+ * parent then frees the answered call's place before it counts the next.
50
+ * A result the engine drops reaches no script code, and what code QuickJS
51
+ * still runs as the stop lands, a stack hook building the stop's error,
52
+ * can't make a call, since the engine refuses `__host` once stopped: its
53
+ * settle holds none.
54
+ */
55
+ let held = null;
56
+ /** Wakes sent, which the script's cap counts. */
57
+ let wakesSent = 0;
58
+ let stopped = false;
59
+ let lastFlush = io.now();
60
+ let lastStopCheck = -Infinity;
61
+ let lastParentCheck = -Infinity;
62
+ /** Its parent has been seen gone, so the child has ended its process, or stopped its guest. */
63
+ let orphan = false;
64
+ const flush = () => {
65
+ lastFlush = io.now();
66
+ for (const text of batch.flush())
67
+ io.send({ t: 'out', text });
68
+ };
69
+ const slots = {
70
+ hostCall(callId, name, argsJson) {
71
+ outstanding.set(callId, name);
72
+ // What the host won't take is refused here, before a frame is built,
73
+ // and by the parent again, since the child is untrusted. A call that
74
+ // passes always fits a frame, which carries its arguments escaped, at
75
+ // most six bytes for each of theirs.
76
+ const wake = name === WAKE_CALL_NAME;
77
+ // A wake past the script's cap is refused too, after its size, so one
78
+ // refused for its size uses none of the script's wakes.
79
+ const refusal = wake
80
+ ? (wakeRefusal(argsJson) ?? (wakesSent >= start.maxWakes ? wakeLimitRefusal(start.maxWakes) : null))
81
+ : argumentsRefusal(name, argsJson);
82
+ if (refusal) {
83
+ // The slot can't settle the call from inside the engine: it's answered
84
+ // as soon as the engine returns.
85
+ local.push({ id: callId, json: JSON.stringify(refusal) });
86
+ return;
87
+ }
88
+ if (wake)
89
+ wakesSent += 1;
90
+ // What the script wrote before the call reaches the host before it does.
91
+ if (batch.unflushed > 0)
92
+ flush();
93
+ const call = { t: 'call', id: callId, name, args: argsJson };
94
+ // A wake takes no place among the calls in flight, so it needn't wait for a seen.
95
+ if (held === null || wake)
96
+ io.send(call);
97
+ else if (held.length < MAX_CALLS_IN_FLIGHT)
98
+ held.push(call);
99
+ else {
100
+ // A guest held to the prelude has at most that many calls out. One
101
+ // that makes more, its promises replaced, would have them held
102
+ // without bound: the rest go out at once, which the parent takes as
103
+ // the protocol break it is, and the guest is stopped.
104
+ stopped = true;
105
+ io.send(call);
106
+ }
107
+ },
108
+ interrupt() {
109
+ const t = io.now();
110
+ if (!stopped && t - lastStopCheck >= STOP_CHECK_MS) {
111
+ lastStopCheck = t;
112
+ stopped = existsSync(start.stopFile);
113
+ }
114
+ if (batch.unflushed > 0 && t - lastFlush >= start.flushMs)
115
+ flush();
116
+ return stopped;
117
+ },
118
+ supervise() {
119
+ // A guest that computes doesn't let the child see its parent go, so
120
+ // that's checked at the engine's interrupt checks, at most once a stop
121
+ // check, a stop's included: a guest can keep a stop from ending it,
122
+ // since QuickJS drops a stop it takes inside a stack hook or an
123
+ // iterator's return, and only the parent kills a child that runs on.
124
+ // The engine calls this first, so an orphan ends its process at once
125
+ // rather than stop its guest. Output waiting to be sent goes with the
126
+ // process: the parent that would read it is gone, and a write to it
127
+ // could fail or block.
128
+ const t = io.now();
129
+ if (orphan || t - lastParentCheck < STOP_CHECK_MS)
130
+ return;
131
+ lastParentCheck = t;
132
+ if (!io.parentGone?.())
133
+ return;
134
+ orphan = true;
135
+ io.orphaned?.();
136
+ stopped = true;
137
+ },
138
+ output(_stream, text) {
139
+ if (batch.write(text) || io.now() - lastFlush >= start.flushMs)
140
+ flush();
141
+ },
142
+ };
143
+ const engine = await loadEngine({ memoryMaxBytes: start.memoryMaxBytes, ...(start.maxStackBytes === undefined ? {} : { maxStackBytes: start.maxStackBytes }) }, slots);
144
+ // The loop's own failure, if one is leaving it: dispose()'s, after it, is the lesser news.
145
+ let failing = false;
146
+ try {
147
+ // The script's own ending: the first terminal state. Calls still in flight
148
+ // when it ends are waited for, so each outcome reaches the record, and their
149
+ // later states don't change how the script ended: a stop then ends the
150
+ // wait, and the script's own ending is what's reported. A failure once the
151
+ // script ran (`failed`: an exception escaped its promises) ends the run at
152
+ // once, past an ending it kept: the engine takes nothing more.
153
+ const terminal = (s) => s.kind === 'fulfilled' || s.kind === 'rejected';
154
+ let ending = { kind: 'pending' };
155
+ let interrupted = false;
156
+ const after = (next) => {
157
+ if (next.kind === 'interrupted')
158
+ interrupted = true;
159
+ if (next.kind === 'failed' || !terminal(ending))
160
+ ending = next;
161
+ };
162
+ const over = () => interrupted || ending.kind === 'failed';
163
+ const settleLocal = () => {
164
+ while (local.length > 0 && !over()) {
165
+ const { id, json } = local.shift();
166
+ outstanding.delete(id);
167
+ after(engine.settle(id, false, json, json));
168
+ }
169
+ };
170
+ after(engine.start(preludeSource(start.tools), scriptCall(start.script), SCRIPT_FILENAME));
171
+ settleLocal();
172
+ for (;;) {
173
+ if (over() || stopped || outstanding.size === 0) {
174
+ flush();
175
+ // The value, or a failure's message and stack, cut as a return shows
176
+ // them, so the ending's frame always fits whatever the script made.
177
+ if (ending.kind === 'fulfilled') {
178
+ // The prelude's run resolves to its value's JSON text, which the engine
179
+ // gives as a JSON string: one layer off is the value's JSON.
180
+ io.send(ending.json === undefined ? { t: 'end', how: 'finished' } : { t: 'end', how: 'finished', value: bounded(valueJson(ending.json), VALUE_CHARS) });
181
+ }
182
+ else if (ending.kind === 'rejected' || ending.kind === 'failed') {
183
+ // The script's frames go apart from the name and message, each cut
184
+ // on its own, so a cut never breaks which is which. Every failure's
185
+ // stack is QuickJS's own, or one the script set, and is put as the
186
+ // agent reads it here (scriptFrames), whether the script threw it or
187
+ // it escaped the script's promises, and cut as it's read: the frames
188
+ // go as scriptFrames gives them, cut once.
189
+ const frames = ending.stack ? scriptFrames(ending.stack, VALUE_CHARS) : '';
190
+ io.send({
191
+ t: 'end',
192
+ how: 'failed',
193
+ error: {
194
+ name: bounded(ending.name, NAME_CHARS),
195
+ message: bounded(ending.message, VALUE_CHARS),
196
+ ...(frames ? { stack: frames } : {}),
197
+ },
198
+ });
199
+ }
200
+ else if (interrupted || stopped) {
201
+ io.send({ t: 'end', how: 'stopped' });
202
+ }
203
+ else {
204
+ io.send({
205
+ t: 'end',
206
+ how: 'failed',
207
+ stalled: true,
208
+ error: {
209
+ name: 'Error',
210
+ message: 'The script is waiting on a promise that nothing can settle: no tool call is pending, and there are no timers here.',
211
+ },
212
+ });
213
+ }
214
+ return;
215
+ }
216
+ // The guest is idle until a call is answered: send its output so far.
217
+ flush();
218
+ const message = await io.next();
219
+ if (message === null)
220
+ return; // the parent is gone, and with it anyone to tell
221
+ if (message.t === 'stop') {
222
+ stopped = true;
223
+ continue;
224
+ }
225
+ if (message.t !== 'result' || !outstanding.has(message.id))
226
+ continue;
227
+ const name = outstanding.get(message.id);
228
+ outstanding.delete(message.id);
229
+ // A result the guest can't take, too large for its memory, nested too
230
+ // deep or not parsed, reaches the script as ResultTooLarge, made here,
231
+ // and the parent hears it wasn't seen. An answer that isn't ok is an
232
+ // error the host gave in the result's place, such as a refusal.
233
+ // The call as the script wrote it: a wake is wake_agent.
234
+ const called = name === WAKE_CALL_NAME ? 'wake_agent' : name;
235
+ // An error the host gave in the result's place keeps its name, such as
236
+ // a refusal's, and its message's start: whether the call ran is in
237
+ // them, read here, outside the guest.
238
+ const unfit = message.ok
239
+ ? JSON.stringify({
240
+ name: RESULT_TOO_LARGE,
241
+ message: `${called}'s result, ${message.json.length} bytes, couldn't be received by this script: it was ${unfitWhy(true)}; ` +
242
+ 'the call took effect, and none of its result reached the script. Calling it again would do the call again, its effect included, and likely bring the same result, so if the call only reads, ask the tool for less if it can',
243
+ bytes: message.json.length,
244
+ })
245
+ : unfitAnswer(called, message.json);
246
+ held = [];
247
+ let state;
248
+ let calls;
249
+ try {
250
+ state = engine.settle(message.id, message.ok, message.json, unfit);
251
+ }
252
+ finally {
253
+ calls = held;
254
+ held = null;
255
+ }
256
+ // A result that reached the script freed its call's place, as the
257
+ // prelude has it, and its seen says so. One that never reached it
258
+ // (`dropped`) has no seen: the script never had it, so the prelude
259
+ // never freed its place, and what code QuickJS still runs as the stop
260
+ // lands can't reach the host, since the engine refuses `__host` once
261
+ // stopped. The run's end counts the answer as one the script didn't
262
+ // read (Gladys-2592, room-203 #159239, #162129).
263
+ if (!state.dropped)
264
+ io.send(state.unfit ? { t: 'seen', id: message.id, unfit: true } : { t: 'seen', id: message.id });
265
+ for (const call of calls)
266
+ io.send(call);
267
+ after(state);
268
+ settleLocal();
269
+ }
270
+ }
271
+ catch (err) {
272
+ failing = true;
273
+ throw err;
274
+ }
275
+ finally {
276
+ try {
277
+ engine.dispose();
278
+ }
279
+ catch (err) {
280
+ if (!failing)
281
+ throw err;
282
+ }
283
+ }
284
+ }
285
+ /** An error the host gave in a result's place, which the guest couldn't take: its name and its message's start, read in the child. */
286
+ function unfitAnswer(tool, json) {
287
+ let name = RESULT_TOO_LARGE;
288
+ let message = '';
289
+ let parsed = false;
290
+ try {
291
+ const answer = JSON.parse(new TextDecoder().decode(json));
292
+ parsed = true;
293
+ if (typeof answer.name === 'string' && answer.name)
294
+ name = bounded(answer.name, NAME_CHARS);
295
+ if (typeof answer.message === 'string')
296
+ message = glimpse(answer.message, UNFIT_GLIMPSE_CHARS);
297
+ }
298
+ catch {
299
+ // Not readable here either: only its size and the tool are known.
300
+ }
301
+ return JSON.stringify({
302
+ name,
303
+ message: `${message ? `${message} ` : `${tool}'s answer `}(the host's answer, ${json.length} bytes, couldn't be received by this script whole: it was ${unfitWhy(!parsed)})`,
304
+ bytes: json.length,
305
+ });
306
+ }
307
+ /** Why the guest couldn't take an answer: what the engine refuses, less what the child has ruled out. */
308
+ function unfitWhy(couldBeJson) {
309
+ return couldBeJson
310
+ ? `too large for its memory, nested deeper than ${MAX_RESULT_DEPTH} levels, or not valid JSON`
311
+ : `too large for its memory, or nested deeper than ${MAX_RESULT_DEPTH} levels`;
312
+ }
313
+ /** How much of an unfit answer's message reaches the script. */
314
+ const UNFIT_GLIMPSE_CHARS = 2000;
315
+ //# sourceMappingURL=child.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child.js","sourceRoot":"","sources":["../../../../src/code-execution/isolate/child.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Length-prefixed frames between a script's parent and its child: four bytes
3
+ * of big-endian length, then that many bytes of body. The parent writes to the
4
+ * child's stdin and reads the child's fd 3.
5
+ *
6
+ * A body's first byte says what it holds:
7
+ * - `JSON_KIND`: a message as UTF-8 JSON. Every frame from a child is one.
8
+ * - `RESULT_KIND`: a call's result for the guest, from the parent: whether it
9
+ * resolves or rejects, the call's id, and the result's JSON as UTF-8 bytes,
10
+ * which the child hands the engine as they are, with no second parse and no
11
+ * string copy (the path the memory budget was measured on).
12
+ *
13
+ * The decoder is the only way bytes from a child become values in the parent,
14
+ * so it bounds what a child can make the parent hold: a frame longer than its
15
+ * limit, of a kind it doesn't take, not JSON, or holding more values than its
16
+ * limit (counted before it's parsed), is a protocol error, and the parent ends
17
+ * the script as crashed rather than reading on.
18
+ */
19
+ /** The largest frame from a child: a call's arguments or a batch of output. */
20
+ export declare const MAX_FRAME_BYTES: number;
21
+ export declare const JSON_KIND = 0;
22
+ export declare const RESULT_KIND = 1;
23
+ /** A frame that breaks the protocol: too long, of a kind not taken, not UTF-8, not JSON, holding too many values, or cut off when its stream ended. */
24
+ export declare class FrameError extends Error {
25
+ /** For a frame too long to encode: how long its body came to. */
26
+ readonly bytes: number | undefined;
27
+ constructor(message: string, bytes?: number);
28
+ }
29
+ /**
30
+ * The values in a JSON text, counted outside its strings: the top value, and
31
+ * each value inside an object or array. Counting stops once past `stopAfter`.
32
+ */
33
+ export declare function countJsonValues(text: string, stopAfter?: number): number;
34
+ /** A call's result as the child decodes it: the JSON's bytes, untouched. */
35
+ export interface ResultFrame {
36
+ t: 'result';
37
+ id: number;
38
+ ok: boolean;
39
+ json: Uint8Array;
40
+ }
41
+ /** One message as a JSON frame. One longer than `maxFrameBytes` throws a FrameError, and nothing is written. */
42
+ export declare function encodeFrame(message: unknown, maxFrameBytes?: number): Buffer;
43
+ /**
44
+ * A call's result as a result frame: the JSON's bytes follow a header of `ok`
45
+ * and the id. Written straight into the frame, so a result's bytes are held
46
+ * once, which the host's memory figure counts.
47
+ */
48
+ export declare function encodeResultFrame(id: number, ok: boolean, json: string, maxFrameBytes: number): Buffer;
49
+ /** How much a result frame's body holds beyond its JSON. */
50
+ export declare const RESULT_FRAME_OVERHEAD: number;
51
+ /**
52
+ * Bytes in, whole frames' values out. Holds at most one frame's bytes plus its
53
+ * header: a header naming more than `maxFrameBytes` throws before any of that
54
+ * frame's body is kept, and once a header names its body's length, the body
55
+ * is one buffer of that length, which each chunk is copied into. So however
56
+ * the bytes arrive, one at a time included, the decoder keeps no chunk of
57
+ * them. Takes result frames only if asked to: a parent's decoder takes JSON
58
+ * alone.
59
+ */
60
+ export declare class FrameDecoder {
61
+ private readonly maxFrameBytes;
62
+ private readonly takesResults;
63
+ /** The most values a JSON frame may hold, counted before it's parsed. */
64
+ private readonly maxValues;
65
+ private readonly header;
66
+ private headerFilled;
67
+ private body;
68
+ private bodyFilled;
69
+ private broken;
70
+ constructor(maxFrameBytes?: number, takesResults?: boolean,
71
+ /** The most values a JSON frame may hold, counted before it's parsed. */
72
+ maxValues?: number);
73
+ /** The values of every frame `chunk` completes, in order. Throws the same FrameError from then on, once one frame was bad. */
74
+ push(chunk: Buffer): unknown[];
75
+ /** At the stream's end: throws if a frame was begun and not finished. */
76
+ end(): void;
77
+ private decode;
78
+ private fail;
79
+ }
80
+ //# sourceMappingURL=frames.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../../../../src/code-execution/isolate/frames.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,+EAA+E;AAC/E,eAAO,MAAM,eAAe,QAAmB,CAAC;AAGhD,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,eAAO,MAAM,WAAW,IAAI,CAAC;AAI7B,uJAAuJ;AACvJ,qBAAa,UAAW,SAAQ,KAAK;IACnC,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAEnC,YAAY,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAI1C;CACF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,SAAW,GAAG,MAAM,CAqB1E;AAED,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,QAAQ,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;CAClB;AAYD,gHAAgH;AAChH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,GAAE,MAAwB,GAAG,MAAM,CAO7F;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAYtG;AAED,4DAA4D;AAC5D,eAAO,MAAM,qBAAqB,QAAsB,CAAC;AAEzD;;;;;;;;GAQG;AACH,qBAAa,YAAY;IAQrB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,yEAAyE;IACzE,OAAO,CAAC,QAAQ,CAAC,SAAS;IAV5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IACrD,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,MAAM,CAA2B;IAEzC,YACmB,aAAa,GAAE,MAAwB,EACvC,YAAY,UAAQ;IACrC,yEAAyE;IACxD,SAAS,SAAW,EACnC;IAEJ,8HAA8H;IAC9H,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,CA8B7B;IAED,yEAAyE;IACzE,GAAG,IAAI,IAAI,CAKV;IAED,OAAO,CAAC,MAAM;IAsBd,OAAO,CAAC,IAAI;CAKb"}
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Length-prefixed frames between a script's parent and its child: four bytes
3
+ * of big-endian length, then that many bytes of body. The parent writes to the
4
+ * child's stdin and reads the child's fd 3.
5
+ *
6
+ * A body's first byte says what it holds:
7
+ * - `JSON_KIND`: a message as UTF-8 JSON. Every frame from a child is one.
8
+ * - `RESULT_KIND`: a call's result for the guest, from the parent: whether it
9
+ * resolves or rejects, the call's id, and the result's JSON as UTF-8 bytes,
10
+ * which the child hands the engine as they are, with no second parse and no
11
+ * string copy (the path the memory budget was measured on).
12
+ *
13
+ * The decoder is the only way bytes from a child become values in the parent,
14
+ * so it bounds what a child can make the parent hold: a frame longer than its
15
+ * limit, of a kind it doesn't take, not JSON, or holding more values than its
16
+ * limit (counted before it's parsed), is a protocol error, and the parent ends
17
+ * the script as crashed rather than reading on.
18
+ */
19
+ /** The largest frame from a child: a call's arguments or a batch of output. */
20
+ export const MAX_FRAME_BYTES = 64 * 1024 * 1024;
21
+ const HEADER_BYTES = 4;
22
+ export const JSON_KIND = 0;
23
+ export const RESULT_KIND = 1;
24
+ /** A result body's own header: its kind, `ok`, and the call's id. */
25
+ const RESULT_HEADER_BYTES = 1 + 1 + 4;
26
+ /** A frame that breaks the protocol: too long, of a kind not taken, not UTF-8, not JSON, holding too many values, or cut off when its stream ended. */
27
+ export class FrameError extends Error {
28
+ /** For a frame too long to encode: how long its body came to. */
29
+ bytes;
30
+ constructor(message, bytes) {
31
+ super(message);
32
+ this.name = 'FrameError';
33
+ this.bytes = bytes;
34
+ }
35
+ }
36
+ /**
37
+ * The values in a JSON text, counted outside its strings: the top value, and
38
+ * each value inside an object or array. Counting stops once past `stopAfter`.
39
+ */
40
+ export function countJsonValues(text, stopAfter = Infinity) {
41
+ let values = 1;
42
+ let inString = false;
43
+ for (let i = 0; i < text.length; i++) {
44
+ const c = text.charCodeAt(i);
45
+ if (inString) {
46
+ if (c === 0x5c)
47
+ i++;
48
+ else if (c === 0x22)
49
+ inString = false;
50
+ }
51
+ else if (c === 0x22) {
52
+ inString = true;
53
+ }
54
+ else if (c === 0x7b || c === 0x5b) {
55
+ // An object or array holds a first value unless it closes at once.
56
+ let j = i + 1;
57
+ while (j < text.length && (text.charCodeAt(j) === 0x20 || text.charCodeAt(j) === 0x0a || text.charCodeAt(j) === 0x0d || text.charCodeAt(j) === 0x09))
58
+ j++;
59
+ const next = text.charCodeAt(j);
60
+ if (next !== 0x7d && next !== 0x5d && ++values > stopAfter)
61
+ return values;
62
+ }
63
+ else if (c === 0x2c) {
64
+ if (++values > stopAfter)
65
+ return values;
66
+ }
67
+ }
68
+ return values;
69
+ }
70
+ function frame(body, maxFrameBytes) {
71
+ if (body.length > maxFrameBytes) {
72
+ throw new FrameError(`a frame of ${body.length} bytes is longer than the ${maxFrameBytes} the protocol allows`, body.length);
73
+ }
74
+ const out = Buffer.allocUnsafe(HEADER_BYTES + body.length);
75
+ out.writeUInt32BE(body.length, 0);
76
+ body.copy(out, HEADER_BYTES);
77
+ return out;
78
+ }
79
+ /** One message as a JSON frame. One longer than `maxFrameBytes` throws a FrameError, and nothing is written. */
80
+ export function encodeFrame(message, maxFrameBytes = MAX_FRAME_BYTES) {
81
+ const json = JSON.stringify(message);
82
+ if (json === undefined)
83
+ throw new FrameError('a frame must hold a JSON value');
84
+ const body = Buffer.allocUnsafe(1 + Buffer.byteLength(json, 'utf8'));
85
+ body[0] = JSON_KIND;
86
+ body.write(json, 1, 'utf8');
87
+ return frame(body, maxFrameBytes);
88
+ }
89
+ /**
90
+ * A call's result as a result frame: the JSON's bytes follow a header of `ok`
91
+ * and the id. Written straight into the frame, so a result's bytes are held
92
+ * once, which the host's memory figure counts.
93
+ */
94
+ export function encodeResultFrame(id, ok, json, maxFrameBytes) {
95
+ const bodyLength = RESULT_HEADER_BYTES + Buffer.byteLength(json, 'utf8');
96
+ if (bodyLength > maxFrameBytes) {
97
+ throw new FrameError(`a frame of ${bodyLength} bytes is longer than the ${maxFrameBytes} the protocol allows`, bodyLength);
98
+ }
99
+ const out = Buffer.allocUnsafe(HEADER_BYTES + bodyLength);
100
+ out.writeUInt32BE(bodyLength, 0);
101
+ out[HEADER_BYTES] = RESULT_KIND;
102
+ out[HEADER_BYTES + 1] = ok ? 1 : 0;
103
+ out.writeUInt32BE(id >>> 0, HEADER_BYTES + 2);
104
+ out.write(json, HEADER_BYTES + RESULT_HEADER_BYTES, 'utf8');
105
+ return out;
106
+ }
107
+ /** How much a result frame's body holds beyond its JSON. */
108
+ export const RESULT_FRAME_OVERHEAD = RESULT_HEADER_BYTES;
109
+ /**
110
+ * Bytes in, whole frames' values out. Holds at most one frame's bytes plus its
111
+ * header: a header naming more than `maxFrameBytes` throws before any of that
112
+ * frame's body is kept, and once a header names its body's length, the body
113
+ * is one buffer of that length, which each chunk is copied into. So however
114
+ * the bytes arrive, one at a time included, the decoder keeps no chunk of
115
+ * them. Takes result frames only if asked to: a parent's decoder takes JSON
116
+ * alone.
117
+ */
118
+ export class FrameDecoder {
119
+ maxFrameBytes;
120
+ takesResults;
121
+ maxValues;
122
+ header = Buffer.alloc(HEADER_BYTES);
123
+ headerFilled = 0;
124
+ body = null;
125
+ bodyFilled = 0;
126
+ broken = null;
127
+ constructor(maxFrameBytes = MAX_FRAME_BYTES, takesResults = false,
128
+ /** The most values a JSON frame may hold, counted before it's parsed. */
129
+ maxValues = Infinity) {
130
+ this.maxFrameBytes = maxFrameBytes;
131
+ this.takesResults = takesResults;
132
+ this.maxValues = maxValues;
133
+ }
134
+ /** The values of every frame `chunk` completes, in order. Throws the same FrameError from then on, once one frame was bad. */
135
+ push(chunk) {
136
+ if (this.broken)
137
+ throw this.broken;
138
+ const values = [];
139
+ let at = 0;
140
+ while (at < chunk.length) {
141
+ if (this.body === null) {
142
+ const n = Math.min(HEADER_BYTES - this.headerFilled, chunk.length - at);
143
+ chunk.copy(this.header, this.headerFilled, at, at + n);
144
+ this.headerFilled += n;
145
+ at += n;
146
+ if (this.headerFilled < HEADER_BYTES)
147
+ break;
148
+ const length = this.header.readUInt32BE(0);
149
+ if (length > this.maxFrameBytes) {
150
+ return this.fail(`a frame announced ${length} bytes, more than the ${this.maxFrameBytes} the protocol allows`);
151
+ }
152
+ if (length === 0)
153
+ return this.fail('a frame was empty');
154
+ this.body = Buffer.allocUnsafe(length);
155
+ this.bodyFilled = 0;
156
+ }
157
+ const n = Math.min(this.body.length - this.bodyFilled, chunk.length - at);
158
+ chunk.copy(this.body, this.bodyFilled, at, at + n);
159
+ this.bodyFilled += n;
160
+ at += n;
161
+ if (this.bodyFilled < this.body.length)
162
+ break;
163
+ const body = this.body;
164
+ this.body = null;
165
+ this.headerFilled = 0;
166
+ values.push(this.decode(body));
167
+ }
168
+ return values;
169
+ }
170
+ /** At the stream's end: throws if a frame was begun and not finished. */
171
+ end() {
172
+ if (this.broken)
173
+ throw this.broken;
174
+ if (this.headerFilled > 0 || this.body !== null) {
175
+ this.fail(`the stream ended inside a frame, with ${this.body === null ? this.headerFilled : this.bodyFilled} of its bytes read`);
176
+ }
177
+ }
178
+ decode(body) {
179
+ if (body[0] === RESULT_KIND && this.takesResults) {
180
+ if (body.length < RESULT_HEADER_BYTES)
181
+ return this.fail('a result frame was shorter than its header');
182
+ const result = { t: 'result', id: body.readUInt32BE(2), ok: body[1] === 1, json: body.subarray(RESULT_HEADER_BYTES) };
183
+ return result;
184
+ }
185
+ if (body[0] !== JSON_KIND)
186
+ return this.fail(`a frame was of kind ${body[0]}, which this side doesn't take`);
187
+ let text;
188
+ try {
189
+ // A byte-order mark is kept, so it fails JSON.parse as the text it is.
190
+ text = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(body.subarray(1));
191
+ }
192
+ catch {
193
+ return this.fail('a frame was not UTF-8');
194
+ }
195
+ if (countJsonValues(text, this.maxValues) > this.maxValues)
196
+ return this.fail(`a frame held more than ${this.maxValues} values`);
197
+ try {
198
+ return JSON.parse(text);
199
+ }
200
+ catch {
201
+ return this.fail('a frame was not JSON');
202
+ }
203
+ }
204
+ fail(message) {
205
+ this.broken = new FrameError(message);
206
+ this.body = null;
207
+ throw this.broken;
208
+ }
209
+ }
210
+ //# sourceMappingURL=frames.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frames.js","sourceRoot":"","sources":["../../../../src/code-execution/isolate/frames.ts"],"names":[],"mappings":"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"}