@smthrs/harness 0.0.0-stage → 1.0.0-rc.3

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 (476) hide show
  1. package/CHANGELOG.md +387 -0
  2. package/LICENSE +21 -0
  3. package/README.md +138 -2
  4. package/dist/cjs/AgentEvent.d.ts +3092 -0
  5. package/dist/cjs/AgentEvent.d.ts.map +1 -0
  6. package/dist/cjs/AgentEvent.js +1116 -0
  7. package/dist/cjs/AgentEvent.js.map +7 -0
  8. package/dist/cjs/CallLedger.d.ts +378 -0
  9. package/dist/cjs/CallLedger.d.ts.map +1 -0
  10. package/dist/cjs/CallLedger.js +240 -0
  11. package/dist/cjs/CallLedger.js.map +7 -0
  12. package/dist/cjs/Cell.d.ts +774 -0
  13. package/dist/cjs/Cell.d.ts.map +1 -0
  14. package/dist/cjs/Cell.js +431 -0
  15. package/dist/cjs/Cell.js.map +7 -0
  16. package/dist/cjs/CellCalls.d.ts +115 -0
  17. package/dist/cjs/CellCalls.d.ts.map +1 -0
  18. package/dist/cjs/CellCalls.js +98 -0
  19. package/dist/cjs/CellCalls.js.map +7 -0
  20. package/dist/cjs/CellHistory.d.ts +102 -0
  21. package/dist/cjs/CellHistory.d.ts.map +1 -0
  22. package/dist/cjs/CellHistory.js +54 -0
  23. package/dist/cjs/CellHistory.js.map +7 -0
  24. package/dist/cjs/CellTurn.d.ts +1071 -0
  25. package/dist/cjs/CellTurn.d.ts.map +1 -0
  26. package/dist/cjs/CellTurn.js +2618 -0
  27. package/dist/cjs/CellTurn.js.map +7 -0
  28. package/dist/cjs/CellValidation.d.ts +94 -0
  29. package/dist/cjs/CellValidation.d.ts.map +1 -0
  30. package/dist/cjs/CellValidation.js +218 -0
  31. package/dist/cjs/CellValidation.js.map +7 -0
  32. package/dist/cjs/Compaction.d.ts +158 -0
  33. package/dist/cjs/Compaction.d.ts.map +1 -0
  34. package/dist/cjs/Compaction.js +189 -0
  35. package/dist/cjs/Compaction.js.map +7 -0
  36. package/dist/cjs/CompletionClaim.d.ts +801 -0
  37. package/dist/cjs/CompletionClaim.d.ts.map +1 -0
  38. package/dist/cjs/CompletionClaim.js +303 -0
  39. package/dist/cjs/CompletionClaim.js.map +7 -0
  40. package/dist/cjs/ContextWindow.d.ts +435 -0
  41. package/dist/cjs/ContextWindow.d.ts.map +1 -0
  42. package/dist/cjs/ContextWindow.js +319 -0
  43. package/dist/cjs/ContextWindow.js.map +7 -0
  44. package/dist/cjs/EngineLike.d.ts +546 -0
  45. package/dist/cjs/EngineLike.d.ts.map +1 -0
  46. package/dist/cjs/EngineLike.js +114 -0
  47. package/dist/cjs/EngineLike.js.map +7 -0
  48. package/dist/cjs/ExternalTranscript.d.ts +349 -0
  49. package/dist/cjs/ExternalTranscript.d.ts.map +1 -0
  50. package/dist/cjs/ExternalTranscript.js +826 -0
  51. package/dist/cjs/ExternalTranscript.js.map +7 -0
  52. package/dist/cjs/FailedCall.d.ts +132 -0
  53. package/dist/cjs/FailedCall.d.ts.map +1 -0
  54. package/dist/cjs/FailedCall.js +53 -0
  55. package/dist/cjs/FailedCall.js.map +7 -0
  56. package/dist/cjs/FlowBinding.d.ts +289 -0
  57. package/dist/cjs/FlowBinding.d.ts.map +1 -0
  58. package/dist/cjs/FlowBinding.js +251 -0
  59. package/dist/cjs/FlowBinding.js.map +7 -0
  60. package/dist/cjs/HarnessError.d.ts +57 -0
  61. package/dist/cjs/HarnessError.d.ts.map +1 -0
  62. package/dist/cjs/HarnessError.js +75 -0
  63. package/dist/cjs/HarnessError.js.map +7 -0
  64. package/dist/cjs/Judgement.d.ts +289 -0
  65. package/dist/cjs/Judgement.d.ts.map +1 -0
  66. package/dist/cjs/Judgement.js +240 -0
  67. package/dist/cjs/Judgement.js.map +7 -0
  68. package/dist/cjs/Monitor.d.ts +374 -0
  69. package/dist/cjs/Monitor.d.ts.map +1 -0
  70. package/dist/cjs/Monitor.js +233 -0
  71. package/dist/cjs/Monitor.js.map +7 -0
  72. package/dist/cjs/NarrowedCheck.d.ts +523 -0
  73. package/dist/cjs/NarrowedCheck.d.ts.map +1 -0
  74. package/dist/cjs/NarrowedCheck.js +263 -0
  75. package/dist/cjs/NarrowedCheck.js.map +7 -0
  76. package/dist/cjs/Notifications.d.ts +42 -0
  77. package/dist/cjs/Notifications.d.ts.map +1 -0
  78. package/dist/cjs/Notifications.js +177 -0
  79. package/dist/cjs/Notifications.js.map +7 -0
  80. package/dist/cjs/Plan.d.ts +127 -0
  81. package/dist/cjs/Plan.d.ts.map +1 -0
  82. package/dist/cjs/Plan.js +77 -0
  83. package/dist/cjs/Plan.js.map +7 -0
  84. package/dist/cjs/QuickJSSandbox.d.ts +151 -0
  85. package/dist/cjs/QuickJSSandbox.d.ts.map +1 -0
  86. package/dist/cjs/QuickJSSandbox.js +987 -0
  87. package/dist/cjs/QuickJSSandbox.js.map +7 -0
  88. package/dist/cjs/Relevance.d.ts +213 -0
  89. package/dist/cjs/Relevance.d.ts.map +1 -0
  90. package/dist/cjs/Relevance.js +183 -0
  91. package/dist/cjs/Relevance.js.map +7 -0
  92. package/dist/cjs/Sandbox.d.ts +637 -0
  93. package/dist/cjs/Sandbox.d.ts.map +1 -0
  94. package/dist/cjs/Sandbox.js +260 -0
  95. package/dist/cjs/Sandbox.js.map +7 -0
  96. package/dist/cjs/Steering.d.ts +464 -0
  97. package/dist/cjs/Steering.d.ts.map +1 -0
  98. package/dist/cjs/Steering.js +153 -0
  99. package/dist/cjs/Steering.js.map +7 -0
  100. package/dist/cjs/StructuredOutput.d.ts +252 -0
  101. package/dist/cjs/StructuredOutput.d.ts.map +1 -0
  102. package/dist/cjs/StructuredOutput.js +266 -0
  103. package/dist/cjs/StructuredOutput.js.map +7 -0
  104. package/dist/cjs/Sufficiency.d.ts +195 -0
  105. package/dist/cjs/Sufficiency.d.ts.map +1 -0
  106. package/dist/cjs/Sufficiency.js +110 -0
  107. package/dist/cjs/Sufficiency.js.map +7 -0
  108. package/dist/cjs/Supervisor.d.ts +719 -0
  109. package/dist/cjs/Supervisor.d.ts.map +1 -0
  110. package/dist/cjs/Supervisor.js +313 -0
  111. package/dist/cjs/Supervisor.js.map +7 -0
  112. package/dist/cjs/Tokens.d.ts +86 -0
  113. package/dist/cjs/Tokens.d.ts.map +1 -0
  114. package/dist/cjs/Tokens.js +72 -0
  115. package/dist/cjs/Tokens.js.map +7 -0
  116. package/dist/cjs/Transcript.d.ts +171 -0
  117. package/dist/cjs/Transcript.d.ts.map +1 -0
  118. package/dist/cjs/Transcript.js +342 -0
  119. package/dist/cjs/Transcript.js.map +7 -0
  120. package/dist/cjs/TruncatedOutput.d.ts +186 -0
  121. package/dist/cjs/TruncatedOutput.d.ts.map +1 -0
  122. package/dist/cjs/TruncatedOutput.js +143 -0
  123. package/dist/cjs/TruncatedOutput.js.map +7 -0
  124. package/dist/cjs/UnmovedTree.d.ts +113 -0
  125. package/dist/cjs/UnmovedTree.d.ts.map +1 -0
  126. package/dist/cjs/UnmovedTree.js +38 -0
  127. package/dist/cjs/UnmovedTree.js.map +7 -0
  128. package/dist/cjs/UnresolvedFailure.d.ts +196 -0
  129. package/dist/cjs/UnresolvedFailure.d.ts.map +1 -0
  130. package/dist/cjs/UnresolvedFailure.js +77 -0
  131. package/dist/cjs/UnresolvedFailure.js.map +7 -0
  132. package/dist/cjs/VacuousVerification.d.ts +237 -0
  133. package/dist/cjs/VacuousVerification.d.ts.map +1 -0
  134. package/dist/cjs/VacuousVerification.js +91 -0
  135. package/dist/cjs/VacuousVerification.js.map +7 -0
  136. package/dist/cjs/VariablesPanel.d.ts +117 -0
  137. package/dist/cjs/VariablesPanel.d.ts.map +1 -0
  138. package/dist/cjs/VariablesPanel.js +108 -0
  139. package/dist/cjs/VariablesPanel.js.map +7 -0
  140. package/dist/cjs/index.d.ts +172 -0
  141. package/dist/cjs/index.d.ts.map +1 -0
  142. package/dist/cjs/index.js +99 -0
  143. package/dist/cjs/index.js.map +7 -0
  144. package/dist/cjs/internal/bytes.d.ts +36 -0
  145. package/dist/cjs/internal/bytes.d.ts.map +1 -0
  146. package/dist/cjs/internal/bytes.js +57 -0
  147. package/dist/cjs/internal/bytes.js.map +7 -0
  148. package/dist/cjs/internal/cellPrompt.d.ts +122 -0
  149. package/dist/cjs/internal/cellPrompt.d.ts.map +1 -0
  150. package/dist/cjs/internal/cellPrompt.js +146 -0
  151. package/dist/cjs/internal/cellPrompt.js.map +7 -0
  152. package/dist/cjs/internal/compactable.d.ts +44 -0
  153. package/dist/cjs/internal/compactable.d.ts.map +1 -0
  154. package/dist/cjs/internal/compactable.js +56 -0
  155. package/dist/cjs/internal/compactable.js.map +7 -0
  156. package/dist/cjs/internal/compactionMarks.d.ts +278 -0
  157. package/dist/cjs/internal/compactionMarks.d.ts.map +1 -0
  158. package/dist/cjs/internal/compactionMarks.js +212 -0
  159. package/dist/cjs/internal/compactionMarks.js.map +7 -0
  160. package/dist/cjs/internal/demandText.d.ts +95 -0
  161. package/dist/cjs/internal/demandText.d.ts.map +1 -0
  162. package/dist/cjs/internal/demandText.js +70 -0
  163. package/dist/cjs/internal/demandText.js.map +7 -0
  164. package/dist/cjs/internal/elide.d.ts +109 -0
  165. package/dist/cjs/internal/elide.d.ts.map +1 -0
  166. package/dist/cjs/internal/elide.js +59 -0
  167. package/dist/cjs/internal/elide.js.map +7 -0
  168. package/dist/cjs/internal/frame.d.ts +463 -0
  169. package/dist/cjs/internal/frame.d.ts.map +1 -0
  170. package/dist/cjs/internal/frame.js +514 -0
  171. package/dist/cjs/internal/frame.js.map +7 -0
  172. package/dist/cjs/internal/nonNegativeSafeInt.d.ts +20 -0
  173. package/dist/cjs/internal/nonNegativeSafeInt.d.ts.map +1 -0
  174. package/dist/cjs/internal/nonNegativeSafeInt.js +29 -0
  175. package/dist/cjs/internal/nonNegativeSafeInt.js.map +7 -0
  176. package/dist/cjs/internal/paidUsage.d.ts +52 -0
  177. package/dist/cjs/internal/paidUsage.d.ts.map +1 -0
  178. package/dist/cjs/internal/paidUsage.js +70 -0
  179. package/dist/cjs/internal/paidUsage.js.map +7 -0
  180. package/dist/cjs/internal/printChannel.d.ts +233 -0
  181. package/dist/cjs/internal/printChannel.d.ts.map +1 -0
  182. package/dist/cjs/internal/printChannel.js +165 -0
  183. package/dist/cjs/internal/printChannel.js.map +7 -0
  184. package/dist/cjs/internal/printsObservation.d.ts +26 -0
  185. package/dist/cjs/internal/printsObservation.d.ts.map +1 -0
  186. package/dist/cjs/internal/printsObservation.js +27 -0
  187. package/dist/cjs/internal/printsObservation.js.map +7 -0
  188. package/dist/cjs/internal/refusal.d.ts +40 -0
  189. package/dist/cjs/internal/refusal.d.ts.map +1 -0
  190. package/dist/cjs/internal/refusal.js +45 -0
  191. package/dist/cjs/internal/refusal.js.map +7 -0
  192. package/dist/cjs/internal/supervision.d.ts +174 -0
  193. package/dist/cjs/internal/supervision.d.ts.map +1 -0
  194. package/dist/cjs/internal/supervision.js +402 -0
  195. package/dist/cjs/internal/supervision.js.map +7 -0
  196. package/dist/cjs/internal/unfinishedWork.d.ts +99 -0
  197. package/dist/cjs/internal/unfinishedWork.d.ts.map +1 -0
  198. package/dist/cjs/internal/unfinishedWork.js +80 -0
  199. package/dist/cjs/internal/unfinishedWork.js.map +7 -0
  200. package/dist/cjs/internal/unobservedCall.d.ts +112 -0
  201. package/dist/cjs/internal/unobservedCall.d.ts.map +1 -0
  202. package/dist/cjs/internal/unobservedCall.js +345 -0
  203. package/dist/cjs/internal/unobservedCall.js.map +7 -0
  204. package/dist/cjs/internal/untrustedData.d.ts +14 -0
  205. package/dist/cjs/internal/untrustedData.d.ts.map +1 -0
  206. package/dist/cjs/internal/untrustedData.js +30 -0
  207. package/dist/cjs/internal/untrustedData.js.map +7 -0
  208. package/dist/cjs/package.json +1 -0
  209. package/dist/esm/AgentEvent.d.ts +3092 -0
  210. package/dist/esm/AgentEvent.d.ts.map +1 -0
  211. package/dist/esm/AgentEvent.js +1610 -0
  212. package/dist/esm/AgentEvent.js.map +1 -0
  213. package/dist/esm/CallLedger.d.ts +378 -0
  214. package/dist/esm/CallLedger.d.ts.map +1 -0
  215. package/dist/esm/CallLedger.js +506 -0
  216. package/dist/esm/CallLedger.js.map +1 -0
  217. package/dist/esm/Cell.d.ts +774 -0
  218. package/dist/esm/Cell.d.ts.map +1 -0
  219. package/dist/esm/Cell.js +772 -0
  220. package/dist/esm/Cell.js.map +1 -0
  221. package/dist/esm/CellCalls.d.ts +115 -0
  222. package/dist/esm/CellCalls.d.ts.map +1 -0
  223. package/dist/esm/CellCalls.js +97 -0
  224. package/dist/esm/CellCalls.js.map +1 -0
  225. package/dist/esm/CellHistory.d.ts +102 -0
  226. package/dist/esm/CellHistory.d.ts.map +1 -0
  227. package/dist/esm/CellHistory.js +91 -0
  228. package/dist/esm/CellHistory.js.map +1 -0
  229. package/dist/esm/CellTurn.d.ts +1071 -0
  230. package/dist/esm/CellTurn.d.ts.map +1 -0
  231. package/dist/esm/CellTurn.js +3410 -0
  232. package/dist/esm/CellTurn.js.map +1 -0
  233. package/dist/esm/CellValidation.d.ts +94 -0
  234. package/dist/esm/CellValidation.d.ts.map +1 -0
  235. package/dist/esm/CellValidation.js +335 -0
  236. package/dist/esm/CellValidation.js.map +1 -0
  237. package/dist/esm/Compaction.d.ts +158 -0
  238. package/dist/esm/Compaction.d.ts.map +1 -0
  239. package/dist/esm/Compaction.js +216 -0
  240. package/dist/esm/Compaction.js.map +1 -0
  241. package/dist/esm/CompletionClaim.d.ts +801 -0
  242. package/dist/esm/CompletionClaim.d.ts.map +1 -0
  243. package/dist/esm/CompletionClaim.js +833 -0
  244. package/dist/esm/CompletionClaim.js.map +1 -0
  245. package/dist/esm/ContextWindow.d.ts +435 -0
  246. package/dist/esm/ContextWindow.d.ts.map +1 -0
  247. package/dist/esm/ContextWindow.js +427 -0
  248. package/dist/esm/ContextWindow.js.map +1 -0
  249. package/dist/esm/EngineLike.d.ts +546 -0
  250. package/dist/esm/EngineLike.d.ts.map +1 -0
  251. package/dist/esm/EngineLike.js +218 -0
  252. package/dist/esm/EngineLike.js.map +1 -0
  253. package/dist/esm/ExternalTranscript.d.ts +349 -0
  254. package/dist/esm/ExternalTranscript.d.ts.map +1 -0
  255. package/dist/esm/ExternalTranscript.js +987 -0
  256. package/dist/esm/ExternalTranscript.js.map +1 -0
  257. package/dist/esm/FailedCall.d.ts +132 -0
  258. package/dist/esm/FailedCall.d.ts.map +1 -0
  259. package/dist/esm/FailedCall.js +131 -0
  260. package/dist/esm/FailedCall.js.map +1 -0
  261. package/dist/esm/FlowBinding.d.ts +289 -0
  262. package/dist/esm/FlowBinding.d.ts.map +1 -0
  263. package/dist/esm/FlowBinding.js +376 -0
  264. package/dist/esm/FlowBinding.js.map +1 -0
  265. package/dist/esm/HarnessError.d.ts +57 -0
  266. package/dist/esm/HarnessError.d.ts.map +1 -0
  267. package/dist/esm/HarnessError.js +85 -0
  268. package/dist/esm/HarnessError.js.map +1 -0
  269. package/dist/esm/Judgement.d.ts +289 -0
  270. package/dist/esm/Judgement.d.ts.map +1 -0
  271. package/dist/esm/Judgement.js +305 -0
  272. package/dist/esm/Judgement.js.map +1 -0
  273. package/dist/esm/Monitor.d.ts +374 -0
  274. package/dist/esm/Monitor.d.ts.map +1 -0
  275. package/dist/esm/Monitor.js +370 -0
  276. package/dist/esm/Monitor.js.map +1 -0
  277. package/dist/esm/NarrowedCheck.d.ts +523 -0
  278. package/dist/esm/NarrowedCheck.d.ts.map +1 -0
  279. package/dist/esm/NarrowedCheck.js +612 -0
  280. package/dist/esm/NarrowedCheck.js.map +1 -0
  281. package/dist/esm/Notifications.d.ts +42 -0
  282. package/dist/esm/Notifications.d.ts.map +1 -0
  283. package/dist/esm/Notifications.js +215 -0
  284. package/dist/esm/Notifications.js.map +1 -0
  285. package/dist/esm/Plan.d.ts +127 -0
  286. package/dist/esm/Plan.d.ts.map +1 -0
  287. package/dist/esm/Plan.js +97 -0
  288. package/dist/esm/Plan.js.map +1 -0
  289. package/dist/esm/QuickJSSandbox.d.ts +151 -0
  290. package/dist/esm/QuickJSSandbox.d.ts.map +1 -0
  291. package/dist/esm/QuickJSSandbox.js +1364 -0
  292. package/dist/esm/QuickJSSandbox.js.map +1 -0
  293. package/dist/esm/Relevance.d.ts +213 -0
  294. package/dist/esm/Relevance.d.ts.map +1 -0
  295. package/dist/esm/Relevance.js +254 -0
  296. package/dist/esm/Relevance.js.map +1 -0
  297. package/dist/esm/Sandbox.d.ts +637 -0
  298. package/dist/esm/Sandbox.d.ts.map +1 -0
  299. package/dist/esm/Sandbox.js +464 -0
  300. package/dist/esm/Sandbox.js.map +1 -0
  301. package/dist/esm/Steering.d.ts +464 -0
  302. package/dist/esm/Steering.d.ts.map +1 -0
  303. package/dist/esm/Steering.js +193 -0
  304. package/dist/esm/Steering.js.map +1 -0
  305. package/dist/esm/StructuredOutput.d.ts +252 -0
  306. package/dist/esm/StructuredOutput.d.ts.map +1 -0
  307. package/dist/esm/StructuredOutput.js +430 -0
  308. package/dist/esm/StructuredOutput.js.map +1 -0
  309. package/dist/esm/Sufficiency.d.ts +195 -0
  310. package/dist/esm/Sufficiency.d.ts.map +1 -0
  311. package/dist/esm/Sufficiency.js +207 -0
  312. package/dist/esm/Sufficiency.js.map +1 -0
  313. package/dist/esm/Supervisor.d.ts +719 -0
  314. package/dist/esm/Supervisor.d.ts.map +1 -0
  315. package/dist/esm/Supervisor.js +575 -0
  316. package/dist/esm/Supervisor.js.map +1 -0
  317. package/dist/esm/Tokens.d.ts +86 -0
  318. package/dist/esm/Tokens.d.ts.map +1 -0
  319. package/dist/esm/Tokens.js +92 -0
  320. package/dist/esm/Tokens.js.map +1 -0
  321. package/dist/esm/Transcript.d.ts +171 -0
  322. package/dist/esm/Transcript.d.ts.map +1 -0
  323. package/dist/esm/Transcript.js +424 -0
  324. package/dist/esm/Transcript.js.map +1 -0
  325. package/dist/esm/TruncatedOutput.d.ts +186 -0
  326. package/dist/esm/TruncatedOutput.d.ts.map +1 -0
  327. package/dist/esm/TruncatedOutput.js +257 -0
  328. package/dist/esm/TruncatedOutput.js.map +1 -0
  329. package/dist/esm/UnmovedTree.d.ts +113 -0
  330. package/dist/esm/UnmovedTree.d.ts.map +1 -0
  331. package/dist/esm/UnmovedTree.js +90 -0
  332. package/dist/esm/UnmovedTree.js.map +1 -0
  333. package/dist/esm/UnresolvedFailure.d.ts +196 -0
  334. package/dist/esm/UnresolvedFailure.d.ts.map +1 -0
  335. package/dist/esm/UnresolvedFailure.js +218 -0
  336. package/dist/esm/UnresolvedFailure.js.map +1 -0
  337. package/dist/esm/VacuousVerification.d.ts +237 -0
  338. package/dist/esm/VacuousVerification.d.ts.map +1 -0
  339. package/dist/esm/VacuousVerification.js +245 -0
  340. package/dist/esm/VacuousVerification.js.map +1 -0
  341. package/dist/esm/VariablesPanel.d.ts +117 -0
  342. package/dist/esm/VariablesPanel.d.ts.map +1 -0
  343. package/dist/esm/VariablesPanel.js +142 -0
  344. package/dist/esm/VariablesPanel.js.map +1 -0
  345. package/dist/esm/index.d.ts +172 -0
  346. package/dist/esm/index.d.ts.map +1 -0
  347. package/dist/esm/index.js +172 -0
  348. package/dist/esm/index.js.map +1 -0
  349. package/dist/esm/internal/bytes.d.ts +36 -0
  350. package/dist/esm/internal/bytes.d.ts.map +1 -0
  351. package/dist/esm/internal/bytes.js +70 -0
  352. package/dist/esm/internal/bytes.js.map +1 -0
  353. package/dist/esm/internal/cellPrompt.d.ts +122 -0
  354. package/dist/esm/internal/cellPrompt.d.ts.map +1 -0
  355. package/dist/esm/internal/cellPrompt.js +276 -0
  356. package/dist/esm/internal/cellPrompt.js.map +1 -0
  357. package/dist/esm/internal/compactable.d.ts +44 -0
  358. package/dist/esm/internal/compactable.d.ts.map +1 -0
  359. package/dist/esm/internal/compactable.js +71 -0
  360. package/dist/esm/internal/compactable.js.map +1 -0
  361. package/dist/esm/internal/compactionMarks.d.ts +278 -0
  362. package/dist/esm/internal/compactionMarks.d.ts.map +1 -0
  363. package/dist/esm/internal/compactionMarks.js +317 -0
  364. package/dist/esm/internal/compactionMarks.js.map +1 -0
  365. package/dist/esm/internal/demandText.d.ts +95 -0
  366. package/dist/esm/internal/demandText.d.ts.map +1 -0
  367. package/dist/esm/internal/demandText.js +128 -0
  368. package/dist/esm/internal/demandText.js.map +1 -0
  369. package/dist/esm/internal/elide.d.ts +109 -0
  370. package/dist/esm/internal/elide.d.ts.map +1 -0
  371. package/dist/esm/internal/elide.js +123 -0
  372. package/dist/esm/internal/elide.js.map +1 -0
  373. package/dist/esm/internal/frame.d.ts +463 -0
  374. package/dist/esm/internal/frame.d.ts.map +1 -0
  375. package/dist/esm/internal/frame.js +861 -0
  376. package/dist/esm/internal/frame.js.map +1 -0
  377. package/dist/esm/internal/nonNegativeSafeInt.d.ts +20 -0
  378. package/dist/esm/internal/nonNegativeSafeInt.d.ts.map +1 -0
  379. package/dist/esm/internal/nonNegativeSafeInt.js +20 -0
  380. package/dist/esm/internal/nonNegativeSafeInt.js.map +1 -0
  381. package/dist/esm/internal/paidUsage.d.ts +52 -0
  382. package/dist/esm/internal/paidUsage.d.ts.map +1 -0
  383. package/dist/esm/internal/paidUsage.js +72 -0
  384. package/dist/esm/internal/paidUsage.js.map +1 -0
  385. package/dist/esm/internal/printChannel.d.ts +233 -0
  386. package/dist/esm/internal/printChannel.d.ts.map +1 -0
  387. package/dist/esm/internal/printChannel.js +376 -0
  388. package/dist/esm/internal/printChannel.js.map +1 -0
  389. package/dist/esm/internal/printsObservation.d.ts +26 -0
  390. package/dist/esm/internal/printsObservation.d.ts.map +1 -0
  391. package/dist/esm/internal/printsObservation.js +29 -0
  392. package/dist/esm/internal/printsObservation.js.map +1 -0
  393. package/dist/esm/internal/refusal.d.ts +40 -0
  394. package/dist/esm/internal/refusal.d.ts.map +1 -0
  395. package/dist/esm/internal/refusal.js +47 -0
  396. package/dist/esm/internal/refusal.js.map +1 -0
  397. package/dist/esm/internal/supervision.d.ts +174 -0
  398. package/dist/esm/internal/supervision.d.ts.map +1 -0
  399. package/dist/esm/internal/supervision.js +485 -0
  400. package/dist/esm/internal/supervision.js.map +1 -0
  401. package/dist/esm/internal/unfinishedWork.d.ts +99 -0
  402. package/dist/esm/internal/unfinishedWork.d.ts.map +1 -0
  403. package/dist/esm/internal/unfinishedWork.js +85 -0
  404. package/dist/esm/internal/unfinishedWork.js.map +1 -0
  405. package/dist/esm/internal/unobservedCall.d.ts +112 -0
  406. package/dist/esm/internal/unobservedCall.d.ts.map +1 -0
  407. package/dist/esm/internal/unobservedCall.js +501 -0
  408. package/dist/esm/internal/unobservedCall.js.map +1 -0
  409. package/dist/esm/internal/untrustedData.d.ts +14 -0
  410. package/dist/esm/internal/untrustedData.d.ts.map +1 -0
  411. package/dist/esm/internal/untrustedData.js +15 -0
  412. package/dist/esm/internal/untrustedData.js.map +1 -0
  413. package/docs/README.md +129 -0
  414. package/docs/api.md +1869 -0
  415. package/docs/concepts.md +238 -0
  416. package/docs/external-transcripts.md +245 -0
  417. package/docs/guides/bind-flows.md +167 -0
  418. package/docs/guides/drive-the-loop.md +265 -0
  419. package/docs/guides/run-cells.md +262 -0
  420. package/docs/guides/workerd.md +144 -0
  421. package/docs/installation.md +69 -0
  422. package/docs/quickstart.md +121 -0
  423. package/docs/reference.md +954 -0
  424. package/docs/troubleshooting.md +177 -0
  425. package/package.json +463 -3
  426. package/src/AgentEvent.ts +1772 -0
  427. package/src/CallLedger.ts +560 -0
  428. package/src/Cell.ts +926 -0
  429. package/src/CellCalls.ts +198 -0
  430. package/src/CellHistory.ts +128 -0
  431. package/src/CellTurn.ts +4450 -0
  432. package/src/CellValidation.ts +382 -0
  433. package/src/Compaction.ts +330 -0
  434. package/src/CompletionClaim.ts +1013 -0
  435. package/src/ContextWindow.ts +669 -0
  436. package/src/EngineLike.ts +614 -0
  437. package/src/ExternalTranscript.ts +1143 -0
  438. package/src/FailedCall.ts +163 -0
  439. package/src/FlowBinding.ts +603 -0
  440. package/src/HarnessError.ts +98 -0
  441. package/src/Judgement.ts +526 -0
  442. package/src/Monitor.ts +579 -0
  443. package/src/NarrowedCheck.ts +694 -0
  444. package/src/Notifications.ts +262 -0
  445. package/src/Plan.ts +113 -0
  446. package/src/QuickJSSandbox.ts +1557 -0
  447. package/src/Relevance.ts +352 -0
  448. package/src/Sandbox.ts +908 -0
  449. package/src/Steering.ts +405 -0
  450. package/src/StructuredOutput.ts +484 -0
  451. package/src/Sufficiency.ts +247 -0
  452. package/src/Supervisor.ts +798 -0
  453. package/src/Tokens.ts +108 -0
  454. package/src/Transcript.ts +513 -0
  455. package/src/TruncatedOutput.ts +297 -0
  456. package/src/UnmovedTree.ts +121 -0
  457. package/src/UnresolvedFailure.ts +240 -0
  458. package/src/VacuousVerification.ts +280 -0
  459. package/src/VariablesPanel.ts +165 -0
  460. package/src/index.ts +204 -0
  461. package/src/internal/bytes.ts +70 -0
  462. package/src/internal/cellPrompt.ts +337 -0
  463. package/src/internal/compactable.ts +76 -0
  464. package/src/internal/compactionMarks.ts +454 -0
  465. package/src/internal/demandText.ts +145 -0
  466. package/src/internal/elide.ts +130 -0
  467. package/src/internal/frame.ts +1178 -0
  468. package/src/internal/nonNegativeSafeInt.ts +24 -0
  469. package/src/internal/paidUsage.ts +90 -0
  470. package/src/internal/printChannel.ts +434 -0
  471. package/src/internal/printsObservation.ts +31 -0
  472. package/src/internal/refusal.ts +53 -0
  473. package/src/internal/supervision.ts +652 -0
  474. package/src/internal/unfinishedWork.ts +123 -0
  475. package/src/internal/unobservedCall.ts +536 -0
  476. package/src/internal/untrustedData.ts +19 -0
@@ -0,0 +1,1364 @@
1
+ /**
2
+ * The QuickJS-WASM sandbox binding.
3
+ *
4
+ * This is the production `Sandbox`: the cell runs inside a QuickJS interpreter
5
+ * compiled to WebAssembly, which is a genuinely separate JavaScript realm with
6
+ * no reference to the host's globals, prototypes, or module loader. The same
7
+ * single-file variant runs unmodified on Node and in a browser, so a browser
8
+ * host provides this layer and calls the identical harness.
9
+ *
10
+ * What the cell can reach is exactly `ctx`: `ctx.call` bridges to the host's
11
+ * durable flow boundary, `ctx.flows` is a frozen catalog projection. The
12
+ * prelude removes `Date` and `Math.random` from the realm, because a replayed
13
+ * cell must reach the same calls in the same order, and `Proxy`, because a
14
+ * value that answers reflection from a handler cannot be weighed against the
15
+ * run's memory ceiling. There is no filesystem, no network, no process, and no
16
+ * module loader to reach in the first place.
17
+ *
18
+ * Teardown is scope finalization and cancellation is fiber interruption: an
19
+ * interrupted frame disposes the runtime, which is the only thing holding the
20
+ * cell alive.
21
+ *
22
+ * Which QuickJS build is compiled is a seam. The default compiles the
23
+ * single-file build from bytes, which is what Node and a browser want. A host
24
+ * whose runtime forbids compiling WebAssembly from bytes at runtime, such as
25
+ * Cloudflare's workerd, provides {@link Variant} instead and names a build
26
+ * whose module came from its toolchain.
27
+ *
28
+ * @since 0.1.0
29
+ */
30
+ import singlefile from "@jitl/quickjs-singlefile-browser-release-sync";
31
+ import { Context, Duration, Effect, Layer, Option, Schema } from "effect";
32
+ import { newQuickJSWASMModuleFromVariant } from "quickjs-emscripten-core";
33
+ import * as Cell from "./Cell.js";
34
+ import * as bytes from "./internal/bytes.js";
35
+ import * as elide from "./internal/elide.js";
36
+ import * as printChannel from "./internal/printChannel.js";
37
+ import { refusal } from "./internal/refusal.js";
38
+ import * as Sandbox from "./Sandbox.js";
39
+ import * as VariablesPanel from "./VariablesPanel.js";
40
+ /**
41
+ * Every intrinsic the host's own realm-side code reads, bound before a cell runs.
42
+ *
43
+ * A global script may rebind `Object`, and under a per-cell realm that cost the
44
+ * cell that did it and nothing else. Under a realm that outlives the cell it
45
+ * costs the run: `encode` reaches `Object.keys` at call time, so one top-level
46
+ * `const Object = {}` in frame 3 makes every `ctx.call` and every
47
+ * `console.log` from frame 4 on die on `TypeError: not a function`, with no
48
+ * name in the failure to connect it to the declaration that caused it. The same
49
+ * holds for `JSON`, `Array`, `Number`, `String`, `TypeError` and `Promise`.
50
+ *
51
+ * Binding them here makes a cell that shadows an intrinsic cost exactly what a
52
+ * REPL should charge for it — its own later code — and nothing the harness runs
53
+ * on the cell's behalf. Nothing is refused, because nothing needs to be.
54
+ */
55
+ const preludeIntrinsics = ` var keysOf = Object.keys
56
+ var freezeValue = Object.freeze
57
+ var prototypeOf = Object.getPrototypeOf
58
+ var objectPrototype = Object.prototype
59
+ var define = Object.defineProperty
60
+ var isArray = Array.isArray
61
+ var stringify = JSON.stringify
62
+ var parse = JSON.parse
63
+ var finite = Number.isFinite
64
+ var render = String
65
+ var Fault = TypeError
66
+ var Deferred = Promise
67
+ var argumentsOf = Array.prototype.slice`;
68
+ /**
69
+ * The realm-side helpers both preludes install.
70
+ *
71
+ * `encode` carries the label of what it is encoding so one validator serves
72
+ * `ctx.call`, `ctx.done`, `ctx.park` and `ctx.justify` without any of them
73
+ * having to describe its own refusal.
74
+ */
75
+ const preludeHelpers = `${preludeIntrinsics}
76
+ var freeze = function (value) {
77
+ if (value !== null && typeof value === "object") {
78
+ keysOf(value).forEach(function (key) { freeze(value[key]) })
79
+ freezeValue(value)
80
+ }
81
+ return value
82
+ }
83
+ var encode = function (label, input) {
84
+ var seen = []
85
+ var visit = function (value) {
86
+ if (value === null || typeof value === "string" || typeof value === "boolean") return
87
+ if (typeof value === "number" && finite(value)) return
88
+ if (typeof value !== "object") throw new Fault(label + " must be JSON-serializable")
89
+ if (seen.indexOf(value) >= 0) throw new Fault(label + " must be JSON-serializable")
90
+ var prototype = prototypeOf(value)
91
+ if (!isArray(value) && prototype !== objectPrototype && prototype !== null) {
92
+ throw new Fault(label + " must be JSON-serializable")
93
+ }
94
+ seen.push(value)
95
+ keysOf(value).forEach(function (key) { visit(value[key]) })
96
+ seen.pop()
97
+ }
98
+ visit(input)
99
+ return stringify(input)
100
+ }
101
+ var settleEnvelope = function (settled) {
102
+ // A failed call RESOLVES with the failure envelope; only teardown throws.
103
+ // See Cell.callFailure for why.
104
+ if (settled.ok) return settled.value
105
+ if (settled.aborted) throw new Error(settled.failure.error.message)
106
+ return settled.failure
107
+ }
108
+ var dispatch = function (flow, input, at) { return bridge(flow, input, at).then(settleEnvelope) }
109
+ // The at option is whatever the cell wrote, so it is encoded defensively
110
+ // rather than strictly: a value JSON cannot hold travels as null and the
111
+ // boundary answers it as an ordinary invalid_input, instead of throwing out
112
+ // of a cell that has already paid for the calls before this line.
113
+ var encodeAt = function (value) {
114
+ try { return encode("ctx.call at", value === undefined ? null : value) } catch (error) { return "null" }
115
+ }`;
116
+ /**
117
+ * The handle `ctx.base` is bound to, rendered into both preludes as data.
118
+ *
119
+ * It is a constant rather than something the host mints, because the run's
120
+ * opening tree is not a thing anybody has to decide to keep: the host either
121
+ * recorded one or it did not, and a call against this id says which by
122
+ * succeeding or by answering `checkpoint_unavailable`.
123
+ */
124
+ const baseHandle = Cell.checkpoint(Cell.baseCheckpoint);
125
+ /**
126
+ * The name a queued mint carries, so an overrun reads as what it was.
127
+ *
128
+ * Nothing resolves it: a checkpoint is not a flow, it is not in the catalog,
129
+ * and no capability gates it. See `Sandbox` `Minter`.
130
+ */
131
+ const checkpointFlow = "checkpoint";
132
+ /** Reads the `at` the realm encoded; the empty string is "the cell passed none". */
133
+ const decodedAt = (encoded) => encoded === "" ? undefined : Schema.decodeUnknownSync(Schema.Json)(JSON.parse(encoded));
134
+ /**
135
+ * The `ctx.call`, `ctx.checkpoint` and `ctx.base` members. `guard` is the one
136
+ * line the REPL mode adds: nothing in the filing mode can end a run part-way
137
+ * through a cell, because there the run ends by returning.
138
+ */
139
+ const preludeCall = (guard) => ` call: function (flow, input, options) {
140
+ if (typeof flow !== "string") return Deferred.reject(new Fault("ctx.call expects a flow name as its first argument"))
141
+ ${guard} var encoded = encode("ctx.call input", input === undefined ? null : input)
142
+ var at = options === null || typeof options !== "object" ? undefined : options.at
143
+ if (at === undefined) return dispatch(flow, encoded, "")
144
+ // A handle the cell never awaited is a promise, and that spelling is the
145
+ // one the ruling wrote: \`const cp = ctx.checkpoint()\`. The pin lands where
146
+ // that line is, because the queue settles in issue order, so awaiting the
147
+ // handle later cannot move the tree it names. Both spellings are accepted.
148
+ if (at !== null && typeof at === "object" && typeof at.then === "function") {
149
+ return at.then(function (resolved) { return dispatch(flow, encoded, encodeAt(resolved)) })
150
+ }
151
+ return dispatch(flow, encoded, encodeAt(at))
152
+ },
153
+ checkpoint: function () {
154
+ ${guard} return pin().then(settleEnvelope)
155
+ },
156
+ base: freeze(parse(${JSON.stringify(JSON.stringify(baseHandle))})),`;
157
+ /**
158
+ * What a `ctx.call` issued after `ctx.done` or `ctx.park` resolves with.
159
+ *
160
+ * A completion takes effect where it is called, so the calls a cell would have
161
+ * made after it do not run. They fail the way every other refused call fails —
162
+ * soft, with a code and a hint — because rule 3 promises a cell that a call
163
+ * resolves rather than throws, and a completion is not the place to break that
164
+ * promise: the guard shape the contract teaches puts `ctx.done` in the middle of
165
+ * a cell, and a throw there would discard the rest of a frame that had already
166
+ * finished the run.
167
+ */
168
+ const sealedCall = Cell.callFailure(refusal("run_completed", "This run was already completed: an earlier line of this cell called ctx.done or ctx.park, which takes effect where it is called, so no further flow call is dispatched."));
169
+ /**
170
+ * The prelude a persistent realm is opened with.
171
+ *
172
+ * It removes the two sources of nondeterminism QuickJS ships with, `Date` and
173
+ * `Math.random`. The raw host bridge is captured in a closure and then deleted
174
+ * from the global object, so a cell cannot reach the unwrapped boundary and
175
+ * hand it unencoded values.
176
+ *
177
+ * It differs from the per-cell prelude the filing surface used in exactly the
178
+ * two ways the persistent realm
179
+ * differs: `ctx.state` is gone, because the realm is the memory, and three new
180
+ * members plus `console` are installed, because a script cannot `return`.
181
+ *
182
+ * `console.log` renders each argument on the host side — a string as itself,
183
+ * structures through the print channel — so a structured value reaches the next model
184
+ * turn as the value it is rather than as `[object Object]`. A value JSON cannot
185
+ * walk at all, a cycle above all, is the one case where that promise cannot be
186
+ * kept, so it is named instead: the kind, the reason, and the fact that the
187
+ * value is still bound. `String(value)` there would print the exact bytes this
188
+ * channel exists to abolish.
189
+ *
190
+ * Both are installed as non-writable, non-configurable own properties, which the
191
+ * per-cell prelude never needed to do. There, a cell that declared `ctx` shadowed
192
+ * the name inside its own async wrapper and the next cell was handed a fresh
193
+ * realm. Here the wrapper is gone and `CellValidation.normalize` rewrites a
194
+ * top-level `const` to `var`, so the same declaration would assign over the run's
195
+ * only host binding and every later cell would die on
196
+ * `TypeError: not a function` — with `ctx` inside the panel's baseline, so
197
+ * nothing would even name what went missing. A `var` declaration over a
198
+ * non-writable global is a silent no-op in sloppy mode, which is a failure the
199
+ * run survives. `CellValidation` refuses the declaration in-frame as well, so
200
+ * the model is told rather than left to wonder.
201
+ */
202
+ const replPrelude = (catalog) => `(function () {
203
+ var bridge = globalThis.__call
204
+ var pin = globalThis.__checkpoint
205
+ var print = globalThis.__print
206
+ var intent = globalThis.__intent
207
+ ${preludeHelpers}
208
+ delete globalThis.__call
209
+ delete globalThis.__checkpoint
210
+ delete globalThis.__print
211
+ delete globalThis.__intent
212
+ delete globalThis.Date
213
+ delete Math.random
214
+ // Removed for the same reason as the two above: it makes the realm answer a
215
+ // question dishonestly. Every reading the panel probe takes goes through the
216
+ // intrinsics captured before any cell ran, and every property comes off its
217
+ // own descriptor, so a cell can neither rebind reflection nor hide weight
218
+ // behind a getter. Neither defence survives a value that IS the trap: a proxy
219
+ // answers \`getOwnPropertyNames\` from its handler, so one wrapping a
220
+ // megabyte-wide target weighs as an empty object while the realm holds the
221
+ // target alive, and the run's only ceiling over string data reads zero for it.
222
+ // No reading of a proxy can be trusted — any number it reports is a number the
223
+ // handler chose — and nothing else in this realm can construct one, so the
224
+ // constructor goes rather than the accounting. \`Reflect\` stays: it offers no
225
+ // way to make a proxy and the probe does not read through it.
226
+ delete globalThis.Proxy
227
+ // The seal: once this frame has said how the run ends, it has ended, and the
228
+ // calls a cell would have made after that line are not dispatched. It lives
229
+ // here rather than on the host because ctx.call has to answer synchronously,
230
+ // and it is cleared per frame by the function this prelude returns — a park
231
+ // whose reason is refused is asked again inside the same frame, and a realm
232
+ // still sealed from the refused attempt would answer that retry with nothing.
233
+ var catalog = freeze(${catalog})
234
+ var sealed = null
235
+ var sealedEnvelope = freeze(parse(${JSON.stringify(JSON.stringify(sealedCall))}))
236
+ var unprintable = function (value, error) {
237
+ var kind = isArray(value) ? "array" : typeof value
238
+ var why = error !== null && typeof error === "object" && error.message ? error.message : render(error)
239
+ return "[unprintable " + kind + ": " + why + " — the value is still bound, so print the part of it you need]"
240
+ }
241
+ var show = function (values) {
242
+ var parts = []
243
+ for (var index = 0; index < values.length; index++) {
244
+ var value = values[index]
245
+ if (typeof value === "string") parts.push({ text: value })
246
+ else if (value === undefined) parts.push({ text: "undefined" })
247
+ else {
248
+ var encoded = null
249
+ var refused = false
250
+ try { encoded = stringify(value) } catch (error) { refused = true; parts.push({ text: unprintable(value, error) }) }
251
+ // JSON answers \`undefined\` rather than throwing for a value it has no
252
+ // notation for at all — a function, a symbol — and those read best as
253
+ // themselves. It throws only for a value it cannot walk, and that is
254
+ // the one case where naming the reason beats printing "[object Object]".
255
+ if (!refused) parts.push(encoded === undefined ? { text: render(value) } : { json: parse(encoded) })
256
+ }
257
+ }
258
+ print(stringify(parts))
259
+ }
260
+ var line = function () { show(argumentsOf.call(arguments)) }
261
+ var host = function (name, value) {
262
+ define(globalThis, name, { value: value, writable: false, enumerable: true, configurable: false })
263
+ }
264
+ host("console", freezeValue({ log: line, info: line, warn: line, error: line }))
265
+ host("ctx", freezeValue({
266
+ ${preludeCall(` if (sealed !== null) return Deferred.resolve(sealed)\n`)}
267
+ get flows() { return catalog },
268
+ done: function (output) {
269
+ if (sealed !== null) return
270
+ if (arguments.length === 0) {
271
+ throw new Fault("ctx.done(output) takes the run's answer; call it with the value the task asked for")
272
+ }
273
+ var encoded = encode("ctx.done output", output === undefined ? null : output)
274
+ sealed = sealedEnvelope
275
+ intent("done", encoded)
276
+ },
277
+ park: function (reason, message) {
278
+ if (sealed !== null) return
279
+ var encoded = encode("ctx.park message", { reason: reason === undefined ? null : reason, message: message === undefined ? "" : message })
280
+ sealed = sealedEnvelope
281
+ intent("park", encoded)
282
+ },
283
+ justify: function (text) { intent("justify", encode("ctx.justify text", text === undefined ? "" : text)) }
284
+ }))
285
+ // Handed back to the host, which calls it as each frame opens. See the seal
286
+ // above for why the clearing is per frame rather than per run.
287
+ return function (nextCatalog) {
288
+ sealed = null
289
+ if (nextCatalog !== undefined) catalog = freeze(parse(nextCatalog))
290
+ }
291
+ })()`;
292
+ const Catalog = Schema.Record(Schema.String, Cell.FlowProjection);
293
+ const catalogOf = (flows) => {
294
+ const encoded = Schema.encodeSync(Catalog)(flows);
295
+ const normalized = Object.fromEntries(Object.entries(encoded).map(([name, projection]) => [
296
+ name,
297
+ Object.fromEntries(Object.entries(projection).flatMap(([field, value]) => Option.isOption(value)
298
+ ? Option.isSome(value) ? [[field, value.value]] : []
299
+ : [[field, value]]))
300
+ ]));
301
+ return JSON.stringify(normalized);
302
+ };
303
+ const raisedFrom = (dumped) => {
304
+ if (typeof dumped === "object" && dumped !== null) {
305
+ const record = dumped;
306
+ return new Cell.Raised({
307
+ name: typeof record.name === "string" ? record.name : "Error",
308
+ // Never `String(object)`: a cell that threw a structured value is told
309
+ // what it threw. See `Sandbox` `describe`.
310
+ message: typeof record.message === "string" ? record.message : Sandbox.raisedOutcome(dumped).message
311
+ });
312
+ }
313
+ return new Cell.Raised({ name: "Error", message: String(dumped) });
314
+ };
315
+ /**
316
+ * Builds one owned QuickJS handle from the already-validated JSON result.
317
+ *
318
+ * Materializing the value directly also avoids parsing a multi-megabyte JSON
319
+ * string inside a promise job, which leaves QuickJS 0.32's runtime heap in an
320
+ * uncollectable state during disposal.
321
+ */
322
+ const handleFromJson = (context, defineDataProperty, value, depth = 0) => {
323
+ if (value === null)
324
+ return context.null;
325
+ switch (typeof value) {
326
+ case "boolean":
327
+ return value ? context.true : context.false;
328
+ case "number":
329
+ return context.newNumber(value);
330
+ case "string":
331
+ return context.newString(value);
332
+ }
333
+ // Leave enough host stack to release every ancestor handle on refusal.
334
+ if (depth >= 128)
335
+ throw new Error("The flow result exceeds 128 levels of JSON nesting");
336
+ const container = Array.isArray(value) ? context.newArray() : context.newObject();
337
+ try {
338
+ for (const [key, item] of Object.entries(value)) {
339
+ const child = handleFromJson(context, defineDataProperty, item, depth + 1);
340
+ try {
341
+ const property = context.newString(key);
342
+ try {
343
+ context.unwrapResult(context.callFunction(defineDataProperty, context.undefined, container, property, child)).dispose();
344
+ }
345
+ finally {
346
+ property.dispose();
347
+ }
348
+ }
349
+ finally {
350
+ child.dispose();
351
+ }
352
+ }
353
+ return container;
354
+ }
355
+ catch (error) {
356
+ container.dispose();
357
+ throw error;
358
+ }
359
+ };
360
+ /**
361
+ * Caches only a successful asynchronous load; a rejection may be retried.
362
+ *
363
+ * @category constructors
364
+ * @since 0.1.0
365
+ */
366
+ export const cacheSuccessful = (load) => {
367
+ let loaded;
368
+ return () => {
369
+ if (loaded === undefined) {
370
+ const pending = load();
371
+ loaded = pending;
372
+ void pending.catch(() => {
373
+ loaded = undefined;
374
+ });
375
+ }
376
+ return loaded;
377
+ };
378
+ };
379
+ /**
380
+ * The QuickJS build the sandbox compiles.
381
+ *
382
+ * @category services
383
+ * @since 0.1.0
384
+ */
385
+ export class Variant extends Context.Service()("@smthrs/harness/QuickJSSandbox/Variant") {
386
+ }
387
+ /**
388
+ * Provides the single-file build, which Node and a browser both compile.
389
+ *
390
+ * @category layers
391
+ * @since 0.1.0
392
+ */
393
+ export const layerVariantLive = Layer.succeed(Variant)({ variant: singlefile });
394
+ /**
395
+ * Provides a build the host names.
396
+ *
397
+ * A workerd host builds one with `newVariant(baseVariant, { wasmModule })` from
398
+ * a `.wasm` module import, because that runtime instantiates a module the
399
+ * toolchain compiled and refuses to compile one from bytes.
400
+ *
401
+ * @category layers
402
+ * @since 0.1.0
403
+ */
404
+ export const layerVariant = (variant) => Layer.succeed(Variant)({ variant });
405
+ /**
406
+ * One compiled module per build, so two sandboxes over one variant share it.
407
+ *
408
+ * Keyed weakly: a variant a host builds per request is collectable with the
409
+ * module it produced.
410
+ */
411
+ const compiled = new WeakMap();
412
+ const loaderFor = (variant) => {
413
+ const known = compiled.get(variant);
414
+ if (known !== undefined)
415
+ return known;
416
+ const loader = cacheSuccessful(() => newQuickJSWASMModuleFromVariant(variant));
417
+ compiled.set(variant, loader);
418
+ return loader;
419
+ };
420
+ /**
421
+ * Synchronous monotonic-enough clock required by QuickJS's interrupt callback.
422
+ *
423
+ * @category services
424
+ * @since 0.1.0
425
+ */
426
+ export class ComputeClock extends Context.Service()("@smthrs/harness/QuickJSSandbox/ComputeClock") {
427
+ }
428
+ /**
429
+ * Provides the browser-safe host clock behind the QuickJS clock seam.
430
+ *
431
+ * @category layers
432
+ * @since 0.1.0
433
+ */
434
+ export const layerClockLive = Layer.succeed(ComputeClock)({ now: () => Date.now() });
435
+ const capabilities = {
436
+ calls: true,
437
+ memoryBytes: true,
438
+ steps: true,
439
+ timeMs: true
440
+ };
441
+ const timeLimitExceeded = (timeMs) => new Cell.Rejected({
442
+ code: "limit_exceeded",
443
+ message: `This cell exceeded its wall-clock limit of ${timeMs} milliseconds`
444
+ });
445
+ /**
446
+ * The reasons `ctx.park` may name, as the transition schema declares them.
447
+ *
448
+ * Checked on the host rather than inside the realm so a wrong one settles the
449
+ * frame as an `invalid_transition` the next frame is asked to fix, instead of as
450
+ * a throw that reads like a bug in the cell's own logic.
451
+ */
452
+ const parkReasons = ["waiting-input", "waiting-event", "waiting-quota"];
453
+ const parkPayload = Schema.decodeUnknownSync(Schema.Struct({ reason: Schema.Json, message: Schema.Json }));
454
+ const printParts = Schema.decodeUnknownSync(Schema.Array(Schema.Union([
455
+ Schema.Struct({ text: Schema.String }),
456
+ Schema.Struct({ json: Schema.Json })
457
+ ])));
458
+ /**
459
+ * Renders one `console.log` call as the statement it contributes.
460
+ *
461
+ * The statement is *not* bounded here beyond what the host is willing to hold:
462
+ * a frame's statements share one budget and the share each one gets is not known
463
+ * until the frame closes, so the reduction happens there. What happens here is
464
+ * the reduction the host needs for itself — a value larger than a whole frame's
465
+ * budget can never be shown whole, so only its two ends are kept, and the size
466
+ * it had is carried beside them so the notice at frame close names the original.
467
+ *
468
+ * The two ends are cut through `elide`, which will not split a surrogate pair.
469
+ * They are joined with nothing between them, so a head ending in the first half
470
+ * of a pair and a tail starting with the second half would fuse into a character
471
+ * the cell never printed.
472
+ */
473
+ const printed = (encoded) => {
474
+ const parts = printParts(JSON.parse(encoded));
475
+ const rendered = parts.map((part) => "text" in part ? part.text : printChannel.render(part.json));
476
+ // A multi-line argument gets its own lines; short neighbours stay space-joined.
477
+ const whole = rendered.reduce((joined, part, index) => index === 0 ? part : joined + (part.includes("\n") || rendered[index - 1].includes("\n") ? "\n" : " ") + part, "");
478
+ const wholeBytes = bytes.size(whole);
479
+ if (wholeBytes <= Sandbox.printFrameBytes)
480
+ return { text: whole, bytes: wholeBytes };
481
+ const edge = Math.floor(Sandbox.printFrameBytes / 2);
482
+ return {
483
+ text: `${elide.headSlice(whole, edge)}${elide.tailSlice(whole, edge)}`,
484
+ bytes: wholeBytes
485
+ };
486
+ };
487
+ /**
488
+ * The transition a REPL frame settled, or the reason it settled none.
489
+ */
490
+ const replOutcome = (recorded, justification) => {
491
+ if (recorded !== undefined && recorded.kind === "park") {
492
+ const reason = parkReasons.find((candidate) => candidate === recorded.reason);
493
+ if (reason === undefined) {
494
+ return new Cell.Rejected({
495
+ code: "invalid_transition",
496
+ message: `ctx.park was called with reason ${JSON.stringify(recorded.reason)}. Call it as ctx.park(reason, message) with reason one of "waiting-input", "waiting-event" or "waiting-quota".`
497
+ });
498
+ }
499
+ return new Cell.Settled({
500
+ transition: Sandbox.replTransition({ _tag: "Park", reason, message: recorded.message }, justification)
501
+ });
502
+ }
503
+ return new Cell.Settled({
504
+ transition: Sandbox.replTransition(recorded === undefined ? undefined : { _tag: "Done", output: recorded.output, value: recorded.value }, justification)
505
+ });
506
+ };
507
+ /**
508
+ * How many values one probe walks before it stops counting.
509
+ *
510
+ * The walk exists to find the string bytes a realm is holding, and strings are
511
+ * few and large where they matter — a file a cell read, a suite's output. The
512
+ * bound is what keeps a realm holding a million small objects from paying for a
513
+ * traversal of all of them, and it doubles as the cycle guard: a graph that
514
+ * points at itself spends the budget instead of the stack.
515
+ */
516
+ const weighNodes = 200_000;
517
+ /**
518
+ * How deep one probe descends before it stops counting.
519
+ *
520
+ * A cell can bind a linked list, and the walk runs inside the realm on the
521
+ * realm's own stack.
522
+ */
523
+ const weighDepth = 32;
524
+ /**
525
+ * Builds the in-realm probe that reads the variables panel and the realm's weight.
526
+ *
527
+ * The source is evaluated **once**, when the realm opens, and answers the
528
+ * function every later frame calls. That is the whole reason it is a factory:
529
+ * the intrinsics the walk needs are read here, before any cell has run, and held
530
+ * in the closure, so a cell that binds `Object` at its top level loses its own
531
+ * reflection and not the panel that would have named the binding for it. Called
532
+ * fresh each frame instead, the probe would read whatever `Object` a cell had
533
+ * left behind, and the frame after the shadowing would report an empty realm.
534
+ *
535
+ * Captured intrinsics stop a cell rebinding reflection, and reading every named
536
+ * property off its own descriptor stops a getter running. Neither stops a value
537
+ * that IS the trap, which is why `replPrelude` deletes `Proxy`: a proxy answers
538
+ * `getOwnPropertyNames` from its handler, so every number this walk could report
539
+ * for one is a number the cell chose. The constructor goes rather than the
540
+ * accounting, because there is no reading of a proxy the realm can be trusted to
541
+ * take.
542
+ *
543
+ * The estimate covers array indices, enumerable own string-keyed properties,
544
+ * Map keys and values, and Set values. It cannot see closure state, weak
545
+ * collection entries, or other storage unreachable by those paths. Functions
546
+ * have a fixed weight of 8 regardless of their scope. This supplements the
547
+ * native allocator limit; it is not a hard bound on all retained memory.
548
+ *
549
+ * The returned function declares nothing on the global object and adds no name
550
+ * of its own to the set it reports, because the host holds it as a handle rather
551
+ * than as a global. Every value's *panel* line is measured cheaply — a string's
552
+ * length, an array's length, an object's key count, a function's arity, a number
553
+ * or boolean by value — because a panel that serialized every global would cost
554
+ * the heap every frame, and the whole point of a realm is that the value is
555
+ * still there under the name the panel prints.
556
+ *
557
+ * `bytes` is a second, separate reading and it exists because QuickJS's own
558
+ * ceiling cannot supply it. Measured on the shipped variant: `str_count` and
559
+ * `str_size` stay at zero for every construction a cell can reach — `repeat`,
560
+ * `join`, and a string handed in by the host bridge alike — so
561
+ * `runtime.setMemoryLimit` refuses one allocation larger than the whole ceiling
562
+ * and never sees accumulation. A realm under a 128 MiB ceiling held 400 MiB of
563
+ * live strings across forty frames and raised nothing while the host's resident
564
+ * set grew by 385 MB. Under a per-cell realm that hole was bounded by one cell;
565
+ * under a per-run realm it compounds for the life of the run, so the run budget
566
+ * is measured here instead. See {@link openRealm}.
567
+ */
568
+ const panelProbe = (baseline) => `(function (ownNames, descriptorOf, keysOf, isArray, stringify, String, mapSize, mapEntries, mapNext, setSize, setValues, setNext, skip) {
569
+ return function () {
570
+ var names = ownNames(globalThis)
571
+ var out = []
572
+ var total = 0
573
+ var budget = ${weighNodes}
574
+ var partial = false
575
+ var partialRoot = null
576
+ var partialBytes = 0
577
+ // The ancestors of the value being weighed, and the whole of this walk's
578
+ // repeat detection. A cycle is the one repeat that MUST be cut, because it
579
+ // never ends, and an ancestor list cuts it at the cost of the depth ceiling
580
+ // rather than of the whole graph. Two siblings that share one object are
581
+ // counted twice, which over-states such a realm: a ceiling that errs toward
582
+ // refusing is the safe direction, and the refusal is spent on the frame it
583
+ // lands in, so the next cell runs and can restructure. A Set or a WeakSet
584
+ // would dedupe them properly and cannot be used here: allocating either
585
+ // inside a realm that is at its heap ceiling, which is the realm this probe
586
+ // exists to weigh, leaves the runtime unable to assert itself empty at
587
+ // teardown and aborts the host process.
588
+ var path = []
589
+ var weigh = function (value, depth) {
590
+ var kind = typeof value
591
+ if (depth > ${weighDepth}) {
592
+ partial = true
593
+ return 0
594
+ }
595
+ if (budget <= 0) {
596
+ partial = true
597
+ return 0
598
+ }
599
+ budget = budget - 1
600
+ // Code units, not UTF-8 bytes, and deliberately: this walk answers "how
601
+ // much of the host's memory is this realm holding", and QuickJS stores a
602
+ // string as one or two bytes per code unit, so a unit count is the honest
603
+ // reading of the thing being bounded. It is also the only O(1) one, and
604
+ // that is load-bearing: the probe runs at frame close under the cell's own
605
+ // interrupt budget, so a scan of a two-hundred-megabyte realm is killed
606
+ // part way and a realm that cannot be weighed at all reads as weighing
607
+ // nothing. UTF-8 bytes are the unit of what the model is SHOWN, which is
608
+ // the print channel and the call ledger, not of what the realm holds.
609
+ if (kind === "string") return value.length
610
+ if (value === null || kind !== "object") return 8
611
+ for (var up = 0; up < path.length; up++) if (path[up] === value) return 8
612
+ path.push(value)
613
+ var sum = 8
614
+ // An array is walked by index so keysOf never allocates a second array as
615
+ // long as the first. Each transient descriptor dies with its iteration,
616
+ // and the same node budget that bounds the walk bounds that pressure.
617
+ // Reading through the descriptor is load-bearing: an index accessor is
618
+ // cell code, not data the memory probe may execute.
619
+ if (isArray(value)) {
620
+ var count = value.length
621
+ for (var item = 0; item < count && !partial; item++) {
622
+ var property = descriptorOf(value, String(item))
623
+ if (property === undefined || !("value" in property)) sum = sum + 8
624
+ else sum = sum + weigh(property.value, depth + 1)
625
+ }
626
+ path.pop()
627
+ return sum
628
+ }
629
+ // Collection entries live in internal slots, not own properties. Use
630
+ // captured native methods for both branding and iteration: instanceof,
631
+ // Symbol.iterator, and methods read from the value are cell-controlled.
632
+ // Catch only a failed brand check, never an incomplete entry traversal.
633
+ var isMap = false
634
+ var isSet = false
635
+ try {
636
+ mapSize(value)
637
+ isMap = true
638
+ } catch (error) {
639
+ try { setSize(value); isSet = true } catch (error) {}
640
+ }
641
+ if (isMap || isSet) {
642
+ // Iterator allocation can exhaust the heap too. Let that failure reach
643
+ // the outer catch so the reading is partial rather than empty.
644
+ var iterator = isMap ? mapEntries(value) : setValues(value)
645
+ while (!partial) {
646
+ var entry = isMap ? mapNext(iterator) : setNext(iterator)
647
+ if (entry.done) break
648
+ if (isMap) {
649
+ sum = sum + weigh(entry.value[0], depth + 1)
650
+ sum = sum + weigh(entry.value[1], depth + 1)
651
+ } else sum = sum + weigh(entry.value, depth + 1)
652
+ }
653
+ }
654
+ var keys = keysOf(value)
655
+ for (var key = 0; key < keys.length && !partial; key++) {
656
+ var property = descriptorOf(value, keys[key])
657
+ sum = sum + keys[key].length
658
+ if (property === undefined || !("value" in property)) sum = sum + 8
659
+ else sum = sum + weigh(property.value, depth + 1)
660
+ }
661
+ path.pop()
662
+ return sum
663
+ }
664
+ var dataProperty = function (value, name, fallbackValue) {
665
+ var descriptor = descriptorOf(value, name)
666
+ return descriptor !== undefined && "value" in descriptor ? descriptor.value : fallbackValue
667
+ }
668
+ for (var index = 0; index < names.length; index++) {
669
+ var name = names[index]
670
+ if (skip.indexOf(name) >= 0) continue
671
+ var before = total
672
+ try {
673
+ var descriptor = descriptorOf(globalThis, name)
674
+ if (descriptor === undefined || !("value" in descriptor)) {
675
+ total = total + 8
676
+ out.push({ name: name, type: descriptor === undefined ? "unreadable" : "accessor", size: "", bytes: 8 })
677
+ continue
678
+ }
679
+ var value = descriptor.value
680
+ var kind = typeof value
681
+ var bytes = weigh(value, 0)
682
+ total = total + bytes
683
+ if (value === null) out.push({ name: name, type: "null", size: "", bytes: bytes })
684
+ else if (kind === "undefined") out.push({ name: name, type: "unset", size: "", bytes: bytes })
685
+ else if (kind === "string") out.push({ name: name, type: "string", size: value.length + " chars", bytes: bytes })
686
+ else if (kind === "function") out.push({ name: name, type: "function", size: "arity " + dataProperty(value, "length", 0), bytes: bytes })
687
+ else if (isArray(value)) out.push({ name: name, type: "array", size: dataProperty(value, "length", 0) + " items", bytes: bytes })
688
+ else if (kind === "object") out.push({ name: name, type: "object", size: keysOf(value).length + " keys", bytes: bytes })
689
+ else out.push({ name: name, type: kind, size: String(value), bytes: bytes })
690
+ if (partial) {
691
+ partialRoot = name
692
+ partialBytes = bytes
693
+ break
694
+ }
695
+ } catch (error) {
696
+ // A name the probe cannot read at all: a proxy that refuses reflection,
697
+ // or a realm so large that walking it is itself what runs out of heap.
698
+ // Either way this reading is a floor and not a total, so it is reported
699
+ // as partial rather than weighed at nothing. No accessor is invoked to
700
+ // get here: every property read above goes through its own descriptor.
701
+ total = before + 8
702
+ out.push({ name: name, type: "unreadable", size: "", bytes: 8 })
703
+ partial = true
704
+ partialRoot = name
705
+ partialBytes = 8
706
+ break
707
+ }
708
+ }
709
+ return stringify(partialRoot === null
710
+ ? { names: out, bytes: total, partial: false }
711
+ : { names: out, bytes: total, partial: true, partialRoot: partialRoot, partialBytes: partialBytes })
712
+ }
713
+ })(
714
+ Object.getOwnPropertyNames,
715
+ Object.getOwnPropertyDescriptor,
716
+ Object.keys,
717
+ Array.isArray,
718
+ JSON.stringify,
719
+ String,
720
+ Function.prototype.call.bind(Object.getOwnPropertyDescriptor(Map.prototype, "size").get),
721
+ Function.prototype.call.bind(Map.prototype.entries),
722
+ Function.prototype.call.bind(Object.getPrototypeOf(new Map().entries()).next),
723
+ Function.prototype.call.bind(Object.getOwnPropertyDescriptor(Set.prototype, "size").get),
724
+ Function.prototype.call.bind(Set.prototype.values),
725
+ Function.prototype.call.bind(Object.getPrototypeOf(new Set().values()).next),
726
+ JSON.parse(${baseline})
727
+ )`;
728
+ /** One name as the probe reports it, before the panel drops the weight. */
729
+ const Weighed = Schema.Struct({
730
+ name: Schema.String,
731
+ type: Schema.String,
732
+ size: Schema.String,
733
+ bytes: Schema.Number
734
+ });
735
+ const ProbeReading = {
736
+ names: Schema.Array(Weighed),
737
+ bytes: Schema.Number
738
+ };
739
+ const decodeProbe = Schema.decodeUnknownSync(Schema.Union([
740
+ Schema.Struct({ ...ProbeReading, partial: Schema.Literal(false) }),
741
+ Schema.Struct({
742
+ ...ProbeReading,
743
+ partial: Schema.Literal(true),
744
+ partialRoot: Schema.String,
745
+ partialBytes: Schema.Number
746
+ })
747
+ ]));
748
+ /**
749
+ * States the run's memory ceiling in the terms the realm can act on.
750
+ *
751
+ * Written for the model, because the model is who reads it: the total, the
752
+ * ceiling, and the three names to reassign. A `var`-created global is
753
+ * non-configurable, so `delete` cannot remove one and assignment is the whole of
754
+ * the recovery — which is also why the refusal has to be spent where it lands.
755
+ * Freeing is done by a cell, and a cell that is refused cannot free anything, so
756
+ * a ceiling that stayed shut would ask for the one act it had just made
757
+ * impossible. See {@link openRealm}.
758
+ */
759
+ const overBudget = (held, ceiling, weighed) => {
760
+ const heaviest = [...weighed]
761
+ .sort((left, right) => right.bytes - left.bytes)
762
+ .slice(0, 3)
763
+ .map((entry) => `${entry.name} (${entry.bytes})`);
764
+ return new Cell.Rejected({
765
+ code: "limit_exceeded",
766
+ message: `The names this realm holds weigh ${held} bytes, over this run's ceiling of ${ceiling}. ` +
767
+ `Nothing ran this frame, and your next cell does run: spend it freeing the largest by assigning over them — ${heaviest.join(", ")} — ` +
768
+ "because a name a cell bound can be reassigned but never deleted. Every other name is still bound, " +
769
+ "and a realm still over the ceiling after that cell is refused again."
770
+ });
771
+ };
772
+ /**
773
+ * States a reading the probe could not finish, in the same terms as one it could.
774
+ *
775
+ * A walk that ran out of node budget, out of depth, or out of heap stopped
776
+ * somewhere inside one name, so what it counted is a floor and not a total. The
777
+ * honest reading of a floor is "at least this much", and a ceiling that cannot
778
+ * be shown to be respected is a ceiling that is spent: the frame is refused
779
+ * exactly as an over-budget one is, and for the same recovery. Failing the other
780
+ * way is what let a realm holding eleven megabytes of string sit under a four
781
+ * megabyte ceiling, because the budget ran out before the string was reached.
782
+ *
783
+ * The name is rendered the way {@link overBudget} renders one, so a model that
784
+ * has read one refusal can act on the other without learning a second shape.
785
+ */
786
+ const tooLargeToWeigh = (held, ceiling, root, bytes) => new Cell.Rejected({
787
+ code: "limit_exceeded",
788
+ message: `This realm is too large to measure: weighing it stopped inside ${root} (${bytes}) before it finished, ` +
789
+ `so the ${held} bytes counted are a floor and not a total, and this run's ceiling of ${ceiling} is treated as spent. ` +
790
+ "Nothing ran this frame, and your next cell does run: spend it freeing that name by assigning over it, " +
791
+ "because a name a cell bound can be reassigned but never deleted. Every other name is still bound, " +
792
+ "and a realm still too large to weigh after that cell is refused again."
793
+ });
794
+ /**
795
+ * Opens one QuickJS realm that lives for a whole run.
796
+ *
797
+ * The acquire/release is the pair the per-cell binding uses, moved up to the
798
+ * caller's scope: teardown is still scope finalization and cancellation is still
799
+ * fiber interruption, so nothing threads an abort signal. What changes is
800
+ * lifetime — every cell is evaluated against the same context, so a top-level
801
+ * declaration made in frame 3 is still bound in frame 9.
802
+ *
803
+ * Each cell is evaluated as `evalCode(text, "cell-<frame>.js", 128)`:
804
+ * `JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAG_ASYNC`. That combination, measured on the
805
+ * shipped variant, does three things at once — top-level `await` compiles, the
806
+ * result is a promise the existing drive loop already knows how to poll, and
807
+ * top-level declarations land in the realm rather than in an async wrapper that
808
+ * dies with the frame. The raw numeric flag is passed because
809
+ * `quickjs-emscripten-core`'s options object does not spell the async flag but
810
+ * hands a numeric `options` straight through.
811
+ *
812
+ * The per-frame budgets survive the move unchanged, because they are counters
813
+ * the interrupt handler reads rather than properties of the runtime: `timeMs`
814
+ * and `steps` reset at each frame's start and the compute clock keeps refunding
815
+ * host-call duration.
816
+ *
817
+ * `memoryBytes` becomes a **run** budget, and it is enforced in two places
818
+ * because one of them cannot see half the heap. `runtime.setMemoryLimit` covers
819
+ * the object graph and refuses any single allocation larger than the whole
820
+ * ceiling; it does not count string data at all on the shipped variant, so
821
+ * accumulation across frames escapes it entirely. The panel probe supplies that
822
+ * half: it weighs what the realm's own names hold and a frame that opens over
823
+ * the ceiling is refused before it runs, with the heaviest names stated, so the
824
+ * next cell frees by assignment and the realm survives.
825
+ *
826
+ * The refusal is spent where it lands, and that is the load-bearing half of it.
827
+ * Freeing is done by a cell, so a ceiling that stayed shut once it had fired
828
+ * would refuse the freeing cell too, and the run would spend every remaining
829
+ * frame being told to do the one thing it was being prevented from doing. So
830
+ * the reading is cleared with the refusal: the next frame runs, the probe weighs
831
+ * the realm again at its close, and a realm still over the ceiling is refused
832
+ * again. The bound is therefore a pair of frames — a cell may allocate past the
833
+ * ceiling and is told at the next frame, and a run that never frees alternates
834
+ * between refusal and cell rather than growing every frame — which is what "the
835
+ * names a run accumulates" can honestly mean when the harness never drops a
836
+ * value behind the model's back.
837
+ */
838
+ const openRealm = (module, options, clock) => Effect.gen(function* () {
839
+ const realmLimits = Sandbox.withDefaults(capabilities, options.limits);
840
+ /* v8 ignore next -- `withDefaults` fills `timeMs` from `defaultLimits` whenever the `timeMs` capability is declared, and this binding declares it, so the coalesce never reaches its fallback; it only discharges the optional type on `Sandbox.Limits` */
841
+ let timeMs = realmLimits.timeMs ?? Sandbox.defaultLimits.timeMs;
842
+ /* v8 ignore next -- `withDefaults` fills `memoryBytes` whenever the `memoryBytes` capability is declared, and this binding declares it, so the coalesce only discharges the optional type */
843
+ const memoryBytes = realmLimits.memoryBytes ?? Sandbox.defaultLimits.memoryBytes;
844
+ let stepBudget = realmLimits.steps;
845
+ let clockBase = clock.now();
846
+ let steps = 0;
847
+ let exhausted;
848
+ let pending = [];
849
+ let closing = true;
850
+ let ordinal = 0;
851
+ let boundary = { terminal: "timeout", dispatched: -1, settled: -1 };
852
+ let lines = [];
853
+ let retained = 0;
854
+ let unread = 0;
855
+ let recorded;
856
+ let justification;
857
+ const acquired = yield* Effect.acquireRelease(Effect.sync(() => {
858
+ const runtime = module.newRuntime();
859
+ /* v8 ignore else -- `withDefaults` fills `memoryBytes` whenever the `memoryBytes` capability is declared, and this binding declares it, so the heap ceiling is always set */
860
+ if (realmLimits.memoryBytes !== undefined) {
861
+ runtime.setMemoryLimit(realmLimits.memoryBytes);
862
+ }
863
+ runtime.setInterruptHandler(() => {
864
+ if (clock.now() - clockBase >= timeMs) {
865
+ exhausted = exhausted ?? timeLimitExceeded(timeMs);
866
+ return true;
867
+ }
868
+ if (stepBudget !== undefined && ++steps > stepBudget) {
869
+ exhausted = exhausted ?? new Cell.Rejected({
870
+ code: "limit_exceeded",
871
+ message: `This cell exceeded its limit of ${stepBudget} interpreter steps`
872
+ });
873
+ return true;
874
+ }
875
+ return false;
876
+ });
877
+ const context = runtime.newContext();
878
+ return { runtime, context };
879
+ }), ({ context, runtime }) => Effect.sync(() => {
880
+ context.dispose();
881
+ runtime.dispose();
882
+ }));
883
+ const { context, runtime } = acquired;
884
+ // Its own scoped resource rather than part of the acquire above, and that
885
+ // is the whole point: a helper the realm cannot evaluate used to be caught
886
+ // by hand, which meant a hand-written teardown and a branch no test could
887
+ // reach once a zero budget stopped being accepted. Registered as a second
888
+ // resource, the failure is ordinary: the scope closes, the finalizer above
889
+ // disposes the context and the runtime, and nothing leaks. Finalizers run
890
+ // in reverse, so this handle is still released before them.
891
+ const defineDataProperty = yield* Effect.acquireRelease(Effect.sync(() => context.unwrapResult(context.evalCode(`(function (defineProperty) {
892
+ return function (object, key, value) {
893
+ defineProperty(object, key, {
894
+ value: value,
895
+ writable: true,
896
+ enumerable: true,
897
+ configurable: true
898
+ })
899
+ }
900
+ })(Object.defineProperty)`))), (handle) => Effect.sync(() => handle.dispose()));
901
+ const install = (name, implementation) => {
902
+ const handle = context.newFunction(name, implementation);
903
+ context.setProp(context.global, name, handle);
904
+ handle.dispose();
905
+ };
906
+ const heapUsed = () => {
907
+ const snapshot = runtime.computeMemoryUsage();
908
+ try {
909
+ const usage = context.dump(snapshot);
910
+ return usage.memory_used_size;
911
+ }
912
+ finally {
913
+ snapshot.dispose();
914
+ }
915
+ };
916
+ const abort = (message) => {
917
+ closing = true;
918
+ for (const call of pending.splice(0))
919
+ call.abort(message);
920
+ };
921
+ const queue = (kind, flow, input, at) => {
922
+ if (closing)
923
+ throw new Error("The cell is closing; no further host calls are accepted");
924
+ const deferred = context.newPromise();
925
+ const reply = (payload) => {
926
+ const remaining = Math.max(0, memoryBytes - heapUsed());
927
+ // JSON byte length misses the storage for values, properties and array
928
+ // slots. Reserve scratch space for the bridge and conservatively price
929
+ // each allocation before any handle can poison the realm on failure.
930
+ let payloadBytes = 64 * 1024;
931
+ const values = [payload];
932
+ while (values.length > 0 && payloadBytes < remaining) {
933
+ const value = values.pop();
934
+ payloadBytes += 64;
935
+ if (typeof value === "string")
936
+ payloadBytes += bytes.size(value) * 2;
937
+ else if (value !== null && typeof value === "object") {
938
+ for (const [key, child] of Object.entries(value)) {
939
+ payloadBytes += 128 + bytes.size(key) * 2;
940
+ values.push(child);
941
+ }
942
+ }
943
+ }
944
+ if (payloadBytes >= remaining) {
945
+ exhausted = exhausted ?? new Cell.Rejected({
946
+ code: "limit_exceeded",
947
+ reason: "heap",
948
+ message: `The flow result is estimated to need ${payloadBytes} bytes of QuickJS heap, but only ${remaining} bytes remain ` +
949
+ `under this run's ceiling of ${memoryBytes}. The result was not materialized.`
950
+ });
951
+ deferred.resolve(context.undefined);
952
+ deferred.dispose();
953
+ return;
954
+ }
955
+ let handle;
956
+ try {
957
+ handle = handleFromJson(context, defineDataProperty, payload);
958
+ deferred.resolve(handle);
959
+ }
960
+ catch {
961
+ // Deep JSON can exhaust the host stack while building handles even
962
+ // when its allocation fits. Settle the bridge after cleanup so the
963
+ // rejected frame remains recordable and realm disposal stays safe.
964
+ exhausted = new Cell.Rejected({
965
+ code: "limit_exceeded",
966
+ reason: "heap",
967
+ message: "Materializing the flow result exceeded the realm's limits."
968
+ });
969
+ deferred.resolve(context.undefined);
970
+ }
971
+ finally {
972
+ handle?.dispose();
973
+ deferred.dispose();
974
+ }
975
+ };
976
+ pending.push({
977
+ ordinal: ordinal++,
978
+ flow,
979
+ input,
980
+ kind,
981
+ ...(at === undefined ? {} : { at }),
982
+ settle: (result) => reply(result.outcome === "success"
983
+ ? { ok: true, value: result.value ?? null }
984
+ : { ok: false, aborted: false, failure: Cell.callFailure(result) }),
985
+ abort: (message) => reply({
986
+ ok: false,
987
+ aborted: true,
988
+ failure: Cell.callFailure(refusal(undefined, message))
989
+ })
990
+ });
991
+ return deferred.handle;
992
+ };
993
+ install("__call", (flowHandle, inputHandle, atHandle) => queue("call", context.getString(flowHandle), Schema.decodeUnknownSync(Schema.Json)(JSON.parse(context.getString(inputHandle))), decodedAt(context.getString(atHandle))));
994
+ install("__checkpoint", () => queue("checkpoint", checkpointFlow, null, undefined));
995
+ install("__print", (partsHandle) => {
996
+ // What the model reads is bounded at frame close; what the host holds
997
+ // while the cell is still running is bounded here, and it has to be a
998
+ // different number because the two are answers to different questions.
999
+ // A cell that prints in a loop hands over one payload per statement, and
1000
+ // every one of them is copied out of the WASM heap, parsed and decoded
1001
+ // before anything can decide it is surplus. Measured on this variant, a
1002
+ // print loop inside the default step budget took the host's resident set
1003
+ // from 288 MB to 746 MB, and two hundred prints of one 3 MiB string took
1004
+ // it to 1.4 GB — while the model, both times, was shown 16 KiB. Past the
1005
+ // retention ceiling the payload is not read at all: the handle belongs to
1006
+ // the caller, so ignoring it costs nothing, and the count of what was
1007
+ // ignored is stated at frame close rather than dropped in silence.
1008
+ if (retained >= Sandbox.printRetainedBytes) {
1009
+ unread = unread + 1;
1010
+ return context.undefined;
1011
+ }
1012
+ const line = printed(context.getString(partsHandle));
1013
+ retained = retained + bytes.size(line.text) + 1;
1014
+ lines.push(line);
1015
+ return context.undefined;
1016
+ });
1017
+ install("__intent", (kindHandle, payloadHandle) => {
1018
+ const kind = context.getString(kindHandle);
1019
+ const payload = Schema.decodeUnknownSync(Schema.Json)(JSON.parse(context.getString(payloadHandle)));
1020
+ if (kind === "done")
1021
+ recorded = { kind: "done", output: Cell.renderText(payload), value: payload };
1022
+ else if (kind === "park") {
1023
+ const park = parkPayload(payload);
1024
+ recorded = { kind: "park", reason: park.reason, message: Cell.renderText(park.message) };
1025
+ }
1026
+ else
1027
+ justification = Cell.renderText(payload);
1028
+ return context.undefined;
1029
+ });
1030
+ const installed = context.evalCode(replPrelude(catalogOf(options.flows)));
1031
+ if (installed.error !== undefined) {
1032
+ const failure = context.dump(installed.error);
1033
+ installed.error.dispose();
1034
+ return yield* new Sandbox.SandboxError({
1035
+ code: "runtime_failed",
1036
+ message: "The sandbox prelude failed to install",
1037
+ cause: failure
1038
+ });
1039
+ }
1040
+ // What the prelude evaluated to: the function that clears the completion
1041
+ // seal. The host holds it as a handle rather than as a global, so no cell
1042
+ // can reach it and no cell can shadow it.
1043
+ const openFrame = installed.value;
1044
+ yield* Effect.addFinalizer(() => Effect.sync(() => openFrame.dispose()));
1045
+ // The names a fresh realm already holds, snapshotted after the prelude so
1046
+ // `ctx` and `console` are part of the baseline rather than part of the
1047
+ // panel. Doubly encoded so no name — `__proto__` included — can reach the
1048
+ // probe's source as anything but data.
1049
+ const snapshot = context.unwrapResult(context.evalCode("JSON.stringify(Object.getOwnPropertyNames(globalThis))"));
1050
+ const baseline = context.getString(snapshot);
1051
+ snapshot.dispose();
1052
+ // Built once, called every frame. The handle lives on this scope beside the
1053
+ // context that made it, which is what keeps the probe's intrinsics the ones
1054
+ // a fresh realm had rather than the ones a cell left behind.
1055
+ const probe = context.unwrapResult(context.evalCode(panelProbe(JSON.stringify(baseline))));
1056
+ yield* Effect.addFinalizer(() => Effect.sync(() => probe.dispose()));
1057
+ let bindings = [];
1058
+ let weighed = [];
1059
+ let held = 0;
1060
+ let unweighed;
1061
+ const evaluateFrame = (evaluation, limits) => {
1062
+ /* v8 ignore next -- the validated frame inherits the opening totalMs default */
1063
+ const totalMs = limits.totalMs ?? Sandbox.defaultLimits.totalMs;
1064
+ const frameStarted = clock.now();
1065
+ let pausedAtForFrame;
1066
+ let pausedMs = 0;
1067
+ return Effect.gen(function* () {
1068
+ /* v8 ignore next -- the validated frame inherits the opening timeMs default */
1069
+ timeMs = limits.timeMs ?? Sandbox.defaultLimits.timeMs;
1070
+ stepBudget = limits.steps;
1071
+ // Per-frame budgets and per-frame buffers, reset before anything can
1072
+ // settle the frame. They are counters, not properties of the runtime, so
1073
+ // a realm that outlives one cell still charges each cell its own — and
1074
+ // resetting them first is what keeps a frame that ends before its cell
1075
+ // runs from being handed the previous frame's print buffer.
1076
+ clockBase = clock.now();
1077
+ steps = 0;
1078
+ exhausted = undefined;
1079
+ pending = [];
1080
+ closing = false;
1081
+ ordinal = 0;
1082
+ boundary = { terminal: "timeout", dispatched: -1, settled: -1 };
1083
+ lines = [];
1084
+ retained = 0;
1085
+ unread = 0;
1086
+ recorded = undefined;
1087
+ justification = undefined;
1088
+ // The realm's own per-frame state: the seal a completion set. A frame
1089
+ // whose transition the harness refused is asked again inside the same
1090
+ // frame, so the retry has to open on an unsealed realm.
1091
+ if (evaluation.flows === undefined) {
1092
+ context.unwrapResult(context.callFunction(openFrame, context.undefined)).dispose();
1093
+ }
1094
+ else {
1095
+ const catalog = context.newString(catalogOf(evaluation.flows));
1096
+ try {
1097
+ context.unwrapResult(context.callFunction(openFrame, context.undefined, catalog)).dispose();
1098
+ }
1099
+ finally {
1100
+ catalog.dispose();
1101
+ }
1102
+ }
1103
+ // Whatever the frame produced, the prints are delivered with it and the
1104
+ // panel is read after it, so the answer is assembled in one place. A
1105
+ // frame that printed past the retention ceiling says so as its last
1106
+ // line, because a buffer that simply stopped would read as a cell that
1107
+ // simply stopped printing.
1108
+ const frameOf = (outcome) => ({
1109
+ outcome,
1110
+ ...(outcome._tag === "rejected" && outcome.code === "limit_exceeded"
1111
+ ? { boundary: { ...boundary, terminal: "settled" } }
1112
+ : {}),
1113
+ prints: printChannel.buffer(lines, unread),
1114
+ bindings
1115
+ });
1116
+ // The run's memory budget, judged against what the realm's own names
1117
+ // weigh rather than against a heap counter that cannot see them. A
1118
+ // frame that opens over the ceiling runs nothing, so nothing is lost
1119
+ // and the recovery is one assignment — and the reading is cleared with
1120
+ // the refusal, because the cell that frees is a cell and has to run.
1121
+ // Left standing, the ceiling would refuse that cell too, and every one
1122
+ // after it, so the run would spend the rest of its frames being told to
1123
+ // do the one thing it was being prevented from doing. Cleared, the next
1124
+ // frame runs, the probe weighs the realm again at its close, and a realm
1125
+ // still over the ceiling is refused again.
1126
+ if (unweighed !== undefined) {
1127
+ const refusal = tooLargeToWeigh(held, memoryBytes, unweighed.root, unweighed.bytes);
1128
+ unweighed = undefined;
1129
+ held = 0;
1130
+ return frameOf(refusal);
1131
+ }
1132
+ if (held > memoryBytes) {
1133
+ const refusal = overBudget(held, memoryBytes, weighed);
1134
+ held = 0;
1135
+ return frameOf(refusal);
1136
+ }
1137
+ // The boundary's own parse when it has one; see `RealmEvaluation.program`.
1138
+ const compiled = evaluation.program ?? Sandbox.compile(evaluation.cell);
1139
+ if (compiled instanceof Cell.Rejected)
1140
+ return frameOf(compiled);
1141
+ const started = context.evalCode(compiled, `cell-${evaluation.frame}.js`, 128);
1142
+ if (started.error !== undefined) {
1143
+ const failure = context.dump(started.error);
1144
+ started.error.dispose();
1145
+ return frameOf(new Cell.Rejected({
1146
+ code: "compile_failed",
1147
+ /* v8 ignore next -- QuickJS reports a compile failure as an Error object, so the `message` arm is what a parser disagreement takes; `String(failure)` only discharges the `unknown` `context.dump` is typed as */
1148
+ message: `The cell did not compile: ${typeof failure === "object" && failure !== null && "message" in failure
1149
+ ? String(failure.message)
1150
+ : String(failure)}`
1151
+ }));
1152
+ }
1153
+ const cellHandle = started.value;
1154
+ let settled;
1155
+ const poll = () => {
1156
+ // Teardown alone runs jobs once admission closes, under its own budget.
1157
+ if (closing)
1158
+ return;
1159
+ runtime.executePendingJobs();
1160
+ if (exhausted !== undefined) {
1161
+ settled = exhausted;
1162
+ return;
1163
+ }
1164
+ const state = context.getPromiseState(cellHandle);
1165
+ if (state.type === "pending")
1166
+ return;
1167
+ if (state.type === "fulfilled") {
1168
+ // A script's completion value is not a transition and is never read:
1169
+ // a REPL cell says what it wants by calling `ctx.done` or `ctx.park`,
1170
+ // and saying nothing asks for another frame.
1171
+ state.value.dispose();
1172
+ settled = replOutcome(recorded, justification);
1173
+ return;
1174
+ }
1175
+ const error = context.dump(state.error);
1176
+ state.error.dispose();
1177
+ settled = raisedFrom(error);
1178
+ };
1179
+ const outcome = yield* Sandbox.driveCell({
1180
+ pending,
1181
+ replay: evaluation.replay,
1182
+ progress: (dispatched, settled) => {
1183
+ boundary = { terminal: "timeout", dispatched, settled };
1184
+ },
1185
+ ...(evaluation.mint === undefined
1186
+ ? {}
1187
+ : {
1188
+ mint: (mint) => Effect.suspend(() => {
1189
+ const pausedAt = clock.now();
1190
+ return evaluation.mint(mint).pipe(Effect.onExit(() => Effect.sync(() => {
1191
+ clockBase += clock.now() - pausedAt;
1192
+ })));
1193
+ })
1194
+ }),
1195
+ ...(evaluation.bounded === undefined ? {} : { bounded: evaluation.bounded }),
1196
+ flush: () => poll(),
1197
+ finished: () => {
1198
+ poll();
1199
+ if (settled !== undefined)
1200
+ return settled;
1201
+ if (pending.length > 0)
1202
+ return undefined;
1203
+ return new Cell.Rejected({
1204
+ code: "stalled",
1205
+ message: "The cell awaited something that never settles. Inside a cell the only thing worth awaiting is ctx.call."
1206
+ });
1207
+ },
1208
+ abort,
1209
+ handler: (call) => Effect.suspend(() => {
1210
+ const pausedAt = clock.now();
1211
+ const pausesFrame = limits.pauseTotalMsFor?.includes(call.flow) === true;
1212
+ if (pausesFrame)
1213
+ pausedAtForFrame = pausedAt;
1214
+ return evaluation.call(call).pipe(Effect.onExit(() => Effect.sync(() => {
1215
+ clockBase += clock.now() - pausedAt;
1216
+ if (pausesFrame) {
1217
+ pausedMs += clock.now() - pausedAt;
1218
+ pausedAtForFrame = undefined;
1219
+ }
1220
+ })));
1221
+ }),
1222
+ limits
1223
+ }).pipe(
1224
+ // Closing is irreversible within this frame. Rejecting a bridge
1225
+ // resumes user catch/finally blocks, so admission must close before
1226
+ // any of those jobs can allocate another host-owned promise handle.
1227
+ Effect.ensuring(Effect.sync(() => {
1228
+ closing = true;
1229
+ try {
1230
+ // A cleanup may keep scheduling promise jobs even without host
1231
+ // calls. Bound that work independently of the compute clock.
1232
+ for (let jobs = 0;; jobs++) {
1233
+ abort("The cell was interrupted");
1234
+ if (jobs >= 1024 || !runtime.hasPendingJob())
1235
+ break;
1236
+ runtime.executePendingJobs(1).dispose();
1237
+ }
1238
+ }
1239
+ finally {
1240
+ cellHandle.dispose();
1241
+ }
1242
+ })));
1243
+ if (evaluation.replay !== undefined) {
1244
+ // A timed-out attempt never reached the probe below. Keep its realm
1245
+ // accounting too, so the next frame sees the same memory admission.
1246
+ return { outcome: evaluation.replay.outcome, prints: "", bindings, boundary: evaluation.replay.boundary };
1247
+ }
1248
+ // The panel, read from the realm the cell just ran in. It shares the
1249
+ // frame's remaining budget, so a cell that spent all of its own leaves
1250
+ // the previous reading standing rather than an empty one. What a cell
1251
+ // cannot do is take the reading away: the probe holds its own
1252
+ // intrinsics from before any cell ran, so a realm whose `Object` a cell
1253
+ // has rebound is still weighed and still named.
1254
+ const read = context.callFunction(probe, context.undefined);
1255
+ if (read.error === undefined) {
1256
+ const measured = decodeProbe(JSON.parse(context.getString(read.value)));
1257
+ read.value.dispose();
1258
+ weighed = measured.names;
1259
+ held = measured.bytes;
1260
+ unweighed = measured.partial ? { root: measured.partialRoot, bytes: measured.partialBytes } : undefined;
1261
+ bindings = measured.names.map((entry) => new VariablesPanel.Binding({ name: entry.name, type: entry.type, size: entry.size }));
1262
+ }
1263
+ else {
1264
+ read.error.dispose();
1265
+ }
1266
+ return frameOf(outcome);
1267
+ }).pipe(limits.pauseTotalMsFor?.length && evaluation.replay === undefined
1268
+ ? Effect.raceFirst(Effect.gen(function* () {
1269
+ for (;;) {
1270
+ const now = clock.now();
1271
+ const elapsed = now - frameStarted - pausedMs -
1272
+ (pausedAtForFrame === undefined ? 0 : now - pausedAtForFrame);
1273
+ const remaining = totalMs - elapsed;
1274
+ if (remaining <= 0) {
1275
+ return {
1276
+ outcome: timeLimitExceeded(totalMs),
1277
+ boundary,
1278
+ prints: "",
1279
+ bindings
1280
+ };
1281
+ }
1282
+ yield* Effect.sleep(Duration.millis(Math.max(1, remaining)));
1283
+ }
1284
+ }))
1285
+ : Effect.timeoutOrElse({
1286
+ // Replay is stopped by its recorded boundary, not a second clock.
1287
+ duration: evaluation.replay === undefined ? totalMs : Infinity,
1288
+ orElse: () => Effect.succeed({
1289
+ outcome: timeLimitExceeded(totalMs),
1290
+ boundary,
1291
+ prints: "",
1292
+ bindings
1293
+ })
1294
+ }));
1295
+ };
1296
+ const evaluate = (evaluation) => Sandbox.evaluationLimits(realmLimits, evaluation.limits).pipe(Effect.flatMap((limits) => evaluateFrame(evaluation, limits)));
1297
+ return { evaluate };
1298
+ });
1299
+ /**
1300
+ * Loads a QuickJS module through the sandbox's typed failure boundary.
1301
+ *
1302
+ * @category constructors
1303
+ * @since 0.1.0
1304
+ */
1305
+ export const loadModule = (loader) => Effect.tryPromise({
1306
+ try: loader,
1307
+ catch: (cause) => new Sandbox.SandboxError({
1308
+ code: "runtime_failed",
1309
+ message: "QuickJS WebAssembly module could not be loaded",
1310
+ cause
1311
+ })
1312
+ });
1313
+ /**
1314
+ * Constructs the QuickJS sandbox over the build the host names, compiling the
1315
+ * WebAssembly module once.
1316
+ *
1317
+ * @category constructors
1318
+ * @since 0.1.0
1319
+ */
1320
+ export const makeWithVariant = Effect
1321
+ .gen(function* () {
1322
+ const clock = yield* ComputeClock;
1323
+ const { variant } = yield* Variant;
1324
+ const module = yield* loadModule(loaderFor(variant));
1325
+ return Sandbox.make({
1326
+ capabilities,
1327
+ openRealm: (options) => openRealm(module, options, clock)
1328
+ });
1329
+ });
1330
+ /**
1331
+ * Constructs the QuickJS sandbox over the single-file build.
1332
+ *
1333
+ * The build is fixed here rather than left in the requirements, so the clock
1334
+ * stays the only seam this constructor asks its caller to fill. A host that
1335
+ * names its own build uses {@link makeWithVariant}.
1336
+ *
1337
+ * @category constructors
1338
+ * @since 0.1.0
1339
+ * @slop
1340
+ */
1341
+ export const makeWithClock = makeWithVariant.pipe(Effect.provide(layerVariantLive));
1342
+ /**
1343
+ * Constructs the QuickJS sandbox with the live clock layer.
1344
+ *
1345
+ * @category constructors
1346
+ * @since 0.1.0
1347
+ */
1348
+ export const make = makeWithClock.pipe(Effect.provide(layerClockLive));
1349
+ /**
1350
+ * Provides the QuickJS sandbox over the build the host names.
1351
+ *
1352
+ * @category layers
1353
+ * @since 0.1.0
1354
+ */
1355
+ export const layerWithVariant = Layer.effect(Sandbox.Sandbox)(makeWithVariant.pipe(Effect.provide(layerClockLive)));
1356
+ /**
1357
+ * Provides the QuickJS sandbox over the single-file build.
1358
+ *
1359
+ * @category layers
1360
+ * @since 0.1.0
1361
+ * @slop
1362
+ */
1363
+ export const layer = Layer.effect(Sandbox.Sandbox)(make);
1364
+ //# sourceMappingURL=QuickJSSandbox.js.map