@sema-agent/server 7.147.0 → 7.149.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/MIGRATION.md +1468 -24
- package/README.md +35 -7
- package/README.zh-CN.md +18 -8
- package/USAGE.md +444 -193
- package/deploy/sema-up/README.md +16 -5
- package/deploy/sema-up/chart/templates/NOTES.txt +1 -1
- package/deploy/sema-up/chart/templates/_helpers.tpl +20 -4
- package/deploy/sema-up/chart/values.yaml +3 -2
- package/deploy/sema-up/cluster-up.sh +74 -176
- package/deploy/sema-up/kube-up.sh +29 -49
- package/deploy/sema-up/lib/chart-run.sh +23 -0
- package/deploy/sema-up/lib/dataroot.sh +3 -3
- package/deploy/sema-up/lib/health.sh +62 -13
- package/deploy/sema-up/lib/helm-values-cluster.py +18 -0
- package/deploy/sema-up/lib/helm-values-kube.py +35 -0
- package/deploy/sema-up/lib/regcred.py +8 -0
- package/deploy/sema-up/lib/remote/helm-install.sh +3 -0
- package/deploy/sema-up/lib/remote/image-import.sh +6 -0
- package/deploy/sema-up/lib/remote/machine-precheck.sh +11 -0
- package/deploy/sema-up/lib/remote/region-probe.sh +3 -0
- package/deploy/sema-up/lib/remote/stack-ready.sh +26 -0
- package/deploy/sema-up/lib/remote/vxlan-guard.sh +8 -0
- package/deploy/sema-up/lib/render-stack.py +17 -0
- package/deploy/sema-up/lib/shell-text.sh +87 -0
- package/deploy/sema-up/lib/usage-flags.txt +10 -0
- package/deploy/sema-up/lib/usage-head.txt +1 -0
- package/deploy/sema-up/lib/usage-tail.txt +13 -0
- package/deploy/sema-up/preflight.sh +10 -8
- package/deploy/sema-up/sema-up.sh +14 -39
- package/deploy/sema-up/smoke.sh +7 -6
- package/deploy/sema-up/stack/compose.dataroot.yaml +3 -0
- package/deploy/sema-up/stack/compose.yaml +13 -1
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +21 -0
- package/dist/adoption/plan.d.ts +24 -0
- package/dist/adoption/plan.js +53 -1
- package/dist/adoption/runner.d.ts +10 -1
- package/dist/adoption/runner.js +36 -16
- package/dist/approval-card.d.ts +36 -38
- package/dist/approval-gate-currency.js +3 -2
- package/dist/approval-leg-origin.d.ts +33 -0
- package/dist/approval-leg-origin.js +4 -0
- package/dist/approval-reconciler.d.ts +4 -13
- package/dist/approval-reconciler.js +2 -2
- package/dist/approval.d.ts +13 -11
- package/dist/approval.js +3 -3
- package/dist/audit.d.ts +10 -3
- package/dist/audit.js +15 -7
- package/dist/auth-bridge.d.ts +9 -15
- package/dist/auth-bridge.js +4 -11
- package/dist/auth-keys.d.ts +10 -1
- package/dist/auth-keys.js +8 -0
- package/dist/auto-mode-face.d.ts +10 -7
- package/dist/auto-mode-face.js +7 -4
- package/dist/background-agent-name.d.ts +19 -1
- package/dist/background-agent-name.js +12 -2
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/bake-runner/main.js +9 -6
- package/dist/bench/s1/arms.js +6 -5
- package/dist/bench/s1/live-deps.js +5 -2
- package/dist/bench/s1/run-firm.js +6 -5
- package/dist/bind-host.d.ts +25 -0
- package/dist/bind-host.js +25 -0
- package/dist/boot/adoption.d.ts +3 -0
- package/dist/boot/adoption.js +1 -0
- package/dist/boot/deployment-mods.d.ts +1 -1
- package/dist/boot/execution-env.d.ts +17 -7
- package/dist/boot/execution-env.js +47 -42
- package/dist/boot/execution-lane.d.ts +6 -4
- package/dist/boot/execution-lane.js +3 -1
- package/dist/boot/exit-boundary.d.ts +2 -2
- package/dist/boot/exit-boundary.js +6 -5
- package/dist/boot/fatal-exit.d.ts +3 -5
- package/dist/boot/fatal-exit.js +2 -2
- package/dist/boot/leader.d.ts +15 -0
- package/dist/boot/leader.js +17 -15
- package/dist/boot/memory-consolidation.d.ts +37 -29
- package/dist/boot/memory-consolidation.js +11 -5
- package/dist/boot/org-delivery.d.ts +3 -2
- package/dist/boot/org-memory.js +1 -1
- package/dist/boot/parked-revive-gate.js +2 -2
- package/dist/boot/reapers.d.ts +4 -3
- package/dist/boot/reapers.js +19 -16
- package/dist/boot/resolve-spec.d.ts +5 -3
- package/dist/boot/resolve-spec.js +60 -70
- package/dist/boot/retention-lane.d.ts +4 -4
- package/dist/boot/retention-lane.js +2 -2
- package/dist/boot/runner-deps.d.ts +28 -7
- package/dist/boot/runner-deps.js +14 -5
- package/dist/boot/runtime-caps.d.ts +2 -2
- package/dist/boot/runtime-caps.js +16 -2
- package/dist/boot/session-faces.d.ts +16 -7
- package/dist/boot/session-faces.js +114 -94
- package/dist/boot/shutdown.d.ts +5 -4
- package/dist/boot/shutdown.js +6 -4
- package/dist/boot/stage-01-config.d.ts +1 -0
- package/dist/boot/stage-01-config.js +13 -4
- package/dist/boot/stage-02-web-admin-pull.d.ts +2 -0
- package/dist/boot/stage-02-web-admin-pull.js +16 -3
- package/dist/boot/stage-03-store-backend.d.ts +4 -0
- package/dist/boot/stage-03-store-backend.js +4 -3
- package/dist/boot/stage-04-stores.d.ts +3 -0
- package/dist/boot/stage-04-stores.js +2 -2
- package/dist/boot/stage-05-execution-env.d.ts +8 -3
- package/dist/boot/stage-05-execution-env.js +2 -2
- package/dist/boot/stage-06-runners.d.ts +12 -13
- package/dist/boot/stage-06-runners.js +23 -15
- package/dist/boot/stage-07-capability-layer.d.ts +13 -9
- package/dist/boot/stage-07-capability-layer.js +5 -3
- package/dist/boot/stage-08-reapers.d.ts +13 -9
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +14 -16
- package/dist/boot/stage-09-leader.js +12 -4
- package/dist/boot/stage-10-http-server.d.ts +14 -16
- package/dist/boot/stage-10-http-server.js +7 -4
- package/dist/boot/store-evidence.d.ts +20 -0
- package/dist/boot/store-evidence.js +13 -0
- package/dist/boot/stores.d.ts +6 -0
- package/dist/boot/stores.js +41 -27
- package/dist/boot/task-list-lane.d.ts +4 -4
- package/dist/boot/web-admin.d.ts +4 -2
- package/dist/boot/web-admin.js +55 -35
- package/dist/boot/webfetch-summarize-lane.d.ts +1 -1
- package/dist/boot-reclaim.d.ts +3 -1
- package/dist/boot-reclaim.js +1 -1
- package/dist/brain.d.ts +7 -18
- package/dist/brain.js +5 -17
- package/dist/budget.js +6 -6
- package/dist/capabilities/center-plugins.d.ts +7 -1
- package/dist/capabilities/center-plugins.js +32 -10
- package/dist/capabilities/center-wiring.js +1 -1
- package/dist/capabilities/composite-members.d.ts +2 -2
- package/dist/capabilities/composite-members.js +2 -2
- package/dist/capabilities/repo-tools.d.ts +2 -0
- package/dist/capabilities/repo-tools.js +14 -12
- package/dist/capabilities/scenarios.d.ts +6 -15
- package/dist/capabilities/scenarios.js +11 -16
- package/dist/capabilities/skills.d.ts +1 -1
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/capability-facts.d.ts +39 -11
- package/dist/capability-facts.js +35 -7
- package/dist/card-settle-stored-scope.d.ts +56 -0
- package/dist/card-settle-stored-scope.js +27 -0
- package/dist/card-void.d.ts +8 -13
- package/dist/card-void.js +2 -7
- package/dist/center-credential-renewer.d.ts +6 -2
- package/dist/center-credential-renewer.js +7 -3
- package/dist/config-catalog.d.ts +28 -1
- package/dist/config-catalog.js +95 -85
- package/dist/config-dir-trust.d.ts +37 -4
- package/dist/config-dir-trust.js +88 -44
- package/dist/config-invariants.d.ts +43 -3
- package/dist/config-invariants.js +69 -5
- package/dist/config-lkg.d.ts +23 -1
- package/dist/config-lkg.js +17 -3
- package/dist/config-provider.d.ts +9 -9
- package/dist/config-provider.js +25 -110
- package/dist/config-pull-failure.d.ts +50 -0
- package/dist/config-pull-failure.js +48 -0
- package/dist/config-types.d.ts +62 -21
- package/dist/config.d.ts +14 -21
- package/dist/config.js +141 -64
- package/dist/context-window-notice.d.ts +31 -0
- package/dist/context-window-notice.js +28 -0
- package/dist/delegated-session-owner.d.ts +1 -1
- package/dist/deleted-session-ids.d.ts +3 -2
- package/dist/deployment-governance.d.ts +3 -3
- package/dist/deployment-shape.d.ts +46 -11
- package/dist/deployment-shape.js +8 -0
- package/dist/egress-redirect.d.ts +25 -7
- package/dist/egress-redirect.js +20 -2
- package/dist/elicitation.d.ts +6 -5
- package/dist/elicitation.js +23 -22
- package/dist/engine-identity.d.ts +28 -0
- package/dist/engine-identity.js +10 -0
- package/dist/entry-problems.d.ts +5 -7
- package/dist/entry-problems.js +1 -1
- package/dist/env-facts.js +2 -1
- package/dist/env-name-allowlist-knobs.d.ts +6 -5
- package/dist/env-name-allowlist-knobs.js +5 -0
- package/dist/env-witness.d.ts +7 -0
- package/dist/env-witness.js +16 -0
- package/dist/execution-lane-caps.d.ts +25 -23
- package/dist/execution-lane-caps.js +18 -26
- package/dist/execution-placement.d.ts +58 -18
- package/dist/execution-placement.js +41 -2
- package/dist/field-conflict.d.ts +7 -11
- package/dist/field-conflict.js +3 -3
- package/dist/file-history-capture.d.ts +3 -3
- package/dist/file-history-disclosure.js +1 -0
- package/dist/fleet/fleet-bus.d.ts +21 -3
- package/dist/fleet/fleet-bus.js +35 -25
- package/dist/fleet/fleet-reconciler.js +2 -2
- package/dist/fleet/serving-lease.js +3 -3
- package/dist/fleet-client.js +3 -3
- package/dist/fleet-lease.d.ts +0 -1
- package/dist/fleet-lease.js +4 -5
- package/dist/history-anchor.d.ts +23 -3
- package/dist/history-anchor.js +24 -4
- package/dist/hitl-delivery.d.ts +90 -0
- package/dist/hitl-delivery.js +98 -0
- package/dist/hooks/classic-stations.d.ts +8 -11
- package/dist/hooks/classic-stations.js +0 -7
- package/dist/hooks/command-spawn.d.ts +7 -2
- package/dist/hooks/command-spawn.js +13 -6
- package/dist/hooks/hook-llm.d.ts +5 -1
- package/dist/hooks/hook-llm.js +24 -15
- package/dist/hooks/hook-runner.d.ts +72 -57
- package/dist/hooks/hook-runner.js +271 -193
- package/dist/host-lsp-manager.d.ts +22 -8
- package/dist/host-lsp-manager.js +4 -1
- package/dist/http/active-run-conflict.d.ts +2 -43
- package/dist/http/active-run-conflict.js +3 -7
- package/dist/http/admission.d.ts +4 -18
- package/dist/http/admission.js +76 -79
- package/dist/http/approval-sweeps.d.ts +3 -3
- package/dist/http/approval-sweeps.js +56 -31
- package/dist/http/caller-trust.d.ts +8 -10
- package/dist/http/caller-trust.js +1 -2
- package/dist/http/claim-heartbeat.d.ts +49 -0
- package/dist/http/claim-heartbeat.js +46 -0
- package/dist/http/claimed-run.d.ts +16 -8
- package/dist/http/claimed-run.js +8 -0
- package/dist/http/dispatch.d.ts +8 -1
- package/dist/http/dispatch.js +78 -30
- package/dist/http/durable-run-leg.d.ts +11 -4
- package/dist/http/durable-run-leg.js +45 -21
- package/dist/http/execution-context.d.ts +122 -47
- package/dist/http/execution-context.js +135 -43
- package/dist/http/health-reader.d.ts +36 -0
- package/dist/http/health-reader.js +21 -0
- package/dist/http/health-self-report.d.ts +9 -9
- package/dist/http/health-self-report.js +4 -4
- package/dist/http/idempotency.d.ts +9 -5
- package/dist/http/idempotency.js +4 -4
- package/dist/http/memory-compliance-failure-reply.d.ts +15 -16
- package/dist/http/memory-compliance-failure-reply.js +4 -2
- package/dist/http/memory-face-fault-reply.d.ts +67 -0
- package/dist/http/memory-face-fault-reply.js +71 -0
- package/dist/http/memory-store-refusal-reply.d.ts +1 -1
- package/dist/http/memory-store-refusal-reply.js +3 -0
- package/dist/http/owner-access.d.ts +392 -67
- package/dist/http/owner-access.js +370 -35
- package/dist/http/principal-gate.d.ts +39 -89
- package/dist/http/principal-gate.js +26 -68
- package/dist/http/refusal-body.d.ts +35 -2
- package/dist/http/refusal-body.js +34 -0
- package/dist/http/request-guards.d.ts +9 -13
- package/dist/http/request-guards.js +34 -68
- package/dist/http/resume-composition.d.ts +37 -0
- package/dist/http/resume-composition.js +18 -0
- package/dist/http/resume-ctx-read.d.ts +46 -12
- package/dist/http/resume-ctx-read.js +31 -6
- package/dist/http/resume-legs.d.ts +54 -19
- package/dist/http/resume-legs.js +408 -196
- package/dist/http/retired-skill-manifest.d.ts +1 -1
- package/dist/http/route-ctx.d.ts +31 -32
- package/dist/http/routes/a2a-serve.d.ts +43 -5
- package/dist/http/routes/a2a-serve.js +60 -37
- package/dist/http/routes/admin-config-refresh.js +2 -2
- package/dist/http/routes/admin-drain.js +2 -2
- package/dist/http/routes/admin-memory-optout.js +4 -3
- package/dist/http/routes/adoption.d.ts +3 -0
- package/dist/http/routes/adoption.js +17 -10
- package/dist/http/routes/agents-roster.js +13 -7
- package/dist/http/routes/approvals-assistant.js +73 -67
- package/dist/http/routes/attachments.js +2 -2
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/background.js +9 -17
- package/dist/http/routes/capabilities.js +16 -19
- package/dist/http/routes/config-catalog.js +2 -2
- package/dist/http/routes/devices.d.ts +3 -3
- package/dist/http/routes/devices.js +4 -4
- package/dist/http/routes/diagnostics.d.ts +29 -3
- package/dist/http/routes/diagnostics.js +49 -18
- package/dist/http/routes/engine.js +2 -2
- package/dist/http/routes/fleet.js +5 -3
- package/dist/http/routes/images.js +10 -6
- package/dist/http/routes/leader.d.ts +7 -2
- package/dist/http/routes/leader.js +12 -3
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +7 -15
- package/dist/http/routes/memory-bundle.js +4 -7
- package/dist/http/routes/memory-compliance.js +4 -4
- package/dist/http/routes/memory-consolidation.js +6 -9
- package/dist/http/routes/memory-origin.d.ts +2 -0
- package/dist/http/routes/memory-origin.js +7 -8
- package/dist/http/routes/memory-policy.js +17 -12
- package/dist/http/routes/notify-wake.js +10 -19
- package/dist/http/routes/observability.js +3 -3
- package/dist/http/routes/principal-inbox.d.ts +4 -2
- package/dist/http/routes/principal-inbox.js +5 -4
- package/dist/http/routes/projects.d.ts +1 -1
- package/dist/http/routes/projects.js +3 -2
- package/dist/http/routes/retention-ops.js +6 -9
- package/dist/http/routes/rules.js +20 -5
- package/dist/http/routes/run-memory-capture.d.ts +2 -2
- package/dist/http/routes/run-memory-capture.js +6 -12
- package/dist/http/routes/run-permission-mode.d.ts +2 -2
- package/dist/http/routes/run-permission-mode.js +10 -17
- package/dist/http/routes/runs.js +155 -237
- package/dist/http/routes/session-memory-sync.d.ts +2 -2
- package/dist/http/routes/session-memory-sync.js +7 -13
- package/dist/http/routes/session-sync.d.ts +28 -7
- package/dist/http/routes/session-sync.js +63 -50
- package/dist/http/routes/sessions-list.d.ts +3 -3
- package/dist/http/routes/sessions-list.js +9 -9
- package/dist/http/routes/sessions.js +87 -124
- package/dist/http/routes/shared-memory.js +6 -6
- package/dist/http/routes/side-query.js +2 -2
- package/dist/http/routes/tasks.js +237 -187
- package/dist/http/routes/trace-usage.d.ts +0 -12
- package/dist/http/routes/trace-usage.js +40 -46
- package/dist/http/routes/workflows.d.ts +39 -4
- package/dist/http/routes/workflows.js +42 -14
- package/dist/http/run-concurrency-cap.d.ts +20 -12
- package/dist/http/run-concurrency-cap.js +39 -26
- package/dist/http/run-read-face.d.ts +3 -5
- package/dist/http/run-read-face.js +8 -13
- package/dist/http/send.d.ts +12 -3
- package/dist/http/send.js +42 -6
- package/dist/http/server.d.ts +43 -45
- package/dist/http/server.js +61 -11
- package/dist/http/sse-log.d.ts +17 -10
- package/dist/http/sse-log.js +7 -7
- package/dist/http/stored-body-replay.d.ts +12 -0
- package/dist/http/stored-body-replay.js +2 -2
- package/dist/http/submit-ctx.d.ts +17 -8
- package/dist/http/submit-ctx.js +8 -5
- package/dist/http/submit-replay.d.ts +19 -6
- package/dist/http/submit-replay.js +18 -6
- package/dist/http/sync-submit-body.d.ts +3 -4
- package/dist/http/sync-submit-body.js +4 -5
- package/dist/http/wire-types.d.ts +4 -3
- package/dist/identity-source.d.ts +36 -5
- package/dist/identity-source.js +27 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -0
- package/dist/key-resolver.d.ts +32 -0
- package/dist/key-resolver.js +23 -9
- package/dist/leader/diffup.js +2 -1
- package/dist/leader/endpoint.d.ts +26 -5
- package/dist/leader/endpoint.js +154 -14
- package/dist/leader/fanout.d.ts +3 -0
- package/dist/leader/fanout.js +78 -63
- package/dist/leader/leader.d.ts +16 -0
- package/dist/leader/leader.js +43 -3
- package/dist/leader/merge.d.ts +9 -1
- package/dist/leader/merge.js +16 -1
- package/dist/leader/repair-wire.js +1 -1
- package/dist/leader/wire.d.ts +36 -3
- package/dist/leader/wire.js +59 -18
- package/dist/leg-facts.d.ts +7 -2
- package/dist/leg-facts.js +1 -0
- package/dist/local-store-declaration.d.ts +54 -0
- package/dist/local-store-declaration.js +59 -0
- package/dist/lsp-evict.d.ts +6 -4
- package/dist/lsp-evict.js +2 -3
- package/dist/mcp-assertion-header.d.ts +1 -1
- package/dist/mcp-assertion-header.js +1 -1
- package/dist/memory-operator-faces.d.ts +5 -4
- package/dist/memory-operator-faces.js +1 -1
- package/dist/memory-project-layer.js +1 -1
- package/dist/memory-scope.d.ts +33 -6
- package/dist/memory-scope.js +68 -19
- package/dist/memory-store-refusal.d.ts +5 -2
- package/dist/memory-sync-client.d.ts +3 -2
- package/dist/memory-sync-client.js +8 -5
- package/dist/model-compat.d.ts +17 -8
- package/dist/model-compat.js +6 -2
- package/dist/model-context-window.d.ts +57 -0
- package/dist/model-context-window.js +21 -0
- package/dist/model-entry-headers.d.ts +46 -4
- package/dist/model-entry-headers.js +2 -2
- package/dist/model-entry-refusal.d.ts +40 -20
- package/dist/model-entry-refusal.js +57 -30
- package/dist/model-plane-face.d.ts +19 -11
- package/dist/model-plane-face.js +9 -1
- package/dist/model-plane-probe.d.ts +2 -0
- package/dist/model-plane-probe.js +17 -0
- package/dist/model-provider.d.ts +3 -3
- package/dist/model-reach-scope.d.ts +2 -1
- package/dist/model-route-endpoint.d.ts +9 -5
- package/dist/model-route-endpoint.js +29 -7
- package/dist/model-select.d.ts +16 -0
- package/dist/model-select.js +4 -0
- package/dist/mountinfo.d.ts +37 -0
- package/dist/mountinfo.js +47 -0
- package/dist/namespaced-rule-name.d.ts +23 -14
- package/dist/namespaced-rule-name.js +8 -11
- package/dist/net-address.d.ts +1 -1
- package/dist/observability/corrupt-read-seat.d.ts +4 -4
- package/dist/observability/corrupt-read-seat.js +5 -3
- package/dist/observability/fail-open.d.ts +72 -40
- package/dist/observability/fail-open.js +74 -40
- package/dist/observability/logger.d.ts +22 -1
- package/dist/observability/logger.js +89 -12
- package/dist/observability/metrics.js +4 -5
- package/dist/observability/otel-exporter.js +2 -1
- package/dist/observability/principal-context.d.ts +14 -7
- package/dist/observability/principal-context.js +8 -3
- package/dist/observability/run-terminal.d.ts +7 -1
- package/dist/observability/run-terminal.js +6 -2
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/secret-env-scrub.js +1 -1
- package/dist/orchestration/hardened-vm-runner.d.ts +1 -0
- package/dist/orchestration/hardened-vm-runner.js +11 -5
- package/dist/orchestration/hardened-vm-worker-runner.d.ts +0 -14
- package/dist/orchestration/hardened-vm-worker-runner.js +5 -0
- package/dist/orchestration/hardened-vm-worker.js +2 -1
- package/dist/orchestration/workflow-completion-inbox.d.ts +3 -3
- package/dist/orchestration/workflow-completion-inbox.js +3 -2
- package/dist/org-delivery-gate.d.ts +36 -10
- package/dist/org-delivery-gate.js +12 -8
- package/dist/outbound-dispatcher.d.ts +1 -1
- package/dist/outbound-dispatcher.js +6 -12
- package/dist/owner-brands.d.ts +81 -0
- package/dist/owner-brands.js +42 -0
- package/dist/owner-faces.d.ts +532 -0
- package/dist/owner-faces.js +126 -0
- package/dist/park-row-commit.d.ts +67 -0
- package/dist/park-row-commit.js +76 -0
- package/dist/parked-decide.d.ts +76 -12
- package/dist/parked-decide.js +152 -11
- package/dist/parked-revive-surface.d.ts +14 -4
- package/dist/parked-revive-surface.js +5 -4
- package/dist/peer-directory.d.ts +7 -9
- package/dist/peer-directory.js +3 -2
- package/dist/permission-rule-vocab.d.ts +53 -8
- package/dist/permission-rule-vocab.js +30 -2
- package/dist/plugins/adoption-log-sql.d.ts +3 -25
- package/dist/plugins/adoption-log-sql.js +23 -21
- package/dist/plugins/approval-ask-retired-delete-by-task-m50.d.ts +7 -0
- package/dist/plugins/approval-ask-retired-delete-by-task-m50.js +17 -0
- package/dist/plugins/approval-ask-store-file.d.ts +18 -7
- package/dist/plugins/approval-ask-store-file.js +37 -14
- package/dist/plugins/approval-ask-store-memory.d.ts +12 -4
- package/dist/plugins/approval-ask-store-memory.js +24 -10
- package/dist/plugins/approval-ask-store-sql.d.ts +40 -21
- package/dist/plugins/approval-ask-store-sql.js +44 -15
- package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
- package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
- package/dist/plugins/approval-exemption-skill-m46.d.ts +14 -0
- package/dist/plugins/approval-exemption-skill-m46.js +21 -0
- package/dist/plugins/approval-exemption-store.d.ts +32 -2
- package/dist/plugins/approval-exemption-store.js +42 -19
- package/dist/plugins/approval-nonce-store.d.ts +39 -12
- package/dist/plugins/approval-nonce-store.js +72 -23
- package/dist/plugins/blob-backend.d.ts +2 -0
- package/dist/plugins/blob-backend.js +9 -6
- package/dist/plugins/caching-session-store.d.ts +13 -1
- package/dist/plugins/caching-session-store.js +43 -4
- package/dist/plugins/checkpoint-index-columns.d.ts +32 -5
- package/dist/plugins/checkpoint-index-columns.js +36 -1
- package/dist/plugins/checkpoint-store-face.d.ts +83 -10
- package/dist/plugins/checkpoint-store-face.js +18 -1
- package/dist/plugins/device-store-sql.js +1 -0
- package/dist/plugins/ensure-index.d.ts +13 -1
- package/dist/plugins/ensure-index.js +154 -21
- package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -18
- package/dist/plugins/ensure-schema-lock-policy.js +76 -9
- package/dist/plugins/file-run-store.d.ts +85 -32
- package/dist/plugins/file-run-store.js +177 -94
- package/dist/plugins/host-platform.d.ts +24 -3
- package/dist/plugins/host-platform.js +15 -1
- package/dist/plugins/image-bake-store-sql.js +2 -0
- package/dist/plugins/imported-layer-root-retirement.d.ts +2 -2
- package/dist/plugins/k8s-pod-reaper.d.ts +1 -3
- package/dist/plugins/k8s-pod-reaper.js +0 -1
- package/dist/plugins/leader-run-store-sql.d.ts +22 -0
- package/dist/plugins/leader-run-store-sql.js +34 -4
- package/dist/plugins/local-checkpoint-store.d.ts +62 -23
- package/dist/plugins/local-checkpoint-store.js +197 -77
- package/dist/plugins/local-data-dir-modes-m39.js +2 -1
- package/dist/plugins/local-data-root-admission.d.ts +52 -0
- package/dist/plugins/local-data-root-admission.js +100 -0
- package/dist/plugins/local-docker-capacity.d.ts +93 -0
- package/dist/plugins/local-docker-capacity.js +194 -0
- package/dist/plugins/local-docker-reaper.d.ts +92 -0
- package/dist/plugins/local-docker-reaper.js +102 -0
- package/dist/plugins/local-engine-high-water.d.ts +29 -6
- package/dist/plugins/local-engine-high-water.js +27 -19
- package/dist/plugins/local-session-store.d.ts +458 -140
- package/dist/plugins/local-session-store.js +906 -292
- package/dist/plugins/local-session-window.d.ts +3 -2
- package/dist/plugins/local-session-window.js +3 -2
- package/dist/plugins/local-sidecar-quarantine.js +3 -2
- package/dist/plugins/local-task-attachment-store.d.ts +18 -1
- package/dist/plugins/local-task-attachment-store.js +22 -1
- package/dist/plugins/memory-embedder.js +9 -7
- package/dist/plugins/memory-engine-pg.d.ts +3 -2
- package/dist/plugins/memory-engine-pg.js +14 -5
- package/dist/plugins/memory-engine-sql-apply.d.ts +8 -4
- package/dist/plugins/memory-engine-sql-apply.js +6 -8
- package/dist/plugins/memory-engine-tidb.d.ts +4 -2
- package/dist/plugins/memory-engine-tidb.js +11 -2
- package/dist/plugins/memory-optout-grant-store-sql.d.ts +1 -1
- package/dist/plugins/memory-optout-grant-store-sql.js +3 -3
- package/dist/plugins/memory-run-store.d.ts +53 -36
- package/dist/plugins/memory-run-store.js +116 -88
- package/dist/plugins/one-time-migration-marker.d.ts +26 -0
- package/dist/plugins/one-time-migration-marker.js +13 -0
- package/dist/plugins/one-time-migrations.d.ts +214 -47
- package/dist/plugins/one-time-migrations.js +481 -135
- package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
- package/dist/plugins/org-delivery-quota-store.js +31 -15
- package/dist/plugins/permission-rule-store-file.d.ts +3 -3
- package/dist/plugins/permission-rule-store-sql.d.ts +5 -64
- package/dist/plugins/permission-rule-store-sql.js +11 -95
- package/dist/plugins/pg-pool.d.ts +2 -32
- package/dist/plugins/pg-pool.js +24 -17
- package/dist/plugins/remote-env-device.d.ts +3 -2
- package/dist/plugins/remote-env-e2b.d.ts +8 -32
- package/dist/plugins/remote-env-e2b.js +44 -32
- package/dist/plugins/remote-env-host.d.ts +51 -17
- package/dist/plugins/remote-env-host.js +111 -42
- package/dist/plugins/remote-env-k8s.d.ts +40 -45
- package/dist/plugins/remote-env-k8s.js +111 -60
- package/dist/plugins/remote-env-local-docker.d.ts +152 -15
- package/dist/plugins/remote-env-local-docker.js +352 -72
- package/dist/plugins/remote-scratchpad.js +4 -0
- package/dist/plugins/retention-deployment.d.ts +49 -17
- package/dist/plugins/retention-deployment.js +39 -8
- package/dist/plugins/run-preview-m45.d.ts +11 -0
- package/dist/plugins/run-preview-m45.js +19 -0
- package/dist/plugins/run-store-sql.d.ts +82 -75
- package/dist/plugins/run-store-sql.js +164 -125
- package/dist/plugins/s3-answer.d.ts +2 -1
- package/dist/plugins/sandbox-reaper.d.ts +26 -0
- package/dist/plugins/sandbox-reaper.js +2 -0
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +56 -0
- package/dist/plugins/scenario-prefix-switch-m42.js +56 -0
- package/dist/plugins/scheduler-support.d.ts +16 -1
- package/dist/plugins/scheduler-support.js +22 -2
- package/dist/plugins/schema-consistency.d.ts +131 -14
- package/dist/plugins/schema-consistency.js +388 -18
- package/dist/plugins/schema-drift-sentence.d.ts +10 -6
- package/dist/plugins/schema-drift-sentence.js +15 -7
- package/dist/plugins/schema-ensure-legs.d.ts +9 -0
- package/dist/plugins/schema-ensure-legs.js +1 -1
- package/dist/plugins/schema-indexes.js +3 -0
- package/dist/plugins/schema-live-columns.d.ts +14 -5
- package/dist/plugins/schema-live-columns.js +10 -10
- package/dist/plugins/send-user-file.js +2 -1
- package/dist/plugins/session-birth.d.ts +37 -0
- package/dist/plugins/session-birth.js +38 -0
- package/dist/plugins/session-epoch-anchor.d.ts +40 -12
- package/dist/plugins/session-epoch-anchor.js +33 -11
- package/dist/plugins/session-ext-table.d.ts +27 -3
- package/dist/plugins/session-ext-table.js +19 -6
- package/dist/plugins/session-fork.d.ts +15 -1
- package/dist/plugins/session-fork.js +3 -0
- package/dist/plugins/session-ownership.d.ts +1 -1
- package/dist/plugins/session-placement.d.ts +27 -20
- package/dist/plugins/session-placement.js +15 -12
- package/dist/plugins/session-row-sql.d.ts +12 -0
- package/dist/plugins/session-row-sql.js +3 -3
- package/dist/plugins/session-run-rollup.d.ts +29 -0
- package/dist/plugins/session-run-rollup.js +40 -0
- package/dist/plugins/session-store-sql.d.ts +38 -12
- package/dist/plugins/session-store-sql.js +130 -30
- package/dist/plugins/session-withdraw-sql.d.ts +36 -0
- package/dist/plugins/session-withdraw-sql.js +42 -0
- package/dist/plugins/shared-memory-store-sql.d.ts +0 -69
- package/dist/plugins/shared-memory-store-sql.js +2 -1
- package/dist/plugins/shell-sentinel-owner-m48.d.ts +42 -0
- package/dist/plugins/shell-sentinel-owner-m48.js +9 -0
- package/dist/plugins/snapshot-bucket-presence.d.ts +2 -1
- package/dist/plugins/sql-driver.d.ts +1 -1
- package/dist/plugins/sql-driver.js +2 -1
- package/dist/plugins/sql-errors.d.ts +32 -5
- package/dist/plugins/sql-errors.js +55 -7
- package/dist/plugins/sql-json-column.d.ts +8 -7
- package/dist/plugins/sql-json-column.js +10 -6
- package/dist/plugins/stop-then-start-sentence.d.ts +16 -0
- package/dist/plugins/stop-then-start-sentence.js +7 -0
- package/dist/plugins/store-backend.d.ts +99 -16
- package/dist/plugins/store-backend.js +230 -65
- package/dist/plugins/store-contracts.d.ts +123 -33
- package/dist/plugins/store-contracts.js +38 -1
- package/dist/plugins/store-fault.d.ts +28 -2
- package/dist/plugins/store-fault.js +20 -2
- package/dist/plugins/task-attachment-store.d.ts +15 -3
- package/dist/plugins/task-attachment-store.js +22 -9
- package/dist/plugins/tidb-pool.d.ts +11 -6
- package/dist/plugins/tidb-pool.js +39 -18
- package/dist/plugins/web-search.js +5 -3
- package/dist/plugins/workflow-run-store-sql.d.ts +6 -1
- package/dist/plugins/workflow-run-store-sql.js +11 -5
- package/dist/plugins/workspace-custody.d.ts +44 -0
- package/dist/plugins/workspace-custody.js +47 -0
- package/dist/principal-jwt.d.ts +4 -4
- package/dist/principal-jwt.js +20 -5
- package/dist/principal-shape.d.ts +41 -0
- package/dist/principal-shape.js +19 -0
- package/dist/project-identity.d.ts +8 -7
- package/dist/project-identity.js +40 -17
- package/dist/project-layer-key.d.ts +13 -2
- package/dist/project-layer-key.js +9 -1
- package/dist/question.d.ts +13 -23
- package/dist/question.js +21 -39
- package/dist/read-deny-floor-notice.d.ts +36 -0
- package/dist/read-deny-floor-notice.js +40 -0
- package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
- package/dist/request-declaration-disposition.js +39 -0
- package/dist/request-declaration-refusal.d.ts +35 -12
- package/dist/request-declaration-refusal.js +21 -9
- package/dist/request-form.d.ts +58 -0
- package/dist/request-form.js +72 -0
- package/dist/request-image-urls.d.ts +8 -2
- package/dist/request-image-urls.js +2 -1
- package/dist/request-images.d.ts +20 -0
- package/dist/request-images.js +59 -0
- package/dist/request-key-closure.d.ts +6 -7
- package/dist/request-key-closure.js +15 -2
- package/dist/resource-suspend.d.ts +7 -16
- package/dist/resource-suspend.js +1 -1
- package/dist/retired-name-host-notice.d.ts +21 -0
- package/dist/retired-name-host-notice.js +12 -0
- package/dist/rule-entry-list.d.ts +2 -2
- package/dist/rule-entry-list.js +3 -4
- package/dist/rule-issue-reading.d.ts +58 -0
- package/dist/rule-issue-reading.js +14 -0
- package/dist/rules-consent.d.ts +5 -3
- package/dist/rules-consent.js +1 -0
- package/dist/run-acceptance.d.ts +3 -1
- package/dist/run-acceptance.js +3 -0
- package/dist/run-cancel-card.d.ts +28 -0
- package/dist/run-cancel-card.js +19 -0
- package/dist/run-cancel-context.d.ts +10 -0
- package/dist/run-cancel-context.js +1 -0
- package/dist/run-local.d.ts +14 -6
- package/dist/run-local.js +117 -90
- package/dist/run-stale-default.d.ts +7 -0
- package/dist/run-stale-default.js +2 -0
- package/dist/runs.d.ts +56 -21
- package/dist/runs.js +73 -43
- package/dist/runtime-caps-resolver.d.ts +21 -6
- package/dist/runtime-caps-resolver.js +17 -4
- package/dist/runtime-governance.d.ts +2 -2
- package/dist/runtime-governance.js +5 -3
- package/dist/sealed-key-layout.d.ts +12 -5
- package/dist/sealed-key-layout.js +5 -0
- package/dist/sealed-key.d.ts +12 -2
- package/dist/sealed-key.js +115 -27
- package/dist/security.d.ts +128 -158
- package/dist/security.js +163 -59
- package/dist/sema-config-dir.d.ts +20 -0
- package/dist/sema-config-dir.js +25 -0
- package/dist/server-secret-env.d.ts +55 -25
- package/dist/server-secret-env.js +75 -22
- package/dist/session-agent.d.ts +3 -2
- package/dist/session-children-retire.d.ts +13 -8
- package/dist/session-children-retire.js +9 -7
- package/dist/session-deletion.d.ts +88 -0
- package/dist/session-deletion.js +8 -0
- package/dist/session-erase.d.ts +145 -0
- package/dist/session-erase.js +115 -0
- package/dist/session-error-wire.d.ts +5 -5
- package/dist/session-error-wire.js +1 -1
- package/dist/session-incarnation.d.ts +52 -5
- package/dist/session-incarnation.js +19 -2
- package/dist/session-policy-wire.d.ts +6 -3
- package/dist/session-policy-wire.js +11 -1
- package/dist/session-resident-background.d.ts +0 -71
- package/dist/session-resident-background.js +4 -3
- package/dist/session-row.d.ts +2 -1
- package/dist/session-rules-seat.d.ts +12 -0
- package/dist/session-rules-seat.js +19 -0
- package/dist/session-titler.d.ts +7 -15
- package/dist/session-titler.js +1 -1
- package/dist/session-workspace.d.ts +3 -3
- package/dist/spec-fields.d.ts +57 -3
- package/dist/spec-fields.js +72 -51
- package/dist/store-admission.d.ts +33 -0
- package/dist/store-admission.js +49 -0
- package/dist/store-posture.d.ts +141 -20
- package/dist/store-posture.js +205 -3
- package/dist/stored-request-hooks-m20.js +2 -2
- package/dist/stores-sql/background-agent-store-sql.d.ts +11 -2
- package/dist/stores-sql/background-agent-store-sql.js +73 -20
- package/dist/stores-sql/checkpoint-store-sql.d.ts +34 -29
- package/dist/stores-sql/checkpoint-store-sql.js +78 -49
- package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
- package/dist/stores-sql/file-history-store-sql.js +3 -5
- package/dist/stores-sql/mailbox-store-sql.d.ts +7 -4
- package/dist/stores-sql/mailbox-store-sql.js +31 -32
- package/dist/stores-sql/pg-session-storage.d.ts +7 -5
- package/dist/stores-sql/pg-session-storage.js +54 -46
- package/dist/stores-sql/retention-store-sql.d.ts +87 -19
- package/dist/stores-sql/retention-store-sql.js +92 -27
- package/dist/stores-sql/session-policy-store-sql.d.ts +32 -10
- package/dist/stores-sql/session-policy-store-sql.js +44 -36
- package/dist/stores-sql/session-write-hooks.d.ts +12 -6
- package/dist/stores-sql/tidb-session-storage.d.ts +4 -4
- package/dist/stores-sql/tidb-session-storage.js +13 -8
- package/dist/stores-sql/tidb-session-store.d.ts +36 -17
- package/dist/stores-sql/tidb-session-store.js +69 -39
- package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.js +4 -6
- package/dist/stores-sql/windowed-session-storage.d.ts +5 -0
- package/dist/stores-sql/windowed-session-storage.js +9 -0
- package/dist/submission-exit.d.ts +50 -0
- package/dist/submission-exit.js +108 -0
- package/dist/task-a2a.d.ts +3 -8
- package/dist/task-a2a.js +28 -30
- package/dist/task-cwd.d.ts +43 -7
- package/dist/task-cwd.js +11 -0
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-mcp.js +4 -4
- package/dist/task-settings.d.ts +14 -10
- package/dist/task-settings.js +19 -7
- package/dist/terminal.d.ts +27 -43
- package/dist/terminal.js +49 -14
- package/dist/tool-approval.d.ts +173 -163
- package/dist/tool-approval.js +247 -232
- package/dist/trace/core-keyset-guard.d.ts +13 -6
- package/dist/trace/core-vocab-wire.d.ts +95 -0
- package/dist/trace/core-vocab-wire.js +15 -0
- package/dist/trace/engine-notice-wire.d.ts +24 -21
- package/dist/trace/engine-notice-wire.js +7 -3
- package/dist/trace/exit-seat.d.ts +30 -4
- package/dist/trace/exit-seat.js +40 -36
- package/dist/trace/extension-call-face.d.ts +3 -2
- package/dist/trace/extension-call-face.js +3 -1
- package/dist/trace/ledger-events.d.ts +4 -7
- package/dist/trace/ledger-sink.d.ts +4 -31
- package/dist/trace/ledger-sink.js +0 -11
- package/dist/trace/model-segment.d.ts +5 -5
- package/dist/trace/model-segment.js +5 -5
- package/dist/trace/project.d.ts +59 -44
- package/dist/trace/project.js +60 -26
- package/dist/trace/redact.d.ts +135 -27
- package/dist/trace/redact.js +884 -260
- package/dist/trace/self-minted-wire.d.ts +567 -20
- package/dist/trace/self-minted-wire.js +205 -24
- package/dist/trace/wire-projection-faces.d.ts +5 -6
- package/dist/trace/wire-projection-faces.js +2 -2
- package/dist/upstream-body.d.ts +23 -0
- package/dist/upstream-body.js +16 -0
- package/dist/url-refusal.d.ts +3 -3
- package/dist/url-refusal.js +11 -4
- package/dist/user-authored-text.d.ts +1 -1
- package/dist/user-input-ledger.d.ts +7 -8
- package/dist/user-input-ledger.js +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +6 -3
- package/dist/web-admin-client/apply-effective.js +33 -23
- package/dist/web-admin-client/apply-ledger.d.ts +16 -7
- package/dist/web-admin-client/apply-ledger.js +5 -2
- package/dist/web-admin-client/center-request.d.ts +2 -2
- package/dist/web-admin-client/center-request.js +15 -15
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/effective-keys.js +1 -1
- package/dist/web-admin-client/entry-metadata.d.ts +8 -0
- package/dist/web-admin-client/entry-metadata.js +13 -0
- package/dist/web-admin-client/http-client.d.ts +1 -1
- package/dist/web-admin-client/http-client.js +23 -4
- package/dist/web-admin-client/mcp-revocation.d.ts +1 -1
- package/dist/web-admin-client/mcp-revocation.js +2 -1
- package/dist/web-admin-client/read-warnings.d.ts +1 -0
- package/dist/web-admin-client/read-warnings.js +1 -0
- package/dist/web-admin-client/restart-signal.js +8 -4
- package/dist/web-admin-client/skills-mcp.d.ts +2 -2
- package/dist/web-admin-client/types.d.ts +1 -2
- package/dist/workspace-space.d.ts +3 -2
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +4 -4
- package/docs/error-text-lexicon.json +317 -0
- package/package.json +8 -3
- package/scripts/drain-check-local.mjs +118 -147
- package/scripts/drain-check.mysql.sql +22 -2
- package/scripts/drain-check.pg.sql +22 -2
- package/scripts/embed-minimal.mjs +183 -0
- package/wire-changes/server@7.148.0.json +1517 -0
- package/wire-changes/server@7.149.0.json +372 -0
- package/dist/http/memory-control-plane-corrupt-reply.d.ts +0 -25
- package/dist/http/memory-control-plane-corrupt-reply.js +0 -19
- package/dist/http/memory-layer-reply.d.ts +0 -30
- package/dist/http/memory-layer-reply.js +0 -24
- package/dist/lsp/e2b-bridge.d.ts +0 -57
- package/dist/lsp/e2b-bridge.js +0 -139
- package/dist/lsp/e2b-manager.d.ts +0 -93
- package/dist/lsp/e2b-manager.js +0 -178
- package/dist/lsp/lsp-frames.d.ts +0 -14
- package/dist/lsp/lsp-frames.js +0 -25
- package/dist/lsp/manager.d.ts +0 -129
- package/dist/lsp/manager.js +0 -127
- package/dist/lsp/types.d.ts +0 -12
- package/dist/lsp/types.js +0 -2
- package/dist/lsp/ws-transport.d.ts +0 -40
- package/dist/lsp/ws-transport.js +0 -210
- package/dist/plain-string-record.js +0 -70
|
@@ -2,8 +2,9 @@ import path from "node:path";
|
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
3
|
import { hostSubprocessEnv } from "../server-secret-env.js";
|
|
4
4
|
import { LANE_HOME_PROBE_COMMAND, LaneHomeSeat } from "../lane-home-probe.js";
|
|
5
|
-
import { randomBytes } from "node:crypto";
|
|
5
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
6
6
|
import { shellQuote, armPipeDestroyGrace, appendFileStaged, readyUpload, writeFileStaged } from "./remote-shell.js";
|
|
7
|
+
import { createWorkspaceCustody } from "./workspace-custody.js";
|
|
7
8
|
import { signalNumber } from "./host-platform.js";
|
|
8
9
|
import { buildLivenessCut, commandBoundsOf } from "../exec-bounds.js";
|
|
9
10
|
import { buildCapturedOutput, createCutError } from "../exec-cut.js";
|
|
@@ -16,6 +17,12 @@ const PROVIDER = "local-docker";
|
|
|
16
17
|
const DEFAULT_MOUNT_PATH = "/workspace";
|
|
17
18
|
const DEFAULT_COMMAND_TIMEOUT_MS = 30 * 60_000;
|
|
18
19
|
const DEFAULT_CONTROL_TIMEOUT_MS = 60_000;
|
|
20
|
+
const INSPECT_ID_STATE_AND_LABELS = "{{.Id}}\t{{.State.Status}}\t{{json .Config.Labels}}";
|
|
21
|
+
const DOCKER_STATES = ["created", "running", "paused", "restarting", "removing", "exited", "dead"];
|
|
22
|
+
const NO_CUSTODY = Object.freeze({ kind: "none" });
|
|
23
|
+
function isNameConflict(stderr, name) {
|
|
24
|
+
return stderr.includes(`The container name "/${name}" is already in use`);
|
|
25
|
+
}
|
|
19
26
|
const ok = (value) => ({ ok: true, value });
|
|
20
27
|
const unsupported = (op) => ({
|
|
21
28
|
ok: false,
|
|
@@ -33,12 +40,18 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
33
40
|
cfg;
|
|
34
41
|
spawnFn;
|
|
35
42
|
containerName;
|
|
43
|
+
custody;
|
|
36
44
|
containerId;
|
|
45
|
+
removedAny = false;
|
|
46
|
+
teardown;
|
|
47
|
+
teardownSettled = false;
|
|
37
48
|
handle;
|
|
38
49
|
destroyed = false;
|
|
39
50
|
connecting;
|
|
40
51
|
connectRefusal;
|
|
41
52
|
homeSeat;
|
|
53
|
+
lifecycle = new AbortController();
|
|
54
|
+
capacityDeadline;
|
|
42
55
|
constructor(config, deps = {}) {
|
|
43
56
|
if (!config.image || !config.image.trim()) {
|
|
44
57
|
config = { ...config, image: config.image ?? "" };
|
|
@@ -56,9 +69,24 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
56
69
|
this.spawnFn = deps.spawn ?? spawn;
|
|
57
70
|
this.floor = deps.readFloor ?? createSandboxReadFloor({ lane: PROVIDER, knob: config.sandboxReadFloor });
|
|
58
71
|
this.capabilities = capabilitiesFor({ remoteExec: { provider: PROVIDER }, sandboxReadFloor: config.sandboxReadFloor });
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
72
|
+
this.containerName = localDockerContainerNameOf(config.workerLabel, config.id ?? randomBytes(6).toString("hex"));
|
|
73
|
+
this.custody = config.leftover ?? NO_CUSTODY;
|
|
74
|
+
}
|
|
75
|
+
get instance() {
|
|
76
|
+
return this.custody.kind === "held" ? this.custody.id : undefined;
|
|
77
|
+
}
|
|
78
|
+
get leftover() {
|
|
79
|
+
const c = this.custody;
|
|
80
|
+
return c.kind === "doomed" || c.kind === "doomed-unknown" ? c : undefined;
|
|
81
|
+
}
|
|
82
|
+
get releasing() {
|
|
83
|
+
return this.teardown;
|
|
84
|
+
}
|
|
85
|
+
get released() {
|
|
86
|
+
return this.teardownSettled;
|
|
87
|
+
}
|
|
88
|
+
get settled() {
|
|
89
|
+
return this.teardownSettled && this.leftover === undefined;
|
|
62
90
|
}
|
|
63
91
|
resolve(p) {
|
|
64
92
|
return path.posix.isAbsolute(p) ? path.posix.normalize(p) : path.posix.normalize(path.posix.join(this.cwd, p));
|
|
@@ -77,18 +105,142 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
77
105
|
return { ok: false, error: new RemoteExecutionError("aborted", "connect aborted") };
|
|
78
106
|
if (this.containerId)
|
|
79
107
|
return ok(this.workspaceHandle());
|
|
108
|
+
return this.connectOnce(config, "start-or-attach");
|
|
109
|
+
}
|
|
110
|
+
async connectOnce(config, mode) {
|
|
80
111
|
if (this.connecting)
|
|
81
112
|
return this.connecting;
|
|
82
|
-
this.connecting = this.doConnect(config);
|
|
113
|
+
this.connecting = this.doConnect(config, mode);
|
|
83
114
|
const r = await this.connecting;
|
|
84
115
|
if (!r.ok)
|
|
85
116
|
this.connecting = undefined;
|
|
86
117
|
return r;
|
|
87
118
|
}
|
|
88
|
-
async doConnect(config) {
|
|
89
|
-
if (!this.cfg.image.trim()) {
|
|
119
|
+
async doConnect(config, mode) {
|
|
120
|
+
if (mode === "start-or-attach" && !this.cfg.image.trim()) {
|
|
90
121
|
return { ok: false, error: new RemoteExecutionError("connect_failed", "local-docker: no base image configured (the image is required — no docker.io default)") };
|
|
91
122
|
}
|
|
123
|
+
const owed = this.custody;
|
|
124
|
+
if (owed.kind === "doomed" && !(await this.removeInstance(owed.id)))
|
|
125
|
+
return this.stillOwed(owed.id);
|
|
126
|
+
let seen = await this.sightContainer(config?.abortSignal);
|
|
127
|
+
if (this.custody.kind === "doomed-unknown") {
|
|
128
|
+
switch (seen.kind) {
|
|
129
|
+
case "unreadable":
|
|
130
|
+
return { ok: false, error: seen.error };
|
|
131
|
+
case "ours":
|
|
132
|
+
if (!(await this.removeInstance(seen.id)))
|
|
133
|
+
return this.stillOwed(seen.id);
|
|
134
|
+
seen = { kind: "absent" };
|
|
135
|
+
break;
|
|
136
|
+
case "absent":
|
|
137
|
+
this.custody = NO_CUSTODY;
|
|
138
|
+
this.cfg.capacity?.removed(this.containerName);
|
|
139
|
+
break;
|
|
140
|
+
case "foreign":
|
|
141
|
+
this.custody = NO_CUSTODY;
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
switch (seen.kind) {
|
|
146
|
+
case "unreadable":
|
|
147
|
+
return { ok: false, error: seen.error };
|
|
148
|
+
case "foreign":
|
|
149
|
+
return { ok: false, error: new RemoteExecutionError("connect_failed", `a container named '${this.containerName}' exists on the docker daemon but this worker did not start it (it does not carry the label ${this.cfg.workerLabel}) — nothing was started or removed; remove or rename that container`) };
|
|
150
|
+
case "absent":
|
|
151
|
+
return mode === "attach-only" ? this.notResumable("gone") : this.startContainer(config);
|
|
152
|
+
case "ours":
|
|
153
|
+
switch (seen.state) {
|
|
154
|
+
case "running":
|
|
155
|
+
return this.attachContainer(seen.id, config?.abortSignal);
|
|
156
|
+
case "exited": {
|
|
157
|
+
const admitted = await this.admitStart(config);
|
|
158
|
+
if (!admitted.ok)
|
|
159
|
+
return admitted;
|
|
160
|
+
this.custody = { kind: "held", id: seen.id };
|
|
161
|
+
const started = await this.docker(["start", seen.id], { signal: config?.abortSignal, timeoutMs: this.cfg.controlTimeoutMs });
|
|
162
|
+
admitted.ticket?.settle(this.startOutcomeOf(started));
|
|
163
|
+
if (!started.ok)
|
|
164
|
+
return { ok: false, error: this.dockerToRemoteError(started.error, "connect_failed") };
|
|
165
|
+
if (started.value.exitCode !== 0)
|
|
166
|
+
return { ok: false, error: new RemoteExecutionError("connect_failed", `container '${this.containerName}' of this worker is exited and docker start failed: ${started.value.stderr.trim() || `exit ${started.value.exitCode}`} — nothing was removed`) };
|
|
167
|
+
return this.attachContainer(seen.id, config?.abortSignal);
|
|
168
|
+
}
|
|
169
|
+
case "created": {
|
|
170
|
+
if (mode === "attach-only")
|
|
171
|
+
return this.notResumable("created, never started");
|
|
172
|
+
if (!(await this.removeInstance(seen.id))) {
|
|
173
|
+
return { ok: false, error: new RemoteExecutionError("connect_failed", `container '${this.containerName}' of this worker was created but never started and could not be removed — nothing was started; remove it and retry`) };
|
|
174
|
+
}
|
|
175
|
+
return this.startContainer(config);
|
|
176
|
+
}
|
|
177
|
+
case "paused":
|
|
178
|
+
case "restarting":
|
|
179
|
+
case "removing":
|
|
180
|
+
case "dead":
|
|
181
|
+
return { ok: false, error: new RemoteExecutionError("connect_failed", `container '${this.containerName}' of this worker is ${seen.state} — it was neither attached nor removed (its workspace may still be there); resolve it with docker and retry`) };
|
|
182
|
+
default: {
|
|
183
|
+
const unhandled = seen.state;
|
|
184
|
+
throw new Error(`local-docker: no ruling for container state ${String(unhandled)}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
stillOwed(id) {
|
|
190
|
+
return { ok: false, error: new RemoteExecutionError("connect_failed", `container ${id.slice(0, 12)} of this worker ('${this.containerName}') is due for removal and docker rm could not confirm it — it is never attached; nothing was started; remove it and retry`) };
|
|
191
|
+
}
|
|
192
|
+
notResumable(why) {
|
|
193
|
+
return { ok: false, error: new RemoteExecutionError("connect_failed", `container '${this.containerName}' is not running (${why}) — no managed snapshot to resume`) };
|
|
194
|
+
}
|
|
195
|
+
async sightContainer(signal) {
|
|
196
|
+
const r = await this.docker(["inspect", "--type", "container", "--format", INSPECT_ID_STATE_AND_LABELS, this.containerName], { signal, timeoutMs: this.cfg.controlTimeoutMs });
|
|
197
|
+
if (!r.ok)
|
|
198
|
+
return { kind: "unreadable", error: this.dockerToRemoteError(r.error, "connect_failed") };
|
|
199
|
+
if (r.value.exitCode !== 0) {
|
|
200
|
+
return /no such (object|container)/i.test(r.value.stderr)
|
|
201
|
+
? { kind: "absent" }
|
|
202
|
+
: { kind: "unreadable", error: new RemoteExecutionError("connect_failed", `docker inspect of '${this.containerName}' failed: ${r.value.stderr.trim() || `exit ${r.value.exitCode}`}`) };
|
|
203
|
+
}
|
|
204
|
+
const line = r.value.stdout.trim();
|
|
205
|
+
const [id = "", state = "", ...rest] = line.split("\t");
|
|
206
|
+
let labels;
|
|
207
|
+
try {
|
|
208
|
+
labels = rest.length === 1 ? JSON.parse(rest[0]) : undefined;
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
labels = undefined;
|
|
212
|
+
}
|
|
213
|
+
const known = DOCKER_STATES.find((s) => s === state);
|
|
214
|
+
if (!/^[0-9a-f]{12,64}$/.test(id) || known === undefined || labels === undefined || (labels !== null && typeof labels !== "object")) {
|
|
215
|
+
return { kind: "unreadable", error: new RemoteExecutionError("connect_failed", `docker inspect of '${this.containerName}' answered a form this adapter does not read (${JSON.stringify(line.slice(0, 160))}) — nothing was started or removed`) };
|
|
216
|
+
}
|
|
217
|
+
const ours = labels !== null && Object.entries(labels).some(([k, v]) => `${k}=${String(v)}` === this.cfg.workerLabel);
|
|
218
|
+
return ours ? { kind: "ours", id, state: known } : { kind: "foreign" };
|
|
219
|
+
}
|
|
220
|
+
async attachContainer(id, signal) {
|
|
221
|
+
this.custody = { kind: "held", id };
|
|
222
|
+
if (this.homeSeat.asks && !(await this.untilOrAborted(this.probeContainerShell(), signal))) {
|
|
223
|
+
return { ok: false, error: new RemoteExecutionError("aborted", "connect aborted while detecting the container's shell") };
|
|
224
|
+
}
|
|
225
|
+
const home = await this.homeVerdict(signal);
|
|
226
|
+
if (home !== undefined)
|
|
227
|
+
return { ok: false, error: home };
|
|
228
|
+
await this.floor.attach(this.floorTransport(), { origin: "resumed", workspaceRoot: this.cfg.mountPath });
|
|
229
|
+
if (this.destroyed)
|
|
230
|
+
return { ok: false, error: new RemoteExecutionError("connect_failed", "execution env destroyed during connect") };
|
|
231
|
+
const filled = await this.fillWorkspace("restored");
|
|
232
|
+
if (!filled.ok) {
|
|
233
|
+
if (filled.standing)
|
|
234
|
+
this.connectRefusal = filled.error;
|
|
235
|
+
return { ok: false, error: filled.error };
|
|
236
|
+
}
|
|
237
|
+
if (this.destroyed)
|
|
238
|
+
return { ok: false, error: new RemoteExecutionError("connect_failed", "execution env destroyed during connect") };
|
|
239
|
+
this.containerId = id;
|
|
240
|
+
this.handle = { sandboxId: this.containerName, provider: PROVIDER, mountPath: this.cfg.mountPath, sessionToken: this.containerName };
|
|
241
|
+
return ok(this.handle);
|
|
242
|
+
}
|
|
243
|
+
async startContainer(config) {
|
|
92
244
|
const pidsLimit = this.cfg.pidsLimit ?? 512;
|
|
93
245
|
const runArgs = [
|
|
94
246
|
"run",
|
|
@@ -96,6 +248,7 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
96
248
|
"--init",
|
|
97
249
|
"--name",
|
|
98
250
|
this.containerName,
|
|
251
|
+
"--label", this.cfg.workerLabel,
|
|
99
252
|
"-w",
|
|
100
253
|
this.cfg.mountPath,
|
|
101
254
|
"--security-opt",
|
|
@@ -110,48 +263,71 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
110
263
|
"-c",
|
|
111
264
|
`mkdir -p ${shellQuote(this.cfg.mountPath)} && exec tail -f /dev/null`,
|
|
112
265
|
];
|
|
266
|
+
const admitted = await this.admitStart(config);
|
|
267
|
+
if (!admitted.ok)
|
|
268
|
+
return admitted;
|
|
113
269
|
const run = await this.docker(runArgs, { signal: config?.abortSignal, timeoutMs: this.cfg.controlTimeoutMs });
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
270
|
+
const outcome = this.startOutcomeOf(run);
|
|
271
|
+
admitted.ticket?.settle(outcome);
|
|
272
|
+
const id = run.ok && run.value.exitCode === 0 ? run.value.stdout.trim() : "";
|
|
273
|
+
if (id === "") {
|
|
274
|
+
if (outcome !== "absent")
|
|
275
|
+
await this.claimLeftoverOfThisStart();
|
|
276
|
+
const error = !run.ok ? this.dockerToRemoteError(run.error, "connect_failed") : new RemoteExecutionError("connect_failed", `docker run failed: ${run.value.stderr.trim() || (run.value.exitCode === 0 ? "it printed no container id" : `exit ${run.value.exitCode}`)}`);
|
|
277
|
+
return { ok: false, error };
|
|
121
278
|
}
|
|
279
|
+
this.custody = { kind: "held", id };
|
|
122
280
|
if (this.destroyed) {
|
|
123
|
-
await this.
|
|
281
|
+
await this.removeInstance(id);
|
|
124
282
|
return { ok: false, error: new RemoteExecutionError("connect_failed", "execution env destroyed during connect") };
|
|
125
283
|
}
|
|
126
284
|
if (this.homeSeat.asks && !(await this.untilOrAborted(this.probeContainerShell(), config?.abortSignal))) {
|
|
127
|
-
await this.
|
|
285
|
+
await this.removeInstance(id);
|
|
128
286
|
return { ok: false, error: new RemoteExecutionError("aborted", "connect aborted while detecting the container's shell") };
|
|
129
287
|
}
|
|
130
288
|
const home = await this.homeVerdict(config?.abortSignal);
|
|
131
289
|
if (home !== undefined) {
|
|
132
|
-
await this.
|
|
290
|
+
await this.removeInstance(id);
|
|
133
291
|
return { ok: false, error: home };
|
|
134
292
|
}
|
|
135
293
|
await this.floor.attach(this.floorTransport(), { origin: "created", workspaceRoot: this.cfg.mountPath });
|
|
136
294
|
if (this.destroyed) {
|
|
137
|
-
await this.
|
|
295
|
+
await this.removeInstance(id);
|
|
138
296
|
return { ok: false, error: new RemoteExecutionError("connect_failed", "execution env destroyed during connect") };
|
|
139
297
|
}
|
|
140
|
-
const filled = await this.fillWorkspace();
|
|
298
|
+
const filled = await this.fillWorkspace("minted");
|
|
141
299
|
if (!filled.ok || this.destroyed) {
|
|
142
|
-
await this.
|
|
300
|
+
await this.removeInstance(id);
|
|
143
301
|
if (!filled.ok && filled.standing)
|
|
144
302
|
this.connectRefusal = filled.error;
|
|
145
303
|
return { ok: false, error: filled.ok ? new RemoteExecutionError("connect_failed", "execution env destroyed during connect") : filled.error };
|
|
146
304
|
}
|
|
147
|
-
this.containerId =
|
|
305
|
+
this.containerId = id;
|
|
148
306
|
this.handle = { sandboxId: this.containerName, provider: PROVIDER, mountPath: this.cfg.mountPath, sessionToken: this.containerName };
|
|
149
307
|
if (config?.secrets?.length) {
|
|
150
308
|
}
|
|
151
309
|
return ok(this.handle);
|
|
152
310
|
}
|
|
153
|
-
|
|
154
|
-
|
|
311
|
+
async admitStart(config) {
|
|
312
|
+
const capacity = this.cfg.capacity;
|
|
313
|
+
if (capacity === undefined)
|
|
314
|
+
return { ok: true };
|
|
315
|
+
this.capacityDeadline ??= Date.now() + this.cfg.controlTimeoutMs;
|
|
316
|
+
const signal = config?.abortSignal ? AbortSignal.any([config.abortSignal, this.lifecycle.signal]) : this.lifecycle.signal;
|
|
317
|
+
const admitted = await capacity.admit({ name: this.containerName, read: (budgetMs, readSignal) => this.readLaneRegistry(budgetMs, readSignal), deadline: this.capacityDeadline, readBoundMs: this.cfg.controlTimeoutMs, signal });
|
|
318
|
+
if (!admitted.ok)
|
|
319
|
+
return { ok: false, error: new RemoteExecutionError(admitted.refusal.verdict === "aborted" ? "aborted" : "connect_failed", admitted.refusal.message) };
|
|
320
|
+
return { ok: true, ticket: admitted.ticket };
|
|
321
|
+
}
|
|
322
|
+
startOutcomeOf(r) {
|
|
323
|
+
if (!r.ok)
|
|
324
|
+
return r.error.code === "spawn_error" ? "absent" : "unknown";
|
|
325
|
+
if (r.value.exitCode === 0)
|
|
326
|
+
return "present";
|
|
327
|
+
return isNameConflict(r.value.stderr, this.containerName) ? "absent" : "unknown";
|
|
328
|
+
}
|
|
329
|
+
fillWorkspace(origin) {
|
|
330
|
+
return this.cfg.workspaceFill === undefined ? Promise.resolve({ ok: true }) : this.cfg.workspaceFill.fill(this.fillChannel(), this.cfg.mountPath, origin);
|
|
155
331
|
}
|
|
156
332
|
fillChannel() {
|
|
157
333
|
const run = async (command, input) => {
|
|
@@ -201,47 +377,100 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
201
377
|
if (sessionToken && sessionToken !== this.containerName) {
|
|
202
378
|
return { ok: false, error: new RemoteExecutionError("connect_failed", `reconnect token '${String(sessionToken)}' does not match this env's container '${this.containerName}'`) };
|
|
203
379
|
}
|
|
204
|
-
if (this.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
this.
|
|
219
|
-
this.
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
380
|
+
if (this.containerId === undefined)
|
|
381
|
+
return this.connectOnce(undefined, "attach-only");
|
|
382
|
+
const seen = await this.sightContainer(undefined);
|
|
383
|
+
if (seen.kind === "ours" && seen.state === "running" && seen.id === this.containerId)
|
|
384
|
+
return ok(this.workspaceHandle());
|
|
385
|
+
if (seen.kind === "unreadable")
|
|
386
|
+
return { ok: false, error: seen.error };
|
|
387
|
+
return this.notResumable(seen.kind === "absent" ? "gone" : seen.kind === "foreign" ? "the name now holds a container this worker did not start" : seen.id !== this.containerId ? "the name now holds another container" : seen.state);
|
|
388
|
+
}
|
|
389
|
+
destroy() {
|
|
390
|
+
this.teardown ??= (async () => {
|
|
391
|
+
this.destroyed = true;
|
|
392
|
+
this.lifecycle.abort();
|
|
393
|
+
const inflight = this.connecting;
|
|
394
|
+
this.connecting = undefined;
|
|
395
|
+
this.containerId = undefined;
|
|
396
|
+
await inflight?.catch(() => { });
|
|
397
|
+
this.floor.dispose();
|
|
398
|
+
const owed = this.custody;
|
|
399
|
+
switch (owed.kind) {
|
|
400
|
+
case "held":
|
|
401
|
+
case "doomed":
|
|
402
|
+
await this.removeInstance(owed.id);
|
|
403
|
+
break;
|
|
404
|
+
case "doomed-unknown":
|
|
405
|
+
await this.claimLeftoverOfThisStart();
|
|
406
|
+
break;
|
|
407
|
+
case "none":
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
})().finally(() => {
|
|
411
|
+
this.teardownSettled = true;
|
|
412
|
+
});
|
|
413
|
+
return this.teardown;
|
|
234
414
|
}
|
|
235
415
|
async cleanup() {
|
|
236
416
|
return this.destroy();
|
|
237
417
|
}
|
|
238
|
-
async
|
|
239
|
-
|
|
418
|
+
async reapWorkspace() {
|
|
419
|
+
if (this.custody.kind === "none")
|
|
420
|
+
this.custody = { kind: "doomed-unknown" };
|
|
421
|
+
await this.destroy();
|
|
422
|
+
return this.leftover !== undefined ? "owed" : this.removedAny ? "removed" : "nothing";
|
|
423
|
+
}
|
|
424
|
+
async removeInstance(id) {
|
|
425
|
+
this.custody = { kind: "doomed", id };
|
|
426
|
+
const r = await this.docker(["rm", "-f", id], { timeoutMs: this.cfg.controlTimeoutMs }).catch(() => undefined);
|
|
427
|
+
const removed = r?.ok === true && (r.value.exitCode === 0 || /no such container/i.test(r.value.stderr));
|
|
428
|
+
if (r?.ok === true && r.value.exitCode === 0)
|
|
429
|
+
this.removedAny = true;
|
|
430
|
+
if (removed) {
|
|
431
|
+
this.cfg.capacity?.removed(this.containerName);
|
|
432
|
+
if (this.custody.kind === "doomed" && this.custody.id === id)
|
|
433
|
+
this.custody = NO_CUSTODY;
|
|
434
|
+
}
|
|
435
|
+
return removed;
|
|
436
|
+
}
|
|
437
|
+
async claimLeftoverOfThisStart() {
|
|
438
|
+
const seen = await this.sightContainer(undefined);
|
|
439
|
+
switch (seen.kind) {
|
|
440
|
+
case "ours":
|
|
441
|
+
await this.removeInstance(seen.id);
|
|
442
|
+
return;
|
|
443
|
+
case "absent":
|
|
444
|
+
this.custody = NO_CUSTODY;
|
|
445
|
+
this.cfg.capacity?.removed(this.containerName);
|
|
446
|
+
return;
|
|
447
|
+
case "foreign":
|
|
448
|
+
this.custody = NO_CUSTODY;
|
|
449
|
+
return;
|
|
450
|
+
case "unreadable":
|
|
451
|
+
this.custody = { kind: "doomed-unknown" };
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
async readLaneRegistry(budgetMs, signal) {
|
|
456
|
+
const r = await this.docker(["ps", "-a", "--filter", `label=${this.cfg.workerLabel}`, "--format", "{{.Names}}\t{{.State}}"], { timeoutMs: Math.max(1, budgetMs), ...(signal !== undefined ? { signal } : {}) });
|
|
457
|
+
if (!r.ok)
|
|
458
|
+
return { ok: false, reason: r.error.message };
|
|
459
|
+
if (r.value.exitCode !== 0)
|
|
460
|
+
return { ok: false, reason: r.value.stderr.trim() || `exit ${r.value.exitCode}` };
|
|
461
|
+
const rows = r.value.stdout
|
|
462
|
+
.split("\n")
|
|
463
|
+
.filter((line) => line.trim().length > 0)
|
|
464
|
+
.map((line) => {
|
|
465
|
+
const [name = "", state = ""] = line.split("\t");
|
|
466
|
+
return { name: name.trim(), state: state.trim().toLowerCase() };
|
|
467
|
+
});
|
|
468
|
+
return { ok: true, rows };
|
|
240
469
|
}
|
|
241
470
|
async exec(command, options) {
|
|
242
471
|
if (options?.abortSignal?.aborted)
|
|
243
472
|
return { ok: false, error: new ExecutionError("aborted", "exec aborted before start") };
|
|
244
|
-
const ready = await this.ensureConnectedExec();
|
|
473
|
+
const ready = await this.ensureConnectedExec(options?.abortSignal);
|
|
245
474
|
if (!ready.ok)
|
|
246
475
|
return ready;
|
|
247
476
|
const execArgs = this.startArgv(engineStart(options?.readFloor), command, { cwd: options?.cwd, env: options?.env });
|
|
@@ -258,9 +487,9 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
258
487
|
return ok({ stdout: r.value.stdout, stderr: r.value.stderr, exitCode: r.value.exitCode });
|
|
259
488
|
}
|
|
260
489
|
async *execStream(command, options) {
|
|
261
|
-
const ready = await this.ensureConnectedExec();
|
|
490
|
+
const ready = await this.ensureConnectedExec(options?.signal);
|
|
262
491
|
if (!ready.ok)
|
|
263
|
-
throw new RemoteExecutionError("connect_failed", ready.error.message, ready.error);
|
|
492
|
+
throw new RemoteExecutionError(ready.error.code === "aborted" ? "aborted" : "connect_failed", ready.error.message, ready.error);
|
|
264
493
|
const execArgs = this.startArgv(engineStart(undefined), command, { cwd: options?.cwd, env: options?.env });
|
|
265
494
|
if (!execArgs.ok)
|
|
266
495
|
throw new RemoteExecutionError("unsupported", execArgs.error.message, execArgs.error);
|
|
@@ -392,7 +621,7 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
392
621
|
return ok(path.posix.join(...parts));
|
|
393
622
|
}
|
|
394
623
|
async readBinaryFile(p, abortSignal) {
|
|
395
|
-
const ready = await this.fsReady(p);
|
|
624
|
+
const ready = await this.fsReady(p, abortSignal);
|
|
396
625
|
if (!ready.ok)
|
|
397
626
|
return ready;
|
|
398
627
|
const abs = this.resolve(p);
|
|
@@ -423,13 +652,13 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
423
652
|
return { prepare: readyUpload((dest, signal) => this.pipeIn(content, dest, signal)), run: (cmd, signal) => this.fsExec(cmd, signal), provider: PROVIDER, logger: this.cfg.logger };
|
|
424
653
|
}
|
|
425
654
|
async writeFile(p, content, abortSignal) {
|
|
426
|
-
const ready = await this.fsReady(p);
|
|
655
|
+
const ready = await this.fsReady(p, abortSignal);
|
|
427
656
|
if (!ready.ok)
|
|
428
657
|
return ready;
|
|
429
658
|
return writeFileStaged(this.stagedLane(content), this.resolve(p), abortSignal);
|
|
430
659
|
}
|
|
431
660
|
async appendFile(p, content, abortSignal) {
|
|
432
|
-
const ready = await this.fsReady(p);
|
|
661
|
+
const ready = await this.fsReady(p, abortSignal);
|
|
433
662
|
if (!ready.ok)
|
|
434
663
|
return ready;
|
|
435
664
|
const abs = this.resolve(p);
|
|
@@ -455,7 +684,9 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
455
684
|
if (this.destroyed)
|
|
456
685
|
return { ok: false, error: new ExecutionError("shell_unavailable", "execution env already destroyed") };
|
|
457
686
|
if (!this.containerId) {
|
|
458
|
-
const c = await this.
|
|
687
|
+
const c = await this.joinConnect(abortSignal);
|
|
688
|
+
if (!c.ok && c.error.code === "aborted" && abortSignal?.aborted)
|
|
689
|
+
return { ok: false, error: new ExecutionError("aborted", "exec aborted before start (file operation; the container was still connecting)", c.error) };
|
|
459
690
|
if (!c.ok)
|
|
460
691
|
return { ok: false, error: new ExecutionError("shell_unavailable", `local-docker connect failed: ${c.error.message}`, c.error) };
|
|
461
692
|
}
|
|
@@ -512,7 +743,9 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
512
743
|
for (const [k, v] of Object.entries(mergedEnv))
|
|
513
744
|
args.push("-e", `${k}=${v}`);
|
|
514
745
|
}
|
|
515
|
-
|
|
746
|
+
if (this.instance === undefined)
|
|
747
|
+
return { ok: false, error: new ExecutionError("shell_unavailable", "no container instance is held by this execution env") };
|
|
748
|
+
args.push(this.instance, ...floorArgv(launch.value, [o.shell ?? this.containerShell, "-c", command]));
|
|
516
749
|
return ok(args);
|
|
517
750
|
}
|
|
518
751
|
floorTransport() {
|
|
@@ -538,7 +771,12 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
538
771
|
return r.value.exitCode === 0 ? { ok: true } : { ok: false, error: r.value.stderr.trim() || `exit ${r.value.exitCode}` };
|
|
539
772
|
},
|
|
540
773
|
openRelay: (identity, command, events) => {
|
|
541
|
-
const
|
|
774
|
+
const instance = this.instance;
|
|
775
|
+
if (instance === undefined) {
|
|
776
|
+
queueMicrotask(() => events.closed("no container instance is held by this execution env"));
|
|
777
|
+
return { send: () => { }, close: () => { } };
|
|
778
|
+
}
|
|
779
|
+
const args = ["exec", "-i", ...dockerIdentityFlags({ mode: "control", identity }), instance, "/bin/sh", "-c", command];
|
|
542
780
|
const child = this.spawnFn(this.cfg.dockerPath, this.withHostFlag(args), { stdio: ["pipe", "pipe", "pipe"], env: this.cliEnv() });
|
|
543
781
|
let closed = false;
|
|
544
782
|
const close = (why) => {
|
|
@@ -567,7 +805,14 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
567
805
|
return new Promise((resolve) => {
|
|
568
806
|
let settled = false;
|
|
569
807
|
let forceSettleTimer;
|
|
570
|
-
|
|
808
|
+
let child;
|
|
809
|
+
try {
|
|
810
|
+
child = this.spawnFn(this.cfg.dockerPath, this.withHostFlag(args), { stdio: [opts?.input !== undefined ? "pipe" : "ignore", "pipe", "pipe"], env: this.cliEnv() });
|
|
811
|
+
}
|
|
812
|
+
catch (e) {
|
|
813
|
+
resolve({ ok: false, error: new ExecutionError("spawn_error", `docker spawn failed (is '${this.cfg.dockerPath}' installed?): ${errMsg(e)}`, e instanceof Error ? e : undefined) });
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
571
816
|
const killGrace = () => {
|
|
572
817
|
try {
|
|
573
818
|
child.kill("SIGKILL");
|
|
@@ -635,6 +880,21 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
635
880
|
});
|
|
636
881
|
});
|
|
637
882
|
}
|
|
883
|
+
joinConnect(signal) {
|
|
884
|
+
const shared = this.connect();
|
|
885
|
+
if (signal === undefined)
|
|
886
|
+
return shared;
|
|
887
|
+
if (signal.aborted)
|
|
888
|
+
return Promise.resolve({ ok: false, error: new RemoteExecutionError("aborted", "aborted while connecting") });
|
|
889
|
+
return new Promise((resolve) => {
|
|
890
|
+
const onAbort = () => resolve({ ok: false, error: new RemoteExecutionError("aborted", "aborted while connecting") });
|
|
891
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
892
|
+
void shared.then((r) => {
|
|
893
|
+
signal.removeEventListener("abort", onAbort);
|
|
894
|
+
resolve(r);
|
|
895
|
+
});
|
|
896
|
+
});
|
|
897
|
+
}
|
|
638
898
|
containerShell = "/bin/sh";
|
|
639
899
|
containerShellReady;
|
|
640
900
|
async untilOrAborted(shared, signal) {
|
|
@@ -668,25 +928,27 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
668
928
|
catch {
|
|
669
929
|
}
|
|
670
930
|
}
|
|
671
|
-
async ensureConnectedExec() {
|
|
931
|
+
async ensureConnectedExec(signal) {
|
|
672
932
|
if (this.destroyed)
|
|
673
933
|
return { ok: false, error: new ExecutionError("shell_unavailable", "execution env already destroyed") };
|
|
674
934
|
if (this.containerId) {
|
|
675
935
|
await this.probeContainerShell();
|
|
676
936
|
return ok(undefined);
|
|
677
937
|
}
|
|
678
|
-
const c = await this.
|
|
938
|
+
const c = await this.joinConnect(signal);
|
|
939
|
+
if (!c.ok && c.error.code === "aborted" && signal?.aborted)
|
|
940
|
+
return { ok: false, error: new ExecutionError("aborted", "exec aborted before start (the container was still connecting)", c.error) };
|
|
679
941
|
if (!c.ok)
|
|
680
942
|
return { ok: false, error: new ExecutionError("shell_unavailable", `local-docker connect failed: ${c.error.message}`, c.error) };
|
|
681
943
|
await this.probeContainerShell();
|
|
682
944
|
return ok(undefined);
|
|
683
945
|
}
|
|
684
|
-
async fsReady(p) {
|
|
946
|
+
async fsReady(p, signal) {
|
|
685
947
|
if (this.destroyed)
|
|
686
948
|
return { ok: false, error: new FileError("unknown", "execution env already destroyed", this.resolve(p)) };
|
|
687
949
|
if (this.containerId)
|
|
688
950
|
return ok(undefined);
|
|
689
|
-
const c = await this.
|
|
951
|
+
const c = await this.joinConnect(signal);
|
|
690
952
|
if (!c.ok)
|
|
691
953
|
return { ok: false, error: fileErrorFromExec(c.error, this.resolve(p)) };
|
|
692
954
|
return ok(undefined);
|
|
@@ -702,14 +964,32 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
702
964
|
function sanitizeId(id) {
|
|
703
965
|
return id.replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 48) || "task";
|
|
704
966
|
}
|
|
967
|
+
export function localDockerContainerNameOf(workerLabel, identity) {
|
|
968
|
+
const digest = createHash("sha256").update(workerLabel).update("\0").update(identity).digest("hex").slice(0, 12);
|
|
969
|
+
return `sema-docker-${sanitizeId(identity)}-${digest}`;
|
|
970
|
+
}
|
|
971
|
+
export function localDockerIdentityOfName(workerLabel, name) {
|
|
972
|
+
const m = /^sema-docker-(.+)-[0-9a-f]{12}$/.exec(name);
|
|
973
|
+
const candidate = m?.[1];
|
|
974
|
+
return candidate !== undefined && localDockerContainerNameOf(workerLabel, candidate) === name ? candidate : undefined;
|
|
975
|
+
}
|
|
705
976
|
function errMsg(e) {
|
|
706
977
|
return e instanceof Error ? e.message : String(e);
|
|
707
978
|
}
|
|
708
979
|
export function localDockerExecutionEnvFactory(config, deps = {}) {
|
|
709
980
|
const { workspaceFillOf, ...base } = config;
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
981
|
+
const custody = createWorkspaceCustody();
|
|
982
|
+
const envOf = (identity, ctx) => custody.envOf(identity, (leftover) => {
|
|
983
|
+
const workspaceFill = ctx !== undefined ? workspaceFillOf?.(ctx) : undefined;
|
|
984
|
+
return new RemoteLocalDockerExecutionEnv({ ...base, id: identity, ...(workspaceFill !== undefined ? { workspaceFill } : {}), ...(leftover !== undefined ? { leftover } : {}) }, deps);
|
|
985
|
+
});
|
|
986
|
+
let lister;
|
|
987
|
+
const reapPort = {
|
|
988
|
+
label: base.workerLabel,
|
|
989
|
+
list: () => (lister ??= new RemoteLocalDockerExecutionEnv({ ...base, id: "reaper-lister" }, deps)).readLaneRegistry(base.controlTimeoutMs ?? DEFAULT_CONTROL_TIMEOUT_MS, undefined),
|
|
990
|
+
identityOf: (name) => localDockerIdentityOfName(base.workerLabel, name),
|
|
991
|
+
settle: async (identity) => (await envOf(identity, undefined)).reapWorkspace(),
|
|
713
992
|
};
|
|
993
|
+
return Object.assign((ctx) => envOf(ctx.taskId ?? ctx.sessionId, ctx), { reapPort });
|
|
714
994
|
}
|
|
715
995
|
//# sourceMappingURL=remote-env-local-docker.js.map
|
|
@@ -6,8 +6,11 @@ export function remoteScratchpadDirFor(sessionId) {
|
|
|
6
6
|
return `/tmp/scratchpad/${sessionId}`;
|
|
7
7
|
}
|
|
8
8
|
export function withRemoteScratchpad(factory, logger) {
|
|
9
|
+
const decorated = new WeakSet();
|
|
9
10
|
return async (ctx) => {
|
|
10
11
|
const env = await factory(ctx);
|
|
12
|
+
if (decorated.has(env))
|
|
13
|
+
return env;
|
|
11
14
|
const dir = remoteScratchpadDirFor(ctx.sessionId);
|
|
12
15
|
if (dir === undefined) {
|
|
13
16
|
if (ctx.sessionId)
|
|
@@ -17,6 +20,7 @@ export function withRemoteScratchpad(factory, logger) {
|
|
|
17
20
|
const e = env;
|
|
18
21
|
if (typeof e.exec !== "function")
|
|
19
22
|
return env;
|
|
23
|
+
decorated.add(env);
|
|
20
24
|
const origExec = e.exec.bind(e);
|
|
21
25
|
let ensured;
|
|
22
26
|
const ensure = () => (ensured ??= (async () => {
|