@provos/ironcurtain 0.9.1 → 0.11.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 +69 -10
- package/dist/auth/oauth-provider.js +1 -4
- package/dist/auth/oauth-provider.js.map +1 -1
- package/dist/cli.js +40 -2
- package/dist/cli.js.map +1 -1
- package/dist/config/config-command.js +174 -10
- package/dist/config/config-command.js.map +1 -1
- package/dist/config/first-start.js +61 -0
- 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 +8 -2
- package/dist/config/model-provider.js +52 -9
- package/dist/config/model-provider.js.map +1 -1
- package/dist/config/paths.d.ts +181 -0
- package/dist/config/paths.js +326 -23
- package/dist/config/paths.js.map +1 -1
- package/dist/config/types.d.ts +7 -1
- package/dist/config/user-config.d.ts +61 -4
- package/dist/config/user-config.js +108 -21
- 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/compile-task-policy.js +1 -0
- package/dist/cron/compile-task-policy.js.map +1 -1
- 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 +16 -2
- package/dist/daemon/daemon-command.js.map +1 -1
- package/dist/daemon/ironcurtain-daemon.d.ts +44 -1
- package/dist/daemon/ironcurtain-daemon.js +210 -8
- package/dist/daemon/ironcurtain-daemon.js.map +1 -1
- package/dist/docker/adapters/claude-code.d.ts +2 -1
- package/dist/docker/adapters/claude-code.js +320 -131
- package/dist/docker/adapters/claude-code.js.map +1 -1
- 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 +178 -4
- package/dist/docker/agent-adapter.js +14 -0
- package/dist/docker/agent-adapter.js.map +1 -1
- package/dist/docker/agent-registry.js +3 -2
- package/dist/docker/agent-registry.js.map +1 -1
- package/dist/docker/code-mode-proxy.d.ts +27 -0
- package/dist/docker/code-mode-proxy.js +3 -0
- package/dist/docker/code-mode-proxy.js.map +1 -1
- package/dist/docker/container-lifecycle.d.ts +15 -0
- package/dist/docker/container-lifecycle.js +32 -0
- package/dist/docker/container-lifecycle.js.map +1 -0
- package/dist/docker/docker-agent-session.d.ts +113 -62
- package/dist/docker/docker-agent-session.js +241 -300
- package/dist/docker/docker-agent-session.js.map +1 -1
- package/dist/docker/docker-infrastructure.d.ts +256 -21
- package/dist/docker/docker-infrastructure.js +585 -30
- package/dist/docker/docker-infrastructure.js.map +1 -1
- package/dist/docker/docker-manager.d.ts +36 -1
- package/dist/docker/docker-manager.js +168 -26
- package/dist/docker/docker-manager.js.map +1 -1
- 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 +90 -1
- package/dist/docker/mitm-proxy.js +720 -40
- package/dist/docker/mitm-proxy.js.map +1 -1
- package/dist/docker/oauth-credentials.d.ts +46 -3
- package/dist/docker/oauth-credentials.js +56 -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/provider-config.d.ts +81 -2
- package/dist/docker/provider-config.js +222 -28
- package/dist/docker/provider-config.js.map +1 -1
- 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 +49 -1
- package/dist/docker/pty-session.js +212 -90
- 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/resource-limits.d.ts +125 -0
- package/dist/docker/resource-limits.js +200 -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/types.d.ts +61 -6
- package/dist/doctor/checks.d.ts +138 -0
- package/dist/doctor/checks.js +511 -0
- package/dist/doctor/checks.js.map +1 -0
- package/dist/doctor/doctor-command.d.ts +29 -0
- package/dist/doctor/doctor-command.js +160 -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 +84 -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 +32 -9
- 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 +30 -34
- package/dist/mux/mux-app.js.map +1 -1
- package/dist/mux/mux-command.d.ts +10 -1
- package/dist/mux/mux-command.js +62 -35
- package/dist/mux/mux-command.js.map +1 -1
- package/dist/mux/mux-renderer.js +22 -17
- 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.d.ts +7 -0
- package/dist/mux/session-scanner.js +21 -2
- package/dist/mux/session-scanner.js.map +1 -1
- package/dist/mux/types.d.ts +0 -4
- package/dist/mux/types.js.map +1 -1
- package/dist/{pipeline → observability}/llm-logger.d.ts +9 -3
- package/dist/{pipeline → observability}/llm-logger.js +16 -4
- package/dist/observability/llm-logger.js.map +1 -0
- package/dist/observe/observe-command.d.ts +12 -0
- package/dist/observe/observe-command.js +298 -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/compile-persona-policy.js +1 -0
- package/dist/persona/compile-persona-policy.js.map +1 -1
- 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 +41 -6
- package/dist/persona/persona-command.js.map +1 -1
- 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/types.d.ts +16 -0
- package/dist/pipeline/annotate.d.ts +7 -1
- package/dist/pipeline/annotate.js +92 -2
- package/dist/pipeline/annotate.js.map +1 -1
- package/dist/pipeline/compile.js +2 -0
- 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/parallel-progress.d.ts +59 -0
- package/dist/pipeline/parallel-progress.js +263 -0
- package/dist/pipeline/parallel-progress.js.map +1 -0
- package/dist/pipeline/pipeline-runner.d.ts +49 -8
- package/dist/pipeline/pipeline-runner.js +419 -231
- package/dist/pipeline/pipeline-runner.js.map +1 -1
- package/dist/pipeline/pipeline-shared.d.ts +59 -1
- package/dist/pipeline/pipeline-shared.js +127 -12
- 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/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/pipeline/server-prefilter.d.ts +31 -0
- package/dist/pipeline/server-prefilter.js +115 -0
- package/dist/pipeline/server-prefilter.js.map +1 -0
- package/dist/pipeline/types.d.ts +5 -0
- package/dist/sandbox/index.d.ts +14 -0
- package/dist/sandbox/index.js +335 -116
- 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 +324 -130
- package/dist/session/index.js.map +1 -1
- package/dist/session/preflight.d.ts +50 -13
- package/dist/session/preflight.js +252 -80
- 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 +311 -5
- package/dist/session/types.js +57 -1
- package/dist/session/types.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.js +7 -1
- 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.js +2 -1
- package/dist/trusted-process/call-circuit-breaker.js.map +1 -1
- 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 +166 -657
- 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 +90 -45
- 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 +26 -0
- package/dist/trusted-process/sandbox-integration.js.map +1 -1
- package/dist/trusted-process/tool-call-coordinator.d.ts +269 -0
- package/dist/trusted-process/tool-call-coordinator.js +508 -0
- package/dist/trusted-process/tool-call-coordinator.js.map +1 -0
- package/dist/trusted-process/tool-call-pipeline.d.ts +205 -0
- package/dist/trusted-process/tool-call-pipeline.js +798 -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/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/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 +6 -0
- package/dist/web-ui/dispatch/persona-dispatch.js +116 -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 +201 -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 +31 -0
- package/dist/web-ui/dispatch/types.js +68 -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 +925 -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 +152 -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 +76 -0
- package/dist/web-ui/web-ui-server.js +461 -0
- package/dist/web-ui/web-ui-server.js.map +1 -0
- package/dist/web-ui/web-ui-types.d.ts +290 -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-BFO5z1js.js +76 -0
- package/dist/web-ui-static/assets/index-CCUwrkIL.css +1 -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-support.d.ts +92 -0
- package/dist/workflow/cli-support.js +423 -0
- package/dist/workflow/cli-support.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 +78 -0
- package/dist/workflow/discovery.js +203 -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/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 +66 -0
- package/dist/workflow/lint.js +410 -0
- package/dist/workflow/lint.js.map +1 -0
- package/dist/workflow/machine-builder.d.ts +90 -0
- package/dist/workflow/machine-builder.js +485 -0
- package/dist/workflow/machine-builder.js.map +1 -0
- package/dist/workflow/message-log.d.ts +85 -0
- package/dist/workflow/message-log.js +40 -0
- package/dist/workflow/message-log.js.map +1 -0
- package/dist/workflow/orchestrator.d.ts +450 -0
- package/dist/workflow/orchestrator.js +1941 -0
- package/dist/workflow/orchestrator.js.map +1 -0
- package/dist/workflow/prompt-builder.d.ts +39 -0
- package/dist/workflow/prompt-builder.js +242 -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 +259 -0
- package/dist/workflow/status-parser.js.map +1 -0
- package/dist/workflow/types.d.ts +498 -0
- package/dist/workflow/types.js +83 -0
- package/dist/workflow/types.js.map +1 -0
- package/dist/workflow/validate.d.ts +58 -0
- package/dist/workflow/validate.js +499 -0
- package/dist/workflow/validate.js.map +1 -0
- package/dist/workflow/workflow-command.d.ts +26 -0
- package/dist/workflow/workflow-command.js +648 -0
- package/dist/workflow/workflow-command.js.map +1 -0
- package/dist/workflow/workflow-discovery.d.ts +25 -0
- package/dist/workflow/workflow-discovery.js +100 -0
- package/dist/workflow/workflow-discovery.js.map +1 -0
- package/dist/workflow/workflow-manager.d.ts +122 -0
- package/dist/workflow/workflow-manager.js +308 -0
- package/dist/workflow/workflow-manager.js.map +1 -0
- package/dist/workflow/workflows/design-and-code/workflow.yaml +169 -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 +89 -0
- package/dist/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +201 -0
- package/dist/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +166 -0
- package/dist/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +185 -0
- package/dist/workflow/workflows/vuln-discovery/workflow.yaml +920 -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 +12 -1
- package/docker/Dockerfile.base.arm64 +17 -1
- package/docker/entrypoint-claude-code.sh +46 -0
- package/docker/entrypoint-goose.sh +25 -0
- package/package.json +22 -8
- 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/workflow.yaml +169 -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 +89 -0
- package/src/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +201 -0
- package/src/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +166 -0
- package/src/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +185 -0
- package/src/workflow/workflows/vuln-discovery/workflow.yaml +920 -0
- package/dist/pipeline/llm-logger.js.map +0 -1
- package/dist/session/errors.js.map +0 -1
package/dist/session/index.js
CHANGED
|
@@ -7,34 +7,24 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { existsSync, mkdirSync, writeFileSync, unlinkSync } from 'node:fs';
|
|
9
9
|
import { dirname, resolve } from 'node:path';
|
|
10
|
-
import { loadConfig } from '../config/index.js';
|
|
11
|
-
import {
|
|
10
|
+
import { loadConfig, applyAllowedDirectoryToMcpArgs, loadGeneratedPolicy, getPackageGeneratedDir, } from '../config/index.js';
|
|
11
|
+
import { extractRequiredServers } from '../trusted-process/policy-roots.js';
|
|
12
|
+
import { getSessionDir, getSessionSandboxDir, getSessionEscalationDir, getSessionAuditLogPath, getSessionLogPath, getSessionLlmLogPath, getSessionAutoApproveLlmLogPath, SESSION_LOG_FILENAME, SESSION_METADATA_FILENAME, } from '../config/paths.js';
|
|
13
|
+
import { validatePolicyDir as sharedValidatePolicyDir } from '../config/validate-policy-dir.js';
|
|
12
14
|
import * as logger from '../logger.js';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
+
import { resolvePersona, applyServerAllowlist, filterMcpServersByPolicy } from '../persona/resolve.js';
|
|
16
|
+
import { resolveSkillsForSession } from '../skills/discovery.js';
|
|
15
17
|
import { buildPersonaSystemPromptAugmentation } from '../persona/persona-prompt.js';
|
|
16
18
|
import { resolveMemoryDbPath } from '../memory/resolve-memory-path.js';
|
|
17
19
|
import { buildMemoryServerConfig, MEMORY_SERVER_NAME } from '../memory/memory-annotations.js';
|
|
18
20
|
import { buildMemorySystemPrompt, adaptMemoryToolNames } from '../memory/memory-prompt.js';
|
|
21
|
+
import { isMemoryEnabledFor } from '../memory/memory-policy.js';
|
|
22
|
+
import { createJobId } from '../cron/types.js';
|
|
23
|
+
import { loadJob } from '../cron/job-store.js';
|
|
19
24
|
import { AgentSession } from './agent-session.js';
|
|
20
|
-
import { SessionError } from '
|
|
21
|
-
import { saveSessionMetadata, loadSessionMetadata } from './session-metadata.js';
|
|
22
|
-
import {
|
|
23
|
-
import { createSessionId } from './types.js';
|
|
24
|
-
/**
|
|
25
|
-
* Creates and initializes a new session.
|
|
26
|
-
*
|
|
27
|
-
* This is the only public entry point for session creation.
|
|
28
|
-
* The concrete implementations are not exported -- callers
|
|
29
|
-
* depend on the Session interface only.
|
|
30
|
-
*
|
|
31
|
-
* When mode is 'docker', spawns an external agent in a Docker
|
|
32
|
-
* container with MCP proxy mediation. Otherwise (default), creates
|
|
33
|
-
* the built-in AgentSession using UTCP Code Mode + AI SDK.
|
|
34
|
-
*
|
|
35
|
-
* @throws {SessionError} with code SESSION_INIT_FAILED if
|
|
36
|
-
* sandbox or MCP connection setup fails.
|
|
37
|
-
*/
|
|
25
|
+
import { SessionError } from '../types/errors.js';
|
|
26
|
+
import { saveSessionMetadata, saveSessionMetadataTo, loadSessionMetadata } from './session-metadata.js';
|
|
27
|
+
import { bundleIdFromSessionId, createAgentConversationId, createSessionId } from './types.js';
|
|
38
28
|
export async function createSession(options = {}) {
|
|
39
29
|
// When resuming, restore persisted session settings (persona, workspace, etc.)
|
|
40
30
|
const effectiveOptions = applyResumeMetadata(options);
|
|
@@ -44,6 +34,39 @@ export async function createSession(options = {}) {
|
|
|
44
34
|
}
|
|
45
35
|
return createBuiltinSession(effectiveOptions);
|
|
46
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Entry point for callers outside the workflow orchestrator — CLI,
|
|
39
|
+
* daemon, signal bot, web UI. For Docker mode: resumes the persisted
|
|
40
|
+
* `AgentConversationId` when `resumeSessionId` is set (so
|
|
41
|
+
* `ironcurtain --resume <id>` continues the prior Claude conversation
|
|
42
|
+
* via `--resume <conv-id>` on the adapter), otherwise mints fresh.
|
|
43
|
+
* Builtin mode ignores the field.
|
|
44
|
+
*
|
|
45
|
+
* Legacy-session fallback: sessions created before
|
|
46
|
+
* `agentConversationId` was persisted in metadata will have no stored
|
|
47
|
+
* id. Those resumes mint fresh, and the agent CLI starts a new
|
|
48
|
+
* conversation — the prior transcript is unreachable but nothing is
|
|
49
|
+
* corrupted. New sessions created post-refactor always persist the id,
|
|
50
|
+
* so subsequent resumes recover the conversation.
|
|
51
|
+
*
|
|
52
|
+
* Workflow callers must not use this: they must thread
|
|
53
|
+
* `agentConversationId` from `context.agentConversationsByState` via
|
|
54
|
+
* `createSession()` directly so `freshSession: false` states resume
|
|
55
|
+
* the prior conversation.
|
|
56
|
+
*/
|
|
57
|
+
export async function createStandaloneSession(options) {
|
|
58
|
+
if (options.mode?.kind === 'docker') {
|
|
59
|
+
const persistedId = options.resumeSessionId
|
|
60
|
+
? loadSessionMetadata(options.resumeSessionId)?.agentConversationId
|
|
61
|
+
: undefined;
|
|
62
|
+
return createSession({
|
|
63
|
+
...options,
|
|
64
|
+
mode: options.mode,
|
|
65
|
+
agentConversationId: persistedId ?? createAgentConversationId(),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return createSession({ ...options, mode: options.mode });
|
|
69
|
+
}
|
|
47
70
|
/**
|
|
48
71
|
* Merges persisted session metadata into options when resuming.
|
|
49
72
|
* Returns options unchanged for new sessions or when no metadata exists
|
|
@@ -63,6 +86,14 @@ function applyResumeMetadata(options) {
|
|
|
63
86
|
...(metadata.workspacePath !== undefined ? { workspacePath: metadata.workspacePath } : {}),
|
|
64
87
|
...(metadata.policyDir !== undefined ? { policyDir: metadata.policyDir } : {}),
|
|
65
88
|
...(metadata.disableAutoApprove !== undefined ? { disableAutoApprove: metadata.disableAutoApprove } : {}),
|
|
89
|
+
// Caller-supplied `agentConversationId` wins over the persisted
|
|
90
|
+
// one (workflow orchestrator always passes its own explicitly).
|
|
91
|
+
// Only the CLI / daemon `createStandaloneSession` path leaves the
|
|
92
|
+
// field unset, and that's exactly the path we want to restore from
|
|
93
|
+
// metadata so `--resume` continues the prior Claude conversation.
|
|
94
|
+
...(options.agentConversationId === undefined && metadata.agentConversationId !== undefined
|
|
95
|
+
? { agentConversationId: metadata.agentConversationId }
|
|
96
|
+
: {}),
|
|
66
97
|
};
|
|
67
98
|
}
|
|
68
99
|
/**
|
|
@@ -92,7 +123,8 @@ async function createBuiltinSession(options) {
|
|
|
92
123
|
await session.initialize();
|
|
93
124
|
}
|
|
94
125
|
catch (error) {
|
|
95
|
-
// Clean up on init failure
|
|
126
|
+
// Clean up on init failure. Teardown logger so error messages from
|
|
127
|
+
// callers (orchestrator, XState) go to the terminal, not the log file.
|
|
96
128
|
await session.close().catch(() => { });
|
|
97
129
|
if (!loggerWasActive)
|
|
98
130
|
logger.teardown();
|
|
@@ -103,96 +135,178 @@ async function createBuiltinSession(options) {
|
|
|
103
135
|
/**
|
|
104
136
|
* Creates a DockerAgentSession that runs an external agent in a container.
|
|
105
137
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
* infrastructure
|
|
138
|
+
* Two paths:
|
|
139
|
+
* - Standalone (default): calls `createDockerInfrastructure()` to stand up
|
|
140
|
+
* the full infrastructure bundle (proxies, orientation, image, running
|
|
141
|
+
* agent container, sidecar and internal network for TCP mode). The
|
|
142
|
+
* session is constructed with `ownsInfra=true`, so `close()` tears down
|
|
143
|
+
* the bundle.
|
|
144
|
+
* - Borrow (`options.workflow.infrastructure` set): uses the caller-supplied
|
|
145
|
+
* bundle as-is and constructs the session with `ownsInfra=false`. The
|
|
146
|
+
* caller retains full responsibility for the bundle's lifetime; the
|
|
147
|
+
* session's `close()` only tears down session-local state.
|
|
148
|
+
*
|
|
149
|
+
* In both paths the session wires up escalation watcher and audit tailer
|
|
150
|
+
* and writes any per-session files (CLAUDE.md, effective system prompt)
|
|
151
|
+
* using fields on the bundle.
|
|
109
152
|
*/
|
|
110
153
|
async function createDockerSession(agentId, options) {
|
|
111
154
|
const config = options.config ?? loadConfig();
|
|
112
155
|
const sessionId = createSessionId();
|
|
113
156
|
const effectiveSessionId = options.resumeSessionId ?? sessionId;
|
|
157
|
+
// Agent-CLI conversation id must be minted by the caller. Docker-mode
|
|
158
|
+
// callers pass `DockerSessionOptions`, which makes this field required
|
|
159
|
+
// at the type level. The runtime guard catches callers that widen to
|
|
160
|
+
// the base `SessionOptions` type and forget to supply it — the factory
|
|
161
|
+
// will not mint on their behalf because the single-conversation model
|
|
162
|
+
// makes the minting site load-bearing (workflow orchestrator reuses
|
|
163
|
+
// per state; each CLI run mints fresh). See §11 step 4 and §3
|
|
164
|
+
// "Identity flow" in docs/designs/workflow-session-identity.md.
|
|
165
|
+
if (!options.agentConversationId) {
|
|
166
|
+
throw new SessionError('agentConversationId is required for Docker sessions: mint via createAgentConversationId() at the call site', 'SESSION_INIT_FAILED');
|
|
167
|
+
}
|
|
168
|
+
const agentConversationId = options.agentConversationId;
|
|
114
169
|
const loggerWasActive = logger.isActive();
|
|
115
170
|
const sessionConfig = buildSessionConfig(config, effectiveSessionId, sessionId, options);
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
171
|
+
// Wrap the entire infrastructure + init sequence so that logger.teardown()
|
|
172
|
+
// runs on ANY failure, not just session.initialize() failures.
|
|
173
|
+
// buildSessionConfig() calls logger.setup() which hijacks console globally;
|
|
174
|
+
// if we don't teardown on error, all subsequent console output (including
|
|
175
|
+
// error messages from the orchestrator and XState) silently goes to a log
|
|
176
|
+
// file instead of the terminal.
|
|
177
|
+
let session;
|
|
178
|
+
// Track the infra bundle in outer scope so the catch path can clean
|
|
179
|
+
// up containers/proxies even if failure happens BEFORE the session
|
|
180
|
+
// instance exists (e.g., writeFileSync for CLAUDE.md throws, or the
|
|
181
|
+
// DockerAgentSession constructor throws). Without this, the session
|
|
182
|
+
// is undefined and `session?.close()` is a no-op — the container,
|
|
183
|
+
// sidecar, network, and proxies all leak.
|
|
184
|
+
let infra;
|
|
185
|
+
// Tracks whether THIS factory allocated the infra bundle. When true and
|
|
186
|
+
// the session never reaches a constructed state, the catch path tears
|
|
187
|
+
// down the bundle directly. When false (borrow path), the caller owns
|
|
188
|
+
// the bundle and the factory must NEVER destroy it, even on error.
|
|
189
|
+
let builtInfra = false;
|
|
190
|
+
try {
|
|
191
|
+
const { DockerAgentSession } = await import('../docker/docker-agent-session.js');
|
|
192
|
+
const { buildDockerClaudeMd } = await import('../docker/claude-md-seed.js');
|
|
193
|
+
if (options.workflow?.infrastructure) {
|
|
194
|
+
// Borrow path: the orchestrator owns the bundle's lifetime. We do
|
|
195
|
+
// not call createDockerInfrastructure(); we do not destroy on close.
|
|
196
|
+
// The orchestrator is also responsible for `setTokenSessionId`: it
|
|
197
|
+
// flips the MITM proxy's routing target to the active agent's session
|
|
198
|
+
// ID before each run and clears it on session end.
|
|
199
|
+
infra = options.workflow.infrastructure;
|
|
131
200
|
}
|
|
132
201
|
else {
|
|
133
|
-
|
|
134
|
-
|
|
202
|
+
// Standalone path: factory creates and owns the bundle.
|
|
203
|
+
// Single-session invariant (§2.1 of workflow-session-identity): the
|
|
204
|
+
// SessionId value doubles as the BundleId. The helper preserves
|
|
205
|
+
// the deterministic `ironcurtain-<sessionId[0:12]>` container
|
|
206
|
+
// name for prior-crash recovery.
|
|
207
|
+
const bundleId = bundleIdFromSessionId(sessionId);
|
|
208
|
+
const { createDockerInfrastructure } = await import('../docker/docker-infrastructure.js');
|
|
209
|
+
infra = await createDockerInfrastructure(sessionConfig.config, { kind: 'docker', agent: agentId }, sessionConfig.sessionDir, sessionConfig.sandboxDir, sessionConfig.escalationDir, bundleId, undefined, undefined, sessionConfig.resolvedSkills);
|
|
210
|
+
// Standalone sessions use their bundle for the session's entire
|
|
211
|
+
// lifetime; pin the token-stream routing ID to this session's ID.
|
|
212
|
+
// Clearing on close is unnecessary because the bundle itself is
|
|
213
|
+
// destroyed by `session.close()` (ownsInfra=true).
|
|
214
|
+
infra.setTokenSessionId(sessionId);
|
|
215
|
+
builtInfra = true;
|
|
216
|
+
}
|
|
217
|
+
const claudeMdContent = buildDockerClaudeMd({
|
|
218
|
+
personaName: options.persona,
|
|
219
|
+
memoryEnabled: sessionConfig.memoryEnabled,
|
|
220
|
+
});
|
|
221
|
+
// Write CLAUDE.md into conversation state dir (unconditionally, even on
|
|
222
|
+
// resume, since persona/memory config may change between sessions).
|
|
223
|
+
// Clean up stale CLAUDE.md when memory is disabled to avoid leftover rules.
|
|
224
|
+
if (infra.conversationStateDir) {
|
|
225
|
+
const claudeMdPath = resolve(infra.conversationStateDir, 'CLAUDE.md');
|
|
226
|
+
if (claudeMdContent) {
|
|
227
|
+
writeFileSync(claudeMdPath, claudeMdContent);
|
|
135
228
|
}
|
|
136
|
-
|
|
137
|
-
|
|
229
|
+
else {
|
|
230
|
+
try {
|
|
231
|
+
unlinkSync(claudeMdPath);
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
/* not present */
|
|
235
|
+
}
|
|
138
236
|
}
|
|
139
237
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
preBuiltInfrastructure: {
|
|
160
|
-
systemPrompt: sessionConfig.systemPromptAugmentation
|
|
161
|
-
? `${infra.systemPrompt}\n\n${sessionConfig.systemPromptAugmentation}`
|
|
162
|
-
: infra.systemPrompt,
|
|
163
|
-
image: infra.image,
|
|
164
|
-
mitmAddr: infra.mitmAddr,
|
|
165
|
-
},
|
|
166
|
-
});
|
|
167
|
-
try {
|
|
238
|
+
const systemPromptOverride = sessionConfig.systemPromptAugmentation
|
|
239
|
+
? `${infra.systemPrompt}\n\n${sessionConfig.systemPromptAugmentation}`
|
|
240
|
+
: undefined;
|
|
241
|
+
session = new DockerAgentSession({
|
|
242
|
+
config: sessionConfig.config,
|
|
243
|
+
sessionId,
|
|
244
|
+
agentConversationId,
|
|
245
|
+
infra,
|
|
246
|
+
// Ownership mirrors who allocated the bundle: standalone path owns
|
|
247
|
+
// and tears down on close; borrow path leaves the bundle alive for
|
|
248
|
+
// the external orchestrator.
|
|
249
|
+
ownsInfra: builtInfra,
|
|
250
|
+
agentModelOverride: options.agentModelOverride,
|
|
251
|
+
onEscalation: options.onEscalation,
|
|
252
|
+
onEscalationExpired: options.onEscalationExpired,
|
|
253
|
+
onEscalationResolved: options.onEscalationResolved,
|
|
254
|
+
onDiagnostic: options.onDiagnostic,
|
|
255
|
+
systemPromptOverride,
|
|
256
|
+
});
|
|
168
257
|
await session.initialize();
|
|
258
|
+
return session;
|
|
169
259
|
}
|
|
170
260
|
catch (error) {
|
|
171
|
-
|
|
261
|
+
// If the session was constructed, its close() respects the ownsInfra
|
|
262
|
+
// flag we passed in: standalone sessions (ownsInfra=true) destroy the
|
|
263
|
+
// bundle they own; borrow-mode sessions (ownsInfra=false) leave the
|
|
264
|
+
// caller's bundle intact. We need only invoke close() -- no
|
|
265
|
+
// conditional cleanup here.
|
|
266
|
+
//
|
|
267
|
+
// Otherwise, if we allocated the bundle ourselves but failed before
|
|
268
|
+
// the session was constructed (e.g., the DockerAgentSession
|
|
269
|
+
// constructor threw, or the CLAUDE.md write threw), destroy it
|
|
270
|
+
// directly. NEVER destroy a caller-supplied bundle on this branch --
|
|
271
|
+
// `builtInfra` is false in borrow mode, so the guard below skips it.
|
|
272
|
+
if (session) {
|
|
273
|
+
await session.close().catch(() => { });
|
|
274
|
+
}
|
|
275
|
+
else if (builtInfra && infra) {
|
|
276
|
+
const { destroyDockerInfrastructure } = await import('../docker/docker-infrastructure.js');
|
|
277
|
+
await destroyDockerInfrastructure(infra).catch(() => { });
|
|
278
|
+
}
|
|
172
279
|
if (!loggerWasActive)
|
|
173
280
|
logger.teardown();
|
|
174
|
-
throw
|
|
281
|
+
throw error instanceof SessionError
|
|
282
|
+
? error
|
|
283
|
+
: new SessionError(`Docker session failed: ${error instanceof Error ? error.message : String(error)}`, 'SESSION_INIT_FAILED');
|
|
175
284
|
}
|
|
176
|
-
return session;
|
|
177
285
|
}
|
|
178
286
|
/**
|
|
179
287
|
* Validates that a policyDir path resolves to a location under the
|
|
180
288
|
* IronCurtain home directory or the package config directory. Prevents
|
|
181
289
|
* loading attacker-controlled policy files from arbitrary filesystem locations.
|
|
182
290
|
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
291
|
+
* Thin wrapper around the shared validator in `config/validate-policy-dir.ts`
|
|
292
|
+
* so failures surface as `SessionError` with our standard code — the
|
|
293
|
+
* shared helper throws `PolicyDirValidationError`, which other callers
|
|
294
|
+
* (e.g., the coordinator's `loadPolicy` RPC) surface in their own way.
|
|
295
|
+
*
|
|
296
|
+
* Returns the realpath-canonicalized path. Callers must use the return
|
|
297
|
+
* value for all subsequent reads: feeding the original (possibly-symlinked)
|
|
298
|
+
* path to downstream artifact loaders would reopen the symlink-swap TOCTOU
|
|
299
|
+
* window the validator was introduced to close.
|
|
186
300
|
*
|
|
187
301
|
* @throws {SessionError} if the path escapes all trusted directories.
|
|
188
302
|
*/
|
|
189
303
|
function validatePolicyDir(policyDir) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
304
|
+
try {
|
|
305
|
+
return sharedValidatePolicyDir(policyDir);
|
|
306
|
+
}
|
|
307
|
+
catch (err) {
|
|
308
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
309
|
+
throw new SessionError(message, 'SESSION_INIT_FAILED');
|
|
196
310
|
}
|
|
197
311
|
}
|
|
198
312
|
/**
|
|
@@ -211,10 +325,24 @@ export function buildSessionConfig(config, effectiveSessionId, sessionId, opts =
|
|
|
211
325
|
let { workspacePath, policyDir, systemPromptAugmentation } = opts;
|
|
212
326
|
const { resumeSessionId, disableAutoApprove } = opts;
|
|
213
327
|
let serverAllowlist;
|
|
214
|
-
|
|
215
|
-
//
|
|
328
|
+
let personaDef = undefined;
|
|
329
|
+
// Borrow-mode invariant: per-state artifact dir / slug only make sense
|
|
330
|
+
// alongside an infrastructure bundle. The nested record keeps these
|
|
331
|
+
// fields colocated; the runtime guard catches the all-or-nothing
|
|
332
|
+
// mismatch (the union of the two-bit input domain isn't expressible
|
|
333
|
+
// at the type level without a discriminator on the workflow record).
|
|
334
|
+
if (opts.workflow?.stateDir && !opts.workflow.infrastructure) {
|
|
335
|
+
throw new SessionError('workflow.stateDir requires workflow.infrastructure; borrow-mode artifacts have no owner without a bundle', 'SESSION_INIT_FAILED');
|
|
336
|
+
}
|
|
337
|
+
// Resolve persona early -- derives policyDir, workspace, and server
|
|
338
|
+
// filter from the persona definition. The persona system prompt
|
|
339
|
+
// augmentation is deferred until after the memory gate is computed
|
|
340
|
+
// with the full (persona + job) scope, so the augmentation and the
|
|
341
|
+
// server bolt-on cannot disagree when both opts.persona and opts.jobId
|
|
342
|
+
// are set.
|
|
216
343
|
if (opts.persona) {
|
|
217
344
|
const resolved = resolvePersona(opts.persona);
|
|
345
|
+
personaDef = resolved.persona;
|
|
218
346
|
if (policyDir) {
|
|
219
347
|
logger.warn('Both persona and policyDir specified; using persona.');
|
|
220
348
|
}
|
|
@@ -224,35 +352,70 @@ export function buildSessionConfig(config, effectiveSessionId, sessionId, opts =
|
|
|
224
352
|
if (!workspacePath) {
|
|
225
353
|
workspacePath = resolved.workspacePath;
|
|
226
354
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
355
|
+
logger.info(`Persona "${opts.persona}" resolved: policyDir=${policyDir}`);
|
|
356
|
+
}
|
|
357
|
+
// Single gate computation with the full scope. Reused for the persona
|
|
358
|
+
// augmentation, the cron-job memory prompt, and the server bolt-on so
|
|
359
|
+
// the prompt cannot mention memory while the relay is gated off (or
|
|
360
|
+
// vice versa). Skip the loadJob disk read when the global kill switch
|
|
361
|
+
// would short-circuit anyway.
|
|
362
|
+
const memoryConfig = config.userConfig.memory;
|
|
363
|
+
const jobDef = memoryConfig.enabled && opts.jobId ? loadJob(createJobId(opts.jobId)) : undefined;
|
|
364
|
+
const memoryEnabled = isMemoryEnabledFor({
|
|
365
|
+
persona: personaDef,
|
|
366
|
+
job: jobDef,
|
|
367
|
+
userConfig: config.userConfig,
|
|
368
|
+
});
|
|
369
|
+
if (personaDef) {
|
|
370
|
+
const personaAugmentation = buildPersonaSystemPromptAugmentation(personaDef, memoryEnabled);
|
|
230
371
|
systemPromptAugmentation = systemPromptAugmentation
|
|
231
372
|
? `${personaAugmentation}\n\n${systemPromptAugmentation}`
|
|
232
373
|
: personaAugmentation;
|
|
233
|
-
logger.info(`Persona "${opts.persona}" resolved: policyDir=${policyDir}`);
|
|
234
374
|
}
|
|
235
375
|
if (policyDir) {
|
|
236
|
-
|
|
376
|
+
// Use the validator's realpath-canonicalized return value. Passing
|
|
377
|
+
// the original (possibly-symlinked) path through to `generatedDir`
|
|
378
|
+
// would reopen the symlink-swap TOCTOU window the validator was
|
|
379
|
+
// introduced to close: downstream artifact reads (compiled policy,
|
|
380
|
+
// dynamic lists) must happen against the same canonical path the
|
|
381
|
+
// containment check approved.
|
|
382
|
+
policyDir = validatePolicyDir(policyDir);
|
|
237
383
|
}
|
|
238
|
-
|
|
384
|
+
// Paths differ by mode:
|
|
385
|
+
// - Borrow mode: per-state artifacts go under `workflow.stateDir` when
|
|
386
|
+
// the orchestrator supplied one; otherwise fall back to the bundle's
|
|
387
|
+
// bundleDir (legacy path, still used by factory-level tests). The
|
|
388
|
+
// bundle owns workspace/escalation/audit on `workflow.infrastructure`.
|
|
389
|
+
// - Standalone/CLI: everything lives under `{home}/sessions/{id}/`.
|
|
390
|
+
const borrowInfra = opts.workflow?.infrastructure;
|
|
391
|
+
const artifactDir = borrowInfra ? (opts.workflow.stateDir ?? borrowInfra.bundleDir) : undefined;
|
|
392
|
+
const sessionDir = artifactDir ?? getSessionDir(effectiveSessionId);
|
|
239
393
|
const sandboxDir = workspacePath ?? getSessionSandboxDir(effectiveSessionId);
|
|
240
|
-
const escalationDir = getSessionEscalationDir(effectiveSessionId);
|
|
241
|
-
const auditLogPath = getSessionAuditLogPath(effectiveSessionId);
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
394
|
+
const escalationDir = borrowInfra ? borrowInfra.escalationDir : getSessionEscalationDir(effectiveSessionId);
|
|
395
|
+
const auditLogPath = borrowInfra ? borrowInfra.auditLogPath : getSessionAuditLogPath(effectiveSessionId);
|
|
396
|
+
// Standalone mode creates its own session tree. Borrow mode relies on
|
|
397
|
+
// directories the orchestrator and bundle already own.
|
|
398
|
+
if (!borrowInfra) {
|
|
399
|
+
if (!opts.workspacePath) {
|
|
400
|
+
mkdirSync(sandboxDir, { recursive: true });
|
|
401
|
+
}
|
|
402
|
+
mkdirSync(escalationDir, { recursive: true });
|
|
248
403
|
}
|
|
249
|
-
|
|
250
|
-
|
|
404
|
+
const sessionLogPath = artifactDir
|
|
405
|
+
? resolve(artifactDir, SESSION_LOG_FILENAME)
|
|
406
|
+
: getSessionLogPath(effectiveSessionId);
|
|
407
|
+
// llm-interactions / auto-approve-llm still live under the standalone
|
|
408
|
+
// session dir even in borrow mode (per-turn LLM logs are not scoped to
|
|
409
|
+
// the workflow state artifact dir; config.llmLogPath is only read when
|
|
410
|
+
// the builtin agent is active, and borrow-mode sessions are Docker).
|
|
251
411
|
const llmLogPath = getSessionLlmLogPath(effectiveSessionId);
|
|
252
412
|
const autoApproveLlmLogPath = getSessionAutoApproveLlmLogPath(effectiveSessionId);
|
|
253
|
-
// Set up session logging -- captures all console output to file
|
|
413
|
+
// Set up session logging -- captures all console output to file.
|
|
414
|
+
// In borrow mode, setup() retargets the singleton to the new state's
|
|
415
|
+
// log file; a prior state's teardown in session.close() releases the
|
|
416
|
+
// console hijack first.
|
|
254
417
|
logger.setup({ logFilePath: sessionLogPath });
|
|
255
|
-
logger.info(`Session ${sessionId} created`);
|
|
418
|
+
logger.info(`Session ${sessionId} created${opts.workflow?.stateSlug ? ` (state=${opts.workflow.stateSlug})` : ''}`);
|
|
256
419
|
logger.info(`${workspacePath ? 'Workspace' : 'Sandbox'}: ${sandboxDir}`);
|
|
257
420
|
logger.info(`Escalation dir: ${escalationDir}`);
|
|
258
421
|
logger.info(`Audit log: ${auditLogPath}`);
|
|
@@ -260,6 +423,18 @@ export function buildSessionConfig(config, effectiveSessionId, sessionId, opts =
|
|
|
260
423
|
if (resumeSessionId) {
|
|
261
424
|
logger.info(`Resumed from session: ${resumeSessionId}`);
|
|
262
425
|
}
|
|
426
|
+
// Build userConfig overrides (auto-approver disable, resource budget).
|
|
427
|
+
// Composed incrementally so multiple overrides don't clobber each other.
|
|
428
|
+
let patchedUserConfig = config.userConfig;
|
|
429
|
+
if (disableAutoApprove) {
|
|
430
|
+
patchedUserConfig = { ...patchedUserConfig, autoApprove: { ...patchedUserConfig.autoApprove, enabled: false } };
|
|
431
|
+
}
|
|
432
|
+
if (opts.resourceBudgetOverrides) {
|
|
433
|
+
patchedUserConfig = {
|
|
434
|
+
...patchedUserConfig,
|
|
435
|
+
resourceBudget: { ...patchedUserConfig.resourceBudget, ...opts.resourceBudgetOverrides },
|
|
436
|
+
};
|
|
437
|
+
}
|
|
263
438
|
// Override config paths for this session's isolated directories.
|
|
264
439
|
// Deep-clone mcpServers so patching doesn't mutate the caller's config.
|
|
265
440
|
const sessionConfig = {
|
|
@@ -280,19 +455,23 @@ export function buildSessionConfig(config, effectiveSessionId, sessionId, opts =
|
|
|
280
455
|
}
|
|
281
456
|
: {}),
|
|
282
457
|
mcpServers: JSON.parse(JSON.stringify(config.mcpServers)),
|
|
283
|
-
|
|
284
|
-
...(disableAutoApprove
|
|
285
|
-
? { userConfig: { ...config.userConfig, autoApprove: { ...config.userConfig.autoApprove, enabled: false } } }
|
|
286
|
-
: {}),
|
|
458
|
+
userConfig: patchedUserConfig,
|
|
287
459
|
};
|
|
288
460
|
// Apply server allowlist if persona specifies one
|
|
289
461
|
if (serverAllowlist) {
|
|
290
462
|
sessionConfig.mcpServers = applyServerAllowlist(sessionConfig.mcpServers, serverAllowlist);
|
|
291
463
|
}
|
|
464
|
+
const { compiledPolicy: policyForFilter } = loadGeneratedPolicy({
|
|
465
|
+
policyDir: sessionConfig.generatedDir,
|
|
466
|
+
toolAnnotationsDir: sessionConfig.toolAnnotationsDir ?? sessionConfig.generatedDir,
|
|
467
|
+
fallbackDir: getPackageGeneratedDir(),
|
|
468
|
+
});
|
|
469
|
+
sessionConfig.mcpServers = filterMcpServersByPolicy(sessionConfig.mcpServers, extractRequiredServers(policyForFilter));
|
|
292
470
|
// Inject the memory MCP server for persona and cron job sessions only.
|
|
293
471
|
// Default (ad-hoc) sessions are stateless and don't benefit from memory.
|
|
294
|
-
|
|
295
|
-
|
|
472
|
+
// The gate decision was made once above; reuse it here so the prompt
|
|
473
|
+
// and the relay cannot diverge.
|
|
474
|
+
if (memoryEnabled) {
|
|
296
475
|
const dbPath = resolveMemoryDbPath({
|
|
297
476
|
persona: opts.persona,
|
|
298
477
|
jobId: opts.jobId,
|
|
@@ -315,18 +494,47 @@ export function buildSessionConfig(config, effectiveSessionId, sessionId, opts =
|
|
|
315
494
|
}
|
|
316
495
|
}
|
|
317
496
|
// Patch MCP server args to use the session-specific sandbox directory
|
|
318
|
-
|
|
497
|
+
applyAllowedDirectoryToMcpArgs(sessionConfig.mcpServers, sandboxDir);
|
|
319
498
|
// Persist session settings so --resume can restore them.
|
|
320
499
|
// Only write on initial creation (not when resuming).
|
|
321
500
|
if (!resumeSessionId) {
|
|
322
|
-
|
|
501
|
+
const metadata = {
|
|
323
502
|
createdAt: new Date().toISOString(),
|
|
324
503
|
...(opts.persona ? { persona: opts.persona } : {}),
|
|
325
504
|
...(opts.workspacePath ? { workspacePath: opts.workspacePath } : {}),
|
|
326
505
|
// Only store policyDir when no persona is set (persona derives its own)
|
|
327
506
|
...(!opts.persona && policyDir ? { policyDir } : {}),
|
|
328
507
|
...(opts.disableAutoApprove ? { disableAutoApprove: true } : {}),
|
|
508
|
+
// Persist the agent-CLI conversation id so `ironcurtain --resume`
|
|
509
|
+
// can continue the same Claude conversation rather than starting
|
|
510
|
+
// fresh. Docker-mode sessions only; builtin has no agent CLI.
|
|
511
|
+
...(opts.agentConversationId ? { agentConversationId: opts.agentConversationId } : {}),
|
|
512
|
+
};
|
|
513
|
+
if (artifactDir) {
|
|
514
|
+
saveSessionMetadataTo(resolve(artifactDir, SESSION_METADATA_FILENAME), metadata);
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
saveSessionMetadata(effectiveSessionId, metadata);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
// Borrow-mode: re-stage the bundle in-place so per-state persona skills
|
|
521
|
+
// become visible without remounting. Standalone mode returns the set
|
|
522
|
+
// through SessionDirConfig for the docker factory to stage at bundle
|
|
523
|
+
// creation. Builtin (non-Docker) sessions never mount skills, so we
|
|
524
|
+
// skip the discovery walk entirely to avoid spurious filesystem reads
|
|
525
|
+
// and `[skills] Ignoring …` warnings.
|
|
526
|
+
const dockerMode = opts.mode?.kind === 'docker';
|
|
527
|
+
let resolvedSkills;
|
|
528
|
+
if (borrowInfra || dockerMode) {
|
|
529
|
+
resolvedSkills = resolveSkillsForSession({
|
|
530
|
+
...(opts.persona ? { personaName: opts.persona } : {}),
|
|
531
|
+
...(opts.workflow?.skillsDir ? { workflowSkillsDir: opts.workflow.skillsDir } : {}),
|
|
532
|
+
...(opts.workflow?.skillFilter ? { workflowSkillFilter: opts.workflow.skillFilter } : {}),
|
|
533
|
+
...(opts.workflow?.disableAllSkills ? { disableAllSkills: true } : {}),
|
|
329
534
|
});
|
|
535
|
+
if (borrowInfra) {
|
|
536
|
+
borrowInfra.restageSkills(resolvedSkills);
|
|
537
|
+
}
|
|
330
538
|
}
|
|
331
539
|
return {
|
|
332
540
|
config: sessionConfig,
|
|
@@ -335,24 +543,10 @@ export function buildSessionConfig(config, effectiveSessionId, sessionId, opts =
|
|
|
335
543
|
escalationDir,
|
|
336
544
|
auditLogPath,
|
|
337
545
|
systemPromptAugmentation,
|
|
546
|
+
memoryEnabled,
|
|
547
|
+
resolvedSkills: borrowInfra ? [] : resolvedSkills,
|
|
338
548
|
};
|
|
339
549
|
}
|
|
340
|
-
|
|
341
|
-
* Patches the filesystem MCP server's allowed directory argument
|
|
342
|
-
* to use the session-specific sandbox directory, mirroring the
|
|
343
|
-
* logic in loadConfig() that syncs ALLOWED_DIRECTORY.
|
|
344
|
-
*/
|
|
345
|
-
export function patchMcpServerAllowedDirectory(config, sandboxDir) {
|
|
346
|
-
const fsServer = config.mcpServers['filesystem'];
|
|
347
|
-
if (!fsServer)
|
|
348
|
-
return;
|
|
349
|
-
// Replace any existing allowed directory path in args.
|
|
350
|
-
// The config may have the original default or a previously patched value.
|
|
351
|
-
const lastArgIndex = fsServer.args.length - 1;
|
|
352
|
-
if (lastArgIndex >= 0) {
|
|
353
|
-
fsServer.args[lastArgIndex] = sandboxDir;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
export { SessionError, SessionNotReadyError, SessionClosedError, BudgetExhaustedError } from './errors.js';
|
|
550
|
+
export { SessionError, SessionNotReadyError, SessionClosedError, BudgetExhaustedError } from '../types/errors.js';
|
|
357
551
|
export { resolveSessionMode, PreflightError } from './preflight.js';
|
|
358
552
|
//# sourceMappingURL=index.js.map
|