@sema-agent/server 7.132.0 → 7.134.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 +353 -0
- package/README.md +8 -9
- package/README.zh-CN.md +7 -6
- package/USAGE.md +301 -64
- package/deploy/sema-up/README.md +35 -1
- package/deploy/sema-up/chart/Chart.yaml +1 -1
- package/deploy/sema-up/chart/templates/NOTES.txt +15 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +129 -0
- package/deploy/sema-up/chart/templates/sealed-key.yaml +24 -0
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +19 -2
- package/deploy/sema-up/chart/templates/server.yaml +19 -2
- package/deploy/sema-up/chart/values-full-single.yaml +5 -1
- package/deploy/sema-up/chart/values.yaml +34 -0
- package/deploy/sema-up/stack/compose.yaml +3 -0
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
- package/dist/adoption/plan.d.ts +3 -2
- package/dist/adoption/plan.js +7 -5
- package/dist/adoption/runner.js +3 -10
- package/dist/adoption/sql.d.ts +3 -2
- package/dist/adoption/sql.js +3 -5
- package/dist/adoption/wire.d.ts +4 -1
- package/dist/adoption/wire.js +1 -0
- package/dist/approval-ask-audit-store.d.ts +32 -14
- package/dist/approval-ask-audit-store.js +272 -74
- package/dist/approval-ask-machine.d.ts +15 -0
- package/dist/approval-ask-machine.js +6 -0
- package/dist/approval-ask-retention.d.ts +136 -0
- package/dist/approval-ask-retention.js +102 -0
- package/dist/approval-card.d.ts +83 -23
- package/dist/approval-card.js +45 -15
- package/dist/approval-content-kind.d.ts +5 -2
- package/dist/approval-content-kind.js +16 -3
- package/dist/approval-deny-reasons.d.ts +1 -1
- package/dist/approval-gate-currency.d.ts +72 -0
- package/dist/approval-gate-currency.js +94 -0
- package/dist/approval.d.ts +15 -0
- package/dist/approval.js +55 -17
- package/dist/audit.d.ts +27 -10
- package/dist/audit.js +12 -16
- package/dist/bake-runner/main.js +3 -2
- package/dist/boot/coordinators.d.ts +6 -1
- package/dist/boot/coordinators.js +6 -3
- package/dist/boot/deferred-sandbox-path-env.js +1 -1
- package/dist/boot/execution-env.js +9 -7
- package/dist/boot/execution-lane.js +11 -0
- package/dist/boot/leader.d.ts +2 -0
- package/dist/boot/leader.js +4 -1
- package/dist/boot/memory-boundary.js +2 -2
- package/dist/boot/memory-consolidation.d.ts +5 -4
- package/dist/boot/memory-consolidation.js +7 -6
- package/dist/boot/org-delivery.d.ts +28 -0
- package/dist/boot/org-delivery.js +20 -0
- package/dist/boot/read-deny-anchor-audit.js +2 -2
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +21 -1
- package/dist/boot/resolve-spec.d.ts +3 -0
- package/dist/boot/resolve-spec.js +60 -81
- package/dist/boot/runner-deps.d.ts +18 -5
- package/dist/boot/runner-deps.js +10 -0
- package/dist/boot/session-faces.d.ts +1 -0
- package/dist/boot/session-faces.js +4 -2
- package/dist/boot/stage-02-web-admin-pull.js +4 -1
- package/dist/boot/stage-06-runners.d.ts +6 -3
- package/dist/boot/stage-06-runners.js +20 -4
- package/dist/boot/stage-07-capability-layer.d.ts +4 -1
- package/dist/boot/stage-07-capability-layer.js +24 -3
- package/dist/boot/stage-08-reapers.d.ts +4 -1
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +5 -1
- package/dist/boot/stage-09-leader.js +2 -2
- package/dist/boot/stage-10-http-server.d.ts +5 -1
- package/dist/boot/stage-10-http-server.js +6 -6
- package/dist/boot/stores.d.ts +8 -0
- package/dist/boot/stores.js +10 -14
- package/dist/boot/web-admin.d.ts +10 -0
- package/dist/boot/web-admin.js +162 -65
- package/dist/boot/workflow-orchestration.d.ts +2 -0
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/brain.js +8 -3
- package/dist/breaker-key.d.ts +6 -0
- package/dist/breaker-key.js +29 -0
- package/dist/budget.js +5 -1
- package/dist/caller-text-echo.d.ts +11 -6
- package/dist/caller-text-echo.js +10 -12
- package/dist/canonical-json.d.ts +2 -41
- package/dist/canonical-json.js +2 -13
- package/dist/capabilities/center-plugins.d.ts +7 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +21 -0
- package/dist/capabilities/hands-lane.js +10 -0
- package/dist/capabilities/mcp-probe.d.ts +36 -4
- package/dist/capabilities/mcp-probe.js +29 -6
- package/dist/capabilities/scenarios.d.ts +63 -7
- package/dist/capabilities/scenarios.js +39 -7
- package/dist/capability-facts.d.ts +36 -4
- package/dist/capability-facts.js +30 -4
- package/dist/center-config-tier.d.ts +69 -0
- package/dist/center-config-tier.js +42 -0
- package/dist/checkpoint-ctx-seal-m28.d.ts +42 -0
- package/dist/checkpoint-ctx-seal-m28.js +19 -0
- package/dist/checkpoint-identity.d.ts +16 -0
- package/dist/checkpoint-identity.js +19 -0
- package/dist/config-catalog.d.ts +17 -10
- package/dist/config-catalog.js +43 -28
- package/dist/config-d-migration.d.ts +3 -1
- package/dist/config-d-migration.js +2 -2
- package/dist/config-dir-trust.d.ts +114 -0
- package/dist/config-dir-trust.js +388 -0
- package/dist/config-invariants.d.ts +18 -5
- package/dist/config-invariants.js +35 -3
- package/dist/config-provider.d.ts +6 -1
- package/dist/config-provider.js +6 -2
- package/dist/config-types.d.ts +71 -14
- package/dist/config-types.js +8 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +121 -59
- package/dist/delegated-session-owner.d.ts +185 -0
- package/dist/delegated-session-owner.js +119 -0
- package/dist/device-protocol.d.ts +5 -3
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.js +21 -2
- package/dist/device-ws-protocol.d.ts +70 -6
- package/dist/device-ws-protocol.js +50 -23
- package/dist/elicitation.js +3 -2
- package/dist/entry-problems.d.ts +34 -0
- package/dist/entry-problems.js +14 -0
- package/dist/execution-lane-caps.d.ts +49 -10
- package/dist/execution-lane-caps.js +43 -4
- package/dist/field-conflict.d.ts +44 -0
- package/dist/field-conflict.js +21 -0
- package/dist/file-history-disclosure.d.ts +34 -5
- package/dist/file-history-disclosure.js +2 -2
- package/dist/fleet/fleet-bus.d.ts +84 -6
- package/dist/fleet/fleet-bus.js +42 -9
- package/dist/hooks/classic-stations.d.ts +10 -5
- package/dist/hooks/classic-stations.js +4 -4
- package/dist/hooks/command-spawn.d.ts +57 -0
- package/dist/hooks/command-spawn.js +139 -0
- package/dist/hooks/hook-llm.js +2 -2
- package/dist/hooks/hook-runner.d.ts +127 -25
- package/dist/hooks/hook-runner.js +668 -287
- package/dist/hooks/hook-source.d.ts +44 -0
- package/dist/hooks/hook-source.js +40 -0
- package/dist/http/active-run-conflict.d.ts +5 -13
- package/dist/http/active-run-conflict.js +17 -27
- package/dist/http/admission.js +111 -60
- package/dist/http/approval-sweeps.js +58 -19
- package/dist/http/caller-trust.d.ts +77 -0
- package/dist/http/caller-trust.js +143 -0
- package/dist/http/checkpoint-ctx.d.ts +173 -18
- package/dist/http/checkpoint-ctx.js +171 -12
- package/dist/http/claimed-run.d.ts +4 -3
- package/dist/http/device-placement.d.ts +2 -4
- package/dist/http/device-placement.js +2 -1
- package/dist/http/dispatch.js +13 -7
- package/dist/http/durable-run-leg.d.ts +4 -32
- package/dist/http/durable-run-leg.js +37 -12
- package/dist/http/idempotency.d.ts +2 -2
- package/dist/http/idempotency.js +2 -2
- package/dist/http/owner-access.d.ts +56 -0
- package/dist/http/owner-access.js +42 -0
- package/dist/http/principal-gate.d.ts +78 -27
- package/dist/http/principal-gate.js +64 -14
- package/dist/http/readiness.d.ts +11 -5
- package/dist/http/readiness.js +10 -3
- package/dist/http/refusal-body.d.ts +12 -0
- package/dist/http/refusal-body.js +11 -0
- package/dist/http/request-guards.d.ts +16 -32
- package/dist/http/request-guards.js +31 -30
- package/dist/http/resume-ctx-read.d.ts +50 -6
- package/dist/http/resume-ctx-read.js +33 -7
- package/dist/http/resume-legs.d.ts +5 -5
- package/dist/http/resume-legs.js +163 -91
- package/dist/http/retired-service-deps.d.ts +43 -0
- package/dist/http/retired-service-deps.js +18 -0
- package/dist/http/route-ctx.d.ts +44 -37
- package/dist/http/route-ctx.js +4 -0
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/a2a-serve.js +3 -4
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.js +1 -1
- package/dist/http/routes/admin-memory-optout.js +5 -1
- package/dist/http/routes/adoption.js +2 -9
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.js +91 -56
- package/dist/http/routes/background.js +3 -2
- package/dist/http/routes/capabilities.js +20 -4
- package/dist/http/routes/config-catalog.d.ts +3 -3
- package/dist/http/routes/config-catalog.js +1 -1
- package/dist/http/routes/devices.js +3 -17
- package/dist/http/routes/diagnostics.d.ts +3 -3
- package/dist/http/routes/diagnostics.js +6 -2
- package/dist/http/routes/fleet.js +4 -4
- package/dist/http/routes/images.js +6 -7
- package/dist/http/routes/leader.js +1 -8
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +3 -2
- package/dist/http/routes/memory-bundle.js +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-consolidation.js +1 -1
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/memory-origin.js +1 -1
- package/dist/http/routes/memory-policy.d.ts +1 -1
- package/dist/http/routes/memory-policy.js +3 -2
- package/dist/http/routes/notify-wake.js +8 -21
- package/dist/http/routes/observability.js +2 -2
- package/dist/http/routes/principal-inbox.d.ts +39 -0
- package/dist/http/routes/principal-inbox.js +76 -0
- package/dist/http/routes/retention-ops.js +2 -9
- package/dist/http/routes/rules.js +9 -22
- package/dist/http/routes/runs.d.ts +5 -0
- package/dist/http/routes/runs.js +63 -115
- package/dist/http/routes/session-sync.d.ts +3 -2
- package/dist/http/routes/session-sync.js +53 -48
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions-list.js +3 -4
- package/dist/http/routes/sessions.js +33 -43
- package/dist/http/routes/side-query.js +6 -4
- package/dist/http/routes/tasks.js +71 -30
- package/dist/http/routes/trace-usage.js +7 -9
- package/dist/http/routes/workflows.d.ts +351 -0
- package/dist/http/routes/workflows.js +153 -119
- package/dist/http/run-declared-families.d.ts +16 -0
- package/dist/http/run-declared-families.js +12 -0
- package/dist/http/send.d.ts +24 -3
- package/dist/http/send.js +14 -2
- package/dist/http/server.d.ts +23 -18
- package/dist/http/server.js +20 -15
- package/dist/http/stored-body-replay.js +17 -4
- package/dist/http/submit-ctx.d.ts +4 -3
- package/dist/http/submit-ctx.js +23 -6
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +5 -4
- package/dist/http/wire-types.d.ts +17 -10
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -1
- package/dist/lane-home-probe.d.ts +78 -9
- package/dist/lane-home-probe.js +78 -12
- package/dist/leader/endpoint.d.ts +4 -1
- package/dist/leader/endpoint.js +11 -10
- package/dist/leader/wire.d.ts +4 -0
- package/dist/leader/wire.js +8 -7
- package/dist/limit-refusal.d.ts +17 -5
- package/dist/limit-refusal.js +4 -1
- package/dist/main.js +1 -1
- package/dist/mcp-assertion-header.d.ts +31 -10
- package/dist/mcp-assertion-header.js +10 -3
- package/dist/memory-origin-fence.js +2 -2
- package/dist/memory-project-layer.d.ts +37 -0
- package/dist/memory-project-layer.js +46 -0
- package/dist/memory-scope.d.ts +23 -16
- package/dist/memory-scope.js +24 -8
- package/dist/memory-sync-client.d.ts +27 -13
- package/dist/memory-sync-client.js +107 -18
- package/dist/model-compat.d.ts +1 -1
- package/dist/model-entry-refusal.d.ts +9 -1
- package/dist/model-entry-refusal.js +6 -1
- package/dist/model-plane-face.d.ts +51 -0
- package/dist/model-plane-face.js +24 -0
- package/dist/model-provider.d.ts +5 -0
- package/dist/model-provider.js +4 -2
- package/dist/model-route-endpoint.d.ts +8 -11
- package/dist/model-route-endpoint.js +4 -7
- package/dist/model-route-env.d.ts +22 -0
- package/dist/model-route-env.js +2 -0
- package/dist/model-route-gap.d.ts +60 -30
- package/dist/model-route-gap.js +21 -15
- package/dist/observability/corrupt-read-seat.d.ts +7 -0
- package/dist/observability/corrupt-read-seat.js +9 -0
- package/dist/observability/err-text.d.ts +6 -0
- package/dist/observability/err-text.js +18 -4
- package/dist/observability/fail-open.d.ts +35 -9
- package/dist/observability/fail-open.js +35 -9
- package/dist/observability/metrics.js +1 -0
- package/dist/observability/prompt-manifest.d.ts +22 -25
- package/dist/observability/prompt-manifest.js +54 -50
- package/dist/observability/tool-trace.js +9 -10
- package/dist/operator-ask.d.ts +10 -0
- package/dist/operator-ask.js +3 -0
- package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
- package/dist/orchestration/workflow-agent-session-index.js +9 -13
- package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
- package/dist/orchestration/workflow-completion-inbox.js +13 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
- package/dist/orchestration/workflow-notify-journal.js +27 -34
- package/dist/orchestration/workflow-park-decision.d.ts +89 -0
- package/dist/orchestration/workflow-park-decision.js +119 -0
- package/dist/org-delivery-gate.d.ts +81 -0
- package/dist/org-delivery-gate.js +59 -0
- package/dist/panel-tool-names.d.ts +23 -0
- package/dist/panel-tool-names.js +8 -0
- package/dist/parked-decide.d.ts +43 -11
- package/dist/parked-decide.js +100 -51
- package/dist/parked-revive-surface.d.ts +9 -2
- package/dist/parked-revive-surface.js +11 -8
- package/dist/permission-rule-list.d.ts +1 -1
- package/dist/permission-rule-list.js +2 -2
- package/dist/permission-rule-vocab.d.ts +1 -23
- package/dist/permission-rule-vocab.js +0 -13
- package/dist/plugins/approval-ask-store-file.d.ts +16 -1
- package/dist/plugins/approval-ask-store-file.js +21 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
- package/dist/plugins/approval-ask-store-memory.js +34 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
- package/dist/plugins/approval-ask-store-sql.js +37 -1
- package/dist/plugins/approval-payload-fingerprint.d.ts +14 -6
- package/dist/plugins/approval-payload-fingerprint.js +1 -1
- package/dist/plugins/blob-backend.d.ts +38 -25
- package/dist/plugins/blob-backend.js +29 -19
- package/dist/plugins/breaker-state-sql.d.ts +2 -2
- package/dist/plugins/breaker-state-sql.js +4 -4
- package/dist/plugins/caching-session-store.d.ts +4 -1
- package/dist/plugins/caching-session-store.js +7 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +36 -1
- package/dist/plugins/checkpoint-store-sql.js +65 -3
- package/dist/plugins/file-history-store-sql.d.ts +5 -2
- package/dist/plugins/file-history-store-sql.js +3 -1
- package/dist/plugins/file-run-store.d.ts +5 -13
- package/dist/plugins/file-run-store.js +9 -0
- package/dist/plugins/fork-routing-session-store.d.ts +9 -1
- package/dist/plugins/fork-routing-session-store.js +12 -1
- package/dist/plugins/host-platform.d.ts +2 -0
- package/dist/plugins/host-platform.js +2 -1
- package/dist/plugins/local-checkpoint-store.d.ts +15 -2
- package/dist/plugins/local-checkpoint-store.js +32 -1
- package/dist/plugins/local-session-store.d.ts +13 -10
- package/dist/plugins/local-session-store.js +23 -14
- package/dist/plugins/local-session-window.d.ts +45 -0
- package/dist/plugins/local-session-window.js +38 -0
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
- package/dist/plugins/mailbox-store-sql.d.ts +30 -48
- package/dist/plugins/mailbox-store-sql.js +77 -52
- package/dist/plugins/memory-embedder-fingerprint.js +2 -1
- package/dist/plugins/memory-run-store.d.ts +5 -13
- package/dist/plugins/memory-run-store.js +8 -0
- package/dist/plugins/one-time-migrations.d.ts +121 -5
- package/dist/plugins/one-time-migrations.js +332 -8
- package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
- package/dist/plugins/org-delivery-quota-store.js +228 -0
- package/dist/plugins/permission-rule-store-file.js +10 -6
- package/dist/plugins/permission-rule-store-sql.js +8 -8
- package/dist/plugins/pg-pool.js +39 -7
- package/dist/plugins/pg-session-storage.d.ts +18 -5
- package/dist/plugins/pg-session-storage.js +68 -23
- package/dist/plugins/remote-env-adb.d.ts +6 -12
- package/dist/plugins/remote-env-adb.js +12 -2
- package/dist/plugins/remote-env-device.d.ts +14 -7
- package/dist/plugins/remote-env-device.js +23 -15
- package/dist/plugins/remote-env-k8s.d.ts +8 -12
- package/dist/plugins/remote-env-k8s.js +23 -5
- package/dist/plugins/remote-env-local-docker.d.ts +10 -15
- package/dist/plugins/remote-env-local-docker.js +12 -9
- package/dist/plugins/remote-env-ssh.d.ts +10 -16
- package/dist/plugins/remote-env-ssh.js +17 -11
- package/dist/plugins/run-store-sql.d.ts +16 -14
- package/dist/plugins/run-store-sql.js +22 -2
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-user-file.js +2 -2
- package/dist/plugins/session-epoch-anchor.d.ts +32 -6
- package/dist/plugins/session-epoch-anchor.js +2 -3
- package/dist/plugins/session-ownership.d.ts +11 -0
- package/dist/plugins/session-ownership.js +11 -0
- package/dist/plugins/session-placement.d.ts +12 -14
- package/dist/plugins/session-placement.js +2 -15
- package/dist/plugins/session-store.d.ts +18 -8
- package/dist/plugins/session-store.js +15 -4
- package/dist/plugins/sql-driver.d.ts +74 -11
- package/dist/plugins/sql-driver.js +210 -12
- package/dist/plugins/sql-errors.d.ts +23 -0
- package/dist/plugins/sql-errors.js +21 -0
- package/dist/plugins/store-backend.d.ts +36 -1
- package/dist/plugins/store-backend.js +40 -14
- package/dist/plugins/store-contracts.d.ts +42 -0
- package/dist/plugins/store-contracts.js +1 -0
- package/dist/plugins/tidb-pool.d.ts +6 -1
- package/dist/plugins/tidb-pool.js +44 -10
- package/dist/plugins/tidb-session-storage.d.ts +3 -2
- package/dist/plugins/tidb-session-storage.js +2 -2
- package/dist/plugins/tidb-session-store.d.ts +25 -5
- package/dist/plugins/tidb-session-store.js +67 -21
- package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
- package/dist/plugins/workflow-journal-store-sql.js +19 -6
- package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
- package/dist/plugins/workflow-run-store-sql.js +50 -9
- package/dist/posture-source.d.ts +18 -10
- package/dist/posture-source.js +4 -1
- package/dist/project-identity.d.ts +45 -6
- package/dist/project-identity.js +162 -8
- package/dist/project-layer-key.d.ts +28 -0
- package/dist/project-layer-key.js +29 -0
- package/dist/question.js +3 -2
- package/dist/read-deny-entry.d.ts +25 -0
- package/dist/read-deny-entry.js +12 -0
- package/dist/read-face-posture.d.ts +37 -11
- package/dist/read-face-posture.js +32 -3
- package/dist/request-key-closure.d.ts +7 -0
- package/dist/request-key-closure.js +9 -1
- package/dist/request-tool-axes.d.ts +12 -0
- package/dist/request-tool-axes.js +20 -0
- package/dist/request-value-closure.d.ts +5 -0
- package/dist/request-value-closure.js +11 -3
- package/dist/rule-entry-list.d.ts +26 -2
- package/dist/rule-entry-list.js +72 -12
- package/dist/rules-consent.js +3 -4
- package/dist/run-acceptance.d.ts +19 -3
- package/dist/run-acceptance.js +13 -1
- package/dist/run-local.js +37 -6
- package/dist/runs.d.ts +12 -10
- package/dist/runs.js +25 -6
- package/dist/runtime-caps-resolver.d.ts +16 -6
- package/dist/runtime-caps-resolver.js +18 -5
- package/dist/sandbox-pkg-source.d.ts +19 -1
- package/dist/sandbox-pkg-source.js +29 -7
- package/dist/sealed-key.d.ts +32 -0
- package/dist/sealed-key.js +55 -1
- package/dist/security.d.ts +95 -15
- package/dist/security.js +52 -9
- package/dist/session-error-wire.d.ts +31 -7
- package/dist/session-error-wire.js +9 -2
- package/dist/session-sync-kernel.d.ts +37 -10
- package/dist/session-sync-kernel.js +10 -0
- package/dist/session-titled-frame.d.ts +33 -0
- package/dist/session-titled-frame.js +4 -0
- package/dist/session-titler.d.ts +9 -1
- package/dist/session-titler.js +15 -4
- package/dist/spec-fields.js +21 -2
- package/dist/sql-engine-posture.d.ts +3 -1
- package/dist/task-a2a.js +4 -3
- package/dist/task-cwd.d.ts +1 -1
- package/dist/task-mcp.d.ts +5 -5
- package/dist/task-mcp.js +27 -74
- package/dist/task-settings.d.ts +93 -88
- package/dist/task-settings.js +71 -63
- package/dist/text-bidi.d.ts +0 -4
- package/dist/text-bidi.js +1 -3
- package/dist/tighten-only-seats.d.ts +150 -0
- package/dist/tighten-only-seats.js +196 -0
- package/dist/tool-approval.d.ts +451 -136
- package/dist/tool-approval.js +733 -256
- package/dist/tool-rule-names.d.ts +6 -0
- package/dist/trace/core-keyset-guard.d.ts +108 -25
- package/dist/trace/exit-seat.d.ts +40 -0
- package/dist/trace/exit-seat.js +130 -0
- package/dist/trace/ledger-events.d.ts +6 -3
- package/dist/trace/project.d.ts +98 -13
- package/dist/trace/project.js +57 -32
- package/dist/trace/projection-table.d.ts +100 -0
- package/dist/trace/projection-table.js +130 -0
- package/dist/trace/redact.d.ts +57 -0
- package/dist/trace/redact.js +962 -168
- package/dist/trace/self-minted-wire.d.ts +349 -1
- package/dist/trace/self-minted-wire.js +118 -1
- package/dist/trace/wire-projection-faces.d.ts +304 -2
- package/dist/trace/wire-projection-faces.js +160 -13
- package/dist/url-refusal.js +2 -0
- package/dist/web-admin-client/apply-effective.d.ts +12 -0
- package/dist/web-admin-client/apply-effective.js +56 -5
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/facade.js +1 -1
- package/dist/web-admin-client/read-face.js +5 -9
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.js +6 -8
- package/dist/web-admin-client/types.d.ts +1 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
- package/package.json +8 -4
- package/scripts/drain-check-local.mjs +34 -2
- package/scripts/drain-check.mysql.sql +20 -2
- package/scripts/drain-check.pg.sql +20 -2
- package/dist/mcp-tool-faces.d.ts +0 -69
- package/dist/mcp-tool-faces.js +0 -106
|
@@ -111,6 +111,7 @@
|
|
|
111
111
|
*/
|
|
112
112
|
import type { Pool as MySqlPool } from "mysql2/promise";
|
|
113
113
|
import type { Pool as PgPool } from "pg";
|
|
114
|
+
import type { Logger } from "../observability/logger.js";
|
|
114
115
|
export type SqlDialect = "tidb" | "pg";
|
|
115
116
|
export type SqlRow = Record<string, unknown>;
|
|
116
117
|
/** Normalized statement result: `rows` for SELECTs, `affected` for INSERT/UPDATE/DELETE. */
|
|
@@ -175,20 +176,35 @@ export interface SqlEngineFacts {
|
|
|
175
176
|
* `StoreRowTooLargeError` (`sql-errors.ts`): the checkpoint store's `putCtx` (resume inputs) and `put` (the INSERT of
|
|
176
177
|
* a pending row). Every other write — the checkpoint store's updates (`resolve` / `reopen` / …), the session log —
|
|
177
178
|
* keeps its existing driver error.
|
|
179
|
+
* **Level**: the TiDB config item is per TiDB instance, read as the minimum across instances (so the reading does not depend
|
|
180
|
+
* on which instance a connection landed on); the 7.6+ variable is read as this connection sees it at initialization. Its
|
|
181
|
+
* readers: the submit admission reads it off {@link SqlDriver.facts} (it has no connection in hand); the SQL snapshot-blob cap
|
|
182
|
+
* reads it off the connection that writes the blob ({@link sqlConnectionFacts}). This version does not change how it is read.
|
|
178
183
|
*/
|
|
179
184
|
readonly maxRowBytes: number | null;
|
|
180
185
|
/**
|
|
181
|
-
* The largest single statement the server accepts
|
|
182
|
-
* so a second fact (one fact per wall; `null` always and only means "this engine has no such wall").
|
|
186
|
+
* The largest single statement the server accepts on **this connection**, in bytes — its session `@@max_allowed_packet`.
|
|
187
|
+
* A second wall, so a second fact (one fact per wall; `null` always and only means "this engine has no such wall").
|
|
188
|
+
* **Level: one physical connection.** The server copies the session value from the global one when the connection is
|
|
189
|
+
* established and never changes it afterwards: after a DBA changes the global value, connections opened later carry the
|
|
190
|
+
* new value and the ones already pooled keep theirs until the pool replaces them. So the reading lives with the connection
|
|
191
|
+
* that took it: read once at that connection's initialization, kept with it, and judged on it.
|
|
183
192
|
* · **MySQL protocol — InnoDB and TiDB alike**: read at connection initialization, in the same place and with the
|
|
184
193
|
* same unreadable disposition as {@link maxRowBytes} on TiDB: the variable unknown / the query failing / a value that
|
|
185
194
|
* is not a positive integer ⇒ the documented default of that server family
|
|
186
195
|
* ({@link PACKET_CAP_UNREAD_LANDING_BYTES}), recorded through `recordFailOpen("server.sql.packet-cap-unread")` (a per-hit
|
|
187
196
|
* count and one warn line naming the reason). Never `null`: on these engines the wall exists, only its size may be unread.
|
|
188
197
|
* · **`null`** — PostgreSQL: the extended protocol has no statement-size wall.
|
|
189
|
-
* Its
|
|
190
|
-
*
|
|
191
|
-
*
|
|
198
|
+
* Its final judge: the SQL snapshot-blob cap (`plugins/blob-backend.ts` `SqlBlobBackend.putBlob`), which borrows the connection
|
|
199
|
+
* it will write on through {@link connectJudged}, reads this off it ({@link sqlConnectionFacts}), judges, and writes on that
|
|
200
|
+
* same connection — and when it refuses on a connection opened before the DBA raised the wall, that stale connection is
|
|
201
|
+
* replaced and the write judged once more ({@link connectJudged}). On {@link SqlDriver.facts} the value is the most recently
|
|
202
|
+
* initialized connection's reading (the operator read face `GET /v1/diagnostics/wiring` → `sqlEngine.maxPacketBytes`, and
|
|
203
|
+
* the submit admission's early run of the same rule — `http/request-guards.ts` `refuseSubmitBody`: it has no connection in
|
|
204
|
+
* hand, so it pre-judges against the newest reading the pool has — a cached value that moves only when a connection is
|
|
205
|
+
* initialized, so right after a DBA changes the global value it can lag in either direction; the database on the writing
|
|
206
|
+
* connection stays the final judge of a submitted body). Both readers (the blob cap on the borrowed connection's own facts, the admission on the pool's) read the walls
|
|
207
|
+
* — this one and {@link maxRowBytes} — through the one judge {@link sqlWallsOf}, which also says what holds when the facts themselves are absent.
|
|
192
208
|
*/
|
|
193
209
|
readonly maxPacketBytes: number | null;
|
|
194
210
|
/**
|
|
@@ -229,19 +245,24 @@ export type RowWallRowShape = keyof typeof ROW_WALL_ALLOWANCE_BYTES;
|
|
|
229
245
|
/**
|
|
230
246
|
* 一条语句里**载荷之外**的字节余量 —— 固定语句文本 + 表名 + 64 字符哈希 + 长度 + 时间戳 + 行包装(mysql2 真格式化量过:最长表名
|
|
231
247
|
* `file_history_blob` 的 blob INSERT 在 blob 之外 240 字节)。1 KiB 盖住它的 4 倍还多,又不松到压低可用量(16 MiB 包墙下少 1 KiB)。
|
|
232
|
-
* 不扣的话恰在包墙上的载荷整条语句会超出包墙几百字节:放行、库在写那一刻拒。经 {@link packetWallStatementBytes}
|
|
248
|
+
* 不扣的话恰在包墙上的载荷整条语句会超出包墙几百字节:放行、库在写那一刻拒。经 {@link packetWallStatementBytes} 被两个读者共读(同一只规则:blob 帽的终判、提交体受理口的提前一跑)。
|
|
233
249
|
*/
|
|
234
250
|
export declare const STATEMENT_ALLOWANCE_BYTES = 1024;
|
|
235
251
|
/** 行墙下一份载荷最多多少字节:`max(0, 行墙 − 这种行的余量)`({@link ROW_WALL_ALLOWANCE_BYTES})。受理口的提交体门限读 `json`、blob 缺省帽的行墙腿读 `blob`。 */
|
|
236
252
|
export declare function rowWallPayloadBytes(maxRowBytes: number, row: RowWallRowShape): number;
|
|
237
|
-
/**
|
|
253
|
+
/**
|
|
254
|
+
* 包墙下一条语句里的载荷最多多少字节:`max(0, 包墙 − {@link STATEMENT_ALLOWANCE_BYTES})` —— 包墙这一只规则的**唯一**算式,两个读者:
|
|
255
|
+
* · blob 缺省帽的包墙腿(再按膨胀律折半),包墙取自将要执行写入的那条连接 —— **终判**;
|
|
256
|
+
* · 提交体受理口(量的是转义后的语句字节,{@link escapedStatementBytes}),包墙取自池里最近初始化的那条连接 —— 同一只规则的**提前一跑**
|
|
257
|
+
* (受理时手里没有将要写入的连接;拒 ⇒ 413 在任何副作用之前,收 ⇒ 写入那条连接上的库仍是终判)。
|
|
258
|
+
*/
|
|
238
259
|
export declare function packetWallStatementBytes(maxPacketBytes: number): number;
|
|
239
260
|
/**
|
|
240
261
|
* 一段文本作为**一只字符串字面**进 MySQL 协议语句时占的字节数(不含外层两只引号)—— 店真正发出去的字节,不是文本自己的字节数。
|
|
241
|
-
* 店用 `
|
|
262
|
+
* 店用 `query(sql, [text])`,mysql2 在客户端把参数格式化进语句(`sql-escaper` 的 `escapeString`):`\0 \b \t \n \r \x1a " ' \` 九个字符各变成两个字符
|
|
242
263
|
* (多一个反斜杠字节),其余字符原样 —— 多字节 UTF-8 不受影响。所以一份 JSON 里引号 / 反斜杠越多,语句越比文本长(上界 2×:每个字符至多多一字节)。
|
|
243
264
|
*
|
|
244
|
-
* 受理口的包墙腿量它(`http/request-guards.ts` `refuseSubmitBody`)
|
|
265
|
+
* 受理口的包墙腿量它(`http/request-guards.ts` `refuseSubmitBody`):门承诺「按池见过的最新包墙读数写不进去的体在任何副作用之前 413」,量的就必须是语句字节。
|
|
245
266
|
* 这是 mysql2 转义表的**镜像**,不是第二份读法:`test/store-row-cap.test.ts` 把它逐字钉在 mysql2 自己的 `escape` 上(`escapedStatementBytes(s) ===
|
|
246
267
|
* Buffer.byteLength(mysql.escape(s)) − 2`,含全码点表扫),mysql2 升级改转义表时那格先红。不直接调 `escape` 取长度,是因为那会为一份 8 MiB 的体再造一份 8–16 MiB 的字符串。
|
|
247
268
|
*/
|
|
@@ -291,7 +312,7 @@ export type SqlEngineReading = Pick<SqlDriver, "dialect" | "facts">;
|
|
|
291
312
|
export declare const SQL_FACTS_ABSENT_WALLS: SqlWallsReading;
|
|
292
313
|
/**
|
|
293
314
|
* 🔴 **此刻一份写入要装进的墙 —— 唯一判官**。两个读者同调它、不各读 `facts`:提交受理口(`http/request-guards.ts` `refuseSubmitBody`)与 SQL 快照 blob 的缺省帽
|
|
294
|
-
* (`plugins/blob-backend.ts` `
|
|
315
|
+
* (`plugins/blob-backend.ts` `sqlBlobCapOf`:店的写前判,读的是**将要执行写入的那条连接**的读口 —— 方言 + 它自己那次初始化的事实;受理口读本池驱动的读口)。输入是一只引擎读口({@link SqlEngineReading}:方言与事实同出),一种读法:
|
|
295
316
|
* · 读口缺席 = 没有 SQL 后端 ⇒ 没有墙(「忘了给」读不成这一臂:后端交出了 SQL 池而没给读口 ⇒ `createHttpServer` 起服拒,见 `ServiceDeps.sqlEngine`);
|
|
296
317
|
* · 事实在场 ⇒ 事实里的两位,出处逐墙取事实里记的那一份({@link SqlEngineFacts.wallSources}:读到的 `reported`,读失败退文档缺省的 `assumed`);
|
|
297
318
|
* · 事实缺席(`null`)⇒ 按读口的方言:PG 没有墙(扩展协议没有这两堵墙 —— 方言事实,不随引擎事实缺席);MySQL 协议 ⇒ {@link SQL_FACTS_ABSENT_WALLS}(两堵都 `assumed`;
|
|
@@ -330,7 +351,10 @@ export declare function sqlDbNowMs(db: Pick<SqlDriver, "dialect" | "query">, sub
|
|
|
330
351
|
export interface SqlDriver extends SqlExec {
|
|
331
352
|
readonly dialect: SqlDialect;
|
|
332
353
|
/**
|
|
333
|
-
* 本池上**最近一次连接初始化的结果**(状态按池存,所以共享一条池的二十多只店 driver 报同一份事实)
|
|
354
|
+
* 本池上**最近一次连接初始化的结果**(状态按池存,所以共享一条池的二十多只店 driver 报同一份事实)—— 运维读面的料。
|
|
355
|
+
* 连接级的事实(包墙 `maxPacketBytes`:会话值,随连接不同)在这里是「最近一次初始化的那条连接的读数」—— 池见过的最新读数,只在有连接初始化时才更新(DBA 调了全局值、
|
|
356
|
+
* 还没有连接重新初始化时它仍是旧值):
|
|
357
|
+
* 提交受理口拿它跑同一只规则的**提前一跑**(手里没有将要写入的连接);终判读的是**将要执行那条语句的连接**的事实({@link sqlConnectionFacts})。
|
|
334
358
|
* 三种读数,含义各不相同:
|
|
335
359
|
* · `null`(还没借出过连接)—— 没有可报的东西,**不猜**;
|
|
336
360
|
* · 事实 —— 最近一次初始化**回读复核**过的值。每条池连接首次借出都重跑一次初始化(记忆化按连接身份),
|
|
@@ -342,6 +366,45 @@ export interface SqlDriver extends SqlExec {
|
|
|
342
366
|
readonly facts: SqlEngineFacts | null;
|
|
343
367
|
connect(): Promise<SqlTxConn>;
|
|
344
368
|
}
|
|
369
|
+
/**
|
|
370
|
+
* 一条**借出的**连接自己的引擎事实 —— 它的初始化回读到的那一份(包墙 `maxPacketBytes` 是这条连接的会话值)。判一条语句装不装得下的地方
|
|
371
|
+
* 只读这里:借出连接 → 读它的墙 → 判 → 在同一条连接上执行(`plugins/blob-backend.ts` `SqlBlobBackend.putBlob`)。
|
|
372
|
+
* 只认本模块的 `mysqlDriver` / `pgDriver` 的 `connect()` 借出的连接;别的连接(测试替身、包装体)没有经过初始化,墙没人读过 ⇒ **响亮抛**,不猜一个数。
|
|
373
|
+
*/
|
|
374
|
+
export declare function sqlConnectionFacts(conn: SqlTxConn): SqlEngineFacts;
|
|
375
|
+
/** 旧连接被换掉时的运维日志事件名。 */
|
|
376
|
+
export declare const STALE_PACKET_WALL_EVENT = "sql_connection_packet_wall_stale";
|
|
377
|
+
/**
|
|
378
|
+
* 判官的**唯一借出口**:借出将要执行写入的那条连接,按它自己的事实判(`judge` 交回 `undefined` = 装得下,否则交回拒绝)。装得下 ⇒ 交回这条连接
|
|
379
|
+
* (调用方在它上面写、负责 `release()`)。拒绝 ⇒ 这条连接已归还,交回拒绝。
|
|
380
|
+
*
|
|
381
|
+
* **旧连接首次撞墙即自换**:包墙是会话值,连接建立时从全局拷一份、此后不变 —— DBA 调大包墙之后,池里已有的连接仍带旧值,而本仓的 MySQL 协议池
|
|
382
|
+
* 不按空闲回收连接(`tidb-pool.ts` `maxIdle` = 连接上限)。所以一次拒绝若由这条连接的**包墙**定(`byPacketWall(拒绝)`),先在**同一条连接**上读一次
|
|
383
|
+
* `@@global.max_allowed_packet`:
|
|
384
|
+
* · 全局值大于这条连接的读数 ⇒ 它是调墙之前建立的旧连接,这一拒不是判决:**销毁**它(池补新连接)、记一行 {@link STALE_PACKET_WALL_EVENT}(连接标识 / 旧值 / 新值),
|
|
385
|
+
* 再借一条**不过时**的连接**重判一次**;仍拒 ⇒ 交回拒绝。重借时,读全局值之前就已初始化、包墙又小于那个全局值的连接同样销毁记一行(不再问库)——
|
|
386
|
+
* 池里这样的旧连接是有限的(都在读全局值之前建立),一条条换完,下一条就是之后才初始化的连接,它带的是那之后的全局值,直接在它上面判(没有固定的跳过上限);
|
|
387
|
+
* · 全局值不大于(或读不出 —— 证明不了过时,拒是关闭方向)⇒ 这一拒就是判决。读不出分两种:变量不认识 / 不是正整数是库的答案,不记;
|
|
388
|
+
* **查询本身失败**是故障,记一行 {@link GLOBAL_PACKET_WALL_UNREAD_EVENT}(连接标识 / 这条连接的墙 / 错误类)再按拒收 —— 方向不变,只是原因不再蒸发。
|
|
389
|
+
* 只在拒的那一刻多一次往返,装得下的写零额外语句;读与判在同一条连接上。运维日志写不出(logger 抛)不改判决、不漏连接:先销毁、再记,
|
|
390
|
+
* 记的失败交给 {@link recordFailOpen}(`server.sql.packet-wall-log-unwritten`,计数 + 契约行 + 探针,不依赖那只坏掉的 logger)。
|
|
391
|
+
*/
|
|
392
|
+
export declare function connectJudged<R>(db: SqlDriver, judge: (facts: SqlEngineFacts) => R | undefined, byPacketWall: (refusal: R) => boolean, log: Pick<Logger, "warn">): Promise<{
|
|
393
|
+
readonly conn: SqlTxConn;
|
|
394
|
+
readonly refusal?: undefined;
|
|
395
|
+
} | {
|
|
396
|
+
readonly conn?: undefined;
|
|
397
|
+
readonly refusal: R;
|
|
398
|
+
}>;
|
|
399
|
+
/**
|
|
400
|
+
* 守卫租约的**池**:交出去的每一条连接 —— 池上裸语句(`pool.query`)和直接 `pool.getConnection()` 的店 —— 都是 {@link leaseOf} 的守卫租约。
|
|
401
|
+
* mysql2 的 `pool.query` 在内部借连接、跑、归还,本仓够不着那条连接,所以库关掉的连接(上面的 1153 一类)只能照常回池;这里换成**每条语句租一条连接**
|
|
402
|
+
* (`getConnection` → 守卫租约上执行 → 归还,被守卫销毁的不归还)。语句契约不变:参数原样到连接,结果是 mysql2 的 `[rows, fields]` 元组,`{ sql, timeout }` 对象形
|
|
403
|
+
* 一并支持(原样交给连接);池的其余成员(`end` / `execute` / `on` …)原样转给底池,返回底池自身的方法(`on` 之类)返回本包装体 —— 链式调用不会逃出守卫。
|
|
404
|
+
* 生产池(`createTidbPool`)恒是它;mysql2 自己的 `pool.query` 对只读类错误(1290 / 1792 / 1836)的销毁收在同一张表里({@link isConnectionUnusableError}),不丢。
|
|
405
|
+
* 不覆盖 `pool.execute`(预备语句:今天只有任务附件店一处,语句是小定长行,碰不到语句墙)。
|
|
406
|
+
*/
|
|
407
|
+
export declare function createCloseAwarePool(pool: MySqlPool): MySqlPool;
|
|
345
408
|
/** MySQL-protocol driver (TiDB / MySQL / MariaDB — `dialect` is the SQL TEXT axis, `facts.engine` the
|
|
346
409
|
* runtime one). Transaction control uses mysql2's NATIVE methods — the historical call shape the
|
|
347
410
|
* fake-pool unit suites script around. */
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { pgSafeJsonStringify, pgProtocolJsonStringify } from "./pg-safe-json.js";
|
|
2
2
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
3
|
+
import { errorKindOf } from "../observability/err-text.js";
|
|
4
|
+
import { isConnectionUnusableError } from "./sql-errors.js";
|
|
3
5
|
export const TIDB_DEFAULT_TXN_ENTRY_SIZE_LIMIT = 6_291_456;
|
|
4
6
|
export const ROW_WALL_ALLOWANCE_BYTES = { json: 64 * 1024, blob: 1024 };
|
|
5
7
|
export const STATEMENT_ALLOWANCE_BYTES = 1024;
|
|
@@ -84,9 +86,92 @@ const POOL_SESSIONS = new WeakMap();
|
|
|
84
86
|
function poolSession(pool) {
|
|
85
87
|
let st = POOL_SESSIONS.get(pool);
|
|
86
88
|
if (st === undefined)
|
|
87
|
-
POOL_SESSIONS.set(pool, (st = {
|
|
89
|
+
POOL_SESSIONS.set(pool, (st = { connections: new WeakMap(), facts: null }));
|
|
88
90
|
return st;
|
|
89
91
|
}
|
|
92
|
+
const LENT = new WeakMap();
|
|
93
|
+
export function sqlConnectionFacts(conn) {
|
|
94
|
+
return lentRecord(conn).facts;
|
|
95
|
+
}
|
|
96
|
+
function lentRecord(conn) {
|
|
97
|
+
const lent = LENT.get(conn);
|
|
98
|
+
if (lent === undefined) {
|
|
99
|
+
throw new Error("sql-driver: this connection was not lent by mysqlDriver()/pgDriver().connect(), so no connection initialization read its walls — " +
|
|
100
|
+
"borrow the connection a statement will run on from the driver before judging that statement's size");
|
|
101
|
+
}
|
|
102
|
+
return lent;
|
|
103
|
+
}
|
|
104
|
+
let INIT_ORDINAL = 0;
|
|
105
|
+
export const STALE_PACKET_WALL_EVENT = "sql_connection_packet_wall_stale";
|
|
106
|
+
const GLOBAL_PACKET_WALL_UNREAD_EVENT = "sql_connection_packet_wall_global_unread";
|
|
107
|
+
export async function connectJudged(db, judge, byPacketWall, log) {
|
|
108
|
+
let conn = await db.connect();
|
|
109
|
+
try {
|
|
110
|
+
let refusal = judge(sqlConnectionFacts(conn));
|
|
111
|
+
if (refusal === undefined)
|
|
112
|
+
return { conn };
|
|
113
|
+
if (byPacketWall(refusal)) {
|
|
114
|
+
const lent = lentRecord(conn);
|
|
115
|
+
const wall = lent.facts.maxPacketBytes;
|
|
116
|
+
const global = wall === null ? null : await readGlobalPacketWallLogged(lent, log);
|
|
117
|
+
if (wall !== null && global !== null && global > wall) {
|
|
118
|
+
const initializedBefore = INIT_ORDINAL;
|
|
119
|
+
retireStale(lent, global, log);
|
|
120
|
+
conn = await borrowNotStale(db, global, initializedBefore, log);
|
|
121
|
+
refusal = judge(sqlConnectionFacts(conn));
|
|
122
|
+
if (refusal === undefined)
|
|
123
|
+
return { conn };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
conn.release();
|
|
127
|
+
return { refusal };
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
conn.release();
|
|
131
|
+
throw err;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function retireStale(lent, globalWallBytes, log) {
|
|
135
|
+
lent.destroy();
|
|
136
|
+
warnPacketWall(log, STALE_PACKET_WALL_EVENT, { connection: lent.id, sessionWallBytes: lent.facts.maxPacketBytes, globalWallBytes });
|
|
137
|
+
}
|
|
138
|
+
async function readGlobalPacketWallLogged(lent, log) {
|
|
139
|
+
try {
|
|
140
|
+
return await lent.readGlobalPacketWall();
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
warnPacketWall(log, GLOBAL_PACKET_WALL_UNREAD_EVENT, { connection: lent.id, sessionWallBytes: lent.facts.maxPacketBytes, errKind: errorKindOf(err) });
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function warnPacketWall(log, event, fields) {
|
|
148
|
+
try {
|
|
149
|
+
log.warn(event, fields);
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
recordFailOpen("server.sql.packet-wall-log-unwritten", `event=${event} err=${errorKindOf(err)}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
async function borrowNotStale(db, globalWallBytes, initializedBefore, log) {
|
|
156
|
+
for (;;) {
|
|
157
|
+
const conn = await db.connect();
|
|
158
|
+
let lent;
|
|
159
|
+
try {
|
|
160
|
+
lent = lentRecord(conn);
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
conn.release();
|
|
164
|
+
throw err;
|
|
165
|
+
}
|
|
166
|
+
const wall = lent.facts.maxPacketBytes;
|
|
167
|
+
if (wall === null || wall >= globalWallBytes || lent.initOrdinal > initializedBefore)
|
|
168
|
+
return conn;
|
|
169
|
+
retireStale(lent, globalWallBytes, log);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async function readGlobalMaxAllowedPacket(c) {
|
|
173
|
+
return positiveIntOf(await mysqlVar(c, "SELECT @@global.max_allowed_packet AS v")) ?? null;
|
|
174
|
+
}
|
|
90
175
|
async function mysqlVar(c, sql) {
|
|
91
176
|
try {
|
|
92
177
|
const r = await mysqlQuery(c, sql);
|
|
@@ -105,16 +190,20 @@ function refuseSession(what) {
|
|
|
105
190
|
`Neither is optional: every "SELECT … FOR UPDATE" decision point in this service is a CURRENT read only under them.`);
|
|
106
191
|
}
|
|
107
192
|
async function establishSession(session, pooled, c, init) {
|
|
108
|
-
|
|
109
|
-
|
|
193
|
+
const known = session.connections.get(pooled);
|
|
194
|
+
if (known !== undefined)
|
|
195
|
+
return known;
|
|
110
196
|
try {
|
|
111
|
-
|
|
112
|
-
|
|
197
|
+
const facts = await init(c);
|
|
198
|
+
const initialized = { facts, initOrdinal: ++INIT_ORDINAL };
|
|
199
|
+
session.facts = facts;
|
|
200
|
+
session.connections.set(pooled, initialized);
|
|
201
|
+
return initialized;
|
|
113
202
|
}
|
|
114
203
|
catch (err) {
|
|
115
204
|
const stale = session.facts;
|
|
116
205
|
session.facts = null;
|
|
117
|
-
session.
|
|
206
|
+
session.connections = new WeakMap();
|
|
118
207
|
if (stale !== null)
|
|
119
208
|
console.warn(`[sql-driver] connection initialization REFUSED — SQL engine facts invalidated (was: ${stale ? `${stale.engine} ${stale.version} ${stale.isolation} txnMode=${stale.txnMode ?? "-"}` : "<absent>"}). GET /v1/diagnostics/wiring -> sqlEngine and GET /v1/capabilities -> sql now report ABSENT, which is the honest ` +
|
|
120
209
|
`reading: this pool cannot currently establish the read semantics every "SELECT … FOR UPDATE" in this repo assumes. Cause: ${err.message}`);
|
|
@@ -203,6 +292,86 @@ async function readMaxAllowedPacket(c, engine) {
|
|
|
203
292
|
recordFailOpen("server.sql.packet-cap-unread", `assumed=${landing} engine=${engine} ${unread}`);
|
|
204
293
|
return { bytes: landing, source: "assumed" };
|
|
205
294
|
}
|
|
295
|
+
const LEASE_STATEMENT_METHODS = new Set(["query", "execute", "beginTransaction", "commit", "rollback"]);
|
|
296
|
+
const GUARDED_LEASES = new WeakSet();
|
|
297
|
+
const BROKEN_LEASES = new WeakMap();
|
|
298
|
+
function leaseOf(raw) {
|
|
299
|
+
if (GUARDED_LEASES.has(raw))
|
|
300
|
+
return raw;
|
|
301
|
+
let destroyed = false;
|
|
302
|
+
const destroy = () => {
|
|
303
|
+
if (destroyed)
|
|
304
|
+
return;
|
|
305
|
+
destroyed = true;
|
|
306
|
+
raw.destroy();
|
|
307
|
+
};
|
|
308
|
+
let turn = Promise.resolve();
|
|
309
|
+
const guard = (run) => {
|
|
310
|
+
const result = turn.then(async () => {
|
|
311
|
+
try {
|
|
312
|
+
return await run();
|
|
313
|
+
}
|
|
314
|
+
catch (err) {
|
|
315
|
+
if (isConnectionUnusableError(err)) {
|
|
316
|
+
destroy();
|
|
317
|
+
BROKEN_LEASES.set(lease, { error: err });
|
|
318
|
+
}
|
|
319
|
+
throw err;
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
turn = result.then(() => undefined, () => undefined);
|
|
323
|
+
return result;
|
|
324
|
+
};
|
|
325
|
+
const lease = new Proxy(raw, {
|
|
326
|
+
get(target, prop) {
|
|
327
|
+
const member = Reflect.get(target, prop, target);
|
|
328
|
+
if (typeof member !== "function")
|
|
329
|
+
return member;
|
|
330
|
+
if (prop === "release")
|
|
331
|
+
return () => (destroyed ? undefined : raw.release());
|
|
332
|
+
if (prop === "destroy")
|
|
333
|
+
return destroy;
|
|
334
|
+
if (prop === "rollback")
|
|
335
|
+
return (...args) => guard(async () => (destroyed ? undefined : member.apply(target, args)));
|
|
336
|
+
if (LEASE_STATEMENT_METHODS.has(prop))
|
|
337
|
+
return (...args) => guard(() => member.apply(target, args));
|
|
338
|
+
return (...args) => {
|
|
339
|
+
const result = member.apply(target, args);
|
|
340
|
+
return result === target ? lease : result;
|
|
341
|
+
};
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
GUARDED_LEASES.add(lease);
|
|
345
|
+
return lease;
|
|
346
|
+
}
|
|
347
|
+
export function createCloseAwarePool(pool) {
|
|
348
|
+
const lend = async () => leaseOf(await pool.getConnection());
|
|
349
|
+
const query = async (...args) => {
|
|
350
|
+
const c = await lend();
|
|
351
|
+
try {
|
|
352
|
+
return await c.query(...args);
|
|
353
|
+
}
|
|
354
|
+
finally {
|
|
355
|
+
c.release();
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
const wrapper = new Proxy(pool, {
|
|
359
|
+
get(target, prop) {
|
|
360
|
+
if (prop === "query")
|
|
361
|
+
return query;
|
|
362
|
+
if (prop === "getConnection")
|
|
363
|
+
return lend;
|
|
364
|
+
const member = Reflect.get(target, prop, target);
|
|
365
|
+
if (typeof member !== "function")
|
|
366
|
+
return member;
|
|
367
|
+
return (...args) => {
|
|
368
|
+
const result = member.apply(target, args);
|
|
369
|
+
return result === target ? wrapper : result;
|
|
370
|
+
};
|
|
371
|
+
},
|
|
372
|
+
});
|
|
373
|
+
return wrapper;
|
|
374
|
+
}
|
|
206
375
|
export function mysqlDriver(pool) {
|
|
207
376
|
const session = poolSession(pool);
|
|
208
377
|
return {
|
|
@@ -212,15 +381,28 @@ export function mysqlDriver(pool) {
|
|
|
212
381
|
},
|
|
213
382
|
query: (sql, params) => mysqlQuery(pool, sql, params),
|
|
214
383
|
async connect() {
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
384
|
+
const raw = await pool.getConnection();
|
|
385
|
+
const c = leaseOf(raw);
|
|
386
|
+
const { facts, initOrdinal } = await establishSession(session, raw.connection ?? raw, c, initMySqlSession);
|
|
387
|
+
const broken = BROKEN_LEASES.get(c);
|
|
388
|
+
if (broken !== undefined)
|
|
389
|
+
throw broken.error;
|
|
390
|
+
const conn = {
|
|
218
391
|
query: (sql, params) => mysqlQuery(c, sql, params),
|
|
219
392
|
begin: () => c.beginTransaction(),
|
|
220
393
|
commit: () => c.commit(),
|
|
221
394
|
rollback: () => c.rollback(),
|
|
222
395
|
release: () => c.release(),
|
|
223
396
|
};
|
|
397
|
+
const threadId = c.threadId;
|
|
398
|
+
LENT.set(conn, {
|
|
399
|
+
facts,
|
|
400
|
+
initOrdinal,
|
|
401
|
+
id: typeof threadId === "number" ? threadId : null,
|
|
402
|
+
destroy: () => c.destroy(),
|
|
403
|
+
readGlobalPacketWall: () => readGlobalMaxAllowedPacket(c),
|
|
404
|
+
});
|
|
405
|
+
return conn;
|
|
224
406
|
},
|
|
225
407
|
};
|
|
226
408
|
}
|
|
@@ -256,8 +438,9 @@ export function pgDriver(pool) {
|
|
|
256
438
|
query: (sql, params) => pgQuery(pool, sql, params),
|
|
257
439
|
async connect() {
|
|
258
440
|
const c = await pool.connect();
|
|
259
|
-
await establishSession(session, c, c, initPgSession);
|
|
260
|
-
|
|
441
|
+
const { facts, initOrdinal } = await establishSession(session, c, c, initPgSession);
|
|
442
|
+
let destroyed = false;
|
|
443
|
+
const conn = {
|
|
261
444
|
query: (sql, params) => pgQuery(c, sql, params),
|
|
262
445
|
begin: async () => {
|
|
263
446
|
await c.query("BEGIN");
|
|
@@ -268,8 +451,23 @@ export function pgDriver(pool) {
|
|
|
268
451
|
rollback: async () => {
|
|
269
452
|
await c.query("ROLLBACK");
|
|
270
453
|
},
|
|
271
|
-
release: () =>
|
|
454
|
+
release: () => {
|
|
455
|
+
if (!destroyed)
|
|
456
|
+
c.release();
|
|
457
|
+
},
|
|
272
458
|
};
|
|
459
|
+
const pid = c.processID;
|
|
460
|
+
LENT.set(conn, {
|
|
461
|
+
facts,
|
|
462
|
+
initOrdinal,
|
|
463
|
+
id: typeof pid === "number" ? pid : null,
|
|
464
|
+
destroy: () => {
|
|
465
|
+
destroyed = true;
|
|
466
|
+
c.release(true);
|
|
467
|
+
},
|
|
468
|
+
readGlobalPacketWall: async () => null,
|
|
469
|
+
});
|
|
470
|
+
return conn;
|
|
273
471
|
},
|
|
274
472
|
};
|
|
275
473
|
}
|
|
@@ -118,6 +118,29 @@ export type RowTooLargeWall = "row" | "statement" | "value";
|
|
|
118
118
|
* MySQL 协议两条墙都认 —— 两条墙对**一条单行 INSERT** 说的是同一件事(这一行写不进),出路不同;PG 认 `54000`。认不出的一律 `undefined`(原始错误原样上抛)。
|
|
119
119
|
*/
|
|
120
120
|
export declare function rowTooLargeWallOf(dialect: SqlDialect, err: unknown): RowTooLargeWall | undefined;
|
|
121
|
+
/**
|
|
122
|
+
* **这条连接不许再回池**的 MySQL 协议错误 —— 闭集,逐码登记「为什么」。两类原因:
|
|
123
|
+
* · **库发完这个错误包之后自己关掉这条连接**(或随后必关):客户端的池只看见「这条语句完了」,连接照常归还,库的 FIN / RST 晚一拍才到 ——
|
|
124
|
+
* 池上紧接着的下一笔借到这条半死的连接,答 `write ECONNRESET`。1153 是真库读数(k3s8 TiDB v7.5.1:超墙的续跑输入写,首笔答 1153 + 带库原句,
|
|
125
|
+
* 同池下一笔 `getCtx` 答 `write ECONNRESET`);其余按各引擎的服务端行为文档登记(**未在真库上逐码复现**,收车档如实标注),错放进来的代价只是一次重连;
|
|
126
|
+
* · **只读类**(只读模式 / 故障切换之后连接落在只读节点上):mysql2 自己的 `pool.query` 对这三个错误号同样销毁连接(`lib/base/pool.js` `isReadOnlyError`)——
|
|
127
|
+
* 本仓的池上裸语句改走租来的连接(`createCloseAwarePool`),不收进来就丢了这条既有行为;归因取 mysql2 的,不另作更窄的断言。
|
|
128
|
+
* **不在表里**的(连接仍可用,语句级错误):唯一键冲突 1062、死锁 1213、锁等待超时 1205、`KILL QUERY` 的 1317、缺表 1146、CHECK 被拒 3819,以及 **TiDB 的单行墙 8025**
|
|
129
|
+
* (`ErrEntryTooLarge`,事务层的语句错;真库读数:同池上 8025 写之后的读照常 —— `checkpoint-row-size-db-integration` ②③④)。
|
|
130
|
+
* 断连形(`ECONNRESET` / `EPIPE` / `PROTOCOL_CONNECTION_LOST`)也不在表里:那是 mysql2 的**致命错误**,连接对象自己已经 `_removeFromPool`。
|
|
131
|
+
* PostgreSQL 没有对应面:node-pg 的 `pool.query` 对任何错误都丢弃那条 client。
|
|
132
|
+
* 新增一行 = 改表 + 在 `test/db-closed-connection-never-pooled.test.ts` 的码表里加一格。
|
|
133
|
+
*/
|
|
134
|
+
export declare const MYSQL_CONNECTION_UNUSABLE_ERRORS: ReadonlyArray<{
|
|
135
|
+
readonly errno: number;
|
|
136
|
+
readonly code: string;
|
|
137
|
+
}>;
|
|
138
|
+
/**
|
|
139
|
+
* 「抛出这个错误的那条连接还能不能回池」的单一判据:{@link MYSQL_CONNECTION_UNUSABLE_ERRORS} 里的错 ⇒ **不能** —— 持连接的一方(`sql-driver.ts` 的 `leaseOf`)
|
|
140
|
+
* 先销毁它、再让错误出去。两个归因键任一在场即认(同本文件其余谓词的姿势:`errno` 与 `code` 是同一件事的两种写法,代理 / 序列化往返可能只留一个)。
|
|
141
|
+
* 认不出的一律不是(连接照常归还;断连形由 mysql2 自己清出池)。只管 MySQL 协议的错误形:PG 的错误没有这两个键,恒 false。
|
|
142
|
+
*/
|
|
143
|
+
export declare function isConnectionUnusableError(err: unknown): boolean;
|
|
121
144
|
/**
|
|
122
145
|
* 检查点店的两笔写(续跑输入 `putCtx` / 停驻行 `put`)被引擎以「一行装不下」拒 ⇒ **这一只**带码错误(码 `store.row_too_large`),不以裸驱动错上抛
|
|
123
146
|
* (其余店写今天仍是各自的驱动错 —— 未收,登记在案)。
|
|
@@ -61,6 +61,27 @@ export function rowTooLargeWallOf(dialect, err) {
|
|
|
61
61
|
return "statement";
|
|
62
62
|
return undefined;
|
|
63
63
|
}
|
|
64
|
+
export const MYSQL_CONNECTION_UNUSABLE_ERRORS = [
|
|
65
|
+
{ errno: 1053, code: "ER_SERVER_SHUTDOWN" },
|
|
66
|
+
{ errno: 1152, code: "ER_ABORTING_CONNECTION" },
|
|
67
|
+
{ errno: 1153, code: "ER_NET_PACKET_TOO_LARGE" },
|
|
68
|
+
{ errno: 1158, code: "ER_NET_READ_ERROR" },
|
|
69
|
+
{ errno: 1159, code: "ER_NET_READ_INTERRUPTED" },
|
|
70
|
+
{ errno: 1160, code: "ER_NET_ERROR_ON_WRITE" },
|
|
71
|
+
{ errno: 1161, code: "ER_NET_WRITE_INTERRUPTED" },
|
|
72
|
+
{ errno: 1927, code: "ER_CONNECTION_KILLED" },
|
|
73
|
+
{ errno: 4031, code: "ER_CLIENT_INTERACTION_TIMEOUT" },
|
|
74
|
+
{ errno: 1290, code: "ER_OPTION_PREVENTS_STATEMENT" },
|
|
75
|
+
{ errno: 1792, code: "ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION" },
|
|
76
|
+
{ errno: 1836, code: "ER_READ_ONLY_MODE" },
|
|
77
|
+
];
|
|
78
|
+
const UNUSABLE_ERRNOS = new Set(MYSQL_CONNECTION_UNUSABLE_ERRORS.map((e) => e.errno));
|
|
79
|
+
const UNUSABLE_CODES = new Set(MYSQL_CONNECTION_UNUSABLE_ERRORS.map((e) => e.code));
|
|
80
|
+
export function isConnectionUnusableError(err) {
|
|
81
|
+
const errno = keyOf(err, "errno");
|
|
82
|
+
const code = keyOf(err, "code");
|
|
83
|
+
return (typeof errno === "number" && UNUSABLE_ERRNOS.has(errno)) || (typeof code === "string" && UNUSABLE_CODES.has(code));
|
|
84
|
+
}
|
|
64
85
|
export class StoreRowTooLargeError extends Error {
|
|
65
86
|
row;
|
|
66
87
|
wall;
|
|
@@ -10,6 +10,7 @@ import { LocalCheckpointStore } from "./local-checkpoint-store.js";
|
|
|
10
10
|
import { FileResumeAnchorStore } from "./file-resume-anchor-store.js";
|
|
11
11
|
import { type ApprovalExemptionStore } from "./approval-exemption-store.js";
|
|
12
12
|
import { type ApprovalNonceStore } from "./approval-nonce-store.js";
|
|
13
|
+
import { type OrgDeliveryQuotaStore } from "./org-delivery-quota-store.js";
|
|
13
14
|
import { type ApprovalAskStore as ApprovalAskStoreType } from "./approval-ask-store-sql.js";
|
|
14
15
|
import { type MemoryOptOutGrantStore } from "./memory-optout-grant-store-sql.js";
|
|
15
16
|
import { type SendFileLedger } from "./send-file-ledger.js";
|
|
@@ -59,6 +60,19 @@ export type ServiceSessionPolicyStore = SessionPolicyStore;
|
|
|
59
60
|
* whole-tree `ServiceFileSnapshotStore` ([ref]: the boundary covers the TRACKED set only — files this
|
|
60
61
|
* session edited; there is no whole-tree manifest anymore). Also the 2c history-transfer store
|
|
61
62
|
* (exportHistory/importHistory + the blob negotiation faces below). */
|
|
63
|
+
/**
|
|
64
|
+
* The 2c `putBlob` answer: core's `FileHistoryResult` plus ONE arm — the SQL blob judge refused the blob on the connection that
|
|
65
|
+
* would have written it ({@link import("./blob-backend.js").BlobTooLargeError}, code `blob_too_large_for_sql`). `PUT /sync/blobs`
|
|
66
|
+
* answers that arm 413 (the store's sentence, plus the machine-readable `wallSource` = where the cap came from) and every other failure 502 (retryable).
|
|
67
|
+
*/
|
|
68
|
+
export type SyncBlobPutResult = import("@sema-agent/core").FileHistoryResult | {
|
|
69
|
+
readonly ok: false;
|
|
70
|
+
readonly error: {
|
|
71
|
+
readonly code: import("./blob-backend.js").BlobTooLargeError["code"];
|
|
72
|
+
readonly message: string;
|
|
73
|
+
readonly wallSource: import("./blob-backend.js").SqlBlobCapReading["source"];
|
|
74
|
+
};
|
|
75
|
+
};
|
|
62
76
|
export type ServiceFileHistoryStore = FileHistoryStore & {
|
|
63
77
|
/** 2c sync blob-face marker — see SqlFileHistoryStore.syncBlobFaces (codex R2-high: name-probing
|
|
64
78
|
* `putBlob` on an arbitrary store collides with the local core store's PRIVATE void helper). */
|
|
@@ -70,7 +84,7 @@ export type ServiceFileHistoryStore = FileHistoryStore & {
|
|
|
70
84
|
* protected — never a synchronous external-store delete). Reaper-driven; SQL twins only. */
|
|
71
85
|
sweepOrphanBlobs?(): Promise<number>;
|
|
72
86
|
/** 2c blob negotiation: upload one content-addressed blob ahead of importHistory. SQL twins only. */
|
|
73
|
-
putBlob?(hash: string, bytes: Uint8Array): Promise<
|
|
87
|
+
putBlob?(hash: string, bytes: Uint8Array): Promise<SyncBlobPutResult>;
|
|
74
88
|
/** 2c blob read face (scope-checked by the route against the session's history graph). SQL twins only. */
|
|
75
89
|
getBlob?(hash: string): Promise<Uint8Array | undefined>;
|
|
76
90
|
/** The subset of `hashes` already present — a cheap SQL INDEX probe (the import presence pre-check,
|
|
@@ -163,6 +177,11 @@ export interface StoreBackend {
|
|
|
163
177
|
* `approvalExemption` 同姿势:tidb/pg = SQL 双方言(单类双语句),local = File 追加日志 + 压实。
|
|
164
178
|
* **不能**退化成进程内易失形:一次重启若把记录抹掉,JWT TTL 窗内的重放就复活了,而那正是本店要关的洞。 */
|
|
165
179
|
approvalNonce(): ApprovalNonceStore;
|
|
180
|
+
/** [ref] §10.2 —— 跨主体投递门的配额店(`org-delivery-quota-store.ts`:一次 take 在同一把锁下判并记对偶界与收件人
|
|
181
|
+
* 聚合界)。REQUIRED on all backends —— tidb/pg = SQL 双方言(单类双语句,窗按库钟),local = File 整份快照(本进程墙钟;
|
|
182
|
+
* 数据根锁保证一个进程)。门装配时才取(`PRINCIPAL_INBOX_ASSISTANT` 在场);**不能**退化成进程内易失形:多副本各数各的
|
|
183
|
+
* = 额度 × 副本数,一次重启清零 = 窗内额度复活。 */
|
|
184
|
+
orgDeliveryQuota(): OrgDeliveryQuotaStore;
|
|
166
185
|
/** [ref]([ref] §3.0-§3.2)流内审批协议持久层:每个流内工具调用一行的 ask 状态机 + 批行。
|
|
167
186
|
* REQUIRED **且持久** on all backends — tidb/pg = SQL 双方言 twin;local = {@link FileApprovalAskStore}。
|
|
168
187
|
*
|
|
@@ -287,6 +306,11 @@ export interface StoreBackend {
|
|
|
287
306
|
* 缺席**是一个真答案**:那里的索引家在 run 店同一间屋子里(`LocalWorkflowAgentSessionIndex`,文件账本
|
|
288
307
|
* 或纯内存),不需要经过 backend。契约与单写者纪律的属主 = orchestration/workflow-agent-session-index.ts。 */
|
|
289
308
|
workflowAgentSessionIndex?(): import("../orchestration/workflow-agent-session-index.js").WorkflowAgentSessionIndex;
|
|
309
|
+
/** workflow 子代停驻卡的耐久决定行(一张卡一行,键 = 子代 checkpoint 的 token),**绑在本后端的 {@link run} 那只 run 店上**(每一笔写都在它的会话认领栅栏里落)。
|
|
310
|
+
* 与 `run()` 同形:无参、恒交同一只(三孪生同),所以这只决定店绑的就是部署的 run 店。SQL 后端 = 跨副本表,读写走 run 店的池;`local` 后端 = 进程内,
|
|
311
|
+
* 账本位置由后端按自己的数据根与 `WORKFLOW_RUN_STORE` 定(`<数据根>/workflows/workflow-park-decisions/decisions.jsonl`;`memory` ⇒ 纯内存)。
|
|
312
|
+
* 契约与律的属主 = orchestration/workflow-park-decision.ts。 */
|
|
313
|
+
workflowParkDecisions?(): import("../orchestration/workflow-park-decision.js").WorkflowParkDecisionStore;
|
|
290
314
|
/** Cloud-only stores below are OPTIONAL: the `local` (in-memory/file) backend omits them (it has no core
|
|
291
315
|
* in-memory twin carrying the service extras, and these are fleet/multi-replica concepts), so a local HTTP
|
|
292
316
|
* service degrades EXACTLY like today's no-DB env (the consumers gate on `backend?.X?.()`). TiDB/PG provide all. */
|
|
@@ -301,6 +325,17 @@ export interface StoreBackend {
|
|
|
301
325
|
checkpoint?(logger?: {
|
|
302
326
|
info?(msg: string, meta?: unknown): void;
|
|
303
327
|
}): CheckpointStoreFull;
|
|
328
|
+
/**
|
|
329
|
+
* 待决 checkpoint 的**只读**读口(**必选**成员)—— 审批账本留存律(`approval-ask-retention.ts` 的挂靠集)读「还有哪些会话停驻着」就走这一口,不走 {@link checkpoint}。
|
|
330
|
+
* 区别只有一条:这一口**不牵动任何别的店**。local 车道的 `checkpoint()` 是 durable 停驻面的装配点 —— 它给 run 店接上 [ref] 的收割探针(停驻行的收割从 no-op 变生效),
|
|
331
|
+
* 那是开了 `DURABLE_APPROVAL` 的部署才该发生的事;留存腿在没开它的部署上同样要读(前世 / 别的副本留下的停驻不因这一世的开关消失,看不见就会把还能被决的停驻的问删掉),
|
|
332
|
+
* 所以读和接线必须分口。SQL 孪生本来无状态(接线靠 JOIN),两口同一只。
|
|
333
|
+
*
|
|
334
|
+
* 🔴 为什么必选而不是跟着 {@link checkpoint} 一起可选:留存腿读不到这一口的后果在**删除方向**(挂靠集里少了待决停驻 ⇒ 还能被决的停驻的问按龄被删),
|
|
335
|
+
* 「有 checkpoint 店却没交读口」若只是运行期的 `undefined`,就是一次静默少保护;必选 ⇒ 漏实现是**编译红**。没有 checkpoint 店的后端(`checkpoint` 缺席)交一只恒空的读口
|
|
336
|
+
* (`{ listPendingSessionIds: async () => [] }` —— 没有店 ⇒ 没有停驻,这是事实不是缺省)。
|
|
337
|
+
*/
|
|
338
|
+
checkpointReadView(): Pick<CheckpointStoreFull, "listPendingSessionIds">;
|
|
304
339
|
toolResult?(): ToolResultStoreFull;
|
|
305
340
|
imageIndex?(): ImageIndex;
|
|
306
341
|
imageBake?(): ImageBake;
|