@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.
- package/LICENSE +21 -0
- package/README.md +219 -0
- package/dist/agent.d.ts +174 -0
- package/dist/agent.js +140 -0
- package/dist/agent.js.map +1 -0
- package/dist/assembly/compose.d.ts +170 -0
- package/dist/assembly/compose.js +391 -0
- package/dist/assembly/compose.js.map +1 -0
- package/dist/assembly/delegation-registry.d.ts +5 -0
- package/dist/assembly/delegation-registry.js +118 -0
- package/dist/assembly/delegation-registry.js.map +1 -0
- package/dist/assembly/index.d.ts +192 -0
- package/dist/assembly/index.js +265 -0
- package/dist/assembly/index.js.map +1 -0
- package/dist/assembly/plain.d.ts +7 -0
- package/dist/assembly/plain.js +41 -0
- package/dist/assembly/plain.js.map +1 -0
- package/dist/authoring-skill/archmax-harness/README.md +76 -0
- package/dist/authoring-skill/archmax-harness/SKILL.md +241 -0
- package/dist/authoring-skill/archmax-harness/references/backend-integration.md +626 -0
- package/dist/authoring-skill/archmax-harness/references/cases.md +41 -0
- package/dist/authoring-skill/archmax-harness/references/diagnostics.md +51 -0
- package/dist/authoring-skill/archmax-harness/references/hook-and-test-scripts.md +1070 -0
- package/dist/authoring-skill/archmax-harness/references/hooks-and-scripts.md +82 -0
- package/dist/authoring-skill/archmax-harness/references/wiring.md +101 -0
- package/dist/authoring-skill/archmax-harness/references/workflow-schema.md +1631 -0
- package/dist/authoring-skill/archmax-harness/references/workflow-yaml.md +241 -0
- package/dist/behaviour/support.d.ts +232 -0
- package/dist/behaviour/support.js +339 -0
- package/dist/behaviour/support.js.map +1 -0
- package/dist/cli/banner.d.ts +11 -0
- package/dist/cli/banner.js +29 -0
- package/dist/cli/banner.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +33 -0
- package/dist/cli/bootstrap.js +153 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/command.d.ts +39 -0
- package/dist/cli/command.js +97 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/state-flow.d.ts +46 -0
- package/dist/cli/state-flow.js +268 -0
- package/dist/cli/state-flow.js.map +1 -0
- package/dist/cli/style.d.ts +41 -0
- package/dist/cli/style.js +64 -0
- package/dist/cli/style.js.map +1 -0
- package/dist/cli/turn.d.ts +41 -0
- package/dist/cli/turn.js +161 -0
- package/dist/cli/turn.js.map +1 -0
- package/dist/cli.d.ts +10 -0
- package/dist/cli.js +426 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/code-description.d.ts +22 -0
- package/dist/core/code-description.js +38 -0
- package/dist/core/code-description.js.map +1 -0
- package/dist/core/deepagents.d.ts +183 -0
- package/dist/core/deepagents.js +128 -0
- package/dist/core/deepagents.js.map +1 -0
- package/dist/core/events.d.ts +350 -0
- package/dist/core/events.js +205 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/frontmatter.d.ts +15 -0
- package/dist/core/frontmatter.js +32 -0
- package/dist/core/frontmatter.js.map +1 -0
- package/dist/core/listing-redact.d.ts +37 -0
- package/dist/core/listing-redact.js +88 -0
- package/dist/core/listing-redact.js.map +1 -0
- package/dist/core/match.d.ts +26 -0
- package/dist/core/match.js +75 -0
- package/dist/core/match.js.map +1 -0
- package/dist/core/message-readers.d.ts +84 -0
- package/dist/core/message-readers.js +159 -0
- package/dist/core/message-readers.js.map +1 -0
- package/dist/core/messages.d.ts +49 -0
- package/dist/core/messages.js +85 -0
- package/dist/core/messages.js.map +1 -0
- package/dist/core/mount-prompt.d.ts +28 -0
- package/dist/core/mount-prompt.js +55 -0
- package/dist/core/mount-prompt.js.map +1 -0
- package/dist/core/mount-redact.d.ts +28 -0
- package/dist/core/mount-redact.js +32 -0
- package/dist/core/mount-redact.js.map +1 -0
- package/dist/core/mounts.d.ts +88 -0
- package/dist/core/mounts.js +147 -0
- package/dist/core/mounts.js.map +1 -0
- package/dist/core/path-mapping.d.ts +52 -0
- package/dist/core/path-mapping.js +113 -0
- package/dist/core/path-mapping.js.map +1 -0
- package/dist/core/platform-prompt.generated.d.ts +2 -0
- package/dist/core/platform-prompt.generated.js +4 -0
- package/dist/core/platform-prompt.generated.js.map +1 -0
- package/dist/core/prompt.d.ts +42 -0
- package/dist/core/prompt.js +75 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/session-id.d.ts +38 -0
- package/dist/core/session-id.js +61 -0
- package/dist/core/session-id.js.map +1 -0
- package/dist/core/session-store.d.ts +85 -0
- package/dist/core/session-store.js +149 -0
- package/dist/core/session-store.js.map +1 -0
- package/dist/core/session-zone.d.ts +54 -0
- package/dist/core/session-zone.js +82 -0
- package/dist/core/session-zone.js.map +1 -0
- package/dist/core/skill-prompt.d.ts +31 -0
- package/dist/core/skill-prompt.js +54 -0
- package/dist/core/skill-prompt.js.map +1 -0
- package/dist/core/skill-redact.d.ts +15 -0
- package/dist/core/skill-redact.js +27 -0
- package/dist/core/skill-redact.js.map +1 -0
- package/dist/core/skills.d.ts +172 -0
- package/dist/core/skills.js +214 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/tool-mocks.d.ts +23 -0
- package/dist/core/tool-mocks.js +39 -0
- package/dist/core/tool-mocks.js.map +1 -0
- package/dist/core/tool-telemetry.d.ts +16 -0
- package/dist/core/tool-telemetry.js +40 -0
- package/dist/core/tool-telemetry.js.map +1 -0
- package/dist/core/usage.d.ts +114 -0
- package/dist/core/usage.js +226 -0
- package/dist/core/usage.js.map +1 -0
- package/dist/core/workspace-context.d.ts +136 -0
- package/dist/core/workspace-context.js +178 -0
- package/dist/core/workspace-context.js.map +1 -0
- package/dist/core/workspace-prompt.d.ts +7 -0
- package/dist/core/workspace-prompt.js +102 -0
- package/dist/core/workspace-prompt.js.map +1 -0
- package/dist/core/workspace-router.d.ts +61 -0
- package/dist/core/workspace-router.js +145 -0
- package/dist/core/workspace-router.js.map +1 -0
- package/dist/core/workspace.d.ts +85 -0
- package/dist/core/workspace.js +193 -0
- package/dist/core/workspace.js.map +1 -0
- package/dist/core/zones.d.ts +181 -0
- package/dist/core/zones.js +202 -0
- package/dist/core/zones.js.map +1 -0
- package/dist/env.d.ts +99 -0
- package/dist/env.js +271 -0
- package/dist/env.js.map +1 -0
- package/dist/index.d.ts +265 -0
- package/dist/index.js +197 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/kernel.d.ts +192 -0
- package/dist/kernel/kernel.js +751 -0
- package/dist/kernel/kernel.js.map +1 -0
- package/dist/lifecycle/hook-shape.d.ts +44 -0
- package/dist/lifecycle/hook-shape.js +66 -0
- package/dist/lifecycle/hook-shape.js.map +1 -0
- package/dist/lifecycle/runner.d.ts +177 -0
- package/dist/lifecycle/runner.js +372 -0
- package/dist/lifecycle/runner.js.map +1 -0
- package/dist/lifecycle/transcript.d.ts +27 -0
- package/dist/lifecycle/transcript.js +43 -0
- package/dist/lifecycle/transcript.js.map +1 -0
- package/dist/machine/allow.d.ts +65 -0
- package/dist/machine/allow.js +107 -0
- package/dist/machine/allow.js.map +1 -0
- package/dist/machine/delegation.d.ts +9 -0
- package/dist/machine/delegation.js +10 -0
- package/dist/machine/delegation.js.map +1 -0
- package/dist/machine/diagnostic.d.ts +14 -0
- package/dist/machine/diagnostic.js +2 -0
- package/dist/machine/diagnostic.js.map +1 -0
- package/dist/machine/lint-spec.d.ts +4 -0
- package/dist/machine/lint-spec.js +266 -0
- package/dist/machine/lint-spec.js.map +1 -0
- package/dist/machine/load-spec.d.ts +90 -0
- package/dist/machine/load-spec.js +120 -0
- package/dist/machine/load-spec.js.map +1 -0
- package/dist/machine/machine.d.ts +273 -0
- package/dist/machine/machine.js +551 -0
- package/dist/machine/machine.js.map +1 -0
- package/dist/machine/mount-grants.d.ts +25 -0
- package/dist/machine/mount-grants.js +24 -0
- package/dist/machine/mount-grants.js.map +1 -0
- package/dist/machine/slug.d.ts +14 -0
- package/dist/machine/slug.js +17 -0
- package/dist/machine/slug.js.map +1 -0
- package/dist/machine/spec-schema.d.ts +662 -0
- package/dist/machine/spec-schema.js +717 -0
- package/dist/machine/spec-schema.js.map +1 -0
- package/dist/machine/tool-names.d.ts +98 -0
- package/dist/machine/tool-names.js +144 -0
- package/dist/machine/tool-names.js.map +1 -0
- package/dist/machine/triggers.d.ts +114 -0
- package/dist/machine/triggers.js +165 -0
- package/dist/machine/triggers.js.map +1 -0
- package/dist/machine/types.d.ts +186 -0
- package/dist/machine/types.js +12 -0
- package/dist/machine/types.js.map +1 -0
- package/dist/machine/validate-spec.d.ts +42 -0
- package/dist/machine/validate-spec.js +29 -0
- package/dist/machine/validate-spec.js.map +1 -0
- package/dist/machine/variables.d.ts +196 -0
- package/dist/machine/variables.js +415 -0
- package/dist/machine/variables.js.map +1 -0
- package/dist/public/cli.d.ts +15 -0
- package/dist/public/cli.js +14 -0
- package/dist/public/cli.js.map +1 -0
- package/dist/public/messages.d.ts +33 -0
- package/dist/public/messages.js +33 -0
- package/dist/public/messages.js.map +1 -0
- package/dist/public/sandbox.d.ts +99 -0
- package/dist/public/sandbox.js +32 -0
- package/dist/public/sandbox.js.map +1 -0
- package/dist/public/spec.d.ts +147 -0
- package/dist/public/spec.js +149 -0
- package/dist/public/spec.js.map +1 -0
- package/dist/public/testing.d.ts +71 -0
- package/dist/public/testing.js +39 -0
- package/dist/public/testing.js.map +1 -0
- package/dist/rubrics/rubrics.d.ts +135 -0
- package/dist/rubrics/rubrics.js +145 -0
- package/dist/rubrics/rubrics.js.map +1 -0
- package/dist/runtime/contract.d.ts +73 -0
- package/dist/runtime/contract.js +96 -0
- package/dist/runtime/contract.js.map +1 -0
- package/dist/sandbox/assets/parts/core.js +22 -0
- package/dist/sandbox/assets/parts/lifecycle-hook.js +47 -0
- package/dist/sandbox/bridge.d.ts +16 -0
- package/dist/sandbox/bridge.js +95 -0
- package/dist/sandbox/bridge.js.map +1 -0
- package/dist/sandbox/executor.d.ts +46 -0
- package/dist/sandbox/executor.js +119 -0
- package/dist/sandbox/executor.js.map +1 -0
- package/dist/sandbox/imports.d.ts +33 -0
- package/dist/sandbox/imports.js +67 -0
- package/dist/sandbox/imports.js.map +1 -0
- package/dist/sandbox/prelude.d.ts +12 -0
- package/dist/sandbox/prelude.js +51 -0
- package/dist/sandbox/prelude.js.map +1 -0
- package/dist/sandbox/ptc-gateway.d.ts +104 -0
- package/dist/sandbox/ptc-gateway.js +167 -0
- package/dist/sandbox/ptc-gateway.js.map +1 -0
- package/dist/sandbox/runtime.d.ts +59 -0
- package/dist/sandbox/runtime.js +51 -0
- package/dist/sandbox/runtime.js.map +1 -0
- package/dist/sandbox/tools.d.ts +34 -0
- package/dist/sandbox/tools.js +147 -0
- package/dist/sandbox/tools.js.map +1 -0
- package/dist/sessions/operations.d.ts +79 -0
- package/dist/sessions/operations.js +121 -0
- package/dist/sessions/operations.js.map +1 -0
- package/dist/sessions/resolve.d.ts +97 -0
- package/dist/sessions/resolve.js +145 -0
- package/dist/sessions/resolve.js.map +1 -0
- package/dist/sessions/resume.d.ts +242 -0
- package/dist/sessions/resume.js +288 -0
- package/dist/sessions/resume.js.map +1 -0
- package/dist/sessions/scope.d.ts +99 -0
- package/dist/sessions/scope.js +145 -0
- package/dist/sessions/scope.js.map +1 -0
- package/dist/sessions/summary.d.ts +65 -0
- package/dist/sessions/summary.js +56 -0
- package/dist/sessions/summary.js.map +1 -0
- package/dist/testing/assertions.d.ts +30 -0
- package/dist/testing/assertions.js +231 -0
- package/dist/testing/assertions.js.map +1 -0
- package/dist/testing/case-document.d.ts +141 -0
- package/dist/testing/case-document.js +51 -0
- package/dist/testing/case-document.js.map +1 -0
- package/dist/testing/case-schema.d.ts +29 -0
- package/dist/testing/case-schema.js +519 -0
- package/dist/testing/case-schema.js.map +1 -0
- package/dist/testing/discovery.d.ts +10 -0
- package/dist/testing/discovery.js +24 -0
- package/dist/testing/discovery.js.map +1 -0
- package/dist/testing/driver.d.ts +78 -0
- package/dist/testing/driver.js +117 -0
- package/dist/testing/driver.js.map +1 -0
- package/dist/testing/grade.d.ts +116 -0
- package/dist/testing/grade.js +261 -0
- package/dist/testing/grade.js.map +1 -0
- package/dist/testing/interpreter.d.ts +55 -0
- package/dist/testing/interpreter.js +103 -0
- package/dist/testing/interpreter.js.map +1 -0
- package/dist/testing/mock-middleware.d.ts +5 -0
- package/dist/testing/mock-middleware.js +33 -0
- package/dist/testing/mock-middleware.js.map +1 -0
- package/dist/testing/runner.d.ts +205 -0
- package/dist/testing/runner.js +266 -0
- package/dist/testing/runner.js.map +1 -0
- package/dist/testing/target.d.ts +27 -0
- package/dist/testing/target.js +21 -0
- package/dist/testing/target.js.map +1 -0
- package/dist/validate/validate.d.ts +41 -0
- package/dist/validate/validate.js +669 -0
- package/dist/validate/validate.js.map +1 -0
- package/dist/workflow/agent-tools.d.ts +10 -0
- package/dist/workflow/agent-tools.js +10 -0
- package/dist/workflow/agent-tools.js.map +1 -0
- package/dist/workflow/checkpointer.d.ts +52 -0
- package/dist/workflow/checkpointer.js +200 -0
- package/dist/workflow/checkpointer.js.map +1 -0
- package/dist/workflow/control-tools.d.ts +174 -0
- package/dist/workflow/control-tools.js +468 -0
- package/dist/workflow/control-tools.js.map +1 -0
- package/dist/workflow/governance.d.ts +104 -0
- package/dist/workflow/governance.js +546 -0
- package/dist/workflow/governance.js.map +1 -0
- package/dist/workflow/middleware.d.ts +85 -0
- package/dist/workflow/middleware.js +283 -0
- package/dist/workflow/middleware.js.map +1 -0
- package/dist/workflow/on-error.d.ts +25 -0
- package/dist/workflow/on-error.js +58 -0
- package/dist/workflow/on-error.js.map +1 -0
- package/dist/workflow/parks.d.ts +46 -0
- package/dist/workflow/parks.js +513 -0
- package/dist/workflow/parks.js.map +1 -0
- package/dist/workflow/paths.d.ts +67 -0
- package/dist/workflow/paths.js +108 -0
- package/dist/workflow/paths.js.map +1 -0
- package/dist/workflow/prompt-cache.d.ts +70 -0
- package/dist/workflow/prompt-cache.js +103 -0
- package/dist/workflow/prompt-cache.js.map +1 -0
- package/dist/workflow/prompt-pruning.d.ts +20 -0
- package/dist/workflow/prompt-pruning.js +83 -0
- package/dist/workflow/prompt-pruning.js.map +1 -0
- package/dist/workflow/render-prompt.d.ts +45 -0
- package/dist/workflow/render-prompt.js +140 -0
- package/dist/workflow/render-prompt.js.map +1 -0
- package/dist/workflow/runtime-config.d.ts +7 -0
- package/dist/workflow/runtime-config.js +9 -0
- package/dist/workflow/runtime-config.js.map +1 -0
- package/dist/workflow/session-artifacts.d.ts +90 -0
- package/dist/workflow/session-artifacts.js +134 -0
- package/dist/workflow/session-artifacts.js.map +1 -0
- package/dist/workflow/session-view.d.ts +31 -0
- package/dist/workflow/session-view.js +94 -0
- package/dist/workflow/session-view.js.map +1 -0
- package/dist/workflow/snapshot.d.ts +14 -0
- package/dist/workflow/snapshot.js +97 -0
- package/dist/workflow/snapshot.js.map +1 -0
- package/dist/workflow/state.d.ts +347 -0
- package/dist/workflow/state.js +322 -0
- package/dist/workflow/state.js.map +1 -0
- package/dist/workflow/sub-workflow.d.ts +174 -0
- package/dist/workflow/sub-workflow.js +392 -0
- package/dist/workflow/sub-workflow.js.map +1 -0
- package/dist/workflow/tool-service.d.ts +48 -0
- package/dist/workflow/tool-service.js +291 -0
- package/dist/workflow/tool-service.js.map +1 -0
- package/dist/workflow/turn-boundary.d.ts +39 -0
- package/dist/workflow/turn-boundary.js +128 -0
- package/dist/workflow/turn-boundary.js.map +1 -0
- package/dist/workflow/turn-runner.d.ts +40 -0
- package/dist/workflow/turn-runner.js +122 -0
- package/dist/workflow/turn-runner.js.map +1 -0
- package/dist/workflow/workflow-tools.d.ts +46 -0
- package/dist/workflow/workflow-tools.js +90 -0
- package/dist/workflow/workflow-tools.js.map +1 -0
- 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;
|