@sema-agent/server 7.150.0 → 7.152.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 +451 -0
- package/README.md +15 -3
- package/README.zh-CN.md +10 -2
- package/USAGE.md +144 -87
- package/deploy/sema-up/README.md +11 -4
- package/deploy/sema-up/chart/Chart.yaml +1 -1
- package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
- package/deploy/sema-up/chart/templates/server.yaml +5 -3
- package/deploy/sema-up/chart/values-full-single.yaml +3 -1
- package/deploy/sema-up/chart/values.yaml +8 -1
- package/deploy/sema-up/cluster-up.sh +7 -6
- package/deploy/sema-up/kube-up.sh +6 -6
- package/deploy/sema-up/lib/flagshape.sh +36 -8
- package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
- package/deploy/sema-up/lib/helm-values-kube.py +2 -0
- package/deploy/sema-up/machines.example.yaml +3 -1
- package/deploy/sema-up/sema-up.sh +22 -16
- package/dist/adoption/import.js +3 -3
- package/dist/approval-ask-audit-store.d.ts +1 -1
- package/dist/approval-ask-machine.d.ts +4 -10
- package/dist/approval-ask-retention.d.ts +1 -1
- package/dist/approval-card.d.ts +12 -14
- package/dist/approval-gate-currency.d.ts +9 -9
- package/dist/approval-gate-currency.js +3 -4
- package/dist/approval-hmac.d.ts +17 -1
- package/dist/approval-hmac.js +7 -1
- package/dist/approval-queue-kind.d.ts +1 -1
- package/dist/approval.d.ts +2 -2
- package/dist/approval.js +2 -2
- package/dist/auth-bridge.d.ts +20 -0
- package/dist/auth-bridge.js +9 -0
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/bake-runner/main.d.ts +4 -2
- package/dist/bind-host.d.ts +3 -6
- package/dist/bind-host.js +4 -7
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/coordinators.d.ts +1 -1
- package/dist/boot/coordinators.js +9 -10
- package/dist/boot/device-lane.js +2 -0
- package/dist/boot/engine-lease.d.ts +5 -0
- package/dist/boot/engine-lease.js +1 -0
- package/dist/boot/execution-env.d.ts +9 -14
- package/dist/boot/execution-env.js +85 -22
- package/dist/boot/execution-lane.js +32 -5
- package/dist/boot/late-binds.d.ts +8 -4
- package/dist/boot/late-binds.js +7 -1
- package/dist/boot/leader.d.ts +31 -30
- package/dist/boot/leader.js +38 -28
- package/dist/boot/leg-path-adjudication.d.ts +40 -0
- package/dist/boot/leg-path-adjudication.js +18 -0
- package/dist/boot/memory-consolidation.d.ts +3 -2
- package/dist/boot/memory-consolidation.js +6 -6
- package/dist/boot/parked-revive-gate.js +3 -15
- package/dist/boot/reapers.d.ts +6 -1
- package/dist/boot/reapers.js +13 -2
- package/dist/boot/resolve-spec.d.ts +3 -3
- package/dist/boot/resolve-spec.js +43 -48
- package/dist/boot/runner-deps.d.ts +46 -35
- package/dist/boot/runner-deps.js +94 -91
- package/dist/boot/session-age-out.d.ts +36 -0
- package/dist/boot/session-age-out.js +101 -0
- package/dist/boot/session-faces.d.ts +5 -14
- package/dist/boot/session-faces.js +9 -5
- package/dist/boot/shutdown.d.ts +6 -0
- package/dist/boot/shutdown.js +10 -4
- package/dist/boot/stage-01-config.js +2 -0
- package/dist/boot/stage-02-web-admin-pull.js +4 -5
- package/dist/boot/stage-05-execution-env.d.ts +5 -3
- package/dist/boot/stage-05-execution-env.js +3 -2
- package/dist/boot/stage-06-runners.d.ts +9 -4
- package/dist/boot/stage-06-runners.js +24 -9
- package/dist/boot/stage-07-capability-layer.d.ts +8 -4
- package/dist/boot/stage-07-capability-layer.js +3 -2
- package/dist/boot/stage-08-reapers.d.ts +8 -4
- package/dist/boot/stage-08-reapers.js +4 -2
- package/dist/boot/stage-09-leader.d.ts +12 -5
- package/dist/boot/stage-09-leader.js +14 -5
- package/dist/boot/stage-10-http-server.d.ts +19 -5
- package/dist/boot/stage-10-http-server.js +14 -21
- package/dist/boot/stores.js +7 -4
- package/dist/boot/web-admin.js +5 -8
- package/dist/boot/workflow-orchestration.d.ts +7 -2
- package/dist/boot/workflow-orchestration.js +24 -7
- package/dist/bounded-rotation.d.ts +29 -0
- package/dist/bounded-rotation.js +24 -0
- package/dist/capabilities/approvals-push.d.ts +3 -3
- package/dist/capabilities/scenarios.d.ts +28 -13
- package/dist/capabilities/scenarios.js +2 -2
- package/dist/capability-facts.d.ts +43 -32
- package/dist/capability-facts.js +45 -51
- package/dist/card-rule-offers.d.ts +32 -0
- package/dist/card-rule-offers.js +130 -0
- package/dist/center-credential.d.ts +25 -6
- package/dist/center-credential.js +25 -5
- package/dist/config-catalog.d.ts +26 -7
- package/dist/config-catalog.js +26 -22
- package/dist/config-dir-trust.js +4 -2
- package/dist/config-invariants.d.ts +20 -8
- package/dist/config-invariants.js +55 -12
- package/dist/config-lkg.d.ts +5 -19
- package/dist/config-lkg.js +8 -62
- package/dist/config-provider.d.ts +1 -1
- package/dist/config-root-migration.d.ts +2 -2
- package/dist/config-types.d.ts +38 -42
- package/dist/config.d.ts +58 -7
- package/dist/config.js +90 -40
- package/dist/control-socket.d.ts +51 -0
- package/dist/control-socket.js +115 -0
- package/dist/deployment-governance.d.ts +2 -1
- package/dist/deployment-shape.d.ts +9 -1
- package/dist/deployment-shape.js +2 -1
- package/dist/device-protocol.d.ts +5 -4
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.d.ts +7 -0
- package/dist/device-ws-hub.js +10 -3
- package/dist/device-ws-protocol.d.ts +63 -10
- package/dist/device-ws-protocol.js +56 -25
- package/dist/elicitation.js +2 -2
- package/dist/engine-identity.d.ts +19 -7
- package/dist/engine-identity.js +10 -2
- package/dist/entry-mode-clamp-notice.d.ts +2 -1
- package/dist/entry-problems.d.ts +40 -3
- package/dist/entry-problems.js +3 -1
- package/dist/execution-env-refusal.d.ts +29 -0
- package/dist/execution-env-refusal.js +8 -0
- package/dist/execution-lane-caps.d.ts +3 -1
- package/dist/field-conflict.d.ts +1 -1
- package/dist/file-history-capture.d.ts +11 -4
- package/dist/file-history-capture.js +9 -6
- package/dist/file-history-disclosure.d.ts +7 -5
- package/dist/file-history-disclosure.js +7 -5
- package/dist/fleet/drain-entry.d.ts +4 -0
- package/dist/fleet/engine-signal.d.ts +12 -29
- package/dist/fleet/engine-signal.js +1 -7
- package/dist/fleet-client.js +2 -5
- package/dist/gate-settlement.d.ts +1 -8
- package/dist/gate-settlement.js +0 -4
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +2 -3
- package/dist/hitl-delivery.js +0 -2
- package/dist/hooks/hook-llm.js +4 -2
- package/dist/hooks/hook-runner.d.ts +3 -2
- package/dist/hooks/hook-runner.js +18 -3
- package/dist/host-decision.d.ts +11 -11
- package/dist/host-lsp-manager.d.ts +2 -2
- package/dist/http/active-run-conflict.d.ts +35 -2
- package/dist/http/active-run-conflict.js +48 -19
- package/dist/http/admission.js +17 -2
- package/dist/http/approval-sweeps.d.ts +1 -1
- package/dist/http/approval-sweeps.js +10 -7
- package/dist/http/checkpoint-ctx.d.ts +4 -0
- package/dist/http/checkpoint-ctx.js +2 -0
- package/dist/http/dispatch.d.ts +8 -3
- package/dist/http/dispatch.js +59 -32
- package/dist/http/durable-run-leg.js +16 -17
- package/dist/http/health-reader.d.ts +16 -9
- package/dist/http/health-reader.js +2 -1
- package/dist/http/health-self-report.d.ts +9 -1
- package/dist/http/health-self-report.js +3 -1
- package/dist/http/owner-access.d.ts +33 -14
- package/dist/http/owner-access.js +40 -10
- package/dist/http/principal-gate.d.ts +49 -21
- package/dist/http/principal-gate.js +61 -11
- package/dist/http/request-channel.d.ts +23 -0
- package/dist/http/request-channel.js +9 -0
- package/dist/http/request-guards.js +17 -2
- package/dist/http/resume-ctx-read.js +42 -3
- package/dist/http/resume-legs.d.ts +4 -3
- package/dist/http/resume-legs.js +367 -117
- package/dist/http/route-ctx.d.ts +91 -15
- package/dist/http/route-ctx.js +17 -0
- package/dist/http/route-table.d.ts +5 -1
- package/dist/http/route-table.js +4 -0
- package/dist/http/routes/admin-config-refresh.js +3 -3
- package/dist/http/routes/admin-drain.d.ts +3 -0
- package/dist/http/routes/admin-drain.js +7 -7
- package/dist/http/routes/admin-memory-optout.d.ts +1 -1
- package/dist/http/routes/admin-memory-optout.js +3 -3
- package/dist/http/routes/adoption.js +3 -5
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.d.ts +2 -1
- package/dist/http/routes/approvals-assistant.js +99 -51
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/capabilities.d.ts +4 -0
- package/dist/http/routes/capabilities.js +38 -10
- package/dist/http/routes/config-catalog.js +2 -2
- package/dist/http/routes/devices.js +1 -1
- package/dist/http/routes/diagnostics.d.ts +3 -3
- package/dist/http/routes/diagnostics.js +19 -7
- package/dist/http/routes/fleet.js +10 -8
- package/dist/http/routes/images.js +10 -10
- package/dist/http/routes/memory-bundle.js +3 -3
- package/dist/http/routes/memory-compliance.js +3 -3
- package/dist/http/routes/memory-consolidation.js +2 -2
- package/dist/http/routes/memory-origin.js +3 -3
- package/dist/http/routes/memory-policy.js +2 -2
- package/dist/http/routes/observability.js +3 -3
- package/dist/http/routes/projects.d.ts +3 -2
- package/dist/http/routes/projects.js +4 -5
- package/dist/http/routes/retention-ops.js +3 -3
- package/dist/http/routes/rules.js +5 -5
- package/dist/http/routes/run-permission-mode.d.ts +2 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +4 -9
- package/dist/http/routes/runs.js +171 -65
- package/dist/http/routes/session-sync.d.ts +22 -9
- package/dist/http/routes/session-sync.js +204 -107
- package/dist/http/routes/sessions-list.js +13 -7
- package/dist/http/routes/sessions.js +30 -15
- package/dist/http/routes/tasks.js +46 -41
- package/dist/http/routes/trace-usage.js +2 -2
- package/dist/http/routes/workflows.js +1 -1
- package/dist/http/server.d.ts +30 -30
- package/dist/http/server.js +16 -4
- package/dist/http/submit-ctx.d.ts +1 -1
- package/dist/http/submit-ctx.js +7 -4
- package/dist/http/wire-types.d.ts +14 -4
- package/dist/human-facing-args.d.ts +33 -0
- package/dist/human-facing-args.js +33 -0
- package/dist/identity-source.d.ts +20 -3
- package/dist/identity-source.js +14 -0
- package/dist/index.d.ts +5 -1
- package/dist/k8s-api-credentials.d.ts +29 -0
- package/dist/k8s-api-credentials.js +25 -0
- package/dist/lane-home-probe.d.ts +3 -7
- package/dist/lane-home-probe.js +2 -2
- package/dist/leader/diffup.d.ts +19 -0
- package/dist/leader/diffup.js +7 -0
- package/dist/leader/leader.d.ts +116 -11
- package/dist/leader/leader.js +69 -5
- package/dist/leader/repair-wire.js +2 -2
- package/dist/leader/run-entry.d.ts +2 -1
- package/dist/leader/run-entry.js +1 -1
- package/dist/leader/wire.d.ts +42 -132
- package/dist/leader/wire.js +81 -67
- package/dist/leg-facts.d.ts +13 -5
- package/dist/leg-facts.js +2 -1
- package/dist/memory-scope.d.ts +23 -11
- package/dist/memory-scope.js +18 -6
- package/dist/memory-sync-client.d.ts +30 -2
- package/dist/memory-sync-client.js +16 -9
- package/dist/model-entry-headers.d.ts +9 -10
- package/dist/model-entry-headers.js +0 -4
- package/dist/model-entry-refusal.d.ts +7 -4
- package/dist/model-entry-refusal.js +11 -5
- package/dist/model-plane-face.d.ts +1 -1
- package/dist/model-plane-face.js +3 -1
- package/dist/model-route-endpoint.d.ts +13 -7
- package/dist/model-route-endpoint.js +14 -11
- package/dist/model-select.d.ts +22 -0
- package/dist/model-select.js +9 -0
- package/dist/model-unreachable-notice.d.ts +11 -0
- package/dist/model-unreachable-notice.js +4 -4
- package/dist/object-store-buckets.d.ts +640 -6
- package/dist/object-store-buckets.js +166 -0
- package/dist/observability/err-text.d.ts +7 -0
- package/dist/observability/err-text.js +5 -0
- package/dist/observability/fail-open.d.ts +25 -17
- package/dist/observability/fail-open.js +25 -17
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -0
- package/dist/operator-roster.d.ts +68 -0
- package/dist/operator-roster.js +32 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
- package/dist/orchestration/workflow-notify-journal.js +12 -1
- package/dist/orchestration/workflow-park-decision.d.ts +70 -18
- package/dist/orchestration/workflow-park-decision.js +49 -10
- package/dist/orchestration/workflow-park-holder.d.ts +65 -0
- package/dist/orchestration/workflow-park-holder.js +98 -0
- package/dist/orchestration/workflow-record-fence.d.ts +36 -0
- package/dist/orchestration/workflow-record-fence.js +42 -0
- package/dist/outbound-dispatcher.d.ts +71 -8
- package/dist/outbound-dispatcher.js +48 -7
- package/dist/owner-faces.d.ts +2 -2
- package/dist/parked-decide.d.ts +106 -55
- package/dist/parked-decide.js +153 -117
- package/dist/peer-directory.d.ts +2 -2
- package/dist/peer-inbound-face.d.ts +2 -6
- package/dist/peer-inbound-face.js +0 -3
- package/dist/permission-mode-admission.d.ts +74 -5
- package/dist/permission-mode-admission.js +56 -3
- package/dist/plugins/adoption-log-sql.d.ts +3 -1
- package/dist/plugins/adoption-log-sql.js +7 -1
- package/dist/plugins/approval-ask-store-file.d.ts +14 -2
- package/dist/plugins/approval-ask-store-file.js +11 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +10 -1
- package/dist/plugins/approval-ask-store-memory.js +35 -10
- package/dist/plugins/approval-ask-store-sql.d.ts +69 -4
- package/dist/plugins/approval-ask-store-sql.js +45 -5
- package/dist/plugins/approval-exemption-store.js +3 -0
- package/dist/plugins/approval-nonce-store.js +2 -0
- package/dist/plugins/blob-backend.d.ts +83 -7
- package/dist/plugins/blob-backend.js +57 -6
- package/dist/plugins/breaker-state-sql.js +2 -0
- package/dist/plugins/caching-session-store.d.ts +9 -15
- package/dist/plugins/caching-session-store.js +6 -0
- package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
- package/dist/plugins/checkpoint-index-columns.js +3 -6
- package/dist/plugins/checkpoint-store-face.d.ts +119 -61
- package/dist/plugins/checkpoint-store-face.js +134 -55
- package/dist/plugins/device-store-sql.js +6 -0
- package/dist/plugins/error-origin.d.ts +18 -0
- package/dist/plugins/error-origin.js +10 -0
- package/dist/plugins/execution-placement-sql.js +6 -6
- package/dist/plugins/image-bake-store-sql.js +6 -0
- package/dist/plugins/image-index-sql.js +4 -0
- package/dist/plugins/landed-attendants.d.ts +212 -0
- package/dist/plugins/landed-attendants.js +161 -0
- package/dist/plugins/leader-run-store-sql.js +4 -0
- package/dist/plugins/local-checkpoint-store.d.ts +13 -3
- package/dist/plugins/local-checkpoint-store.js +38 -49
- package/dist/plugins/local-session-live-reference.d.ts +40 -0
- package/dist/plugins/local-session-live-reference.js +39 -0
- package/dist/plugins/local-session-store.d.ts +71 -33
- package/dist/plugins/local-session-store.js +129 -27
- package/dist/plugins/memory-engine-pg.js +4 -0
- package/dist/plugins/memory-engine-sql-apply.js +5 -2
- package/dist/plugins/memory-engine-tidb.js +4 -0
- package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
- package/dist/plugins/memory-sync-store-pg.js +5 -0
- package/dist/plugins/memory-sync-store-tidb.js +5 -0
- package/dist/plugins/one-time-migrations.d.ts +104 -80
- package/dist/plugins/one-time-migrations.js +226 -132
- package/dist/plugins/org-delivery-quota-store.js +4 -1
- package/dist/plugins/outcome-ledger-sql.js +2 -0
- package/dist/plugins/permission-rule-store-sql.js +11 -4
- package/dist/plugins/pg-cost-quota.js +4 -0
- package/dist/plugins/pg-pool.js +35 -10
- package/dist/plugins/pg-rate-limiter.js +2 -0
- package/dist/plugins/posix-shell-fs.d.ts +6 -1
- package/dist/plugins/posix-shell-fs.js +4 -1
- package/dist/plugins/remote-env-adb.d.ts +19 -15
- package/dist/plugins/remote-env-adb.js +41 -15
- package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
- package/dist/plugins/remote-env-connect-seat.js +72 -0
- package/dist/plugins/remote-env-device.d.ts +22 -5
- package/dist/plugins/remote-env-device.js +106 -8
- package/dist/plugins/remote-env-e2b.d.ts +15 -6
- package/dist/plugins/remote-env-e2b.js +42 -32
- package/dist/plugins/remote-env-file-error.js +6 -2
- package/dist/plugins/remote-env-host.d.ts +46 -10
- package/dist/plugins/remote-env-host.js +124 -52
- package/dist/plugins/remote-env-k8s.d.ts +109 -41
- package/dist/plugins/remote-env-k8s.js +160 -54
- package/dist/plugins/remote-env-local-docker.d.ts +13 -8
- package/dist/plugins/remote-env-local-docker.js +34 -41
- package/dist/plugins/remote-env-ssh.d.ts +18 -12
- package/dist/plugins/remote-env-ssh.js +60 -59
- package/dist/plugins/remote-shell.d.ts +98 -1
- package/dist/plugins/remote-shell.js +218 -0
- package/dist/plugins/replica-registration.d.ts +1 -1
- package/dist/plugins/replica-registration.js +1 -1
- package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
- package/dist/plugins/resume-anchor-store-sql.js +12 -5
- package/dist/plugins/retention-lane-store-sql.js +4 -0
- package/dist/plugins/retention-sql.d.ts +20 -2
- package/dist/plugins/retention-sql.js +11 -0
- package/dist/plugins/run-store-sql.d.ts +21 -2
- package/dist/plugins/run-store-sql.js +31 -7
- package/dist/plugins/s3-presign.d.ts +23 -0
- package/dist/plugins/s3-presign.js +37 -3
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
- package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
- package/dist/plugins/scheduler-support.d.ts +2 -2
- package/dist/plugins/scheduler-support.js +0 -3
- package/dist/plugins/schema-consistency.d.ts +4 -2
- package/dist/plugins/schema-consistency.js +19 -2
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-file-ledger.d.ts +2 -2
- package/dist/plugins/send-file-ledger.js +5 -2
- package/dist/plugins/send-user-file.d.ts +3 -4
- package/dist/plugins/send-user-file.js +56 -52
- package/dist/plugins/serving-requirement.d.ts +26 -7
- package/dist/plugins/serving-requirement.js +11 -4
- package/dist/plugins/session-birth.d.ts +6 -2
- package/dist/plugins/session-blob-claim-token.d.ts +15 -0
- package/dist/plugins/session-blob-claim-token.js +20 -0
- package/dist/plugins/session-blob-namespace.d.ts +46 -0
- package/dist/plugins/session-blob-namespace.js +116 -0
- package/dist/plugins/session-capture-record-store-sql.js +2 -0
- package/dist/plugins/session-ext-table.d.ts +14 -1
- package/dist/plugins/session-ext-table.js +5 -1
- package/dist/plugins/session-row-sql.d.ts +49 -2
- package/dist/plugins/session-row-sql.js +56 -13
- package/dist/plugins/session-store-sql.d.ts +34 -18
- package/dist/plugins/session-store-sql.js +98 -17
- package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
- package/dist/plugins/shared-memory-store-sql.js +6 -2
- package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
- package/dist/plugins/snapshot-bucket-presence.js +8 -2
- package/dist/plugins/sql-driver.d.ts +2 -1
- package/dist/plugins/sql-driver.js +18 -3
- package/dist/plugins/sql-errors.d.ts +11 -6
- package/dist/plugins/sql-errors.js +5 -6
- package/dist/plugins/sql-json-column.d.ts +1 -1
- package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
- package/dist/plugins/stop-then-start-sentence.js +14 -10
- package/dist/plugins/stop-then-start.d.ts +109 -0
- package/dist/plugins/stop-then-start.js +104 -0
- package/dist/plugins/store-backend.d.ts +84 -15
- package/dist/plugins/store-backend.js +236 -72
- package/dist/plugins/store-boundary.d.ts +57 -0
- package/dist/plugins/store-boundary.js +139 -0
- package/dist/plugins/store-contracts.d.ts +17 -0
- package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
- package/dist/plugins/store-fault-sentence-m53.js +25 -0
- package/dist/plugins/store-fault.d.ts +26 -7
- package/dist/plugins/store-fault.js +18 -2
- package/dist/plugins/task-attachment-store.d.ts +2 -1
- package/dist/plugins/task-attachment-store.js +14 -1
- package/dist/plugins/task-list-store-sql.d.ts +2 -2
- package/dist/plugins/task-list-store-sql.js +10 -8
- package/dist/plugins/tidb-cost-quota.js +4 -0
- package/dist/plugins/tidb-pool.js +21 -25
- package/dist/plugins/tidb-rate-limiter.js +4 -0
- package/dist/plugins/user-input-ledger-sql.js +4 -0
- package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
- package/dist/plugins/workflow-run-store-sql.js +64 -4
- package/dist/plugins/workspace-custody.d.ts +4 -3
- package/dist/plugins/workspace-fill.d.ts +4 -7
- package/dist/plugins/workspace-fill.js +2 -1
- package/dist/plugins/write-behind-counter.js +5 -0
- package/dist/project-context.d.ts +0 -2
- package/dist/project-context.js +4 -8
- package/dist/project-registry.d.ts +46 -0
- package/dist/project-registry.js +44 -0
- package/dist/question.d.ts +2 -1
- package/dist/question.js +5 -13
- package/dist/request-form.d.ts +6 -1
- package/dist/request-form.js +4 -1
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +4 -0
- package/dist/request-value-closure.js +10 -0
- package/dist/rule-issue-reading.d.ts +1 -1
- package/dist/rules-consent.d.ts +1 -1
- package/dist/run-acceptance.d.ts +3 -2
- package/dist/run-acceptance.js +4 -6
- package/dist/run-local.js +9 -9
- package/dist/runs.d.ts +54 -16
- package/dist/runs.js +67 -13
- package/dist/runtime-governance.d.ts +5 -4
- package/dist/security.d.ts +30 -32
- package/dist/security.js +41 -7
- package/dist/sema-config-dir.d.ts +2 -1
- package/dist/server-secret-env.d.ts +12 -10
- package/dist/server-secret-env.js +24 -15
- package/dist/session-bindings.d.ts +82 -0
- package/dist/session-bindings.js +18 -0
- package/dist/session-children-retire.d.ts +2 -2
- package/dist/session-children-retire.js +2 -6
- package/dist/session-deletion.d.ts +16 -1
- package/dist/session-error-wire.d.ts +3 -3
- package/dist/session-error-wire.js +3 -3
- package/dist/session-incarnation.d.ts +10 -0
- package/dist/session-incarnation.js +10 -1
- package/dist/session-kind.d.ts +57 -0
- package/dist/session-kind.js +22 -0
- package/dist/session-row.d.ts +21 -1
- package/dist/session-row.js +7 -1
- package/dist/session-sync-kernel.d.ts +24 -14
- package/dist/session-sync-kernel.js +3 -6
- package/dist/session-sync.d.ts +25 -103
- package/dist/session-sync.js +14 -76
- package/dist/session-titler.d.ts +10 -3
- package/dist/session-titler.js +19 -6
- package/dist/ssh-host-key.d.ts +5 -0
- package/dist/ssh-host-key.js +3 -0
- package/dist/stores-sql/blob-index-sql.d.ts +30 -9
- package/dist/stores-sql/blob-index-sql.js +40 -21
- package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
- package/dist/stores-sql/checkpoint-store-sql.js +70 -146
- package/dist/stores-sql/file-history-store-sql.d.ts +113 -15
- package/dist/stores-sql/file-history-store-sql.js +205 -95
- package/dist/stores-sql/pg-session-storage.d.ts +34 -7
- package/dist/stores-sql/pg-session-storage.js +37 -13
- package/dist/stores-sql/retention-store-sql.d.ts +1 -9
- package/dist/stores-sql/retention-store-sql.js +5 -19
- package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
- package/dist/stores-sql/session-policy-store-sql.js +61 -44
- package/dist/stores-sql/session-write-hooks.d.ts +11 -0
- package/dist/stores-sql/tidb-session-store.d.ts +58 -7
- package/dist/stores-sql/tidb-session-store.js +37 -13
- package/dist/submission-exit.d.ts +3 -2
- package/dist/submission-exit.js +9 -1
- package/dist/task-cwd.d.ts +2 -2
- package/dist/task-settings.d.ts +7 -5
- package/dist/task-settings.js +3 -3
- package/dist/terminal.d.ts +33 -2
- package/dist/terminal.js +139 -9
- package/dist/tool-approval.d.ts +465 -507
- package/dist/tool-approval.js +606 -1222
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/ledger-events.d.ts +3 -3
- package/dist/trace/project.d.ts +2 -3
- package/dist/trace/redact.js +3 -2
- package/dist/trace/self-minted-wire.d.ts +571 -178
- package/dist/trace/self-minted-wire.js +189 -56
- package/dist/web-admin-client/apply-effective.js +2 -2
- package/dist/web-admin-client/read-warnings.d.ts +2 -2
- package/dist/web-admin-client/read-warnings.js +1 -1
- package/dist/web-admin-client/types.d.ts +1 -1
- package/dist/workspace-space.d.ts +10 -4
- package/dist/workspace-space.js +4 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +79 -28
- package/package.json +7 -3
- package/scripts/embed-minimal.mjs +3 -3
- package/wire-changes/server@7.151.0.json +762 -0
- package/wire-changes/server@7.152.0.json +900 -0
- package/dist/config-d-migration.d.ts +0 -37
- package/dist/config-d-migration.js +0 -60
- package/dist/http/session-inherit-env.d.ts +0 -36
- package/dist/http/session-inherit-env.js +0 -6
|
@@ -9,6 +9,7 @@ import { decodeJsonColumn, foldJsonColumn, jsonColumnText, readJsonObjectColumn,
|
|
|
9
9
|
import { ensureIndexes } from "./ensure-index.js";
|
|
10
10
|
import { isExecutionLane } from "../execution-lane-caps.js";
|
|
11
11
|
import { retiredExecutionLaneHintM40 } from "./execution-lane-rename-m40.js";
|
|
12
|
+
import { sealStoreClass } from "./store-boundary.js";
|
|
12
13
|
export function assertIntegralEpochMs(field, value) {
|
|
13
14
|
if (!Number.isSafeInteger(value)) {
|
|
14
15
|
throw new TypeError(`approval-ask store: ${field} must be an integer epoch-ms (BIGINT column), got ${String(value)}`);
|
|
@@ -120,6 +121,13 @@ export function projectAskTerminalClaimTruth(row) {
|
|
|
120
121
|
export function askRowOnCall(row, call) {
|
|
121
122
|
return row.taskId === call.taskId && row.legKey === call.legKey && row.toolCallId === call.toolCallId && row.sourceSessionId === call.sourceSessionId;
|
|
122
123
|
}
|
|
124
|
+
export function askAtGate(r, sourceSessionId, binding) {
|
|
125
|
+
if (r.sourceSessionId !== sourceSessionId)
|
|
126
|
+
return false;
|
|
127
|
+
if (r.state === "PARKED")
|
|
128
|
+
return r.gateBoundCallId === binding.boundCallId && r.gateBoundInputHash === binding.boundInputHash;
|
|
129
|
+
return r.state === "PARKING" && r.toolCallId === binding.boundCallId && r.boundInputHash === binding.boundInputHash;
|
|
130
|
+
}
|
|
123
131
|
export function askRowCarriesOwner(row, owner) {
|
|
124
132
|
return row !== null && row.owner === owner;
|
|
125
133
|
}
|
|
@@ -565,11 +573,7 @@ export class SqlApprovalAskStore {
|
|
|
565
573
|
let askRes;
|
|
566
574
|
try {
|
|
567
575
|
askRes = await conn.query(`UPDATE ${APPROVAL_ASK_TABLE} SET state='DECIDED', decision=${ph(dialect, 1)}, decision_actor=${ph(dialect, 2)}, decision_note=${ph(dialect, 3)}, settled_by=${ph(dialect, 4)}, decided_via=${ph(dialect, 5)}, updated_input=${ph(dialect, 6)}, decided_at_ms=${ph(dialect, 7)}, idempotency_key=${ph(dialect, 8)}, rev=rev+1, updated_at_ms=${ph(dialect, 9)} WHERE ${pendingClaimWhere(dialect, 10)} AND ${ownerWhere.sql}`, [
|
|
568
|
-
|
|
569
|
-
decision.decisionActor == null ? null : this.json(decision.decisionActor),
|
|
570
|
-
decision.decisionNote ?? null,
|
|
571
|
-
decision.settledBy ?? null,
|
|
572
|
-
decision.decidedVia ?? null,
|
|
576
|
+
...this.decisionRecordValues(decision),
|
|
573
577
|
decision.updatedInput === undefined ? null : this.json(decision.updatedInput),
|
|
574
578
|
now,
|
|
575
579
|
decision.idempotencyKey ?? null,
|
|
@@ -608,6 +612,32 @@ export class SqlApprovalAskStore {
|
|
|
608
612
|
throw new Error(`decideAsk: row vanished after commit (askId=${askId})`);
|
|
609
613
|
return { ok: true, row };
|
|
610
614
|
}
|
|
615
|
+
decisionRecordValues(record) {
|
|
616
|
+
return [record.decision, record.decisionActor == null ? null : this.json(record.decisionActor), record.decisionNote ?? null, record.settledBy ?? null, record.decidedVia ?? null];
|
|
617
|
+
}
|
|
618
|
+
async recordParkedDecision(askId, owner, record) {
|
|
619
|
+
if (record.idempotencyKey != null)
|
|
620
|
+
assertIdempotencyKeyShape(record.idempotencyKey);
|
|
621
|
+
assertDecideSource(record);
|
|
622
|
+
const now = Date.now();
|
|
623
|
+
const dialect = this.db.dialect;
|
|
624
|
+
const ownerWhere = decideOwnerWhere(dialect, owner, 10);
|
|
625
|
+
let res;
|
|
626
|
+
try {
|
|
627
|
+
res = await this.db.query(`UPDATE ${APPROVAL_ASK_TABLE} SET decision=${ph(dialect, 1)}, decision_actor=${ph(dialect, 2)}, decision_note=${ph(dialect, 3)}, settled_by=${ph(dialect, 4)}, decided_via=${ph(dialect, 5)}, decided_at_ms=${ph(dialect, 6)}, idempotency_key=${ph(dialect, 7)}, rev=rev+1, updated_at_ms=${ph(dialect, 8)} WHERE ask_id = ${ph(dialect, 9)} AND state = 'PARKED' AND ${ownerWhere.sql}`, [...this.decisionRecordValues(record), now, record.idempotencyKey ?? null, now, askId, ...ownerWhere.params]);
|
|
628
|
+
}
|
|
629
|
+
catch (err) {
|
|
630
|
+
if (this.isDupKey(err))
|
|
631
|
+
return { ok: false, reason: "idempotency_conflict", row: projectDecideReading(await this.getAsk(askId), owner) };
|
|
632
|
+
throw err;
|
|
633
|
+
}
|
|
634
|
+
const row = projectDecideReading(await this.getAsk(askId), owner);
|
|
635
|
+
if (res.affected !== 1)
|
|
636
|
+
return { ok: false, reason: "ask_not_parked", row };
|
|
637
|
+
if (row === null)
|
|
638
|
+
throw new Error(`recordParkedDecision: row vanished after write (askId=${askId})`);
|
|
639
|
+
return { ok: true, row };
|
|
640
|
+
}
|
|
611
641
|
async claimTerminal(askId, batchId, intent, opts) {
|
|
612
642
|
const to = claimTargetState(intent);
|
|
613
643
|
if (!canAskTransition("STREAM_PENDING", to)) {
|
|
@@ -794,6 +824,10 @@ export class SqlApprovalAskStore {
|
|
|
794
824
|
const { rows } = await this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE source_task_id = ? AND state = 'PARKING' ORDER BY created_at_ms ASC, ask_id ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE source_task_id = $1 AND state = 'PARKING' ORDER BY created_at_ms ASC, ask_id ASC`), [sourceSessionId]);
|
|
795
825
|
return rows.map(mapAskRow).filter((r) => r.sourceSessionId === sourceSessionId);
|
|
796
826
|
}
|
|
827
|
+
async listAsksAtGate(sourceSessionId, binding) {
|
|
828
|
+
const { rows } = await this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE source_task_id = ? AND ((state = 'PARKED' AND gate_bound_call_id = ? AND gate_bound_input_hash = ?) OR (state = 'PARKING' AND tool_call_id = ? AND bound_input_hash = ?)) ORDER BY created_at_ms ASC, ask_id ASC`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE source_task_id = $1 AND ((state = 'PARKED' AND gate_bound_call_id = $2 AND gate_bound_input_hash = $3) OR (state = 'PARKING' AND tool_call_id = $2 AND bound_input_hash = $3)) ORDER BY created_at_ms ASC, ask_id ASC`), [sourceSessionId, binding.boundCallId, binding.boundInputHash, binding.boundCallId, binding.boundInputHash]);
|
|
829
|
+
return rows.map(mapAskRow).filter((r) => askAtGate(r, sourceSessionId, binding));
|
|
830
|
+
}
|
|
797
831
|
async getAsk(askId) {
|
|
798
832
|
const { rows } = await this.db.query(this.q(`SELECT ${askCols("mysql")} FROM ${APPROVAL_ASK_TABLE} WHERE ask_id = ?`, `SELECT ${askCols("pg")} FROM ${APPROVAL_ASK_TABLE} WHERE ask_id = $1`), [
|
|
799
833
|
askId,
|
|
@@ -877,6 +911,12 @@ export class SqlApprovalAskStore {
|
|
|
877
911
|
return rows[0] ? mapBatchRow(rows[0]) : null;
|
|
878
912
|
}
|
|
879
913
|
}
|
|
914
|
+
sealStoreClass(SqlApprovalAskStore, "sql-approval-ask-store", {
|
|
915
|
+
ensureAsk: "exit", transitionAsk: "exit", decideAsk: "exit", claimTerminal: "exit", expireAsk: "exit", bindBatch: "exit", abortBatch: "exit",
|
|
916
|
+
listByState: "exit", listPendingByTask: "exit", listPendingBySession: "exit", listByCall: "exit", listParkingBySourceSession: "exit", getAsk: "exit",
|
|
917
|
+
getByIdempotencyKey: "exit", deferReconcile: "exit", resolveProvisional: "exit", deleteBySession: "exit", reapSettledAsks: "exit", reapEmptyBatches: "exit",
|
|
918
|
+
getBatch: "exit", recordParkedDecision: "exit", listAsksAtGate: "exit",
|
|
919
|
+
});
|
|
880
920
|
export class TiDBApprovalAskStore extends SqlApprovalAskStore {
|
|
881
921
|
constructor(pool) {
|
|
882
922
|
super(mysqlDriver(pool));
|
|
@@ -2,6 +2,7 @@ import { join } from "node:path";
|
|
|
2
2
|
import { existsSync, readdirSync, rmSync } from "node:fs";
|
|
3
3
|
import { AppendLog, ensureDir, sanitizePathComponent } from "@sema-agent/core";
|
|
4
4
|
import { replayJsonlGuarded } from "../observability/corrupt-read-seat.js";
|
|
5
|
+
import { sealStoreClass } from "./store-boundary.js";
|
|
5
6
|
export const APPROVAL_EXEMPTED_EVENT = "approval_exempted";
|
|
6
7
|
export class TiDBApprovalExemptionStore {
|
|
7
8
|
pool;
|
|
@@ -33,6 +34,7 @@ export class TiDBApprovalExemptionStore {
|
|
|
33
34
|
return r.affectedRows;
|
|
34
35
|
}
|
|
35
36
|
}
|
|
37
|
+
sealStoreClass(TiDBApprovalExemptionStore, "tidb-approval-exemption-store", { grant: "exit", has: "exit", list: "exit", revoke: "exit", deleteBySession: "exit" });
|
|
36
38
|
export class PgApprovalExemptionStore {
|
|
37
39
|
pool;
|
|
38
40
|
constructor(pool) {
|
|
@@ -69,6 +71,7 @@ export class PgApprovalExemptionStore {
|
|
|
69
71
|
return res.rowCount ?? 0;
|
|
70
72
|
}
|
|
71
73
|
}
|
|
74
|
+
sealStoreClass(PgApprovalExemptionStore, "pg-approval-exemption-store", { grant: "exit", has: "exit", list: "exit", revoke: "exit", deleteBySession: "exit" });
|
|
72
75
|
export class MemoryApprovalExemptionStore {
|
|
73
76
|
bySession = new Map();
|
|
74
77
|
async grant(sessionId, toolName, grantedBy) {
|
|
@@ -4,6 +4,7 @@ import { mysqlDriver, pgDriver, SQL_DB_NOW_MS } from "./sql-driver.js";
|
|
|
4
4
|
import { isDupKeyError } from "./sql-errors.js";
|
|
5
5
|
import { replayJsonlGuarded } from "../observability/corrupt-read-seat.js";
|
|
6
6
|
import { createLogger } from "../observability/logger.js";
|
|
7
|
+
import { sealStoreClass } from "./store-boundary.js";
|
|
7
8
|
export const APPROVAL_NONCE_TABLE = "approval_nonce";
|
|
8
9
|
export const MAX_APPROVAL_NONCE_CHARS = 190;
|
|
9
10
|
export const APPROVAL_NONCE_FLOOR_TABLE = "approval_nonce_floor";
|
|
@@ -62,6 +63,7 @@ export class SqlApprovalNonceStore {
|
|
|
62
63
|
return res.affected;
|
|
63
64
|
}
|
|
64
65
|
}
|
|
66
|
+
sealStoreClass(SqlApprovalNonceStore, "sql-approval-nonce-store", { nowMs: "exit", consume: "exit", reapExpired: "exit" });
|
|
65
67
|
export class TiDBApprovalNonceStore extends SqlApprovalNonceStore {
|
|
66
68
|
constructor(pool, opts) {
|
|
67
69
|
super(mysqlDriver(pool), opts);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type ObjectStoreOp } from "../object-store-buckets.js";
|
|
2
|
+
import type { SessionBlobNamespace } from "./session-blob-namespace.js";
|
|
1
3
|
/**
|
|
2
4
|
* The byte port. Keys are opaque to it (today every index owner keys a blob by its sha256 hash).
|
|
3
5
|
* - `put`: store `bytes` under `key`. Idempotent (a repeat for the same key overwrites with the identical bytes); a rejection is a
|
|
@@ -5,7 +7,10 @@
|
|
|
5
7
|
* - `get`: the bytes under `key`, or `undefined` when nothing is there. A TRANSIENT fault THROWS (so a restore / import fails LOUD,
|
|
6
8
|
* not as a silent "missing blob"). The index owner checks the bytes against the hash ({@link readAtAddress}).
|
|
7
9
|
* - `delete`: remove the bytes under each key. Idempotent — a key with nothing under it is a success; a key that could not be removed
|
|
8
|
-
* makes the call reject (after every key was tried).
|
|
10
|
+
* makes the call reject (after every key was tried). A port whose deletes wait on a precondition (the session blob ports: the namespace's
|
|
11
|
+
* ownership, `session-blob-namespace.ts`) checks it at the start of EVERY call, before any key — so `delete([])` is that precondition alone:
|
|
12
|
+
* it rejects exactly as a real delete would be refused, and removes nothing. An index owner whose own writes come before its byte deletes
|
|
13
|
+
* asks it that way first (`SqlBlobIndex.sweep`).
|
|
9
14
|
*/
|
|
10
15
|
export interface BlobBackend {
|
|
11
16
|
put(key: string, bytes: Uint8Array): Promise<void>;
|
|
@@ -19,20 +24,47 @@ export interface BlobBackend {
|
|
|
19
24
|
* where both index owners judge it (the file-history blob index, the attachment store).
|
|
20
25
|
*/
|
|
21
26
|
export declare function readAtAddress(port: Pick<BlobBackend, "get">, hash: string): Promise<Uint8Array | undefined>;
|
|
22
|
-
|
|
27
|
+
/** A name a content-addressed domain could have written: a hex sha256, one key segment. A listed name of any other shape (a nested prefix's object, a
|
|
28
|
+
* hand-placed file) is not the domain's — its sweep leaves it alone. */
|
|
29
|
+
export declare function isContentAddress(name: string): boolean;
|
|
30
|
+
/** The object-store action table rows one blob backend signs, by verb (`object-store-buckets.ts`). A verb with no row is a request this backend never
|
|
31
|
+
* makes: calling it throws before anything is signed (the retired epoch's index only deletes; the boot check only lists). */
|
|
32
|
+
export interface BlobBackendOps {
|
|
33
|
+
readonly put?: ObjectStoreOp;
|
|
34
|
+
readonly get?: ObjectStoreOp;
|
|
35
|
+
readonly head?: ObjectStoreOp;
|
|
36
|
+
readonly delete?: ObjectStoreOp;
|
|
37
|
+
readonly list?: ObjectStoreOp;
|
|
38
|
+
}
|
|
39
|
+
interface MinioBlobBackendBaseConfig {
|
|
23
40
|
endpoint: string;
|
|
24
41
|
bucket: string;
|
|
25
42
|
accessKey: string;
|
|
26
43
|
secretKey: string;
|
|
27
44
|
region?: string;
|
|
28
|
-
/** Key prefix for blob objects
|
|
29
|
-
keyPrefix
|
|
30
|
-
/** Presigned-URL TTL (seconds).
|
|
31
|
-
*
|
|
45
|
+
/** Key prefix for blob objects. Object key = keyPrefix + key. The production domains get theirs from {@link createSessionBlobBackend}. */
|
|
46
|
+
keyPrefix: string;
|
|
47
|
+
/** Presigned-URL TTL (seconds; `SESSION_SNAPSHOT_TTL_SEC`). Unset ⇒ the row's default in the object-store action table (3600 s — it must
|
|
48
|
+
* comfortably exceed a ~64 MiB single-PUT/GET on a slow link: a SigV4 X-Amz-Expires bounds the WHOLE transfer from X-Amz-Date; a too-short TTL
|
|
49
|
+
* fails mid-stream). A row whose TTL is fixed (the boot probe's) refuses a configured one. */
|
|
32
50
|
presignTtlSec?: number;
|
|
33
51
|
/** 测试注入口(listObjects 分页钉用);生产缺省 global fetch。 */
|
|
34
52
|
fetchImpl?: typeof fetch;
|
|
35
53
|
}
|
|
54
|
+
/** A backend's rows and, for one that signs DELETE, the namespace's ownership every DELETE waits for — required by construction: every delete of a
|
|
55
|
+
* content-addressed domain is judged by one database's references, so a port that can delete is built from that database's proven namespace
|
|
56
|
+
* (`session-blob-namespace.ts`; `createSessionBlobBackend` passes it). A port with no DELETE row (the boot probe) has no owner. */
|
|
57
|
+
export type MinioBlobBackendConfig = MinioBlobBackendBaseConfig & ({
|
|
58
|
+
readonly ops: BlobBackendOps & {
|
|
59
|
+
readonly delete?: undefined;
|
|
60
|
+
};
|
|
61
|
+
readonly owner?: undefined;
|
|
62
|
+
} | {
|
|
63
|
+
readonly ops: BlobBackendOps & {
|
|
64
|
+
readonly delete: ObjectStoreOp;
|
|
65
|
+
};
|
|
66
|
+
readonly owner: Pick<SessionBlobNamespace, "assertOwned">;
|
|
67
|
+
});
|
|
36
68
|
/** 鲁棒性批2 C2/C3/C6(2026-08-03):S3 兼容端点 IO 的统一 abort 上界(fleet-client C1 定常量形
|
|
37
69
|
* 先例)。半开端点此前各挂 undici 默认 ~300s headersTimeout——blob GET 卡住 restore/session-import
|
|
38
70
|
* 同步路径,SendUserFile 工具调用永不返回。120s 对慢链路 ~64MiB 单 PUT/GET 仍宽裕(presignTtlSec
|
|
@@ -56,11 +88,14 @@ export type BucketProbe = {
|
|
|
56
88
|
export declare class MinioBlobBackend implements BlobBackend {
|
|
57
89
|
private readonly cfg;
|
|
58
90
|
private readonly keyPrefix;
|
|
91
|
+
/** The configured TTL, or nothing (the seat then takes the row's own). */
|
|
59
92
|
private readonly ttl;
|
|
60
93
|
/** 六个站点(put / get / delete / listObjects / headObject / probeBucket)的唯一出口:端点回重定向 ⇒ 拒,预签名 URL 与对象体不被带去 `Location`。 */
|
|
61
94
|
private readonly egressFetch;
|
|
62
95
|
constructor(cfg: MinioBlobBackendConfig);
|
|
63
96
|
private objectKey;
|
|
97
|
+
/** The table row this backend signs `verb` under; none ⇒ throw (a request this backend's domain never makes). */
|
|
98
|
+
private opFor;
|
|
64
99
|
private presign;
|
|
65
100
|
/** PUT the bytes under the key. A non-2xx PUT throws (an upload failure must surface — a silent drop would later read_failed on
|
|
66
101
|
* restore). NOTE no post-PUT read-back verify on the live path (perf): a corrupted PUT is caught at the next read's content-address
|
|
@@ -75,7 +110,8 @@ export declare class MinioBlobBackend implements BlobBackend {
|
|
|
75
110
|
/** DELETE every key's object, at most {@link MINIO_OP_CONCURRENCY} in flight (no FD / throttle storm). Each key is independent: a
|
|
76
111
|
* 2xx or a 404 (already gone) is a success; any other answer or a network failure is a failure. Every key is tried; then, if any
|
|
77
112
|
* failed, the call REJECTS naming how many (🔴 复审 F4 的同一判据:对象存储完全不可写时绝不报「清理成功」—— 失败只在这里说出来,
|
|
78
|
-
* 调用方据此记账,不吞)。
|
|
113
|
+
* 调用方据此记账,不吞)。The namespace's ownership is read first on every call, an empty `keys` included (that call is the precondition
|
|
114
|
+
* alone: the port contract, {@link BlobBackend}). */
|
|
79
115
|
delete(keys: readonly string[]): Promise<void>;
|
|
80
116
|
/** D-1 孤儿对象 GC(clay 拍 2026-07-28):列举本后端 keyPrefix 下的全部对象(ListObjectsV2 分页,
|
|
81
117
|
* 零依赖 XML 取 <Key>/<LastModified>/<NextContinuationToken>)。**server 端 sweep 专用**——presign 的
|
|
@@ -95,4 +131,44 @@ export declare class MinioBlobBackend implements BlobBackend {
|
|
|
95
131
|
* 都**证明不了**缺桶 ⇒ `unknown`,调用方不拒启、只报一次。总函数:不抛。`timeoutMs`:boot 期调用方给的单次上界(黑洞端点不许把起服拖到 120s)。 */
|
|
96
132
|
probeBucket(timeoutMs?: number): Promise<BucketProbe>;
|
|
97
133
|
}
|
|
134
|
+
/** The blob domains of the session snapshot bucket (closed set) → the table rows each signs. File history reads, writes and sweeps; attachments also list
|
|
135
|
+
* and HEAD (their orphan sweep); the retired snapshot epoch only deletes (its sweep). */
|
|
136
|
+
export declare const SESSION_BLOB_DOMAIN_OPS: {
|
|
137
|
+
readonly "file-history": {
|
|
138
|
+
readonly put: "file-history/blob:PUT";
|
|
139
|
+
readonly get: "file-history/blob:GET";
|
|
140
|
+
readonly delete: "file-history/blob:DELETE";
|
|
141
|
+
};
|
|
142
|
+
readonly attachments: {
|
|
143
|
+
readonly put: "attachments/blob:PUT";
|
|
144
|
+
readonly get: "attachments/blob:GET";
|
|
145
|
+
readonly head: "attachments/blob:HEAD";
|
|
146
|
+
readonly delete: "attachments/blob:DELETE";
|
|
147
|
+
readonly list: "attachments/prefix:LIST";
|
|
148
|
+
};
|
|
149
|
+
readonly "legacy-blobs": {
|
|
150
|
+
readonly delete: "legacy-blobs/blob:DELETE";
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
export type SessionBlobDomain = keyof typeof SESSION_BLOB_DOMAIN_OPS;
|
|
154
|
+
/** The session snapshot bucket's store config (`config.snapshotBlobStore`: `SESSION_SNAPSHOT_BUCKET`, `SESSION_SNAPSHOT_PREFIX`, `SESSION_SNAPSHOT_TTL_SEC`). */
|
|
155
|
+
export interface SessionBlobStoreConfig {
|
|
156
|
+
endpoint: string;
|
|
157
|
+
bucket: string;
|
|
158
|
+
accessKey: string;
|
|
159
|
+
secretKey: string;
|
|
160
|
+
region?: string;
|
|
161
|
+
keyPrefix?: string;
|
|
162
|
+
presignTtlSec?: number;
|
|
163
|
+
}
|
|
164
|
+
/** The key prefix of a session blob domain, or the key of the namespace's claim — the ONE place each composes `SESSION_SNAPSHOT_PREFIX` with its
|
|
165
|
+
* segment (the table's key forms `{sessionPrefix}file-history/…`, `{sessionPrefix}attachments/…`, `{legacyBlobRoot}…`, `{sessionPrefix}blob-namespace-claim`).
|
|
166
|
+
* An empty prefix reads as unset (the env loader's reading of the knob, kept for a hand-built config too): file history, attachments and the claim then
|
|
167
|
+
* sit at the bucket root, the retired epoch at its own root `blobs/` (where its objects were written). */
|
|
168
|
+
export declare function sessionBlobKeyPrefixOf(store: Pick<SessionBlobStoreConfig, "keyPrefix">, part: SessionBlobDomain | "claim"): string;
|
|
169
|
+
/** The byte port of one session blob domain over the session snapshot bucket: its key prefix ({@link sessionBlobKeyPrefixOf}), its table rows
|
|
170
|
+
* ({@link SESSION_BLOB_DOMAIN_OPS}) and the namespace's ownership its deletes wait for — the one construction every production domain uses, and it
|
|
171
|
+
* takes the namespace (one database's), not a bare bucket config. */
|
|
172
|
+
export declare function createSessionBlobBackend(namespace: SessionBlobNamespace, domain: SessionBlobDomain): MinioBlobBackend;
|
|
173
|
+
export {};
|
|
98
174
|
//# sourceMappingURL=blob-backend.d.ts.map
|
|
@@ -2,12 +2,16 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { presignS3Url, presignS3ListUrl } from "./s3-presign.js";
|
|
3
3
|
import { isNoSuchBucketAnswer } from "./s3-answer.js";
|
|
4
4
|
import { createEgressFetch } from "../egress-redirect.js";
|
|
5
|
+
import { ATTACHMENT_BLOB_SEGMENT, FILE_HISTORY_BLOB_SEGMENT, LEGACY_BLOB_ROOT_DEFAULT, SESSION_BLOB_CLAIM_KEY } from "../object-store-buckets.js";
|
|
5
6
|
export async function readAtAddress(port, hash) {
|
|
6
7
|
const bytes = await port.get(hash);
|
|
7
8
|
if (bytes === undefined)
|
|
8
9
|
return undefined;
|
|
9
10
|
return createHash("sha256").update(bytes).digest("hex") === hash ? bytes : undefined;
|
|
10
11
|
}
|
|
12
|
+
export function isContentAddress(name) {
|
|
13
|
+
return /^[0-9a-f]{64}$/.test(name);
|
|
14
|
+
}
|
|
11
15
|
const MINIO_OP_CONCURRENCY = 16;
|
|
12
16
|
async function mapBounded(items, limit, fn) {
|
|
13
17
|
let i = 0;
|
|
@@ -27,23 +31,30 @@ export class MinioBlobBackend {
|
|
|
27
31
|
egressFetch;
|
|
28
32
|
constructor(cfg) {
|
|
29
33
|
this.cfg = cfg;
|
|
30
|
-
this.keyPrefix = cfg.keyPrefix
|
|
31
|
-
this.ttl = cfg.presignTtlSec
|
|
34
|
+
this.keyPrefix = cfg.keyPrefix;
|
|
35
|
+
this.ttl = cfg.presignTtlSec !== undefined ? { expiresSec: cfg.presignTtlSec } : {};
|
|
32
36
|
this.egressFetch = createEgressFetch("declare the final object-store address as MINIO_ENDPOINT / S3_ENDPOINT", cfg.fetchImpl);
|
|
33
37
|
}
|
|
34
38
|
objectKey(key) {
|
|
35
39
|
return `${this.keyPrefix}${key}`;
|
|
36
40
|
}
|
|
41
|
+
opFor(verb) {
|
|
42
|
+
const op = this.cfg.ops[verb];
|
|
43
|
+
if (op === undefined)
|
|
44
|
+
throw new Error(`MinioBlobBackend: this blob domain (prefix ${JSON.stringify(this.keyPrefix)}) signs no ${verb.toUpperCase()} — no object-store action row for it`);
|
|
45
|
+
return op;
|
|
46
|
+
}
|
|
37
47
|
presign(key, method) {
|
|
38
48
|
return presignS3Url({
|
|
49
|
+
op: this.opFor(method === "GET" ? "get" : method === "PUT" ? "put" : method === "HEAD" ? "head" : "delete"),
|
|
39
50
|
endpoint: this.cfg.endpoint,
|
|
40
51
|
bucket: this.cfg.bucket,
|
|
41
52
|
key: this.objectKey(key),
|
|
42
|
-
method
|
|
53
|
+
method,
|
|
43
54
|
accessKey: this.cfg.accessKey,
|
|
44
55
|
secretKey: this.cfg.secretKey,
|
|
45
56
|
...(this.cfg.region ? { region: this.cfg.region } : {}),
|
|
46
|
-
|
|
57
|
+
...this.ttl,
|
|
47
58
|
});
|
|
48
59
|
}
|
|
49
60
|
async put(key, bytes) {
|
|
@@ -72,7 +83,13 @@ export class MinioBlobBackend {
|
|
|
72
83
|
return new Uint8Array(await res.arrayBuffer());
|
|
73
84
|
}
|
|
74
85
|
async delete(keys) {
|
|
86
|
+
const owner = this.cfg.owner;
|
|
87
|
+
if (owner === undefined)
|
|
88
|
+
throw new Error(`MinioBlobBackend: this blob domain (prefix ${JSON.stringify(this.keyPrefix)}) has no namespace ownership to delete under — a port that signs DELETE is built from a proven namespace`);
|
|
89
|
+
await owner.assertOwned();
|
|
75
90
|
const distinct = [...new Set(keys)];
|
|
91
|
+
if (distinct.length === 0)
|
|
92
|
+
return;
|
|
76
93
|
let failed = 0;
|
|
77
94
|
let firstFailure;
|
|
78
95
|
await mapBounded(distinct, MINIO_OP_CONCURRENCY, async (key) => {
|
|
@@ -100,6 +117,7 @@ export class MinioBlobBackend {
|
|
|
100
117
|
if (++pages > MAX_PAGES)
|
|
101
118
|
throw new Error(`listObjects: exceeded ${MAX_PAGES} pages (max-keys 1000/page) — the backend is looping its continuation-token or the prefix is unexpectedly large; refusing to report a partial orphan set`);
|
|
102
119
|
const url = presignS3ListUrl({
|
|
120
|
+
op: this.opFor("list"),
|
|
103
121
|
endpoint: this.cfg.endpoint,
|
|
104
122
|
bucket: this.cfg.bucket,
|
|
105
123
|
prefix: this.keyPrefix,
|
|
@@ -108,7 +126,7 @@ export class MinioBlobBackend {
|
|
|
108
126
|
accessKey: this.cfg.accessKey,
|
|
109
127
|
secretKey: this.cfg.secretKey,
|
|
110
128
|
...(this.cfg.region ? { region: this.cfg.region } : {}),
|
|
111
|
-
|
|
129
|
+
...this.ttl,
|
|
112
130
|
});
|
|
113
131
|
const res = await f(url, { method: "GET", signal: AbortSignal.timeout(OBJECT_STORE_IO_TIMEOUT_MS) });
|
|
114
132
|
if (!res.ok)
|
|
@@ -141,6 +159,7 @@ export class MinioBlobBackend {
|
|
|
141
159
|
async probeBucket(timeoutMs = OBJECT_STORE_IO_TIMEOUT_MS) {
|
|
142
160
|
const f = this.egressFetch;
|
|
143
161
|
const url = presignS3ListUrl({
|
|
162
|
+
op: this.opFor("list"),
|
|
144
163
|
endpoint: this.cfg.endpoint,
|
|
145
164
|
bucket: this.cfg.bucket,
|
|
146
165
|
prefix: this.keyPrefix,
|
|
@@ -148,7 +167,7 @@ export class MinioBlobBackend {
|
|
|
148
167
|
accessKey: this.cfg.accessKey,
|
|
149
168
|
secretKey: this.cfg.secretKey,
|
|
150
169
|
...(this.cfg.region ? { region: this.cfg.region } : {}),
|
|
151
|
-
|
|
170
|
+
...this.ttl,
|
|
152
171
|
});
|
|
153
172
|
let res;
|
|
154
173
|
try {
|
|
@@ -165,4 +184,36 @@ export class MinioBlobBackend {
|
|
|
165
184
|
return { state: "unknown", detail: `HTTP ${res.status}` };
|
|
166
185
|
}
|
|
167
186
|
}
|
|
187
|
+
export const SESSION_BLOB_DOMAIN_OPS = {
|
|
188
|
+
"file-history": { put: "file-history/blob:PUT", get: "file-history/blob:GET", delete: "file-history/blob:DELETE" },
|
|
189
|
+
attachments: { put: "attachments/blob:PUT", get: "attachments/blob:GET", head: "attachments/blob:HEAD", delete: "attachments/blob:DELETE", list: "attachments/prefix:LIST" },
|
|
190
|
+
"legacy-blobs": { delete: "legacy-blobs/blob:DELETE" },
|
|
191
|
+
};
|
|
192
|
+
export function sessionBlobKeyPrefixOf(store, part) {
|
|
193
|
+
const prefix = store.keyPrefix === "" ? undefined : store.keyPrefix;
|
|
194
|
+
switch (part) {
|
|
195
|
+
case "file-history":
|
|
196
|
+
return `${prefix ?? ""}${FILE_HISTORY_BLOB_SEGMENT}`;
|
|
197
|
+
case "attachments":
|
|
198
|
+
return `${prefix ?? ""}${ATTACHMENT_BLOB_SEGMENT}`;
|
|
199
|
+
case "claim":
|
|
200
|
+
return `${prefix ?? ""}${SESSION_BLOB_CLAIM_KEY}`;
|
|
201
|
+
case "legacy-blobs":
|
|
202
|
+
return prefix ?? LEGACY_BLOB_ROOT_DEFAULT;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
export function createSessionBlobBackend(namespace, domain) {
|
|
206
|
+
const store = namespace.store;
|
|
207
|
+
return new MinioBlobBackend({
|
|
208
|
+
endpoint: store.endpoint,
|
|
209
|
+
bucket: store.bucket,
|
|
210
|
+
accessKey: store.accessKey,
|
|
211
|
+
secretKey: store.secretKey,
|
|
212
|
+
...(store.region ? { region: store.region } : {}),
|
|
213
|
+
keyPrefix: sessionBlobKeyPrefixOf(store, domain),
|
|
214
|
+
ops: SESSION_BLOB_DOMAIN_OPS[domain],
|
|
215
|
+
owner: namespace,
|
|
216
|
+
...(store.presignTtlSec ? { presignTtlSec: store.presignTtlSec } : {}),
|
|
217
|
+
});
|
|
218
|
+
}
|
|
168
219
|
//# sourceMappingURL=blob-backend.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mysqlDriver, pgDriver } from "./sql-driver.js";
|
|
2
|
+
import { sealStoreClass } from "./store-boundary.js";
|
|
2
3
|
export const PG_BREAKER_STATE_SCHEMA = [
|
|
3
4
|
`CREATE TABLE IF NOT EXISTS breaker_state (
|
|
4
5
|
breaker_key VARCHAR(190) COLLATE "C" NOT NULL,
|
|
@@ -91,6 +92,7 @@ export class SqlBreakerState {
|
|
|
91
92
|
this.timer = undefined;
|
|
92
93
|
}
|
|
93
94
|
}
|
|
95
|
+
sealStoreClass(SqlBreakerState, "sql-breaker-state", { get: "exit", set: "exit", refresh: "exit", startRefresh: "exit", stop: "exit" });
|
|
94
96
|
export class TiDBBreakerState extends SqlBreakerState {
|
|
95
97
|
constructor(pool, onWriteFail) {
|
|
96
98
|
super(mysqlDriver(pool), onWriteFail);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type AcquiredSession, type PlacedSessionRow, type RetentionDeclaration, type SessionPlacementRecord, type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
|
|
2
|
+
import type { EntriesStreamOptions } from "../session-sync-kernel.js";
|
|
2
3
|
import type { LocalSessionDeletionSection } from "../session-erase.js";
|
|
3
4
|
import type { OwnerAwareSessionStore, SessionListItem } from "../security.js";
|
|
4
5
|
import type { StagingHandle } from "../session-sync-kernel.js";
|
|
@@ -7,6 +8,7 @@ import { type PlacementAcquireOpts } from "./session-placement.js";
|
|
|
7
8
|
import type { InstructionSourceStore } from "../instruction-source-notice.js";
|
|
8
9
|
import type { SessionWorkspaceStore } from "../session-workspace.js";
|
|
9
10
|
import { type SessionBirthFace, type SessionWithdrawFace } from "./session-birth.js";
|
|
11
|
+
import type { SessionFace } from "../session-incarnation.js";
|
|
10
12
|
export interface CachingOptions {
|
|
11
13
|
/** Idle seconds a woken session is kept warm. 0 disables caching (pure passthrough). */
|
|
12
14
|
ttlSec: number;
|
|
@@ -72,18 +74,13 @@ export declare class CachingSessionStore implements SessionStore {
|
|
|
72
74
|
readonly withdrawBirth?: SessionWithdrawFace["withdrawBirth"];
|
|
73
75
|
/** Delegated SessionRepo seam (§0.5) — list/fork/delete operate on the DURABLE tables directly (they bypass the
|
|
74
76
|
* warm cache by design; a fork/delete must read/write durable state, not a possibly-stale cached view). */
|
|
75
|
-
readonly listSessions?:
|
|
76
|
-
owner?: string;
|
|
77
|
-
includeUnowned?: boolean;
|
|
78
|
-
cursor?: {
|
|
79
|
-
lastActivityAt: string;
|
|
80
|
-
sessionId: string;
|
|
81
|
-
};
|
|
82
|
-
limit: number;
|
|
83
|
-
q?: string;
|
|
84
|
-
}) => Promise<SessionListItem[]>;
|
|
77
|
+
readonly listSessions?: OwnerAwareSessionStore["listSessions"];
|
|
85
78
|
/** 带住客的同一只列表面(原样转发;理由同 listSessions)。 */
|
|
86
79
|
readonly listSessionRows?: OwnerAwareSessionStore["listSessionRows"];
|
|
80
|
+
/** 按 id 的种类读(`session-kind.ts`;纯转发、不经暖缓存 —— 答的是行)。🔴 必须转发:授权口的种类判与能力位读的是本类。 */
|
|
81
|
+
readonly sessionKindOf?: OwnerAwareSessionStore["sessionKindOf"];
|
|
82
|
+
/** 老化候选面(纯转发;读的是持久行)。🔴 必须转发:能力位 `sessionKinds` 与老化腿读的是本类。 */
|
|
83
|
+
readonly listIdleOfKind?: OwnerAwareSessionStore["listIdleOfKind"];
|
|
87
84
|
readonly fork?: OwnerAwareSessionStore["fork"];
|
|
88
85
|
/** fork 续写的店契约(原样转发;与 fork 同理绕过暖缓存 —— 读写的是持久行,新 id 本来就不在缓存里)。 */
|
|
89
86
|
readonly forkTo?: OwnerAwareSessionStore["forkTo"];
|
|
@@ -99,7 +96,7 @@ export declare class CachingSessionStore implements SessionStore {
|
|
|
99
96
|
readonly sessionSummaryOf?: (sessionId: string) => Promise<SessionListItem | undefined>;
|
|
100
97
|
readonly writeSessionRowCells?: OwnerAwareSessionStore["writeSessionRowCells"];
|
|
101
98
|
/** The auto-titler's NULL-only title write (SQL twins + local sidecar carry it; pure pass-through). */
|
|
102
|
-
readonly setTitleIfNull?: (sessionId: string, title: string) => Promise<boolean>;
|
|
99
|
+
readonly setTitleIfNull?: (sessionId: string, title: string, landed: SessionFace) => Promise<boolean>;
|
|
103
100
|
readonly probeTitle?: (sessionId: string) => Promise<"none" | "untitled" | "titled">;
|
|
104
101
|
/** [ref] —— 换源通告的基线面(`session_ext.instruction_source` / local sidecar),纯转发、不经暖缓存。
|
|
105
102
|
* 🔴 必须转发(与 retention / placements 同一条教训):默认 `SESSION_CACHE_TTL_SEC=300` 把真店包进本类,
|
|
@@ -117,10 +114,7 @@ export declare class CachingSessionStore implements SessionStore {
|
|
|
117
114
|
* (read straight from the durable log, bypassing the warm cache, like exportEntries). The stream's per-batch query
|
|
118
115
|
* discipline (one pooled query per page) lives in the inner store; this wrapper just forwards. */
|
|
119
116
|
readonly listEntryIds?: (sessionId: string) => Promise<string[] | null>;
|
|
120
|
-
readonly exportEntriesStream?: (sessionId: string, opts
|
|
121
|
-
afterSeq?: number;
|
|
122
|
-
batchSize?: number;
|
|
123
|
-
}) => Promise<AsyncIterable<SessionTreeEntry> | null>;
|
|
117
|
+
readonly exportEntriesStream?: (sessionId: string, opts: EntriesStreamOptions) => Promise<AsyncIterable<SessionTreeEntry> | null>;
|
|
124
118
|
/** 轴A #1(1.254):core B-17 forget 面(evict 本地 + 转发 inner 可选面)。 */
|
|
125
119
|
forget?: (sessionId: string) => void | Promise<void>;
|
|
126
120
|
readonly importEntries?: (sessionId: string, owner: string | null, entries: SessionTreeEntry[]) => Promise<void>;
|
|
@@ -15,6 +15,8 @@ export class CachingSessionStore {
|
|
|
15
15
|
withdrawBirth;
|
|
16
16
|
listSessions;
|
|
17
17
|
listSessionRows;
|
|
18
|
+
sessionKindOf;
|
|
19
|
+
listIdleOfKind;
|
|
18
20
|
fork;
|
|
19
21
|
forkTo;
|
|
20
22
|
executionPlacement;
|
|
@@ -82,6 +84,10 @@ export class CachingSessionStore {
|
|
|
82
84
|
this.listSessions = ownerAware.listSessions.bind(inner);
|
|
83
85
|
if (ownerAware.listSessionRows)
|
|
84
86
|
this.listSessionRows = ownerAware.listSessionRows.bind(inner);
|
|
87
|
+
if (ownerAware.sessionKindOf)
|
|
88
|
+
this.sessionKindOf = ownerAware.sessionKindOf.bind(inner);
|
|
89
|
+
if (ownerAware.listIdleOfKind)
|
|
90
|
+
this.listIdleOfKind = ownerAware.listIdleOfKind.bind(inner);
|
|
85
91
|
if (ownerAware.sessionSummaryOf)
|
|
86
92
|
this.sessionSummaryOf = ownerAware.sessionSummaryOf.bind(inner);
|
|
87
93
|
if (ownerAware.writeSessionRowCells)
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*
|
|
5
5
|
* ## 写:一只派生 = core `checkpointIndexFacts(cp)`(core 7.55.0 [ref] P1 阶段二)
|
|
6
6
|
* 行上「core 铸下、此后不动」的十三个事实(令牌、scope、会话、格式版本、门型、卡、待决工具的名 / 调用 id / 入参摘要、deadline、铸行时刻、风险描述符、
|
|
7
|
-
* 双向控制字符在场位),每一个都由 core
|
|
8
|
-
*
|
|
9
|
-
* (
|
|
10
|
-
*
|
|
11
|
-
* `
|
|
7
|
+
* 双向控制字符在场位),每一个都由 core 那一只函数答;本模块只把**有读者找行 / 判到期**的那几个落到列名下({@link buildCheckpointIndexCells})。
|
|
8
|
+
* 键表对 core 的事实键闭合({@link CHECKPOINT_INDEX_COLUMNS} `satisfies Record<keyof CheckpointIndexFacts, string | null>`):core 加 / 删一个事实 ⇒ 编译红,
|
|
9
|
+
* 由人决定它落不落列。**不落列**(`null`)的三个 —— 工具名、风险描述符、bidi 位 —— 只是运维队列的展示材料:队列行在读时从续跑执行的同一份字节、同一次整行解码投影
|
|
10
|
+
* (`checkpoint-store-face.ts` 的 `buildQueueActionFacts`,同调这同一只 core 派生),落一份列就是同一事实的第二份存储(7.151.x 及以前落过,一次性迁移 M54 删)。
|
|
11
|
+
* 不在这里的:CAS 面推动的状态(`status` / `rev` / `reopen_reason` / 执行记录)、部署铸的值(`terminal_at_ms` 兜底)—— 它们不是行的不变事实,core 也不答。
|
|
12
12
|
*
|
|
13
13
|
* ## 写之前:一只判官 = {@link judgeCheckpointIndexCells}
|
|
14
14
|
* 一份文档能不能落进这些列,在写之前由**同一只**判官答 —— 写口 `put` 与 M29 的存量回填都问它,界不抄第二份。三个答案:`cells`(放得下,列格在手);`unreadable`(门或待决动作
|
|
@@ -29,9 +29,13 @@
|
|
|
29
29
|
* (`boot/stores.ts`,先于任何路由与收割器装配),跑不完就拒启 —— 所以每只副本的收割器只在本次起服的 M29 完成之后才运行。混跑期间旧副本新写的行
|
|
30
30
|
* 不带卡列(它们不认这一列),由下一次起服的 M29 补上;升级序见 MIGRATION 7.135.0 节(同一只库不混跑两版)。
|
|
31
31
|
*/
|
|
32
|
-
import { PAUSE_REGISTRY, type Checkpoint, type CheckpointIndexFacts, type GateKind
|
|
32
|
+
import { PAUSE_REGISTRY, type Checkpoint, type CheckpointIndexFacts, type GateKind } from "@sema-agent/core";
|
|
33
33
|
import type { SqlDialect } from "./sql-driver.js";
|
|
34
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* 每个索引事实落在哪一列;`null` = 不落列(键表对 core 的事实键闭合:core 加 / 删一个事实 ⇒ 编译红,由人定落不落)。
|
|
36
|
+
* 落列的判据只有一条:**有读者按它找行或判到期**(决断口的门型绑定、对账与决断回放的调用 id / 绑定摘要、到期 facet 的卡与门型、会话 / scope / 时刻 / 截止)。
|
|
37
|
+
* 只给人看的事实不落列 —— 队列在读时从同一次整行解码投影,一个事实一份存储。
|
|
38
|
+
*/
|
|
35
39
|
export declare const CHECKPOINT_INDEX_COLUMNS: {
|
|
36
40
|
readonly token: "token";
|
|
37
41
|
readonly scope: "scope";
|
|
@@ -39,21 +43,21 @@ export declare const CHECKPOINT_INDEX_COLUMNS: {
|
|
|
39
43
|
readonly version: "version";
|
|
40
44
|
readonly gateKind: "gate_kind";
|
|
41
45
|
readonly approvalCard: "approval_card";
|
|
42
|
-
readonly toolName:
|
|
46
|
+
readonly toolName: null;
|
|
43
47
|
readonly toolCallId: "tool_call_id";
|
|
44
48
|
readonly boundInputHash: "bound_input_hash";
|
|
45
49
|
readonly deadline: "deadline";
|
|
46
50
|
readonly createdAt: "created_at_ms";
|
|
47
|
-
readonly riskDescriptor:
|
|
48
|
-
readonly hasBidiControls:
|
|
51
|
+
readonly riskDescriptor: null;
|
|
52
|
+
readonly hasBidiControls: null;
|
|
49
53
|
};
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
*/
|
|
54
|
+
/** 落列的那几个事实(键表上列名不是 `null` 的)。 */
|
|
55
|
+
type StoredIndexFact = {
|
|
56
|
+
[K in keyof CheckpointIndexFacts]: (typeof CHECKPOINT_INDEX_COLUMNS)[K] extends string ? K : never;
|
|
57
|
+
}[keyof CheckpointIndexFacts];
|
|
58
|
+
/** 一行的索引列格:落列的 core 事实落在列名下,值逐字是事实本身。 */
|
|
55
59
|
export type CheckpointIndexCells = {
|
|
56
|
-
readonly [K in
|
|
60
|
+
readonly [K in StoredIndexFact as (typeof CHECKPOINT_INDEX_COLUMNS)[K] & string]: CheckpointIndexFacts[K];
|
|
57
61
|
};
|
|
58
62
|
/** 一行的索引列格(纯数据;写口与 M29 回填同调这一只 —— 回填不另读门子树自算)。 */
|
|
59
63
|
export declare function buildCheckpointIndexCells(cp: Checkpoint): CheckpointIndexCells;
|
|
@@ -7,13 +7,13 @@ export const CHECKPOINT_INDEX_COLUMNS = {
|
|
|
7
7
|
version: "version",
|
|
8
8
|
gateKind: "gate_kind",
|
|
9
9
|
approvalCard: "approval_card",
|
|
10
|
-
toolName:
|
|
10
|
+
toolName: null,
|
|
11
11
|
toolCallId: "tool_call_id",
|
|
12
12
|
boundInputHash: "bound_input_hash",
|
|
13
13
|
deadline: "deadline",
|
|
14
14
|
createdAt: "created_at_ms",
|
|
15
|
-
riskDescriptor:
|
|
16
|
-
hasBidiControls:
|
|
15
|
+
riskDescriptor: null,
|
|
16
|
+
hasBidiControls: null,
|
|
17
17
|
};
|
|
18
18
|
export function buildCheckpointIndexCells(cp) {
|
|
19
19
|
const f = checkpointIndexFacts(cp);
|
|
@@ -24,13 +24,10 @@ export function buildCheckpointIndexCells(cp) {
|
|
|
24
24
|
version: f.version,
|
|
25
25
|
gate_kind: f.gateKind,
|
|
26
26
|
approval_card: f.approvalCard,
|
|
27
|
-
tool_name: f.toolName,
|
|
28
27
|
tool_call_id: f.toolCallId,
|
|
29
28
|
bound_input_hash: f.boundInputHash,
|
|
30
29
|
deadline: f.deadline,
|
|
31
30
|
created_at_ms: f.createdAt,
|
|
32
|
-
risk_descriptor: f.riskDescriptor,
|
|
33
|
-
has_bidi_controls: f.hasBidiControls === true ? 1 : null,
|
|
34
31
|
};
|
|
35
32
|
}
|
|
36
33
|
export const APPROVAL_CARD_COLUMN_MAX_BYTES = {
|