@provos/ironcurtain 0.11.0 → 0.13.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 +23 -19
- 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 +14 -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.d.ts +33 -1
- package/dist/config/config-command.js +723 -11
- 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/openrouter-catalog.d.ts +46 -0
- package/dist/config/openrouter-catalog.js +111 -0
- package/dist/config/openrouter-catalog.js.map +1 -0
- package/dist/config/openrouter-models-fallback.d.ts +15 -0
- package/dist/config/openrouter-models-fallback.js +49 -0
- package/dist/config/openrouter-models-fallback.js.map +1 -0
- 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/types.d.ts +8 -0
- package/dist/config/user-config.d.ts +179 -6
- package/dist/config/user-config.js +282 -5
- 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 +28 -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/claude-code.js +109 -1
- package/dist/docker/adapters/claude-code.js.map +1 -1
- package/dist/docker/adapters/codex.d.ts +18 -0
- package/dist/docker/adapters/codex.js +376 -0
- package/dist/docker/adapters/codex.js.map +1 -0
- package/dist/docker/adapters/goose.js +38 -2
- package/dist/docker/adapters/goose.js.map +1 -1
- package/dist/docker/agent-adapter.d.ts +34 -6
- 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 +486 -0
- package/dist/docker/apple-container-manager.js.map +1 -0
- package/dist/docker/ca.js +9 -2
- package/dist/docker/ca.js.map +1 -1
- 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 +9 -0
- package/dist/docker/container-lifecycle.js.map +1 -1
- package/dist/docker/container-runtime.d.ts +29 -0
- package/dist/docker/container-runtime.js +76 -0
- package/dist/docker/container-runtime.js.map +1 -0
- package/dist/docker/docker-agent-session.d.ts +31 -0
- package/dist/docker/docker-agent-session.js +97 -7
- package/dist/docker/docker-agent-session.js.map +1 -1
- package/dist/docker/docker-infrastructure.d.ts +232 -15
- package/dist/docker/docker-infrastructure.js +762 -118
- package/dist/docker/docker-infrastructure.js.map +1 -1
- package/dist/docker/docker-manager.d.ts +25 -5
- package/dist/docker/docker-manager.js +388 -21
- 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/docker-resource-lifecycle.d.ts +71 -0
- package/dist/docker/docker-resource-lifecycle.js +454 -0
- package/dist/docker/docker-resource-lifecycle.js.map +1 -0
- package/dist/docker/gc-command.d.ts +2 -0
- package/dist/docker/gc-command.js +37 -0
- package/dist/docker/gc-command.js.map +1 -0
- package/dist/docker/mitm-proxy.d.ts +58 -5
- package/dist/docker/mitm-proxy.js +338 -26
- package/dist/docker/mitm-proxy.js.map +1 -1
- package/dist/docker/network-topology.d.ts +88 -0
- package/dist/docker/network-topology.js +167 -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/openrouter.d.ts +107 -0
- package/dist/docker/openrouter.js +236 -0
- package/dist/docker/openrouter.js.map +1 -0
- package/dist/docker/orientation.js +1 -1
- package/dist/docker/orientation.js.map +1 -1
- package/dist/docker/package-types.d.ts +1 -1
- package/dist/docker/platform.d.ts +3 -1
- package/dist/docker/platform.js +3 -1
- package/dist/docker/platform.js.map +1 -1
- package/dist/docker/provider-config.d.ts +35 -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 +22 -0
- package/dist/docker/pty-session.js +238 -84
- package/dist/docker/pty-session.js.map +1 -1
- package/dist/docker/pty-types.d.ts +15 -0
- package/dist/docker/pty-types.js +8 -0
- package/dist/docker/pty-types.js.map +1 -1
- package/dist/docker/registry-proxy.d.ts +46 -0
- package/dist/docker/registry-proxy.js +255 -1
- package/dist/docker/registry-proxy.js.map +1 -1
- package/dist/docker/resource-limits.d.ts +14 -5
- package/dist/docker/resource-limits.js +11 -8
- package/dist/docker/resource-limits.js.map +1 -1
- package/dist/docker/sse-extractor.js +55 -5
- package/dist/docker/sse-extractor.js.map +1 -1
- package/dist/docker/stream-delay.d.ts +86 -0
- package/dist/docker/stream-delay.js +218 -0
- package/dist/docker/stream-delay.js.map +1 -0
- package/dist/docker/token-stream-types.d.ts +15 -0
- package/dist/docker/trajectory-capture.d.ts +79 -0
- package/dist/docker/trajectory-capture.js +521 -0
- package/dist/docker/trajectory-capture.js.map +1 -0
- package/dist/docker/trajectory-reassembler.d.ts +286 -0
- package/dist/docker/trajectory-reassembler.js +1010 -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 +116 -12
- package/dist/doctor/checks.d.ts +39 -6
- package/dist/doctor/checks.js +129 -25
- 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/escalation/escalation-watcher.js +6 -0
- package/dist/escalation/escalation-watcher.js.map +1 -1
- package/dist/{mux → escalation}/trusted-input.d.ts +7 -4
- package/dist/{mux → escalation}/trusted-input.js +8 -5
- package/dist/escalation/trusted-input.js.map +1 -0
- package/dist/hash.js.map +1 -1
- package/dist/index.js +65 -16
- package/dist/index.js.map +1 -1
- package/dist/mux/mux-app.d.ts +9 -0
- package/dist/mux/mux-app.js +18 -16
- package/dist/mux/mux-app.js.map +1 -1
- package/dist/mux/mux-command.js +26 -8
- package/dist/mux/mux-command.js.map +1 -1
- package/dist/mux/mux-input-handler.d.ts +26 -2
- package/dist/mux/mux-input-handler.js +93 -11
- package/dist/mux/mux-input-handler.js.map +1 -1
- package/dist/mux/mux-renderer.d.ts +2 -1
- package/dist/mux/mux-renderer.js +67 -0
- package/dist/mux/mux-renderer.js.map +1 -1
- package/dist/mux/provider-profile-snapshot.d.ts +44 -0
- package/dist/mux/provider-profile-snapshot.js +56 -0
- package/dist/mux/provider-profile-snapshot.js.map +1 -0
- package/dist/mux/types.d.ts +3 -2
- package/dist/mux/types.js +6 -2
- package/dist/mux/types.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/constitution-compiler.js.map +1 -1
- package/dist/pipeline/generate-with-repair.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/pipeline/scenario-schema-validator.js.map +1 -1
- package/dist/{mux → pty}/pty-bridge.d.ts +41 -3
- package/dist/{mux → pty}/pty-bridge.js +71 -18
- package/dist/pty/pty-bridge.js.map +1 -0
- package/dist/pty/resolve-ironcurtain-bin.d.ts +17 -0
- package/dist/pty/resolve-ironcurtain-bin.js +22 -0
- package/dist/pty/resolve-ironcurtain-bin.js.map +1 -0
- 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/servers/fetch-server.js +2 -0
- package/dist/servers/fetch-server.js.map +1 -1
- package/dist/session/index.d.ts +1 -1
- package/dist/session/index.js +20 -2
- package/dist/session/index.js.map +1 -1
- package/dist/session/preflight.d.ts +20 -35
- package/dist/session/preflight.js +92 -109
- package/dist/session/preflight.js.map +1 -1
- package/dist/session/resource-budget-tracker.js +8 -0
- package/dist/session/resource-budget-tracker.js.map +1 -1
- package/dist/session/session-manager.d.ts +7 -0
- package/dist/session/session-manager.js.map +1 -1
- package/dist/session/types.d.ts +23 -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-bot-daemon.d.ts +1 -0
- package/dist/signal/signal-bot-daemon.js +9 -2
- package/dist/signal/signal-bot-daemon.js.map +1 -1
- package/dist/signal/signal-container.d.ts +3 -3
- package/dist/signal/signal-container.js +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-error-utils.js +4 -1
- package/dist/trusted-process/mcp-error-utils.js.map +1 -1
- package/dist/trusted-process/mcp-proxy-server.js +37 -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 +19 -1
- package/dist/trusted-process/tcp-server-transport.js +56 -10
- 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/utils/preflight-checks.js +1 -3
- package/dist/utils/preflight-checks.js.map +1 -1
- package/dist/utils/stdio-guard.d.ts +1 -0
- package/dist/utils/stdio-guard.js +27 -0
- package/dist/utils/stdio-guard.js.map +1 -0
- package/dist/web-ui/__tests__/config-dispatch.test.d.ts +13 -0
- package/dist/web-ui/__tests__/config-dispatch.test.js +383 -0
- package/dist/web-ui/__tests__/config-dispatch.test.js.map +1 -0
- package/dist/web-ui/__tests__/json-rpc-dispatch.test.js +6 -0
- package/dist/web-ui/__tests__/json-rpc-dispatch.test.js.map +1 -1
- 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/config-dispatch.d.ts +15 -0
- package/dist/web-ui/dispatch/config-dispatch.js +277 -0
- package/dist/web-ui/dispatch/config-dispatch.js.map +1 -0
- package/dist/web-ui/dispatch/escalation-dispatch.js +11 -2
- package/dist/web-ui/dispatch/escalation-dispatch.js.map +1 -1
- 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/pty-dispatch.d.ts +15 -0
- package/dist/web-ui/dispatch/pty-dispatch.js +66 -0
- package/dist/web-ui/dispatch/pty-dispatch.js.map +1 -0
- package/dist/web-ui/dispatch/session-dispatch.js +89 -6
- package/dist/web-ui/dispatch/session-dispatch.js.map +1 -1
- package/dist/web-ui/dispatch/types.d.ts +35 -0
- package/dist/web-ui/dispatch/types.js +42 -1
- 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 +4 -1
- package/dist/web-ui/json-rpc-dispatch.js.map +1 -1
- package/dist/web-ui/pty-session-manager.d.ts +234 -0
- package/dist/web-ui/pty-session-manager.js +599 -0
- package/dist/web-ui/pty-session-manager.js.map +1 -0
- package/dist/web-ui/web-event-bus.d.ts +34 -1
- package/dist/web-ui/web-event-bus.js.map +1 -1
- package/dist/web-ui/web-session-transport.js.map +1 -1
- package/dist/web-ui/web-ui-server.d.ts +22 -0
- package/dist/web-ui/web-ui-server.js +41 -0
- package/dist/web-ui/web-ui-server.js.map +1 -1
- package/dist/web-ui/web-ui-types.d.ts +212 -5
- package/dist/web-ui/web-ui-types.js.map +1 -1
- package/dist/web-ui-static/assets/index-CCVI4nEK.css +1 -0
- package/dist/web-ui-static/assets/index-Dm012gvY.js +114 -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 +595 -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 +1725 -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/shutdown-signals.d.ts +7 -0
- package/dist/workflow/shutdown-signals.js +40 -0
- package/dist/workflow/shutdown-signals.js.map +1 -0
- 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 +118 -94
- 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/README.md +66 -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/README.md +54 -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 +28 -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 +39 -30
- 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/README.md +66 -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/README.md +54 -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/mux/pty-bridge.js.map +0 -1
- package/dist/mux/trusted-input.js.map +0 -1
- package/dist/web-ui-static/assets/index-BFO5z1js.js +0 -76
- package/dist/web-ui-static/assets/index-CCUwrkIL.css +0 -1
- package/packages/web-ui/README.md +0 -113
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Persistent cognition store with semantic retrieval."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import uuid
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from threading import RLock
|
|
9
|
+
from typing import Dict, List, Optional, Tuple
|
|
10
|
+
|
|
11
|
+
from .embedding import EmbeddingService
|
|
12
|
+
from .structures import CognitionItem
|
|
13
|
+
from .vector_index import FAISSIndex
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Cognition:
|
|
17
|
+
"""Persistent cognition store with embedding-backed retrieval."""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
storage_dir: Path,
|
|
22
|
+
embedding_model: str = "sentence-transformers/all-MiniLM-L6-v2",
|
|
23
|
+
embedding_dim: int = 384,
|
|
24
|
+
retrieval_top_k: int = 5,
|
|
25
|
+
score_threshold: float = 0.3,
|
|
26
|
+
faiss_index_type: str = "IP",
|
|
27
|
+
):
|
|
28
|
+
self.storage_dir = Path(storage_dir)
|
|
29
|
+
self.storage_dir.mkdir(parents=True, exist_ok=True)
|
|
30
|
+
self.lock = RLock()
|
|
31
|
+
self.retrieval_top_k = retrieval_top_k
|
|
32
|
+
self.score_threshold = score_threshold
|
|
33
|
+
self.items: Dict[str, CognitionItem] = {}
|
|
34
|
+
self.embedding = EmbeddingService(
|
|
35
|
+
model_name=embedding_model,
|
|
36
|
+
dimension=embedding_dim,
|
|
37
|
+
)
|
|
38
|
+
self.faiss = FAISSIndex(
|
|
39
|
+
dimension=embedding_dim,
|
|
40
|
+
index_type=faiss_index_type,
|
|
41
|
+
storage_path=self.storage_dir / "faiss",
|
|
42
|
+
)
|
|
43
|
+
self.str_to_int: Dict[str, int] = {}
|
|
44
|
+
self.int_to_str: Dict[int, str] = {}
|
|
45
|
+
self.next_int_id = 0
|
|
46
|
+
self._load()
|
|
47
|
+
|
|
48
|
+
def add(self, item: CognitionItem) -> str:
|
|
49
|
+
with self.lock:
|
|
50
|
+
if not item.id:
|
|
51
|
+
item.id = str(uuid.uuid4())
|
|
52
|
+
self.items[item.id] = item
|
|
53
|
+
if item.content:
|
|
54
|
+
int_id = self._get_int_id(item.id)
|
|
55
|
+
self.faiss.add(int_id, self.embedding.encode(item.content))
|
|
56
|
+
self._save()
|
|
57
|
+
return item.id
|
|
58
|
+
|
|
59
|
+
def add_batch(self, items: List[CognitionItem]) -> List[str]:
|
|
60
|
+
return [self.add(item) for item in items]
|
|
61
|
+
|
|
62
|
+
def search(self, query: str, top_k: Optional[int] = None) -> List[CognitionItem]:
|
|
63
|
+
return [item for item, _ in self.retrieve(query, top_k=top_k)]
|
|
64
|
+
|
|
65
|
+
def retrieve(
|
|
66
|
+
self,
|
|
67
|
+
query: str,
|
|
68
|
+
top_k: Optional[int] = None,
|
|
69
|
+
score_threshold: Optional[float] = None,
|
|
70
|
+
) -> List[Tuple[CognitionItem, float]]:
|
|
71
|
+
top_k = top_k or self.retrieval_top_k
|
|
72
|
+
threshold = self.score_threshold if score_threshold is None else score_threshold
|
|
73
|
+
results = self.faiss.search(self.embedding.encode(query), top_k, threshold)
|
|
74
|
+
|
|
75
|
+
enriched: List[Tuple[CognitionItem, float]] = []
|
|
76
|
+
for int_id, score in results:
|
|
77
|
+
item_id = self.int_to_str.get(int_id)
|
|
78
|
+
if item_id and item_id in self.items:
|
|
79
|
+
enriched.append((self.items[item_id], score))
|
|
80
|
+
return enriched
|
|
81
|
+
|
|
82
|
+
def get_all(self) -> List[CognitionItem]:
|
|
83
|
+
return list(self.items.values())
|
|
84
|
+
|
|
85
|
+
def reset(self) -> None:
|
|
86
|
+
with self.lock:
|
|
87
|
+
self.items.clear()
|
|
88
|
+
self.str_to_int.clear()
|
|
89
|
+
self.int_to_str.clear()
|
|
90
|
+
self.next_int_id = 0
|
|
91
|
+
self.faiss.reset()
|
|
92
|
+
data_file = self.storage_dir / "cognition.json"
|
|
93
|
+
if data_file.exists():
|
|
94
|
+
data_file.unlink()
|
|
95
|
+
|
|
96
|
+
def _get_int_id(self, item_id: str) -> int:
|
|
97
|
+
if item_id not in self.str_to_int:
|
|
98
|
+
self.str_to_int[item_id] = self.next_int_id
|
|
99
|
+
self.int_to_str[self.next_int_id] = item_id
|
|
100
|
+
self.next_int_id += 1
|
|
101
|
+
return self.str_to_int[item_id]
|
|
102
|
+
|
|
103
|
+
def _save(self) -> None:
|
|
104
|
+
payload = {
|
|
105
|
+
"items": {item_id: item.to_dict() for item_id, item in self.items.items()},
|
|
106
|
+
"str_to_int": self.str_to_int,
|
|
107
|
+
"int_to_str": {str(key): value for key, value in self.int_to_str.items()},
|
|
108
|
+
"next_int_id": self.next_int_id,
|
|
109
|
+
}
|
|
110
|
+
with open(self.storage_dir / "cognition.json", "w", encoding="utf-8") as handle:
|
|
111
|
+
json.dump(payload, handle, ensure_ascii=False, indent=2)
|
|
112
|
+
self.faiss.save()
|
|
113
|
+
|
|
114
|
+
def _load(self) -> None:
|
|
115
|
+
data_file = self.storage_dir / "cognition.json"
|
|
116
|
+
if not data_file.exists():
|
|
117
|
+
return
|
|
118
|
+
with open(data_file, "r", encoding="utf-8") as handle:
|
|
119
|
+
payload = json.load(handle)
|
|
120
|
+
for item_id, raw_item in payload.get("items", {}).items():
|
|
121
|
+
self.items[item_id] = CognitionItem.from_dict(raw_item)
|
|
122
|
+
self.str_to_int = payload.get("str_to_int", {})
|
|
123
|
+
self.int_to_str = {int(key): value for key, value in payload.get("int_to_str", {}).items()}
|
|
124
|
+
self.next_int_id = payload.get("next_int_id", 0)
|
|
125
|
+
|
|
126
|
+
def __len__(self) -> int:
|
|
127
|
+
return len(self.items)
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"""Persistent node database for skill-driven evolution runs."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import copy
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
import tempfile
|
|
9
|
+
import time
|
|
10
|
+
from contextlib import contextmanager
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from threading import RLock
|
|
13
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
14
|
+
|
|
15
|
+
from .algorithms import get_sampler
|
|
16
|
+
from .embedding import EmbeddingService
|
|
17
|
+
from .file_lock import InterProcessFileLock
|
|
18
|
+
from .structures import Node
|
|
19
|
+
from .vector_index import FAISSIndex
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Database:
|
|
23
|
+
"""Persistent experiment database with sampler pluggability."""
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
storage_dir: Path,
|
|
28
|
+
embedding_model: str = "sentence-transformers/all-MiniLM-L6-v2",
|
|
29
|
+
embedding_dim: int = 384,
|
|
30
|
+
sampling_algorithm: str = "ucb1",
|
|
31
|
+
sampling_kwargs: Optional[Dict[str, Any]] = None,
|
|
32
|
+
faiss_index_type: str = "IP",
|
|
33
|
+
max_size: Optional[int] = None,
|
|
34
|
+
):
|
|
35
|
+
self.storage_dir = Path(storage_dir)
|
|
36
|
+
self.storage_dir.mkdir(parents=True, exist_ok=True)
|
|
37
|
+
self.lock = RLock()
|
|
38
|
+
self.lock_path = self.storage_dir / ".database.lock"
|
|
39
|
+
self.nodes: Dict[int, Node] = {}
|
|
40
|
+
self.next_id = 0
|
|
41
|
+
self.max_size = max_size
|
|
42
|
+
self.embedding_dim = embedding_dim
|
|
43
|
+
self.faiss_index_type = faiss_index_type
|
|
44
|
+
self.embedding = EmbeddingService(
|
|
45
|
+
model_name=embedding_model,
|
|
46
|
+
dimension=embedding_dim,
|
|
47
|
+
)
|
|
48
|
+
self.sampling_algorithm = sampling_algorithm
|
|
49
|
+
self.sampling_kwargs = sampling_kwargs or {}
|
|
50
|
+
self.default_sampler = get_sampler(sampling_algorithm, **self.sampling_kwargs)
|
|
51
|
+
self.faiss = self._build_faiss_index()
|
|
52
|
+
|
|
53
|
+
def sample(self, n: int, algorithm: Optional[str] = None, **kwargs) -> List[Node]:
|
|
54
|
+
with self._database_guard():
|
|
55
|
+
nodes = list(self.nodes.values())
|
|
56
|
+
sampler = (
|
|
57
|
+
get_sampler(algorithm, **kwargs) if algorithm else self.default_sampler
|
|
58
|
+
)
|
|
59
|
+
selected = sampler.sample(nodes, n)
|
|
60
|
+
self._save_locked()
|
|
61
|
+
return self._clone_nodes(selected)
|
|
62
|
+
|
|
63
|
+
def add(self, node: Node) -> int:
|
|
64
|
+
node_id, _ = self.add_with_previous_nodes(node)
|
|
65
|
+
return node_id
|
|
66
|
+
|
|
67
|
+
def add_with_previous_nodes(self, node: Node) -> Tuple[int, List[Node]]:
|
|
68
|
+
with self._database_guard():
|
|
69
|
+
previous_nodes = self._clone_nodes(self.nodes.values())
|
|
70
|
+
if self.max_size is not None and len(self.nodes) >= self.max_size:
|
|
71
|
+
self._remove_worst_node_locked()
|
|
72
|
+
|
|
73
|
+
node.id = self.next_id
|
|
74
|
+
self.next_id += 1
|
|
75
|
+
self.nodes[node.id] = node
|
|
76
|
+
if hasattr(self.default_sampler, "on_node_added"):
|
|
77
|
+
self.default_sampler.on_node_added(node)
|
|
78
|
+
|
|
79
|
+
context_text = node.get_context_text()
|
|
80
|
+
if context_text:
|
|
81
|
+
vector = self.embedding.encode(context_text)
|
|
82
|
+
self.faiss.add(node.id, vector)
|
|
83
|
+
|
|
84
|
+
self._save_locked()
|
|
85
|
+
return node.id, previous_nodes
|
|
86
|
+
|
|
87
|
+
def get_all(self) -> List[Node]:
|
|
88
|
+
with self._database_guard():
|
|
89
|
+
return self._clone_nodes(self.nodes.values())
|
|
90
|
+
|
|
91
|
+
def get(self, node_id: int) -> Optional[Node]:
|
|
92
|
+
with self._database_guard():
|
|
93
|
+
node = self.nodes.get(node_id)
|
|
94
|
+
if node is None:
|
|
95
|
+
return None
|
|
96
|
+
return self._clone_node(node)
|
|
97
|
+
|
|
98
|
+
def remove(self, node_id: int) -> bool:
|
|
99
|
+
with self._database_guard():
|
|
100
|
+
if node_id not in self.nodes:
|
|
101
|
+
return False
|
|
102
|
+
node = self.nodes[node_id]
|
|
103
|
+
if hasattr(self.default_sampler, "on_node_removed"):
|
|
104
|
+
self.default_sampler.on_node_removed(node)
|
|
105
|
+
del self.nodes[node_id]
|
|
106
|
+
self.faiss.remove(node_id)
|
|
107
|
+
self._save_locked()
|
|
108
|
+
return True
|
|
109
|
+
|
|
110
|
+
def reset(self) -> None:
|
|
111
|
+
with self._database_guard(refresh=False):
|
|
112
|
+
if hasattr(self.default_sampler, "reset"):
|
|
113
|
+
self.default_sampler.reset()
|
|
114
|
+
self.nodes.clear()
|
|
115
|
+
self.next_id = 0
|
|
116
|
+
self.faiss.reset()
|
|
117
|
+
data_file = self.storage_dir / "nodes.json"
|
|
118
|
+
if data_file.exists():
|
|
119
|
+
data_file.unlink()
|
|
120
|
+
|
|
121
|
+
def get_sampler_stats(self) -> Optional[Dict[str, Any]]:
|
|
122
|
+
_, sampler_stats = self.snapshot()
|
|
123
|
+
return sampler_stats
|
|
124
|
+
|
|
125
|
+
def snapshot(self) -> Tuple[List[Node], Optional[Dict[str, Any]]]:
|
|
126
|
+
with self._database_guard():
|
|
127
|
+
return self._clone_nodes(self.nodes.values()), self._get_sampler_stats_locked()
|
|
128
|
+
|
|
129
|
+
def _remove_worst_node_locked(self) -> None:
|
|
130
|
+
if not self.nodes:
|
|
131
|
+
return
|
|
132
|
+
worst_id = min(self.nodes, key=lambda node_id: (self.nodes[node_id].score, node_id))
|
|
133
|
+
node = self.nodes[worst_id]
|
|
134
|
+
if hasattr(self.default_sampler, "on_node_removed"):
|
|
135
|
+
self.default_sampler.on_node_removed(node)
|
|
136
|
+
del self.nodes[worst_id]
|
|
137
|
+
self.faiss.remove(worst_id)
|
|
138
|
+
|
|
139
|
+
def _save_locked(self) -> None:
|
|
140
|
+
payload = {
|
|
141
|
+
"next_id": self.next_id,
|
|
142
|
+
"nodes": {str(node_id): node.to_dict() for node_id, node in self.nodes.items()},
|
|
143
|
+
}
|
|
144
|
+
if hasattr(self.default_sampler, "get_state"):
|
|
145
|
+
payload["sampler_state"] = self.default_sampler.get_state()
|
|
146
|
+
|
|
147
|
+
temp_path: Optional[Path] = None
|
|
148
|
+
try:
|
|
149
|
+
with tempfile.NamedTemporaryFile(
|
|
150
|
+
mode="w",
|
|
151
|
+
encoding="utf-8",
|
|
152
|
+
dir=self.storage_dir,
|
|
153
|
+
prefix="nodes.",
|
|
154
|
+
suffix=".tmp",
|
|
155
|
+
delete=False,
|
|
156
|
+
) as handle:
|
|
157
|
+
json.dump(payload, handle, ensure_ascii=False, indent=2)
|
|
158
|
+
handle.flush()
|
|
159
|
+
os.fsync(handle.fileno())
|
|
160
|
+
temp_path = Path(handle.name)
|
|
161
|
+
|
|
162
|
+
os.replace(temp_path, self.storage_dir / "nodes.json")
|
|
163
|
+
finally:
|
|
164
|
+
if temp_path is not None and temp_path.exists():
|
|
165
|
+
temp_path.unlink(missing_ok=True)
|
|
166
|
+
|
|
167
|
+
self.faiss.save()
|
|
168
|
+
|
|
169
|
+
def _load_locked(self) -> None:
|
|
170
|
+
data_file = self.storage_dir / "nodes.json"
|
|
171
|
+
self.nodes = {}
|
|
172
|
+
self.next_id = 0
|
|
173
|
+
self.default_sampler = get_sampler(self.sampling_algorithm, **self.sampling_kwargs)
|
|
174
|
+
self.faiss = self._build_faiss_index()
|
|
175
|
+
if not data_file.exists():
|
|
176
|
+
return
|
|
177
|
+
with open(data_file, "r", encoding="utf-8") as handle:
|
|
178
|
+
payload = json.load(handle)
|
|
179
|
+
self.next_id = payload.get("next_id", 0)
|
|
180
|
+
for node_id, node_data in payload.get("nodes", {}).items():
|
|
181
|
+
self.nodes[int(node_id)] = Node.from_dict(node_data)
|
|
182
|
+
if hasattr(self.default_sampler, "load_state") and "sampler_state" in payload:
|
|
183
|
+
self.default_sampler.load_state(payload["sampler_state"])
|
|
184
|
+
if hasattr(self.default_sampler, "rebuild_from_nodes"):
|
|
185
|
+
self.default_sampler.rebuild_from_nodes(list(self.nodes.values()))
|
|
186
|
+
|
|
187
|
+
def _build_faiss_index(self) -> FAISSIndex:
|
|
188
|
+
return FAISSIndex(
|
|
189
|
+
dimension=self.embedding_dim,
|
|
190
|
+
index_type=self.faiss_index_type,
|
|
191
|
+
storage_path=self.storage_dir / "faiss",
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
def _get_sampler_stats_locked(self) -> Optional[Dict[str, Any]]:
|
|
195
|
+
if hasattr(self.default_sampler, "get_island_stats"):
|
|
196
|
+
return self.default_sampler.get_island_stats(list(self.nodes.values()))
|
|
197
|
+
return None
|
|
198
|
+
|
|
199
|
+
@staticmethod
|
|
200
|
+
def _clone_node(node: Node) -> Node:
|
|
201
|
+
return Node.from_dict(copy.deepcopy(node.to_dict()))
|
|
202
|
+
|
|
203
|
+
def _clone_nodes(self, nodes: List[Node] | Any) -> List[Node]:
|
|
204
|
+
return [self._clone_node(node) for node in nodes]
|
|
205
|
+
|
|
206
|
+
@contextmanager
|
|
207
|
+
def _database_guard(self, refresh: bool = True):
|
|
208
|
+
with self.lock:
|
|
209
|
+
with InterProcessFileLock(self.lock_path):
|
|
210
|
+
if refresh:
|
|
211
|
+
self._load_locked()
|
|
212
|
+
hold_ms = int(os.environ.get("EVOLVE_DB_TEST_HOLD_LOCK_MS", "0") or 0)
|
|
213
|
+
if hold_ms > 0:
|
|
214
|
+
time.sleep(hold_ms / 1000.0)
|
|
215
|
+
yield
|
|
216
|
+
|
|
217
|
+
def __len__(self) -> int:
|
|
218
|
+
return len(self.get_all())
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Helpers for diff-style code edits."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from difflib import unified_diff
|
|
7
|
+
from typing import List, Optional, Tuple
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def extract_diffs(
|
|
11
|
+
llm_response: str,
|
|
12
|
+
pattern: str = r"<<<<<<< SEARCH\n(.*?)=======\n(.*?)>>>>>>> REPLACE",
|
|
13
|
+
) -> List[Tuple[str, str]]:
|
|
14
|
+
matches = re.findall(pattern, llm_response, re.DOTALL)
|
|
15
|
+
return [(search.strip("\n"), replace.strip("\n")) for search, replace in matches]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def apply_diff(
|
|
19
|
+
original_code: str,
|
|
20
|
+
llm_response: str,
|
|
21
|
+
pattern: str = r"<<<<<<< SEARCH\n(.*?)=======\n(.*?)>>>>>>> REPLACE",
|
|
22
|
+
) -> str:
|
|
23
|
+
diff_blocks = extract_diffs(llm_response, pattern)
|
|
24
|
+
if not diff_blocks:
|
|
25
|
+
raise ValueError("No valid diff blocks found")
|
|
26
|
+
|
|
27
|
+
updated_code = original_code
|
|
28
|
+
for search, replace in diff_blocks:
|
|
29
|
+
if search not in updated_code:
|
|
30
|
+
raise ValueError("SEARCH block not found in target text")
|
|
31
|
+
updated_code = updated_code.replace(search, replace, 1)
|
|
32
|
+
return updated_code
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def parse_full_rewrite(llm_response: str, language: str = "python") -> Optional[str]:
|
|
36
|
+
pattern = rf"```{language}\n(.*?)```"
|
|
37
|
+
match = re.search(pattern, llm_response, re.DOTALL)
|
|
38
|
+
if match:
|
|
39
|
+
return match.group(1).strip()
|
|
40
|
+
stripped = llm_response.strip()
|
|
41
|
+
return stripped or None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def format_diff_summary(diff_blocks: List[Tuple[str, str]]) -> str:
|
|
45
|
+
parts: List[str] = []
|
|
46
|
+
for search, replace in diff_blocks:
|
|
47
|
+
lines = list(
|
|
48
|
+
unified_diff(
|
|
49
|
+
search.splitlines(),
|
|
50
|
+
replace.splitlines(),
|
|
51
|
+
fromfile="before",
|
|
52
|
+
tofile="after",
|
|
53
|
+
lineterm="",
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
parts.append("\n".join(lines))
|
|
57
|
+
return "\n\n".join(parts)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Embedding helpers with a graceful local fallback."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import math
|
|
6
|
+
import re
|
|
7
|
+
from typing import List, Union
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
from sentence_transformers import SentenceTransformer
|
|
13
|
+
|
|
14
|
+
ST_AVAILABLE = True
|
|
15
|
+
except Exception:
|
|
16
|
+
SentenceTransformer = None
|
|
17
|
+
ST_AVAILABLE = False
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class EmbeddingService:
|
|
21
|
+
"""Encode text with sentence-transformers when available, else hash tokens."""
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
model_name: str = "sentence-transformers/all-MiniLM-L6-v2",
|
|
26
|
+
device: str = "cpu",
|
|
27
|
+
dimension: int = 384,
|
|
28
|
+
):
|
|
29
|
+
self.dimension = dimension
|
|
30
|
+
self.model = None
|
|
31
|
+
|
|
32
|
+
if ST_AVAILABLE and SentenceTransformer is not None:
|
|
33
|
+
try:
|
|
34
|
+
self.model = SentenceTransformer(model_name, device=device)
|
|
35
|
+
self.dimension = self.model.get_sentence_embedding_dimension()
|
|
36
|
+
except Exception:
|
|
37
|
+
self.model = None
|
|
38
|
+
|
|
39
|
+
def encode(
|
|
40
|
+
self,
|
|
41
|
+
texts: Union[str, List[str]],
|
|
42
|
+
normalize: bool = True,
|
|
43
|
+
) -> np.ndarray:
|
|
44
|
+
if isinstance(texts, str):
|
|
45
|
+
texts = [texts]
|
|
46
|
+
|
|
47
|
+
if self.model is not None:
|
|
48
|
+
embeddings = self.model.encode(
|
|
49
|
+
texts,
|
|
50
|
+
normalize_embeddings=normalize,
|
|
51
|
+
show_progress_bar=False,
|
|
52
|
+
)
|
|
53
|
+
return np.array(embeddings, dtype=np.float32)
|
|
54
|
+
|
|
55
|
+
vectors = np.vstack([self._fallback_encode_one(text) for text in texts]).astype(
|
|
56
|
+
np.float32
|
|
57
|
+
)
|
|
58
|
+
if normalize:
|
|
59
|
+
vectors = self._normalize(vectors)
|
|
60
|
+
return vectors
|
|
61
|
+
|
|
62
|
+
def get_dimension(self) -> int:
|
|
63
|
+
return self.dimension
|
|
64
|
+
|
|
65
|
+
def _fallback_encode_one(self, text: str) -> np.ndarray:
|
|
66
|
+
vector = np.zeros(self.dimension, dtype=np.float32)
|
|
67
|
+
tokens = re.findall(r"[A-Za-z0-9_]+", text.lower())
|
|
68
|
+
if not tokens:
|
|
69
|
+
return vector
|
|
70
|
+
|
|
71
|
+
for token in tokens:
|
|
72
|
+
hashed = hash(token)
|
|
73
|
+
index = abs(hashed) % self.dimension
|
|
74
|
+
sign = -1.0 if hashed % 2 else 1.0
|
|
75
|
+
weight = 1.0 + math.log1p(len(token))
|
|
76
|
+
vector[index] += sign * weight
|
|
77
|
+
|
|
78
|
+
return vector
|
|
79
|
+
|
|
80
|
+
@staticmethod
|
|
81
|
+
def _normalize(vectors: np.ndarray) -> np.ndarray:
|
|
82
|
+
norms = np.linalg.norm(vectors, axis=1, keepdims=True)
|
|
83
|
+
norms[norms == 0] = 1.0
|
|
84
|
+
return vectors / norms
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Cross-process file locking helpers for the Evolve skill runtime."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
if os.name == "nt":
|
|
9
|
+
import msvcrt
|
|
10
|
+
else:
|
|
11
|
+
import fcntl
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class InterProcessFileLock:
|
|
15
|
+
"""Hold an exclusive lock on a sentinel file across processes."""
|
|
16
|
+
|
|
17
|
+
def __init__(self, path: Path):
|
|
18
|
+
self.path = Path(path)
|
|
19
|
+
self._handle = None
|
|
20
|
+
|
|
21
|
+
def __enter__(self) -> "InterProcessFileLock":
|
|
22
|
+
self.path.parent.mkdir(parents=True, exist_ok=True)
|
|
23
|
+
self._handle = open(self.path, "a+b")
|
|
24
|
+
self._handle.seek(0)
|
|
25
|
+
self._handle.write(b"\0")
|
|
26
|
+
self._handle.flush()
|
|
27
|
+
self._handle.seek(0)
|
|
28
|
+
|
|
29
|
+
if os.name == "nt":
|
|
30
|
+
msvcrt.locking(self._handle.fileno(), msvcrt.LK_LOCK, 1)
|
|
31
|
+
else:
|
|
32
|
+
fcntl.flock(self._handle.fileno(), fcntl.LOCK_EX)
|
|
33
|
+
return self
|
|
34
|
+
|
|
35
|
+
def __exit__(self, exc_type, exc, tb) -> None:
|
|
36
|
+
if self._handle is None:
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
self._handle.seek(0)
|
|
40
|
+
if os.name == "nt":
|
|
41
|
+
msvcrt.locking(self._handle.fileno(), msvcrt.LK_UNLCK, 1)
|
|
42
|
+
else:
|
|
43
|
+
fcntl.flock(self._handle.fileno(), fcntl.LOCK_UN)
|
|
44
|
+
self._handle.close()
|
|
45
|
+
self._handle = None
|