@provos/ironcurtain 0.11.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 +9 -7
- 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 +8 -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 +116 -1
- package/dist/config/config-command.js.map +1 -1
- package/dist/config/first-start.js +2 -8
- package/dist/config/first-start.js.map +1 -1
- 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 +48 -6
- package/dist/config/paths.js +63 -8
- package/dist/config/paths.js.map +1 -1
- package/dist/config/user-config.d.ts +48 -1
- package/dist/config/user-config.js +49 -1
- package/dist/config/user-config.js.map +1 -1
- package/dist/daemon/daemon-command.js +14 -5
- package/dist/daemon/daemon-command.js.map +1 -1
- package/dist/daemon/ironcurtain-daemon.d.ts +18 -0
- package/dist/daemon/ironcurtain-daemon.js +22 -1
- 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/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/agent-adapter.d.ts +5 -1
- package/dist/docker/agent-adapter.js +2 -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 +11 -0
- package/dist/docker/code-mode-proxy.js +3 -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.js +30 -1
- package/dist/docker/docker-agent-session.js.map +1 -1
- package/dist/docker/docker-infrastructure.d.ts +186 -9
- package/dist/docker/docker-infrastructure.js +521 -77
- package/dist/docker/docker-infrastructure.js.map +1 -1
- package/dist/docker/docker-manager.d.ts +25 -5
- package/dist/docker/docker-manager.js +262 -22
- 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 +1 -1
- package/dist/docker/mitm-proxy.d.ts +52 -1
- package/dist/docker/mitm-proxy.js +234 -10
- 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 +13 -0
- package/dist/docker/oauth-credentials.js +125 -0
- package/dist/docker/oauth-credentials.js.map +1 -1
- package/dist/docker/package-types.d.ts +1 -1
- package/dist/docker/provider-config.d.ts +29 -1
- package/dist/docker/provider-config.js +93 -3
- 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/pty-session.d.ts +15 -0
- package/dist/docker/pty-session.js +139 -67
- package/dist/docker/pty-session.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 +14 -5
- package/dist/docker/resource-limits.js +11 -8
- package/dist/docker/resource-limits.js.map +1 -1
- 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 +53 -7
- package/dist/doctor/checks.d.ts +36 -3
- package/dist/doctor/checks.js +102 -15
- package/dist/doctor/checks.js.map +1 -1
- package/dist/doctor/doctor-command.js +39 -9
- package/dist/doctor/doctor-command.js.map +1 -1
- package/dist/doctor/mcp-liveness.d.ts +1 -1
- package/dist/doctor/mcp-liveness.js +12 -4
- package/dist/doctor/mcp-liveness.js.map +1 -1
- package/dist/index.js +30 -12
- package/dist/index.js.map +1 -1
- 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.js +19 -6
- package/dist/mux/mux-command.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/observe/observe-command.js +112 -125
- package/dist/observe/observe-command.js.map +1 -1
- 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/persona-command.js +46 -76
- 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/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 +12 -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/pipeline-runner.d.ts +63 -4
- package/dist/pipeline/pipeline-runner.js +159 -50
- package/dist/pipeline/pipeline-runner.js.map +1 -1
- package/dist/pipeline/pipeline-shared.d.ts +32 -3
- package/dist/pipeline/pipeline-shared.js +76 -8
- package/dist/pipeline/pipeline-shared.js.map +1 -1
- package/dist/pipeline/refresh-lists.js +3 -5
- package/dist/pipeline/refresh-lists.js.map +1 -1
- package/dist/sandbox/index.d.ts +19 -4
- package/dist/sandbox/index.js +31 -18
- package/dist/sandbox/index.js.map +1 -1
- package/dist/session/index.js +10 -1
- package/dist/session/index.js.map +1 -1
- package/dist/session/preflight.d.ts +1 -30
- package/dist/session/preflight.js +52 -85
- package/dist/session/preflight.js.map +1 -1
- package/dist/session/types.d.ts +9 -0
- package/dist/signal/bot-command.js +6 -1
- package/dist/signal/bot-command.js.map +1 -1
- package/dist/signal/setup-signal.js +1 -1
- package/dist/signal/setup-signal.js.map +1 -1
- package/dist/signal/signal-container.d.ts +3 -3
- package/dist/signal/signal-container.js +2 -2
- package/dist/signal/signal-container.js.map +1 -1
- package/dist/trusted-process/call-circuit-breaker.d.ts +6 -0
- package/dist/trusted-process/call-circuit-breaker.js +22 -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/mcp-proxy-server.js +35 -3
- package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
- package/dist/trusted-process/policy-engine.js +13 -2
- package/dist/trusted-process/policy-engine.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 +22 -8
- package/dist/trusted-process/tool-call-coordinator.js +149 -65
- package/dist/trusted-process/tool-call-coordinator.js.map +1 -1
- package/dist/trusted-process/tool-call-pipeline.d.ts +8 -0
- package/dist/trusted-process/tool-call-pipeline.js +68 -34
- package/dist/trusted-process/tool-call-pipeline.js.map +1 -1
- 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/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/persona-dispatch.d.ts +46 -2
- package/dist/web-ui/dispatch/persona-dispatch.js +209 -56
- package/dist/web-ui/dispatch/persona-dispatch.js.map +1 -1
- package/dist/web-ui/dispatch/session-dispatch.js +22 -4
- package/dist/web-ui/dispatch/session-dispatch.js.map +1 -1
- package/dist/web-ui/dispatch/types.d.ts +23 -0
- package/dist/web-ui/dispatch/types.js +4 -0
- package/dist/web-ui/dispatch/types.js.map +1 -1
- package/dist/web-ui/dispatch/workflow-dispatch.js +116 -5
- package/dist/web-ui/dispatch/workflow-dispatch.js.map +1 -1
- package/dist/web-ui/json-rpc-dispatch.js +1 -1
- package/dist/web-ui/json-rpc-dispatch.js.map +1 -1
- package/dist/web-ui/web-event-bus.d.ts +25 -1
- package/dist/web-ui/web-event-bus.js.map +1 -1
- package/dist/web-ui/web-ui-server.d.ts +14 -0
- package/dist/web-ui/web-ui-server.js +16 -0
- package/dist/web-ui/web-ui-server.js.map +1 -1
- package/dist/web-ui/web-ui-types.d.ts +133 -5
- package/dist/web-ui/web-ui-types.js.map +1 -1
- 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/index.html +2 -2
- 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.js +0 -2
- package/dist/workflow/cli-support.js.map +1 -1
- 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/discovery.d.ts +29 -0
- package/dist/workflow/discovery.js +67 -7
- package/dist/workflow/discovery.js.map +1 -1
- 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.d.ts +7 -1
- package/dist/workflow/lint.js +186 -3
- package/dist/workflow/lint.js.map +1 -1
- package/dist/workflow/machine-builder.d.ts +90 -2
- package/dist/workflow/machine-builder.js +222 -29
- package/dist/workflow/machine-builder.js.map +1 -1
- package/dist/workflow/message-log.d.ts +15 -1
- package/dist/workflow/message-log.js.map +1 -1
- package/dist/workflow/orchestrator.d.ts +505 -1
- package/dist/workflow/orchestrator.js +1722 -69
- package/dist/workflow/orchestrator.js.map +1 -1
- package/dist/workflow/prompt-builder.js +2 -1
- package/dist/workflow/prompt-builder.js.map +1 -1
- package/dist/workflow/run-state-command.js +1 -1
- package/dist/workflow/run-state-command.js.map +1 -1
- package/dist/workflow/status-parser.js +19 -4
- package/dist/workflow/status-parser.js.map +1 -1
- package/dist/workflow/types.d.ts +123 -23
- package/dist/workflow/types.js +2 -0
- package/dist/workflow/types.js.map +1 -1
- package/dist/workflow/validate.d.ts +23 -1
- package/dist/workflow/validate.js +311 -22
- package/dist/workflow/validate.js.map +1 -1
- package/dist/workflow/workflow-command.d.ts +0 -17
- package/dist/workflow/workflow-command.js +110 -88
- package/dist/workflow/workflow-command.js.map +1 -1
- package/dist/workflow/workflow-discovery.d.ts +2 -0
- package/dist/workflow/workflow-discovery.js +22 -1
- package/dist/workflow/workflow-discovery.js.map +1 -1
- package/dist/workflow/workflow-manager.d.ts +34 -0
- package/dist/workflow/workflow-manager.js +52 -1
- package/dist/workflow/workflow-manager.js.map +1 -1
- package/dist/workflow/workflows/design-and-code/README.md +50 -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/workflow.yaml +1 -0
- package/dist/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +6 -1
- package/dist/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +1 -0
- package/dist/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +4 -0
- package/dist/workflow/workflows/vuln-discovery/workflow.yaml +13 -8
- package/docker/Dockerfile.base +22 -0
- package/docker/Dockerfile.base.arm64 +18 -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 +6 -45
- package/docker/entrypoint-codex.sh +42 -0
- package/docker/entrypoint-goose.sh +5 -24
- package/docker/entrypoint-uid-remap.sh +93 -0
- package/package.json +9 -4
- package/src/workflow/workflows/design-and-code/README.md +50 -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/workflow.yaml +1 -0
- package/src/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +6 -1
- package/src/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +1 -0
- package/src/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +4 -0
- package/src/workflow/workflows/vuln-discovery/workflow.yaml +13 -8
- package/dist/web-ui-static/assets/index-BFO5z1js.js +0 -76
- package/dist/web-ui-static/assets/index-CCUwrkIL.css +0 -1
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A thin, generic JSON-RPC-over-WebSocket client for the IronCurtain daemon.
|
|
3
|
+
*
|
|
4
|
+
* This is the single reusable transport for talking to the daemon's web-UI
|
|
5
|
+
* WebSocket surface (`ws://{host}:{port}/ws?token=`). It is workflow-agnostic:
|
|
6
|
+
* it sends arbitrary `MethodName` requests and optionally subscribes to push
|
|
7
|
+
* event frames. Workflow-specific knowledge lives in the calling CLI command.
|
|
8
|
+
*
|
|
9
|
+
* Layering: this module is a LEAF. Its only runtime dependencies are `ws`,
|
|
10
|
+
* node builtins, `src/config/paths.ts` (for discovery), and
|
|
11
|
+
* `src/web-ui/ws-utils.ts`. It imports the wire-contract types from
|
|
12
|
+
* `web-ui-types.ts` as **type-only** imports, which creates no runtime edge.
|
|
13
|
+
*
|
|
14
|
+
* Contract recap (see the {@link DaemonClient} interface for the full list):
|
|
15
|
+
* - RPC-level errors resolve as `{ ok:false, ... }` — callers branch on the
|
|
16
|
+
* discriminant rather than try/catch.
|
|
17
|
+
* - Transport failures (socket closed, connect/request timeout) reject.
|
|
18
|
+
* - `onClose()` fires at most once for an *involuntary* disconnect (remote or
|
|
19
|
+
* network close, or a post-handshake error). A deliberate `close()` does NOT
|
|
20
|
+
* fire it — that is how listeners distinguish "the daemon went away" from
|
|
21
|
+
* "we tore down on purpose".
|
|
22
|
+
*/
|
|
23
|
+
import { readFileSync } from 'node:fs';
|
|
24
|
+
import { WebSocket } from 'ws';
|
|
25
|
+
import { getWebUiStatePath } from '../config/paths.js';
|
|
26
|
+
import { wsDataToString } from '../web-ui/ws-utils.js';
|
|
27
|
+
/**
|
|
28
|
+
* Signals that no daemon is running with `--web-ui` (no discoverable endpoint).
|
|
29
|
+
* Carries a `code` discriminant so cross-module catchers branch on a string
|
|
30
|
+
* rather than `instanceof` (per CLAUDE.md module-layering guidance).
|
|
31
|
+
*/
|
|
32
|
+
export class DaemonNotRunningError extends Error {
|
|
33
|
+
code = 'DAEMON_NOT_RUNNING';
|
|
34
|
+
constructor(message = 'No IronCurtain daemon with web UI is running') {
|
|
35
|
+
super(message);
|
|
36
|
+
this.name = 'DaemonNotRunningError';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Discovery
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
|
|
43
|
+
const DEFAULT_CONNECT_TIMEOUT_MS = 10_000;
|
|
44
|
+
/**
|
|
45
|
+
* Reads daemon connection info from the well-known state file
|
|
46
|
+
* (`getWebUiStatePath()` → `~/.ironcurtain/web-ui.json`).
|
|
47
|
+
*
|
|
48
|
+
* Returns `undefined` when the file is absent or unparseable — i.e. when no
|
|
49
|
+
* daemon is running with `--web-ui`. Callers distinguish "no daemon" from other
|
|
50
|
+
* failures by this `undefined` return, never by catching.
|
|
51
|
+
*/
|
|
52
|
+
export function discoverDaemon() {
|
|
53
|
+
let raw;
|
|
54
|
+
try {
|
|
55
|
+
raw = readFileSync(getWebUiStatePath(), 'utf-8');
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
let parsed;
|
|
61
|
+
try {
|
|
62
|
+
parsed = JSON.parse(raw);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
if (!isDaemonEndpoint(parsed))
|
|
68
|
+
return undefined;
|
|
69
|
+
return { host: parsed.host, port: parsed.port, token: parsed.token };
|
|
70
|
+
}
|
|
71
|
+
/** Structural guard for a discovered endpoint (rejects garbage state files). */
|
|
72
|
+
function isDaemonEndpoint(value) {
|
|
73
|
+
if (value === null || typeof value !== 'object')
|
|
74
|
+
return false;
|
|
75
|
+
const v = value;
|
|
76
|
+
return (typeof v.host === 'string' &&
|
|
77
|
+
v.host.length > 0 &&
|
|
78
|
+
typeof v.port === 'number' &&
|
|
79
|
+
Number.isInteger(v.port) &&
|
|
80
|
+
v.port > 0 &&
|
|
81
|
+
v.port <= 65535 &&
|
|
82
|
+
typeof v.token === 'string' &&
|
|
83
|
+
v.token.length > 0);
|
|
84
|
+
}
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
// Construction
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
/**
|
|
89
|
+
* Constructs (but does not connect) a {@link DaemonClient}.
|
|
90
|
+
*
|
|
91
|
+
* Throws {@link DaemonNotRunningError} when no `endpoint` is supplied and
|
|
92
|
+
* discovery fails — the single typed signal an agent uses to decide whether to
|
|
93
|
+
* start a daemon.
|
|
94
|
+
*/
|
|
95
|
+
export function createDaemonClient(options = {}) {
|
|
96
|
+
const endpoint = options.endpoint ?? discoverDaemon();
|
|
97
|
+
if (!endpoint) {
|
|
98
|
+
throw new DaemonNotRunningError();
|
|
99
|
+
}
|
|
100
|
+
return new WebSocketDaemonClient(endpoint, {
|
|
101
|
+
requestTimeoutMs: options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
|
|
102
|
+
connectTimeoutMs: options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
class WebSocketDaemonClient {
|
|
106
|
+
endpoint;
|
|
107
|
+
timeouts;
|
|
108
|
+
ws;
|
|
109
|
+
pending = new Map();
|
|
110
|
+
listeners = new Set();
|
|
111
|
+
closeListeners = new Set();
|
|
112
|
+
idCounter = 0;
|
|
113
|
+
closed = false;
|
|
114
|
+
lastError;
|
|
115
|
+
closeNotified = false;
|
|
116
|
+
constructor(endpoint, timeouts) {
|
|
117
|
+
this.endpoint = endpoint;
|
|
118
|
+
this.timeouts = timeouts;
|
|
119
|
+
}
|
|
120
|
+
connect() {
|
|
121
|
+
if (this.closed) {
|
|
122
|
+
return Promise.reject(new Error('DaemonClient is closed'));
|
|
123
|
+
}
|
|
124
|
+
if (this.ws) {
|
|
125
|
+
return Promise.reject(new Error('DaemonClient is already connected'));
|
|
126
|
+
}
|
|
127
|
+
const url = `ws://${this.endpoint.host}:${this.endpoint.port}/ws?token=${this.endpoint.token}`;
|
|
128
|
+
const ws = new WebSocket(url);
|
|
129
|
+
this.ws = ws;
|
|
130
|
+
// Permanent error-capturing listener, attached BEFORE the connect-phase
|
|
131
|
+
// handlers. `ws.close()` on a still-CONNECTING socket schedules a deferred
|
|
132
|
+
// 'error' emit; without any listener that becomes an unhandled 'error' event
|
|
133
|
+
// and crashes the process. Keeping a handler attached for the socket's whole
|
|
134
|
+
// life guarantees the deferred error always has somewhere to go, and
|
|
135
|
+
// preserves its message for the onClose info.
|
|
136
|
+
ws.on('error', (err) => {
|
|
137
|
+
this.lastError = err;
|
|
138
|
+
});
|
|
139
|
+
return new Promise((resolve, reject) => {
|
|
140
|
+
const timer = setTimeout(() => {
|
|
141
|
+
ws.removeListener('open', onOpen);
|
|
142
|
+
ws.removeListener('error', onError);
|
|
143
|
+
if (this.ws === ws)
|
|
144
|
+
this.ws = undefined;
|
|
145
|
+
ws.close();
|
|
146
|
+
reject(new Error(`Timed out connecting to daemon after ${this.timeouts.connectTimeoutMs}ms`));
|
|
147
|
+
}, this.timeouts.connectTimeoutMs);
|
|
148
|
+
const onOpen = () => {
|
|
149
|
+
clearTimeout(timer);
|
|
150
|
+
ws.removeListener('error', onError);
|
|
151
|
+
this.attachSteadyStateHandlers(ws);
|
|
152
|
+
resolve();
|
|
153
|
+
};
|
|
154
|
+
const onError = (err) => {
|
|
155
|
+
clearTimeout(timer);
|
|
156
|
+
ws.removeListener('open', onOpen);
|
|
157
|
+
if (this.ws === ws)
|
|
158
|
+
this.ws = undefined;
|
|
159
|
+
ws.close();
|
|
160
|
+
reject(err);
|
|
161
|
+
};
|
|
162
|
+
ws.once('open', onOpen);
|
|
163
|
+
ws.once('error', onError);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
call(method, params = {}) {
|
|
167
|
+
if (this.closed) {
|
|
168
|
+
return Promise.reject(new Error('DaemonClient is closed'));
|
|
169
|
+
}
|
|
170
|
+
const ws = this.ws;
|
|
171
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
172
|
+
return Promise.reject(new Error('DaemonClient is not connected'));
|
|
173
|
+
}
|
|
174
|
+
const id = `rpc-${++this.idCounter}`;
|
|
175
|
+
return new Promise((resolve, reject) => {
|
|
176
|
+
const timer = setTimeout(() => {
|
|
177
|
+
this.pending.delete(id);
|
|
178
|
+
reject(new Error(`Request "${method}" (${id}) timed out after ${this.timeouts.requestTimeoutMs}ms`));
|
|
179
|
+
}, this.timeouts.requestTimeoutMs);
|
|
180
|
+
this.pending.set(id, {
|
|
181
|
+
resolve: resolve,
|
|
182
|
+
reject,
|
|
183
|
+
timer,
|
|
184
|
+
});
|
|
185
|
+
try {
|
|
186
|
+
ws.send(JSON.stringify({ id, method, params }));
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
this.pending.delete(id);
|
|
190
|
+
clearTimeout(timer);
|
|
191
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
onEvent(listener) {
|
|
196
|
+
this.listeners.add(listener);
|
|
197
|
+
return () => {
|
|
198
|
+
this.listeners.delete(listener);
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
onClose(listener) {
|
|
202
|
+
this.closeListeners.add(listener);
|
|
203
|
+
return () => {
|
|
204
|
+
this.closeListeners.delete(listener);
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
async close() {
|
|
208
|
+
if (this.closed)
|
|
209
|
+
return;
|
|
210
|
+
this.closed = true;
|
|
211
|
+
this.rejectAllPending(new Error('DaemonClient closed'));
|
|
212
|
+
this.listeners.clear();
|
|
213
|
+
// Deliberate teardown: `this.closed = true` (set above) is already in place
|
|
214
|
+
// before `ws.close()` below, so the steady-state 'close' handler's
|
|
215
|
+
// `!this.closed` guard suppresses any spurious onClose. Clearing here also
|
|
216
|
+
// releases references for callers that never disconnect involuntarily.
|
|
217
|
+
this.closeListeners.clear();
|
|
218
|
+
const ws = this.ws;
|
|
219
|
+
if (!ws)
|
|
220
|
+
return;
|
|
221
|
+
if (ws.readyState === WebSocket.CLOSED)
|
|
222
|
+
return;
|
|
223
|
+
await new Promise((resolve) => {
|
|
224
|
+
ws.once('close', () => resolve());
|
|
225
|
+
ws.close();
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
// -----------------------------------------------------------------------
|
|
229
|
+
// Internals
|
|
230
|
+
// -----------------------------------------------------------------------
|
|
231
|
+
attachSteadyStateHandlers(ws) {
|
|
232
|
+
ws.on('message', (data) => this.handleMessage(data));
|
|
233
|
+
ws.on('close', (code) => this.handleClose(code));
|
|
234
|
+
// Post-handshake errors surface via the 'close' that follows; rejecting
|
|
235
|
+
// pending calls there keeps a single drain path. The permanent error-capturing
|
|
236
|
+
// listener attached in `connect()` (before this socket reached steady state)
|
|
237
|
+
// already records `this.lastError`, so its message is available for the
|
|
238
|
+
// onClose info — no second 'error' listener is needed here.
|
|
239
|
+
}
|
|
240
|
+
handleMessage(data) {
|
|
241
|
+
let frame;
|
|
242
|
+
try {
|
|
243
|
+
frame = JSON.parse(wsDataToString(data));
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (typeof frame.id === 'string') {
|
|
249
|
+
this.settleResponse(frame.id, frame);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (typeof frame.event === 'string') {
|
|
253
|
+
this.fanOutEvent({
|
|
254
|
+
event: frame.event,
|
|
255
|
+
payload: frame.payload,
|
|
256
|
+
seq: typeof frame.seq === 'number' ? frame.seq : 0,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
settleResponse(id, frame) {
|
|
261
|
+
const pending = this.pending.get(id);
|
|
262
|
+
if (!pending)
|
|
263
|
+
return;
|
|
264
|
+
this.pending.delete(id);
|
|
265
|
+
clearTimeout(pending.timer);
|
|
266
|
+
pending.resolve(toRpcResult(frame));
|
|
267
|
+
}
|
|
268
|
+
fanOutEvent(event) {
|
|
269
|
+
for (const listener of this.listeners) {
|
|
270
|
+
try {
|
|
271
|
+
listener(event);
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
// A misbehaving listener must not break delivery to the others.
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
handleClose(code) {
|
|
279
|
+
this.rejectAllPending(new Error('Daemon connection closed'));
|
|
280
|
+
// Only fire onClose for an *involuntary* disconnect. `close()` sets
|
|
281
|
+
// `this.closed = true` before closing the socket, so a deliberate teardown
|
|
282
|
+
// is suppressed here. Fire at most once via the `closeNotified` latch.
|
|
283
|
+
if (this.closed || this.closeNotified)
|
|
284
|
+
return;
|
|
285
|
+
this.closeNotified = true;
|
|
286
|
+
const info = {
|
|
287
|
+
code,
|
|
288
|
+
reason: this.lastError?.message ?? `daemon connection closed${code !== undefined ? ` (code ${code})` : ''}`,
|
|
289
|
+
...(this.lastError ? { error: this.lastError } : {}),
|
|
290
|
+
};
|
|
291
|
+
this.fanOutClose(info);
|
|
292
|
+
}
|
|
293
|
+
fanOutClose(info) {
|
|
294
|
+
for (const listener of this.closeListeners) {
|
|
295
|
+
try {
|
|
296
|
+
listener(info);
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
// A misbehaving listener must not break delivery to the others.
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
rejectAllPending(err) {
|
|
304
|
+
for (const [, pending] of this.pending) {
|
|
305
|
+
clearTimeout(pending.timer);
|
|
306
|
+
pending.reject(err);
|
|
307
|
+
}
|
|
308
|
+
this.pending.clear();
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/** Maps a raw `{id,ok,...}` response frame to the {@link RpcResult} discriminant. */
|
|
312
|
+
function toRpcResult(frame) {
|
|
313
|
+
if (frame.ok === true) {
|
|
314
|
+
return { ok: true, payload: frame.payload };
|
|
315
|
+
}
|
|
316
|
+
const error = frame.error;
|
|
317
|
+
return {
|
|
318
|
+
ok: false,
|
|
319
|
+
code: (typeof error?.code === 'string' ? error.code : 'INTERNAL_ERROR'),
|
|
320
|
+
message: typeof error?.message === 'string' ? error.message : 'Unknown RPC error',
|
|
321
|
+
data: error?.data,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=daemon-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon-client.js","sourceRoot":"","sources":["../../src/daemon-client/daemon-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex CLI adapter for Docker Agent Mode.
|
|
3
|
+
*
|
|
4
|
+
* Runs OpenAI Codex CLI non-interactively through the same container,
|
|
5
|
+
* MCP proxy, and MITM fake-token path as other Docker agents. The adapter
|
|
6
|
+
* uses Codex's ChatGPT OAuth/access-token flow, not OPENAI_API_KEY.
|
|
7
|
+
*/
|
|
8
|
+
import type { AgentAdapter } from '../agent-adapter.js';
|
|
9
|
+
export declare function createCodexAdapter(): AgentAdapter;
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex CLI adapter for Docker Agent Mode.
|
|
3
|
+
*
|
|
4
|
+
* Runs OpenAI Codex CLI non-interactively through the same container,
|
|
5
|
+
* MCP proxy, and MITM fake-token path as other Docker agents. The adapter
|
|
6
|
+
* uses Codex's ChatGPT OAuth/access-token flow, not OPENAI_API_KEY.
|
|
7
|
+
*/
|
|
8
|
+
import { buildSystemPrompt } from '../../session/prompts.js';
|
|
9
|
+
import { codexAuthProvider, codexChatGptProvider } from '../provider-config.js';
|
|
10
|
+
import { loadCodexOAuthCredentials } from '../oauth-credentials.js';
|
|
11
|
+
import { parseModelId } from '../../config/model-provider.js';
|
|
12
|
+
import { buildAttributionSection, buildCheckPtySizeScript, buildNetworkSection, buildPolicySection, buildResizePtyScript, } from './shared-scripts.js';
|
|
13
|
+
const CODEX_IMAGE = 'ironcurtain-codex:latest';
|
|
14
|
+
const CODEX_FAKE_ID_TOKEN = 'eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.' +
|
|
15
|
+
'eyJlbWFpbCI6Imlyb25jdXJ0YWluQGV4YW1wbGUuaW52YWxpZCIsImh0dHBzOi8vYXBpLm9wZW5haS5jb20vYXV0aCI6eyJjaGF0Z3B0X3BsYW5fdHlwZSI6InBybyIsImNoYXRncHRfdXNlcl9pZCI6Imlyb25jdXJ0YWluLXVzZXIiLCJjaGF0Z3B0X2FjY291bnRfaWQiOiJpcm9uY3VydGFpbi1hY2NvdW50IiwiY2hhdGdwdF9hY2NvdW50X2lzX2ZlZHJhbXAiOmZhbHNlfX0.' +
|
|
16
|
+
'c2ln';
|
|
17
|
+
function tomlString(value) {
|
|
18
|
+
return JSON.stringify(value);
|
|
19
|
+
}
|
|
20
|
+
function buildCodexDockerEnvironmentPrompt(context) {
|
|
21
|
+
return `## Docker Environment
|
|
22
|
+
|
|
23
|
+
### Workspace (\`${context.workspaceDir}\`)
|
|
24
|
+
This is your workspace inside the container. You have full access here.
|
|
25
|
+
For local file operations inside ${context.workspaceDir}, use your built-in shell tools.
|
|
26
|
+
|
|
27
|
+
### External Operations (MCP tools)
|
|
28
|
+
Use the IronCurtain MCP server for operations that require external access:
|
|
29
|
+
- Network requests (HTTP fetches, web searches, API calls)
|
|
30
|
+
- Git remote operations (clone, push, pull, fetch)
|
|
31
|
+
- Reading files outside ${context.workspaceDir}
|
|
32
|
+
|
|
33
|
+
After cloning a repo or writing files via MCP tools, use your built-in
|
|
34
|
+
tools for subsequent file operations.
|
|
35
|
+
|
|
36
|
+
${buildNetworkSection('the IronCurtain MCP tools')}
|
|
37
|
+
${buildPolicySection('MCP tool call')}
|
|
38
|
+
${buildAttributionSection()}`;
|
|
39
|
+
}
|
|
40
|
+
function buildStartScript() {
|
|
41
|
+
return `#!/bin/bash
|
|
42
|
+
if [ -n "$IRONCURTAIN_INITIAL_COLS" ] && [ -n "$IRONCURTAIN_INITIAL_ROWS" ]; then
|
|
43
|
+
stty cols "$IRONCURTAIN_INITIAL_COLS" rows "$IRONCURTAIN_INITIAL_ROWS" 2>/dev/null
|
|
44
|
+
fi
|
|
45
|
+
cd /workspace
|
|
46
|
+
|
|
47
|
+
MODEL_ARGS=()
|
|
48
|
+
if [ -n "$IRONCURTAIN_MODEL" ]; then
|
|
49
|
+
MODEL_ARGS=(--model "$IRONCURTAIN_MODEL")
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
exec codex --ask-for-approval never --sandbox danger-full-access "\${MODEL_ARGS[@]}" --cd /workspace
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
55
|
+
export function createCodexAdapter() {
|
|
56
|
+
return {
|
|
57
|
+
id: 'codex',
|
|
58
|
+
displayName: 'Codex CLI',
|
|
59
|
+
credentialHelpText: 'No Codex OAuth credentials found. Run `codex login` on the host; OPENAI_API_KEY is not required.',
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- interface requires Promise return
|
|
61
|
+
async getImage() {
|
|
62
|
+
return CODEX_IMAGE;
|
|
63
|
+
},
|
|
64
|
+
generateMcpConfig(socketPath) {
|
|
65
|
+
const isTcp = socketPath.includes(':');
|
|
66
|
+
const connectTarget = isTcp ? `TCP:${socketPath}` : `UNIX-CONNECT:${socketPath}`;
|
|
67
|
+
const toml = [
|
|
68
|
+
'cli_auth_credentials_store = "file"',
|
|
69
|
+
'project_doc_fallback_filenames = ["CLAUDE.md"]',
|
|
70
|
+
'',
|
|
71
|
+
'[projects."/workspace"]',
|
|
72
|
+
'trust_level = "trusted"',
|
|
73
|
+
'',
|
|
74
|
+
'[mcp_servers.ironcurtain]',
|
|
75
|
+
'command = "socat"',
|
|
76
|
+
`args = ["STDIO", ${tomlString(connectTarget)}]`,
|
|
77
|
+
'startup_timeout_sec = 20',
|
|
78
|
+
'tool_timeout_sec = 600',
|
|
79
|
+
'default_tools_approval_mode = "auto"',
|
|
80
|
+
'',
|
|
81
|
+
].join('\n');
|
|
82
|
+
return [{ path: 'codex-config.toml', content: toml }];
|
|
83
|
+
},
|
|
84
|
+
generateOrientationFiles() {
|
|
85
|
+
return [
|
|
86
|
+
{ path: 'start-codex.sh', content: buildStartScript(), mode: 0o755 },
|
|
87
|
+
{ path: 'resize-pty.sh', content: buildResizePtyScript('codex'), mode: 0o755 },
|
|
88
|
+
{ path: 'check-pty-size.sh', content: buildCheckPtySizeScript('codex'), mode: 0o755 },
|
|
89
|
+
];
|
|
90
|
+
},
|
|
91
|
+
buildCommand(message, systemPrompt, options) {
|
|
92
|
+
const prompt = `${systemPrompt}\n\n---\n\nUser request:\n${message}`;
|
|
93
|
+
const cmd = ['codex', '--ask-for-approval', 'never', '--sandbox', 'danger-full-access'];
|
|
94
|
+
if (options.modelOverride) {
|
|
95
|
+
cmd.push('--model', parseModelId(options.modelOverride).modelId);
|
|
96
|
+
}
|
|
97
|
+
cmd.push('exec', '--json', '--skip-git-repo-check', '--cd', '/workspace', prompt);
|
|
98
|
+
return cmd;
|
|
99
|
+
},
|
|
100
|
+
buildSystemPrompt(context) {
|
|
101
|
+
const codeModePrompt = buildSystemPrompt(context.serverListings, context.hostSandboxDir);
|
|
102
|
+
const dockerPrompt = buildCodexDockerEnvironmentPrompt(context);
|
|
103
|
+
return `${codeModePrompt}\n${dockerPrompt}`;
|
|
104
|
+
},
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- authKind kept for adapter interface symmetry
|
|
106
|
+
getProviders(_authKind) {
|
|
107
|
+
return [codexChatGptProvider, codexAuthProvider];
|
|
108
|
+
},
|
|
109
|
+
buildEnv(_config, fakeKeys) {
|
|
110
|
+
const fakeToken = fakeKeys.get('chatgpt.com');
|
|
111
|
+
if (!fakeToken) {
|
|
112
|
+
throw new Error('No fake token generated for chatgpt.com — cannot configure Codex authentication');
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
CODEX_HOME: '/home/codespace/.codex',
|
|
116
|
+
IRONCURTAIN_CODEX_ACCESS_TOKEN: fakeToken,
|
|
117
|
+
IRONCURTAIN_CODEX_ID_TOKEN: CODEX_FAKE_ID_TOKEN,
|
|
118
|
+
IRONCURTAIN_CODEX_ACCOUNT_ID: 'ironcurtain-account',
|
|
119
|
+
CODEX_CA_CERTIFICATE: '/usr/local/share/ca-certificates/ironcurtain-ca.crt',
|
|
120
|
+
SSL_CERT_FILE: '/etc/ssl/certs/ca-certificates.crt',
|
|
121
|
+
RUST_LOG: 'error',
|
|
122
|
+
};
|
|
123
|
+
},
|
|
124
|
+
/**
|
|
125
|
+
* NOTE on quota / transient-failure handling and the assumed Codex
|
|
126
|
+
* envelope schema.
|
|
127
|
+
*
|
|
128
|
+
* Codex `exec --json` emits a JSONL event stream, one JSON object per
|
|
129
|
+
* line. The happy path carries `item.completed` events whose `item.type`
|
|
130
|
+
* is `agent_message` (the model's text). We CANNOT confirm Codex's exact
|
|
131
|
+
* failure-event schema from the repo, so detection is intentionally
|
|
132
|
+
* conservative and generic (see `scanCodexEvents`):
|
|
133
|
+
*
|
|
134
|
+
* - A top-level event is treated as a failure when its `type` ends in
|
|
135
|
+
* `.failed` (e.g. `turn.failed`) or equals `error`, OR when its
|
|
136
|
+
* `item.type` is `error`. We pull a human-readable message from the
|
|
137
|
+
* event's / item's `error.message`, `message`, or `text` field.
|
|
138
|
+
* - From that failure message (plus the non-zero-exit stderr/stdout on
|
|
139
|
+
* the error path), `withFailureSignal` does narrow, string-based
|
|
140
|
+
* matching: a rate-limit / usage-limit / quota / HTTP-429 hit sets
|
|
141
|
+
* `quotaExhausted` (the orchestrator pauses-and-resumes instead of
|
|
142
|
+
* burning the run); anything else error-shaped sets a transient
|
|
143
|
+
* `degenerate_response` failure.
|
|
144
|
+
*
|
|
145
|
+
* Detection is deliberately narrow so it cannot misfire on normal
|
|
146
|
+
* output: the happy-path return value below is byte-identical to the
|
|
147
|
+
* previous implementation (last `agent_message`, else raw stdout). See
|
|
148
|
+
* the Claude Code adapter (`adapters/claude-code.ts`) for the canonical
|
|
149
|
+
* contract and `AgentResponse.quotaExhausted` / `transientFailure` in
|
|
150
|
+
* `../agent-adapter.ts` for the interface requirement.
|
|
151
|
+
*/
|
|
152
|
+
extractResponse(exitCode, stdout, stderr) {
|
|
153
|
+
const clean = stdout.trim();
|
|
154
|
+
const scan = scanCodexEvents(clean);
|
|
155
|
+
if (exitCode !== 0) {
|
|
156
|
+
const errorOutput = [clean, stderr?.trim()].filter((part) => part && part.length > 0).join('\n\n');
|
|
157
|
+
const baseText = `Codex exited with code ${exitCode}.\n\nOutput:\n${errorOutput}`;
|
|
158
|
+
// Combine any in-band failure message with the raw error output so a
|
|
159
|
+
// 429 surfaced either in-band OR only in stderr/stdout is detected.
|
|
160
|
+
const probe = [scan.errorMessage, clean, stderr].filter((p) => p && p.length > 0).join('\n');
|
|
161
|
+
return withFailureSignal({ text: baseText }, probe);
|
|
162
|
+
}
|
|
163
|
+
// Exit 0: prefer the model's final message. If none is present but the
|
|
164
|
+
// stream carried a failure event, describe the failure (and attach the
|
|
165
|
+
// structured signal) instead of dumping a raw JSONL line.
|
|
166
|
+
if (scan.finalMessage) {
|
|
167
|
+
return { text: scan.finalMessage };
|
|
168
|
+
}
|
|
169
|
+
if (scan.errorMessage) {
|
|
170
|
+
return withFailureSignal({ text: `Codex reported an error:\n\n${scan.errorMessage}` }, scan.errorMessage);
|
|
171
|
+
}
|
|
172
|
+
return { text: clean };
|
|
173
|
+
},
|
|
174
|
+
buildPtyCommand(_systemPrompt, ptySockPath, ptyPort) {
|
|
175
|
+
const listenArg = ptySockPath ? `UNIX-LISTEN:${ptySockPath},fork` : `TCP-LISTEN:${ptyPort},reuseaddr`;
|
|
176
|
+
return ['socat', listenArg, 'EXEC:/etc/ironcurtain/start-codex.sh,pty,setsid,ctty,stderr,rawer'];
|
|
177
|
+
},
|
|
178
|
+
detectCredential() {
|
|
179
|
+
const credentials = loadCodexOAuthCredentials();
|
|
180
|
+
if (!credentials)
|
|
181
|
+
return { kind: 'none' };
|
|
182
|
+
return {
|
|
183
|
+
kind: 'oauth',
|
|
184
|
+
credentials: {
|
|
185
|
+
accessToken: credentials.accessToken,
|
|
186
|
+
refreshToken: credentials.refreshToken,
|
|
187
|
+
expiresAt: credentials.expiresAt,
|
|
188
|
+
},
|
|
189
|
+
source: 'file',
|
|
190
|
+
};
|
|
191
|
+
},
|
|
192
|
+
getConversationStateConfig() {
|
|
193
|
+
return {
|
|
194
|
+
hostDirName: 'codex-state',
|
|
195
|
+
containerMountPath: '/home/codespace/.codex/',
|
|
196
|
+
seed: [
|
|
197
|
+
{ path: 'sessions/', content: '' },
|
|
198
|
+
{ path: 'logs/', content: '' },
|
|
199
|
+
],
|
|
200
|
+
resumeFlags: [],
|
|
201
|
+
};
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Single-pass scan over the Codex `exec --json` JSONL stream.
|
|
207
|
+
*
|
|
208
|
+
* Collects the last `agent_message` text and the first detected
|
|
209
|
+
* failure/error message. Malformed/truncated lines are skipped (the JSONL
|
|
210
|
+
* stream can be truncated when a process is killed), so a valid
|
|
211
|
+
* `agent_message` on a later line is still recovered.
|
|
212
|
+
*/
|
|
213
|
+
function scanCodexEvents(stdout) {
|
|
214
|
+
if (stdout.length === 0)
|
|
215
|
+
return { finalMessage: null, errorMessage: null };
|
|
216
|
+
let lastAgentMessage = null;
|
|
217
|
+
let errorMessage = null;
|
|
218
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
219
|
+
if (line.trim().length === 0)
|
|
220
|
+
continue;
|
|
221
|
+
let parsed;
|
|
222
|
+
try {
|
|
223
|
+
parsed = JSON.parse(line);
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (!parsed || typeof parsed !== 'object')
|
|
229
|
+
continue;
|
|
230
|
+
const event = parsed;
|
|
231
|
+
const item = event.item && typeof event.item === 'object' ? event.item : undefined;
|
|
232
|
+
if (item && item.type === 'agent_message' && typeof item.text === 'string') {
|
|
233
|
+
lastAgentMessage = item.text;
|
|
234
|
+
}
|
|
235
|
+
if (errorMessage === null) {
|
|
236
|
+
errorMessage = extractCodexErrorMessage(event, item);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return { finalMessage: lastAgentMessage?.trim() || null, errorMessage };
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Recognizes a Codex failure/error envelope generically (the exact schema
|
|
243
|
+
* is not confirmable from the repo): a top-level `type` ending in `.failed`
|
|
244
|
+
* or equal to `error`, or an item whose `type` is `error`. Returns a
|
|
245
|
+
* best-effort human-readable message, or null when the event is not a
|
|
246
|
+
* failure shape.
|
|
247
|
+
*/
|
|
248
|
+
function extractCodexErrorMessage(event, item) {
|
|
249
|
+
const eventType = typeof event.type === 'string' ? event.type : undefined;
|
|
250
|
+
const isEventFailure = eventType !== undefined && (eventType.endsWith('.failed') || eventType === 'error');
|
|
251
|
+
const isItemFailure = item !== undefined && item.type === 'error';
|
|
252
|
+
if (!isEventFailure && !isItemFailure)
|
|
253
|
+
return null;
|
|
254
|
+
return pickErrorMessage(event) ?? (item ? pickErrorMessage(item) : undefined) ?? eventType ?? 'unknown Codex error';
|
|
255
|
+
}
|
|
256
|
+
/** Pulls a message string from an `error.message` / `message` / `text` field. */
|
|
257
|
+
function pickErrorMessage(obj) {
|
|
258
|
+
const nested = obj.error;
|
|
259
|
+
if (nested && typeof nested === 'object') {
|
|
260
|
+
const msg = nested.message;
|
|
261
|
+
if (typeof msg === 'string' && msg.length > 0)
|
|
262
|
+
return msg;
|
|
263
|
+
}
|
|
264
|
+
if (typeof obj.message === 'string' && obj.message.length > 0)
|
|
265
|
+
return obj.message;
|
|
266
|
+
if (typeof obj.text === 'string' && obj.text.length > 0)
|
|
267
|
+
return obj.text;
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
/** Narrow, case-insensitive substring matches for upstream quota/rate-limit. */
|
|
271
|
+
const QUOTA_PROBE_PATTERNS = [
|
|
272
|
+
/\b429\b/,
|
|
273
|
+
/rate.?limit/i,
|
|
274
|
+
/usage.?limit/i,
|
|
275
|
+
/\bquota\b/i,
|
|
276
|
+
/too many requests/i,
|
|
277
|
+
];
|
|
278
|
+
/**
|
|
279
|
+
* Best-effort classification of a Codex error string into a structured
|
|
280
|
+
* signal. Quota / rate-limit / 429 hits map to `quotaExhausted`; any other
|
|
281
|
+
* non-empty error string maps to a transient `degenerate_response`.
|
|
282
|
+
* Returns the response unchanged when `probe` is empty.
|
|
283
|
+
*
|
|
284
|
+
* Detection is intentionally string-based and narrow so it cannot misfire
|
|
285
|
+
* on normal model output (only reached when a failure event was detected or
|
|
286
|
+
* the process exited non-zero).
|
|
287
|
+
*/
|
|
288
|
+
function withFailureSignal(response, probe) {
|
|
289
|
+
const trimmed = probe.trim();
|
|
290
|
+
if (trimmed.length === 0)
|
|
291
|
+
return response;
|
|
292
|
+
if (QUOTA_PROBE_PATTERNS.some((re) => re.test(trimmed))) {
|
|
293
|
+
return { ...response, quotaExhausted: { rawMessage: trimmed } };
|
|
294
|
+
}
|
|
295
|
+
return { ...response, transientFailure: { kind: 'degenerate_response', rawMessage: trimmed } };
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../src/docker/adapters/codex.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,GAAG,0BAA0B,CAAC;AAC/C,MAAM,mBAAmB,GACvB,sCAAsC;IACtC,8RAA8R;IAC9R,MAAM,CAAC;AAET,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,iCAAiC,CAAC,OAA2B;IACpE,OAAO;;mBAEU,OAAO,CAAC,YAAY;;mCAEJ,OAAO,CAAC,YAAY;;;;;;0BAM7B,OAAO,CAAC,YAAY;;;;;EAK5C,mBAAmB,CAAC,2BAA2B,CAAC;EAChD,kBAAkB,CAAC,eAAe,CAAC;EACnC,uBAAuB,EAAE,EAAE,CAAC;AAC9B,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO;;;;;;;;;;;;CAYR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,EAAE,EAAE,OAAkB;QACtB,WAAW,EAAE,WAAW;QACxB,kBAAkB,EAChB,kGAAkG;QAEpG,iGAAiG;QACjG,KAAK,CAAC,QAAQ;YACZ,OAAO,WAAW,CAAC;QACrB,CAAC;QAED,iBAAiB,CAAC,UAAkB;YAClC,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YACvC,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,UAAU,EAAE,CAAC,CAAC,CAAC,gBAAgB,UAAU,EAAE,CAAC;YAEjF,MAAM,IAAI,GAAG;gBACX,qCAAqC;gBACrC,gDAAgD;gBAChD,EAAE;gBACF,yBAAyB;gBACzB,yBAAyB;gBACzB,EAAE;gBACF,2BAA2B;gBAC3B,mBAAmB;gBACnB,oBAAoB,UAAU,CAAC,aAAa,CAAC,GAAG;gBAChD,0BAA0B;gBAC1B,wBAAwB;gBACxB,sCAAsC;gBACtC,EAAE;aACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEb,OAAO,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,wBAAwB;YACtB,OAAO;gBACL,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;gBACpE,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,oBAAoB,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE;gBAC9E,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,uBAAuB,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE;aACtF,CAAC;QACJ,CAAC;QAED,YAAY,CACV,OAAe,EACf,YAAoB,EACpB,OAIC;YAED,MAAM,MAAM,GAAG,GAAG,YAAY,6BAA6B,OAAO,EAAE,CAAC;YACrE,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,WAAW,EAAE,oBAAoB,CAAC,CAAC;YACxF,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;gBAC1B,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC;YACnE,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;YAClF,OAAO,GAAG,CAAC;QACb,CAAC;QAED,iBAAiB,CAAC,OAA2B;YAC3C,MAAM,cAAc,GAAG,iBAAiB,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;YACzF,MAAM,YAAY,GAAG,iCAAiC,CAAC,OAAO,CAAC,CAAC;YAChE,OAAO,GAAG,cAAc,KAAK,YAAY,EAAE,CAAC;QAC9C,CAAC;QAED,6GAA6G;QAC7G,YAAY,CAAC,SAA0B;YACrC,OAAO,CAAC,oBAAoB,EAAE,iBAAiB,CAAC,CAAC;QACnD,CAAC;QAED,QAAQ,CAAC,OAA0B,EAAE,QAAqC;YACxE,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAC9C,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAC;YACrG,CAAC;YAED,OAAO;gBACL,UAAU,EAAE,wBAAwB;gBACpC,8BAA8B,EAAE,SAAS;gBACzC,0BAA0B,EAAE,mBAAmB;gBAC/C,4BAA4B,EAAE,qBAAqB;gBACnD,oBAAoB,EAAE,qDAAqD;gBAC3E,aAAa,EAAE,oCAAoC;gBACnD,QAAQ,EAAE,OAAO;aAClB,CAAC;QACJ,CAAC;QAED;;;;;;;;;;;;;;;;;;;;;;;;;;;WA2BG;QACH,eAAe,CAAC,QAAgB,EAAE,MAAc,EAAE,MAAe;YAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;YAEpC,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;gBACnB,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACnG,MAAM,QAAQ,GAAG,0BAA0B,QAAQ,iBAAiB,WAAW,EAAE,CAAC;gBAClF,qEAAqE;gBACrE,oEAAoE;gBACpE,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC7F,OAAO,iBAAiB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;YACtD,CAAC;YAED,uEAAuE;YACvE,uEAAuE;YACvE,0DAA0D;YAC1D,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACtB,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;YACrC,CAAC;YACD,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACtB,OAAO,iBAAiB,CAAC,EAAE,IAAI,EAAE,+BAA+B,IAAI,CAAC,YAAY,EAAE,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YAC5G,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACzB,CAAC;QAED,eAAe,CACb,aAAqB,EACrB,WAA+B,EAC/B,OAA2B;YAE3B,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,eAAe,WAAW,OAAO,CAAC,CAAC,CAAC,cAAc,OAAO,YAAY,CAAC;YACtG,OAAO,CAAC,OAAO,EAAE,SAAS,EAAE,mEAAmE,CAAC,CAAC;QACnG,CAAC;QAED,gBAAgB;YACd,MAAM,WAAW,GAAG,yBAAyB,EAAE,CAAC;YAChD,IAAI,CAAC,WAAW;gBAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YAC1C,OAAO;gBACL,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE;oBACX,WAAW,EAAE,WAAW,CAAC,WAAW;oBACpC,YAAY,EAAE,WAAW,CAAC,YAAY;oBACtC,SAAS,EAAE,WAAW,CAAC,SAAS;iBACjC;gBACD,MAAM,EAAE,MAAM;aACf,CAAC;QACJ,CAAC;QAED,0BAA0B;YACxB,OAAO;gBACL,WAAW,EAAE,aAAa;gBAC1B,kBAAkB,EAAE,yBAAyB;gBAC7C,IAAI,EAAE;oBACJ,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE;oBAClC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE;iBAC/B;gBACD,WAAW,EAAE,EAAE;aAChB,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAaD;;;;;;;GAOG;AACH,SAAS,eAAe,CAAC,MAAc;IACrC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IAE3E,IAAI,gBAAgB,GAAkB,IAAI,CAAC;IAC3C,IAAI,YAAY,GAAkB,IAAI,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACvC,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,SAAS;QACpD,MAAM,KAAK,GAAG,MAAiC,CAAC;QAEhD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAE,KAAK,CAAC,IAAgC,CAAC,CAAC,CAAC,SAAS,CAAC;QAEhH,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3E,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC;QAC/B,CAAC;QAED,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC1B,YAAY,GAAG,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,YAAY,EAAE,CAAC;AAC1E,CAAC;AAED;;;;;;GAMG;AACH,SAAS,wBAAwB,CAC/B,KAA8B,EAC9B,IAAyC;IAEzC,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,MAAM,cAAc,GAAG,SAAS,KAAK,SAAS,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,KAAK,OAAO,CAAC,CAAC;IAC3G,MAAM,aAAa,GAAG,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC;IAClE,IAAI,CAAC,cAAc,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAEnD,OAAO,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,qBAAqB,CAAC;AACtH,CAAC;AAED,iFAAiF;AACjF,SAAS,gBAAgB,CAAC,GAA4B;IACpD,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC;IACzB,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QACzC,MAAM,GAAG,GAAI,MAAkC,CAAC,OAAO,CAAC;QACxD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC;IAC5D,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAClF,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC;IACzE,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,gFAAgF;AAChF,MAAM,oBAAoB,GAAsB;IAC9C,SAAS;IACT,cAAc;IACd,eAAe;IACf,YAAY;IACZ,oBAAoB;CACrB,CAAC;AAEF;;;;;;;;;GASG;AACH,SAAS,iBAAiB,CAAC,QAAuB,EAAE,KAAa;IAC/D,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IAE1C,IAAI,oBAAoB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACxD,OAAO,EAAE,GAAG,QAAQ,EAAE,cAAc,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;IAClE,CAAC;IACD,OAAO,EAAE,GAAG,QAAQ,EAAE,gBAAgB,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;AACjG,CAAC"}
|