@sema-agent/server 7.131.0 → 7.133.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 +575 -0
- package/README.md +12 -9
- package/README.zh-CN.md +9 -6
- package/USAGE.md +326 -98
- package/deploy/sema-up/README.md +19 -1
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -2
- package/deploy/sema-up/chart/templates/server.yaml +5 -2
- package/deploy/sema-up/stack/compose.yaml +3 -0
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
- package/dist/adoption/plan.d.ts +3 -2
- package/dist/adoption/plan.js +7 -5
- package/dist/adoption/runner.js +3 -10
- package/dist/adoption/sql.d.ts +3 -2
- package/dist/adoption/sql.js +3 -5
- package/dist/adoption/wire.d.ts +4 -1
- package/dist/adoption/wire.js +1 -0
- package/dist/approval-ask-audit-store.d.ts +31 -13
- package/dist/approval-ask-audit-store.js +272 -74
- package/dist/approval-ask-machine.d.ts +15 -0
- package/dist/approval-ask-machine.js +6 -0
- package/dist/approval-ask-retention.d.ts +136 -0
- package/dist/approval-ask-retention.js +102 -0
- package/dist/approval-card.d.ts +82 -20
- package/dist/approval-card.js +46 -16
- package/dist/approval-deny-reasons.d.ts +1 -1
- package/dist/approval.d.ts +9 -0
- package/dist/approval.js +24 -3
- package/dist/audit.d.ts +33 -19
- package/dist/audit.js +12 -16
- package/dist/auth-bridge.d.ts +4 -0
- package/dist/auth-bridge.js +10 -11
- package/dist/bake-runner/main.js +3 -2
- package/dist/boot/deferred-sandbox-path-env.js +1 -1
- package/dist/boot/deployment-mods.d.ts +31 -0
- package/dist/boot/deployment-mods.js +26 -0
- package/dist/boot/execution-env.d.ts +1 -1
- package/dist/boot/execution-env.js +27 -12
- package/dist/boot/execution-lane.js +11 -0
- package/dist/boot/leader.js +2 -0
- package/dist/boot/memory-boundary.d.ts +2 -2
- package/dist/boot/memory-boundary.js +2 -2
- package/dist/boot/memory-consolidation.d.ts +5 -4
- package/dist/boot/memory-consolidation.js +7 -6
- package/dist/boot/org-delivery.d.ts +28 -0
- package/dist/boot/org-delivery.js +20 -0
- package/dist/boot/read-deny-anchor-audit.d.ts +17 -0
- package/dist/boot/read-deny-anchor-audit.js +36 -0
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +21 -1
- package/dist/boot/resolve-spec.d.ts +4 -5
- package/dist/boot/resolve-spec.js +74 -123
- package/dist/boot/runner-deps.d.ts +19 -8
- package/dist/boot/runner-deps.js +15 -2
- package/dist/boot/session-faces.d.ts +2 -7
- package/dist/boot/session-faces.js +4 -2
- package/dist/boot/stage-02-web-admin-pull.js +4 -1
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +4 -4
- package/dist/boot/stage-05-execution-env.js +7 -10
- package/dist/boot/stage-06-runners.d.ts +4 -2
- package/dist/boot/stage-06-runners.js +11 -7
- package/dist/boot/stage-07-capability-layer.d.ts +4 -2
- package/dist/boot/stage-07-capability-layer.js +27 -6
- package/dist/boot/stage-08-reapers.d.ts +4 -2
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +6 -9
- package/dist/boot/stage-10-http-server.d.ts +6 -9
- package/dist/boot/stage-10-http-server.js +7 -9
- package/dist/boot/stores.d.ts +1 -1
- package/dist/boot/stores.js +7 -8
- package/dist/boot/web-admin.d.ts +4 -3
- package/dist/boot/web-admin.js +186 -98
- package/dist/boot/workflow-orchestration.d.ts +2 -0
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/brain.js +25 -25
- package/dist/breaker-key.d.ts +6 -0
- package/dist/breaker-key.js +29 -0
- package/dist/budget.js +5 -4
- package/dist/caller-text-echo.d.ts +23 -0
- package/dist/caller-text-echo.js +21 -0
- package/dist/capabilities/brand-identity.d.ts +26 -0
- package/dist/capabilities/brand-identity.js +27 -0
- package/dist/capabilities/center-plugins.d.ts +7 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/center-prompts.d.ts +32 -59
- package/dist/capabilities/center-prompts.js +18 -32
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/engine-capabilities.js +2 -1
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +30 -6
- package/dist/capabilities/hands-lane.js +11 -1
- package/dist/capabilities/mcp-probe.d.ts +48 -3
- package/dist/capabilities/mcp-probe.js +47 -135
- package/dist/capabilities/scenarios.d.ts +95 -45
- package/dist/capabilities/scenarios.js +53 -38
- package/dist/capabilities/skills.d.ts +19 -4
- package/dist/capabilities/skills.js +30 -10
- package/dist/capability-facts.d.ts +34 -4
- package/dist/capability-facts.js +28 -2
- package/dist/center-config-tier.d.ts +69 -0
- package/dist/center-config-tier.js +42 -0
- package/dist/checkpoint-identity.d.ts +16 -0
- package/dist/checkpoint-identity.js +19 -0
- package/dist/config-catalog.d.ts +17 -10
- package/dist/config-catalog.js +47 -32
- package/dist/config-d-migration.d.ts +3 -1
- package/dist/config-d-migration.js +2 -2
- package/dist/config-dir-trust.d.ts +114 -0
- package/dist/config-dir-trust.js +388 -0
- package/dist/config-invariants.d.ts +18 -5
- package/dist/config-invariants.js +35 -3
- package/dist/config-lkg.d.ts +9 -9
- package/dist/config-lkg.js +20 -4
- package/dist/config-provider.d.ts +9 -2
- package/dist/config-provider.js +18 -6
- package/dist/config-types.d.ts +75 -20
- package/dist/config-types.js +8 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +137 -62
- package/dist/delegated-session-owner.d.ts +185 -0
- package/dist/delegated-session-owner.js +119 -0
- package/dist/device-protocol.d.ts +5 -3
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.js +21 -2
- package/dist/device-ws-protocol.d.ts +70 -6
- package/dist/device-ws-protocol.js +50 -22
- package/dist/elicitation.js +3 -2
- package/dist/entry-problems.d.ts +34 -0
- package/dist/entry-problems.js +14 -0
- package/dist/env-name-allowlist-knobs.d.ts +12 -2
- package/dist/env-name-allowlist-knobs.js +5 -4
- package/dist/exec-bounds.d.ts +15 -3
- package/dist/exec-bounds.js +4 -0
- package/dist/execution-lane-caps.d.ts +56 -10
- package/dist/execution-lane-caps.js +50 -0
- package/dist/field-conflict.d.ts +43 -0
- package/dist/field-conflict.js +20 -0
- package/dist/fleet/fleet-bus.d.ts +80 -6
- package/dist/fleet/fleet-bus.js +41 -9
- package/dist/hooks/classic-stations.d.ts +91 -0
- package/dist/hooks/classic-stations.js +27 -0
- package/dist/hooks/command-spawn.d.ts +57 -0
- package/dist/hooks/command-spawn.js +139 -0
- package/dist/hooks/hook-llm.d.ts +8 -5
- package/dist/hooks/hook-llm.js +79 -36
- package/dist/hooks/hook-runner.d.ts +349 -95
- package/dist/hooks/hook-runner.js +855 -568
- package/dist/hooks/hook-source.d.ts +44 -0
- package/dist/hooks/hook-source.js +40 -0
- package/dist/http/active-run-conflict.d.ts +5 -13
- package/dist/http/active-run-conflict.js +17 -27
- package/dist/http/admission.d.ts +8 -2
- package/dist/http/admission.js +188 -101
- package/dist/http/approval-sweeps.js +99 -21
- package/dist/http/caller-trust.d.ts +77 -0
- package/dist/http/caller-trust.js +143 -0
- package/dist/http/checkpoint-ctx.d.ts +41 -24
- package/dist/http/checkpoint-ctx.js +23 -16
- package/dist/http/claimed-run.d.ts +14 -0
- package/dist/http/claimed-run.js +15 -0
- package/dist/http/device-placement.d.ts +2 -4
- package/dist/http/device-placement.js +7 -11
- package/dist/http/dispatch.d.ts +0 -4
- package/dist/http/dispatch.js +15 -13
- package/dist/http/durable-run-leg.d.ts +6 -33
- package/dist/http/durable-run-leg.js +36 -10
- package/dist/http/health-self-report.d.ts +7 -5
- package/dist/http/health-self-report.js +4 -18
- package/dist/http/owner-access.d.ts +56 -0
- package/dist/http/owner-access.js +42 -0
- package/dist/http/principal-gate.d.ts +70 -28
- package/dist/http/principal-gate.js +61 -15
- package/dist/http/readiness.d.ts +11 -5
- package/dist/http/readiness.js +10 -3
- package/dist/http/refusal-body.d.ts +21 -0
- package/dist/http/refusal-body.js +4 -0
- package/dist/http/request-guards.d.ts +43 -23
- package/dist/http/request-guards.js +53 -17
- package/dist/http/resume-ctx-read.d.ts +2 -5
- package/dist/http/resume-ctx-read.js +7 -4
- package/dist/http/resume-legs.d.ts +28 -4
- package/dist/http/resume-legs.js +169 -91
- package/dist/http/retired-service-deps.d.ts +43 -0
- package/dist/http/retired-service-deps.js +18 -0
- package/dist/http/route-ctx.d.ts +44 -28
- package/dist/http/route-ctx.js +4 -0
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/a2a-serve.js +3 -4
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.js +1 -1
- package/dist/http/routes/admin-memory-optout.js +5 -1
- package/dist/http/routes/adoption.js +2 -9
- package/dist/http/routes/approvals-assistant.js +49 -48
- package/dist/http/routes/background.js +3 -2
- package/dist/http/routes/capabilities.js +21 -5
- package/dist/http/routes/config-catalog.d.ts +3 -3
- package/dist/http/routes/config-catalog.js +1 -1
- package/dist/http/routes/devices.js +3 -17
- package/dist/http/routes/diagnostics.js +6 -2
- package/dist/http/routes/images.js +6 -7
- package/dist/http/routes/leader.js +1 -8
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +3 -2
- package/dist/http/routes/memory-bundle.js +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-consolidation.js +1 -1
- package/dist/http/routes/memory-origin.js +1 -1
- package/dist/http/routes/memory-policy.d.ts +1 -1
- package/dist/http/routes/memory-policy.js +3 -2
- package/dist/http/routes/notify-wake.js +8 -21
- package/dist/http/routes/observability.js +2 -2
- package/dist/http/routes/principal-inbox.d.ts +39 -0
- package/dist/http/routes/principal-inbox.js +76 -0
- package/dist/http/routes/retention-ops.js +2 -9
- package/dist/http/routes/rules.js +5 -18
- package/dist/http/routes/runs.d.ts +5 -0
- package/dist/http/routes/runs.js +34 -107
- package/dist/http/routes/session-sync.js +15 -26
- package/dist/http/routes/sessions.js +30 -40
- package/dist/http/routes/shared-memory.js +2 -13
- package/dist/http/routes/side-query.js +8 -7
- package/dist/http/routes/tasks.js +67 -21
- package/dist/http/routes/workflows.d.ts +351 -0
- package/dist/http/routes/workflows.js +153 -119
- package/dist/http/send.d.ts +33 -10
- package/dist/http/send.js +21 -4
- package/dist/http/server.d.ts +27 -18
- package/dist/http/server.js +34 -6
- package/dist/http/stored-body-replay.js +17 -4
- package/dist/http/submit-ctx.d.ts +25 -0
- package/dist/http/submit-ctx.js +40 -0
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +5 -4
- package/dist/http/wire-types.d.ts +11 -8
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -2
- package/dist/lane-home-probe.d.ts +112 -0
- package/dist/lane-home-probe.js +101 -0
- package/dist/leader/endpoint.d.ts +4 -1
- package/dist/leader/endpoint.js +11 -10
- package/dist/limit-refusal.d.ts +59 -0
- package/dist/limit-refusal.js +15 -0
- package/dist/main.js +1 -1
- package/dist/mcp-assertion-header.d.ts +32 -19
- package/dist/mcp-assertion-header.js +10 -9
- package/dist/mcp-tool-faces.d.ts +5 -0
- package/dist/mcp-tool-faces.js +6 -4
- package/dist/memory-project-layer.d.ts +37 -0
- package/dist/memory-project-layer.js +46 -0
- package/dist/memory-scope.d.ts +24 -17
- package/dist/memory-scope.js +24 -8
- package/dist/memory-sync-client.d.ts +27 -13
- package/dist/memory-sync-client.js +107 -18
- package/dist/model-entry-refusal.d.ts +9 -1
- package/dist/model-entry-refusal.js +6 -1
- package/dist/model-plane-face.d.ts +51 -0
- package/dist/model-plane-face.js +24 -0
- package/dist/model-provider.d.ts +44 -12
- package/dist/model-provider.js +21 -2
- package/dist/model-route-endpoint.d.ts +9 -12
- package/dist/model-route-endpoint.js +8 -11
- package/dist/model-route-env.d.ts +22 -0
- package/dist/model-route-env.js +2 -0
- package/dist/model-route-gap.d.ts +60 -30
- package/dist/model-route-gap.js +21 -15
- package/dist/observability/corrupt-read-seat.d.ts +7 -0
- package/dist/observability/corrupt-read-seat.js +9 -0
- package/dist/observability/cost-taxonomy.d.ts +7 -7
- package/dist/observability/err-text.d.ts +6 -0
- package/dist/observability/err-text.js +18 -4
- package/dist/observability/fail-open.d.ts +76 -14
- package/dist/observability/fail-open.js +76 -14
- package/dist/observability/metrics.js +4 -1
- package/dist/observability/prompt-manifest.d.ts +33 -82
- package/dist/observability/prompt-manifest.js +122 -17
- package/dist/observability/run-terminal.js +14 -6
- package/dist/observability/secret-env-scrub.d.ts +13 -1
- package/dist/observability/secret-env-scrub.js +13 -1
- package/dist/observability/tool-trace.d.ts +16 -21
- package/dist/observability/tool-trace.js +58 -49
- package/dist/operator-ask.d.ts +10 -0
- package/dist/operator-ask.js +3 -0
- package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
- package/dist/orchestration/workflow-agent-session-index.js +9 -13
- package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
- package/dist/orchestration/workflow-completion-inbox.js +13 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
- package/dist/orchestration/workflow-notify-journal.js +27 -34
- package/dist/orchestration/workflow-park-decision.d.ts +89 -0
- package/dist/orchestration/workflow-park-decision.js +118 -0
- package/dist/org-delivery-gate.d.ts +81 -0
- package/dist/org-delivery-gate.js +59 -0
- package/dist/panel-tool-names.d.ts +23 -0
- package/dist/panel-tool-names.js +8 -0
- package/dist/parked-decide.d.ts +39 -6
- package/dist/parked-decide.js +98 -51
- package/dist/parked-revive-surface.d.ts +9 -2
- package/dist/parked-revive-surface.js +11 -8
- package/dist/per-task-image.d.ts +7 -1
- package/dist/per-task-image.js +3 -3
- package/dist/permission-rule-list.d.ts +1 -1
- package/dist/permission-rule-list.js +2 -2
- package/dist/plain-string-record.d.ts +25 -0
- package/dist/plain-string-record.js +32 -0
- package/dist/plugins/approval-ask-store-file.d.ts +16 -1
- package/dist/plugins/approval-ask-store-file.js +21 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
- package/dist/plugins/approval-ask-store-memory.js +34 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
- package/dist/plugins/approval-ask-store-sql.js +37 -1
- package/dist/plugins/blob-backend.d.ts +83 -15
- package/dist/plugins/blob-backend.js +68 -15
- package/dist/plugins/breaker-state-sql.d.ts +2 -2
- package/dist/plugins/breaker-state-sql.js +4 -4
- package/dist/plugins/caching-session-store.d.ts +3 -0
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-store-sql.d.ts +28 -4
- package/dist/plugins/checkpoint-store-sql.js +59 -28
- package/dist/plugins/file-history-store-sql.d.ts +5 -2
- package/dist/plugins/file-history-store-sql.js +3 -1
- package/dist/plugins/file-run-store.d.ts +5 -13
- package/dist/plugins/file-run-store.js +9 -0
- package/dist/plugins/fork-routing-session-store.d.ts +9 -1
- package/dist/plugins/fork-routing-session-store.js +12 -1
- package/dist/plugins/host-platform.d.ts +2 -0
- package/dist/plugins/host-platform.js +2 -1
- package/dist/plugins/k8s-bg-scripts.d.ts +11 -0
- package/dist/plugins/k8s-bg-scripts.js +22 -0
- package/dist/plugins/local-checkpoint-store.d.ts +2 -0
- package/dist/plugins/local-checkpoint-store.js +11 -3
- package/dist/plugins/local-session-store.d.ts +1 -1
- package/dist/plugins/local-session-store.js +1 -1
- package/dist/plugins/local-session-window.d.ts +39 -0
- package/dist/plugins/local-session-window.js +54 -0
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
- package/dist/plugins/mailbox-store-sql.d.ts +30 -48
- package/dist/plugins/mailbox-store-sql.js +77 -52
- package/dist/plugins/memory-embedder-fingerprint.js +2 -1
- package/dist/plugins/memory-run-store.d.ts +5 -13
- package/dist/plugins/memory-run-store.js +8 -0
- package/dist/plugins/one-time-migrations.d.ts +245 -93
- package/dist/plugins/one-time-migrations.js +668 -207
- package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
- package/dist/plugins/org-delivery-quota-store.js +228 -0
- package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
- package/dist/plugins/permission-rule-store-sql.js +4 -18
- package/dist/plugins/pg-pool.js +39 -7
- package/dist/plugins/pg-session-storage.d.ts +20 -8
- package/dist/plugins/pg-session-storage.js +34 -21
- package/dist/plugins/remote-env-adb.d.ts +12 -12
- package/dist/plugins/remote-env-adb.js +21 -6
- package/dist/plugins/remote-env-device.js +3 -0
- package/dist/plugins/remote-env-e2b.d.ts +1 -1
- package/dist/plugins/remote-env-e2b.js +21 -9
- package/dist/plugins/remote-env-host.d.ts +9 -9
- package/dist/plugins/remote-env-host.js +10 -32
- package/dist/plugins/remote-env-k8s.d.ts +103 -38
- package/dist/plugins/remote-env-k8s.js +288 -95
- package/dist/plugins/remote-env-local-docker.d.ts +27 -13
- package/dist/plugins/remote-env-local-docker.js +82 -11
- package/dist/plugins/remote-env-ssh.d.ts +21 -12
- package/dist/plugins/remote-env-ssh.js +117 -5
- package/dist/plugins/remote-shell.d.ts +0 -1
- package/dist/plugins/remote-shell.js +1 -2
- package/dist/plugins/retention-store-sql.js +6 -2
- package/dist/plugins/run-store-sql.d.ts +16 -14
- package/dist/plugins/run-store-sql.js +22 -2
- package/dist/plugins/schema-consistency.d.ts +54 -0
- package/dist/plugins/schema-consistency.js +52 -0
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-user-file.js +2 -2
- package/dist/plugins/session-epoch-anchor.d.ts +39 -0
- package/dist/plugins/session-epoch-anchor.js +22 -0
- package/dist/plugins/session-store.d.ts +18 -8
- package/dist/plugins/session-store.js +15 -4
- package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
- package/dist/plugins/shared-memory-store-sql.js +5 -16
- package/dist/plugins/sql-driver.d.ts +205 -1
- package/dist/plugins/sql-driver.js +325 -13
- package/dist/plugins/sql-errors.d.ts +64 -0
- package/dist/plugins/sql-errors.js +57 -0
- package/dist/plugins/store-backend.d.ts +36 -1
- package/dist/plugins/store-backend.js +42 -15
- package/dist/plugins/store-contracts.d.ts +42 -0
- package/dist/plugins/store-contracts.js +1 -0
- package/dist/plugins/tidb-pool.d.ts +6 -1
- package/dist/plugins/tidb-pool.js +44 -10
- package/dist/plugins/tidb-session-storage.d.ts +8 -11
- package/dist/plugins/tidb-session-storage.js +6 -16
- package/dist/plugins/tidb-session-store.d.ts +24 -4
- package/dist/plugins/tidb-session-store.js +29 -5
- package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
- package/dist/plugins/workflow-journal-store-sql.js +19 -6
- package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
- package/dist/plugins/workflow-run-store-sql.js +50 -9
- package/dist/posture-source.d.ts +18 -10
- package/dist/posture-source.js +4 -1
- package/dist/project-identity.d.ts +45 -6
- package/dist/project-identity.js +162 -8
- package/dist/project-layer-key.d.ts +28 -0
- package/dist/project-layer-key.js +29 -0
- package/dist/prompts-domain-validate.d.ts +17 -61
- package/dist/prompts-domain-validate.js +9 -119
- package/dist/question.js +3 -2
- package/dist/read-deny-entry.d.ts +25 -0
- package/dist/read-deny-entry.js +12 -0
- package/dist/read-face-posture.d.ts +37 -11
- package/dist/read-face-posture.js +32 -3
- package/dist/request-key-closure.d.ts +9 -2
- package/dist/request-key-closure.js +11 -5
- package/dist/request-value-closure.d.ts +5 -0
- package/dist/request-value-closure.js +11 -3
- package/dist/rule-entry-list.d.ts +38 -11
- package/dist/rule-entry-list.js +106 -30
- package/dist/rules-consent.js +3 -4
- package/dist/run-acceptance.d.ts +19 -3
- package/dist/run-acceptance.js +13 -1
- package/dist/run-local.js +54 -24
- package/dist/runs.d.ts +15 -8
- package/dist/runs.js +35 -1
- package/dist/runtime-caps-resolver.d.ts +16 -6
- package/dist/runtime-caps-resolver.js +18 -5
- package/dist/sandbox-pkg-source.d.ts +19 -1
- package/dist/sandbox-pkg-source.js +29 -7
- package/dist/security.d.ts +87 -9
- package/dist/security.js +52 -9
- package/dist/server-secret-env.d.ts +44 -18
- package/dist/server-secret-env.js +49 -8
- package/dist/session-error-wire.d.ts +19 -2
- package/dist/session-error-wire.js +5 -1
- package/dist/session-incarnation.d.ts +15 -5
- package/dist/session-incarnation.js +16 -9
- package/dist/session-titled-frame.d.ts +33 -0
- package/dist/session-titled-frame.js +4 -0
- package/dist/session-titler.d.ts +9 -1
- package/dist/session-titler.js +27 -6
- package/dist/spec-fields.d.ts +28 -16
- package/dist/spec-fields.js +66 -54
- package/dist/sql-engine-posture.d.ts +31 -4
- package/dist/sql-engine-posture.js +36 -1
- package/dist/stored-request-tool-axes-m19.d.ts +19 -4
- package/dist/stored-request-tool-axes-m19.js +30 -2
- package/dist/task-a2a.d.ts +9 -1
- package/dist/task-a2a.js +73 -47
- package/dist/task-cwd.d.ts +1 -1
- package/dist/task-mcp.d.ts +46 -58
- package/dist/task-mcp.js +82 -107
- package/dist/task-settings.d.ts +95 -108
- package/dist/task-settings.js +77 -98
- package/dist/text-bidi.d.ts +1 -48
- package/dist/text-bidi.js +3 -5
- package/dist/tighten-only-seats.d.ts +150 -0
- package/dist/tighten-only-seats.js +196 -0
- package/dist/tool-approval.d.ts +304 -88
- package/dist/tool-approval.js +623 -239
- package/dist/trace/core-keyset-guard.d.ts +122 -20
- package/dist/trace/engine-notice-wire.d.ts +11 -3
- package/dist/trace/engine-notice-wire.js +8 -1
- package/dist/trace/exit-seat.d.ts +28 -0
- package/dist/trace/exit-seat.js +76 -0
- package/dist/trace/ledger-events.d.ts +6 -3
- package/dist/trace/ledger-sink.js +4 -1
- package/dist/trace/model-segment.js +1 -1
- package/dist/trace/project.d.ts +98 -17
- package/dist/trace/project.js +98 -50
- package/dist/trace/projection-table.d.ts +100 -0
- package/dist/trace/projection-table.js +130 -0
- package/dist/trace/redact.d.ts +54 -0
- package/dist/trace/redact.js +778 -152
- package/dist/trace/self-minted-wire.d.ts +345 -1
- package/dist/trace/self-minted-wire.js +117 -1
- package/dist/trace/wire-projection-faces.d.ts +377 -3
- package/dist/trace/wire-projection-faces.js +164 -1
- package/dist/url-refusal.js +2 -0
- package/dist/web-admin-client/apply-effective.d.ts +12 -0
- package/dist/web-admin-client/apply-effective.js +56 -5
- package/dist/web-admin-client/candidate-gate.d.ts +6 -6
- package/dist/web-admin-client/candidate-gate.js +3 -3
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/facade.js +1 -1
- package/dist/web-admin-client/http-client.js +0 -6
- package/dist/web-admin-client/read-face.js +5 -9
- package/dist/web-admin-client/read-warnings.d.ts +13 -0
- package/dist/web-admin-client/read-warnings.js +10 -0
- package/dist/web-admin-client/skills-mcp.d.ts +3 -0
- package/dist/web-admin-client/skills-mcp.js +11 -9
- package/dist/web-admin-client/types.d.ts +2 -3
- package/dist/workspace-cache.d.ts +35 -0
- package/dist/workspace-cache.js +36 -0
- package/dist/workspace-space.d.ts +3 -2
- package/dist/workspace-space.js +2 -0
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +65 -10
- package/package.json +8 -4
- package/scripts/drain-check-local.mjs +34 -1
- package/scripts/drain-check.mysql.sql +30 -2
- package/scripts/drain-check.pg.sql +29 -2
- package/dist/capabilities/memory-notice.d.ts +0 -138
- package/dist/capabilities/memory-notice.js +0 -64
- package/dist/capabilities/prompt.d.ts +0 -17
- package/dist/capabilities/prompt.js +0 -6
- package/dist/mcp-content-origin.d.ts +0 -34
- package/dist/mcp-content-origin.js +0 -10
- package/dist/tool-axis-words.d.ts +0 -27
- package/dist/tool-axis-words.js +0 -9
- package/dist/wire-name-bound.d.ts +0 -14
- package/dist/wire-name-bound.js +0 -13
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* core's `createCircuitBreakerBrain` defaults to a per-PROCESS Map → on a multi-replica deployment
|
|
8
8
|
* every replica re-discovers a provider outage independently (slow fleet-wide reaction). This backs
|
|
9
|
-
* the breaker with the shared `
|
|
9
|
+
* the breaker with the shared `breaker_state` table so a trip on one replica is learned by the others.
|
|
10
10
|
*
|
|
11
11
|
* IMPORTANT — `BreakerState.get/set` are **synchronous** (core calls them on the hot path of every
|
|
12
12
|
* brain invocation; a DB round-trip per call is untenable). So this is a **write-through cache**:
|
|
@@ -40,7 +40,7 @@ import type { Pool as MySqlPool } from "mysql2/promise";
|
|
|
40
40
|
import type { Pool as PgPool, PoolClient } from "pg";
|
|
41
41
|
import type { BreakerSnapshot, BreakerState } from "@sema-agent/core";
|
|
42
42
|
import { type SqlDriver } from "./sql-driver.js";
|
|
43
|
-
/** PG translation of the tidb-pool.ts `
|
|
43
|
+
/** PG translation of the tidb-pool.ts `breaker_state` DDL (DATETIME(3)→TIMESTAMPTZ(3)). Disjoint from other
|
|
44
44
|
* stores' tables, so a self-contained ensureSchema is safe (no central-schema shadowing). TiDB's DDL lives
|
|
45
45
|
* centrally in tidb-pool.ts (no PG-side twin needed there — production wires ONE ensureTidbSchema). */
|
|
46
46
|
export declare const PG_BREAKER_STATE_SCHEMA: string[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mysqlDriver, pgDriver } from "./sql-driver.js";
|
|
2
2
|
export const PG_BREAKER_STATE_SCHEMA = [
|
|
3
|
-
`CREATE TABLE IF NOT EXISTS
|
|
3
|
+
`CREATE TABLE IF NOT EXISTS breaker_state (
|
|
4
4
|
breaker_key VARCHAR(190) COLLATE "C" NOT NULL,
|
|
5
5
|
phase VARCHAR(16) COLLATE "C" NOT NULL,
|
|
6
6
|
failures INTEGER NOT NULL DEFAULT 0,
|
|
@@ -37,8 +37,8 @@ export class SqlBreakerState {
|
|
|
37
37
|
}
|
|
38
38
|
async writeThrough(key, snap) {
|
|
39
39
|
try {
|
|
40
|
-
await this.db.query(this.q("INSERT INTO
|
|
41
|
-
"ON DUPLICATE KEY UPDATE phase=VALUES(phase), failures=VALUES(failures), opened_at=VALUES(opened_at), updated_at=VALUES(updated_at)", "INSERT INTO
|
|
40
|
+
await this.db.query(this.q("INSERT INTO breaker_state (breaker_key, phase, failures, opened_at, updated_at) VALUES (?,?,?,?,?) " +
|
|
41
|
+
"ON DUPLICATE KEY UPDATE phase=VALUES(phase), failures=VALUES(failures), opened_at=VALUES(opened_at), updated_at=VALUES(updated_at)", "INSERT INTO breaker_state (breaker_key, phase, failures, opened_at, updated_at) VALUES ($1,$2,$3,$4,$5) " +
|
|
42
42
|
"ON CONFLICT (breaker_key) DO UPDATE SET phase=EXCLUDED.phase, failures=EXCLUDED.failures, opened_at=EXCLUDED.opened_at, updated_at=EXCLUDED.updated_at"), [key, snap.phase, snap.failures, snap.openedAt != null ? new Date(snap.openedAt) : null, new Date()]);
|
|
43
43
|
this.pending.delete(key);
|
|
44
44
|
if (this.writeFailStreak > 0) {
|
|
@@ -60,7 +60,7 @@ export class SqlBreakerState {
|
|
|
60
60
|
try {
|
|
61
61
|
const pendingAtStart = new Set(this.pending);
|
|
62
62
|
const guarded = (key) => this.pending.has(key) || pendingAtStart.has(key);
|
|
63
|
-
const { rows } = await this.db.query("SELECT breaker_key, phase, failures, opened_at FROM
|
|
63
|
+
const { rows } = await this.db.query("SELECT breaker_key, phase, failures, opened_at FROM breaker_state");
|
|
64
64
|
const seen = new Set();
|
|
65
65
|
for (const r of rows) {
|
|
66
66
|
const key = String(r.breaker_key);
|
|
@@ -4,6 +4,7 @@ import type { StagingHandle } from "../session-sync-kernel.js";
|
|
|
4
4
|
import { type PlacementAcquireOpts } from "./session-placement.js";
|
|
5
5
|
import type { InstructionSourceStore } from "../instruction-source-notice.js";
|
|
6
6
|
import type { SessionFaceReader } from "../session-incarnation.js";
|
|
7
|
+
import type { OwnerlessClaim } from "../delegated-session-owner.js";
|
|
7
8
|
export interface CachingOptions {
|
|
8
9
|
/** Idle seconds a woken session is kept warm. 0 disables caching (pure passthrough). */
|
|
9
10
|
ttlSec: number;
|
|
@@ -59,6 +60,8 @@ export declare class CachingSessionStore implements SessionStore {
|
|
|
59
60
|
* (缓存的会话活得比「另一只店删掉又重建了这一行」长)。🔴 必须转发:k8s 工作区空间的每 run 读与起服门读的就是本类。 */
|
|
60
61
|
readonly incarnationOf?: SessionStore["incarnationOf"];
|
|
61
62
|
readonly register?: (sessionId: string, owner: string | null) => Promise<void>;
|
|
63
|
+
/** S-1770 委派继承律的认领口,纯转发(写的是行上的属主那一格 —— 只 CAS 子行自己,不碰暖缓存里的会话;停驻挂点在默认部署上读的就是本类 —— 与 `placementOf` 同转发同缺:内店记录委派树 ⇒ 两只都在)。 */
|
|
64
|
+
readonly claimOwnerless?: OwnerlessClaim;
|
|
62
65
|
/** Delegated SessionRepo seam (§0.5) — list/fork/delete operate on the DURABLE tables directly (they bypass the
|
|
63
66
|
* warm cache by design; a fork/delete must read/write durable state, not a possibly-stale cached view). */
|
|
64
67
|
readonly listSessions?: (opts: {
|
|
@@ -10,6 +10,7 @@ export class CachingSessionStore {
|
|
|
10
10
|
sessionFaceOf;
|
|
11
11
|
incarnationOf;
|
|
12
12
|
register;
|
|
13
|
+
claimOwnerless;
|
|
13
14
|
listSessions;
|
|
14
15
|
fork;
|
|
15
16
|
deleteSession;
|
|
@@ -57,6 +58,8 @@ export class CachingSessionStore {
|
|
|
57
58
|
this.incarnationOf = inner.incarnationOf.bind(inner);
|
|
58
59
|
if (ownerAware.register)
|
|
59
60
|
this.register = ownerAware.register.bind(inner);
|
|
61
|
+
if (ownerAware.claimOwnerless)
|
|
62
|
+
this.claimOwnerless = ownerAware.claimOwnerless.bind(inner);
|
|
60
63
|
if (ownerAware.listSessions)
|
|
61
64
|
this.listSessions = ownerAware.listSessions.bind(inner);
|
|
62
65
|
if (ownerAware.sessionSummaryOf)
|
|
@@ -37,6 +37,14 @@ export declare function tokenFingerprint(token: string): string;
|
|
|
37
37
|
* 交给它、原样展开)。继承而不是在这里逐键再写一遍:core 给这一臂再加一位同类事实时,改的只有那张 Pick 表。 */
|
|
38
38
|
export interface PendingCheckpoint extends ParkRowFacts {
|
|
39
39
|
sessionId: string;
|
|
40
|
+
/**
|
|
41
|
+
* 这道停驻门的**非秘密稳定身份**(core `Checkpoint.checkpointId`,引擎每次停驻铸)—— 三处 durable 读面(本行 = `GET /v1/approvals` 的 `pending[]`
|
|
42
|
+
* 与 `/v1/approvals/stream` 的 `pending` 帧;停驻收件 `GET /v1/assistant/inbox` 的 `inbox[]`)共用的 **join 键**,也是 409 载体 A
|
|
43
|
+
* `pendingGate.checkpointId` / `terminal.paused.checkpointId` 的同一个值。**在场就是可信的那一个值,缺席就是缺席**:读法唯一 = `checkpoint-identity.ts` 的
|
|
44
|
+
* `durableRowIdentity`(过信任边界 —— 不含 token、有界),没有它的行(core 5.42.0 之前停驻的老行 / 没过边界的值)**照列**、键缺席(这一行没有可 join 的身份)、
|
|
45
|
+
* 每行计一次 `server.approvals.durable-row-checkpoint-id-missing`。两只店各读自己手里的那一份(SQL 孪生读 `checkpoint` 列的成员,LOCAL 孪生读 blob)。
|
|
46
|
+
*/
|
|
47
|
+
checkpointId?: string;
|
|
40
48
|
scope: string;
|
|
41
49
|
toolName: string | null;
|
|
42
50
|
toolCallId: string | null;
|
|
@@ -51,11 +59,12 @@ export interface PendingCheckpoint extends ParkRowFacts {
|
|
|
51
59
|
* consumer to treat the key's PRESENCE as "there is a binding" and echo `null` back into /decide. */
|
|
52
60
|
boundCallId?: string;
|
|
53
61
|
boundInputHash?: string;
|
|
54
|
-
/** 🔴 [ref]
|
|
62
|
+
/** 🔴 [ref]③: the checkpoint's gate kind — the operator queue mixes tool approvals with
|
|
55
63
|
* plan_review / resource_limit / task_done parks (all of which carry `toolName: null`), so a durable-recovery
|
|
56
|
-
* consumer needs this to ROUTE a row to the right wire (`/decide` vs `/plan_review` vs `/resume`).
|
|
57
|
-
*
|
|
58
|
-
|
|
64
|
+
* consumer needs this to ROUTE a row to the right wire (`/decide` vs `/plan_review` vs `/resume`). ALWAYS present
|
|
65
|
+
* (S-1681, 7.132.0): every park stamps it, the one-time migration M21 filled any row without it from the row's gate,
|
|
66
|
+
* and a SQL row that still carries none is not listed by `listPending` (counted: `server.approvals.queue-row-gate-kind-missing`; no decide route binds it either). */
|
|
67
|
+
gateKind: CheckpointGate["kind"];
|
|
59
68
|
/** The suspended run's taskId (task_active join) — the key to the run/trace ("view task context"). */
|
|
60
69
|
taskId: string | null;
|
|
61
70
|
/** The pending tool call's args (post-hook), redacted + bounded — for tool_approval the write payload, for a
|
|
@@ -278,6 +287,15 @@ export declare function assertCheckpointColumnSchema(query: (sql: string) => Pro
|
|
|
278
287
|
export declare function boundedRuleOffers(raw: unknown, opts?: {
|
|
279
288
|
countRedactions?: boolean;
|
|
280
289
|
}): RuleOfferProjection[] | undefined;
|
|
290
|
+
/**
|
|
291
|
+
* S-1681 —— 运维队列行的门型:**两只孪生同一只判官**(SQL 孪生读 `gate_kind` 列 —— put 时从同一只门反范式下来的那一格,每次停驻都盖,一次性迁移 M21 把没有它的
|
|
292
|
+
* 存量行从门子树补齐;local 孪生读快照上的门 `cp.gate.kind`)。
|
|
293
|
+
* 读到的值是 NULL / 缺席 / 不是 core 登记的门型 ⇒ `undefined`:这一行**不列**(响亮:计一次 `server.approvals.queue-row-gate-kind-missing`)—— 与每一条决断口同一个读法:
|
|
294
|
+
* 按门型绑定取行的读口对这种行本来就不命中(`pendingRowQuery` 的 `gate_kind IN (…)`,证不出门型就不当它是这道门),队列不再把一行谁也决不了的行投出去,
|
|
295
|
+
* 也不按缺键投(消费方按 `gateKind` 路由、缺键即 fail-closed)。不整只拒:一行坏行不许让整个租户的队列(列表 500、SSE 心跳照常而队列永远停在旧帧)消失。
|
|
296
|
+
* 按构造不可达(写口恒盖、M21 补齐);计数非零 = 写腿或手改出了错,按 `SELECT … WHERE status = 'pending' AND gate_kind IS NULL` 查那一行。
|
|
297
|
+
*/
|
|
298
|
+
export declare function queueRowGateKind(kind: unknown): CheckpointGate["kind"] | undefined;
|
|
281
299
|
/** Redact + size-bound a pending tool call's args for persistence/serving. JSON-roundtrips so the stored shape
|
|
282
300
|
* matches what the operator queue serves; oversized payloads collapse to a marker rather than bloating the row.
|
|
283
301
|
* Exported for the LOCAL twin (local-checkpoint-store.ts) so the operator-queue projection can't drift. */
|
|
@@ -695,6 +713,12 @@ export declare class SqlCheckpointStore implements CheckpointStore {
|
|
|
695
713
|
* {@link SqlCheckpointStore.pendingRowQuery};语义与三态全文见 {@link PendingRowBinding} 顶注。
|
|
696
714
|
* `scope` 传 `""`(空串)历史上与缺席同义(旧形 `scope ?` 真值判),这里逐字保留。
|
|
697
715
|
*/
|
|
716
|
+
/**
|
|
717
|
+
* 每一只**待决** checkpoint 的会话(去重)—— 审批账本留存律的挂靠源(`approval-ask-retention.ts`:待决 checkpoint = 一个还能动的停驻,
|
|
718
|
+
* 它的会话就是停驻那条腿上问行的 `source_task_id`)。**不按门型过滤**:运维队列 {@link listPending} 不列 `gate_kind` 读不出的行,
|
|
719
|
+
* 而决断口的令牌回落仍认它 —— 留存若跟着队列漏掉它,就会删掉一只还能被决的停驻的问。只读 `session_id`,不读 blob。
|
|
720
|
+
*/
|
|
721
|
+
listPendingSessionIds(): Promise<string[]>;
|
|
698
722
|
findPendingTokenBySession(sessionId: string, scope?: string, binding?: PendingRowBinding): Promise<CheckpointToken | null>;
|
|
699
723
|
/**
|
|
700
724
|
* 🔴 [ref] 车5 §9 C4 —— 流内审批对账收敛器判据 1 的**窄读口**(店面承载;收敛器本体不在本车)。
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { parkedApprovalCard, parkedFacetOf } from "../approval-content-kind.js";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { APPROVAL_GATE_KINDS_SQL_IN, denySweepOwns } from "../tool-approval.js";
|
|
4
|
-
import { CheckpointError, MAX_RULE_TEXT_CHARS, validatePendingSteer, appendPendingSteer, checkpointVersionOf, winnerFromOutcome, summarizeCheckpoint, MAX_SUPPORTED_CHECKPOINT_VERSION, ExecutionOutcomeConflictError, executionRecordDisposition, executionVerdict, } from "@sema-agent/core";
|
|
4
|
+
import { CheckpointError, isGateKind, MAX_RULE_TEXT_CHARS, validatePendingSteer, appendPendingSteer, checkpointVersionOf, winnerFromOutcome, summarizeCheckpoint, MAX_SUPPORTED_CHECKPOINT_VERSION, ExecutionOutcomeConflictError, executionRecordDisposition, executionVerdict, } from "@sema-agent/core";
|
|
5
5
|
import { redactDeep, redactSecrets } from "../trace/redact.js";
|
|
6
6
|
import { MAX_RULE_OFFERS, MAX_RULE_OFFER_BATCH_MEMBERS, RuleOfferRawSchema, backfillLegacyBatchMemberKind, parkRowFacts, screenUncoveredDetailSeat } from "../approval-card.js";
|
|
7
7
|
import { assertJsonColumnWritable, createObjectColumnReader, decodeJsonColumn, decodeNullableJsonColumn, foldJsonColumn, isJsonColumnBodyProblem, jsonColumnText, readJsonArrayColumn, readJsonObjectColumn, readNonNullJsonValueColumn, } from "./sql-json-column.js";
|
|
8
8
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
9
|
+
import { durableRowIdentity } from "../checkpoint-identity.js";
|
|
9
10
|
import { mysqlDriver, pgDriver, dialectProtocolJsonEncoder } from "./sql-driver.js";
|
|
10
|
-
import { isDupKeyError, isMissingColumnError } from "./sql-errors.js";
|
|
11
|
+
import { isDupKeyError, isMissingColumnError, rowTooLargeOrSelf } from "./sql-errors.js";
|
|
11
12
|
import { MANAGED_RETENTION } from "./retention-store-sql.js";
|
|
12
13
|
import { approvalPayloadFingerprint } from "./approval-payload-fingerprint.js";
|
|
13
14
|
const REAP_CLASSIFY_BATCH = 200;
|
|
@@ -183,6 +184,18 @@ function readParkRowFactsCell(cell) {
|
|
|
183
184
|
return parkRowFacts(pendingAction);
|
|
184
185
|
}
|
|
185
186
|
const PARK_ROW_PENDING_ACTION = { key: "pendingAction", as: "pending_action" };
|
|
187
|
+
const PARK_ROW_CHECKPOINT_ID = { key: "checkpointId", as: "checkpoint_id" };
|
|
188
|
+
const readCheckpointIdMemberBody = (body) => (typeof body === "string" ? { value: body } : { problem: "checkpointId is not a JSON string" });
|
|
189
|
+
function readCheckpointIdCell(cell) {
|
|
190
|
+
try {
|
|
191
|
+
return decodeNullableJsonColumn(cell, readCheckpointIdMemberBody, "checkpoint.checkpoint $.checkpointId (operator queue row)");
|
|
192
|
+
}
|
|
193
|
+
catch (e) {
|
|
194
|
+
if (!isJsonColumnBodyProblem(e))
|
|
195
|
+
throw e;
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
186
199
|
const PARK_ROW_GATE = { key: "gate", as: "park_gate" };
|
|
187
200
|
function readParkGateCell(cell) {
|
|
188
201
|
try {
|
|
@@ -196,6 +209,12 @@ function readParkGateCell(cell) {
|
|
|
196
209
|
}
|
|
197
210
|
}
|
|
198
211
|
const readParkGateMemberBody = createObjectColumnReader();
|
|
212
|
+
export function queueRowGateKind(kind) {
|
|
213
|
+
if (isGateKind(kind))
|
|
214
|
+
return kind;
|
|
215
|
+
recordFailOpen("server.approvals.queue-row-gate-kind-missing", `gate_kind=${kind === null || kind === undefined ? "NULL" : redactSecrets(String(kind)).slice(0, 40)}`);
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
199
218
|
function parkedGateOfRow(r) {
|
|
200
219
|
return { kind: r.gate_kind ?? undefined, approvalCard: readParkGateCell(r[PARK_ROW_GATE.as])?.approvalCard };
|
|
201
220
|
}
|
|
@@ -418,7 +437,7 @@ export class SqlCheckpointStore {
|
|
|
418
437
|
if (this.isDupKey(e)) {
|
|
419
438
|
throw new CheckpointError("checkpoint.already_exists", `checkpoint token already exists`);
|
|
420
439
|
}
|
|
421
|
-
throw e;
|
|
440
|
+
throw rowTooLargeOrSelf(this.db.dialect, e, `the checkpoint row for session ${JSON.stringify(cp.sessionId)}`);
|
|
422
441
|
}
|
|
423
442
|
}
|
|
424
443
|
async get(token) {
|
|
@@ -575,38 +594,41 @@ export class SqlCheckpointStore {
|
|
|
575
594
|
}
|
|
576
595
|
async listPending(scope) {
|
|
577
596
|
const d = this.db.dialect;
|
|
578
|
-
const base = `SELECT c.session_id, c.scope, c.tool_name, c.tool_call_id, ${jsonColumnText(d, "tool_input")}, c.bound_input_hash, ` +
|
|
597
|
+
const base = `SELECT c.session_id, c.token, c.scope, c.tool_name, c.tool_call_id, ${jsonColumnText(d, "tool_input")}, c.bound_input_hash, ` +
|
|
579
598
|
`${jsonColumnText(d, "risk_descriptor")}, ${jsonColumnText(d, "rule_suggestions")}, c.has_bidi_controls, c.created_at_ms, c.deadline, c.gate_kind, ta.task_id, ` +
|
|
580
|
-
`${jsonColumnText(d, "checkpoint", PARK_ROW_PENDING_ACTION)}, ${jsonColumnText(d, "checkpoint", PARK_ROW_GATE)} ` +
|
|
599
|
+
`${jsonColumnText(d, "checkpoint", PARK_ROW_PENDING_ACTION)}, ${jsonColumnText(d, "checkpoint", PARK_ROW_GATE)}, ${jsonColumnText(d, "checkpoint", PARK_ROW_CHECKPOINT_ID)} ` +
|
|
581
600
|
"FROM checkpoint c LEFT JOIN task_active ta ON ta.session_id = c.session_id WHERE c.status='pending'";
|
|
582
601
|
const { rows } = scope
|
|
583
602
|
? await this.db.query(`${base}${this.q(" AND c.scope=?", " AND c.scope=$1")} ORDER BY c.created_at_ms ASC`, [scope])
|
|
584
603
|
: await this.db.query(`${base} ORDER BY c.created_at_ms ASC`);
|
|
585
|
-
const out = rows.
|
|
604
|
+
const out = rows.flatMap((r) => {
|
|
605
|
+
const gateKind = queueRowGateKind(r.gate_kind);
|
|
606
|
+
if (gateKind === undefined)
|
|
607
|
+
return [];
|
|
586
608
|
const toolName = r.tool_name ?? null;
|
|
587
609
|
const toolCallId = r.tool_call_id ?? null;
|
|
588
610
|
const boundInputHash = r.bound_input_hash ?? null;
|
|
589
|
-
const gateKind = r.gate_kind ?? null;
|
|
590
611
|
const ruleOffers = readRuleOffersCell(r.rule_suggestions);
|
|
591
612
|
const approvalCard = parkedApprovalCard(parkedGateOfRow(r));
|
|
592
|
-
return {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
613
|
+
return [{
|
|
614
|
+
sessionId: String(r.session_id),
|
|
615
|
+
...durableRowIdentity("approvals-queue", readCheckpointIdCell(r[PARK_ROW_CHECKPOINT_ID.as]), r.token),
|
|
616
|
+
scope: String(r.scope),
|
|
617
|
+
toolName,
|
|
618
|
+
toolCallId,
|
|
619
|
+
...(toolCallId !== null ? { boundCallId: toolCallId } : {}),
|
|
620
|
+
...(boundInputHash !== null ? { boundInputHash } : {}),
|
|
621
|
+
gateKind,
|
|
622
|
+
taskId: r.task_id ?? null,
|
|
623
|
+
input: refusing("a tool input the operator would be approving unseen", () => decodeToolInputColumn(r.tool_input)) ?? null,
|
|
624
|
+
createdAt: Number(r.created_at_ms),
|
|
625
|
+
deadline: r.deadline == null ? null : Number(r.deadline),
|
|
626
|
+
riskDescriptor: readRiskDescriptorCell(r.risk_descriptor),
|
|
627
|
+
...(ruleOffers !== undefined ? { ruleOffers } : {}),
|
|
628
|
+
...(Number(r.has_bidi_controls) === 1 ? { hasBidiControls: true } : {}),
|
|
629
|
+
...(approvalCard !== undefined ? { approvalCard } : {}),
|
|
630
|
+
...readParkRowFactsCell(r[PARK_ROW_PENDING_ACTION.as]),
|
|
631
|
+
}];
|
|
610
632
|
});
|
|
611
633
|
return out.sort((a, b) => (b.riskDescriptor?.severity ?? 0) - (a.riskDescriptor?.severity ?? 0) || a.createdAt - b.createdAt);
|
|
612
634
|
}
|
|
@@ -620,6 +642,10 @@ export class SqlCheckpointStore {
|
|
|
620
642
|
}
|
|
621
643
|
return out;
|
|
622
644
|
}
|
|
645
|
+
async listPendingSessionIds() {
|
|
646
|
+
const { rows } = await this.db.query("SELECT DISTINCT session_id FROM checkpoint WHERE status='pending'", []);
|
|
647
|
+
return rows.map((r) => String(r.session_id));
|
|
648
|
+
}
|
|
623
649
|
async findPendingTokenBySession(sessionId, scope, binding) {
|
|
624
650
|
const { sql, params } = this.pendingRowQuery("token", sessionId, scope || undefined, binding);
|
|
625
651
|
const { rows } = await this.db.query(sql, params);
|
|
@@ -716,9 +742,14 @@ export class SqlCheckpointStore {
|
|
|
716
742
|
async putCtx(sessionId, ctx) {
|
|
717
743
|
const text = this.json(ctx, "checkpoint ctx");
|
|
718
744
|
assertJsonColumnWritable(text, createObjectColumnReader(), `checkpoint_ctx.ctx for session ${JSON.stringify(sessionId)} (write leg)`);
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
745
|
+
try {
|
|
746
|
+
await this.db.query(this.q("INSERT INTO checkpoint_ctx (session_id, ctx, updated_at_ms) VALUES (?,?,?) " +
|
|
747
|
+
"ON DUPLICATE KEY UPDATE ctx = VALUES(ctx), updated_at_ms = VALUES(updated_at_ms)", "INSERT INTO checkpoint_ctx (session_id, ctx, updated_at_ms) VALUES ($1,$2::jsonb,$3) " +
|
|
748
|
+
"ON CONFLICT (session_id) DO UPDATE SET ctx = EXCLUDED.ctx, updated_at_ms = EXCLUDED.updated_at_ms"), [sessionId, text, Date.now()]);
|
|
749
|
+
}
|
|
750
|
+
catch (e) {
|
|
751
|
+
throw rowTooLargeOrSelf(this.db.dialect, e, `checkpoint_ctx.ctx for session ${JSON.stringify(sessionId)}`);
|
|
752
|
+
}
|
|
722
753
|
}
|
|
723
754
|
async getCtx(sessionId) {
|
|
724
755
|
const { rows } = await this.db.query(this.q(`SELECT ${jsonColumnText("tidb", "ctx")} FROM checkpoint_ctx WHERE session_id=?`, `SELECT ${jsonColumnText("pg", "ctx")} FROM checkpoint_ctx WHERE session_id=$1`), [sessionId]);
|
|
@@ -2,6 +2,7 @@ import type { Pool as MySqlPool } from "mysql2/promise";
|
|
|
2
2
|
import type { Pool as PgPool } from "pg";
|
|
3
3
|
import { type FileHistoryRetentionPolicy, type ExecutionEnv, type FileHistoryStore, type FileHistoryResult, type FileHistoryTrackResult, type FileHistoryRestoreResult, type FileHistoryExport } from "@sema-agent/core";
|
|
4
4
|
import { type BlobBackend } from "./blob-backend.js";
|
|
5
|
+
import type { SyncBlobPutResult } from "./store-backend.js";
|
|
5
6
|
import { type SqlDriver } from "./sql-driver.js";
|
|
6
7
|
/** The file-history blob domain's SQL table (BlobBackend `table`/MinIO index binding + the A7 assert). */
|
|
7
8
|
export declare const FILE_HISTORY_BLOB_TABLE = "file_history_blob";
|
|
@@ -147,8 +148,10 @@ export declare class SqlFileHistoryStore implements FileHistoryStore {
|
|
|
147
148
|
* Domain-isolated by construction (this store's blob table only — [ref] D1). Reaper-driven. */
|
|
148
149
|
sweepOrphanBlobs(): Promise<number>;
|
|
149
150
|
/** Upload ONE content-addressed blob ahead of an importHistory (§5 streamed negotiation). Store-level
|
|
150
|
-
* integrity re-check (the route pre-verifies too — the internal caller might not). Never-throw.
|
|
151
|
-
|
|
151
|
+
* integrity re-check (the route pre-verifies too — the internal caller might not). Never-throw.
|
|
152
|
+
* The SQL blob judge's refusal ({@link BlobTooLargeError}, judged on the connection that would have written the blob)
|
|
153
|
+
* keeps its own code — the route answers it 413 (the sentence names that connection's walls), every other write failure 502 ("retry"). */
|
|
154
|
+
putBlob(hash: string, bytes: Uint8Array): Promise<SyncBlobPutResult>;
|
|
152
155
|
getBlob(hash: string): Promise<Uint8Array | undefined>;
|
|
153
156
|
/** The subset of `hashes` already present — one SQL INDEX probe (the import presence pre-check). */
|
|
154
157
|
hasBlobs(hashes: string[]): Promise<Set<string>>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { captureFileBackupViaEnv, applyFileRestoreViaEnv, fileHistoryModeProvenDifferent, worldStillMatchesMint, boundaryPublishVerdict, fileHistoryDescribeTrackKey, fileHistoryTrackKeyOf, fileHistoryResolveTrackKey, fileHistoryExportDigest, validateFileHistoryExport, resolveFileHistoryRetention, fileHistoryBoundariesToKeep, } from "@sema-agent/core";
|
|
3
|
-
import { SqlBlobBackend } from "./blob-backend.js";
|
|
3
|
+
import { BlobTooLargeError, SqlBlobBackend } from "./blob-backend.js";
|
|
4
4
|
import { mysqlDriver, pgDriver } from "./sql-driver.js";
|
|
5
5
|
import { isMissingColumnError } from "./sql-errors.js";
|
|
6
6
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
@@ -594,6 +594,8 @@ export class SqlFileHistoryStore {
|
|
|
594
594
|
return { ok: true };
|
|
595
595
|
}
|
|
596
596
|
catch (err) {
|
|
597
|
+
if (err instanceof BlobTooLargeError)
|
|
598
|
+
return { ok: false, error: { code: err.code, message: err.message, wallSource: err.cap.source } };
|
|
597
599
|
return { ok: false, error: { code: "snapshot_failed", message: `putBlob ${hash} write/upload failed: ${discloseCaughtFailure(err)}` } };
|
|
598
600
|
}
|
|
599
601
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type UsageRow } from "../usage-analytics.js";
|
|
2
2
|
import type { TaskStatus } from "@sema-agent/core";
|
|
3
|
-
import { StoreBootRefusalError, type CreateRunOutcome, type NewRunMeta, type RunIdemBinding, type RunRecord, type SessionSummary, type RunEvent, type PersistedTaskResult, type LatestRunRef } from "./store-contracts.js";
|
|
3
|
+
import { StoreBootRefusalError, type FenceLanded, type InProcessClaimFence, type CreateRunOutcome, type NewRunMeta, type RunIdemBinding, type RunListQuery, type RunRecord, type SessionSummary, type RunEvent, type PersistedTaskResult, type LatestRunRef } from "./store-contracts.js";
|
|
4
4
|
import type { RunStoreCheckpointProbe } from "./memory-run-store.js";
|
|
5
5
|
import type { LedgerEventType } from "../trace/ledger-events.js";
|
|
6
6
|
import { type SpaceCommitClaim, type SpaceCommitReading, type SpaceCommitState } from "../workspace-space-commit.js";
|
|
@@ -22,7 +22,7 @@ import { type SpaceCommitClaim, type SpaceCommitReading, type SpaceCommitState }
|
|
|
22
22
|
export declare class RunStoreStrictHydrateError extends StoreBootRefusalError {
|
|
23
23
|
readonly name = "RunStoreStrictHydrateError";
|
|
24
24
|
}
|
|
25
|
-
export declare class FileRunStore {
|
|
25
|
+
export declare class FileRunStore implements InProcessClaimFence {
|
|
26
26
|
private readonly runsDir;
|
|
27
27
|
private readonly activeDir;
|
|
28
28
|
private readonly tmpDir;
|
|
@@ -148,6 +148,8 @@ export declare class FileRunStore {
|
|
|
148
148
|
* [ref](codex R1 [medium]):认领 = 接管 `instanceId`(= 当前持有副本;SQL 孪生同注)。CAS 输不改。 */
|
|
149
149
|
markResuming(taskId: string, instanceId: string): Promise<boolean>;
|
|
150
150
|
getActiveTaskId(sessionId: string): Promise<string | undefined>;
|
|
151
|
+
/** 认领当写栅栏用(契约 = `store-contracts.ts` 的 `InProcessClaimFence`):判、刷新活性(同步落盘)与 `write` 是同一个同步段。 */
|
|
152
|
+
whileHoldingClaim(sessionId: string, taskId: string, write: () => FenceLanded): boolean;
|
|
151
153
|
getRun(taskId: string): Promise<RunRecord | undefined>;
|
|
152
154
|
/** Undo THIS submission's binding (key + body fingerprint → null) — called only where the submit surface refuses the submission
|
|
153
155
|
* before any work and terminalizes the row it just claimed (the sync leg's zero-work refusal, a device-placement reject):
|
|
@@ -161,17 +163,7 @@ export declare class FileRunStore {
|
|
|
161
163
|
/** The run a submission's scoped `Idempotency-Key` names (the file twin of `uq_task_run_idem`), if any. */
|
|
162
164
|
getRunByIdem(idemKey: string): Promise<RunRecord | undefined>;
|
|
163
165
|
/** Runs newest-first, keyset on (createdAt, taskId) DESC; optional exact-match filters (owner is exact, like the SQL). */
|
|
164
|
-
listRuns(opts:
|
|
165
|
-
status?: string;
|
|
166
|
-
jobId?: string;
|
|
167
|
-
source?: string;
|
|
168
|
-
owner?: string;
|
|
169
|
-
cursor?: {
|
|
170
|
-
createdAt: string;
|
|
171
|
-
taskId: string;
|
|
172
|
-
};
|
|
173
|
-
limit: number;
|
|
174
|
-
}): Promise<RunRecord[]>;
|
|
166
|
+
listRuns(opts: RunListQuery): Promise<RunRecord[]>;
|
|
175
167
|
/**
|
|
176
168
|
* S-297 —— 这个会话**最近一条腿**的窄指针({@link SqlRunStore.latestRunForSession} 的孪生:同一个排序口径
|
|
177
169
|
* `createdAt DESC, taskId DESC`,与本店 {@link FileRunStore.listSessions} 挑 `rn=1` 那一行的比较器逐字同一份)。
|
|
@@ -525,6 +525,15 @@ export class FileRunStore {
|
|
|
525
525
|
async getActiveTaskId(sessionId) {
|
|
526
526
|
return this.active.get(sessionId);
|
|
527
527
|
}
|
|
528
|
+
whileHoldingClaim(sessionId, taskId, write) {
|
|
529
|
+
const r = this.runs.get(taskId);
|
|
530
|
+
if (this.active.get(sessionId) !== taskId || r === undefined || r.status !== "running")
|
|
531
|
+
return false;
|
|
532
|
+
r.updatedAt = new Date();
|
|
533
|
+
this.persist(r);
|
|
534
|
+
write();
|
|
535
|
+
return true;
|
|
536
|
+
}
|
|
528
537
|
async getRun(taskId) {
|
|
529
538
|
const r = this.runs.get(taskId);
|
|
530
539
|
return r ? this.toRecord(r) : undefined;
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
* (requireExisting 的 host-first 重试仍落对店),中途 touch/noteTaskRun 缺路由=落 transient(no-op 级)。
|
|
25
25
|
*/
|
|
26
26
|
import { type SessionStore, type AcquiredSession, type SessionStoreSummary, type SessionPlacement, type PlacedSessionRow } from "@sema-agent/core";
|
|
27
|
+
import { type DelegationTree } from "../delegated-session-owner.js";
|
|
27
28
|
/** acquire 选项形(core 5.48 SessionStore 契约):[ref] placement=受信 spawner 的分区建会话声明。 */
|
|
28
29
|
type AcquireOpts = {
|
|
29
30
|
requireExisting?: boolean;
|
|
@@ -85,8 +86,15 @@ export declare class ForkRoutingSessionStore implements SessionStore {
|
|
|
85
86
|
* unpin 不落错店)。
|
|
86
87
|
*
|
|
87
88
|
* 已在 host(路由或真行)⇒ 幂等直返。两店都无此会话 ⇒ 抛(调用方=park veto,诚实 fail-closed)。
|
|
89
|
+
*
|
|
90
|
+
* S-1770:宿主行**在建行那一笔里**带属主 `owner` —— 调用方按委派继承律算好(`delegated-session-owner.ts`:委派树根的属主,
|
|
91
|
+
* 推不出 ⇒ 孤行哨兵;`tree` = 判据读到的委派树,判断用:宿主行记着别的树 ⇒ 拒),这里经宿主店的首写登记写下、再按律定夺(core `register` 契约:登记不判授权,判在复读)。
|
|
92
|
+
* 宿主店里同 id 已有一行:记着这一棵委派树且无主 ⇒ 按同一条律认领(只有记录委派树的店);别的树的 / 属主不是它(别人先认领的空壳,或 local 店的无主空壳)⇒ 抛(停驻否决),
|
|
93
|
+
* 转录不拷进别人的行;宿主店记不了 / 读不回属主 ⇒ 同样抛 —— 晋升出一只无主的转录行就是把它交给任何拿到 id 的人。
|
|
88
94
|
*/
|
|
89
|
-
promoteToHost(sessionId: string): Promise<void>;
|
|
95
|
+
promoteToHost(sessionId: string, owner: string | null, tree: DelegationTree): Promise<void>;
|
|
96
|
+
/** 晋升的建行那一笔(S-1770,规则见 {@link promoteToHost} 头注):宿主店首写登记 `owner`,然后按律定下宿主行的属主(与停驻快路同一只 `settleDelegatedOwner`)。 */
|
|
97
|
+
private registerPromotedOwner;
|
|
90
98
|
fork(sourceId: string, owner?: string | null): Promise<string | null>;
|
|
91
99
|
get size(): number;
|
|
92
100
|
dispose(): void | Promise<void>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SessionError } from "@sema-agent/core";
|
|
2
2
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
3
|
+
import { delegatedOwnerHostOf, settleDelegatedOwner } from "../delegated-session-owner.js";
|
|
3
4
|
const ROUTE_MAX = 8192;
|
|
4
5
|
export class ForkRoutingSessionStore {
|
|
5
6
|
host;
|
|
@@ -170,7 +171,7 @@ export class ForkRoutingSessionStore {
|
|
|
170
171
|
list() {
|
|
171
172
|
return this.transient.list?.() ?? Promise.resolve([]);
|
|
172
173
|
}
|
|
173
|
-
async promoteToHost(sessionId) {
|
|
174
|
+
async promoteToHost(sessionId, owner, tree) {
|
|
174
175
|
if (this.promoted.has(sessionId))
|
|
175
176
|
return;
|
|
176
177
|
if (this.route.get(sessionId) === "host") {
|
|
@@ -190,6 +191,7 @@ export class ForkRoutingSessionStore {
|
|
|
190
191
|
}
|
|
191
192
|
const entries = await src.session.getEntries();
|
|
192
193
|
const leaf = await src.session.getLeafId();
|
|
194
|
+
await this.registerPromotedOwner(sessionId, owner, tree);
|
|
193
195
|
const dst = await this.host.acquire(sessionId);
|
|
194
196
|
try {
|
|
195
197
|
const storage = dst.session.getStorage();
|
|
@@ -217,6 +219,15 @@ export class ForkRoutingSessionStore {
|
|
|
217
219
|
this.promoted.add(sessionId);
|
|
218
220
|
this.remember(sessionId, "host");
|
|
219
221
|
}
|
|
222
|
+
async registerPromotedOwner(sessionId, owner, tree) {
|
|
223
|
+
const register = this.host.register;
|
|
224
|
+
const host = delegatedOwnerHostOf(this.host);
|
|
225
|
+
if (register === undefined || host === undefined) {
|
|
226
|
+
throw new Error(`session "${sessionId}" cannot be promoted: the host session store cannot record or read back a session owner (register / ownerOf / sessionFaceOf; placementOf and claimOwnerless together or neither), so the promoted transcript would land ownerless`);
|
|
227
|
+
}
|
|
228
|
+
await register.call(this.host, sessionId, owner);
|
|
229
|
+
await settleDelegatedOwner(host, sessionId, owner, tree);
|
|
230
|
+
}
|
|
220
231
|
async fork(sourceId, owner) {
|
|
221
232
|
const routed = this.route.get(sourceId);
|
|
222
233
|
const tryFork = async (store, where) => {
|
|
@@ -34,6 +34,8 @@
|
|
|
34
34
|
import type { ChildProcess } from "node:child_process";
|
|
35
35
|
import { killProcessTree, type BackgroundHardKillOutcome } from "@sema-agent/core";
|
|
36
36
|
import type { Logger } from "../observability/logger.js";
|
|
37
|
+
/** 平台读点全仓一处(`test/host-shell-settle-order.test.ts` 源码钉);别处要平台串从这里取,不直读 Node 的平台字段。 */
|
|
38
|
+
export declare const HOST_PLATFORM: NodeJS.Platform;
|
|
37
39
|
export declare const IS_WIN32: boolean;
|
|
38
40
|
export interface HostShell {
|
|
39
41
|
shell: string;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import os from "node:os";
|
|
2
2
|
import { getShellConfig, killProcessTree, signalProcessTree } from "@sema-agent/core";
|
|
3
3
|
import { redactSecrets } from "../trace/redact.js";
|
|
4
|
-
export const
|
|
4
|
+
export const HOST_PLATFORM = process.platform;
|
|
5
|
+
export const IS_WIN32 = HOST_PLATFORM === "win32";
|
|
5
6
|
const POSIX_SH_FALLBACK = { shell: "/bin/sh", args: ["-c"] };
|
|
6
7
|
let cachedPosixShell;
|
|
7
8
|
let winShellState = { kind: "unsettled" };
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/** The longest the kill script itself may take beyond one control-plane wall: its re-check rounds (4 pauses of one second, plus slack). */
|
|
2
|
+
export declare const KILL_ALL_RECHECK_MS = 5000;
|
|
3
|
+
/**
|
|
4
|
+
* The pod-side "end all work" script: SIGKILL every LIVE process of the pod except pid 1, the container's keeper (`sleep infinity` — as pid 1, or as the child
|
|
5
|
+
* of the `sh` that is pid 1 when the pod's start command runs a hook first: killing it would end the container and with it the exec the snapshot needs) and this
|
|
6
|
+
* script's own shell — what a run-end snapshot needs of a command still running when its run is over (the pod is deleted right after; killing the exec socket would
|
|
7
|
+
* not stop the process, see the adapter's header). Exits 0 only when nothing it should have killed is alive any more: a killed process is re-checked (up to 5 rounds,
|
|
8
|
+
* one second apart, only while something is still alive) by its `State:` line — a zombie (`Z`, which a pid-1 `sleep` never reaps) is dead; a process that outlives the
|
|
9
|
+
* rounds makes the script exit 1, so the caller never reads a silent kill failure as a still tree. `procDir` is `/proc` (a test points it at a fake tree).
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildKillAllScript(procDir?: string): string;
|
|
1
12
|
/** The detached runner (base64'd into the pod, run under `setsid`). Self-reports pgid; streams output to out/err. */
|
|
2
13
|
export declare function buildBgRunnerScript(dir: string): string;
|
|
3
14
|
/** Short foreground launcher: writes cmd.sh + runner.sh, then `setsid`s the runner detached and returns immediately. */
|
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
import { shellQuote } from "./remote-shell.js";
|
|
2
|
+
export const KILL_ALL_RECHECK_MS = 5_000;
|
|
3
|
+
export function buildKillAllScript(procDir = "/proc") {
|
|
4
|
+
return [
|
|
5
|
+
'alive() { st=; while read -r k v; do [ "$k" = "State:" ] && st=${v%% *}; done 2>/dev/null < "$1/status"; [ -n "$st" ] && [ "$st" != Z ] && [ "$st" != X ]; }',
|
|
6
|
+
`keeper() { [ "$(tr '\\0' ' ' 2>/dev/null < "$1/cmdline")" = "sleep infinity " ]; }`,
|
|
7
|
+
'spare() { pid=${1##*/}; [ "$pid" = 1 ] || [ "$pid" = "$$" ] || keeper "$1"; }',
|
|
8
|
+
"round=0",
|
|
9
|
+
"while :; do",
|
|
10
|
+
"left=0",
|
|
11
|
+
`for p in ${shellQuote(procDir)}/[0-9]*; do`,
|
|
12
|
+
'spare "$p" && continue',
|
|
13
|
+
'alive "$p" || continue',
|
|
14
|
+
"left=1",
|
|
15
|
+
'kill -9 "${p##*/}" 2>/dev/null',
|
|
16
|
+
"done",
|
|
17
|
+
'[ "$left" = 0 ] && exit 0',
|
|
18
|
+
"round=$((round + 1))",
|
|
19
|
+
'[ "$round" -ge 5 ] && exit 1',
|
|
20
|
+
"sleep 1",
|
|
21
|
+
"done",
|
|
22
|
+
].join("\n");
|
|
23
|
+
}
|
|
2
24
|
export function buildBgRunnerScript(dir) {
|
|
3
25
|
const q = (name) => shellQuote(`${dir}/${name}`);
|
|
4
26
|
return [
|
|
@@ -98,6 +98,8 @@ export declare class LocalCheckpointStore {
|
|
|
98
98
|
/** All still-pending checkpoints across the registered scopes (summary + full row via get). */
|
|
99
99
|
private pendings;
|
|
100
100
|
/** Operator approval queue — the same NON-secret card as the SQL twins (never the token). */
|
|
101
|
+
/** 每一只待决 checkpoint 的会话(去重;不按门型过滤 —— 理由与 SQL 孪生 `listPendingSessionIds` 逐字同,见那里)。 */
|
|
102
|
+
listPendingSessionIds(): Promise<string[]>;
|
|
101
103
|
listPending(scope?: string): Promise<PendingCheckpoint[]>;
|
|
102
104
|
/**
|
|
103
105
|
* [ref]:与 SQL 孪生**同判**的 session 键读口 —— `binding.gateKinds` 过滤门型、序恒「最新优先,token 兜平局」
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { parkedApprovalCard } from "../approval-content-kind.js";
|
|
3
3
|
import { parkRowFacts } from "../approval-card.js";
|
|
4
|
+
import { durableRowIdentity } from "../checkpoint-identity.js";
|
|
4
5
|
import { createHash } from "node:crypto";
|
|
5
6
|
import { existsSync, readFileSync, readdirSync, unlinkSync, mkdirSync } from "node:fs";
|
|
6
7
|
import { join } from "node:path";
|
|
7
8
|
import { denySweepOwns } from "../tool-approval.js";
|
|
8
9
|
import { FileCheckpointStore, atomicWriteFile, executionVerdict, sanitizePathComponent, } from "@sema-agent/core";
|
|
9
|
-
import { approvalDecisionOfWinner, approvalPayloadFingerprint, boundedRuleOffers, boundedToolInput, pendingActionToolCallId, pendingRowPrecedes, TERMINAL_BACKSTOP_MS, TERMINAL_GRACE_MS } from "./checkpoint-store-sql.js";
|
|
10
|
+
import { approvalDecisionOfWinner, approvalPayloadFingerprint, boundedRuleOffers, boundedToolInput, pendingActionToolCallId, pendingRowPrecedes, queueRowGateKind, TERMINAL_BACKSTOP_MS, TERMINAL_GRACE_MS } from "./checkpoint-store-sql.js";
|
|
10
11
|
import { quarantineUnreadableSidecar } from "./local-sidecar-quarantine.js";
|
|
11
12
|
import { createZodColumnReader, decodeJsonColumn, foldJsonColumn, readStringArrayColumn } from "./sql-json-column.js";
|
|
12
13
|
import { UNMANAGED_RETENTION } from "./retention-store-sql.js";
|
|
@@ -160,20 +161,27 @@ export class LocalCheckpointStore {
|
|
|
160
161
|
}
|
|
161
162
|
return out;
|
|
162
163
|
}
|
|
164
|
+
async listPendingSessionIds() {
|
|
165
|
+
return [...new Set((await this.pendings()).map(({ cp }) => cp.sessionId))];
|
|
166
|
+
}
|
|
163
167
|
async listPending(scope) {
|
|
164
168
|
const rows = [];
|
|
165
|
-
for (const { cp } of await this.pendings(scope)) {
|
|
169
|
+
for (const { token, cp } of await this.pendings(scope)) {
|
|
166
170
|
const pa = cp.pendingAction;
|
|
167
171
|
const gate = cp.gate;
|
|
172
|
+
const gateKind = queueRowGateKind(gate?.kind);
|
|
173
|
+
if (gateKind === undefined)
|
|
174
|
+
continue;
|
|
168
175
|
const toolCallId = pa?.toolCallId ?? null;
|
|
169
176
|
rows.push({
|
|
170
177
|
sessionId: cp.sessionId,
|
|
178
|
+
...durableRowIdentity("approvals-queue", cp.checkpointId, token),
|
|
171
179
|
scope: cp.scope,
|
|
172
180
|
toolName: pa?.toolName ?? null,
|
|
173
181
|
toolCallId,
|
|
174
182
|
...(toolCallId !== null ? { boundCallId: toolCallId } : {}),
|
|
175
183
|
...(pa?.boundInputHash !== undefined ? { boundInputHash: pa.boundInputHash } : {}),
|
|
176
|
-
|
|
184
|
+
gateKind,
|
|
177
185
|
taskId: (await this.opts.getActiveTaskId?.(cp.sessionId)) ?? null,
|
|
178
186
|
input: boundedToolInput(pa?.args),
|
|
179
187
|
createdAt: cp.createdAt,
|
|
@@ -7,7 +7,7 @@ import { type InstructionSourceBaseline } from "../instruction-source-notice.js"
|
|
|
7
7
|
import { type StagingHandle, type SyncRelation } from "../session-sync-kernel.js";
|
|
8
8
|
/**
|
|
9
9
|
* local 车道会话存档的**唯一 repo 出口**:本仓里每一只读 `<root>/sessions/*.jsonl` 的 `FileSessionRepo` 都从这里取(`LocalSessionStore` 的底座与会话视图口
|
|
10
|
-
* `
|
|
10
|
+
* 窗口 `local-session-window.ts#LocalSessionWindow.wake` 的读旁路),所以坏记录的披露座只有这一份接线 —— 修前视图口自建一只不带座的 repo,同一份坏档在这里读到有计数 / 探针,
|
|
11
11
|
* 在视图口读到一个字都没有。座 = F 类 `server.session-repo.corrupt-record-skipped`(会话存档里读不出的记录丢的是可用性:历史少一截 / 列表少一行,不开任何门;
|
|
12
12
|
* 计数单位 = 一条被跳过的记录,逐命中探针行,warn 每进程一次),外加会话打开作用域的计数腿(`noteReplayInSessionOpenScope`:只在 `openSessionForItself`
|
|
13
13
|
* 的作用域里才记,作用域外 —— 列表 / 导出 / 视图口 —— 是空操作,那些读只进运维面)。
|
|
@@ -642,7 +642,7 @@ export class LocalSessionStore {
|
|
|
642
642
|
const current = await this.metaOf(sessionId);
|
|
643
643
|
const prior = current === undefined ? undefined : { owner: current.owner ?? null, incarnation: current.incarnation };
|
|
644
644
|
await this.deleteSessionHeld(sessionId, owner);
|
|
645
|
-
await this.importEntriesAs(sessionId, owner, entries, carriedIncarnation(prior, owner));
|
|
645
|
+
await this.importEntriesAs(sessionId, owner, entries, carriedIncarnation(sessionId, prior, owner));
|
|
646
646
|
}
|
|
647
647
|
beginImportStaging(realSessionId, token) {
|
|
648
648
|
const h = new LocalStagingHandle(this, realSessionId, stagingIdFor(realSessionId, token));
|