@archmax-ai/harness 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (351) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +219 -0
  3. package/dist/agent.d.ts +174 -0
  4. package/dist/agent.js +140 -0
  5. package/dist/agent.js.map +1 -0
  6. package/dist/assembly/compose.d.ts +170 -0
  7. package/dist/assembly/compose.js +391 -0
  8. package/dist/assembly/compose.js.map +1 -0
  9. package/dist/assembly/delegation-registry.d.ts +5 -0
  10. package/dist/assembly/delegation-registry.js +118 -0
  11. package/dist/assembly/delegation-registry.js.map +1 -0
  12. package/dist/assembly/index.d.ts +192 -0
  13. package/dist/assembly/index.js +265 -0
  14. package/dist/assembly/index.js.map +1 -0
  15. package/dist/assembly/plain.d.ts +7 -0
  16. package/dist/assembly/plain.js +41 -0
  17. package/dist/assembly/plain.js.map +1 -0
  18. package/dist/authoring-skill/archmax-harness/README.md +76 -0
  19. package/dist/authoring-skill/archmax-harness/SKILL.md +241 -0
  20. package/dist/authoring-skill/archmax-harness/references/backend-integration.md +626 -0
  21. package/dist/authoring-skill/archmax-harness/references/cases.md +41 -0
  22. package/dist/authoring-skill/archmax-harness/references/diagnostics.md +51 -0
  23. package/dist/authoring-skill/archmax-harness/references/hook-and-test-scripts.md +1070 -0
  24. package/dist/authoring-skill/archmax-harness/references/hooks-and-scripts.md +82 -0
  25. package/dist/authoring-skill/archmax-harness/references/wiring.md +101 -0
  26. package/dist/authoring-skill/archmax-harness/references/workflow-schema.md +1631 -0
  27. package/dist/authoring-skill/archmax-harness/references/workflow-yaml.md +241 -0
  28. package/dist/behaviour/support.d.ts +232 -0
  29. package/dist/behaviour/support.js +339 -0
  30. package/dist/behaviour/support.js.map +1 -0
  31. package/dist/cli/banner.d.ts +11 -0
  32. package/dist/cli/banner.js +29 -0
  33. package/dist/cli/banner.js.map +1 -0
  34. package/dist/cli/bootstrap.d.ts +33 -0
  35. package/dist/cli/bootstrap.js +153 -0
  36. package/dist/cli/bootstrap.js.map +1 -0
  37. package/dist/cli/command.d.ts +39 -0
  38. package/dist/cli/command.js +97 -0
  39. package/dist/cli/command.js.map +1 -0
  40. package/dist/cli/state-flow.d.ts +46 -0
  41. package/dist/cli/state-flow.js +268 -0
  42. package/dist/cli/state-flow.js.map +1 -0
  43. package/dist/cli/style.d.ts +41 -0
  44. package/dist/cli/style.js +64 -0
  45. package/dist/cli/style.js.map +1 -0
  46. package/dist/cli/turn.d.ts +41 -0
  47. package/dist/cli/turn.js +161 -0
  48. package/dist/cli/turn.js.map +1 -0
  49. package/dist/cli.d.ts +10 -0
  50. package/dist/cli.js +426 -0
  51. package/dist/cli.js.map +1 -0
  52. package/dist/core/code-description.d.ts +22 -0
  53. package/dist/core/code-description.js +38 -0
  54. package/dist/core/code-description.js.map +1 -0
  55. package/dist/core/deepagents.d.ts +183 -0
  56. package/dist/core/deepagents.js +128 -0
  57. package/dist/core/deepagents.js.map +1 -0
  58. package/dist/core/events.d.ts +350 -0
  59. package/dist/core/events.js +205 -0
  60. package/dist/core/events.js.map +1 -0
  61. package/dist/core/frontmatter.d.ts +15 -0
  62. package/dist/core/frontmatter.js +32 -0
  63. package/dist/core/frontmatter.js.map +1 -0
  64. package/dist/core/listing-redact.d.ts +37 -0
  65. package/dist/core/listing-redact.js +88 -0
  66. package/dist/core/listing-redact.js.map +1 -0
  67. package/dist/core/match.d.ts +26 -0
  68. package/dist/core/match.js +75 -0
  69. package/dist/core/match.js.map +1 -0
  70. package/dist/core/message-readers.d.ts +84 -0
  71. package/dist/core/message-readers.js +159 -0
  72. package/dist/core/message-readers.js.map +1 -0
  73. package/dist/core/messages.d.ts +49 -0
  74. package/dist/core/messages.js +85 -0
  75. package/dist/core/messages.js.map +1 -0
  76. package/dist/core/mount-prompt.d.ts +28 -0
  77. package/dist/core/mount-prompt.js +55 -0
  78. package/dist/core/mount-prompt.js.map +1 -0
  79. package/dist/core/mount-redact.d.ts +28 -0
  80. package/dist/core/mount-redact.js +32 -0
  81. package/dist/core/mount-redact.js.map +1 -0
  82. package/dist/core/mounts.d.ts +88 -0
  83. package/dist/core/mounts.js +147 -0
  84. package/dist/core/mounts.js.map +1 -0
  85. package/dist/core/path-mapping.d.ts +52 -0
  86. package/dist/core/path-mapping.js +113 -0
  87. package/dist/core/path-mapping.js.map +1 -0
  88. package/dist/core/platform-prompt.generated.d.ts +2 -0
  89. package/dist/core/platform-prompt.generated.js +4 -0
  90. package/dist/core/platform-prompt.generated.js.map +1 -0
  91. package/dist/core/prompt.d.ts +42 -0
  92. package/dist/core/prompt.js +75 -0
  93. package/dist/core/prompt.js.map +1 -0
  94. package/dist/core/session-id.d.ts +38 -0
  95. package/dist/core/session-id.js +61 -0
  96. package/dist/core/session-id.js.map +1 -0
  97. package/dist/core/session-store.d.ts +85 -0
  98. package/dist/core/session-store.js +149 -0
  99. package/dist/core/session-store.js.map +1 -0
  100. package/dist/core/session-zone.d.ts +54 -0
  101. package/dist/core/session-zone.js +82 -0
  102. package/dist/core/session-zone.js.map +1 -0
  103. package/dist/core/skill-prompt.d.ts +31 -0
  104. package/dist/core/skill-prompt.js +54 -0
  105. package/dist/core/skill-prompt.js.map +1 -0
  106. package/dist/core/skill-redact.d.ts +15 -0
  107. package/dist/core/skill-redact.js +27 -0
  108. package/dist/core/skill-redact.js.map +1 -0
  109. package/dist/core/skills.d.ts +172 -0
  110. package/dist/core/skills.js +214 -0
  111. package/dist/core/skills.js.map +1 -0
  112. package/dist/core/tool-mocks.d.ts +23 -0
  113. package/dist/core/tool-mocks.js +39 -0
  114. package/dist/core/tool-mocks.js.map +1 -0
  115. package/dist/core/tool-telemetry.d.ts +16 -0
  116. package/dist/core/tool-telemetry.js +40 -0
  117. package/dist/core/tool-telemetry.js.map +1 -0
  118. package/dist/core/usage.d.ts +114 -0
  119. package/dist/core/usage.js +226 -0
  120. package/dist/core/usage.js.map +1 -0
  121. package/dist/core/workspace-context.d.ts +136 -0
  122. package/dist/core/workspace-context.js +178 -0
  123. package/dist/core/workspace-context.js.map +1 -0
  124. package/dist/core/workspace-prompt.d.ts +7 -0
  125. package/dist/core/workspace-prompt.js +102 -0
  126. package/dist/core/workspace-prompt.js.map +1 -0
  127. package/dist/core/workspace-router.d.ts +61 -0
  128. package/dist/core/workspace-router.js +145 -0
  129. package/dist/core/workspace-router.js.map +1 -0
  130. package/dist/core/workspace.d.ts +85 -0
  131. package/dist/core/workspace.js +193 -0
  132. package/dist/core/workspace.js.map +1 -0
  133. package/dist/core/zones.d.ts +181 -0
  134. package/dist/core/zones.js +202 -0
  135. package/dist/core/zones.js.map +1 -0
  136. package/dist/env.d.ts +99 -0
  137. package/dist/env.js +271 -0
  138. package/dist/env.js.map +1 -0
  139. package/dist/index.d.ts +265 -0
  140. package/dist/index.js +197 -0
  141. package/dist/index.js.map +1 -0
  142. package/dist/kernel/kernel.d.ts +192 -0
  143. package/dist/kernel/kernel.js +751 -0
  144. package/dist/kernel/kernel.js.map +1 -0
  145. package/dist/lifecycle/hook-shape.d.ts +44 -0
  146. package/dist/lifecycle/hook-shape.js +66 -0
  147. package/dist/lifecycle/hook-shape.js.map +1 -0
  148. package/dist/lifecycle/runner.d.ts +177 -0
  149. package/dist/lifecycle/runner.js +372 -0
  150. package/dist/lifecycle/runner.js.map +1 -0
  151. package/dist/lifecycle/transcript.d.ts +27 -0
  152. package/dist/lifecycle/transcript.js +43 -0
  153. package/dist/lifecycle/transcript.js.map +1 -0
  154. package/dist/machine/allow.d.ts +65 -0
  155. package/dist/machine/allow.js +107 -0
  156. package/dist/machine/allow.js.map +1 -0
  157. package/dist/machine/delegation.d.ts +9 -0
  158. package/dist/machine/delegation.js +10 -0
  159. package/dist/machine/delegation.js.map +1 -0
  160. package/dist/machine/diagnostic.d.ts +14 -0
  161. package/dist/machine/diagnostic.js +2 -0
  162. package/dist/machine/diagnostic.js.map +1 -0
  163. package/dist/machine/lint-spec.d.ts +4 -0
  164. package/dist/machine/lint-spec.js +266 -0
  165. package/dist/machine/lint-spec.js.map +1 -0
  166. package/dist/machine/load-spec.d.ts +90 -0
  167. package/dist/machine/load-spec.js +120 -0
  168. package/dist/machine/load-spec.js.map +1 -0
  169. package/dist/machine/machine.d.ts +273 -0
  170. package/dist/machine/machine.js +551 -0
  171. package/dist/machine/machine.js.map +1 -0
  172. package/dist/machine/mount-grants.d.ts +25 -0
  173. package/dist/machine/mount-grants.js +24 -0
  174. package/dist/machine/mount-grants.js.map +1 -0
  175. package/dist/machine/slug.d.ts +14 -0
  176. package/dist/machine/slug.js +17 -0
  177. package/dist/machine/slug.js.map +1 -0
  178. package/dist/machine/spec-schema.d.ts +662 -0
  179. package/dist/machine/spec-schema.js +717 -0
  180. package/dist/machine/spec-schema.js.map +1 -0
  181. package/dist/machine/tool-names.d.ts +98 -0
  182. package/dist/machine/tool-names.js +144 -0
  183. package/dist/machine/tool-names.js.map +1 -0
  184. package/dist/machine/triggers.d.ts +114 -0
  185. package/dist/machine/triggers.js +165 -0
  186. package/dist/machine/triggers.js.map +1 -0
  187. package/dist/machine/types.d.ts +186 -0
  188. package/dist/machine/types.js +12 -0
  189. package/dist/machine/types.js.map +1 -0
  190. package/dist/machine/validate-spec.d.ts +42 -0
  191. package/dist/machine/validate-spec.js +29 -0
  192. package/dist/machine/validate-spec.js.map +1 -0
  193. package/dist/machine/variables.d.ts +196 -0
  194. package/dist/machine/variables.js +415 -0
  195. package/dist/machine/variables.js.map +1 -0
  196. package/dist/public/cli.d.ts +15 -0
  197. package/dist/public/cli.js +14 -0
  198. package/dist/public/cli.js.map +1 -0
  199. package/dist/public/messages.d.ts +33 -0
  200. package/dist/public/messages.js +33 -0
  201. package/dist/public/messages.js.map +1 -0
  202. package/dist/public/sandbox.d.ts +99 -0
  203. package/dist/public/sandbox.js +32 -0
  204. package/dist/public/sandbox.js.map +1 -0
  205. package/dist/public/spec.d.ts +147 -0
  206. package/dist/public/spec.js +149 -0
  207. package/dist/public/spec.js.map +1 -0
  208. package/dist/public/testing.d.ts +71 -0
  209. package/dist/public/testing.js +39 -0
  210. package/dist/public/testing.js.map +1 -0
  211. package/dist/rubrics/rubrics.d.ts +135 -0
  212. package/dist/rubrics/rubrics.js +145 -0
  213. package/dist/rubrics/rubrics.js.map +1 -0
  214. package/dist/runtime/contract.d.ts +73 -0
  215. package/dist/runtime/contract.js +96 -0
  216. package/dist/runtime/contract.js.map +1 -0
  217. package/dist/sandbox/assets/parts/core.js +22 -0
  218. package/dist/sandbox/assets/parts/lifecycle-hook.js +47 -0
  219. package/dist/sandbox/bridge.d.ts +16 -0
  220. package/dist/sandbox/bridge.js +95 -0
  221. package/dist/sandbox/bridge.js.map +1 -0
  222. package/dist/sandbox/executor.d.ts +46 -0
  223. package/dist/sandbox/executor.js +119 -0
  224. package/dist/sandbox/executor.js.map +1 -0
  225. package/dist/sandbox/imports.d.ts +33 -0
  226. package/dist/sandbox/imports.js +67 -0
  227. package/dist/sandbox/imports.js.map +1 -0
  228. package/dist/sandbox/prelude.d.ts +12 -0
  229. package/dist/sandbox/prelude.js +51 -0
  230. package/dist/sandbox/prelude.js.map +1 -0
  231. package/dist/sandbox/ptc-gateway.d.ts +104 -0
  232. package/dist/sandbox/ptc-gateway.js +167 -0
  233. package/dist/sandbox/ptc-gateway.js.map +1 -0
  234. package/dist/sandbox/runtime.d.ts +59 -0
  235. package/dist/sandbox/runtime.js +51 -0
  236. package/dist/sandbox/runtime.js.map +1 -0
  237. package/dist/sandbox/tools.d.ts +34 -0
  238. package/dist/sandbox/tools.js +147 -0
  239. package/dist/sandbox/tools.js.map +1 -0
  240. package/dist/sessions/operations.d.ts +79 -0
  241. package/dist/sessions/operations.js +121 -0
  242. package/dist/sessions/operations.js.map +1 -0
  243. package/dist/sessions/resolve.d.ts +97 -0
  244. package/dist/sessions/resolve.js +145 -0
  245. package/dist/sessions/resolve.js.map +1 -0
  246. package/dist/sessions/resume.d.ts +242 -0
  247. package/dist/sessions/resume.js +288 -0
  248. package/dist/sessions/resume.js.map +1 -0
  249. package/dist/sessions/scope.d.ts +99 -0
  250. package/dist/sessions/scope.js +145 -0
  251. package/dist/sessions/scope.js.map +1 -0
  252. package/dist/sessions/summary.d.ts +65 -0
  253. package/dist/sessions/summary.js +56 -0
  254. package/dist/sessions/summary.js.map +1 -0
  255. package/dist/testing/assertions.d.ts +30 -0
  256. package/dist/testing/assertions.js +231 -0
  257. package/dist/testing/assertions.js.map +1 -0
  258. package/dist/testing/case-document.d.ts +141 -0
  259. package/dist/testing/case-document.js +51 -0
  260. package/dist/testing/case-document.js.map +1 -0
  261. package/dist/testing/case-schema.d.ts +29 -0
  262. package/dist/testing/case-schema.js +519 -0
  263. package/dist/testing/case-schema.js.map +1 -0
  264. package/dist/testing/discovery.d.ts +10 -0
  265. package/dist/testing/discovery.js +24 -0
  266. package/dist/testing/discovery.js.map +1 -0
  267. package/dist/testing/driver.d.ts +78 -0
  268. package/dist/testing/driver.js +117 -0
  269. package/dist/testing/driver.js.map +1 -0
  270. package/dist/testing/grade.d.ts +116 -0
  271. package/dist/testing/grade.js +261 -0
  272. package/dist/testing/grade.js.map +1 -0
  273. package/dist/testing/interpreter.d.ts +55 -0
  274. package/dist/testing/interpreter.js +103 -0
  275. package/dist/testing/interpreter.js.map +1 -0
  276. package/dist/testing/mock-middleware.d.ts +5 -0
  277. package/dist/testing/mock-middleware.js +33 -0
  278. package/dist/testing/mock-middleware.js.map +1 -0
  279. package/dist/testing/runner.d.ts +205 -0
  280. package/dist/testing/runner.js +266 -0
  281. package/dist/testing/runner.js.map +1 -0
  282. package/dist/testing/target.d.ts +27 -0
  283. package/dist/testing/target.js +21 -0
  284. package/dist/testing/target.js.map +1 -0
  285. package/dist/validate/validate.d.ts +41 -0
  286. package/dist/validate/validate.js +669 -0
  287. package/dist/validate/validate.js.map +1 -0
  288. package/dist/workflow/agent-tools.d.ts +10 -0
  289. package/dist/workflow/agent-tools.js +10 -0
  290. package/dist/workflow/agent-tools.js.map +1 -0
  291. package/dist/workflow/checkpointer.d.ts +52 -0
  292. package/dist/workflow/checkpointer.js +200 -0
  293. package/dist/workflow/checkpointer.js.map +1 -0
  294. package/dist/workflow/control-tools.d.ts +174 -0
  295. package/dist/workflow/control-tools.js +468 -0
  296. package/dist/workflow/control-tools.js.map +1 -0
  297. package/dist/workflow/governance.d.ts +104 -0
  298. package/dist/workflow/governance.js +546 -0
  299. package/dist/workflow/governance.js.map +1 -0
  300. package/dist/workflow/middleware.d.ts +85 -0
  301. package/dist/workflow/middleware.js +283 -0
  302. package/dist/workflow/middleware.js.map +1 -0
  303. package/dist/workflow/on-error.d.ts +25 -0
  304. package/dist/workflow/on-error.js +58 -0
  305. package/dist/workflow/on-error.js.map +1 -0
  306. package/dist/workflow/parks.d.ts +46 -0
  307. package/dist/workflow/parks.js +513 -0
  308. package/dist/workflow/parks.js.map +1 -0
  309. package/dist/workflow/paths.d.ts +67 -0
  310. package/dist/workflow/paths.js +108 -0
  311. package/dist/workflow/paths.js.map +1 -0
  312. package/dist/workflow/prompt-cache.d.ts +70 -0
  313. package/dist/workflow/prompt-cache.js +103 -0
  314. package/dist/workflow/prompt-cache.js.map +1 -0
  315. package/dist/workflow/prompt-pruning.d.ts +20 -0
  316. package/dist/workflow/prompt-pruning.js +83 -0
  317. package/dist/workflow/prompt-pruning.js.map +1 -0
  318. package/dist/workflow/render-prompt.d.ts +45 -0
  319. package/dist/workflow/render-prompt.js +140 -0
  320. package/dist/workflow/render-prompt.js.map +1 -0
  321. package/dist/workflow/runtime-config.d.ts +7 -0
  322. package/dist/workflow/runtime-config.js +9 -0
  323. package/dist/workflow/runtime-config.js.map +1 -0
  324. package/dist/workflow/session-artifacts.d.ts +90 -0
  325. package/dist/workflow/session-artifacts.js +134 -0
  326. package/dist/workflow/session-artifacts.js.map +1 -0
  327. package/dist/workflow/session-view.d.ts +31 -0
  328. package/dist/workflow/session-view.js +94 -0
  329. package/dist/workflow/session-view.js.map +1 -0
  330. package/dist/workflow/snapshot.d.ts +14 -0
  331. package/dist/workflow/snapshot.js +97 -0
  332. package/dist/workflow/snapshot.js.map +1 -0
  333. package/dist/workflow/state.d.ts +347 -0
  334. package/dist/workflow/state.js +322 -0
  335. package/dist/workflow/state.js.map +1 -0
  336. package/dist/workflow/sub-workflow.d.ts +174 -0
  337. package/dist/workflow/sub-workflow.js +392 -0
  338. package/dist/workflow/sub-workflow.js.map +1 -0
  339. package/dist/workflow/tool-service.d.ts +48 -0
  340. package/dist/workflow/tool-service.js +291 -0
  341. package/dist/workflow/tool-service.js.map +1 -0
  342. package/dist/workflow/turn-boundary.d.ts +39 -0
  343. package/dist/workflow/turn-boundary.js +128 -0
  344. package/dist/workflow/turn-boundary.js.map +1 -0
  345. package/dist/workflow/turn-runner.d.ts +40 -0
  346. package/dist/workflow/turn-runner.js +122 -0
  347. package/dist/workflow/turn-runner.js.map +1 -0
  348. package/dist/workflow/workflow-tools.d.ts +46 -0
  349. package/dist/workflow/workflow-tools.js +90 -0
  350. package/dist/workflow/workflow-tools.js.map +1 -0
  351. package/package.json +119 -0
@@ -0,0 +1,119 @@
1
+ import { transformForEval } from "@langchain/quickjs";
2
+ import { normalizeRelPath } from "../core/workspace.js";
3
+ import { readPrelude } from "./prelude.js";
4
+ import { prepareHookSource } from "./imports.js";
5
+ import { DEFAULT_SANDBOX_VERSION } from "../runtime/contract.js";
6
+ import { createQuickJsSandboxRuntime } from "./runtime.js";
7
+ /**
8
+ * Sandboxed execution for the two sandbox tools (`archmax_eval`, `archmax_run`)
9
+ * and for lifecycle hooks.
10
+ *
11
+ * Script *sources* are read through the {@link Workspace} backend (not the
12
+ * local filesystem), so scripts work against whatever Deep Agents backend the
13
+ * runtime is configured with. Inline code and an authored file evaluate in the
14
+ * same REPL session for a scope and under the same PTC contract — the only
15
+ * difference is where the source came from.
16
+ */
17
+ const DEFAULT_TIMEOUT_MS = 5_000;
18
+ export const AGENT_SESSION = "agent";
19
+ export const PROCESS_SESSION = "process";
20
+ function errorOutcome(message) {
21
+ return { ok: false, value: undefined, logs: [], error: { message }, formatted: `error: ${message}` };
22
+ }
23
+ /** Lifecycle hooks get the hook contract; everything else the PTC contract. */
24
+ function sandboxContext(params) {
25
+ return params.lifecycle ? "lifecycle-hook" : "ptc";
26
+ }
27
+ const argsAssignment = (args) => `globalThis.args = ${JSON.stringify(args ?? {})};`;
28
+ /**
29
+ * The code a lifecycle hook runs as. The hook body is evaluated as its own
30
+ * async IIFE (`transformForEval`) so its completion value can be read — a
31
+ * bare-body hook may end in `veto("…")` — and a registered `export default`
32
+ * function is then called with the hook input: the arguments plus `tools`.
33
+ * Whatever came back is reduced to a verdict by the prelude.
34
+ */
35
+ function buildHookCode(prepared, filePath, prelude, args) {
36
+ return [
37
+ prelude,
38
+ "globalThis.__hookDef = undefined;",
39
+ argsAssignment(args),
40
+ `globalThis.__scriptPath = ${JSON.stringify(normalizeRelPath(filePath))};`,
41
+ `globalThis.__hookBody = await ${transformForEval(prepared)};`,
42
+ "globalThis.__hookVerdict(",
43
+ " typeof globalThis.__hookDef === \"function\"",
44
+ " ? await globalThis.__hookDef(Object.assign({}, globalThis.args, {",
45
+ " tools: typeof tools === \"undefined\" ? undefined : tools,",
46
+ " }))",
47
+ " : globalThis.__hookBody,",
48
+ ");",
49
+ ].join("\n");
50
+ }
51
+ export function createScriptExecutor(opts) {
52
+ const { workspace } = opts;
53
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
54
+ const sandboxVersion = opts.sandboxVersion ?? DEFAULT_SANDBOX_VERSION;
55
+ const runtime = opts.sandboxRuntime ?? createQuickJsSandboxRuntime();
56
+ const sessionKey = (sessionId, ns) => `${sessionId}:${ns}`;
57
+ async function evalCode(code, params) {
58
+ const session = runtime.session(sessionKey(params.sessionId, params.sessionNamespace), {
59
+ tools: params.tools ?? [],
60
+ quotas: {
61
+ memoryLimitBytes: opts.memoryLimitBytes,
62
+ maxPtcCalls: opts.maxPtcCalls,
63
+ maxResultChars: opts.maxResultChars,
64
+ },
65
+ captureConsole: true,
66
+ sessionId: params.sessionId,
67
+ });
68
+ return session.eval(code, timeoutMs);
69
+ }
70
+ async function runHook(source, filePath, params) {
71
+ // Typed `@archmax-ai/harness/*` imports are stripped (the prelude provides the
72
+ // globals) and `export default` becomes the hook registration; any other
73
+ // import — or a source that does not parse — fails closed here, host-side.
74
+ let code;
75
+ try {
76
+ const prelude = readPrelude("lifecycle-hook", sandboxVersion);
77
+ code = buildHookCode(prepareHookSource(source, { file: filePath }), filePath, prelude, params.args);
78
+ }
79
+ catch (err) {
80
+ return errorOutcome(err.message);
81
+ }
82
+ return evalCode(code, params);
83
+ }
84
+ return {
85
+ async runFile(filePath, params) {
86
+ const source = await workspace.readText(filePath);
87
+ if (source == null)
88
+ return errorOutcome(`cannot read script '${filePath}' from the agent workspace.`);
89
+ if (params.lifecycle)
90
+ return runHook(source, filePath, params);
91
+ const prelude = readPrelude(sandboxContext(params), sandboxVersion);
92
+ const code = [
93
+ prelude,
94
+ argsAssignment(params.args),
95
+ `globalThis.__scriptPath = ${JSON.stringify(normalizeRelPath(filePath))};`,
96
+ source,
97
+ ].join("\n");
98
+ return evalCode(code, params);
99
+ },
100
+ runCode(code, params) {
101
+ if (!params.prelude)
102
+ return evalCode(code, params);
103
+ // Same contract as an authored file: the PTC prelude runs first so inline
104
+ // code sees the same `SANDBOX_CONTRACT` marker and the same absence of
105
+ // the hook-only vocabulary.
106
+ return evalCode(`${readPrelude(sandboxContext(params), sandboxVersion)}\n${code}`, params);
107
+ },
108
+ dispose(sessionId, sessionNamespace) {
109
+ if (sessionNamespace) {
110
+ runtime.dispose(sessionKey(sessionId, sessionNamespace));
111
+ return;
112
+ }
113
+ for (const ns of [AGENT_SESSION, PROCESS_SESSION]) {
114
+ runtime.dispose(sessionKey(sessionId, ns));
115
+ }
116
+ },
117
+ };
118
+ }
119
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/sandbox/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Source preparation for lifecycle hook scripts.
3
+ *
4
+ * `@langchain/quickjs`'s `transformForEval` (which `ReplSession.eval` applies to
5
+ * everything it runs) silently **drops** `import` and `export` statements and
6
+ * rejects nothing — so a hook's `export default async function hook(...)`
7
+ * would vanish and a foreign import would pass unnoticed. This module does the
8
+ * three things the transform will not:
9
+ *
10
+ * - **reject** any import that is not a `@archmax-ai/harness/*` type carrier (sandbox
11
+ * scripts are self-contained — inline the logic or use `tools.*`);
12
+ * - **strip** the `@archmax-ai/harness/*` imports, preserving line count so sandbox
13
+ * stack traces keep pointing at the right source lines;
14
+ * - **rewrite** `export default <expr>` to `globalThis.__hookDef = <expr>`, so
15
+ * the hook function survives evaluation as a script and the executor can call
16
+ * it with the hook input.
17
+ */
18
+ /** Thrown (host-side) when a sandbox script imports a non-`@archmax-ai/harness/*` specifier. */
19
+ export declare class ForbiddenSandboxImportError extends Error {
20
+ readonly specifier: string;
21
+ readonly file?: string | undefined;
22
+ constructor(specifier: string, file?: string | undefined);
23
+ }
24
+ /** All import specifiers in a source that are NOT `@archmax-ai/harness/*` (for validation). */
25
+ export declare function findForeignImports(source: string): string[];
26
+ /**
27
+ * Prepare a hook source for evaluation: strip `@archmax-ai/harness/*` imports, rewrite
28
+ * `export default` to the `__hookDef` registration, and throw
29
+ * {@link ForbiddenSandboxImportError} on any other import specifier.
30
+ */
31
+ export declare function prepareHookSource(source: string, opts?: {
32
+ file?: string;
33
+ }): string;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Source preparation for lifecycle hook scripts.
3
+ *
4
+ * `@langchain/quickjs`'s `transformForEval` (which `ReplSession.eval` applies to
5
+ * everything it runs) silently **drops** `import` and `export` statements and
6
+ * rejects nothing — so a hook's `export default async function hook(...)`
7
+ * would vanish and a foreign import would pass unnoticed. This module does the
8
+ * three things the transform will not:
9
+ *
10
+ * - **reject** any import that is not a `@archmax-ai/harness/*` type carrier (sandbox
11
+ * scripts are self-contained — inline the logic or use `tools.*`);
12
+ * - **strip** the `@archmax-ai/harness/*` imports, preserving line count so sandbox
13
+ * stack traces keep pointing at the right source lines;
14
+ * - **rewrite** `export default <expr>` to `globalThis.__hookDef = <expr>`, so
15
+ * the hook function survives evaluation as a script and the executor can call
16
+ * it with the hook input.
17
+ */
18
+ /** Import specifiers the sandbox accepts (and strips) in script sources. */
19
+ const ALLOWED_SPECIFIER_PREFIX = "@archmax-ai/harness";
20
+ /**
21
+ * Static import statements, single- or multi-line:
22
+ * `import { a, b } from "spec";`, `import x from 'spec'`, `import "spec";`.
23
+ */
24
+ const IMPORT_RE = /(^|\n)[ \t]*import\s+(?:[^"'()]*?from\s+)?["']([^"']+)["'][ \t]*;?/g;
25
+ /** `export default` at statement position. */
26
+ const EXPORT_DEFAULT_RE = /(^|\n)([ \t]*)export[ \t]+default[ \t]+/g;
27
+ /** Thrown (host-side) when a sandbox script imports a non-`@archmax-ai/harness/*` specifier. */
28
+ export class ForbiddenSandboxImportError extends Error {
29
+ specifier;
30
+ file;
31
+ constructor(specifier, file) {
32
+ super(`sandbox scripts may import only from '@archmax-ai/harness/*' type-carrier entry points; ` +
33
+ `found 'import ... from "${specifier}"'${file ? ` in ${file}` : ""}. ` +
34
+ `Sandbox scripts are self-contained — inline the logic or use the tools bridge.`);
35
+ this.specifier = specifier;
36
+ this.file = file;
37
+ this.name = "ForbiddenSandboxImportError";
38
+ }
39
+ }
40
+ function specifierAllowed(specifier) {
41
+ return (specifier === ALLOWED_SPECIFIER_PREFIX ||
42
+ specifier.startsWith(`${ALLOWED_SPECIFIER_PREFIX}/`));
43
+ }
44
+ /** All import specifiers in a source that are NOT `@archmax-ai/harness/*` (for validation). */
45
+ export function findForeignImports(source) {
46
+ const foreign = [];
47
+ for (const match of String(source).matchAll(IMPORT_RE)) {
48
+ const specifier = match[2];
49
+ if (!specifierAllowed(specifier))
50
+ foreign.push(specifier);
51
+ }
52
+ return foreign;
53
+ }
54
+ /**
55
+ * Prepare a hook source for evaluation: strip `@archmax-ai/harness/*` imports, rewrite
56
+ * `export default` to the `__hookDef` registration, and throw
57
+ * {@link ForbiddenSandboxImportError} on any other import specifier.
58
+ */
59
+ export function prepareHookSource(source, opts = {}) {
60
+ const stripped = String(source).replace(IMPORT_RE, (whole, _lead, specifier) => {
61
+ if (!specifierAllowed(specifier))
62
+ throw new ForbiddenSandboxImportError(specifier, opts.file);
63
+ return "\n".repeat(whole.split("\n").length - 1);
64
+ });
65
+ return stripped.replace(EXPORT_DEFAULT_RE, "$1$2globalThis.__hookDef = ");
66
+ }
67
+ //# sourceMappingURL=imports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imports.js","sourceRoot":"","sources":["../../src/sandbox/imports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,4EAA4E;AAC5E,MAAM,wBAAwB,GAAG,qBAAqB,CAAC;AAEvD;;;GAGG;AACH,MAAM,SAAS,GAAG,qEAAqE,CAAC;AAExF,8CAA8C;AAC9C,MAAM,iBAAiB,GAAG,0CAA0C,CAAC;AAErE,gGAAgG;AAChG,MAAM,OAAO,2BAA4B,SAAQ,KAAK;IAEzC;IACA;IAFX,YACW,SAAiB,EACjB,IAAa;QAEtB,KAAK,CACH,0FAA0F;YACxF,2BAA2B,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;YACtE,gFAAgF,CACnF,CAAC;QAPO,cAAS,GAAT,SAAS,CAAQ;QACjB,SAAI,GAAJ,IAAI,CAAS;QAOtB,IAAI,CAAC,IAAI,GAAG,6BAA6B,CAAC;IAC5C,CAAC;CACF;AAED,SAAS,gBAAgB,CAAC,SAAiB;IACzC,OAAO,CACL,SAAS,KAAK,wBAAwB;QACtC,SAAS,CAAC,UAAU,CAAC,GAAG,wBAAwB,GAAG,CAAC,CACrD,CAAC;AACJ,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACvD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAGD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,OAA0B,EAAE;IAC5E,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,KAAa,EAAE,SAAiB,EAAE,EAAE;QAC7F,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC;YAAE,MAAM,IAAI,2BAA2B,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9F,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC,OAAO,CAAC,iBAAiB,EAAE,6BAA6B,CAAC,CAAC;AAC5E,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { type SandboxContext } from "../runtime/contract.js";
2
+ /**
3
+ * Assemble the QuickJS prelude for a sandbox context. The lifecycle-hook context
4
+ * is the verdict helpers (`ok`/`veto`/`correct`), `defineHook`, and the verdict
5
+ * reducer; the PTC context is the contract marker alone. Cached per
6
+ * `(context, version)`.
7
+ *
8
+ * There are exactly two preludes: no compatibility prelude exists for a
9
+ * superseded vocabulary, so a hook source using one throws in the sandbox and
10
+ * the phase vetoes fail-closed.
11
+ */
12
+ export declare function readPrelude(context?: SandboxContext, version?: number): string;
@@ -0,0 +1,51 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { DEFAULT_SANDBOX_VERSION } from "../runtime/contract.js";
5
+ const partsCache = new Map();
6
+ const assembledCache = new Map();
7
+ function partsDir() {
8
+ return join(dirname(fileURLToPath(import.meta.url)), "assets", "parts");
9
+ }
10
+ function readPart(name) {
11
+ const cached = partsCache.get(name);
12
+ if (cached !== undefined)
13
+ return cached;
14
+ const content = readFileSync(join(partsDir(), `${name}.js`), "utf8");
15
+ partsCache.set(name, content);
16
+ return content;
17
+ }
18
+ /**
19
+ * The PTC context's whole prelude: the versioned contract marker and nothing
20
+ * else. The model's own code (`archmax_eval`, `archmax_run`) gets no hook
21
+ * vocabulary — `tools` and `args` are injected separately by the executor and
22
+ * the QuickJS session.
23
+ */
24
+ const PTC_PRELUDE = `globalThis.SANDBOX_CONTRACT = { context: "ptc", version: globalThis.__SANDBOX_VERSION };`;
25
+ /**
26
+ * Assemble the QuickJS prelude for a sandbox context. The lifecycle-hook context
27
+ * is the verdict helpers (`ok`/`veto`/`correct`), `defineHook`, and the verdict
28
+ * reducer; the PTC context is the contract marker alone. Cached per
29
+ * `(context, version)`.
30
+ *
31
+ * There are exactly two preludes: no compatibility prelude exists for a
32
+ * superseded vocabulary, so a hook source using one throws in the sandbox and
33
+ * the phase vetoes fail-closed.
34
+ */
35
+ export function readPrelude(context = "lifecycle-hook", version = DEFAULT_SANDBOX_VERSION) {
36
+ const key = `${context}@${version}`;
37
+ const cached = assembledCache.get(key);
38
+ if (cached !== undefined)
39
+ return cached;
40
+ const header = `globalThis.__SANDBOX_VERSION = ${JSON.stringify(version)};`;
41
+ const parts = context === "ptc"
42
+ ? [PTC_PRELUDE]
43
+ : [
44
+ readPart("core"),
45
+ readPart("lifecycle-hook"),
46
+ ];
47
+ const assembled = [header, ...parts].join("\n");
48
+ assembledCache.set(key, assembled);
49
+ return assembled;
50
+ }
51
+ //# sourceMappingURL=prelude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prelude.js","sourceRoot":"","sources":["../../src/sandbox/prelude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAuB,MAAM,wBAAwB,CAAC;AAEtF,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;AAC7C,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC;AAEjD,SAAS,QAAQ;IACf,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACxC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,IAAI,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;IACrE,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,WAAW,GACf,0FAA0F,CAAC;AAE7F;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CACzB,UAA0B,gBAAgB,EAC1C,UAAkB,uBAAuB;IAEzC,MAAM,GAAG,GAAG,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACxC,MAAM,MAAM,GAAG,kCAAkC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC;IAC5E,MAAM,KAAK,GACT,OAAO,KAAK,KAAK;QACf,CAAC,CAAC,CAAC,WAAW,CAAC;QACf,CAAC,CAAC;YACE,QAAQ,CAAC,MAAM,CAAC;YAChB,QAAQ,CAAC,gBAAgB,CAAC;SAC3B,CAAC;IACR,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACnC,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,104 @@
1
+ import type { RunnableConfig } from "@langchain/core/runnables";
2
+ import type { StructuredTool } from "@langchain/core/tools";
3
+ import type { WorkflowEventEmitter } from "../core/events.js";
4
+ import { type GovernanceRule, type ToolCallOrigin } from "../kernel/kernel.js";
5
+ import type { WorkflowMachine } from "../machine/machine.js";
6
+ import type { VariableStore } from "../machine/variables.js";
7
+ import { type MountPrefixes } from "../core/mounts.js";
8
+ import { type SkillPrefixes } from "../core/skills.js";
9
+ /**
10
+ * Governance and telemetry for programmatic tool calls (PTC) — the `tools.*`
11
+ * namespace sandbox scripts call.
12
+ *
13
+ * The sandbox bridge calls `invoke(input)` on a tool directly, bypassing the
14
+ * agent's tool node and `wrapToolCall`, so the gateway hands it *wrapped* tools:
15
+ * each runs the kernel `decide()` pipeline, emits the same tool events, honours
16
+ * declarative mocks and forwards the run's `RunnableConfig` before delegating to
17
+ * the real tool. One wrap covers both PTC consumers — `archmax_eval`/`archmax_run`
18
+ * code and lifecycle hooks.
19
+ *
20
+ * A script's call (`script` origin) is governed exactly as the model's own: the
21
+ * run's variables — refreshed per model call — resolve the state's `${{name}}`
22
+ * argument guards, so a guard admits from a script exactly what it admits from
23
+ * the model. Unlike `wrapToolCall`, no `${{…}}` substitution is applied to a
24
+ * script's arguments: a script passes computed values and reads the variables
25
+ * as `args.variables`, so such text is ordinary data and passes through
26
+ * verbatim — substituting would refuse or rewrite legitimate data.
27
+ */
28
+ /**
29
+ * The live call context for one session's wrapped tools. A QuickJS session
30
+ * freezes its injected tool set at first eval but outlives many calls across
31
+ * several workflow states, so the wrapped tools close over this object and read
32
+ * it per call. Invariant: one context per session, mutated in place by
33
+ * {@link PtcToolGateway.refresh} at the start of every turn and never replaced,
34
+ * or the frozen tools would keep reading a stale one. The abort signal and tool
35
+ * mocks travel inside `config`, so there is exactly one thing to keep current.
36
+ */
37
+ export interface PtcCallContext {
38
+ /** The workflow state a call made right now is governed against. */
39
+ state: string;
40
+ /** Runtime config forwarded to the underlying tool (session id, signal, store). */
41
+ config: RunnableConfig;
42
+ /**
43
+ * Whether the turn in force is reply-only (the run parked, nothing to produce
44
+ * but text). Enforced here as well as at the model's surface: a script from
45
+ * an earlier turn keeps its tools, and "a parked run may speak, never act"
46
+ * must hold on every path to a tool.
47
+ */
48
+ replyOnly?: boolean;
49
+ /**
50
+ * The run's variables at the turn's model call, as checkpointed: what the
51
+ * state's `${{name}}` guards resolve against. Absent means none are set — a
52
+ * guard that references one is then unevaluable and refuses the call.
53
+ */
54
+ variables?: VariableStore;
55
+ }
56
+ export interface PtcWrapOptions {
57
+ /** Which authority these tools run on; decides how the kernel governs them. */
58
+ origin: Extract<ToolCallOrigin, "script" | "lifecycle">;
59
+ /** The session whose live context these tools read on every call. */
60
+ sessionId: string;
61
+ }
62
+ export interface PtcToolGateway {
63
+ /**
64
+ * Wrap a resolved PTC tool surface. The returned tools are drop-in
65
+ * replacements — same `name`, `description`, and schema — so the sandbox
66
+ * bridge's own naming (it camel-cases `name`, and special-cases `read_file`)
67
+ * behaves exactly as it did with the raw tools.
68
+ */
69
+ wrap(tools: StructuredTool[], opts: PtcWrapOptions): StructuredTool[];
70
+ /**
71
+ * Point a session's live context at the current turn. Called once per model
72
+ * call, before any script can run, so tools wrapped in an earlier turn read
73
+ * the state committed for this one.
74
+ */
75
+ refresh(sessionId: string, next: PtcCallContext): void;
76
+ /** Drop a session's context (its wrapped tools go with the session). */
77
+ release(sessionId: string): void;
78
+ }
79
+ /**
80
+ * A PTC call the kernel refused. Thrown so the sandbox bridge rejects the
81
+ * script's promise: fail-closed (the underlying tool never runs) but catchable,
82
+ * so a script can handle the refusal instead of dying on it.
83
+ */
84
+ export declare class PtcGovernanceError extends Error {
85
+ readonly tool: string;
86
+ readonly ruleId: string;
87
+ constructor(tool: string, ruleId: string, reason: string);
88
+ }
89
+ export interface PtcToolGatewayOptions {
90
+ machine: WorkflowMachine;
91
+ /** Consumer governance rules, applied to PTC calls exactly as to agent calls. */
92
+ policyRules?: GovernanceRule[];
93
+ /** The workspace's resolved mount keys, for the kernel's read-only rule. */
94
+ mountPrefixes?: MountPrefixes;
95
+ /**
96
+ * The workspace's resolved skill bundles, for the kernel's skill rule. A
97
+ * script's calls run on the model's authority, so the state's enabled set binds
98
+ * them; a hook's do not (the gateway passes `lifecycle` origin, which the rule
99
+ * exempts).
100
+ */
101
+ skills?: SkillPrefixes;
102
+ emit: WorkflowEventEmitter;
103
+ }
104
+ export declare function createPtcToolGateway(opts: PtcToolGatewayOptions): PtcToolGateway;
@@ -0,0 +1,167 @@
1
+ import { findMock, mockPayload, readMocks } from "../core/tool-mocks.js";
2
+ import { isWorkflowToolName } from "../machine/tool-names.js";
3
+ import { SubWorkflowError, subWorkflowParkOf } from "../workflow/sub-workflow.js";
4
+ import { toolCallDetail, toolOutputPreview } from "../core/tool-telemetry.js";
5
+ import { decide } from "../kernel/kernel.js";
6
+ import { NO_MOUNTS } from "../core/mounts.js";
7
+ import { NO_SKILLS } from "../core/skills.js";
8
+ import { REDACTED_TOOLS, redactDisabledSkills } from "../core/skill-redact.js";
9
+ /**
10
+ * A PTC call the kernel refused. Thrown so the sandbox bridge rejects the
11
+ * script's promise: fail-closed (the underlying tool never runs) but catchable,
12
+ * so a script can handle the refusal instead of dying on it.
13
+ */
14
+ export class PtcGovernanceError extends Error {
15
+ tool;
16
+ ruleId;
17
+ constructor(tool, ruleId, reason) {
18
+ super(reason);
19
+ this.tool = tool;
20
+ this.ruleId = ruleId;
21
+ this.name = "PtcGovernanceError";
22
+ }
23
+ }
24
+ /**
25
+ * Filter a listing a script asked for to the state's enabled skills — the PTC
26
+ * half of the invisibility rule the governance middleware applies to the model's
27
+ * own calls, since `tools.ls` inside `archmax_eval` reaches the same tool by
28
+ * another door. `lifecycle` origin is exempt, as it is from the rule itself: a
29
+ * hook runs on harness authority.
30
+ */
31
+ function redactPtcListing(result, enabled, skills, tool, origin) {
32
+ if (origin === "lifecycle" || skills.length === 0 || !REDACTED_TOOLS.has(tool))
33
+ return result;
34
+ if (typeof result !== "string")
35
+ return result;
36
+ return redactDisabledSkills(result, enabled, skills);
37
+ }
38
+ /** Normalize whatever the sandbox passed as tool input to a governable args object. */
39
+ function toArgs(input) {
40
+ return input != null && typeof input === "object" && !Array.isArray(input)
41
+ ? input
42
+ : {};
43
+ }
44
+ export function createPtcToolGateway(opts) {
45
+ const { machine, policyRules = [], mountPrefixes = NO_MOUNTS, skills = NO_SKILLS, emit } = opts;
46
+ const contexts = new Map();
47
+ let callSeq = 0;
48
+ const skillSlugs = skills.map((skill) => skill.slug);
49
+ const redactSkills = (result, state, tool, origin) => redactPtcListing(result, machine.enabledSkills(state, skillSlugs), skills, tool, origin);
50
+ /** The session's stable context ref, created on first use. */
51
+ function contextFor(sessionId) {
52
+ let context = contexts.get(sessionId);
53
+ if (!context) {
54
+ context = { state: machine.entry, config: {} };
55
+ contexts.set(sessionId, context);
56
+ }
57
+ return context;
58
+ }
59
+ function governedInvoke(inner, origin, context) {
60
+ return async (input, config) => {
61
+ const tool = inner.name;
62
+ const args = toArgs(input);
63
+ // Read per call, not per wrap: the session's tool set is frozen but the
64
+ // workflow state behind it moves with every `archmax_advance`.
65
+ const { state, config: contextConfig, replyOnly, variables = {} } = context;
66
+ const callId = `ptc:${++callSeq}`;
67
+ const verdict = decide(machine, { kind: "tool-call", state, tool, args, origin, ...(replyOnly ? { replyOnly } : {}) }, policyRules, mountPrefixes, variables, skills);
68
+ if (verdict.decision === "block") {
69
+ const reason = verdict.reason ?? `'${tool}' is not allowed in state '${state}'.`;
70
+ // Gated on `warn` for parity with the agent path, where a non-warn
71
+ // block (the inline-`eval` refusal) is deliberately silent.
72
+ if (verdict.warn) {
73
+ emit({ type: "tool-blocked", state, tool, reason, callId, args, origin });
74
+ }
75
+ throw new PtcGovernanceError(tool, verdict.ruleId, reason);
76
+ }
77
+ const detail = toolCallDetail(args);
78
+ emit({
79
+ type: "tool-called",
80
+ state,
81
+ tool,
82
+ callId,
83
+ args,
84
+ origin,
85
+ ...(detail ? { detail } : {}),
86
+ });
87
+ const startedAt = Date.now();
88
+ const settle = (status, value) => {
89
+ emit({
90
+ type: "tool-result",
91
+ state,
92
+ tool,
93
+ callId,
94
+ status,
95
+ durationMs: Date.now() - startedAt,
96
+ origin,
97
+ ...toolOutputPreview(value),
98
+ });
99
+ };
100
+ try {
101
+ // Mocks are checked after governance, mirroring the agent path where the
102
+ // mock middleware sits inside the workflow middleware: a call the state
103
+ // forbids is refused whether or not a test mocked it.
104
+ // Delegation mocks belong to the dispatcher (see the mock middleware):
105
+ // serving one here would skip the dispatch and its record of itself.
106
+ const mock = isWorkflowToolName(tool)
107
+ ? undefined
108
+ : findMock(readMocks(contextConfig.configurable), tool, args);
109
+ const result = mock
110
+ ? mockPayload(mock)
111
+ : // The bridge passes no config of its own; the turn's gives the tool
112
+ // the session id, signal and store an agent call would have had, and
113
+ // `toolCallId` lets a delegation's telemetry trace back to this call.
114
+ await inner.invoke(args, { ...(config ?? contextConfig), toolCallId: callId });
115
+ const served = redactSkills(result, state, tool, origin);
116
+ settle("ok", served);
117
+ return served;
118
+ }
119
+ catch (err) {
120
+ // A delegated sub-run stopped for a person. A script cannot park — a
121
+ // QuickJS frame is not durable — so this fails closed as an error rather
122
+ // than letting a raw suspension escape: a script's park must never
123
+ // unwind the turn that ran it.
124
+ const parked = subWorkflowParkOf(err);
125
+ if (parked) {
126
+ const failure = new SubWorkflowError("parked", parked.workflow, `Sub-workflow '${parked.workflow}' stopped for a person, and a script cannot wait ` +
127
+ `for one: the sandbox has no way to resume. Call it from the state's agent, or ` +
128
+ `move the decision to a human node in the calling workflow.`);
129
+ settle("error", failure.message);
130
+ throw failure;
131
+ }
132
+ settle("error", err?.message ?? String(err));
133
+ throw err;
134
+ }
135
+ };
136
+ }
137
+ return {
138
+ wrap(tools, { origin, sessionId }) {
139
+ const context = contextFor(sessionId);
140
+ return tools.map((inner) => {
141
+ const invoke = governedInvoke(inner, origin, context);
142
+ // A Proxy rather than a rebuilt tool: `name`, `description` and schema
143
+ // stay the originals. Non-intercepted members are bound to the target so
144
+ // the real tool's internals never see the proxy as `this`.
145
+ return new Proxy(inner, {
146
+ get(target, prop) {
147
+ if (prop === "invoke")
148
+ return invoke;
149
+ const value = Reflect.get(target, prop, target);
150
+ return typeof value === "function" ? value.bind(target) : value;
151
+ },
152
+ });
153
+ });
154
+ },
155
+ refresh(sessionId, next) {
156
+ const context = contextFor(sessionId);
157
+ context.state = next.state;
158
+ context.config = next.config;
159
+ context.replyOnly = next.replyOnly;
160
+ context.variables = next.variables;
161
+ },
162
+ release(sessionId) {
163
+ contexts.delete(sessionId);
164
+ },
165
+ };
166
+ }
167
+ //# sourceMappingURL=ptc-gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ptc-gateway.js","sourceRoot":"","sources":["../../src/sandbox/ptc-gateway.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import type { StructuredTool } from "@langchain/core/tools";
2
+ import { type SubagentBridgeOptions } from "@langchain/quickjs";
3
+ /**
4
+ * The pluggable script-execution backend and its bundled QuickJS default.
5
+ *
6
+ * Namespaced sessions with an `eval` operation and disposal: QuickJS is what
7
+ * ships ({@link createQuickJsSandboxRuntime}); a consumer may supply another
8
+ * implementation to run scripts in a worker or remotely alongside a remote Deep
9
+ * Agents backend. The executor talks only to this interface.
10
+ */
11
+ /** Resource quotas applied to a sandbox session, uniformly across implementations. */
12
+ export interface SandboxQuotas {
13
+ memoryLimitBytes?: number;
14
+ maxPtcCalls?: number | null;
15
+ maxResultChars?: number;
16
+ }
17
+ /** Options for creating (or reusing) a namespaced sandbox session. */
18
+ export interface SandboxSessionOptions {
19
+ /** Privileged tools scripts may call (PTC). */
20
+ tools?: StructuredTool[];
21
+ /** Quotas bounding this session's execution. */
22
+ quotas?: SandboxQuotas;
23
+ /** Capture `console.*` output into the eval result's `logs`. */
24
+ captureConsole?: boolean;
25
+ /** Session id surfaced to scripts (the run/session id). */
26
+ sessionId?: string;
27
+ /** Subagent bridge dispatch for `task()` calls, and its concurrency cap. */
28
+ subagentDispatch?: SubagentBridgeOptions["dispatch"];
29
+ subagentMaxConcurrency?: number;
30
+ }
31
+ /** The normalized result of one sandbox `eval` — the shape the executor surfaces. */
32
+ export interface SandboxEvalResult {
33
+ ok: boolean;
34
+ value: unknown;
35
+ logs: string[];
36
+ error?: {
37
+ name?: string;
38
+ message?: string;
39
+ };
40
+ /** Human-readable rendering of the result (value or error), for tool replies. */
41
+ formatted: string;
42
+ }
43
+ /** A namespaced sandbox session that evaluates code with a per-call timeout. */
44
+ export interface SandboxSession {
45
+ eval(code: string, timeoutMs?: number): Promise<SandboxEvalResult>;
46
+ }
47
+ export interface SandboxRuntime {
48
+ /** Get or create the session for a namespace, applying the given options. */
49
+ session(namespace: string, options: SandboxSessionOptions): SandboxSession;
50
+ /** Release the session for a namespace (idempotent). */
51
+ dispose(namespace: string): void;
52
+ }
53
+ /**
54
+ * The bundled default: `@langchain/quickjs`'s `ReplSession` behind the
55
+ * interface. Sessions are keyed by namespace and reused across evals (the
56
+ * runtime namespaces per session + session kind), and `formatReplResult`
57
+ * renders the outcome so the executor stays engine-agnostic.
58
+ */
59
+ export declare function createQuickJsSandboxRuntime(): SandboxRuntime;