@sema-agent/server 7.149.0 → 7.151.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 +307 -9
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +92 -40
- package/deploy/sema-up/README.md +7 -1
- 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 +1 -0
- package/deploy/sema-up/kube-up.sh +1 -1
- package/deploy/sema-up/lib/flagshape.sh +1 -1
- package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
- package/deploy/sema-up/lib/helm-values-kube.py +2 -0
- package/dist/adoption/import.js +3 -3
- package/dist/approval-ask-machine.d.ts +1 -1
- package/dist/approval-card.d.ts +3 -3
- package/dist/approval-gate-currency.d.ts +2 -2
- package/dist/audit.d.ts +1 -1
- package/dist/audit.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 +2 -2
- package/dist/bake-runner/main.d.ts +4 -2
- package/dist/bind-host.d.ts +2 -3
- package/dist/bind-host.js +2 -4
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
- package/dist/boot/deferred-sandbox-path-env.js +1 -2
- package/dist/boot/engine-lease.d.ts +5 -0
- package/dist/boot/engine-lease.js +1 -0
- package/dist/boot/execution-env.d.ts +8 -14
- package/dist/boot/execution-env.js +54 -17
- 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/memory-consolidation.d.ts +3 -2
- package/dist/boot/memory-consolidation.js +6 -6
- package/dist/boot/parked-revive-gate.d.ts +5 -5
- package/dist/boot/parked-revive-gate.js +2 -3
- package/dist/boot/reapers.d.ts +5 -0
- package/dist/boot/reapers.js +12 -1
- package/dist/boot/resolve-spec.d.ts +7 -8
- package/dist/boot/resolve-spec.js +80 -35
- package/dist/boot/retention-lane.d.ts +1 -1
- package/dist/boot/runner-deps.d.ts +9 -2
- package/dist/boot/runner-deps.js +3 -3
- 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 +28 -24
- package/dist/boot/stage-01-config.js +2 -0
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-05-execution-env.d.ts +5 -3
- package/dist/boot/stage-05-execution-env.js +2 -2
- package/dist/boot/stage-06-runners.d.ts +7 -4
- package/dist/boot/stage-06-runners.js +16 -8
- package/dist/boot/stage-07-capability-layer.d.ts +7 -4
- package/dist/boot/stage-07-capability-layer.js +3 -2
- package/dist/boot/stage-08-reapers.d.ts +7 -4
- package/dist/boot/stage-08-reapers.js +4 -2
- package/dist/boot/stage-09-leader.d.ts +11 -5
- package/dist/boot/stage-09-leader.js +12 -3
- package/dist/boot/stage-10-http-server.d.ts +44 -6
- package/dist/boot/stage-10-http-server.js +12 -10
- package/dist/boot/web-admin.d.ts +1 -1
- package/dist/boot/web-admin.js +3 -1
- 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/capability-facts.d.ts +84 -66
- package/dist/capability-facts.js +58 -41
- 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 +15 -12
- package/dist/config-invariants.d.ts +2 -1
- package/dist/config-invariants.js +4 -4
- package/dist/config-types.d.ts +22 -15
- package/dist/config.d.ts +51 -2
- package/dist/config.js +35 -24
- package/dist/deployment-governance.d.ts +7 -28
- package/dist/deployment-governance.js +1 -14
- 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 +1 -0
- package/dist/device-ws-hub.js +66 -29
- package/dist/device-ws-protocol.d.ts +79 -12
- package/dist/device-ws-protocol.js +64 -26
- package/dist/engine-identity.d.ts +23 -5
- package/dist/engine-identity.js +13 -0
- package/dist/entry-mode-clamp-notice.d.ts +2 -1
- package/dist/execution-env-refusal.d.ts +23 -0
- package/dist/execution-env-refusal.js +5 -0
- package/dist/execution-lane-caps.d.ts +3 -1
- package/dist/field-conflict.d.ts +3 -3
- 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 +14 -1
- package/dist/fleet/engine-signal.js +5 -1
- package/dist/fleet/fleet-reconciler.d.ts +1 -1
- package/dist/fleet/serving-lease.d.ts +18 -3
- package/dist/fleet/serving-lease.js +81 -35
- package/dist/fleet-client.d.ts +13 -11
- package/dist/fleet-client.js +53 -33
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +1 -3
- package/dist/hitl-delivery.js +1 -1
- package/dist/hooks/hook-runner.js +2 -2
- package/dist/host-lsp-manager.d.ts +2 -2
- package/dist/http/active-run-conflict.d.ts +3 -7
- package/dist/http/active-run-conflict.js +2 -2
- package/dist/http/admission.js +19 -4
- package/dist/http/approval-sweeps.js +7 -6
- package/dist/http/caller-trust.d.ts +2 -2
- package/dist/http/caller-trust.js +3 -3
- package/dist/http/checkpoint-ctx.d.ts +20 -63
- package/dist/http/checkpoint-ctx.js +2 -24
- package/dist/http/claim-heartbeat.d.ts +4 -4
- package/dist/http/claim-heartbeat.js +3 -3
- package/dist/http/dispatch.d.ts +2 -1
- package/dist/http/dispatch.js +36 -29
- package/dist/http/durable-run-leg.js +17 -17
- package/dist/http/health-self-report.d.ts +9 -1
- package/dist/http/health-self-report.js +2 -0
- package/dist/http/owner-access.d.ts +264 -20
- package/dist/http/owner-access.js +215 -5
- package/dist/http/readiness.d.ts +4 -2
- package/dist/http/resume-ctx-read.js +38 -1
- package/dist/http/resume-legs.d.ts +2 -1
- package/dist/http/resume-legs.js +273 -89
- package/dist/http/route-ctx.d.ts +41 -19
- package/dist/http/route-table.d.ts +1 -1
- package/dist/http/routes/a2a-serve.js +15 -14
- package/dist/http/routes/admin-memory-optout.d.ts +1 -1
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.d.ts +3 -2
- package/dist/http/routes/approvals-assistant.js +12 -12
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/capabilities.js +10 -6
- package/dist/http/routes/config-catalog.d.ts +1 -1
- package/dist/http/routes/fleet.js +10 -8
- package/dist/http/routes/mcp-reconnect.js +2 -2
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/notify-wake.js +2 -3
- package/dist/http/routes/projects.d.ts +4 -2
- package/dist/http/routes/projects.js +7 -6
- package/dist/http/routes/retention-ops.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +1 -1
- package/dist/http/routes/runs.js +125 -66
- package/dist/http/routes/session-memory-sync.js +4 -5
- package/dist/http/routes/session-sync.d.ts +4 -3
- package/dist/http/routes/session-sync.js +174 -83
- package/dist/http/routes/sessions-list.js +13 -7
- package/dist/http/routes/sessions.d.ts +1 -1
- package/dist/http/routes/sessions.js +26 -48
- package/dist/http/routes/tasks.js +38 -23
- package/dist/http/routes/trace-usage.js +14 -14
- package/dist/http/routes/workflows.d.ts +1 -0
- package/dist/http/routes/workflows.js +20 -38
- package/dist/http/server.d.ts +28 -30
- package/dist/http/server.js +7 -3
- package/dist/http/stored-body-replay.d.ts +3 -24
- package/dist/http/stored-body-replay.js +2 -12
- package/dist/http/submit-ctx.d.ts +1 -2
- package/dist/http/submit-ctx.js +8 -6
- package/dist/http/submit-replay.d.ts +15 -2
- package/dist/http/submit-replay.js +10 -4
- package/dist/http/wire-types.d.ts +19 -6
- package/dist/identity-source.d.ts +20 -3
- package/dist/identity-source.js +14 -0
- package/dist/index.d.ts +4 -0
- package/dist/lane-home-probe.d.ts +3 -7
- package/dist/lane-home-probe.js +0 -1
- package/dist/leader/endpoint.js +9 -8
- package/dist/leader/leader.d.ts +2 -1
- package/dist/leg-facts.d.ts +19 -5
- package/dist/leg-facts.js +3 -1
- package/dist/mcp-authorization-face.d.ts +18 -14
- package/dist/mcp-authorization-face.js +3 -2
- package/dist/memory-scope.d.ts +5 -4
- package/dist/memory-scope.js +4 -4
- package/dist/memory-store-refusal.d.ts +1 -1
- package/dist/memory-sync-client.d.ts +30 -2
- package/dist/memory-sync-client.js +16 -9
- package/dist/observability/corrupt-read-seat.d.ts +1 -1
- package/dist/observability/err-text.d.ts +7 -0
- package/dist/observability/err-text.js +5 -0
- package/dist/observability/fail-open.d.ts +12 -8
- package/dist/observability/fail-open.js +12 -8
- package/dist/observability/logger.d.ts +7 -0
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -0
- package/dist/observability/run-terminal.d.ts +1 -1
- 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/owner-faces.d.ts +28 -4
- package/dist/owner-faces.js +2 -0
- package/dist/parked-decide.d.ts +104 -53
- 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/peer-seat.d.ts +1 -1
- package/dist/peer-seat.js +52 -59
- package/dist/permission-mode-admission.d.ts +41 -5
- package/dist/permission-mode-admission.js +29 -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 +10 -2
- package/dist/plugins/approval-ask-store-file.js +8 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +6 -1
- package/dist/plugins/approval-ask-store-memory.js +28 -9
- package/dist/plugins/approval-ask-store-sql.d.ts +43 -2
- package/dist/plugins/approval-ask-store-sql.js +34 -5
- package/dist/plugins/approval-exemption-store.js +3 -0
- package/dist/plugins/approval-nonce-store.js +2 -0
- 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/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/exec-path-law.d.ts +34 -0
- package/dist/plugins/exec-path-law.js +13 -0
- package/dist/plugins/execution-placement-sql.js +6 -6
- package/dist/plugins/file-run-store.js +1 -1
- 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 +4 -1
- package/dist/plugins/local-checkpoint-store.js +3 -0
- 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-run-store.js +1 -1
- 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 +80 -61
- package/dist/plugins/one-time-migrations.js +241 -104
- 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 +28 -1
- 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 +8 -3
- package/dist/plugins/remote-env-adb.d.ts +19 -15
- package/dist/plugins/remote-env-adb.js +44 -17
- 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 +114 -14
- package/dist/plugins/remote-env-e2b.d.ts +18 -7
- package/dist/plugins/remote-env-e2b.js +53 -40
- package/dist/plugins/remote-env-file-error.js +6 -2
- package/dist/plugins/remote-env-host.d.ts +18 -1
- package/dist/plugins/remote-env-host.js +48 -47
- package/dist/plugins/remote-env-k8s.d.ts +41 -39
- package/dist/plugins/remote-env-k8s.js +56 -32
- package/dist/plugins/remote-env-local-docker.d.ts +13 -8
- package/dist/plugins/remote-env-local-docker.js +37 -43
- package/dist/plugins/remote-env-ssh.d.ts +18 -12
- package/dist/plugins/remote-env-ssh.js +64 -62
- package/dist/plugins/remote-shell.d.ts +101 -2
- package/dist/plugins/remote-shell.js +221 -3
- package/dist/plugins/replica-registration.d.ts +35 -0
- package/dist/plugins/replica-registration.js +48 -0
- 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.d.ts +1 -1
- 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 +22 -3
- package/dist/plugins/run-store-sql.js +33 -9
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +6 -12
- package/dist/plugins/scenario-prefix-switch-m42.js +7 -5
- package/dist/plugins/schema-consistency.d.ts +9 -5
- package/dist/plugins/schema-consistency.js +48 -18
- package/dist/plugins/schema-drift-sentence.js +1 -1
- package/dist/plugins/send-file-ledger.js +3 -0
- package/dist/plugins/serving-requirement.d.ts +68 -0
- package/dist/plugins/serving-requirement.js +60 -0
- package/dist/plugins/session-birth.d.ts +6 -2
- 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/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/stop-then-start-sentence.d.ts +48 -3
- package/dist/plugins/stop-then-start-sentence.js +48 -0
- 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 +40 -13
- package/dist/plugins/store-backend.js +169 -27
- package/dist/plugins/store-boundary.d.ts +57 -0
- package/dist/plugins/store-boundary.js +139 -0
- package/dist/plugins/store-contracts.d.ts +29 -2
- package/dist/plugins/store-contracts.js +3 -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.js +9 -0
- 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 +6 -1
- 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-fill.d.ts +4 -7
- package/dist/plugins/workspace-fill.js +2 -1
- package/dist/plugins/write-behind-counter.js +5 -0
- package/dist/process-instance.d.ts +3 -0
- package/dist/process-instance.js +7 -0
- package/dist/project-context.d.ts +64 -0
- package/dist/project-context.js +66 -0
- package/dist/project-registry.d.ts +46 -0
- package/dist/project-registry.js +44 -0
- package/dist/question.d.ts +9 -21
- package/dist/question.js +28 -19
- 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/run-acceptance.d.ts +3 -2
- package/dist/run-acceptance.js +4 -6
- package/dist/run-cancel-card.d.ts +1 -1
- package/dist/run-cancel-card.js +2 -1
- package/dist/run-local.js +1 -0
- package/dist/runs.d.ts +37 -8
- package/dist/runs.js +53 -12
- package/dist/runtime-governance.d.ts +5 -4
- package/dist/security.d.ts +31 -33
- package/dist/security.js +41 -7
- package/dist/server-secret-env.d.ts +12 -10
- package/dist/server-secret-env.js +24 -15
- package/dist/session-agent.d.ts +1 -10
- package/dist/session-agent.js +0 -6
- 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 +28 -4
- package/dist/session-incarnation.js +14 -2
- package/dist/session-kind.d.ts +57 -0
- package/dist/session-kind.js +22 -0
- package/dist/session-notify-door.d.ts +4 -4
- package/dist/session-notify-door.js +5 -6
- package/dist/session-row.d.ts +21 -1
- package/dist/session-row.js +7 -1
- package/dist/session-rules-seat.d.ts +4 -3
- package/dist/session-rules-seat.js +3 -11
- package/dist/session-sync-kernel.d.ts +24 -14
- package/dist/session-sync-kernel.js +3 -6
- package/dist/session-sync.d.ts +4 -98
- package/dist/session-sync.js +4 -74
- 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/checkpoint-store-sql.d.ts +21 -2
- package/dist/stores-sql/checkpoint-store-sql.js +106 -18
- package/dist/stores-sql/file-history-store-sql.d.ts +52 -2
- package/dist/stores-sql/file-history-store-sql.js +108 -70
- 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 +2 -10
- package/dist/stores-sql/retention-store-sql.js +2 -10
- 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 +6 -5
- package/dist/task-settings.d.ts +19 -5
- package/dist/task-settings.js +13 -7
- package/dist/terminal.d.ts +33 -2
- package/dist/terminal.js +139 -9
- package/dist/tool-approval.d.ts +147 -12
- package/dist/tool-approval.js +206 -109
- package/dist/trace/engine-notice-wire.d.ts +14 -0
- package/dist/trace/engine-notice-wire.js +18 -1
- package/dist/trace/project.d.ts +4 -3
- package/dist/trace/project.js +3 -2
- package/dist/trace/projection-table.d.ts +33 -2
- package/dist/trace/self-minted-wire.d.ts +422 -26
- package/dist/trace/self-minted-wire.js +149 -23
- package/dist/trace/tool-card.d.ts +3 -0
- package/dist/trace/tool-card.js +24 -0
- package/dist/trace/tool-output-media.d.ts +2 -1
- package/dist/unattended-permission-mode.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +1 -1
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +120 -41
- package/package.json +3 -3
- package/wire-changes/server@7.150.0.json +335 -0
- package/wire-changes/server@7.151.0.json +762 -0
- package/dist/http/session-inherit-env.d.ts +0 -36
- package/dist/http/session-inherit-env.js +0 -6
|
@@ -133,8 +133,10 @@ export declare class SqlAdoptionLogStore implements AdoptionLogStore {
|
|
|
133
133
|
constructor(db: SqlDriver);
|
|
134
134
|
private q;
|
|
135
135
|
/** 池级只读执行面(phase 0 的 preflight 扫描用——它**零写**,不需要也不该占一条事务连接)。
|
|
136
|
-
* 写路径一律走 {@link rebindTransaction};把驱动整个暴露出去会让调用方能绕开 phase CAS。
|
|
136
|
+
* 写路径一律走 {@link rebindTransaction};把驱动整个暴露出去会让调用方能绕开 phase CAS。
|
|
137
|
+
* 交出的是**封过**的执行面(只一个 `query`,出店口:库错只带原码 + 稳定句),不是驱动本身。 */
|
|
137
138
|
get reader(): SqlExec;
|
|
139
|
+
private sealedReader;
|
|
138
140
|
/**
|
|
139
141
|
* 发起腿的 **insert-or-fetch 原子形**。返回读回的行(可能是别人插的)+ 是否本次插入。
|
|
140
142
|
* 调用方据 `row.toPrincipal !== toPrincipal` 判「同 from 异 to」⇒ typed 409。
|
|
@@ -3,6 +3,7 @@ import { createHash } from "node:crypto";
|
|
|
3
3
|
import { mysqlDriver, pgDriver } from "./sql-driver.js";
|
|
4
4
|
import { acquireAdvisoryLockWithin, releaseAdvisoryLock } from "./ensure-schema-lock-policy.js";
|
|
5
5
|
import { ensureIndexes } from "./ensure-index.js";
|
|
6
|
+
import { sealStoreClass, sealStoreObject } from "./store-boundary.js";
|
|
6
7
|
export const ADOPTION_LOG_TABLE = "adoption_log";
|
|
7
8
|
export const ADOPTION_PHASE = {
|
|
8
9
|
INTENT: 2,
|
|
@@ -105,8 +106,9 @@ export class SqlAdoptionLogStore {
|
|
|
105
106
|
return this.db.dialect === "mysql" ? mysql : pg;
|
|
106
107
|
}
|
|
107
108
|
get reader() {
|
|
108
|
-
return this.db;
|
|
109
|
+
return (this.sealedReader ??= sealStoreObject({ query: (sql, params) => this.db.query(sql, params) }, "sql-adoption-log-reader", { query: "exit" }));
|
|
109
110
|
}
|
|
111
|
+
sealedReader;
|
|
110
112
|
async ensureAdoption(row) {
|
|
111
113
|
const emptyLegs = "[]";
|
|
112
114
|
const res = await this.db.query(this.q(`INSERT IGNORE INTO ${ADOPTION_LOG_TABLE} (${COLS}) VALUES (?, ?, ?, ?, 'in_flight', ?, ?, NULL, NULL, NULL, ?, ?)`, `INSERT INTO ${ADOPTION_LOG_TABLE} (${COLS}) VALUES ($1, $2, $3, $4, 'in_flight', $5, $6, NULL, NULL, NULL, $7, $8) ON CONFLICT (from_principal) DO NOTHING`), [row.adoptionId, row.fromPrincipal, row.toPrincipal, ADOPTION_PHASE.INTENT, emptyLegs, emptyLegs, row.nowMs, row.nowMs]);
|
|
@@ -216,6 +218,10 @@ export class SqlAdoptionLogStore {
|
|
|
216
218
|
}
|
|
217
219
|
}
|
|
218
220
|
}
|
|
221
|
+
sealStoreClass(SqlAdoptionLogStore, "sql-adoption-log-store", {
|
|
222
|
+
ensureAdoption: "exit", getById: "exit", getByFrom: "exit", listInFlight: "exit", rebindOn: "exit", sweepOn: "exit", advancePhase: "exit", putConfigs: "exit",
|
|
223
|
+
finalizeAdopted: "exit", finalizeRejected: "exit", withLock: "exit",
|
|
224
|
+
});
|
|
219
225
|
export class TiDBAdoptionLogStore extends SqlAdoptionLogStore {
|
|
220
226
|
constructor(pool) {
|
|
221
227
|
super(mysqlDriver(pool));
|
|
@@ -2,7 +2,7 @@ import { type ExecutionLane } from "../execution-lane-caps.js";
|
|
|
2
2
|
import { type LocalAskLaneBackfillRefusal } from "./one-time-migrations.js";
|
|
3
3
|
import type { AskState } from "../approval-ask-machine.js";
|
|
4
4
|
import type { SettleCause } from "../approval-deny-reasons.js";
|
|
5
|
-
import type { AskCallCoordinate, AskRow, AskTerminalClaimIntent, AskTerminalClaimOpts, AskTerminalClaimOutcome, AskTransitionPatch, ApprovalAskStore, BatchRow, BindGateInput, BindResult, DecideAskInput, DecideResult, EnsureAskResult, ExpireResult, NewAskRow } from "./approval-ask-store-sql.js";
|
|
5
|
+
import type { AskCallCoordinate, AskDecisionRecord, AskRow, AskTerminalClaimIntent, AskTerminalClaimOpts, AskTerminalClaimOutcome, AskTransitionPatch, ApprovalAskStore, BatchRow, BindGateInput, BindResult, DecideAskInput, DecideResult, EnsureAskResult, ExpireResult, NewAskRow, RecordParkedDecisionResult } from "./approval-ask-store-sql.js";
|
|
6
6
|
/** 数据根下的目录名。**按店命名**,与兄弟 File 店同规(`approval-nonces` / `approval-ask-audit` /
|
|
7
7
|
* `approval-exemptions` / `resume-anchors` / `checkpoint-ctx` / …)—— 首版写的是族名 `approvals`,而那
|
|
8
8
|
* 正是读者会去找**持久 park 行**的地方(它们其实在 `checkpoint-ctx`),且持久数据面的名字按硬 breaking
|
|
@@ -24,7 +24,7 @@ export declare const ASK_JOURNAL_COMPACT_GROWTH = 2;
|
|
|
24
24
|
* 账本的**动词闭集**([ref] 形)。运行期的词表判定与编译期的穷尽 `switch` 读同一份:
|
|
25
25
|
* 往这里加一个词,{@link FileApprovalAskStore.replayOp} 的 switch 立刻编译红(漏一口不可能发布)。
|
|
26
26
|
*/
|
|
27
|
-
declare const JOURNAL_OPS: readonly ["ensureAsk", "transitionAsk", "decideAsk", "claimTerminal", "claimTerminalRefuse", "expireAsk", "bindBatch", "abortBatch", "deferReconcile", "resolveProvisional", "deleteBySession", "reapSettledAsks", "reapEmptyBatches"];
|
|
27
|
+
declare const JOURNAL_OPS: readonly ["ensureAsk", "transitionAsk", "decideAsk", "recordParkedDecision", "claimTerminal", "claimTerminalRefuse", "expireAsk", "bindBatch", "abortBatch", "deferReconcile", "resolveProvisional", "deleteBySession", "reapSettledAsks", "reapEmptyBatches"];
|
|
28
28
|
type JournalOpWord = (typeof JOURNAL_OPS)[number];
|
|
29
29
|
/** 运行期词表(上面的数组)与类型面动词维({@link JournalCall})的**双向**对表 —— 任一边加词而另一边
|
|
30
30
|
* 没跟上,这个别名解析成 `never`,{@link JOURNAL_OP_TABLE_GATE} 的赋值当场编译红。 */
|
|
@@ -59,6 +59,12 @@ type JournalCall = {
|
|
|
59
59
|
askId: string;
|
|
60
60
|
batchId: string;
|
|
61
61
|
decision: DecideAskInput;
|
|
62
|
+
}
|
|
63
|
+
/** 停驻形的人决落行。更老的读者不认这个动词 ⇒ 拒启并点名出路(与留存两动词同一条降级纪律)。 */
|
|
64
|
+
| {
|
|
65
|
+
op: "recordParkedDecision";
|
|
66
|
+
askId: string;
|
|
67
|
+
record: AskDecisionRecord;
|
|
62
68
|
} | {
|
|
63
69
|
op: "claimTerminal";
|
|
64
70
|
askId: string;
|
|
@@ -202,6 +208,8 @@ export declare class FileApprovalAskStore implements ApprovalAskStore {
|
|
|
202
208
|
* (整本账的信封号另算 —— 见顶注「信封版本」)。
|
|
203
209
|
*/
|
|
204
210
|
decideAsk(askId: string, batchId: string, owner: string | null, decision: DecideAskInput): Promise<DecideResult>;
|
|
211
|
+
/** 停驻形的人决落行 —— 出域的一次不落账本(与 {@link decideAsk} 同一条 [ref] 理由),其余落账 → 内核。 */
|
|
212
|
+
recordParkedDecision(askId: string, owner: string | null, record: AskDecisionRecord): Promise<RecordParkedDecisionResult>;
|
|
205
213
|
claimTerminal(askId: string, batchId: string, intent: AskTerminalClaimIntent, opts?: AskTerminalClaimOpts): Promise<AskTerminalClaimOutcome>;
|
|
206
214
|
expireAsk(askId: string, batchId: string): Promise<ExpireResult>;
|
|
207
215
|
bindBatch(batchId: string, askId: string, gate: BindGateInput): Promise<BindResult>;
|
|
@@ -20,6 +20,7 @@ const JOURNAL_OPS = [
|
|
|
20
20
|
"ensureAsk",
|
|
21
21
|
"transitionAsk",
|
|
22
22
|
"decideAsk",
|
|
23
|
+
"recordParkedDecision",
|
|
23
24
|
"claimTerminal",
|
|
24
25
|
"claimTerminalRefuse",
|
|
25
26
|
"expireAsk",
|
|
@@ -280,6 +281,8 @@ export class FileApprovalAskStore {
|
|
|
280
281
|
return this.core.transitionAsk(rec.askId, rec.from, rec.to, rec.patch);
|
|
281
282
|
case "decideAsk":
|
|
282
283
|
return this.core.decideAsk(rec.askId, rec.batchId, this.core.peekAsk(rec.askId)?.owner ?? null, rec.decision);
|
|
284
|
+
case "recordParkedDecision":
|
|
285
|
+
return this.core.recordParkedDecision(rec.askId, this.core.peekAsk(rec.askId)?.owner ?? null, rec.record);
|
|
283
286
|
case "claimTerminal":
|
|
284
287
|
return this.core.claimTerminal(rec.askId, rec.batchId, rec.intent, rec.cause !== undefined ? { cause: rec.cause } : undefined);
|
|
285
288
|
case "claimTerminalRefuse":
|
|
@@ -318,6 +321,11 @@ export class FileApprovalAskStore {
|
|
|
318
321
|
return this.core.decideAsk(askId, batchId, owner, journalled);
|
|
319
322
|
return this.write({ op: "decideAsk", askId, batchId, decision: journalled }, (c) => this.core.decideAsk(c.askId, c.batchId, owner, c.decision));
|
|
320
323
|
}
|
|
324
|
+
async recordParkedDecision(askId, owner, record) {
|
|
325
|
+
if (!askRowCarriesOwner(this.core.peekAsk(askId), owner))
|
|
326
|
+
return this.core.recordParkedDecision(askId, owner, record);
|
|
327
|
+
return this.write({ op: "recordParkedDecision", askId, record }, (c) => this.core.recordParkedDecision(c.askId, owner, c.record));
|
|
328
|
+
}
|
|
321
329
|
async claimTerminal(askId, batchId, intent, opts) {
|
|
322
330
|
switch (intent) {
|
|
323
331
|
case "expire":
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
*/
|
|
32
32
|
import { type AskState, type BatchState } from "../approval-ask-machine.js";
|
|
33
33
|
import type { ExecutionLane } from "../execution-lane-caps.js";
|
|
34
|
-
import type { AskCallCoordinate, AskDecision, AskRow, AskTerminalClaimIntent, AskTerminalClaimOpts, AskTerminalClaimOutcome, AskTransitionPatch, ApprovalAskStore, BatchRow, BindGateInput, BindResult, DecideAskInput, EnsureAskResult, DecideResult, ExpireResult, NewAskRow } from "./approval-ask-store-sql.js";
|
|
34
|
+
import type { AskCallCoordinate, AskDecision, AskDecisionRecord, AskRow, AskTerminalClaimIntent, AskTerminalClaimOpts, AskTerminalClaimOutcome, AskTransitionPatch, ApprovalAskStore, BatchRow, BindGateInput, BindResult, DecideAskInput, EnsureAskResult, DecideResult, ExpireResult, NewAskRow, RecordParkedDecisionResult } from "./approval-ask-store-sql.js";
|
|
35
35
|
/**
|
|
36
36
|
* [ref] 的 `updatedInput` **入店编码**——两 twin 共用的那一只(本函数是唯一真源)。
|
|
37
37
|
*
|
|
@@ -99,6 +99,11 @@ export declare class InMemoryApprovalAskStore implements ApprovalAskStore {
|
|
|
99
99
|
ensureAsk(row: NewAskRow): Promise<EnsureAskResult>;
|
|
100
100
|
transitionAsk(askId: string, from: AskState, to: AskState, patch: AskTransitionPatch): Promise<boolean>;
|
|
101
101
|
decideAsk(askId: string, batchId: string, owner: string | null, decision: DecideAskInput): Promise<DecideResult>;
|
|
102
|
+
/**
|
|
103
|
+
* 停驻形的人决落行(接口契约见 SQL 侧 {@link ApprovalAskStore.recordParkedDecision})。判定序照 SQL twin:行在 ∧ `PARKED` ∧ 属主维(UPDATE 谓词)→ 才轮到撞键
|
|
104
|
+
* (UNIQUE `(task_id, idempotency_key)` 的内存镜像,与 `decideAsk` 同一段;本行自己占着同一把键不算撞)。态不变。
|
|
105
|
+
*/
|
|
106
|
+
recordParkedDecision(askId: string, owner: string | null, record: AskDecisionRecord): Promise<RecordParkedDecisionResult>;
|
|
102
107
|
/**
|
|
103
108
|
* [ref] 原子终局 claim(接口契约见 SQL 侧 {@link ApprovalAskStore.claimTerminal})。**委托形**:CAS 走
|
|
104
109
|
* 既有 verb(expire ⇒ `this.expireAsk`;cancel ⇒ `this.transitionAsk(STREAM_PENDING→VOID)`)——律 2
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { ASK_TERMINAL, canAskTransition } from "../approval-ask-machine.js";
|
|
2
2
|
import { APPROVAL_ENDING_CAUSES } from "../approval-deny-reasons.js";
|
|
3
3
|
import { askAttachedToSession, askRowCarriesOwner, askRowOnCall, assertDecideSource, assertIdempotencyKeyShape, assertIntegralEpochMs, assertReapBounds, ApprovalAskReadAbortedError, claimTargetState, POLICY_REFUSAL_DECISION, projectAskTerminalClaimTruth, projectDecideReading } from "./approval-ask-store-sql.js";
|
|
4
|
+
function applyDecisionRecord(row, record, now) {
|
|
5
|
+
row.decision = record.decision;
|
|
6
|
+
row.decisionActor = record.decisionActor ?? null;
|
|
7
|
+
row.decisionNote = record.decisionNote ?? null;
|
|
8
|
+
row.settledBy = record.settledBy ?? null;
|
|
9
|
+
row.decidedVia = record.decidedVia ?? null;
|
|
10
|
+
row.decidedAtMs = now;
|
|
11
|
+
row.idempotencyKey = record.idempotencyKey ?? null;
|
|
12
|
+
row.rev += 1;
|
|
13
|
+
row.updatedAtMs = now;
|
|
14
|
+
}
|
|
4
15
|
function applyPatch(row, patch) {
|
|
5
16
|
if (patch.decision !== undefined)
|
|
6
17
|
row.decision = patch.decision;
|
|
@@ -181,19 +192,27 @@ export class InMemoryApprovalAskStore {
|
|
|
181
192
|
batch.rev += 1;
|
|
182
193
|
batch.updatedAtMs = now;
|
|
183
194
|
ask.state = "DECIDED";
|
|
184
|
-
ask
|
|
185
|
-
ask.decisionActor = decision.decisionActor ?? null;
|
|
186
|
-
ask.decisionNote = decision.decisionNote ?? null;
|
|
187
|
-
ask.settledBy = decision.settledBy ?? null;
|
|
188
|
-
ask.decidedVia = decision.decidedVia ?? null;
|
|
195
|
+
applyDecisionRecord(ask, decision, now);
|
|
189
196
|
if (decision.updatedInput === undefined)
|
|
190
197
|
delete ask.updatedInput;
|
|
191
198
|
else
|
|
192
199
|
ask.updatedInput = encodedUpdatedInput;
|
|
193
|
-
ask
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
200
|
+
return { ok: true, row: { ...ask } };
|
|
201
|
+
}
|
|
202
|
+
async recordParkedDecision(askId, owner, record) {
|
|
203
|
+
if (record.idempotencyKey != null)
|
|
204
|
+
assertIdempotencyKeyShape(record.idempotencyKey);
|
|
205
|
+
assertDecideSource(record);
|
|
206
|
+
const ask = this.asks.get(askId);
|
|
207
|
+
if (!ask || ask.state !== "PARKED" || !askRowCarriesOwner(ask, owner))
|
|
208
|
+
return { ok: false, reason: "ask_not_parked", row: projectDecideReading(ask ? { ...ask } : null, owner) };
|
|
209
|
+
if (record.idempotencyKey != null) {
|
|
210
|
+
for (const [id, r] of this.asks) {
|
|
211
|
+
if (id !== askId && r.taskId === ask.taskId && r.idempotencyKey === record.idempotencyKey)
|
|
212
|
+
return { ok: false, reason: "idempotency_conflict", row: { ...ask } };
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
applyDecisionRecord(ask, record, this.now());
|
|
197
216
|
return { ok: true, row: { ...ask } };
|
|
198
217
|
}
|
|
199
218
|
async claimTerminal(askId, batchId, intent, opts) {
|
|
@@ -249,11 +249,17 @@ export interface AskTransitionPatch {
|
|
|
249
249
|
provisional?: boolean;
|
|
250
250
|
updatedAtMs: number;
|
|
251
251
|
}
|
|
252
|
-
|
|
252
|
+
/**
|
|
253
|
+
* 一次人对一张卡的决定**落行的那一份记录** —— live 与停驻两形同一份、同一张列、同一只映射(SQL twin {@link SqlApprovalAskStore} 的 `decisionRecordValues`、
|
|
254
|
+
* 内存 twin 的 `applyDecisionRecord`):决议向 · 署名 · 理由 · 回决幂等键 · 出处两格(+ 决定时刻,店铸)。
|
|
255
|
+
* live 形随 `STREAM_PENDING → DECIDED` 那一笔单赢者 CAS 落({@link ApprovalAskStore.decideAsk});停驻形在停驻门受理之后落在仍 `PARKED` 的行上
|
|
256
|
+
* ({@link ApprovalAskStore.recordParkedDecision})。两形唯一的写者 = 协调器的回决写者(`ToolApprovalCoordinator.writeAskDecision`)。
|
|
257
|
+
*/
|
|
258
|
+
export interface AskDecisionRecord {
|
|
253
259
|
decision: AskDecision;
|
|
254
260
|
decisionActor?: unknown;
|
|
255
261
|
decisionNote?: string | null;
|
|
256
|
-
/** 车4 §12-E
|
|
262
|
+
/** 车4 §12-E:回决幂等键,随决议一起落列(见 `AskRow.idempotencyKey`)。缺席 ⇒ 列 NULL。 */
|
|
257
263
|
idempotencyKey?: string | null;
|
|
258
264
|
/**
|
|
259
265
|
* 🔴 [ref]:本次回决的**结算来源**,与决议同一条 UPDATE 落列 `settled_by`(语义/两态读法/为什么是
|
|
@@ -265,6 +271,9 @@ export interface DecideAskInput {
|
|
|
265
271
|
settledBy?: HostSettledBy;
|
|
266
272
|
/** core 7.61.0([ref]):`settledBy:"policy"` 旁的机器座位,与决议同一条 UPDATE 落列 `decided_via`(语义见 {@link AskRow.decidedVia});缺席 ⇒ 列 NULL。 */
|
|
267
273
|
decidedVia?: DecidedVia;
|
|
274
|
+
}
|
|
275
|
+
/** live 形的决定 = 那份记录 + 随决议交给在等那条腿的编辑实参(停驻形的编辑走停驻门的绑定,不落问行)。 */
|
|
276
|
+
export interface DecideAskInput extends AskDecisionRecord {
|
|
268
277
|
/** [ref]:ctrl+g 编辑实参,与决议同一条 UPDATE 落列(语义三态见 {@link AskRow.updatedInput})。
|
|
269
278
|
* 缺席 / `undefined` ⇒ 列 NULL(没带编辑);**`null` 是值**(编辑成 null),照存 JSON `"null"`。
|
|
270
279
|
* 调用方纪律:deny 不传(店不替调用方判决议方向,写什么存什么)。 */
|
|
@@ -285,6 +294,18 @@ export type DecideResult = {
|
|
|
285
294
|
reason: "batch_closed" | "ask_not_pending" | "idempotency_conflict";
|
|
286
295
|
row: AskRow | null;
|
|
287
296
|
};
|
|
297
|
+
/**
|
|
298
|
+
* {@link ApprovalAskStore.recordParkedDecision} 的结局:`ok` ⇒ 落后的行;`ask_not_parked` ⇒ 行不在 / 不在 `PARKED` / 已出了门判过的属主域;
|
|
299
|
+
* `idempotency_conflict` ⇒ 这把键已被同 task 另一只问占着(UNIQUE `(task_id, idempotency_key)`)。`row` 与 {@link DecideResult} 同一只属主维投影。
|
|
300
|
+
*/
|
|
301
|
+
export type RecordParkedDecisionResult = {
|
|
302
|
+
ok: true;
|
|
303
|
+
row: AskRow;
|
|
304
|
+
} | {
|
|
305
|
+
ok: false;
|
|
306
|
+
reason: "ask_not_parked" | "idempotency_conflict";
|
|
307
|
+
row: AskRow | null;
|
|
308
|
+
};
|
|
288
309
|
/**
|
|
289
310
|
* 幂等键的入店卫生门(属主兜底轮 F2,三 twin 同判——SQL 双方言与 InMemory 都从这里过)。
|
|
290
311
|
*
|
|
@@ -513,6 +534,15 @@ export interface ApprovalAskStore {
|
|
|
513
534
|
* 缺省等于不绑属主,安全轴上那是静默放行。
|
|
514
535
|
*/
|
|
515
536
|
decideAsk(askId: string, batchId: string, owner: string | null, decision: DecideAskInput): Promise<DecideResult>;
|
|
537
|
+
/**
|
|
538
|
+
* **停驻形的人决落行**(一张卡一条记录:停驻卡的决定记在它的问行上,行仍 `PARKED`)—— 停驻门(checkpoint 上的那道门,单赢者是续跑腿的门 CAS)
|
|
539
|
+
* **已经受理**这次决定之后,把它的记录({@link AskDecisionRecord})落到这只问的行上。态不变:停驻形的终局恒是那道门,不是这一笔。
|
|
540
|
+
* 谓词 = 行在 ∧ `state = 'PARKED'` ∧ 门判过的那位属主还在行上([ref],与 {@link decideAsk} 同一只属主维)。
|
|
541
|
+
* **覆写**:门被引擎重开(同一把 token 翻回待决、世代号前进)之后又被受理的那一次再落一次 —— 记录恒是「门上此刻站着的那次决定」的那一份
|
|
542
|
+
* (决议向、谁、带哪把键);读者只在门已决时认它(`ToolApprovalCoordinator` 的停驻形读法)。
|
|
543
|
+
* 唯一调用方 = 协调器的回决写者,只在赎回席 2xx 之后调。三 twin 同答。
|
|
544
|
+
*/
|
|
545
|
+
recordParkedDecision(askId: string, owner: string | null, record: AskDecisionRecord): Promise<RecordParkedDecisionResult>;
|
|
516
546
|
/**
|
|
517
547
|
* [ref]:原子终局 claim —— 把「争终局」与「读真相」并成**一次**店往返(胜负判定与败方 `current` 读数
|
|
518
548
|
* 在同一原子单元内,语义见 {@link AskTerminalClaimOutcome})。[ref]-R1 的病根「CAS 与读真相是两次店
|
|
@@ -751,6 +781,17 @@ export declare class SqlApprovalAskStore implements ApprovalAskStore {
|
|
|
751
781
|
ensureAsk(row: NewAskRow): Promise<EnsureAskResult>;
|
|
752
782
|
transitionAsk(askId: string, from: AskState, to: AskState, patch: AskTransitionPatch): Promise<boolean>;
|
|
753
783
|
decideAsk(askId: string, batchId: string, owner: string | null, decision: DecideAskInput): Promise<DecideResult>;
|
|
784
|
+
/**
|
|
785
|
+
* 一份决定记录({@link AskDecisionRecord})的前五格列值,序 = `decision, decision_actor, decision_note, settled_by, decided_via` ——
|
|
786
|
+
* live 形({@link decideAsk})与停驻形({@link recordParkedDecision})两条 UPDATE 共用这**一只**映射(一个事实一处铸列值)。
|
|
787
|
+
*/
|
|
788
|
+
private decisionRecordValues;
|
|
789
|
+
/**
|
|
790
|
+
* 停驻形的人决落行(接口契约见 {@link ApprovalAskStore.recordParkedDecision})。单条 UPDATE,谓词 `state='PARKED'` + 属主维([ref] 的同一只方言镜像);
|
|
791
|
+
* `rev = rev + 1` 照 CAS 铁则②(MySQL 同值 UPDATE 的 affectedRows=0 坑:覆写同一份记录时列值可以逐字节相同)。
|
|
792
|
+
* `(task_id, idempotency_key)` 撞键 ⇒ typed 臂 `idempotency_conflict`(方言错误不出店,与 `decideAsk` 同一只判别)。
|
|
793
|
+
*/
|
|
794
|
+
recordParkedDecision(askId: string, owner: string | null, record: AskDecisionRecord): Promise<RecordParkedDecisionResult>;
|
|
754
795
|
/**
|
|
755
796
|
* [ref] 原子终局 claim(接口契约见 {@link ApprovalAskStore.claimTerminal};类型语义见
|
|
756
797
|
* {@link AskTerminalClaimOutcome})。expire 意图 = 既有 `expireAsk` 事务**原体**(步⓪-③ 逐字保留,
|
|
@@ -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)}`);
|
|
@@ -565,11 +566,7 @@ export class SqlApprovalAskStore {
|
|
|
565
566
|
let askRes;
|
|
566
567
|
try {
|
|
567
568
|
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,
|
|
569
|
+
...this.decisionRecordValues(decision),
|
|
573
570
|
decision.updatedInput === undefined ? null : this.json(decision.updatedInput),
|
|
574
571
|
now,
|
|
575
572
|
decision.idempotencyKey ?? null,
|
|
@@ -608,6 +605,32 @@ export class SqlApprovalAskStore {
|
|
|
608
605
|
throw new Error(`decideAsk: row vanished after commit (askId=${askId})`);
|
|
609
606
|
return { ok: true, row };
|
|
610
607
|
}
|
|
608
|
+
decisionRecordValues(record) {
|
|
609
|
+
return [record.decision, record.decisionActor == null ? null : this.json(record.decisionActor), record.decisionNote ?? null, record.settledBy ?? null, record.decidedVia ?? null];
|
|
610
|
+
}
|
|
611
|
+
async recordParkedDecision(askId, owner, record) {
|
|
612
|
+
if (record.idempotencyKey != null)
|
|
613
|
+
assertIdempotencyKeyShape(record.idempotencyKey);
|
|
614
|
+
assertDecideSource(record);
|
|
615
|
+
const now = Date.now();
|
|
616
|
+
const dialect = this.db.dialect;
|
|
617
|
+
const ownerWhere = decideOwnerWhere(dialect, owner, 10);
|
|
618
|
+
let res;
|
|
619
|
+
try {
|
|
620
|
+
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]);
|
|
621
|
+
}
|
|
622
|
+
catch (err) {
|
|
623
|
+
if (this.isDupKey(err))
|
|
624
|
+
return { ok: false, reason: "idempotency_conflict", row: projectDecideReading(await this.getAsk(askId), owner) };
|
|
625
|
+
throw err;
|
|
626
|
+
}
|
|
627
|
+
const row = projectDecideReading(await this.getAsk(askId), owner);
|
|
628
|
+
if (res.affected !== 1)
|
|
629
|
+
return { ok: false, reason: "ask_not_parked", row };
|
|
630
|
+
if (row === null)
|
|
631
|
+
throw new Error(`recordParkedDecision: row vanished after write (askId=${askId})`);
|
|
632
|
+
return { ok: true, row };
|
|
633
|
+
}
|
|
611
634
|
async claimTerminal(askId, batchId, intent, opts) {
|
|
612
635
|
const to = claimTargetState(intent);
|
|
613
636
|
if (!canAskTransition("STREAM_PENDING", to)) {
|
|
@@ -877,6 +900,12 @@ export class SqlApprovalAskStore {
|
|
|
877
900
|
return rows[0] ? mapBatchRow(rows[0]) : null;
|
|
878
901
|
}
|
|
879
902
|
}
|
|
903
|
+
sealStoreClass(SqlApprovalAskStore, "sql-approval-ask-store", {
|
|
904
|
+
ensureAsk: "exit", transitionAsk: "exit", decideAsk: "exit", claimTerminal: "exit", expireAsk: "exit", bindBatch: "exit", abortBatch: "exit",
|
|
905
|
+
listByState: "exit", listPendingByTask: "exit", listPendingBySession: "exit", listByCall: "exit", listParkingBySourceSession: "exit", getAsk: "exit",
|
|
906
|
+
getByIdempotencyKey: "exit", deferReconcile: "exit", resolveProvisional: "exit", deleteBySession: "exit", reapSettledAsks: "exit", reapEmptyBatches: "exit",
|
|
907
|
+
getBatch: "exit", recordParkedDecision: "exit",
|
|
908
|
+
});
|
|
880
909
|
export class TiDBApprovalAskStore extends SqlApprovalAskStore {
|
|
881
910
|
constructor(pool) {
|
|
882
911
|
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,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)
|
|
@@ -5,6 +5,7 @@ import { WRITABLE, boundDeviceOf, settledDeviceBindOutcome, settledDeviceRebindO
|
|
|
5
5
|
import { bindDeviceStatement, countDeviceBindingsOn, lockRootAndReadClaim, placeWriterStatement, readPlacementOn, rebindDeviceStatement, rowsOnSqlExec, writeCellOn } from "./execution-placement-sql.js";
|
|
6
6
|
import { ensureIndexes } from "./ensure-index.js";
|
|
7
7
|
import { decodeJsonColumn, foldJsonColumn, jsonColumnText, readJsonObjectColumn } from "./sql-json-column.js";
|
|
8
|
+
import { sealStoreClass } from "./store-boundary.js";
|
|
8
9
|
export const DEVICES_TABLE = "device";
|
|
9
10
|
export const DEVICE_ENROLL_TOKENS_TABLE = "device_enroll_token";
|
|
10
11
|
export const DEVICE_AUDIT_TABLE = "device_audit";
|
|
@@ -616,6 +617,11 @@ export class SqlDeviceStore {
|
|
|
616
617
|
return rows.map(mapAuditRow);
|
|
617
618
|
}
|
|
618
619
|
}
|
|
620
|
+
sealStoreClass(SqlDeviceStore, "sql-device-store", {
|
|
621
|
+
issueEnrollToken: "exit", getEnrollToken: "exit", consumeEnrollToken: "exit", readDeviceForAdmission: "exit", getDeviceUnscoped: "exit",
|
|
622
|
+
listDevicesByOwner: "exit", listDevicesUnscoped: "exit", revokeDevice: "exit", acquireConnection: "exit", heartbeatConnection: "exit",
|
|
623
|
+
releaseConnection: "exit", placeDeviceExecution: "exit", rebindDeviceExecution: "exit", countDeviceBindings: "exit", appendAudit: "exit", listAudit: "exit",
|
|
624
|
+
});
|
|
619
625
|
export class TiDBDeviceStore extends SqlDeviceStore {
|
|
620
626
|
constructor(pool) {
|
|
621
627
|
super(mysqlDriver(pool));
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **错误出身记号** —— 「这只错是谁交出来的」这件事的唯一属主(叶:零 import)。词是闭集两只({@link ErrorOrigin}),读者一只:店边界 `terminal.ts` 的 `storeBoundaryFault`。
|
|
3
|
+
* · `driver` —— 数据库驱动交出的错。写者两只、都是池座,都只**记**(不改错误对象、不记日志、不改控制流):
|
|
4
|
+
* MySQL 协议 `sql-driver.ts` 的 `createCloseAwarePool`(借连接、池上其余返回承诺的成员)与守卫租约 `leaseOf`(语句与事务动词);
|
|
5
|
+
* PostgreSQL `pg-pool.ts` 的 `createPgPool` 拦截层(`pool.query` / `pool.connect` 与借出 client 的 `query`)。
|
|
6
|
+
* 边界沿 `cause` 链查它 —— 与词法扳机(码出了本仓词法)是边界的两条扳机;它补的是词法看不见的那一类:驱动交出的**无码**错。
|
|
7
|
+
* · `caller` —— 调用方自己的抛出物,店把它原样还给调用方(店在自己的体里已经把它与库错分开了:记忆补丁落地的 `confirm` 钩抛出物)。
|
|
8
|
+
* 边界见它即同一引用放行:它不是店的失败,它的类、码、身份都是调用方的(码长什么样都不换句)。写者 = 店里分开调用方抛出物的那一处(`memory-engine-sql-apply.ts`)。
|
|
9
|
+
*
|
|
10
|
+
* 为什么记号住在这只叶子里:边界函数在 `terminal.ts`,`sql-driver.ts` 的连接初始化拒句要先读边界(`terminal.ts` → `sql-driver.ts` 再反向就成环,
|
|
11
|
+
* 运行时值图零环由 `test/module-cycle-gate.test.ts` 守);池座、店与边界都只依赖这一张表。
|
|
12
|
+
*/
|
|
13
|
+
export type ErrorOrigin = "driver" | "caller";
|
|
14
|
+
/** 打记号(原样交回,便于 `throw markErrorOrigin(err, "driver")`);非对象的抛出值记不了,原样交回。先打的词为准(同一只错不改出身)。 */
|
|
15
|
+
export declare function markErrorOrigin<E>(err: E, origin: ErrorOrigin): E;
|
|
16
|
+
/** 这一只对象的出身词(只看它本身;沿 `cause` 链查是读者的事);没记过 ⇒ `undefined`。 */
|
|
17
|
+
export declare function errorOriginOf(err: unknown): ErrorOrigin | undefined;
|
|
18
|
+
//# sourceMappingURL=error-origin.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const ORIGIN = new WeakMap();
|
|
2
|
+
export function markErrorOrigin(err, origin) {
|
|
3
|
+
if (typeof err === "object" && err !== null && !ORIGIN.has(err))
|
|
4
|
+
ORIGIN.set(err, origin);
|
|
5
|
+
return err;
|
|
6
|
+
}
|
|
7
|
+
export function errorOriginOf(err) {
|
|
8
|
+
return typeof err === "object" && err !== null ? ORIGIN.get(err) : undefined;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=error-origin.js.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The execution seam's path law — ONE reading for every execution environment this server mints (the seven lanes: adb / device / e2b /
|
|
3
|
+
* host / k8s / local-docker / ssh) and for the sandbox write gate's stand-in environment (`boot/deferred-sandbox-path-env.ts`).
|
|
4
|
+
*
|
|
5
|
+
* The law (the engine's, `ExecutionEnv` contract; the engine's own `NodeExecutionEnv` reads every path this way): a path a method is
|
|
6
|
+
* handed is ABSOLUTE AS WRITTEN, or relative and ANCHORED at the environment's working directory with exactly one separator. Nothing here
|
|
7
|
+
* folds a `..` or a `.` and nothing resolves a link: the filesystem the path lands on resolves them, components first — so a `..` that
|
|
8
|
+
* follows a symbolic link goes where the link leads (`<base>/bridge/../next` with `bridge -> elsewhere/sub` names `<base>/elsewhere/next`).
|
|
9
|
+
* A lexical fold would name `<base>/next` instead: the write gate (which asks the real filesystem what the spelling names) and the tool
|
|
10
|
+
* (which opened the folded name) would then judge and touch two different files.
|
|
11
|
+
*
|
|
12
|
+
* Three faces, one anchor ({@link anchorUnder}): the path a method reads ({@link anchoredPath}), `joinPath` ({@link joinedPath}) and the
|
|
13
|
+
* paths a listing reports (each entry anchored under the path the listing was handed). The remote lanes' shell scripts (the link-chain walk
|
|
14
|
+
* and the staged write, `remote-shell.ts`) already anchor this way in shell; this module is the same law for the TypeScript faces.
|
|
15
|
+
*
|
|
16
|
+
* Pure leaf: string arithmetic only, no I/O.
|
|
17
|
+
*/
|
|
18
|
+
import type { PlatformPath } from "node:path";
|
|
19
|
+
/**
|
|
20
|
+
* The two facts of a path family the law reads: its separator and its absolute-path judge. The remote lanes read POSIX whatever the
|
|
21
|
+
* worker runs on (`path.posix`; the device lane passes its one absolute-path judge, `isDeviceAbsolutePath`); the host lane reads the
|
|
22
|
+
* worker's own (`path`).
|
|
23
|
+
*/
|
|
24
|
+
export type SeamPathFamily = Pick<PlatformPath, "sep" | "isAbsolute">;
|
|
25
|
+
/** `name` placed under `dir` with exactly one separator — never folded, never re-rooted. */
|
|
26
|
+
export declare function anchorUnder(family: SeamPathFamily, dir: string, name: string): string;
|
|
27
|
+
/** The path a method is handed, as the environment reads it: absolute ⇒ as written; relative ⇒ anchored at `cwd`. */
|
|
28
|
+
export declare function anchoredPath(family: SeamPathFamily, cwd: string, p: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* `joinPath`: the first part as written; every later part is a segment, never a root (its leading separators are dropped); empty parts
|
|
31
|
+
* are dropped; the rest anchored in turn. No parts ⇒ `"."`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function joinedPath(family: SeamPathFamily, parts: readonly string[]): string;
|
|
34
|
+
//# sourceMappingURL=exec-path-law.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function anchorUnder(family, dir, name) {
|
|
2
|
+
const endsInSeparator = dir.endsWith(family.sep) || (family.sep === "\\" && dir.endsWith("/"));
|
|
3
|
+
return endsInSeparator ? `${dir}${name}` : `${dir}${family.sep}${name}`;
|
|
4
|
+
}
|
|
5
|
+
export function anchoredPath(family, cwd, p) {
|
|
6
|
+
return family.isAbsolute(p) ? p : anchorUnder(family, cwd, p);
|
|
7
|
+
}
|
|
8
|
+
export function joinedPath(family, parts) {
|
|
9
|
+
const leading = family.sep === "\\" ? /^[\\/]+/ : /^\/+/;
|
|
10
|
+
const named = parts.map((part, i) => (i === 0 ? part : part.replace(leading, ""))).filter((part) => part !== "");
|
|
11
|
+
return named.length === 0 ? "." : named.reduce((at, part) => anchorUnder(family, at, part));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=exec-path-law.js.map
|
|
@@ -3,12 +3,13 @@ import { retiredExecutionLaneHintM40 } from "./execution-lane-rename-m40.js";
|
|
|
3
3
|
import { sessionFaceFromRow } from "../session-incarnation.js";
|
|
4
4
|
import { toIso } from "./sql-row-helpers.js";
|
|
5
5
|
import { SESSION_EXT_TABLE, ensureSessionExtRowStatement, ensureSessionExtRowsStatement } from "./session-ext-table.js";
|
|
6
|
+
import { lockSessionRootOn } from "./session-row-sql.js";
|
|
6
7
|
import { WRITABLE, assertPlaceableLane, boundDeviceOf, settledMirrorOutcome, settledPlaceOutcome, } from "../execution-placement.js";
|
|
8
|
+
import { sealStoreObject } from "./store-boundary.js";
|
|
7
9
|
const WRITER = "writer";
|
|
8
10
|
const MIRROR = "mirror";
|
|
9
11
|
const NOT_WRITER = "(execution_role IS NULL OR execution_role <> 'writer')";
|
|
10
12
|
const EXECUTION_CELL_COLUMNS = "execution_role, execution_lane, execution_device_id, execution_device_owner_tenant, execution_device_owner_subject, execution_placed_at, execution_rev";
|
|
11
|
-
const OCCUPANT_COLUMNS = "owner, incarnation, placement_kind";
|
|
12
13
|
const READING_COLUMNS = `sm.owner, sm.incarnation, sm.placement_kind, ${EXECUTION_CELL_COLUMNS.split(", ").map((c) => `se.${c}`).join(", ")}`;
|
|
13
14
|
function binder(dialect) {
|
|
14
15
|
const values = [];
|
|
@@ -174,9 +175,8 @@ export function placementReadingFromRow(root, row) {
|
|
|
174
175
|
export function rowsOnSqlExec(exec) {
|
|
175
176
|
return async (sql, values) => (await exec.query(sql, [...values])).rows;
|
|
176
177
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
return (await conn(`SELECT ${OCCUPANT_COLUMNS} FROM session_meta WHERE session_id = ${ph} FOR UPDATE`, [root]))[0];
|
|
178
|
+
function lockRootOn(conn, dialect, root) {
|
|
179
|
+
return lockSessionRootOn(conn, dialect, root);
|
|
180
180
|
}
|
|
181
181
|
export async function readClaimOn(conn, dialect, root) {
|
|
182
182
|
const ph = dialect === "pg" ? "$1" : "?";
|
|
@@ -214,7 +214,7 @@ export function createSqlExecutionPlacementSeat(db) {
|
|
|
214
214
|
const s = readPlacementRowStatement(db.dialect, root);
|
|
215
215
|
return placementReadingFromRow(root, (await db.query(s.text, [...s.values])).rows[0]);
|
|
216
216
|
};
|
|
217
|
-
return {
|
|
217
|
+
return sealStoreObject({
|
|
218
218
|
read,
|
|
219
219
|
async place(root, occupant, cell) {
|
|
220
220
|
assertPlaceableLane(root, cell);
|
|
@@ -269,6 +269,6 @@ export function createSqlExecutionPlacementSeat(db) {
|
|
|
269
269
|
conn.release();
|
|
270
270
|
}
|
|
271
271
|
},
|
|
272
|
-
};
|
|
272
|
+
}, "sql-execution-placement-seat", { read: "exit", place: "exit", markMirror: "exit" });
|
|
273
273
|
}
|
|
274
274
|
//# sourceMappingURL=execution-placement-sql.js.map
|