@provos/ironcurtain 0.10.0 → 0.12.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/README.md +68 -14
- package/dist/auth/oauth-provider.js +1 -4
- package/dist/auth/oauth-provider.js.map +1 -1
- package/dist/cli-help.d.ts +12 -0
- package/dist/cli-help.js +21 -0
- package/dist/cli-help.js.map +1 -1
- package/dist/cli.js +46 -6
- package/dist/cli.js.map +1 -1
- package/dist/config/agent-model-guard.d.ts +14 -0
- package/dist/config/agent-model-guard.js +24 -0
- package/dist/config/agent-model-guard.js.map +1 -0
- package/dist/config/config-command.js +277 -7
- package/dist/config/config-command.js.map +1 -1
- package/dist/config/first-start.js +62 -7
- package/dist/config/first-start.js.map +1 -1
- package/dist/config/generated/compiled-policy.json +528 -161
- package/dist/config/generated/test-scenarios.json +4810 -170
- package/dist/config/generated/tool-annotations.json +34 -47
- package/dist/config/index.d.ts +58 -0
- package/dist/config/index.js +97 -15
- package/dist/config/index.js.map +1 -1
- package/dist/config/mcp-servers.json +2 -2
- package/dist/config/model-provider.d.ts +9 -0
- package/dist/config/model-provider.js +13 -0
- package/dist/config/model-provider.js.map +1 -1
- package/dist/config/paths.d.ts +217 -0
- package/dist/config/paths.js +363 -14
- package/dist/config/paths.js.map +1 -1
- package/dist/config/types.d.ts +7 -1
- package/dist/config/user-config.d.ts +101 -6
- package/dist/config/user-config.js +145 -31
- package/dist/config/user-config.js.map +1 -1
- package/dist/config/validate-policy-dir.d.ts +10 -0
- package/dist/config/validate-policy-dir.js +59 -0
- package/dist/config/validate-policy-dir.js.map +1 -0
- package/dist/cron/job-commands.js +22 -2
- package/dist/cron/job-commands.js.map +1 -1
- package/dist/cron/types.d.ts +16 -2
- package/dist/cron/types.js +1 -3
- package/dist/cron/types.js.map +1 -1
- package/dist/daemon/daemon-command.js +30 -7
- package/dist/daemon/daemon-command.js.map +1 -1
- package/dist/daemon/ironcurtain-daemon.d.ts +62 -1
- package/dist/daemon/ironcurtain-daemon.js +231 -8
- package/dist/daemon/ironcurtain-daemon.js.map +1 -1
- package/dist/daemon-client/daemon-client.d.ts +123 -0
- package/dist/daemon-client/daemon-client.js +324 -0
- package/dist/daemon-client/daemon-client.js.map +1 -0
- package/dist/docker/adapters/claude-code.js +194 -20
- package/dist/docker/adapters/claude-code.js.map +1 -1
- package/dist/docker/adapters/codex.d.ts +9 -0
- package/dist/docker/adapters/codex.js +297 -0
- package/dist/docker/adapters/codex.js.map +1 -0
- package/dist/docker/adapters/goose.d.ts +12 -11
- package/dist/docker/adapters/goose.js +80 -27
- package/dist/docker/adapters/goose.js.map +1 -1
- package/dist/docker/agent-adapter.d.ts +183 -5
- package/dist/docker/agent-adapter.js +16 -0
- package/dist/docker/agent-adapter.js.map +1 -1
- package/dist/docker/agent-registry.js +5 -0
- package/dist/docker/agent-registry.js.map +1 -1
- package/dist/docker/apple-container-manager.d.ts +49 -0
- package/dist/docker/apple-container-manager.js +464 -0
- package/dist/docker/apple-container-manager.js.map +1 -0
- package/dist/docker/code-mode-proxy.d.ts +38 -0
- package/dist/docker/code-mode-proxy.js +6 -1
- package/dist/docker/code-mode-proxy.js.map +1 -1
- package/dist/docker/container-lifecycle.d.ts +2 -2
- package/dist/docker/container-lifecycle.js.map +1 -1
- package/dist/docker/container-runtime.d.ts +29 -0
- package/dist/docker/container-runtime.js +76 -0
- package/dist/docker/container-runtime.js.map +1 -0
- package/dist/docker/docker-agent-session.d.ts +113 -62
- package/dist/docker/docker-agent-session.js +271 -294
- package/dist/docker/docker-agent-session.js.map +1 -1
- package/dist/docker/docker-infrastructure.d.ts +428 -26
- package/dist/docker/docker-infrastructure.js +1005 -70
- package/dist/docker/docker-infrastructure.js.map +1 -1
- package/dist/docker/docker-manager.d.ts +58 -3
- package/dist/docker/docker-manager.js +378 -33
- package/dist/docker/docker-manager.js.map +1 -1
- package/dist/docker/docker-probe.d.ts +45 -0
- package/dist/docker/docker-probe.js +86 -0
- package/dist/docker/docker-probe.js.map +1 -0
- package/dist/docker/docker-progress-sink.d.ts +43 -0
- package/dist/docker/docker-progress-sink.js +299 -0
- package/dist/docker/docker-progress-sink.js.map +1 -0
- package/dist/docker/mitm-proxy.d.ts +135 -1
- package/dist/docker/mitm-proxy.js +611 -25
- package/dist/docker/mitm-proxy.js.map +1 -1
- package/dist/docker/network-topology.d.ts +81 -0
- package/dist/docker/network-topology.js +160 -0
- package/dist/docker/network-topology.js.map +1 -0
- package/dist/docker/oauth-credentials.d.ts +59 -3
- package/dist/docker/oauth-credentials.js +181 -14
- package/dist/docker/oauth-credentials.js.map +1 -1
- package/dist/docker/oauth-token-manager.js +2 -2
- package/dist/docker/oauth-token-manager.js.map +1 -1
- package/dist/docker/orientation.d.ts +1 -1
- package/dist/docker/package-types.d.ts +1 -1
- package/dist/docker/provider-config.d.ts +78 -3
- package/dist/docker/provider-config.js +295 -31
- package/dist/docker/provider-config.js.map +1 -1
- package/dist/docker/provision-lock.d.ts +46 -0
- package/dist/docker/provision-lock.js +152 -0
- package/dist/docker/provision-lock.js.map +1 -0
- package/dist/docker/proxy-tools.d.ts +0 -2
- package/dist/docker/proxy-tools.js +2 -7
- package/dist/docker/proxy-tools.js.map +1 -1
- package/dist/docker/pty-session.d.ts +64 -1
- package/dist/docker/pty-session.js +306 -104
- package/dist/docker/pty-session.js.map +1 -1
- package/dist/docker/pty-types.d.ts +0 -2
- package/dist/docker/pty-types.js +0 -2
- package/dist/docker/pty-types.js.map +1 -1
- package/dist/docker/registry-proxy.d.ts +46 -0
- package/dist/docker/registry-proxy.js +255 -1
- package/dist/docker/registry-proxy.js.map +1 -1
- package/dist/docker/resource-limits.d.ts +134 -0
- package/dist/docker/resource-limits.js +203 -0
- package/dist/docker/resource-limits.js.map +1 -0
- package/dist/docker/spawn-with-idle-timeout.d.ts +39 -0
- package/dist/docker/spawn-with-idle-timeout.js +152 -0
- package/dist/docker/spawn-with-idle-timeout.js.map +1 -0
- package/dist/docker/sse-extractor.d.ts +51 -0
- package/dist/docker/sse-extractor.js +303 -0
- package/dist/docker/sse-extractor.js.map +1 -0
- package/dist/docker/token-stream-bus.d.ts +83 -0
- package/dist/docker/token-stream-bus.js +98 -0
- package/dist/docker/token-stream-bus.js.map +1 -0
- package/dist/docker/token-stream-types.d.ts +71 -0
- package/dist/docker/token-stream-types.js +8 -0
- package/dist/docker/token-stream-types.js.map +1 -0
- package/dist/docker/trajectory-capture.d.ts +79 -0
- package/dist/docker/trajectory-capture.js +521 -0
- package/dist/docker/trajectory-capture.js.map +1 -0
- package/dist/docker/trajectory-reassembler.d.ts +286 -0
- package/dist/docker/trajectory-reassembler.js +990 -0
- package/dist/docker/trajectory-reassembler.js.map +1 -0
- package/dist/docker/trajectory-tap.d.ts +100 -0
- package/dist/docker/trajectory-tap.js +410 -0
- package/dist/docker/trajectory-tap.js.map +1 -0
- package/dist/docker/trajectory-types.d.ts +187 -0
- package/dist/docker/trajectory-types.js +43 -0
- package/dist/docker/trajectory-types.js.map +1 -0
- package/dist/docker/types.d.ts +105 -12
- package/dist/doctor/checks.d.ts +171 -0
- package/dist/doctor/checks.js +598 -0
- package/dist/doctor/checks.js.map +1 -0
- package/dist/doctor/doctor-command.d.ts +29 -0
- package/dist/doctor/doctor-command.js +190 -0
- package/dist/doctor/doctor-command.js.map +1 -0
- package/dist/doctor/mcp-liveness.d.ts +28 -0
- package/dist/doctor/mcp-liveness.js +92 -0
- package/dist/doctor/mcp-liveness.js.map +1 -0
- package/dist/doctor/oauth-checks.d.ts +23 -0
- package/dist/doctor/oauth-checks.js +157 -0
- package/dist/doctor/oauth-checks.js.map +1 -0
- package/dist/doctor/output.d.ts +26 -0
- package/dist/doctor/output.js +82 -0
- package/dist/doctor/output.js.map +1 -0
- package/dist/escalation/listener-command.js +0 -3
- package/dist/escalation/listener-command.js.map +1 -1
- package/dist/event-bus/typed-event-bus.d.ts +26 -0
- package/dist/event-bus/typed-event-bus.js +35 -0
- package/dist/event-bus/typed-event-bus.js.map +1 -0
- package/dist/index.js +54 -21
- package/dist/index.js.map +1 -1
- package/dist/logger.js +31 -2
- package/dist/logger.js.map +1 -1
- package/dist/memory/auto-save.d.ts +18 -4
- package/dist/memory/auto-save.js +46 -6
- package/dist/memory/auto-save.js.map +1 -1
- package/dist/memory/memory-policy.d.ts +41 -0
- package/dist/memory/memory-policy.js +36 -0
- package/dist/memory/memory-policy.js.map +1 -0
- package/dist/mux/mux-app.d.ts +2 -0
- package/dist/mux/mux-app.js +1 -0
- package/dist/mux/mux-app.js.map +1 -1
- package/dist/mux/mux-command.d.ts +10 -1
- package/dist/mux/mux-command.js +74 -40
- package/dist/mux/mux-command.js.map +1 -1
- package/dist/mux/mux-renderer.js +2 -12
- package/dist/mux/mux-renderer.js.map +1 -1
- package/dist/mux/pty-bridge.d.ts +2 -0
- package/dist/mux/pty-bridge.js +3 -0
- package/dist/mux/pty-bridge.js.map +1 -1
- package/dist/mux/session-scanner.js +1 -2
- package/dist/mux/session-scanner.js.map +1 -1
- package/dist/{pipeline → observability}/llm-logger.d.ts +8 -3
- package/dist/{pipeline → observability}/llm-logger.js +8 -3
- package/dist/observability/llm-logger.js.map +1 -0
- package/dist/observe/observe-command.d.ts +12 -0
- package/dist/observe/observe-command.js +285 -0
- package/dist/observe/observe-command.js.map +1 -0
- package/dist/observe/observe-renderer.d.ts +24 -0
- package/dist/observe/observe-renderer.js +87 -0
- package/dist/observe/observe-renderer.js.map +1 -0
- package/dist/observe/observe-tui-rain.d.ts +42 -0
- package/dist/observe/observe-tui-rain.js +531 -0
- package/dist/observe/observe-tui-rain.js.map +1 -0
- package/dist/observe/observe-tui-text-panel.d.ts +46 -0
- package/dist/observe/observe-tui-text-panel.js +525 -0
- package/dist/observe/observe-tui-text-panel.js.map +1 -0
- package/dist/observe/observe-tui-types.d.ts +270 -0
- package/dist/observe/observe-tui-types.js +200 -0
- package/dist/observe/observe-tui-types.js.map +1 -0
- package/dist/observe/observe-tui-word-scorer.d.ts +143 -0
- package/dist/observe/observe-tui-word-scorer.js +572 -0
- package/dist/observe/observe-tui-word-scorer.js.map +1 -0
- package/dist/observe/observe-tui.d.ts +59 -0
- package/dist/observe/observe-tui.js +592 -0
- package/dist/observe/observe-tui.js.map +1 -0
- package/dist/persona/broad-policy-validator.d.ts +95 -0
- package/dist/persona/broad-policy-validator.js +171 -0
- package/dist/persona/broad-policy-validator.js.map +1 -0
- package/dist/persona/compile-persona-policy.d.ts +54 -2
- package/dist/persona/compile-persona-policy.js +29 -4
- package/dist/persona/compile-persona-policy.js.map +1 -1
- package/dist/persona/event-bus-progress-reporter.d.ts +57 -0
- package/dist/persona/event-bus-progress-reporter.js +66 -0
- package/dist/persona/event-bus-progress-reporter.js.map +1 -0
- package/dist/persona/memory-gate.d.ts +19 -0
- package/dist/persona/memory-gate.js +33 -0
- package/dist/persona/memory-gate.js.map +1 -0
- package/dist/persona/persona-command.js +77 -72
- package/dist/persona/persona-command.js.map +1 -1
- package/dist/persona/persona-compile-orchestrator.d.ts +101 -0
- package/dist/persona/persona-compile-orchestrator.js +504 -0
- package/dist/persona/persona-compile-orchestrator.js.map +1 -0
- package/dist/persona/persona-service.d.ts +137 -0
- package/dist/persona/persona-service.js +263 -0
- package/dist/persona/persona-service.js.map +1 -0
- package/dist/persona/policy-mutation-audit.d.ts +109 -0
- package/dist/persona/policy-mutation-audit.js +179 -0
- package/dist/persona/policy-mutation-audit.js.map +1 -0
- package/dist/persona/resolve.d.ts +22 -0
- package/dist/persona/resolve.js +45 -2
- package/dist/persona/resolve.js.map +1 -1
- package/dist/persona/rule-delta.d.ts +30 -0
- package/dist/persona/rule-delta.js +82 -0
- package/dist/persona/rule-delta.js.map +1 -0
- package/dist/persona/types.d.ts +28 -0
- package/dist/pipeline/annotate.js +10 -2
- package/dist/pipeline/annotate.js.map +1 -1
- package/dist/pipeline/compile.js +14 -2
- package/dist/pipeline/compile.js.map +1 -1
- package/dist/pipeline/constitution-compiler.d.ts +25 -14
- package/dist/pipeline/constitution-compiler.js +107 -38
- package/dist/pipeline/constitution-compiler.js.map +1 -1
- package/dist/pipeline/dynamic-list-types.d.ts +3 -6
- package/dist/pipeline/dynamic-list-types.js +3 -16
- package/dist/pipeline/dynamic-list-types.js.map +1 -1
- package/dist/pipeline/pipeline-runner.d.ts +63 -4
- package/dist/pipeline/pipeline-runner.js +242 -94
- package/dist/pipeline/pipeline-runner.js.map +1 -1
- package/dist/pipeline/pipeline-shared.d.ts +33 -4
- package/dist/pipeline/pipeline-shared.js +79 -19
- package/dist/pipeline/pipeline-shared.js.map +1 -1
- package/dist/pipeline/policy-verifier.js +16 -3
- package/dist/pipeline/policy-verifier.js.map +1 -1
- package/dist/pipeline/proxy-mcp-connections.js +17 -2
- package/dist/pipeline/proxy-mcp-connections.js.map +1 -1
- package/dist/pipeline/refresh-lists.js +3 -5
- package/dist/pipeline/refresh-lists.js.map +1 -1
- package/dist/pipeline/scenario-generator.d.ts +4 -8
- package/dist/pipeline/scenario-generator.js +13 -46
- package/dist/pipeline/scenario-generator.js.map +1 -1
- package/dist/sandbox/index.d.ts +29 -0
- package/dist/sandbox/index.js +351 -119
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/ironcurtain-protocol.d.ts +52 -0
- package/dist/sandbox/ironcurtain-protocol.js +185 -0
- package/dist/sandbox/ironcurtain-protocol.js.map +1 -0
- package/dist/session/agent-session.d.ts +6 -0
- package/dist/session/agent-session.js +16 -5
- package/dist/session/agent-session.js.map +1 -1
- package/dist/session/cli-transport.js +0 -6
- package/dist/session/cli-transport.js.map +1 -1
- package/dist/session/index.d.ts +35 -14
- package/dist/session/index.js +333 -130
- package/dist/session/index.js.map +1 -1
- package/dist/session/preflight.d.ts +21 -13
- package/dist/session/preflight.js +227 -88
- package/dist/session/preflight.js.map +1 -1
- package/dist/session/prompts.d.ts +2 -5
- package/dist/session/prompts.js.map +1 -1
- package/dist/session/session-manager.d.ts +61 -6
- package/dist/session/session-manager.js +72 -10
- package/dist/session/session-manager.js.map +1 -1
- package/dist/session/session-metadata.d.ts +21 -5
- package/dist/session/session-metadata.js +34 -12
- package/dist/session/session-metadata.js.map +1 -1
- package/dist/session/types.d.ts +320 -5
- package/dist/session/types.js +57 -1
- package/dist/session/types.js.map +1 -1
- package/dist/signal/bot-command.js +6 -1
- package/dist/signal/bot-command.js.map +1 -1
- package/dist/signal/setup-signal.js +13 -21
- package/dist/signal/setup-signal.js.map +1 -1
- package/dist/signal/signal-bot-daemon.d.ts +16 -1
- package/dist/signal/signal-bot-daemon.js +39 -27
- package/dist/signal/signal-bot-daemon.js.map +1 -1
- package/dist/signal/signal-container.d.ts +3 -3
- package/dist/signal/signal-container.js +9 -3
- package/dist/signal/signal-container.js.map +1 -1
- package/dist/skills/discovery.d.ts +77 -0
- package/dist/skills/discovery.js +206 -0
- package/dist/skills/discovery.js.map +1 -0
- package/dist/skills/index.d.ts +4 -0
- package/dist/skills/index.js +3 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/staging.d.ts +28 -0
- package/dist/skills/staging.js +68 -0
- package/dist/skills/staging.js.map +1 -0
- package/dist/skills/types.d.ts +46 -0
- package/dist/skills/types.js +2 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/trusted-process/approval-whitelist.d.ts +0 -2
- package/dist/trusted-process/approval-whitelist.js +17 -17
- package/dist/trusted-process/approval-whitelist.js.map +1 -1
- package/dist/trusted-process/async-mutex.d.ts +32 -0
- package/dist/trusted-process/async-mutex.js +50 -0
- package/dist/trusted-process/async-mutex.js.map +1 -0
- package/dist/trusted-process/audit-log.d.ts +38 -1
- package/dist/trusted-process/audit-log.js +82 -13
- package/dist/trusted-process/audit-log.js.map +1 -1
- package/dist/trusted-process/call-circuit-breaker.d.ts +6 -0
- package/dist/trusted-process/call-circuit-breaker.js +23 -3
- package/dist/trusted-process/call-circuit-breaker.js.map +1 -1
- package/dist/trusted-process/container-command.d.ts +35 -0
- package/dist/trusted-process/container-command.js +49 -0
- package/dist/trusted-process/container-command.js.map +1 -0
- package/dist/trusted-process/control-server.d.ts +101 -0
- package/dist/trusted-process/control-server.js +282 -0
- package/dist/trusted-process/control-server.js.map +1 -0
- package/dist/trusted-process/domain-utils.d.ts +6 -6
- package/dist/trusted-process/domain-utils.js +7 -23
- package/dist/trusted-process/domain-utils.js.map +1 -1
- package/dist/trusted-process/error-prefixes.d.ts +16 -0
- package/dist/trusted-process/error-prefixes.js +17 -0
- package/dist/trusted-process/error-prefixes.js.map +1 -0
- package/dist/trusted-process/index.d.ts +40 -23
- package/dist/trusted-process/index.js +131 -225
- package/dist/trusted-process/index.js.map +1 -1
- package/dist/trusted-process/list-matcher.d.ts +17 -0
- package/dist/trusted-process/list-matcher.js +31 -0
- package/dist/trusted-process/list-matcher.js.map +1 -0
- package/dist/trusted-process/mcp-client-manager.d.ts +35 -6
- package/dist/trusted-process/mcp-client-manager.js +40 -45
- package/dist/trusted-process/mcp-client-manager.js.map +1 -1
- package/dist/trusted-process/mcp-proxy-server.d.ts +31 -120
- package/dist/trusted-process/mcp-proxy-server.js +201 -660
- package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
- package/dist/trusted-process/policy-engine.d.ts +16 -4
- package/dist/trusted-process/policy-engine.js +103 -47
- package/dist/trusted-process/policy-engine.js.map +1 -1
- package/dist/trusted-process/policy-roots.d.ts +6 -0
- package/dist/trusted-process/policy-roots.js +20 -0
- package/dist/trusted-process/policy-roots.js.map +1 -1
- package/dist/trusted-process/sandbox-integration.d.ts +12 -0
- package/dist/trusted-process/sandbox-integration.js +18 -0
- package/dist/trusted-process/sandbox-integration.js.map +1 -1
- package/dist/trusted-process/tcp-server-transport.d.ts +12 -1
- package/dist/trusted-process/tcp-server-transport.js +9 -1
- package/dist/trusted-process/tcp-server-transport.js.map +1 -1
- package/dist/trusted-process/tool-call-coordinator.d.ts +283 -0
- package/dist/trusted-process/tool-call-coordinator.js +592 -0
- package/dist/trusted-process/tool-call-coordinator.js.map +1 -0
- package/dist/trusted-process/tool-call-pipeline.d.ts +213 -0
- package/dist/trusted-process/tool-call-pipeline.js +832 -0
- package/dist/trusted-process/tool-call-pipeline.js.map +1 -0
- package/dist/trusted-process/tool-description-hints.d.ts +1 -1
- package/dist/types/argument-roles.d.ts +1 -1
- package/dist/types/argument-roles.js +14 -1
- package/dist/types/argument-roles.js.map +1 -1
- package/dist/types/audit.d.ts +9 -0
- package/dist/{session → types}/errors.d.ts +8 -2
- package/dist/{session → types}/errors.js +8 -2
- package/dist/types/errors.js.map +1 -0
- package/dist/types/reserved-servers.d.ts +11 -0
- package/dist/types/reserved-servers.js +12 -0
- package/dist/types/reserved-servers.js.map +1 -0
- package/dist/types/server-listing.d.ts +14 -0
- package/dist/types/server-listing.js +2 -0
- package/dist/types/server-listing.js.map +1 -0
- package/dist/types/slug.d.ts +2 -0
- package/dist/types/slug.js +2 -0
- package/dist/types/slug.js.map +1 -1
- package/dist/types/url-normalize.d.ts +16 -0
- package/dist/types/url-normalize.js +33 -0
- package/dist/types/url-normalize.js.map +1 -0
- package/dist/util/atomic-write.d.ts +31 -0
- package/dist/util/atomic-write.js +43 -0
- package/dist/util/atomic-write.js.map +1 -0
- package/dist/utils/error-message.d.ts +8 -0
- package/dist/utils/error-message.js +11 -0
- package/dist/utils/error-message.js.map +1 -0
- package/dist/utils/exec-error.d.ts +19 -0
- package/dist/utils/exec-error.js +16 -0
- package/dist/utils/exec-error.js.map +1 -0
- package/dist/utils/is-plain-object.d.ts +7 -0
- package/dist/utils/is-plain-object.js +12 -0
- package/dist/utils/is-plain-object.js.map +1 -0
- package/dist/utils/preflight-checks.d.ts +16 -0
- package/dist/utils/preflight-checks.js +178 -0
- package/dist/utils/preflight-checks.js.map +1 -0
- package/dist/web-ui/__tests__/json-rpc-dispatch.test.d.ts +7 -0
- package/dist/web-ui/__tests__/json-rpc-dispatch.test.js +725 -0
- package/dist/web-ui/__tests__/json-rpc-dispatch.test.js.map +1 -0
- package/dist/web-ui/conn-registry.d.ts +14 -0
- package/dist/web-ui/conn-registry.js +25 -0
- package/dist/web-ui/conn-registry.js.map +1 -0
- package/dist/web-ui/dispatch/escalation-dispatch.d.ts +7 -0
- package/dist/web-ui/dispatch/escalation-dispatch.js +52 -0
- package/dist/web-ui/dispatch/escalation-dispatch.js.map +1 -0
- package/dist/web-ui/dispatch/job-dispatch.d.ts +8 -0
- package/dist/web-ui/dispatch/job-dispatch.js +83 -0
- package/dist/web-ui/dispatch/job-dispatch.js.map +1 -0
- package/dist/web-ui/dispatch/persona-dispatch.d.ts +50 -0
- package/dist/web-ui/dispatch/persona-dispatch.js +269 -0
- package/dist/web-ui/dispatch/persona-dispatch.js.map +1 -0
- package/dist/web-ui/dispatch/session-dispatch.d.ts +9 -0
- package/dist/web-ui/dispatch/session-dispatch.js +219 -0
- package/dist/web-ui/dispatch/session-dispatch.js.map +1 -0
- package/dist/web-ui/dispatch/token-stream-dispatch.d.ts +15 -0
- package/dist/web-ui/dispatch/token-stream-dispatch.js +55 -0
- package/dist/web-ui/dispatch/token-stream-dispatch.js.map +1 -0
- package/dist/web-ui/dispatch/types.d.ts +54 -0
- package/dist/web-ui/dispatch/types.js +72 -0
- package/dist/web-ui/dispatch/types.js.map +1 -0
- package/dist/web-ui/dispatch/workflow-dispatch.d.ts +103 -0
- package/dist/web-ui/dispatch/workflow-dispatch.js +1036 -0
- package/dist/web-ui/dispatch/workflow-dispatch.js.map +1 -0
- package/dist/web-ui/json-rpc-dispatch.d.ts +12 -0
- package/dist/web-ui/json-rpc-dispatch.js +34 -0
- package/dist/web-ui/json-rpc-dispatch.js.map +1 -0
- package/dist/web-ui/state-graph.d.ts +13 -0
- package/dist/web-ui/state-graph.js +82 -0
- package/dist/web-ui/state-graph.js.map +1 -0
- package/dist/web-ui/token-stream-bridge.d.ts +76 -0
- package/dist/web-ui/token-stream-bridge.js +265 -0
- package/dist/web-ui/token-stream-bridge.js.map +1 -0
- package/dist/web-ui/web-event-bus.d.ts +176 -0
- package/dist/web-ui/web-event-bus.js +19 -0
- package/dist/web-ui/web-event-bus.js.map +1 -0
- package/dist/web-ui/web-session-transport.d.ts +31 -0
- package/dist/web-ui/web-session-transport.js +109 -0
- package/dist/web-ui/web-session-transport.js.map +1 -0
- package/dist/web-ui/web-ui-server.d.ts +90 -0
- package/dist/web-ui/web-ui-server.js +477 -0
- package/dist/web-ui/web-ui-server.js.map +1 -0
- package/dist/web-ui/web-ui-types.d.ts +418 -0
- package/dist/web-ui/web-ui-types.js +32 -0
- package/dist/web-ui/web-ui-types.js.map +1 -0
- package/dist/web-ui/ws-utils.d.ts +5 -0
- package/dist/web-ui/ws-utils.js +12 -0
- package/dist/web-ui/ws-utils.js.map +1 -0
- package/dist/web-ui-static/assets/index-BD5U6ILh.css +1 -0
- package/dist/web-ui-static/assets/index-FMsHWEfK.js +79 -0
- package/dist/web-ui-static/assets/orbitron-latin-700-normal-4jsRXGGJ.woff2 +0 -0
- package/dist/web-ui-static/assets/orbitron-latin-700-normal-DmYOh-W9.woff +0 -0
- package/dist/web-ui-static/index.html +14 -0
- package/dist/workflow/artifacts.d.ts +59 -0
- package/dist/workflow/artifacts.js +188 -0
- package/dist/workflow/artifacts.js.map +1 -0
- package/dist/workflow/checkpoint-selection.d.ts +34 -0
- package/dist/workflow/checkpoint-selection.js +48 -0
- package/dist/workflow/checkpoint-selection.js.map +1 -0
- package/dist/workflow/checkpoint.d.ts +35 -0
- package/dist/workflow/checkpoint.js +84 -0
- package/dist/workflow/checkpoint.js.map +1 -0
- package/dist/workflow/cli-shared.d.ts +62 -0
- package/dist/workflow/cli-shared.js +117 -0
- package/dist/workflow/cli-shared.js.map +1 -0
- package/dist/workflow/cli-support.d.ts +92 -0
- package/dist/workflow/cli-support.js +421 -0
- package/dist/workflow/cli-support.js.map +1 -0
- package/dist/workflow/container-snapshots.d.ts +29 -0
- package/dist/workflow/container-snapshots.js +137 -0
- package/dist/workflow/container-snapshots.js.map +1 -0
- package/dist/workflow/daemon-gate-commands.d.ts +21 -0
- package/dist/workflow/daemon-gate-commands.js +599 -0
- package/dist/workflow/daemon-gate-commands.js.map +1 -0
- package/dist/workflow/definition-loader.d.ts +32 -0
- package/dist/workflow/definition-loader.js +56 -0
- package/dist/workflow/definition-loader.js.map +1 -0
- package/dist/workflow/discovery.d.ts +107 -0
- package/dist/workflow/discovery.js +263 -0
- package/dist/workflow/discovery.js.map +1 -0
- package/dist/workflow/errors.d.ts +66 -0
- package/dist/workflow/errors.js +49 -0
- package/dist/workflow/errors.js.map +1 -0
- package/dist/workflow/guards.d.ts +8 -0
- package/dist/workflow/guards.js +38 -0
- package/dist/workflow/guards.js.map +1 -0
- package/dist/workflow/lane-template.d.ts +89 -0
- package/dist/workflow/lane-template.js +141 -0
- package/dist/workflow/lane-template.js.map +1 -0
- package/dist/workflow/lint-integration.d.ts +64 -0
- package/dist/workflow/lint-integration.js +56 -0
- package/dist/workflow/lint-integration.js.map +1 -0
- package/dist/workflow/lint.d.ts +72 -0
- package/dist/workflow/lint.js +593 -0
- package/dist/workflow/lint.js.map +1 -0
- package/dist/workflow/machine-builder.d.ts +178 -0
- package/dist/workflow/machine-builder.js +678 -0
- package/dist/workflow/machine-builder.js.map +1 -0
- package/dist/workflow/message-log.d.ts +99 -0
- package/dist/workflow/message-log.js +40 -0
- package/dist/workflow/message-log.js.map +1 -0
- package/dist/workflow/orchestrator.d.ts +954 -0
- package/dist/workflow/orchestrator.js +3594 -0
- package/dist/workflow/orchestrator.js.map +1 -0
- package/dist/workflow/prompt-builder.d.ts +39 -0
- package/dist/workflow/prompt-builder.js +243 -0
- package/dist/workflow/prompt-builder.js.map +1 -0
- package/dist/workflow/run-state-command.d.ts +9 -0
- package/dist/workflow/run-state-command.js +414 -0
- package/dist/workflow/run-state-command.js.map +1 -0
- package/dist/workflow/run-state-debug-capture.d.ts +40 -0
- package/dist/workflow/run-state-debug-capture.js +101 -0
- package/dist/workflow/run-state-debug-capture.js.map +1 -0
- package/dist/workflow/status-parser.d.ts +68 -0
- package/dist/workflow/status-parser.js +274 -0
- package/dist/workflow/status-parser.js.map +1 -0
- package/dist/workflow/types.d.ts +598 -0
- package/dist/workflow/types.js +85 -0
- package/dist/workflow/types.js.map +1 -0
- package/dist/workflow/validate.d.ts +80 -0
- package/dist/workflow/validate.js +788 -0
- package/dist/workflow/validate.js.map +1 -0
- package/dist/workflow/workflow-command.d.ts +9 -0
- package/dist/workflow/workflow-command.js +670 -0
- package/dist/workflow/workflow-command.js.map +1 -0
- package/dist/workflow/workflow-discovery.d.ts +27 -0
- package/dist/workflow/workflow-discovery.js +121 -0
- package/dist/workflow/workflow-discovery.js.map +1 -0
- package/dist/workflow/workflow-manager.d.ts +156 -0
- package/dist/workflow/workflow-manager.js +359 -0
- package/dist/workflow/workflow-manager.js.map +1 -0
- package/dist/workflow/workflows/design-and-code/README.md +50 -0
- package/dist/workflow/workflows/design-and-code/workflow.yaml +169 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/scripts/format_report.js +29 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/scripts/package.json +5 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/scripts/requirements.txt +1 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/scripts/run_eval.py +41 -0
- package/dist/workflow/workflows/deterministic-eval-smoke/workflow.yaml +57 -0
- package/dist/workflow/workflows/deterministic-verdict-smoke/scripts/classify.py +18 -0
- package/dist/workflow/workflows/deterministic-verdict-smoke/workflow.yaml +51 -0
- package/dist/workflow/workflows/evolve/scripts/LICENSE +201 -0
- package/dist/workflow/workflows/evolve/scripts/README.md +314 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-brief +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-cognition +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-db +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-eval +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-files +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve-summary +16 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/__init__.py +14 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/__init__.py +17 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/base.py +21 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/factory.py +90 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/greedy.py +17 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/island.py +316 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/random.py +18 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/ucb1.py +55 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/best_snapshot.py +62 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/cli.py +752 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/cognition.py +127 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/database.py +218 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/diff.py +57 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/embedding.py +84 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/file_lock.py +45 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/run_state.py +343 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/sampling_config.py +173 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/structures.py +93 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_core/vector_index.py +191 -0
- package/dist/workflow/workflows/evolve/scripts/evolve_result.py +1503 -0
- package/dist/workflow/workflows/evolve/scripts/requirements.txt +2 -0
- package/dist/workflow/workflows/evolve/workflow.yaml +646 -0
- package/dist/workflow/workflows/test-email-summary/skills/email-formatting/SKILL.md +55 -0
- package/dist/workflow/workflows/test-email-summary/skills/gmail-query-syntax/SKILL.md +63 -0
- package/dist/workflow/workflows/test-email-summary/skills/json-schema-emails/SKILL.md +41 -0
- package/dist/workflow/workflows/test-email-summary/skills/json-schema-emails/schema.json +34 -0
- package/dist/workflow/workflows/test-email-summary/skills/summary-style-guide/SKILL.md +51 -0
- package/dist/workflow/workflows/test-email-summary/workflow.yaml +90 -0
- package/dist/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +206 -0
- package/dist/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +167 -0
- package/dist/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +189 -0
- package/dist/workflow/workflows/vuln-discovery/workflow.yaml +925 -0
- package/dist/workflow/worktree.d.ts +43 -0
- package/dist/workflow/worktree.js +106 -0
- package/dist/workflow/worktree.js.map +1 -0
- package/docker/Dockerfile.base +31 -0
- package/docker/Dockerfile.base.arm64 +27 -0
- package/docker/Dockerfile.claude-code +3 -1
- package/docker/Dockerfile.codex +17 -0
- package/docker/Dockerfile.goose +3 -1
- package/docker/entrypoint-claude-code.sh +7 -0
- package/docker/entrypoint-codex.sh +42 -0
- package/docker/entrypoint-goose.sh +6 -0
- package/docker/entrypoint-uid-remap.sh +93 -0
- package/package.json +27 -11
- package/packages/web-ui/README.md +113 -0
- package/packages/web-ui/docs/workflow-state-machine.png +0 -0
- package/src/config/generated/compiled-policy.json +528 -161
- package/src/config/generated/test-scenarios.json +4810 -170
- package/src/config/generated/tool-annotations.json +34 -47
- package/src/config/mcp-servers.json +2 -2
- package/src/workflow/workflows/design-and-code/README.md +50 -0
- package/src/workflow/workflows/design-and-code/workflow.yaml +169 -0
- package/src/workflow/workflows/deterministic-eval-smoke/scripts/format_report.js +29 -0
- package/src/workflow/workflows/deterministic-eval-smoke/scripts/package.json +5 -0
- package/src/workflow/workflows/deterministic-eval-smoke/scripts/requirements.txt +1 -0
- package/src/workflow/workflows/deterministic-eval-smoke/scripts/run_eval.py +41 -0
- package/src/workflow/workflows/deterministic-eval-smoke/workflow.yaml +57 -0
- package/src/workflow/workflows/deterministic-verdict-smoke/scripts/classify.py +18 -0
- package/src/workflow/workflows/deterministic-verdict-smoke/workflow.yaml +51 -0
- package/src/workflow/workflows/evolve/scripts/LICENSE +201 -0
- package/src/workflow/workflows/evolve/scripts/README.md +314 -0
- package/src/workflow/workflows/evolve/scripts/evolve-brief +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-cognition +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-db +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-eval +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-files +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve-summary +16 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/__init__.py +14 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/__init__.py +17 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/base.py +21 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/factory.py +90 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/greedy.py +17 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/island.py +316 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/random.py +18 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/ucb1.py +55 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/best_snapshot.py +62 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/cli.py +752 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/cognition.py +127 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/database.py +218 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/diff.py +57 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/embedding.py +84 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/file_lock.py +45 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/run_state.py +343 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/sampling_config.py +173 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/structures.py +93 -0
- package/src/workflow/workflows/evolve/scripts/evolve_core/vector_index.py +191 -0
- package/src/workflow/workflows/evolve/scripts/evolve_result.py +1503 -0
- package/src/workflow/workflows/evolve/scripts/requirements.txt +2 -0
- package/src/workflow/workflows/evolve/workflow.yaml +646 -0
- package/src/workflow/workflows/test-email-summary/skills/email-formatting/SKILL.md +55 -0
- package/src/workflow/workflows/test-email-summary/skills/gmail-query-syntax/SKILL.md +63 -0
- package/src/workflow/workflows/test-email-summary/skills/json-schema-emails/SKILL.md +41 -0
- package/src/workflow/workflows/test-email-summary/skills/json-schema-emails/schema.json +34 -0
- package/src/workflow/workflows/test-email-summary/skills/summary-style-guide/SKILL.md +51 -0
- package/src/workflow/workflows/test-email-summary/workflow.yaml +90 -0
- package/src/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +206 -0
- package/src/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +167 -0
- package/src/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +189 -0
- package/src/workflow/workflows/vuln-discovery/workflow.yaml +925 -0
- package/dist/pipeline/llm-logger.js.map +0 -1
- package/dist/session/errors.js.map +0 -1
|
@@ -0,0 +1,678 @@
|
|
|
1
|
+
import { setup, assign, fromPromise } from 'xstate';
|
|
2
|
+
import { guardImplementations } from './guards.js';
|
|
3
|
+
import { stripStatusBlock } from './status-parser.js';
|
|
4
|
+
import { isAgentInvocationError } from './errors.js';
|
|
5
|
+
import { laneScopeEvolveCurrentPath, templateLaneCommand } from './lane-template.js';
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Extraction helpers (used by guards and actions inside the machine)
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
/**
|
|
10
|
+
* Extracts the invoke result from an xstate.done.actor.* event.
|
|
11
|
+
* XState wraps the promise resolution in `event.output`.
|
|
12
|
+
*/
|
|
13
|
+
function extractInvokeResult(event) {
|
|
14
|
+
const output = event.output;
|
|
15
|
+
if (output && typeof output === 'object' && 'output' in output && 'outputHash' in output) {
|
|
16
|
+
return output;
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Agent output truncation
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
const MAX_AGENT_OUTPUT_BYTES = 32_768;
|
|
24
|
+
const TRUNCATION_NOTICE = '\n\n[Output truncated. Read the artifact directories for full details.]';
|
|
25
|
+
/**
|
|
26
|
+
* Sanitizes agent response text for reuse in subsequent prompts: escapes any
|
|
27
|
+
* literal NUL bytes and truncates to stay within the 32KB limit.
|
|
28
|
+
*
|
|
29
|
+
* NUL escaping is load-bearing, not cosmetic. Agent output flows back into
|
|
30
|
+
* later prompts via `previousAgentOutput` / `previousAgentNotes`, which the
|
|
31
|
+
* Docker adapter passes as an argv element to `child_process.spawn`. Node
|
|
32
|
+
* refuses argv strings containing `\0` (`ERR_INVALID_ARG_VALUE`) and throws
|
|
33
|
+
* synchronously before the container even starts — aborting the workflow. A
|
|
34
|
+
* security-research agent describing a binary file format ("APP1 'Exif\\0\\0'")
|
|
35
|
+
* is the natural way this happens. We escape rather than strip so the textual
|
|
36
|
+
* description survives intact for downstream readers.
|
|
37
|
+
*
|
|
38
|
+
* Exported for testing.
|
|
39
|
+
*/
|
|
40
|
+
export function truncateAgentOutput(text) {
|
|
41
|
+
const sanitized = text.includes('\0') ? text.replaceAll('\0', '\\x00') : text;
|
|
42
|
+
if (Buffer.byteLength(sanitized, 'utf-8') <= MAX_AGENT_OUTPUT_BYTES) {
|
|
43
|
+
return sanitized;
|
|
44
|
+
}
|
|
45
|
+
const budget = MAX_AGENT_OUTPUT_BYTES - Buffer.byteLength(TRUNCATION_NOTICE, 'utf-8');
|
|
46
|
+
let truncated = sanitized;
|
|
47
|
+
while (Buffer.byteLength(truncated, 'utf-8') > budget) {
|
|
48
|
+
truncated = truncated.slice(0, Math.floor(truncated.length * 0.9));
|
|
49
|
+
}
|
|
50
|
+
return truncated + TRUNCATION_NOTICE;
|
|
51
|
+
}
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// Initial context factory
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
/**
|
|
56
|
+
* Creates the initial WorkflowContext for a given definition.
|
|
57
|
+
* Exported for testing.
|
|
58
|
+
*/
|
|
59
|
+
export function createInitialContext(definition) {
|
|
60
|
+
return {
|
|
61
|
+
artifacts: {},
|
|
62
|
+
round: 0,
|
|
63
|
+
maxRounds: definition.settings?.maxRounds ?? 4,
|
|
64
|
+
previousOutputHashes: {},
|
|
65
|
+
previousTestCount: null,
|
|
66
|
+
humanPrompt: null,
|
|
67
|
+
reviewHistory: [],
|
|
68
|
+
totalTokens: 0,
|
|
69
|
+
lastError: null,
|
|
70
|
+
agentConversationsByState: {},
|
|
71
|
+
previousAgentOutput: null,
|
|
72
|
+
previousAgentNotes: null,
|
|
73
|
+
previousStateName: null,
|
|
74
|
+
visitCounts: {},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// State builders
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
/**
|
|
81
|
+
* Finds an appropriate error target for a state. Looks for a human_gate
|
|
82
|
+
* in the definition's transitions, then falls back to any terminal state.
|
|
83
|
+
*/
|
|
84
|
+
function findErrorTarget(stateDef, definition) {
|
|
85
|
+
// Check if any transition leads to a human gate (good for error review)
|
|
86
|
+
for (const t of stateDef.transitions) {
|
|
87
|
+
const targetState = definition.states[t.to];
|
|
88
|
+
if (targetState.type === 'human_gate')
|
|
89
|
+
return t.to;
|
|
90
|
+
}
|
|
91
|
+
// Fall back: prefer terminal states named 'aborted' or 'failed'
|
|
92
|
+
for (const [id, state] of Object.entries(definition.states)) {
|
|
93
|
+
if (state.type === 'terminal' && (id === 'aborted' || id === 'failed'))
|
|
94
|
+
return id;
|
|
95
|
+
}
|
|
96
|
+
// Then any terminal
|
|
97
|
+
for (const [id, state] of Object.entries(definition.states)) {
|
|
98
|
+
if (state.type === 'terminal')
|
|
99
|
+
return id;
|
|
100
|
+
}
|
|
101
|
+
// Last resort: first transition target (machine will at least not crash)
|
|
102
|
+
if (stateDef.transitions.length > 0) {
|
|
103
|
+
return stateDef.transitions[0].to;
|
|
104
|
+
}
|
|
105
|
+
// Should not happen in a validated definition
|
|
106
|
+
throw new Error('No valid error target found');
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Collects all transition actions for a given transition definition into
|
|
110
|
+
* XState action entries, preserving order:
|
|
111
|
+
* 1. the default context-update action (caller-provided),
|
|
112
|
+
* 2. each entry from `actions[]` translated to XState form.
|
|
113
|
+
*/
|
|
114
|
+
function collectTransitionActions(t, defaultContextAction) {
|
|
115
|
+
const entries = [defaultContextAction];
|
|
116
|
+
for (const action of t.actions ?? []) {
|
|
117
|
+
entries.push(compileAction(action));
|
|
118
|
+
}
|
|
119
|
+
return entries;
|
|
120
|
+
}
|
|
121
|
+
// Adding a new variant to WorkflowTransitionAction will make
|
|
122
|
+
// `action.stateIds` a compile error, forcing a switch here.
|
|
123
|
+
function compileAction(action) {
|
|
124
|
+
return { type: 'resetVisitCounts', params: { stateIds: action.stateIds } };
|
|
125
|
+
}
|
|
126
|
+
// Shared onDone-transition builder for agent and deterministic states: both map a
|
|
127
|
+
// `when:` clause to the __matchesWhen guard, else a bare `guard:`, and run a
|
|
128
|
+
// per-state-type context-update action. Only the update action differs.
|
|
129
|
+
function buildOnDoneTransitions(transitions, updateAction, mapTarget = (transition) => transition.to) {
|
|
130
|
+
return transitions.map((t) => {
|
|
131
|
+
let guard;
|
|
132
|
+
if (t.when) {
|
|
133
|
+
guard = { type: '__matchesWhen', params: { when: t.when } };
|
|
134
|
+
}
|
|
135
|
+
else if (t.guard) {
|
|
136
|
+
guard = t.guard;
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
target: mapTarget(t),
|
|
140
|
+
...(guard ? { guard } : {}),
|
|
141
|
+
actions: collectTransitionActions(t, updateAction),
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function buildAgentState(stateId, config, definition, options = {}) {
|
|
146
|
+
return {
|
|
147
|
+
entry: [{ type: 'incrementVisitCount', params: { stateId } }],
|
|
148
|
+
invoke: {
|
|
149
|
+
id: stateId,
|
|
150
|
+
src: 'agentService',
|
|
151
|
+
input: ({ context }) => ({
|
|
152
|
+
stateId,
|
|
153
|
+
stateConfig: config,
|
|
154
|
+
context,
|
|
155
|
+
}),
|
|
156
|
+
onDone: buildOnDoneTransitions(config.transitions, 'updateContextFromAgentResult', options.mapTransitionTarget),
|
|
157
|
+
onError: {
|
|
158
|
+
target: options.onErrorTarget ?? findErrorTarget(config, definition),
|
|
159
|
+
actions: ['storeError', 'updateContextFromAgentInvocationError'],
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function buildDeterministicState(stateId, config, definition, options = {}) {
|
|
165
|
+
const onDoneTransitions = buildOnDoneTransitions(config.transitions, 'updateContextFromDeterministicResult', options.mapTransitionTarget);
|
|
166
|
+
return {
|
|
167
|
+
invoke: {
|
|
168
|
+
id: stateId,
|
|
169
|
+
src: 'deterministicService',
|
|
170
|
+
input: ({ context }) => ({
|
|
171
|
+
stateId,
|
|
172
|
+
commands: config.run.map((command) => templateLaneCommand(command, context)),
|
|
173
|
+
context,
|
|
174
|
+
container: config.container ?? false,
|
|
175
|
+
containerScope: config.containerScope,
|
|
176
|
+
timeoutMs: config.timeoutMs,
|
|
177
|
+
resultFile: config.resultFile ? laneScopeEvolveCurrentPath(config.resultFile, context) : undefined,
|
|
178
|
+
}),
|
|
179
|
+
onDone: onDoneTransitions,
|
|
180
|
+
onError: {
|
|
181
|
+
target: options.onErrorTarget ?? findErrorTarget(config, definition),
|
|
182
|
+
actions: ['storeError'],
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Builds the parent `workers` state: a single XState invoke of `fanOutService`
|
|
189
|
+
* (the orchestrator's `runFanOutSegment`). From the parent FSM's vantage the
|
|
190
|
+
* whole batch is ONE invoke — the N child round actors live inside the invoke
|
|
191
|
+
* body, not in the parent's state value, so the parent's `snapshot.value` stays
|
|
192
|
+
* the string `"workers"` (single-active-state spine, §6.4). `onDone` runs
|
|
193
|
+
* `updateContextFromFanOutResult` (promote the joined context) then follows the
|
|
194
|
+
* verdict-matched edge; `onError` routes to the definition's error target.
|
|
195
|
+
*/
|
|
196
|
+
function buildFanOutState(stateId, config, definition) {
|
|
197
|
+
return {
|
|
198
|
+
invoke: {
|
|
199
|
+
id: stateId,
|
|
200
|
+
src: 'fanOutService',
|
|
201
|
+
input: ({ context }) => ({
|
|
202
|
+
stateId,
|
|
203
|
+
stateConfig: config,
|
|
204
|
+
context,
|
|
205
|
+
}),
|
|
206
|
+
onDone: buildOnDoneTransitions(config.transitions, 'updateContextFromFanOutResult'),
|
|
207
|
+
onError: {
|
|
208
|
+
target: findErrorTarget(config, definition),
|
|
209
|
+
actions: ['storeError'],
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function buildHumanGateState(_stateId, config) {
|
|
215
|
+
const on = {};
|
|
216
|
+
for (const t of config.transitions) {
|
|
217
|
+
const eventName = `HUMAN_${t.event}`;
|
|
218
|
+
// Order: the hardcoded gate actions (storeHumanPrompt, clearError) run
|
|
219
|
+
// first so they set up context (prompt, error state) before any
|
|
220
|
+
// user-declared actions observe or modify it. User-declared actions
|
|
221
|
+
// (e.g., resetVisitCounts) run afterward.
|
|
222
|
+
const actions = ['storeHumanPrompt', 'clearError'];
|
|
223
|
+
for (const action of t.actions ?? []) {
|
|
224
|
+
actions.push(compileAction(action));
|
|
225
|
+
}
|
|
226
|
+
on[eventName] = {
|
|
227
|
+
target: t.to,
|
|
228
|
+
actions,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
return { on };
|
|
232
|
+
}
|
|
233
|
+
/** The three synthetic terminal state names every child round machine carries. */
|
|
234
|
+
const ROUND_CHILD_RECORDED = 'recorded';
|
|
235
|
+
const ROUND_CHILD_BLOCKED = 'blocked';
|
|
236
|
+
const ROUND_CHILD_ERRORED = 'errored';
|
|
237
|
+
/**
|
|
238
|
+
* Factors a fan-out segment (the round sub-chain
|
|
239
|
+
* `sample -> researcher -> evaluate -> analysis_record`) into a standalone
|
|
240
|
+
* child machine definition. Each member is copied verbatim except for two
|
|
241
|
+
* rewrites: its out-of-segment transition targets are remapped to one of
|
|
242
|
+
* three synthetic terminals via {@link mapRoundChildTarget}, and the
|
|
243
|
+
* `fanOut`/`segment` markers are stripped so the recursive
|
|
244
|
+
* `buildWorkflowMachine` does not try to re-factor the member into yet
|
|
245
|
+
* another child.
|
|
246
|
+
*
|
|
247
|
+
* The three synthetic terminals (`recorded`, `blocked`, `errored`) are the
|
|
248
|
+
* lane verdict surface — every lane finishes in exactly one, and the parent
|
|
249
|
+
* barrier reads it to decide the batch verdict (§6.1). `initial: segment[0]`
|
|
250
|
+
* starts the child at the first segment member. `settings` are inherited from
|
|
251
|
+
* the parent so the child's per-lane `maxVisits` guard fires natively from the
|
|
252
|
+
* member's own declared limits (§6.1).
|
|
253
|
+
*/
|
|
254
|
+
function buildRoundChildDefinition(definition, fanOutStateId, segment) {
|
|
255
|
+
const segmentSet = new Set(segment);
|
|
256
|
+
const states = {};
|
|
257
|
+
for (const memberId of segment) {
|
|
258
|
+
const member = definition.states[memberId];
|
|
259
|
+
if (member.type !== 'agent' && member.type !== 'deterministic') {
|
|
260
|
+
throw new Error(`fan-out state "${fanOutStateId}" segment member "${memberId}" is not executable`);
|
|
261
|
+
}
|
|
262
|
+
const transitions = member.transitions.map((transition) => ({
|
|
263
|
+
...transition,
|
|
264
|
+
to: mapRoundChildTarget(definition, transition, segmentSet),
|
|
265
|
+
}));
|
|
266
|
+
// The agent and deterministic arms produce byte-identical state objects
|
|
267
|
+
// (strip the fan-out markers, override transitions); the only difference
|
|
268
|
+
// is the discriminated-union narrowing of `member`, so one block covers
|
|
269
|
+
// both once the `type` guard above has run. `_fanOut`/`_segment` are
|
|
270
|
+
// destructured only to omit them from `rest`; `void` marks them used.
|
|
271
|
+
const { fanOut: _fanOut, segment: _segment, ...rest } = member;
|
|
272
|
+
void _fanOut;
|
|
273
|
+
void _segment;
|
|
274
|
+
states[memberId] = { ...rest, transitions };
|
|
275
|
+
}
|
|
276
|
+
states[ROUND_CHILD_RECORDED] = {
|
|
277
|
+
type: 'terminal',
|
|
278
|
+
description: `Fan-out segment "${fanOutStateId}" recorded successfully.`,
|
|
279
|
+
};
|
|
280
|
+
states[ROUND_CHILD_BLOCKED] = {
|
|
281
|
+
type: 'terminal',
|
|
282
|
+
description: `Fan-out segment "${fanOutStateId}" needs human review.`,
|
|
283
|
+
};
|
|
284
|
+
states[ROUND_CHILD_ERRORED] = {
|
|
285
|
+
type: 'terminal',
|
|
286
|
+
description: `Fan-out segment "${fanOutStateId}" failed.`,
|
|
287
|
+
};
|
|
288
|
+
return {
|
|
289
|
+
name: `${definition.name}-${fanOutStateId}-round`,
|
|
290
|
+
description: `Child round machine for ${definition.name}.${fanOutStateId}`,
|
|
291
|
+
initial: segment[0],
|
|
292
|
+
settings: definition.settings,
|
|
293
|
+
states,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Maps a segment member's transition target onto a child round-machine
|
|
298
|
+
* target. In-segment edges pass through unchanged; everything that would
|
|
299
|
+
* leave the segment is collapsed onto one of the three synthetic terminals.
|
|
300
|
+
*
|
|
301
|
+
* The mapping table:
|
|
302
|
+
* - target is another segment member -> passthrough (the target name)
|
|
303
|
+
* - `when.verdict === 'recorded'` -> `recorded` (round committed a node)
|
|
304
|
+
* - `when.verdict === 'evaluator_blocked'` -> `blocked` (needs human review)
|
|
305
|
+
* - any other named verdict -> `errored` (unexpected verdict)
|
|
306
|
+
* - target is a human_gate state -> `blocked` (escalation edge)
|
|
307
|
+
* - else (bare fallthrough / failed) -> `errored`
|
|
308
|
+
*/
|
|
309
|
+
function mapRoundChildTarget(definition, transition, segment) {
|
|
310
|
+
if (segment.has(transition.to))
|
|
311
|
+
return transition.to;
|
|
312
|
+
const verdict = transition.when?.verdict;
|
|
313
|
+
if (verdict === 'recorded')
|
|
314
|
+
return ROUND_CHILD_RECORDED;
|
|
315
|
+
if (verdict === 'evaluator_blocked')
|
|
316
|
+
return ROUND_CHILD_BLOCKED;
|
|
317
|
+
if (typeof verdict === 'string')
|
|
318
|
+
return ROUND_CHILD_ERRORED;
|
|
319
|
+
const targetState = definition.states[transition.to];
|
|
320
|
+
if (targetState.type === 'human_gate')
|
|
321
|
+
return ROUND_CHILD_BLOCKED;
|
|
322
|
+
return ROUND_CHILD_ERRORED;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Builds an XState v5 machine from a validated WorkflowDefinition.
|
|
326
|
+
*
|
|
327
|
+
* The returned machine has placeholder actors (`agentService`,
|
|
328
|
+
* `deterministicService`) that throw if invoked directly. Callers
|
|
329
|
+
* must call `.provide({ actors: { ... } })` to inject real
|
|
330
|
+
* implementations before passing to `createActor()`.
|
|
331
|
+
*
|
|
332
|
+
* Guards are registered with concrete implementations from the guards
|
|
333
|
+
* module. Actions for context updates are defined inline via `assign`.
|
|
334
|
+
*/
|
|
335
|
+
export function buildWorkflowMachine(definition, taskDescription, options = {}) {
|
|
336
|
+
const states = {};
|
|
337
|
+
const roundMachinesByState = new Map();
|
|
338
|
+
const gateStateNames = new Set();
|
|
339
|
+
const terminalStateNames = new Set();
|
|
340
|
+
// Per-state maxVisits map, built at machine-construction time and
|
|
341
|
+
// closed over by the `isStateVisitLimitReached` guard below. Only
|
|
342
|
+
// agent states can declare `maxVisits`; states without it are absent
|
|
343
|
+
// from the map and the guard returns false for them.
|
|
344
|
+
const maxVisitsByState = new Map();
|
|
345
|
+
// For child round machines, every executable member's error path is forced
|
|
346
|
+
// to the synthetic `errored` terminal (see `onErrorTarget` doc above); the
|
|
347
|
+
// parent machine leaves it undefined and falls back to `findErrorTarget`.
|
|
348
|
+
const executableOptions = { onErrorTarget: options.onErrorTarget };
|
|
349
|
+
for (const [stateId, stateDef] of Object.entries(definition.states)) {
|
|
350
|
+
switch (stateDef.type) {
|
|
351
|
+
case 'agent':
|
|
352
|
+
states[stateId] =
|
|
353
|
+
stateDef.fanOut !== undefined
|
|
354
|
+
? buildFanOutState(stateId, stateDef, definition)
|
|
355
|
+
: buildAgentState(stateId, stateDef, definition, executableOptions);
|
|
356
|
+
if (typeof stateDef.maxVisits === 'number') {
|
|
357
|
+
maxVisitsByState.set(stateId, stateDef.maxVisits);
|
|
358
|
+
}
|
|
359
|
+
break;
|
|
360
|
+
case 'deterministic':
|
|
361
|
+
states[stateId] =
|
|
362
|
+
stateDef.fanOut !== undefined
|
|
363
|
+
? buildFanOutState(stateId, stateDef, definition)
|
|
364
|
+
: buildDeterministicState(stateId, stateDef, definition, executableOptions);
|
|
365
|
+
break;
|
|
366
|
+
case 'human_gate':
|
|
367
|
+
states[stateId] = buildHumanGateState(stateId, stateDef);
|
|
368
|
+
gateStateNames.add(stateId);
|
|
369
|
+
break;
|
|
370
|
+
case 'terminal':
|
|
371
|
+
states[stateId] = { type: 'final' };
|
|
372
|
+
terminalStateNames.add(stateId);
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if (options.buildRoundMachines !== false) {
|
|
377
|
+
for (const [stateId, stateDef] of Object.entries(definition.states)) {
|
|
378
|
+
if ((stateDef.type !== 'agent' && stateDef.type !== 'deterministic') || stateDef.fanOut === undefined) {
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
const segment = stateDef.segment ?? [];
|
|
382
|
+
if (segment.length === 0)
|
|
383
|
+
continue;
|
|
384
|
+
const childDefinition = buildRoundChildDefinition(definition, stateId, segment);
|
|
385
|
+
const child = buildWorkflowMachine(childDefinition, taskDescription, {
|
|
386
|
+
contextFromInput: true,
|
|
387
|
+
buildRoundMachines: false,
|
|
388
|
+
// A segment member's service rejection must land in the child's
|
|
389
|
+
// `errored` terminal, not fall through `findErrorTarget` to the
|
|
390
|
+
// first terminal (`recorded`). See `onErrorTarget` above.
|
|
391
|
+
onErrorTarget: ROUND_CHILD_ERRORED,
|
|
392
|
+
});
|
|
393
|
+
roundMachinesByState.set(stateId, child.machine);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
// Build XState guard implementations compatible with XState's guard API.
|
|
397
|
+
// XState v5 guards receive ({ context, event }) but the event type
|
|
398
|
+
// during onDone is the xstate done event, not our WorkflowEvent.
|
|
399
|
+
// We need to adapt our guards to work with the done event's output.
|
|
400
|
+
// The second `params` argument is used by parameterized guards like __matchesWhen.
|
|
401
|
+
const xstateGuards = {};
|
|
402
|
+
for (const [name, guardFn] of Object.entries(guardImplementations)) {
|
|
403
|
+
xstateGuards[name] = ({ context, event }) => {
|
|
404
|
+
// For xstate.done.actor.* events, extract the output and create
|
|
405
|
+
// a synthetic WorkflowEvent for the guard
|
|
406
|
+
const doneEvent = event;
|
|
407
|
+
let workflowEvent;
|
|
408
|
+
if (doneEvent.type.startsWith('xstate.done.actor.')) {
|
|
409
|
+
const result = extractInvokeResult(doneEvent);
|
|
410
|
+
if (result) {
|
|
411
|
+
// Special case: isStalled needs access to outputHash and stateId
|
|
412
|
+
// which are not part of AgentOutput/WorkflowEvent.
|
|
413
|
+
if (name === 'isStalled') {
|
|
414
|
+
const stateId = doneEvent.type.replace('xstate.done.actor.', '');
|
|
415
|
+
const prevHash = context.previousOutputHashes[stateId];
|
|
416
|
+
return !!prevHash && result.outputHash === prevHash;
|
|
417
|
+
}
|
|
418
|
+
// Special case: isStateVisitLimitReached consults the per-state
|
|
419
|
+
// maxVisits map (closed over from the definition) and compares it
|
|
420
|
+
// to the visit count for the state that just completed.
|
|
421
|
+
if (name === 'isStateVisitLimitReached') {
|
|
422
|
+
const stateId = doneEvent.type.replace('xstate.done.actor.', '');
|
|
423
|
+
const cap = maxVisitsByState.get(stateId);
|
|
424
|
+
if (cap === undefined)
|
|
425
|
+
return false;
|
|
426
|
+
const visits = context.visitCounts[stateId] ?? 0;
|
|
427
|
+
return visits >= cap;
|
|
428
|
+
}
|
|
429
|
+
// Agent service result -> AGENT_COMPLETED event
|
|
430
|
+
workflowEvent = { type: 'AGENT_COMPLETED', output: result.output };
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
// Deterministic service result -> map to VALIDATION_PASSED/FAILED
|
|
434
|
+
const detResult = doneEvent.output;
|
|
435
|
+
if (detResult?.passed) {
|
|
436
|
+
workflowEvent = { type: 'VALIDATION_PASSED', testCount: detResult.testCount ?? 0 };
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
workflowEvent = { type: 'VALIDATION_FAILED', errors: detResult?.errors ?? 'unknown' };
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
// For human gate events, pass through directly
|
|
445
|
+
workflowEvent = event;
|
|
446
|
+
}
|
|
447
|
+
return guardFn({ context, event: workflowEvent });
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
// Register the __matchesWhen parameterized guard. This intentionally
|
|
451
|
+
// bypasses the guard adapter loop above because it operates on AgentOutput
|
|
452
|
+
// directly (via extractInvokeResult inline) rather than on WorkflowEvent.
|
|
453
|
+
xstateGuards['__matchesWhen'] = ({ event }, params) => {
|
|
454
|
+
const doneEvent = event;
|
|
455
|
+
let matchSource;
|
|
456
|
+
if (doneEvent.type.startsWith('xstate.done.actor.')) {
|
|
457
|
+
const result = extractInvokeResult(doneEvent);
|
|
458
|
+
if (result) {
|
|
459
|
+
matchSource = result.output;
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
const detResult = doneEvent.output;
|
|
463
|
+
if (typeof detResult?.verdict === 'string') {
|
|
464
|
+
matchSource = { verdict: detResult.verdict };
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if (!matchSource)
|
|
469
|
+
return false;
|
|
470
|
+
// Defensive: fail closed if params are missing or when is empty/missing.
|
|
471
|
+
// Validation prevents these cases, but we don't want a silent unconditional
|
|
472
|
+
// match if validation is bypassed.
|
|
473
|
+
if (!params || typeof params !== 'object')
|
|
474
|
+
return false;
|
|
475
|
+
const whenMap = params.when;
|
|
476
|
+
if (!whenMap || typeof whenMap !== 'object' || Object.keys(whenMap).length === 0) {
|
|
477
|
+
return false;
|
|
478
|
+
}
|
|
479
|
+
const when = whenMap;
|
|
480
|
+
for (const [key, expected] of Object.entries(when)) {
|
|
481
|
+
const actual = matchSource[key];
|
|
482
|
+
if (actual !== expected)
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
return true;
|
|
486
|
+
};
|
|
487
|
+
const machine = setup({
|
|
488
|
+
types: {
|
|
489
|
+
context: {},
|
|
490
|
+
events: {},
|
|
491
|
+
input: {},
|
|
492
|
+
},
|
|
493
|
+
actors: {
|
|
494
|
+
agentService: fromPromise(() => {
|
|
495
|
+
return Promise.reject(new Error('agentService must be provided via machine.provide()'));
|
|
496
|
+
}),
|
|
497
|
+
deterministicService: fromPromise(() => {
|
|
498
|
+
return Promise.reject(new Error('deterministicService must be provided via machine.provide()'));
|
|
499
|
+
}),
|
|
500
|
+
fanOutService: fromPromise(() => {
|
|
501
|
+
return Promise.reject(new Error('fanOutService must be provided via machine.provide()'));
|
|
502
|
+
}),
|
|
503
|
+
},
|
|
504
|
+
guards: xstateGuards,
|
|
505
|
+
actions: {
|
|
506
|
+
updateContextFromAgentResult: assign(({ context, event }) => {
|
|
507
|
+
const doneEvent = event;
|
|
508
|
+
const result = extractInvokeResult(doneEvent);
|
|
509
|
+
if (!result)
|
|
510
|
+
return {};
|
|
511
|
+
const output = result.output;
|
|
512
|
+
// Derive stateId from the event type: xstate.done.actor.<stateId>
|
|
513
|
+
const stateId = event.type.replace('xstate.done.actor.', '');
|
|
514
|
+
return {
|
|
515
|
+
artifacts: { ...context.artifacts, ...result.artifacts },
|
|
516
|
+
previousOutputHashes: {
|
|
517
|
+
...context.previousOutputHashes,
|
|
518
|
+
[stateId]: result.outputHash,
|
|
519
|
+
},
|
|
520
|
+
round: context.round + 1,
|
|
521
|
+
reviewHistory: output.verdict === 'rejected' ? [...context.reviewHistory, output.notes ?? ''] : context.reviewHistory,
|
|
522
|
+
agentConversationsByState: {
|
|
523
|
+
...context.agentConversationsByState,
|
|
524
|
+
[stateId]: result.agentConversationId,
|
|
525
|
+
},
|
|
526
|
+
// Sourced from `instance.outputTokens` in the orchestrator,
|
|
527
|
+
// which subscribes to the token-stream bus and accumulates
|
|
528
|
+
// `message_end.outputTokens` across every session this workflow
|
|
529
|
+
// has spawned. The orchestrator always supplies a numeric
|
|
530
|
+
// cumulative value — the field is required on AgentInvokeResult.
|
|
531
|
+
totalTokens: result.totalTokens,
|
|
532
|
+
previousAgentOutput: truncateAgentOutput(stripStatusBlock(result.responseText)),
|
|
533
|
+
previousAgentNotes: output.notes ? truncateAgentOutput(output.notes) : null,
|
|
534
|
+
previousStateName: stateId,
|
|
535
|
+
humanPrompt: null,
|
|
536
|
+
};
|
|
537
|
+
}),
|
|
538
|
+
updateContextFromDeterministicResult: assign(({ context, event }) => {
|
|
539
|
+
const doneEvent = event;
|
|
540
|
+
const result = doneEvent.output;
|
|
541
|
+
if (!result)
|
|
542
|
+
return {};
|
|
543
|
+
// Only attach lastDeterministicResult when the state actually produced a
|
|
544
|
+
// verdict/payload (a result-file state). Guard-only deterministic states
|
|
545
|
+
// leave context byte-identical to the legacy path (the field stays absent).
|
|
546
|
+
const verdictUpdate = result.verdict !== undefined || result.payload !== undefined
|
|
547
|
+
? {
|
|
548
|
+
lastDeterministicResult: {
|
|
549
|
+
...(result.verdict !== undefined ? { verdict: result.verdict } : {}),
|
|
550
|
+
...(result.payload !== undefined ? { payload: result.payload } : {}),
|
|
551
|
+
},
|
|
552
|
+
}
|
|
553
|
+
: {};
|
|
554
|
+
const baseUpdate = {
|
|
555
|
+
previousTestCount: result.testCount ?? context.previousTestCount,
|
|
556
|
+
...verdictUpdate,
|
|
557
|
+
};
|
|
558
|
+
if (result.passed)
|
|
559
|
+
return baseUpdate;
|
|
560
|
+
// Set previousStateName to the deterministic state's id (not the prior agent)
|
|
561
|
+
// so prompt-builder's cross-state framing (buildScopingSection) renders the
|
|
562
|
+
// failure as "Output from <det-state>" for the next agent.
|
|
563
|
+
const stateId = event.type.replace('xstate.done.actor.', '');
|
|
564
|
+
return {
|
|
565
|
+
...baseUpdate,
|
|
566
|
+
previousAgentOutput: truncateAgentOutput(result.errors ?? ''),
|
|
567
|
+
previousAgentNotes: null,
|
|
568
|
+
previousStateName: stateId,
|
|
569
|
+
};
|
|
570
|
+
}),
|
|
571
|
+
// Promotes the batch's joined context onto the parent FSM after a
|
|
572
|
+
// fan-out invoke resolves (the parent was frozen at `workers` for the
|
|
573
|
+
// whole batch — see runFanOutSegment). The result already carries the
|
|
574
|
+
// chosen lane's full WorkflowContext, so this replaces context wholesale.
|
|
575
|
+
// `if (!result) return {}` keeps the existing context unchanged when the
|
|
576
|
+
// invoke produced no output — never blanks the parent context on a
|
|
577
|
+
// malformed/empty result.
|
|
578
|
+
updateContextFromFanOutResult: assign(({ event }) => {
|
|
579
|
+
const doneEvent = event;
|
|
580
|
+
const result = doneEvent.output;
|
|
581
|
+
if (!result)
|
|
582
|
+
return {};
|
|
583
|
+
return result.context;
|
|
584
|
+
}),
|
|
585
|
+
storeHumanPrompt: assign(({ event }) => ({
|
|
586
|
+
humanPrompt: event.prompt ?? null,
|
|
587
|
+
})),
|
|
588
|
+
clearError: assign(() => ({
|
|
589
|
+
lastError: null,
|
|
590
|
+
})),
|
|
591
|
+
storeError: assign(({ event }) => {
|
|
592
|
+
const errorEvent = event;
|
|
593
|
+
const err = errorEvent.error;
|
|
594
|
+
let message;
|
|
595
|
+
if (err instanceof Error) {
|
|
596
|
+
message = err.message;
|
|
597
|
+
}
|
|
598
|
+
else if (typeof err === 'object' && err !== null && 'message' in err) {
|
|
599
|
+
message = String(err.message);
|
|
600
|
+
}
|
|
601
|
+
else if (typeof err === 'string') {
|
|
602
|
+
message = err;
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
606
|
+
message = err != null ? String(err) : 'Unknown error';
|
|
607
|
+
}
|
|
608
|
+
// Write directly to stderr to bypass any console hijacking
|
|
609
|
+
// (logger.setup() redirects console.error to a log file).
|
|
610
|
+
process.stderr.write(`[workflow] storeError action: ${message}\n`);
|
|
611
|
+
return { lastError: message };
|
|
612
|
+
}),
|
|
613
|
+
/**
|
|
614
|
+
* Mirrors `updateContextFromAgentResult` for the error path: when
|
|
615
|
+
* the agent service rejects, recover the `agentConversationId` that
|
|
616
|
+
* was minted for the invocation (wrapped in `AgentInvocationError`)
|
|
617
|
+
* and persist it into `context.agentConversationsByState[stateId]`.
|
|
618
|
+
*
|
|
619
|
+
* Without this, `onError` drops the conversation id on the floor —
|
|
620
|
+
* `onDone` stamps the id into context, but `onError` used to record
|
|
621
|
+
* only `lastError`, which silently broke `freshSession: false`
|
|
622
|
+
* resume on the next visit to an errored state.
|
|
623
|
+
*/
|
|
624
|
+
updateContextFromAgentInvocationError: assign(({ context, event }) => {
|
|
625
|
+
const errorEvent = event;
|
|
626
|
+
const err = errorEvent.error;
|
|
627
|
+
if (!isAgentInvocationError(err))
|
|
628
|
+
return {};
|
|
629
|
+
return {
|
|
630
|
+
agentConversationsByState: {
|
|
631
|
+
...context.agentConversationsByState,
|
|
632
|
+
[err.stateId]: err.agentConversationId,
|
|
633
|
+
},
|
|
634
|
+
};
|
|
635
|
+
}),
|
|
636
|
+
incrementVisitCount: assign(({ context }, params) => ({
|
|
637
|
+
visitCounts: {
|
|
638
|
+
...context.visitCounts,
|
|
639
|
+
[params.stateId]: (context.visitCounts[params.stateId] ?? 0) + 1,
|
|
640
|
+
},
|
|
641
|
+
})),
|
|
642
|
+
resetVisitCounts: assign(({ context }, params) => {
|
|
643
|
+
// Clear only the named keys; leave all other visit counts intact.
|
|
644
|
+
// Used on transitions that re-enter a bounded loop (e.g., when the
|
|
645
|
+
// orchestrator sends a fresh hypothesis) to reset the cap without
|
|
646
|
+
// losing counts for unrelated states.
|
|
647
|
+
const next = { ...context.visitCounts };
|
|
648
|
+
for (const stateId of params.stateIds) {
|
|
649
|
+
next[stateId] = 0;
|
|
650
|
+
}
|
|
651
|
+
return { visitCounts: next };
|
|
652
|
+
}),
|
|
653
|
+
},
|
|
654
|
+
}).createMachine({
|
|
655
|
+
id: definition.name,
|
|
656
|
+
initial: definition.initial,
|
|
657
|
+
context: ({ input }) => {
|
|
658
|
+
if (options.contextFromInput) {
|
|
659
|
+
if (!input?.context) {
|
|
660
|
+
throw new Error(`machine "${definition.name}" requires input.context`);
|
|
661
|
+
}
|
|
662
|
+
return input.context;
|
|
663
|
+
}
|
|
664
|
+
return {
|
|
665
|
+
...createInitialContext(definition),
|
|
666
|
+
taskDescription,
|
|
667
|
+
};
|
|
668
|
+
},
|
|
669
|
+
states,
|
|
670
|
+
});
|
|
671
|
+
return {
|
|
672
|
+
machine,
|
|
673
|
+
roundMachinesByState,
|
|
674
|
+
gateStateNames,
|
|
675
|
+
terminalStateNames,
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
//# sourceMappingURL=machine-builder.js.map
|