@relayflows/sdk 2.0.9 → 2.0.11
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/dist/adapters/base.d.ts +46 -0
- package/dist/adapters/base.d.ts.map +1 -0
- package/dist/adapters/base.js +15 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/claude.d.ts +5 -0
- package/dist/adapters/claude.d.ts.map +1 -0
- package/dist/adapters/claude.js +44 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/adapters/codex.d.ts +5 -0
- package/dist/adapters/codex.d.ts.map +1 -0
- package/dist/adapters/codex.js +45 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/index.d.ts +14 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +29 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/wrapper.d.ts +12 -0
- package/dist/adapters/wrapper.d.ts.map +1 -0
- package/dist/adapters/wrapper.js +31 -0
- package/dist/adapters/wrapper.js.map +1 -0
- package/dist/agent-relay-receipt.d.ts +24 -0
- package/dist/agent-relay-receipt.d.ts.map +1 -0
- package/dist/agent-relay-receipt.js +66 -0
- package/dist/agent-relay-receipt.js.map +1 -0
- package/dist/agent-relay-state.d.ts +18 -0
- package/dist/agent-relay-state.d.ts.map +1 -0
- package/dist/agent-relay-state.js +58 -0
- package/dist/agent-relay-state.js.map +1 -0
- package/dist/agent-relay-transport.d.ts +31 -0
- package/dist/agent-relay-transport.d.ts.map +1 -0
- package/dist/agent-relay-transport.js +199 -0
- package/dist/agent-relay-transport.js.map +1 -0
- package/dist/authored-budget.d.ts +13 -0
- package/dist/authored-budget.d.ts.map +1 -0
- package/dist/authored-budget.js +78 -0
- package/dist/authored-budget.js.map +1 -0
- package/dist/authored-flow-error.d.ts +2 -21
- package/dist/authored-flow-error.d.ts.map +1 -1
- package/dist/authored-flow-error.js +1 -12
- package/dist/authored-flow-error.js.map +1 -1
- package/dist/authored-flow-executor.d.ts +13 -7
- package/dist/authored-flow-executor.d.ts.map +1 -1
- package/dist/authored-flow-executor.js +116 -235
- package/dist/authored-flow-executor.js.map +1 -1
- package/dist/authored-flow-loader.d.ts +10 -1
- package/dist/authored-flow-loader.d.ts.map +1 -1
- package/dist/authored-flow-loader.js +56 -3
- package/dist/authored-flow-loader.js.map +1 -1
- package/dist/authored-flow-operation.d.ts +9 -1
- package/dist/authored-flow-operation.d.ts.map +1 -1
- package/dist/authored-flow-operation.js +35 -4
- package/dist/authored-flow-operation.js.map +1 -1
- package/dist/authored-helper-effect.d.ts +12 -0
- package/dist/authored-helper-effect.d.ts.map +1 -0
- package/dist/authored-helper-effect.js +144 -0
- package/dist/authored-helper-effect.js.map +1 -0
- package/dist/authored-mcp.d.ts +17 -0
- package/dist/authored-mcp.d.ts.map +1 -0
- package/dist/authored-mcp.js +171 -0
- package/dist/authored-mcp.js.map +1 -0
- package/dist/authored-memory.d.ts +7 -0
- package/dist/authored-memory.d.ts.map +1 -0
- package/dist/authored-memory.js +60 -0
- package/dist/authored-memory.js.map +1 -0
- package/dist/authored-plugin-effect.d.ts +16 -0
- package/dist/authored-plugin-effect.d.ts.map +1 -0
- package/dist/authored-plugin-effect.js +163 -0
- package/dist/authored-plugin-effect.js.map +1 -0
- package/dist/authored-step-output.d.ts +23 -0
- package/dist/authored-step-output.d.ts.map +1 -0
- package/dist/authored-step-output.js +67 -0
- package/dist/authored-step-output.js.map +1 -0
- package/dist/authored-worker-step.d.ts +15 -0
- package/dist/authored-worker-step.d.ts.map +1 -0
- package/dist/authored-worker-step.js +136 -0
- package/dist/authored-worker-step.js.map +1 -0
- package/dist/budget-preflight.d.ts +5 -0
- package/dist/budget-preflight.d.ts.map +1 -0
- package/dist/budget-preflight.js +33 -0
- package/dist/budget-preflight.js.map +1 -0
- package/dist/budget.d.ts +14 -0
- package/dist/budget.d.ts.map +1 -0
- package/dist/budget.js +52 -0
- package/dist/budget.js.map +1 -0
- package/dist/bundle-transport.d.ts +18 -0
- package/dist/bundle-transport.d.ts.map +1 -0
- package/dist/bundle-transport.js +111 -0
- package/dist/bundle-transport.js.map +1 -0
- package/dist/bundle-typescript.d.ts +8 -0
- package/dist/bundle-typescript.d.ts.map +1 -0
- package/dist/bundle-typescript.js +108 -0
- package/dist/bundle-typescript.js.map +1 -0
- package/dist/bundle.d.ts +25 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +199 -0
- package/dist/bundle.js.map +1 -0
- package/dist/child-stop.d.ts +59 -0
- package/dist/child-stop.d.ts.map +1 -0
- package/dist/child-stop.js +94 -0
- package/dist/child-stop.js.map +1 -0
- package/dist/cli/add.d.ts +6 -0
- package/dist/cli/add.d.ts.map +1 -0
- package/dist/cli/add.js +47 -0
- package/dist/cli/add.js.map +1 -0
- package/dist/cli/build.d.ts +13 -0
- package/dist/cli/build.d.ts.map +1 -0
- package/dist/cli/build.js +224 -0
- package/dist/cli/build.js.map +1 -0
- package/dist/cli/bundle-preflight.d.ts +5 -0
- package/dist/cli/bundle-preflight.d.ts.map +1 -0
- package/dist/cli/bundle-preflight.js +28 -0
- package/dist/cli/bundle-preflight.js.map +1 -0
- package/dist/cli/check-helper-body.d.ts +4 -0
- package/dist/cli/check-helper-body.d.ts.map +1 -0
- package/dist/cli/check-helper-body.js +15 -0
- package/dist/cli/check-helper-body.js.map +1 -0
- package/dist/cli/check-triggers.d.ts +14 -0
- package/dist/cli/check-triggers.d.ts.map +1 -0
- package/dist/cli/check-triggers.js +37 -0
- package/dist/cli/check-triggers.js.map +1 -0
- package/dist/cli/check-typescript.d.ts +20 -0
- package/dist/cli/check-typescript.d.ts.map +1 -0
- package/dist/cli/check-typescript.js +54 -0
- package/dist/cli/check-typescript.js.map +1 -0
- package/dist/cli/check.d.ts +36 -3
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +122 -11
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/cloud-run.d.ts +8 -0
- package/dist/cli/cloud-run.d.ts.map +1 -0
- package/dist/cli/cloud-run.js +50 -0
- package/dist/cli/cloud-run.js.map +1 -0
- package/dist/cli/deploy.d.ts +9 -0
- package/dist/cli/deploy.d.ts.map +1 -0
- package/dist/cli/deploy.js +58 -0
- package/dist/cli/deploy.js.map +1 -0
- package/dist/cli/deterministic-failure.d.ts +5 -0
- package/dist/cli/deterministic-failure.d.ts.map +1 -0
- package/dist/cli/deterministic-failure.js +66 -0
- package/dist/cli/deterministic-failure.js.map +1 -0
- package/dist/cli/direct-run.d.ts.map +1 -1
- package/dist/cli/direct-run.js +83 -18
- package/dist/cli/direct-run.js.map +1 -1
- package/dist/cli/hn-monitor.d.ts.map +1 -1
- package/dist/cli/hn-monitor.js +2 -1
- package/dist/cli/hn-monitor.js.map +1 -1
- package/dist/cli/replay.d.ts +12 -0
- package/dist/cli/replay.d.ts.map +1 -0
- package/dist/cli/replay.js +82 -0
- package/dist/cli/replay.js.map +1 -0
- package/dist/cli/reuse.d.ts +8 -0
- package/dist/cli/reuse.d.ts.map +1 -0
- package/dist/cli/reuse.js +25 -0
- package/dist/cli/reuse.js.map +1 -0
- package/dist/cli/run-digest.d.ts +4 -0
- package/dist/cli/run-digest.d.ts.map +1 -0
- package/dist/cli/run-digest.js +24 -0
- package/dist/cli/run-digest.js.map +1 -0
- package/dist/cli/run.d.ts +16 -5
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +99 -17
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/serve-webhook.d.ts +40 -0
- package/dist/cli/serve-webhook.d.ts.map +1 -0
- package/dist/cli/serve-webhook.js +233 -0
- package/dist/cli/serve-webhook.js.map +1 -0
- package/dist/cli/tick-runner.d.ts.map +1 -1
- package/dist/cli/tick-runner.js +2 -1
- package/dist/cli/tick-runner.js.map +1 -1
- package/dist/cli-adapter.d.ts +8 -14
- package/dist/cli-adapter.d.ts.map +1 -1
- package/dist/cli-adapter.js +19 -64
- package/dist/cli-adapter.js.map +1 -1
- package/dist/cli-watch.d.ts +13 -0
- package/dist/cli-watch.d.ts.map +1 -0
- package/dist/cli-watch.js +185 -0
- package/dist/cli-watch.js.map +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +387 -14
- package/dist/cli.js.map +1 -1
- package/dist/cloud-http.d.ts +22 -0
- package/dist/cloud-http.d.ts.map +1 -0
- package/dist/cloud-http.js +84 -0
- package/dist/cloud-http.js.map +1 -0
- package/dist/cloud-run.d.ts +38 -0
- package/dist/cloud-run.d.ts.map +1 -0
- package/dist/cloud-run.js +112 -0
- package/dist/cloud-run.js.map +1 -0
- package/dist/compile.d.ts +21 -3
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +97 -23
- package/dist/compile.js.map +1 -1
- package/dist/create-flow.d.ts +17 -0
- package/dist/create-flow.d.ts.map +1 -0
- package/dist/create-flow.js +72 -0
- package/dist/create-flow.js.map +1 -0
- package/dist/daemon-connection.d.ts +14 -0
- package/dist/daemon-connection.d.ts.map +1 -1
- package/dist/daemon-connection.js +33 -1
- package/dist/daemon-connection.js.map +1 -1
- package/dist/demo-hn-monitor.js +2 -1
- package/dist/demo-hn-monitor.js.map +1 -1
- package/dist/effect-channel.d.ts +30 -0
- package/dist/effect-channel.d.ts.map +1 -0
- package/dist/effect-channel.js +71 -0
- package/dist/effect-channel.js.map +1 -0
- package/dist/failure-kinds.d.ts +14 -3
- package/dist/failure-kinds.d.ts.map +1 -1
- package/dist/failure-kinds.js +27 -0
- package/dist/failure-kinds.js.map +1 -1
- package/dist/gate-contract.d.ts.map +1 -1
- package/dist/gate-contract.js +9 -0
- package/dist/gate-contract.js.map +1 -1
- package/dist/helper-preflight.d.ts +18 -0
- package/dist/helper-preflight.d.ts.map +1 -0
- package/dist/helper-preflight.js +32 -0
- package/dist/helper-preflight.js.map +1 -0
- package/dist/helper-storage.d.ts +5 -0
- package/dist/helper-storage.d.ts.map +1 -0
- package/dist/helper-storage.js +31 -0
- package/dist/helper-storage.js.map +1 -0
- package/dist/helper-writeback.d.ts +12 -0
- package/dist/helper-writeback.d.ts.map +1 -0
- package/dist/helper-writeback.js +95 -0
- package/dist/helper-writeback.js.map +1 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/input-binding.d.ts +4 -0
- package/dist/input-binding.d.ts.map +1 -0
- package/dist/input-binding.js +78 -0
- package/dist/input-binding.js.map +1 -0
- package/dist/journal-client.d.ts +12 -4
- package/dist/journal-client.d.ts.map +1 -1
- package/dist/journal-client.js +17 -6
- package/dist/journal-client.js.map +1 -1
- package/dist/journal-offset.d.ts +3 -0
- package/dist/journal-offset.d.ts.map +1 -0
- package/dist/journal-offset.js +69 -0
- package/dist/journal-offset.js.map +1 -0
- package/dist/journal-reader.d.ts +30 -0
- package/dist/journal-reader.d.ts.map +1 -0
- package/dist/journal-reader.js +156 -0
- package/dist/journal-reader.js.map +1 -0
- package/dist/json-schema.d.ts +2 -0
- package/dist/json-schema.d.ts.map +1 -1
- package/dist/json-schema.js +38 -22
- package/dist/json-schema.js.map +1 -1
- package/dist/llm-worker.d.ts +16 -0
- package/dist/llm-worker.d.ts.map +1 -0
- package/dist/llm-worker.js +79 -0
- package/dist/llm-worker.js.map +1 -0
- package/dist/local-agent.d.ts +8 -0
- package/dist/local-agent.d.ts.map +1 -0
- package/dist/local-agent.js +25 -0
- package/dist/local-agent.js.map +1 -0
- package/dist/mcp-client.d.ts +15 -0
- package/dist/mcp-client.d.ts.map +1 -0
- package/dist/mcp-client.js +104 -0
- package/dist/mcp-client.js.map +1 -0
- package/dist/mcp-config.d.ts +4 -0
- package/dist/mcp-config.d.ts.map +1 -0
- package/dist/mcp-config.js +61 -0
- package/dist/mcp-config.js.map +1 -0
- package/dist/mcp-stdio.d.ts +24 -0
- package/dist/mcp-stdio.d.ts.map +1 -0
- package/dist/mcp-stdio.js +89 -0
- package/dist/mcp-stdio.js.map +1 -0
- package/dist/model-pricing.d.ts +22 -0
- package/dist/model-pricing.d.ts.map +1 -0
- package/dist/model-pricing.js +30 -0
- package/dist/model-pricing.js.map +1 -0
- package/dist/mount-registry.d.ts +9 -0
- package/dist/mount-registry.d.ts.map +1 -0
- package/dist/mount-registry.js +47 -0
- package/dist/mount-registry.js.map +1 -0
- package/dist/named-gate-lowering.d.ts +9 -0
- package/dist/named-gate-lowering.d.ts.map +1 -0
- package/dist/named-gate-lowering.js +152 -0
- package/dist/named-gate-lowering.js.map +1 -0
- package/dist/named-gates.d.ts +10 -0
- package/dist/named-gates.d.ts.map +1 -0
- package/dist/named-gates.js +69 -0
- package/dist/named-gates.js.map +1 -0
- package/dist/observer-link.d.ts +129 -0
- package/dist/observer-link.d.ts.map +1 -0
- package/dist/observer-link.js +274 -0
- package/dist/observer-link.js.map +1 -0
- package/dist/plugin-loader.d.ts +13 -0
- package/dist/plugin-loader.d.ts.map +1 -0
- package/dist/plugin-loader.js +110 -0
- package/dist/plugin-loader.js.map +1 -0
- package/dist/plugin-manifest.d.ts +27 -0
- package/dist/plugin-manifest.d.ts.map +1 -0
- package/dist/plugin-manifest.js +89 -0
- package/dist/plugin-manifest.js.map +1 -0
- package/dist/preflight.d.ts +26 -2
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +175 -1
- package/dist/preflight.js.map +1 -1
- package/dist/progress.d.ts +14 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +39 -0
- package/dist/progress.js.map +1 -0
- package/dist/protocol.d.ts +11 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/pty-sidechannel.d.ts +14 -0
- package/dist/pty-sidechannel.d.ts.map +1 -0
- package/dist/pty-sidechannel.js +103 -0
- package/dist/pty-sidechannel.js.map +1 -0
- package/dist/scope-compiler.d.ts +52 -0
- package/dist/scope-compiler.d.ts.map +1 -0
- package/dist/scope-compiler.js +62 -0
- package/dist/scope-compiler.js.map +1 -0
- package/dist/slack-preflight.d.ts +6 -0
- package/dist/slack-preflight.d.ts.map +1 -0
- package/dist/slack-preflight.js +28 -0
- package/dist/slack-preflight.js.map +1 -0
- package/dist/slack-writeback.d.ts +40 -0
- package/dist/slack-writeback.d.ts.map +1 -0
- package/dist/slack-writeback.js +60 -0
- package/dist/slack-writeback.js.map +1 -0
- package/dist/spec.d.ts +134 -4
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js.map +1 -1
- package/dist/step-dependencies.d.ts.map +1 -1
- package/dist/step-dependencies.js +2 -1
- package/dist/step-dependencies.js.map +1 -1
- package/dist/step-fields.d.ts +4 -4
- package/dist/step-fields.d.ts.map +1 -1
- package/dist/step-fields.js +5 -2
- package/dist/step-fields.js.map +1 -1
- package/dist/trigger-executor.d.ts +7 -0
- package/dist/trigger-executor.d.ts.map +1 -0
- package/dist/trigger-executor.js +35 -0
- package/dist/trigger-executor.js.map +1 -0
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +53 -6
- package/dist/validate.js.map +1 -1
- package/dist/webhook-rate-limit.d.ts +29 -0
- package/dist/webhook-rate-limit.d.ts.map +1 -0
- package/dist/webhook-rate-limit.js +38 -0
- package/dist/webhook-rate-limit.js.map +1 -0
- package/dist/webhook-signature.d.ts +22 -0
- package/dist/webhook-signature.d.ts.map +1 -0
- package/dist/webhook-signature.js +53 -0
- package/dist/webhook-signature.js.map +1 -0
- package/dist/worker-cli.d.ts +16 -1
- package/dist/worker-cli.d.ts.map +1 -1
- package/dist/worker-cli.js +129 -12
- package/dist/worker-cli.js.map +1 -1
- package/dist/worker-input.d.ts +4 -0
- package/dist/worker-input.d.ts.map +1 -0
- package/dist/worker-input.js +14 -0
- package/dist/worker-input.js.map +1 -0
- package/dist/worker-lease.d.ts +5 -0
- package/dist/worker-lease.d.ts.map +1 -0
- package/dist/worker-lease.js +80 -0
- package/dist/worker-lease.js.map +1 -0
- package/dist/worker-spend.d.ts +19 -0
- package/dist/worker-spend.d.ts.map +1 -0
- package/dist/worker-spend.js +22 -0
- package/dist/worker-spend.js.map +1 -0
- package/dist/worker-usage.d.ts +7 -0
- package/dist/worker-usage.d.ts.map +1 -0
- package/dist/worker-usage.js +54 -0
- package/dist/worker-usage.js.map +1 -0
- package/dist/worker.d.ts +2 -0
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +29 -9
- package/dist/worker.js.map +1 -1
- package/dist/wrapper-session.d.ts +1 -1
- package/dist/wrapper-session.d.ts.map +1 -1
- package/dist/wrapper-session.js +56 -19
- package/dist/wrapper-session.js.map +1 -1
- package/dist/yaml-helper-effect.d.ts +8 -0
- package/dist/yaml-helper-effect.d.ts.map +1 -0
- package/dist/yaml-helper-effect.js +79 -0
- package/dist/yaml-helper-effect.js.map +1 -0
- package/dist/yaml-helpers.d.ts +18 -0
- package/dist/yaml-helpers.d.ts.map +1 -0
- package/dist/yaml-helpers.js +116 -0
- package/dist/yaml-helpers.js.map +1 -0
- package/package.json +19 -2
- package/src/adapters/base.ts +53 -0
- package/src/adapters/claude.ts +55 -0
- package/src/adapters/codex.ts +56 -0
- package/src/adapters/index.ts +36 -0
- package/src/adapters/wrapper.ts +42 -0
- package/src/agent-relay-receipt.ts +120 -0
- package/src/agent-relay-state.ts +73 -0
- package/src/agent-relay-transport.ts +273 -0
- package/src/authored-budget.ts +69 -0
- package/src/authored-flow-error.ts +10 -10
- package/src/authored-flow-executor.ts +171 -347
- package/src/authored-flow-loader.ts +60 -3
- package/src/authored-flow-operation.ts +38 -5
- package/src/authored-helper-effect.ts +143 -0
- package/src/authored-mcp.ts +166 -0
- package/src/authored-memory.ts +55 -0
- package/src/authored-plugin-effect.ts +152 -0
- package/src/authored-step-output.ts +107 -0
- package/src/authored-worker-step.ts +181 -0
- package/src/budget-preflight.ts +31 -0
- package/src/budget.ts +49 -0
- package/src/bundle-transport.ts +79 -0
- package/src/bundle-typescript.ts +98 -0
- package/src/bundle.ts +182 -0
- package/src/child-stop.ts +138 -0
- package/src/cli/add.ts +45 -0
- package/src/cli/build.ts +214 -0
- package/src/cli/bundle-preflight.ts +28 -0
- package/src/cli/check-helper-body.ts +14 -0
- package/src/cli/check-triggers.ts +41 -0
- package/src/cli/check-typescript.ts +63 -0
- package/src/cli/check.ts +132 -14
- package/src/cli/cloud-run.ts +47 -0
- package/src/cli/deploy.ts +52 -0
- package/src/cli/deterministic-failure.ts +69 -0
- package/src/cli/direct-run.ts +79 -18
- package/src/cli/hn-monitor.ts +2 -1
- package/src/cli/replay.ts +81 -0
- package/src/cli/reuse.ts +23 -0
- package/src/cli/run-digest.ts +24 -0
- package/src/cli/run.ts +104 -21
- package/src/cli/serve-webhook.ts +246 -0
- package/src/cli/tick-runner.ts +2 -1
- package/src/cli-adapter.ts +31 -74
- package/src/cli-watch.ts +174 -0
- package/src/cli.ts +396 -17
- package/src/cloud-http.ts +100 -0
- package/src/cloud-run.ts +137 -0
- package/src/compile.ts +102 -23
- package/src/create-flow.ts +82 -0
- package/src/daemon-connection.ts +32 -1
- package/src/demo-hn-monitor.ts +2 -1
- package/src/effect-channel.ts +97 -0
- package/src/failure-kinds.ts +38 -0
- package/src/gate-contract.ts +7 -0
- package/src/helper-preflight.ts +34 -0
- package/src/helper-storage.ts +23 -0
- package/src/helper-writeback.ts +83 -0
- package/src/index.ts +26 -0
- package/src/input-binding.ts +76 -0
- package/src/journal-client.ts +20 -7
- package/src/journal-offset.ts +60 -0
- package/src/journal-reader.ts +165 -0
- package/src/json-schema.ts +34 -18
- package/src/llm-worker.ts +82 -0
- package/src/local-agent.ts +30 -0
- package/src/mcp-client.ts +97 -0
- package/src/mcp-config.ts +42 -0
- package/src/mcp-stdio.ts +84 -0
- package/src/model-pricing.ts +32 -0
- package/src/mount-registry.ts +44 -0
- package/src/named-gate-lowering.ts +147 -0
- package/src/named-gates.ts +76 -0
- package/src/observer-link.ts +368 -0
- package/src/plugin-loader.ts +88 -0
- package/src/plugin-manifest.ts +76 -0
- package/src/preflight.ts +178 -4
- package/src/progress.ts +51 -0
- package/src/protocol.ts +12 -0
- package/src/pty-sidechannel.ts +92 -0
- package/src/scope-compiler.ts +105 -0
- package/src/slack-preflight.ts +25 -0
- package/src/slack-writeback.ts +63 -0
- package/src/spec.ts +112 -4
- package/src/step-dependencies.ts +3 -1
- package/src/step-fields.ts +5 -2
- package/src/trigger-executor.ts +34 -0
- package/src/validate.ts +47 -6
- package/src/webhook-rate-limit.ts +69 -0
- package/src/webhook-signature.ts +74 -0
- package/src/worker-cli.ts +150 -11
- package/src/worker-input.ts +15 -0
- package/src/worker-lease.ts +85 -0
- package/src/worker-spend.ts +23 -0
- package/src/worker-usage.ts +48 -0
- package/src/worker.ts +34 -10
- package/src/wrapper-session.ts +50 -15
- package/src/yaml-helper-effect.ts +78 -0
- package/src/yaml-helpers.ts +131 -0
package/src/failure-kinds.ts
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
|
+
import { PLUGIN_FAILURE_KINDS } from './plugin-manifest.js';
|
|
2
|
+
import { NAMED_GATE_FAILURE_KINDS } from './named-gates.js';
|
|
1
3
|
const SHARED_SPEC_FAILURE_KINDS = ['invalid_spec'] as const;
|
|
2
4
|
|
|
3
5
|
/** Environment refusal kinds produced after spec validation succeeds. */
|
|
4
6
|
const PREFLIGHT_ENVIRONMENT_FAILURE_KINDS = [
|
|
7
|
+
...NAMED_GATE_FAILURE_KINDS,
|
|
8
|
+
...PLUGIN_FAILURE_KINDS,
|
|
9
|
+
'helper_provider.mount_required',
|
|
10
|
+
'helper_provider.unsupported',
|
|
11
|
+
'helper_slack.credential_missing',
|
|
12
|
+
'helper_slack.mount_required',
|
|
13
|
+
'helper_mount_required',
|
|
14
|
+
'mcp_undeclared_server',
|
|
15
|
+
'mcp_unreachable',
|
|
16
|
+
'budget_syntax_invalid',
|
|
17
|
+
'budget_missing_price',
|
|
5
18
|
'cli_missing',
|
|
6
19
|
'cli_unauthenticated',
|
|
7
20
|
'cli_unresolved',
|
|
@@ -9,8 +22,12 @@ const PREFLIGHT_ENVIRONMENT_FAILURE_KINDS = [
|
|
|
9
22
|
'command_missing',
|
|
10
23
|
'model_unavailable',
|
|
11
24
|
'model_unknown',
|
|
25
|
+
'memory_unreachable',
|
|
12
26
|
'no_executor',
|
|
13
27
|
'probe_failed',
|
|
28
|
+
'scope_syntax_invalid',
|
|
29
|
+
'mount_unknown',
|
|
30
|
+
'scope_ungrantable',
|
|
14
31
|
] as const;
|
|
15
32
|
|
|
16
33
|
/** Closed refusal taxonomy for public preflight (RFC covenant 2). */
|
|
@@ -63,6 +80,14 @@ export const PREFLIGHT_WARNING_KINDS = [
|
|
|
63
80
|
* step failed. All of them are still exit 2 — refused before a journal write.
|
|
64
81
|
*/
|
|
65
82
|
export const RUN_FAILURE_KINDS = [
|
|
83
|
+
'bucket_unconfigured',
|
|
84
|
+
'bucket_unreachable',
|
|
85
|
+
'bundle_signature_invalid',
|
|
86
|
+
'bundle_unsupported',
|
|
87
|
+
'human_influenced_run',
|
|
88
|
+
'reuse_spec_mismatch',
|
|
89
|
+
'reuse_run_not_found',
|
|
90
|
+
'reuse_journal_read_failed',
|
|
66
91
|
'daemon_unreachable',
|
|
67
92
|
'daemon_protocol_mismatch',
|
|
68
93
|
'daemon_start_failed',
|
|
@@ -83,12 +108,25 @@ export const RUN_WARNING_KINDS = [
|
|
|
83
108
|
'connection_file_stale',
|
|
84
109
|
] as const;
|
|
85
110
|
|
|
111
|
+
/** File-level editor hints emitted by flows check, outside pure preflight. */
|
|
112
|
+
export const CHECK_WARNING_KINDS = ['editor_schema_missing'] as const;
|
|
113
|
+
export type CheckWarningKind = (typeof CHECK_WARNING_KINDS)[number];
|
|
114
|
+
|
|
86
115
|
export type PreflightFailureKind = (typeof PREFLIGHT_FAILURE_KINDS)[number];
|
|
87
116
|
export type CheckFailureKind = (typeof CHECK_FAILURE_KINDS)[number];
|
|
88
117
|
export type PreflightWarningKind = (typeof PREFLIGHT_WARNING_KINDS)[number];
|
|
89
118
|
export type RunFailureKind = (typeof RUN_FAILURE_KINDS)[number];
|
|
90
119
|
export type RunWarningKind = (typeof RUN_WARNING_KINDS)[number];
|
|
91
120
|
|
|
121
|
+
/** Optional evidence on the existing step_failed diagnostic, not a new kind. */
|
|
122
|
+
export interface StepFailedDetails {
|
|
123
|
+
stepId?: string;
|
|
124
|
+
exitCode?: number;
|
|
125
|
+
/** Terminal-safe UTF-8 excerpt, at most 1,024 bytes. */
|
|
126
|
+
stderrTail?: string;
|
|
127
|
+
hint?: string;
|
|
128
|
+
}
|
|
129
|
+
|
|
92
130
|
const CHECK_FAILURE_KIND_SET: ReadonlySet<string> = new Set(CHECK_FAILURE_KINDS);
|
|
93
131
|
const RUN_FAILURE_KIND_SET: ReadonlySet<string> = new Set(RUN_FAILURE_KINDS);
|
|
94
132
|
|
package/src/gate-contract.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { StepSpec } from './spec.js';
|
|
2
|
+
import { isNamedGate } from './named-gates.js';
|
|
2
3
|
|
|
3
4
|
export type JournalGateCheck =
|
|
4
5
|
| 'completion'
|
|
@@ -54,6 +55,12 @@ export function acceptsAnyOutput(schema: unknown): boolean {
|
|
|
54
55
|
/** Describe the exact named checks the existing kernel applies to a step. */
|
|
55
56
|
export function inspectStepGate(step: StepSpec): StepGateInspection {
|
|
56
57
|
const checks: JournalGateCheck[] = [];
|
|
58
|
+
if (isNamedGate(step.verification)) {
|
|
59
|
+
checks.push('exit_code');
|
|
60
|
+
if (step.verification.type === 'references_input') checks.push('output_contains');
|
|
61
|
+
if (step.verification.type === 'word_count_bounds') checks.push('json_schema');
|
|
62
|
+
return { stepId: step.id, kind: 'data', checks, evaluator: 'kernel', preflightable: true, replayable: true };
|
|
63
|
+
}
|
|
57
64
|
if (step.type === 'deterministic') checks.push('exit_code');
|
|
58
65
|
if (step.verification?.type === 'output_contains') checks.push('output_contains');
|
|
59
66
|
if (step.verification?.type === 'json_schema') checks.push('json_schema');
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { helperProviders } from '@relayflows/surface/runtime';
|
|
2
|
+
import type { PreflightResult, PreflightDiagnostic } from './preflight.js';
|
|
3
|
+
|
|
4
|
+
/** Static discovery never executes the body; dynamic aliases are checked at call time. */
|
|
5
|
+
export function preflightHelpers(
|
|
6
|
+
definition: { header?: { tools?: Readonly<Record<string, unknown>> }; body?: Function },
|
|
7
|
+
facts: { slackToken?: string; slackMount?: boolean; slackMock?: boolean;
|
|
8
|
+
providers?: Readonly<Record<string, { mount: boolean; mock: boolean; token?: string }>> },
|
|
9
|
+
): PreflightResult {
|
|
10
|
+
const body = typeof definition.body === 'function' ? Function.prototype.toString.call(definition.body) : '';
|
|
11
|
+
const parameter = body.match(/^(?:async\s+)?(?:function(?:\s+[\w$]+)?\s*)?(?:\(\s*([\w$]+)|([\w$]+)\s*=>)/);
|
|
12
|
+
const root = (parameter?.[1] ?? parameter?.[2])?.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
13
|
+
const diagnostics: PreflightDiagnostic[] = [];
|
|
14
|
+
for (const { provider, namespace, supported } of helperProviders) {
|
|
15
|
+
const used = definition.header?.tools?.[namespace] === true
|
|
16
|
+
|| (root !== undefined && new RegExp(`(?:^|[^\\w$.])${root}\\s*(?:\\.\\s*${namespace}\\b|\\[\\s*['"]${namespace}['"]\\s*\\])`).test(body));
|
|
17
|
+
if (!used) continue;
|
|
18
|
+
const fact = facts.providers?.[provider] ?? (provider === 'slack'
|
|
19
|
+
? { mount: facts.slackMount, mock: facts.slackMock, token: facts.slackToken }
|
|
20
|
+
: { mount: false, mock: false, token: undefined });
|
|
21
|
+
if (!supported) {
|
|
22
|
+
diagnostics.push({ severity: 'refusal', kind: 'helper_provider.unsupported',
|
|
23
|
+
message: `f.${namespace} has no upstream relayfile writeback client.` });
|
|
24
|
+
} else if (!fact.mock && !fact.mount) {
|
|
25
|
+
diagnostics.push({ severity: 'refusal',
|
|
26
|
+
kind: provider === 'slack' ? (fact.token?.trim() ? 'helper_slack.mount_required' : 'helper_slack.credential_missing') : 'helper_provider.mount_required',
|
|
27
|
+
message: `f.${namespace} requires a relayfile ${provider} mount; direct-token transport is not implemented.` });
|
|
28
|
+
} else if (provider === 'notion' && !fact.mock && /\.\s*appendBlock\b/.test(body)) {
|
|
29
|
+
diagnostics.push({ severity: 'refusal', kind: 'helper_provider.unsupported',
|
|
30
|
+
message: 'f.notion.appendBlock is mock-only: the Notion adapter has no append-block writeback route.' });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return { ok: diagnostics.length === 0, gates: [], resolutions: [], diagnostics };
|
|
34
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { mkdir, open, readFile, rename } from 'node:fs/promises';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
/** Durable receipt precedes effect.confirm, so a confirmed replay can recover it. */
|
|
6
|
+
export async function atomicJson(path: string, value: unknown): Promise<void> {
|
|
7
|
+
await mkdir(dirname(path), { recursive: true });
|
|
8
|
+
const temporary = `${path}.${randomUUID()}.tmp`;
|
|
9
|
+
const file = await open(temporary, 'wx', 0o600);
|
|
10
|
+
try { await file.writeFile(JSON.stringify(value)); await file.sync(); }
|
|
11
|
+
finally { await file.close(); }
|
|
12
|
+
await rename(temporary, path);
|
|
13
|
+
const directory = await open(dirname(path), 'r');
|
|
14
|
+
try { await directory.sync(); } finally { await directory.close(); }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function receiptPath(dataDir: string, runId: string, stepId: string): string {
|
|
18
|
+
return join(dataDir, 'helper-receipts', createHash('sha256').update(`${runId}:${stepId}`).digest('hex') + '.json');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function readHelperReceipt(path: string): Promise<unknown> {
|
|
22
|
+
return JSON.parse(await readFile(path, 'utf8')) as unknown;
|
|
23
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { writeJsonFile, readJsonFile, listJsonFiles, type WritebackResult } from '@relayfile/adapter-core/vfs-client';
|
|
4
|
+
import type { RelayTransport, RelayTransportRequest } from '@relayfile/relay-helpers/transport';
|
|
5
|
+
import { helperClients, helperProviders, invokeHelper, type HelperCall } from '@relayflows/surface/runtime';
|
|
6
|
+
import { providerMount } from './slack-preflight.js';
|
|
7
|
+
import { atomicJson } from './helper-storage.js';
|
|
8
|
+
import type { SlackCall } from './slack-writeback.js';
|
|
9
|
+
|
|
10
|
+
export class HelperDeliveryError extends Error {}
|
|
11
|
+
|
|
12
|
+
export async function helperWriteback(call: HelperCall, dataDir: string, runId: string, stepId: string, signal: AbortSignal): Promise<unknown> {
|
|
13
|
+
const factory = helperClients[call.provider];
|
|
14
|
+
if (!factory) throw new Error(`No writeback client for ${call.provider}`);
|
|
15
|
+
const { transport } = helperTransport(call, dataDir, runId, stepId, signal);
|
|
16
|
+
try { return await invokeHelper(factory, call, transport); }
|
|
17
|
+
catch (cause) { throw new HelperDeliveryError(cause instanceof Error ? cause.message : String(cause), { cause }); }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** One transport for every provider, including Slack. Only confirmed writes succeed. */
|
|
21
|
+
export function helperTransport(call: HelperCall | SlackCall, dataDir: string, runId: string, stepId: string, signal: AbortSignal) {
|
|
22
|
+
const provider = helperProviders.find(p => p.provider === call.provider);
|
|
23
|
+
if (!provider) throw new Error(`Unknown helper provider ${call.provider}`);
|
|
24
|
+
const mock = process.env[provider.mockEnv] === '1';
|
|
25
|
+
const mount = providerMount(provider.provider);
|
|
26
|
+
const options = () => {
|
|
27
|
+
signal.throwIfAborted();
|
|
28
|
+
if (!mount) throw new Error(`${provider.provider} requires a relayfile mount`);
|
|
29
|
+
return { relayfileMountRoot: mount };
|
|
30
|
+
};
|
|
31
|
+
const idempotencyKey = `${runId}:${stepId}`;
|
|
32
|
+
let deliveredRef = '';
|
|
33
|
+
const transport: RelayTransport = {
|
|
34
|
+
async read<T>(request: RelayTransportRequest): Promise<T> {
|
|
35
|
+
signal.throwIfAborted();
|
|
36
|
+
if (mock) return {} as T;
|
|
37
|
+
return readJsonFile<T>(options(), call.provider, `read.${request.resource}`, request.path);
|
|
38
|
+
},
|
|
39
|
+
async list<T>(request: RelayTransportRequest): Promise<T[]> {
|
|
40
|
+
signal.throwIfAborted();
|
|
41
|
+
if (mock) return [];
|
|
42
|
+
return (await listJsonFiles<T>(options(), call.provider, `list.${request.resource}`, request.path)).map(file => file.value);
|
|
43
|
+
},
|
|
44
|
+
async write(request) {
|
|
45
|
+
signal.throwIfAborted();
|
|
46
|
+
if (request.provider !== call.provider) throw new Error('Helper transport provider mismatch');
|
|
47
|
+
if (!mock && call.provider === 'notion' && call.verb === 'appendBlock') {
|
|
48
|
+
throw new Error('Notion appendBlock has no upstream mount writeback route');
|
|
49
|
+
}
|
|
50
|
+
if (typeof request.body !== 'object' || request.body === null || Array.isArray(request.body)) {
|
|
51
|
+
throw new Error('Helper writeback requires a JSON object');
|
|
52
|
+
}
|
|
53
|
+
const body: Record<string, unknown> = { ...request.body as Record<string, unknown>, idempotencyKey };
|
|
54
|
+
// Item paths must remain canonical; only collections receive a draft filename.
|
|
55
|
+
const draft = /\.[a-z]+$/i.test(request.path) ? request.path
|
|
56
|
+
: `${request.path}/draft-${createHash('sha256').update(idempotencyKey).digest('hex')}.json`;
|
|
57
|
+
let result: WritebackResult;
|
|
58
|
+
if (mock) {
|
|
59
|
+
deliveredRef = `mock-ref-${stepId}`;
|
|
60
|
+
result = { path: deliveredRef, absolutePath: draft, deliveryStatus: 'confirmed', receipt: { externalId: `mock-${stepId}` } };
|
|
61
|
+
await atomicJson(join(dataDir, 'mock-writeback', call.provider, `${stepId}.json`), {
|
|
62
|
+
...call, ...body,
|
|
63
|
+
...(call.provider === 'slack' ? { channel: request.parameters.channelId,
|
|
64
|
+
...(body.parentRef === undefined ? {} : { replyTo: body.parentRef }) } : {}),
|
|
65
|
+
runId, stepId, request: { ...request, body }, receipt: result.receipt,
|
|
66
|
+
});
|
|
67
|
+
} else {
|
|
68
|
+
try { result = await writeJsonFile(options(), call.provider, `write.${request.resource}`, draft, body); }
|
|
69
|
+
catch (cause) {
|
|
70
|
+
// Upstream created() converts pending/terminal adapter errors into values.
|
|
71
|
+
// A journal effect must fail instead of confirming an undelivered write.
|
|
72
|
+
throw new Error(`${call.provider} writeback failed: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
|
|
73
|
+
}
|
|
74
|
+
if (result.deliveryStatus !== 'confirmed' || !result.receipt) throw new Error(`${call.provider} writeback is pending; no delivery receipt`);
|
|
75
|
+
if (call.provider === 'slack' && call.verb !== 'react' && !result.receipt.externalId && !result.receipt.ts) throw new Error('Slack writeback has no delivered timestamp');
|
|
76
|
+
deliveredRef = result.path;
|
|
77
|
+
}
|
|
78
|
+
signal.throwIfAborted();
|
|
79
|
+
return result;
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
return { transport, deliveredRef: () => deliveredRef };
|
|
83
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,11 @@ export type {
|
|
|
12
12
|
DeterministicStepSpec,
|
|
13
13
|
ExitCodeGate,
|
|
14
14
|
FlowSpec,
|
|
15
|
+
YamlFlowSpec,
|
|
16
|
+
YamlHelperStepSpec,
|
|
17
|
+
YamlHelperParams,
|
|
18
|
+
FlowsJson,
|
|
19
|
+
McpServerConfig,
|
|
15
20
|
JsonSchemaGate,
|
|
16
21
|
JsonOutputSchema,
|
|
17
22
|
KernelAgentStep,
|
|
@@ -28,7 +33,13 @@ export type {
|
|
|
28
33
|
KernelVerificationSpec,
|
|
29
34
|
LlmStepSpec,
|
|
30
35
|
NamedAgentSpec,
|
|
36
|
+
NamedDataGate,
|
|
37
|
+
ReferencesInputGate,
|
|
38
|
+
SubprocessGate,
|
|
39
|
+
WordCountBoundsGate,
|
|
40
|
+
RegexMatchGate,
|
|
31
41
|
OutputContainsGate,
|
|
42
|
+
OutputBinding,
|
|
32
43
|
OutputVerificationSpec,
|
|
33
44
|
PermissionsSpec,
|
|
34
45
|
RecoveryMode,
|
|
@@ -42,8 +53,17 @@ export type {
|
|
|
42
53
|
VerificationSpec,
|
|
43
54
|
WorkspaceSurface,
|
|
44
55
|
} from './spec.js';
|
|
56
|
+
export { MODEL_PRICING } from './model-pricing.js';
|
|
57
|
+
export type { HeaderBudget } from './budget.js';
|
|
58
|
+
export type { StepSpend } from './protocol.js';
|
|
45
59
|
export { SPEC_SCHEMA_VERSION } from './spec.js';
|
|
46
60
|
|
|
61
|
+
export { CloudFlowError, type CloudConnectionOptions } from './cloud-http.js';
|
|
62
|
+
export {
|
|
63
|
+
runInCloud, getCloudFlowRun, waitForCloudFlowRun,
|
|
64
|
+
type CloudFlowSource, type RunInCloudOptions, type CloudRunReceipt, type CloudRunState,
|
|
65
|
+
} from './cloud-run.js';
|
|
66
|
+
|
|
47
67
|
export { canonicalize, specHash } from './canonical.js';
|
|
48
68
|
export {
|
|
49
69
|
compileAndHash,
|
|
@@ -63,6 +83,7 @@ export {
|
|
|
63
83
|
} from './authored-flow.js';
|
|
64
84
|
export {
|
|
65
85
|
preflight,
|
|
86
|
+
preflightHelpers,
|
|
66
87
|
type CliResolution,
|
|
67
88
|
type CliResolutionSource,
|
|
68
89
|
type CliProbeResult,
|
|
@@ -199,3 +220,8 @@ export {
|
|
|
199
220
|
type TickPayload,
|
|
200
221
|
type TickSchedule,
|
|
201
222
|
} from './tick-source.js';
|
|
223
|
+
|
|
224
|
+
export { createFlow, type CreateFlowOptions, type CreatedFlow } from './create-flow.js';
|
|
225
|
+
|
|
226
|
+
export { renderProgress, type ProgressEvent } from './progress.js';
|
|
227
|
+
export { webhookTriggerSpec } from './trigger-executor.js';
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { OutputBinding } from './spec.js';
|
|
2
|
+
|
|
3
|
+
/** Input is a closed selector map, never a template or expression language. */
|
|
4
|
+
export function inputBindingErrors(steps: readonly unknown[]): string[] {
|
|
5
|
+
const errors: string[] = [];
|
|
6
|
+
const sources = new Map(steps.flatMap((step, index) =>
|
|
7
|
+
isObject(step) && typeof step.id === 'string' ? [[step.id, { step, index }] as const] : []));
|
|
8
|
+
for (const [index, step] of steps.entries()) {
|
|
9
|
+
if (!isObject(step) || step.input === undefined) continue;
|
|
10
|
+
const at = `spec.steps[${index}].input`;
|
|
11
|
+
if (!isObject(step.input)) {
|
|
12
|
+
errors.push(`${at}: expected a map of output selectors`);
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
for (const [name, binding] of Object.entries(step.input)) {
|
|
16
|
+
const where = `${at}.${name}`;
|
|
17
|
+
if (!name.trim() || !isBinding(binding)) {
|
|
18
|
+
errors.push(`${where}: expected { step: <id>, path?: [object keys or array indices] }`);
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const source = sources.get(binding.step);
|
|
22
|
+
if (source === undefined) {
|
|
23
|
+
errors.push(`${where}: unknown source step "${binding.step}"`);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (source.index >= index) {
|
|
27
|
+
errors.push(`${where}: source "${binding.step}" must precede this step; forward and self references are not supported`);
|
|
28
|
+
}
|
|
29
|
+
const gate = source.step.verification;
|
|
30
|
+
const schema = source.step.output ?? (isObject(gate) && gate.type === 'json_schema' ? gate.schema : undefined);
|
|
31
|
+
if (schema === undefined) {
|
|
32
|
+
errors.push(`${where}: source "${binding.step}" must declare an output schema (output or json_schema verification)`);
|
|
33
|
+
} else if (!declaresPath(schema, binding.path ?? [])) {
|
|
34
|
+
errors.push(`${where}: path ${JSON.stringify(binding.path)} is not present in source "${binding.step}"'s declared output schema`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return errors;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function bindingDependencies(input: unknown): string[] {
|
|
42
|
+
return isObject(input) ? Object.values(input).filter(isBinding).map(binding => binding.step) : [];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function isBinding(value: unknown): value is OutputBinding {
|
|
46
|
+
return isObject(value)
|
|
47
|
+
&& Object.keys(value).every(key => key === 'step' || key === 'path')
|
|
48
|
+
&& typeof value.step === 'string' && value.step.trim().length > 0
|
|
49
|
+
&& (value.path === undefined || (Array.isArray(value.path) && value.path.every(segment =>
|
|
50
|
+
typeof segment === 'string' || (typeof segment === 'number' && Number.isSafeInteger(segment) && segment >= 0))));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Only explicit properties/items paths are portable; no schema inference. */
|
|
54
|
+
function declaresPath(schema: unknown, path: readonly (string | number)[]): boolean {
|
|
55
|
+
let current = schema;
|
|
56
|
+
for (const segment of path) {
|
|
57
|
+
if (!isObject(current)) return false;
|
|
58
|
+
if (typeof segment === 'string') {
|
|
59
|
+
if (!isObject(current.properties) || !Object.hasOwn(current.properties, segment)) return false;
|
|
60
|
+
current = current.properties[segment];
|
|
61
|
+
} else if (Array.isArray(current.prefixItems) && segment < current.prefixItems.length) {
|
|
62
|
+
current = current.prefixItems[segment];
|
|
63
|
+
} else if (Array.isArray(current.items)) {
|
|
64
|
+
if (segment >= current.items.length) return false;
|
|
65
|
+
current = current.items[segment];
|
|
66
|
+
} else {
|
|
67
|
+
if (current.items === undefined) return false;
|
|
68
|
+
current = current.items;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return current !== undefined && current !== false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isObject(value: unknown): value is Record<string, unknown> {
|
|
75
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
76
|
+
}
|
package/src/journal-client.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
// loopback double in tests.
|
|
11
11
|
|
|
12
12
|
import { EventEmitter } from 'node:events';
|
|
13
|
+
export { walkJournal, JournalReadError, type JournalEvent, type JournalReadFailure } from './journal-reader.js';
|
|
13
14
|
import { randomUUID } from 'node:crypto';
|
|
14
15
|
import { createConnection, type Socket } from 'node:net';
|
|
15
16
|
import type { VerbContract, EventSubmitParams } from './protocol.js';
|
|
@@ -65,7 +66,7 @@ export class JournalClient extends EventEmitter {
|
|
|
65
66
|
private readonly connectTimeoutMs: number;
|
|
66
67
|
|
|
67
68
|
constructor(
|
|
68
|
-
|
|
69
|
+
readonly socketPath: string,
|
|
69
70
|
options: JournalClientOptions = {},
|
|
70
71
|
) {
|
|
71
72
|
super();
|
|
@@ -73,6 +74,13 @@ export class JournalClient extends EventEmitter {
|
|
|
73
74
|
this.connectTimeoutMs = options.connectTimeoutMs ?? 2_000;
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
/** Independent session for an SDK helper worker; preserves the caller's registration. */
|
|
78
|
+
createPeer(): JournalClient {
|
|
79
|
+
return new JournalClient(this.socketPath, {
|
|
80
|
+
requestTimeoutMs: this.requestTimeoutMs, connectTimeoutMs: this.connectTimeoutMs,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
76
84
|
/** Open the unix socket connection. Rejects on connect failure (fail-closed). */
|
|
77
85
|
connect(): Promise<void> {
|
|
78
86
|
return new Promise((resolve, reject) => {
|
|
@@ -196,13 +204,13 @@ export class JournalClient extends EventEmitter {
|
|
|
196
204
|
* the run file, and append `run.spawned`. Authoring specs must be compiled
|
|
197
205
|
* with `toKernelSpec` before crossing this journal-protocol boundary.
|
|
198
206
|
*/
|
|
199
|
-
runStart(spec: KernelRunSpec): Promise<VerbContract['run.start']['result']> {
|
|
200
|
-
return this.request('run.start', { spec }, null);
|
|
207
|
+
runStart(spec: KernelRunSpec, reuseFromRunId?: string): Promise<VerbContract['run.start']['result']> {
|
|
208
|
+
return this.request('run.start', { spec, ...(reuseFromRunId === undefined ? {} : { reuse_from_run_id: reuseFromRunId }) }, null);
|
|
201
209
|
}
|
|
202
210
|
|
|
203
211
|
/** §3 memoized resume. */
|
|
204
|
-
runResume(runId: string): Promise<VerbContract['run.resume']['result']> {
|
|
205
|
-
return this.request('run.resume', { run_id: runId }, null);
|
|
212
|
+
runResume(runId: string, allowHumanInfluenced = false): Promise<VerbContract['run.resume']['result']> {
|
|
213
|
+
return this.request('run.resume', { run_id: runId, ...(allowHumanInfluenced ? { allow_human_influenced: true } : {}) }, null);
|
|
206
214
|
}
|
|
207
215
|
|
|
208
216
|
/** Durably request cancellation and return the terminal run fact. */
|
|
@@ -341,7 +349,11 @@ export class JournalClient extends EventEmitter {
|
|
|
341
349
|
});
|
|
342
350
|
}
|
|
343
351
|
|
|
344
|
-
/**
|
|
352
|
+
/**
|
|
353
|
+
* Complete a dispatched step — also the out-of-band path. Like runStart
|
|
354
|
+
* and runResume, this drives downstream steps before replying, so their
|
|
355
|
+
* execution bounds apply rather than the bounded protocol-request timeout.
|
|
356
|
+
*/
|
|
345
357
|
stepComplete(
|
|
346
358
|
runId: string,
|
|
347
359
|
stepId: string,
|
|
@@ -355,6 +367,7 @@ export class JournalClient extends EventEmitter {
|
|
|
355
367
|
end_pins?: Pins;
|
|
356
368
|
effects?: EffectRef[];
|
|
357
369
|
trajectory_tail?: unknown;
|
|
370
|
+
human_intervention?: boolean;
|
|
358
371
|
} = {},
|
|
359
372
|
): Promise<VerbContract['step.complete']['result']> {
|
|
360
373
|
return this.request('step.complete', {
|
|
@@ -364,7 +377,7 @@ export class JournalClient extends EventEmitter {
|
|
|
364
377
|
idempotency_key: idempotencyKey,
|
|
365
378
|
completionReason,
|
|
366
379
|
...extra,
|
|
367
|
-
});
|
|
380
|
+
}, null);
|
|
368
381
|
}
|
|
369
382
|
|
|
370
383
|
/** Satisfy `wait.event`; a human response arrives here too. */
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
|
|
3
|
+
/** Locate a table row's cell in a SQLite snapshot for read-error diagnostics. */
|
|
4
|
+
export function journalRecordOffset(path: string, rootPage: number, seq: number): string {
|
|
5
|
+
const main = readFileSync(path);
|
|
6
|
+
const encodedSize = main.readUInt16BE(16);
|
|
7
|
+
const pageSize = encodedSize === 1 ? 65536 : encodedSize;
|
|
8
|
+
const pages = new Map<number, { bytes: Buffer; offset: number; file: string }>();
|
|
9
|
+
let wal: Buffer | undefined;
|
|
10
|
+
try { wal = readFileSync(`${path}-wal`); } catch (error) {
|
|
11
|
+
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
|
|
12
|
+
}
|
|
13
|
+
if (wal !== undefined) {
|
|
14
|
+
const frameSize = pageSize + 24;
|
|
15
|
+
let lastCommit = 0;
|
|
16
|
+
for (let frame = 32; frame + frameSize <= wal.length; frame += frameSize) {
|
|
17
|
+
// RESTART checkpoints reuse the WAL without truncating its old tail.
|
|
18
|
+
// Frames from that prior generation are not part of SQLite's view.
|
|
19
|
+
if (!wal.subarray(frame + 8, frame + 16).equals(wal.subarray(16, 24))) break;
|
|
20
|
+
if (wal.readUInt32BE(frame + 4) !== 0) lastCommit = frame;
|
|
21
|
+
}
|
|
22
|
+
for (let frame = 32; frame <= lastCommit; frame += frameSize) {
|
|
23
|
+
pages.set(wal.readUInt32BE(frame), { bytes: wal, offset: frame + 24, file: 'WAL' });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const visited = new Set<number>();
|
|
27
|
+
let page = rootPage;
|
|
28
|
+
while (!visited.has(page)) {
|
|
29
|
+
visited.add(page);
|
|
30
|
+
const source = pages.get(page) ?? { bytes: main, offset: (page - 1) * pageSize, file: 'journal' };
|
|
31
|
+
const header = source.offset + (page === 1 ? 100 : 0);
|
|
32
|
+
const kind = source.bytes[header];
|
|
33
|
+
if (kind !== 5 && kind !== 13) break;
|
|
34
|
+
const count = source.bytes.readUInt16BE(header + 3);
|
|
35
|
+
let next = kind === 5 ? source.bytes.readUInt32BE(header + 8) : 0;
|
|
36
|
+
for (let index = 0; index < count; index += 1) {
|
|
37
|
+
const cell = source.offset + source.bytes.readUInt16BE(header + (kind === 5 ? 12 : 8) + 2 * index);
|
|
38
|
+
const rowIdOffset = kind === 5 ? cell + 4 : varint(source.bytes, cell).next;
|
|
39
|
+
const rowId = varint(source.bytes, rowIdOffset).value;
|
|
40
|
+
if (kind === 13 && rowId === BigInt(seq)) return `${source.file} byte offset ${cell}`;
|
|
41
|
+
if (kind === 5 && BigInt(seq) <= rowId) {
|
|
42
|
+
next = source.bytes.readUInt32BE(cell);
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (next === 0) break;
|
|
47
|
+
page = next;
|
|
48
|
+
}
|
|
49
|
+
throw new Error('Cannot locate journal record cell.');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function varint(bytes: Buffer, offset: number): { value: bigint; next: number } {
|
|
53
|
+
let value = 0n;
|
|
54
|
+
for (let index = 0; index < 9; index += 1) {
|
|
55
|
+
const byte = bytes.readUInt8(offset++);
|
|
56
|
+
value = (value << (index === 8 ? 8n : 7n)) | BigInt(index === 8 ? byte : byte & 0x7f);
|
|
57
|
+
if (byte < 0x80 || index === 8) return { value, next: offset };
|
|
58
|
+
}
|
|
59
|
+
throw new Error('Invalid SQLite varint.');
|
|
60
|
+
}
|