@sema-agent/server 7.146.0 → 7.147.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 +384 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +170 -66
- package/deploy/facts/lanes.json +7 -0
- package/deploy/sema-up/README.md +2 -2
- package/deploy/sema-up/chart/templates/_helpers.tpl +22 -0
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -4
- package/deploy/sema-up/chart/templates/server.yaml +5 -4
- package/deploy/sema-up/chart/values.yaml +1 -1
- package/deploy/sema-up/cluster-up.sh +2 -1
- package/deploy/sema-up/lib/flagshape.sh +4 -0
- package/deploy/sema-up/lib/lanes.json +2 -5
- package/deploy/sema-up/sema-up.sh +12 -9
- package/deploy/sema-up/stack/compose.yaml +5 -4
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -3
- package/dist/approval-card.d.ts +4 -4
- package/dist/approval.d.ts +3 -3
- package/dist/audit.js +2 -2
- package/dist/bench/s1/live-deps.js +3 -1
- package/dist/boot/crash-last.js +2 -1
- package/dist/boot/device-lane.js +5 -5
- package/dist/boot/engine-lease.d.ts +12 -11
- package/dist/boot/execution-env.d.ts +2 -1
- package/dist/boot/execution-env.js +45 -33
- package/dist/boot/execution-lane.d.ts +37 -9
- package/dist/boot/execution-lane.js +74 -20
- package/dist/boot/exit-boundary.d.ts +1 -1
- package/dist/boot/exit-last.js +2 -1
- package/dist/boot/governance-seams.d.ts +2 -2
- package/dist/boot/leader.js +1 -1
- package/dist/boot/memory-boundary.d.ts +11 -11
- package/dist/boot/memory-boundary.js +3 -3
- package/dist/boot/memory-consolidation.d.ts +13 -24
- package/dist/boot/memory-consolidation.js +0 -13
- package/dist/boot/org-memory.js +3 -2
- package/dist/boot/parked-revive-gate.d.ts +1 -1
- package/dist/boot/parked-revive-gate.js +1 -1
- package/dist/boot/reapers.js +1 -1
- package/dist/boot/resolve-spec.js +91 -111
- package/dist/boot/retention-lane.d.ts +4 -42
- package/dist/boot/session-faces.d.ts +1 -0
- package/dist/boot/session-faces.js +8 -2
- package/dist/boot/stage-01-config.d.ts +1 -1
- package/dist/boot/stage-01-config.js +6 -2
- package/dist/boot/stage-02-web-admin-pull.d.ts +1 -1
- package/dist/boot/stage-02-web-admin-pull.js +10 -8
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +2 -2
- package/dist/boot/stage-05-execution-env.js +3 -3
- package/dist/boot/stage-06-runners.d.ts +3 -3
- package/dist/boot/stage-06-runners.js +1 -3
- package/dist/boot/stage-07-capability-layer.d.ts +3 -3
- package/dist/boot/stage-07-capability-layer.js +4 -9
- package/dist/boot/stage-08-reapers.d.ts +3 -3
- package/dist/boot/stage-09-leader.d.ts +4 -3
- package/dist/boot/stage-10-http-server.d.ts +4 -3
- package/dist/boot/stage-10-http-server.js +2 -1
- package/dist/boot/stores.d.ts +9 -0
- package/dist/boot/stores.js +18 -7
- package/dist/boot/web-admin.js +3 -3
- package/dist/capabilities/center-plugins.d.ts +2 -0
- package/dist/capabilities/center-plugins.js +6 -2
- package/dist/capabilities/composite-members.d.ts +1 -0
- package/dist/capabilities/composite-members.js +1 -0
- package/dist/capabilities/execution-lane.d.ts +7 -7
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +1 -1
- package/dist/capabilities/scenarios.d.ts +32 -18
- package/dist/capabilities/scenarios.js +13 -9
- package/dist/capabilities/settings-contract.d.ts +29 -0
- package/dist/capabilities/settings-contract.js +14 -0
- package/dist/capabilities/skills.d.ts +5 -5
- package/dist/capability-facts.d.ts +38 -0
- package/dist/capability-facts.js +34 -1
- package/dist/center-credential-renewer.js +3 -2
- package/dist/config-catalog.js +6 -5
- package/dist/config-invariants.d.ts +18 -3
- package/dist/config-invariants.js +36 -19
- package/dist/config-lkg.d.ts +1 -1
- package/dist/config-lkg.js +5 -6
- package/dist/config-provider.js +2 -0
- package/dist/config-types.d.ts +190 -186
- package/dist/config.d.ts +68 -5
- package/dist/config.js +80 -54
- package/dist/degenerate-instrument.js +1 -1
- package/dist/deploy-facts.js +3 -2
- package/dist/deployment-shape.d.ts +21 -12
- package/dist/deployment-shape.js +24 -6
- package/dist/env-facts.d.ts +7 -5
- package/dist/env-facts.js +10 -6
- package/dist/execution-config-root.d.ts +5 -5
- package/dist/execution-config-root.js +5 -5
- package/dist/execution-env-purpose.d.ts +14 -0
- package/dist/execution-env-purpose.js +29 -0
- package/dist/execution-lane-caps.d.ts +49 -86
- package/dist/execution-lane-caps.js +52 -62
- package/dist/execution-placement.d.ts +18 -2
- package/dist/execution-placement.js +19 -0
- package/dist/file-history-disclosure.d.ts +2 -2
- package/dist/fleet/drain-entry.d.ts +17 -10
- package/dist/fleet/drain-entry.js +1 -1
- package/dist/fleet/serving-lease.js +3 -4
- package/dist/history-anchor.d.ts +22 -0
- package/dist/history-anchor.js +14 -0
- package/dist/hooks/command-spawn.d.ts +1 -4
- package/dist/hooks/command-spawn.js +0 -11
- package/dist/hooks/hook-runner.d.ts +52 -8
- package/dist/hooks/hook-runner.js +160 -36
- package/dist/http/approval-sweeps.d.ts +2 -5
- package/dist/http/approval-sweeps.js +3 -2
- package/dist/http/checkpoint-ctx.d.ts +17 -0
- package/dist/http/checkpoint-ctx.js +6 -0
- package/dist/http/claim-latency.d.ts +10 -0
- package/dist/http/claim-latency.js +12 -0
- package/dist/http/dispatch.js +1 -1
- package/dist/http/durable-run-leg.js +2 -1
- package/dist/http/execution-context.d.ts +3 -1
- package/dist/http/execution-context.js +4 -0
- package/dist/http/memory-compliance-failure-reply.d.ts +1 -1
- package/dist/http/memory-compliance-failure-reply.js +3 -0
- package/dist/http/memory-store-refusal-reply.d.ts +3 -3
- package/dist/http/memory-store-refusal-reply.js +3 -0
- package/dist/http/owner-access.d.ts +11 -0
- package/dist/http/owner-access.js +7 -4
- package/dist/http/principal-gate.d.ts +3 -14
- package/dist/http/principal-gate.js +0 -13
- package/dist/http/request-guards.d.ts +1 -1
- package/dist/http/resume-legs.d.ts +7 -10
- package/dist/http/resume-legs.js +79 -50
- package/dist/http/rewind-files-reply.d.ts +34 -0
- package/dist/http/rewind-files-reply.js +36 -0
- package/dist/http/route-ctx.d.ts +32 -16
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/approvals-assistant.js +5 -25
- package/dist/http/routes/capabilities.js +8 -2
- package/dist/http/routes/devices.js +1 -1
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/notify-wake.js +2 -1
- package/dist/http/routes/projects.d.ts +70 -0
- package/dist/http/routes/projects.js +86 -0
- package/dist/http/routes/rules.js +30 -2
- package/dist/http/routes/runs.js +8 -8
- package/dist/http/routes/session-sync.js +27 -10
- package/dist/http/routes/sessions.d.ts +7 -1
- package/dist/http/routes/sessions.js +104 -2
- package/dist/http/routes/tasks.js +9 -3
- package/dist/http/server.d.ts +24 -10
- package/dist/http/server.js +17 -6
- package/dist/http/stored-body-replay.d.ts +5 -3
- package/dist/http/stored-body-replay.js +10 -1
- package/dist/http/wire-types.d.ts +19 -10
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/instruction-source-notice.d.ts +1 -1
- package/dist/memory-embedder-reembed.d.ts +38 -0
- package/dist/memory-embedder-reembed.js +20 -0
- package/dist/memory-incident-sink.d.ts +0 -28
- package/dist/memory-incident-sink.js +5 -0
- package/dist/memory-scope.d.ts +2 -2
- package/dist/memory-scope.js +1 -1
- package/dist/memory-store-refusal.d.ts +17 -4
- package/dist/memory-store-refusal.js +1 -1
- package/dist/memory-sync-client.d.ts +2 -0
- package/dist/memory-sync-client.js +13 -11
- package/dist/memory-sync.js +1 -1
- package/dist/model-compat.d.ts +35 -21
- package/dist/model-compat.js +49 -21
- package/dist/model-entry-refusal.d.ts +11 -1
- package/dist/model-entry-refusal.js +7 -0
- package/dist/namespaced-rule-name.d.ts +18 -1
- package/dist/namespaced-rule-name.js +12 -0
- package/dist/observability/fail-open.d.ts +17 -9
- package/dist/observability/fail-open.js +17 -9
- package/dist/observability/metrics.d.ts +2 -0
- package/dist/observability/metrics.js +2 -0
- package/dist/observability/secret-env-scrub.d.ts +30 -4
- package/dist/observability/secret-env-scrub.js +15 -3
- package/dist/orchestration/workflow-agent-session-index.d.ts +7 -12
- package/dist/orchestration/workflow-agent-session-index.js +1 -6
- package/dist/orchestration/workflow-completion-inbox.d.ts +26 -6
- package/dist/orchestration/workflow-completion-inbox.js +63 -45
- package/dist/org-memory-admission.d.ts +5 -2
- package/dist/org-memory-admission.js +25 -10
- package/dist/parked-decide.d.ts +33 -26
- package/dist/parked-decide.js +36 -44
- package/dist/plugins/approval-ask-store-file.d.ts +10 -2
- package/dist/plugins/approval-ask-store-file.js +37 -4
- package/dist/plugins/approval-ask-store-memory.d.ts +5 -3
- package/dist/plugins/approval-ask-store-memory.js +11 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +3 -0
- package/dist/plugins/approval-ask-store-sql.js +3 -1
- package/dist/plugins/blob-backend.d.ts +38 -195
- package/dist/plugins/blob-backend.js +33 -229
- package/dist/plugins/caching-session-store.d.ts +9 -4
- package/dist/plugins/checkpoint-index-columns.d.ts +1 -1
- package/dist/plugins/checkpoint-index-columns.js +3 -2
- package/dist/plugins/checkpoint-store-face.d.ts +1 -1
- package/dist/plugins/device-store-sql.d.ts +2 -2
- package/dist/plugins/device-store-sql.js +5 -10
- package/dist/plugins/execution-lane-rename-m40.d.ts +20 -0
- package/dist/plugins/execution-lane-rename-m40.js +10 -0
- package/dist/plugins/execution-placement-sql.d.ts +63 -88
- package/dist/plugins/execution-placement-sql.js +94 -54
- package/dist/plugins/file-run-store.d.ts +26 -12
- package/dist/plugins/file-run-store.js +63 -63
- package/dist/plugins/imported-layer-root-retirement.d.ts +17 -8
- package/dist/plugins/imported-layer-root-retirement.js +4 -8
- package/dist/plugins/inbox-payload-column.d.ts +14 -0
- package/dist/plugins/inbox-payload-column.js +13 -0
- package/dist/plugins/local-checkpoint-store.d.ts +5 -0
- package/dist/plugins/local-checkpoint-store.js +11 -7
- package/dist/plugins/local-data-dir-modes-m39.d.ts +48 -0
- package/dist/plugins/local-data-dir-modes-m39.js +182 -0
- package/dist/plugins/local-engine-high-water.d.ts +11 -0
- package/dist/plugins/local-engine-high-water.js +59 -0
- package/dist/plugins/local-session-store.d.ts +91 -25
- package/dist/plugins/local-session-store.js +124 -45
- package/dist/plugins/local-task-attachment-store.d.ts +2 -0
- package/dist/plugins/local-task-attachment-store.js +10 -11
- package/dist/plugins/memory-embedder-fingerprint.d.ts +33 -10
- package/dist/plugins/memory-embedder-fingerprint.js +52 -12
- package/dist/plugins/memory-embedder.d.ts +1 -1
- package/dist/plugins/memory-embedder.js +2 -2
- package/dist/plugins/memory-engine-pg.d.ts +4 -3
- package/dist/plugins/memory-engine-pg.js +4 -4
- package/dist/plugins/memory-engine-sql-apply.d.ts +13 -4
- package/dist/plugins/memory-engine-sql-apply.js +1 -1
- package/dist/plugins/memory-engine-tidb.d.ts +8 -5
- package/dist/plugins/memory-engine-tidb.js +7 -8
- package/dist/plugins/one-time-migrations.d.ts +145 -35
- package/dist/plugins/one-time-migrations.js +272 -120
- package/dist/plugins/owner-only-file-mode.d.ts +29 -0
- package/dist/plugins/owner-only-file-mode.js +141 -0
- package/dist/plugins/permission-rule-store-file.d.ts +8 -8
- package/dist/plugins/permission-rule-store-file.js +14 -2
- package/dist/plugins/pg-pool.d.ts +2 -1
- package/dist/plugins/pg-pool.js +11 -4
- package/dist/plugins/release-version.d.ts +20 -0
- package/dist/plugins/release-version.js +28 -0
- package/dist/plugins/remote-env-adb.d.ts +20 -4
- package/dist/plugins/remote-env-adb.js +39 -11
- package/dist/plugins/remote-env-e2b.d.ts +12 -3
- package/dist/plugins/remote-env-e2b.js +6 -4
- package/dist/plugins/remote-env-host.d.ts +9 -1
- package/dist/plugins/remote-env-host.js +6 -5
- package/dist/plugins/remote-env-k8s.d.ts +5 -2
- package/dist/plugins/remote-env-k8s.js +15 -4
- package/dist/plugins/remote-env-local-docker.d.ts +4 -1
- package/dist/plugins/remote-env-local-docker.js +3 -3
- package/dist/plugins/remote-env-ssh.d.ts +8 -2
- package/dist/plugins/remote-env-ssh.js +26 -24
- package/dist/plugins/remote-shell.d.ts +59 -30
- package/dist/plugins/remote-shell.js +175 -62
- package/dist/plugins/retention-declaration.d.ts +37 -0
- package/dist/plugins/retention-declaration.js +9 -0
- package/dist/plugins/retention-deployment.d.ts +126 -0
- package/dist/plugins/retention-deployment.js +88 -0
- package/dist/plugins/retention-lane-store-sql.d.ts +74 -4
- package/dist/plugins/retention-lane-store-sql.js +103 -1
- package/dist/plugins/retention-sql.d.ts +29 -0
- package/dist/plugins/retention-sql.js +8 -0
- package/dist/plugins/schema-consistency.d.ts +0 -6
- package/dist/plugins/schema-consistency.js +1 -2
- package/dist/plugins/schema-ensure-legs.d.ts +1 -1
- package/dist/plugins/schema-ensure-legs.js +11 -1
- package/dist/plugins/session-ext-table.d.ts +74 -0
- package/dist/plugins/session-ext-table.js +121 -0
- package/dist/plugins/session-fork.d.ts +1 -1
- package/dist/plugins/session-row-sql.d.ts +8 -7
- package/dist/plugins/session-row-sql.js +15 -7
- package/dist/plugins/session-store-sql.d.ts +131 -0
- package/dist/plugins/session-store-sql.js +298 -0
- package/dist/plugins/session-workspace-cell.d.ts +2 -2
- package/dist/plugins/session-workspace-cell.js +2 -2
- package/dist/plugins/shared-memory-store-sql.d.ts +10 -0
- package/dist/plugins/shared-memory-store-sql.js +13 -13
- package/dist/plugins/snapshot-bucket-presence.js +1 -1
- package/dist/plugins/sql-driver.d.ts +23 -7
- package/dist/plugins/sql-driver.js +41 -8
- package/dist/plugins/sql-errors.d.ts +5 -2
- package/dist/plugins/sql-errors.js +4 -0
- package/dist/plugins/store-backend.d.ts +35 -8
- package/dist/plugins/store-backend.js +184 -62
- package/dist/plugins/store-contracts.d.ts +9 -2
- package/dist/plugins/store-contracts.js +1 -0
- package/dist/plugins/task-attachment-store.d.ts +6 -8
- package/dist/plugins/task-attachment-store.js +15 -10
- package/dist/plugins/task-list-store-sql.d.ts +1 -1
- package/dist/plugins/text-column-capacity.d.ts +21 -0
- package/dist/plugins/text-column-capacity.js +5 -0
- package/dist/plugins/tidb-pool.d.ts +3 -2
- package/dist/plugins/tidb-pool.js +19 -31
- package/dist/plugins/user-input-ledger-sql.d.ts +1 -1
- package/dist/read-face-posture.d.ts +6 -6
- package/dist/read-face-posture.js +2 -2
- package/dist/request-value-closure.d.ts +5 -5
- package/dist/request-value-closure.js +1 -1
- package/dist/rules-consent.d.ts +41 -13
- package/dist/rules-consent.js +101 -53
- package/dist/run-local.js +17 -13
- package/dist/runs.d.ts +48 -30
- package/dist/runs.js +26 -16
- package/dist/runtime-caps-resolver.d.ts +15 -8
- package/dist/runtime-caps-resolver.js +14 -10
- package/dist/sealed-key-layout.d.ts +2 -3
- package/dist/sealed-key-layout.js +0 -1
- package/dist/sealed-key.js +7 -5
- package/dist/security.d.ts +5 -3
- package/dist/sema-config-dir.js +2 -2
- package/dist/server-secret-env.d.ts +2 -0
- package/dist/service-version.d.ts +2 -1
- package/dist/service-version.js +2 -2
- package/dist/session-error-wire.d.ts +1 -1
- package/dist/session-incarnation.d.ts +8 -5
- package/dist/session-resident-background.d.ts +85 -32
- package/dist/session-resident-background.js +75 -7
- package/dist/session-row.d.ts +1 -1
- package/dist/session-sync-kernel.d.ts +1 -1
- package/dist/session-workspace.d.ts +11 -2
- package/dist/session-workspace.js +5 -0
- package/dist/sighup-idle.d.ts +1 -1
- package/dist/store-posture.d.ts +2 -1
- package/dist/stored-request-hooks-m20.d.ts +3 -2
- package/dist/stored-request-hooks-m20.js +19 -14
- package/dist/stores-sql/blob-index-sql.d.ts +148 -0
- package/dist/stores-sql/blob-index-sql.js +154 -0
- package/dist/stores-sql/checkpoint-store-sql.d.ts +1 -1
- package/dist/stores-sql/checkpoint-store-sql.js +11 -27
- package/dist/{plugins → stores-sql}/file-history-store-sql.d.ts +23 -11
- package/dist/{plugins → stores-sql}/file-history-store-sql.js +23 -18
- package/dist/{plugins → stores-sql}/pg-session-storage.d.ts +23 -76
- package/dist/{plugins → stores-sql}/pg-session-storage.js +80 -209
- package/dist/{plugins → stores-sql}/retention-store-sql.d.ts +123 -217
- package/dist/{plugins → stores-sql}/retention-store-sql.js +66 -190
- package/dist/{plugins → stores-sql}/session-event-payload.d.ts +1 -1
- package/dist/{plugins → stores-sql}/session-event-payload.js +1 -1
- package/dist/stores-sql/session-policy-store-sql.d.ts +1 -1
- package/dist/stores-sql/session-write-hooks.d.ts +59 -0
- package/dist/stores-sql/session-write-hooks.js +2 -0
- package/dist/{plugins → stores-sql}/tidb-session-storage.d.ts +10 -11
- package/dist/{plugins → stores-sql}/tidb-session-storage.js +10 -21
- package/dist/{plugins → stores-sql}/tidb-session-store.d.ts +32 -122
- package/dist/{plugins → stores-sql}/tidb-session-store.js +71 -171
- package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.js +1 -1
- package/dist/stores-sql/windowed-session-storage.d.ts +56 -0
- package/dist/stores-sql/windowed-session-storage.js +61 -0
- package/dist/task-a2a.d.ts +7 -1
- package/dist/task-a2a.js +15 -14
- package/dist/task-cwd.d.ts +11 -3
- package/dist/task-cwd.js +17 -1
- package/dist/task-mcp.d.ts +10 -2
- package/dist/task-mcp.js +13 -16
- package/dist/task-settings.d.ts +9 -4
- package/dist/task-settings.js +17 -6
- package/dist/tool-approval.d.ts +21 -8
- package/dist/tool-approval.js +10 -6
- package/dist/trace/core-keyset-guard.d.ts +9 -3
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/exit-seat.d.ts +23 -1
- package/dist/trace/exit-seat.js +3 -0
- package/dist/trace/project.d.ts +33 -16
- package/dist/trace/project.js +12 -9
- package/dist/trace/redact.d.ts +1 -1
- package/dist/trace/redact.js +61 -73
- package/dist/trace/self-minted-wire.d.ts +263 -10
- package/dist/trace/self-minted-wire.js +90 -2
- package/dist/trace/sema-provenance.d.ts +45 -41
- package/dist/trace/sema-provenance.js +81 -10
- package/dist/trace/task-notification-facets.d.ts +70 -2
- package/dist/trace/task-notification-facets.js +71 -1
- package/dist/trace/wire-projection-faces.d.ts +38 -2
- package/dist/trace/wire-projection-faces.js +26 -1
- package/dist/unread-request-members.d.ts +66 -0
- package/dist/unread-request-members.js +41 -0
- package/dist/user-input-ledger.d.ts +2 -2
- package/dist/web-admin-client/apply-effective.js +22 -26
- package/dist/web-admin-client/candidate-gate.d.ts +35 -3
- package/dist/web-admin-client/candidate-gate.js +53 -5
- package/dist/web-admin-client/center-request.d.ts +4 -1
- package/dist/web-admin-client/center-request.js +2 -1
- package/dist/web-admin-client/effective-keys.js +0 -1
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/http-client.d.ts +1 -0
- package/dist/web-admin-client/http-client.js +17 -9
- package/dist/web-admin-client/restart-signal.js +5 -2
- package/dist/web-admin-client/skills-mcp.d.ts +20 -6
- package/dist/web-admin-client/skills-mcp.js +26 -21
- package/dist/web-admin-client/types.d.ts +34 -49
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +2 -2
- package/package.json +13 -12
- package/scripts/drain-check-local.mjs +2 -28
- package/scripts/drain-check.mysql.sql +2 -18
- package/scripts/drain-check.pg.sql +2 -18
- package/wire-changes/server@7.147.0.json +813 -0
|
@@ -2,6 +2,30 @@ import { pgSafeJsonStringify, pgProtocolJsonStringify } from "./pg-safe-json.js"
|
|
|
2
2
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
3
3
|
import { errorKindOf } from "../observability/err-text.js";
|
|
4
4
|
import { isConnectionUnusableError } from "./sql-errors.js";
|
|
5
|
+
export class SqlStatementDeadlineExceeded extends Error {
|
|
6
|
+
deadlineMs;
|
|
7
|
+
constructor(deadlineMs) {
|
|
8
|
+
super(`SQL statement did not settle within ${deadlineMs}ms — the connection was destroyed (its transaction rolls back when it closes)`);
|
|
9
|
+
this.deadlineMs = deadlineMs;
|
|
10
|
+
this.name = "SqlStatementDeadlineExceeded";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function withStatementDeadline(run, opts, destroy) {
|
|
14
|
+
const deadlineMs = opts?.deadlineMs;
|
|
15
|
+
if (deadlineMs === undefined)
|
|
16
|
+
return run();
|
|
17
|
+
const running = run();
|
|
18
|
+
running.catch(() => undefined);
|
|
19
|
+
let timer;
|
|
20
|
+
const expired = new Promise((_, reject) => {
|
|
21
|
+
timer = setTimeout(() => {
|
|
22
|
+
destroy();
|
|
23
|
+
reject(new SqlStatementDeadlineExceeded(deadlineMs));
|
|
24
|
+
}, deadlineMs);
|
|
25
|
+
timer.unref?.();
|
|
26
|
+
});
|
|
27
|
+
return Promise.race([running, expired]).finally(() => clearTimeout(timer));
|
|
28
|
+
}
|
|
5
29
|
export const TIDB_DEFAULT_TXN_ENTRY_SIZE_LIMIT = 6_291_456;
|
|
6
30
|
export const ROW_WALL_ALLOWANCE_BYTES = { json: 64 * 1024, blob: 1024 };
|
|
7
31
|
export const STATEMENT_ALLOWANCE_BYTES = 1024;
|
|
@@ -299,15 +323,20 @@ function leaseOf(raw) {
|
|
|
299
323
|
if (GUARDED_LEASES.has(raw))
|
|
300
324
|
return raw;
|
|
301
325
|
let destroyed = false;
|
|
326
|
+
let leaveQueue = () => undefined;
|
|
327
|
+
const gone = new Promise((resolve) => {
|
|
328
|
+
leaveQueue = resolve;
|
|
329
|
+
});
|
|
302
330
|
const destroy = () => {
|
|
303
331
|
if (destroyed)
|
|
304
332
|
return;
|
|
305
333
|
destroyed = true;
|
|
334
|
+
leaveQueue();
|
|
306
335
|
raw.destroy();
|
|
307
336
|
};
|
|
308
337
|
let turn = Promise.resolve();
|
|
309
338
|
const guard = (run) => {
|
|
310
|
-
const result = turn.then(async () => {
|
|
339
|
+
const result = Promise.race([turn, gone]).then(async () => {
|
|
311
340
|
try {
|
|
312
341
|
return await run();
|
|
313
342
|
}
|
|
@@ -388,7 +417,7 @@ export function mysqlDriver(pool) {
|
|
|
388
417
|
if (broken !== undefined)
|
|
389
418
|
throw broken.error;
|
|
390
419
|
const conn = {
|
|
391
|
-
query: (sql, params) => mysqlQuery(c, sql, params),
|
|
420
|
+
query: (sql, params, opts) => withStatementDeadline(() => mysqlQuery(c, sql, params), opts, () => c.destroy()),
|
|
392
421
|
begin: () => c.beginTransaction(),
|
|
393
422
|
commit: () => c.commit(),
|
|
394
423
|
rollback: () => c.rollback(),
|
|
@@ -440,8 +469,14 @@ export function pgDriver(pool) {
|
|
|
440
469
|
const c = await pool.connect();
|
|
441
470
|
const { facts, initOrdinal } = await establishSession(session, c, c, initPgSession);
|
|
442
471
|
let destroyed = false;
|
|
472
|
+
const destroy = () => {
|
|
473
|
+
if (destroyed)
|
|
474
|
+
return;
|
|
475
|
+
destroyed = true;
|
|
476
|
+
c.release(true);
|
|
477
|
+
};
|
|
443
478
|
const conn = {
|
|
444
|
-
query: (sql, params) => pgQuery(c, sql, params),
|
|
479
|
+
query: (sql, params, opts) => withStatementDeadline(() => pgQuery(c, sql, params), opts, destroy),
|
|
445
480
|
begin: async () => {
|
|
446
481
|
await c.query("BEGIN");
|
|
447
482
|
},
|
|
@@ -449,7 +484,8 @@ export function pgDriver(pool) {
|
|
|
449
484
|
await c.query("COMMIT");
|
|
450
485
|
},
|
|
451
486
|
rollback: async () => {
|
|
452
|
-
|
|
487
|
+
if (!destroyed)
|
|
488
|
+
await c.query("ROLLBACK");
|
|
453
489
|
},
|
|
454
490
|
release: () => {
|
|
455
491
|
if (!destroyed)
|
|
@@ -461,10 +497,7 @@ export function pgDriver(pool) {
|
|
|
461
497
|
facts,
|
|
462
498
|
initOrdinal,
|
|
463
499
|
id: typeof pid === "number" ? pid : null,
|
|
464
|
-
destroy
|
|
465
|
-
destroyed = true;
|
|
466
|
-
c.release(true);
|
|
467
|
-
},
|
|
500
|
+
destroy,
|
|
468
501
|
readGlobalPacketWall: async () => null,
|
|
469
502
|
});
|
|
470
503
|
return conn;
|
|
@@ -193,12 +193,15 @@ export declare function isConnectionFaultError(err: unknown): boolean;
|
|
|
193
193
|
* **部署错配类故障**的识别表(闭集;逐行登记「为什么」)—— 到库的连接是好的、语句也是对的,是这套库的形与本部署的要求不符:**重试注定失败**,修表 / 授权之前什么都不会变
|
|
194
194
|
* (与连接类互为反面:那一类是「什么都不改稍后再试可能成」)。读者:整仓一只判官 `plugins/store-fault.ts` 的 `storeFaultClassOf` 的 `deployment` 一词 ——
|
|
195
195
|
* 文件历史店的折点与会话同步拉取口(`503 state.file_history_unreadable`)据它判 `permanence: "terminal"`;审批队列读口并入「此刻读不出」的 503;各读者各自表态,**不在自己那里写码**。
|
|
196
|
+
* 起服建表(`session-ext-table.ts` 的 `ensureSessionExtTableMysql`)问的也是这一只:「库确定拒了这条 DDL」= 本表认得 ⇒ 当场拒启;认不出 ⇒ 原样上抛、开库等待窗重试 —— 不自带第二份分类。
|
|
197
|
+
* 外键四码(3780 / 1215 / 1822 / 1005)只可能出在建表 / 改表上,读写路径上的读者见不到它们 —— 加进本表对那几处零变化。
|
|
196
198
|
*
|
|
197
199
|
* 识别集 = 本表一张,按归因键登记:`code`(字符串)与 MySQL 协议的数字 `errno`(两键是同一件事的两种写法,代理 / 序列化往返可能只留一个;同本文件其余谓词的姿势)。
|
|
198
200
|
* **与连接类互斥**:本表的任何一码都不在 {@link CONNECTION_FAULT_ERRORS} / {@link MYSQL_CONNECTION_UNUSABLE_ERRORS} 的识别集里,反之亦然(`test/store-fault-judge.test.ts` 钉两个方向)—— 同一只错只落一个词。
|
|
199
201
|
*
|
|
200
|
-
* **不在表里**(
|
|
201
|
-
* 认证类拒连(MySQL 1045、PG `28xxx`:凭据 / 白名单)、库级与列级的权限拒(MySQL 1044 / 1143)
|
|
202
|
+
* **不在表里**(认不出一律不是;今天收缺表、权限拒与外键建不成三形,其余是登记在案的未收项,不是「已裁定不判」):缺列(1054 / `42703`:升级前置断言 `assert*Schema` 族有自己的判据与出路)、
|
|
203
|
+
* 认证类拒连(MySQL 1045、PG `28xxx`:凭据 / 白名单)、库级与列级的权限拒(MySQL 1044 / 1143)、语法错(1064:多半是我方的语句,不是库的形)、
|
|
204
|
+
* TiDB 自己的忙 / 区域不可用 / 结构变更冲突一族(9001 / 9005 / 8028,同连接类表的登记)、锁等待超时(1205)。
|
|
202
205
|
*/
|
|
203
206
|
export declare const DEPLOYMENT_FAULT_ERRORS: ReadonlyArray<{
|
|
204
207
|
readonly code: string;
|
|
@@ -148,6 +148,10 @@ export const DEPLOYMENT_FAULT_ERRORS = [
|
|
|
148
148
|
{ code: "42501", why: "PG insufficient_privilege(权限拒:库账号缺这张表 / 这类语句的授权 —— 授权之前重试注定失败)" },
|
|
149
149
|
{ code: "ER_NO_SUCH_TABLE", errno: 1146, why: "MySQL 协议(MySQL / MariaDB / TiDB)缺表:同 PG `42P01`" },
|
|
150
150
|
{ code: "ER_TABLEACCESS_DENIED_ERROR", errno: 1142, why: "MySQL 协议表级权限拒:库账号对这张表缺这类语句的授权,同 PG `42501`" },
|
|
151
|
+
{ code: "ER_FK_INCOMPATIBLE_COLUMNS", errno: 3780, why: "MySQL 协议外键两侧列不相容(类型 / 字符集 / 排序规则对不上):被引表的形与外键要求不符,重试同一句仍不相容" },
|
|
152
|
+
{ code: "ER_CANNOT_ADD_FOREIGN", errno: 1215, why: "MySQL 协议加不上外键(如被引表不是 InnoDB):库的形不收这条约束,改表之前重试注定失败" },
|
|
153
|
+
{ code: "ER_FK_NO_INDEX_PARENT", errno: 1822, why: "MySQL 协议外键的被引列上缺索引:被引表的形不符,建索引之前重试注定失败" },
|
|
154
|
+
{ code: "ER_CANT_CREATE_TABLE", errno: 1005, why: "MySQL 协议建表被存储引擎拒(errno 150 外键形不成 / 121 约束名已占 / 28 盘满):修库之前重试同一句仍被拒" },
|
|
151
155
|
];
|
|
152
156
|
const DEPLOYMENT_FAULT_CODES = new Set(DEPLOYMENT_FAULT_ERRORS.map((r) => r.code));
|
|
153
157
|
const DEPLOYMENT_FAULT_ERRNOS = new Set(DEPLOYMENT_FAULT_ERRORS.flatMap((r) => (r.errno === undefined ? [] : [r.errno])));
|
|
@@ -33,9 +33,12 @@ import type { CounterDegradeHook } from "./write-behind-counter.js";
|
|
|
33
33
|
import { PgRateLimiter } from "./pg-rate-limiter.js";
|
|
34
34
|
import { type SqlSharedMemoryStore, type SharedMemoryScopeAuthorizer } from "./shared-memory-store-sql.js";
|
|
35
35
|
import { type AdoptionLogStore } from "./adoption-log-sql.js";
|
|
36
|
-
import { type
|
|
36
|
+
import { type SqlTransactionHooks } from "../stores-sql/retention-store-sql.js";
|
|
37
|
+
import type { EndedSpace } from "../workspace-space.js";
|
|
38
|
+
import { type RetentionDestructiveInput, type RetentionExecutor, type RetentionExecutorOptions } from "./retention-deployment.js";
|
|
37
39
|
import { type RetentionLaneStore } from "./retention-lane-store-sql.js";
|
|
38
40
|
import type { PermissionRuleStoreBundle } from "../rules-consent.js";
|
|
41
|
+
import { type SqlDriver } from "./sql-driver.js";
|
|
39
42
|
import { type StoreDegradedReason } from "../store-posture.js";
|
|
40
43
|
/** boot 期的一条日志座(级别由**座位**决定,不由参数携带):`createStoreBackend` 的 `onWarn` / `onError`
|
|
41
44
|
* 两参与 `LocalBackend` 的同名字段共用此形。装配层把它们分别接到 `logger.warn` / `logger.error` 上。 */
|
|
@@ -65,7 +68,7 @@ export type ServiceSessionPolicyStore = SessionPolicyStore;
|
|
|
65
68
|
* The SQL twins' blob exchange — core's {@link FileHistoryBlobExchange} group (`put` / `get` / `has`, all three or none, read only
|
|
66
69
|
* through `blobExchangeOf` in `session-sync.ts`, which defers to core's judge) with ONE narrowing: a `put` refusal may carry
|
|
67
70
|
* `blobCap`, the SQL blob judge's refusal on the connection that would have written the blob
|
|
68
|
-
* ({@link import("
|
|
71
|
+
* ({@link import("../stores-sql/blob-index-sql.js").BlobTooLargeError}). Present ⟺ that refusal; `PUT /sync/blobs` answers it 413
|
|
69
72
|
* `blob_too_large_for_sql` (the judge's sentence, plus the machine-readable `wallSource` = where the cap came from). The content-address
|
|
70
73
|
* refusal is core's own (`adopt_failed`, `permanence: "terminal"`, nothing stored); every other failure is a write fault the route answers 502.
|
|
71
74
|
*/
|
|
@@ -75,7 +78,7 @@ export type SqlBlobPutResult = {
|
|
|
75
78
|
readonly ok: false;
|
|
76
79
|
readonly error: FileHistoryError & {
|
|
77
80
|
readonly blobCap?: {
|
|
78
|
-
readonly wallSource: import("
|
|
81
|
+
readonly wallSource: import("../stores-sql/blob-index-sql.js").SqlBlobCapReading["source"];
|
|
79
82
|
};
|
|
80
83
|
};
|
|
81
84
|
};
|
|
@@ -163,7 +166,8 @@ export interface StoreBackend {
|
|
|
163
166
|
* schema that the one-time migrations of server 7.74.0–7.125.x retired and **refuses** with `RetiredSchemaPresentError`
|
|
164
167
|
* (code `config.schema_mismatch`, exported from the package root) before it issues the first CREATE; only then does it create.
|
|
165
168
|
* The check lives in this method itself, so the public sequence `createStoreBackend()` → `ensureSchema()` → `runOneTimeMigrations()`
|
|
166
|
-
* needs no step of its own. The LOCAL backend has no SQL pool
|
|
169
|
+
* needs no step of its own. The LOCAL backend has no SQL pool: its data root's engine high-water is judged when the backend is opened (before any store is built),
|
|
170
|
+
* and a data root refused there surfaces here, as that refusal; otherwise this runs the local reconciliation (strict sidecars, archive snapshots). */
|
|
167
171
|
ensureSchema(): Promise<void>;
|
|
168
172
|
close(): Promise<void>;
|
|
169
173
|
run(): RunStore;
|
|
@@ -354,7 +358,7 @@ export interface StoreBackend {
|
|
|
354
358
|
* `local` 刻意省略 —— 与 {@link leaderRun} 逐字同一条理由:config 层已经把「`REMOTE_EXEC=device` 且
|
|
355
359
|
* 无外部 SQL 店」整个组合拒启了(`device-durable-store` 不变量),所以 local 车道上根本不存在一个需要
|
|
356
360
|
* 这四张表的 device worker。消费点按 `backend?.device?.()` 取,缺席 ⇒ `boot/device-lane.ts` 的
|
|
357
|
-
* `assertDeviceLaneWired` 响亮拒启(
|
|
361
|
+
* `assertDeviceLaneWired` 响亮拒启(**不是**静默跑成无手)。
|
|
358
362
|
*/
|
|
359
363
|
device?(): DeviceStore;
|
|
360
364
|
/**
|
|
@@ -364,9 +368,9 @@ export interface StoreBackend {
|
|
|
364
368
|
*
|
|
365
369
|
* `taskAttachmentTable` 必填、无默认值 —— boot 只在配了对象存储时才 ensure 那张表,一条盲发的
|
|
366
370
|
* DELETE 在无 MinIO 的部署上会以 unknown-table 打红整轮 sweep(理由逐字见
|
|
367
|
-
* `retention-
|
|
371
|
+
* `retention-deployment.ts` 的 `RetentionExecutorOptions`)。组合形见 {@link createSqlRetentionExecutor}。
|
|
368
372
|
*/
|
|
369
|
-
retention?(opts:
|
|
373
|
+
retention?(opts: RetentionExecutorOptions): RetentionExecutor;
|
|
370
374
|
/**
|
|
371
375
|
* [ref] 车2 —— 留存执行面的**非破坏性**半场:sweep 租约、legal-hold 的放置/解除、审计表的读与
|
|
372
376
|
* 非破坏行的写。同样 SQL 专有(它写的三张表只在 SQL schema 里)。
|
|
@@ -403,6 +407,23 @@ export interface StoreBackend {
|
|
|
403
407
|
* `new FileUsageWindowStore(root)` 第二只实例、不接座 ⇒ 坏值只拒不披露,运维找不到是哪只文件。SQL 后端省略(它们有自己的 usage-window 双方言店)。 */
|
|
404
408
|
fileUsageWindowStore?(): UsageWindowStore;
|
|
405
409
|
}
|
|
410
|
+
/**
|
|
411
|
+
* 托管留存执行器的**组合**:引擎座表那一半(`SqlRetentionStore`,事务属主)+ 部署那一半(hold / 审计 / 认领判 / 十一张部署表,
|
|
412
|
+
* `plugins/retention-deployment.ts`,经 K4 事务内钩参与同一事务)。
|
|
413
|
+
*
|
|
414
|
+
* 破坏性三方法**每次调用**铸一只执行器、钩表绑这一次调用(`createRetentionDeploymentHooks` 的头注:审计行的判定时点三格与
|
|
415
|
+
* `checkpoint_ctx` 属主门的域是这一次调用的事实)。会话树删除的 `endedSpaces` 由部署从 `beforeDelete` 收到的行自算,
|
|
416
|
+
* 只在执行器**提交成功返回之后**挂上回执(回滚 ⇒ 执行器抛,不挂)。非破坏两口(域枚举 / 预览)不经钩。
|
|
417
|
+
*/
|
|
418
|
+
/**
|
|
419
|
+
* 一次破坏性调用的整张事务内钩表:部署的 `retention` 组(按这一次调用铸,`createRetentionDeploymentHooks`)+ 会话座的钩
|
|
420
|
+
* (`createSqlSessionWriteHooks`,会话店用的同一只工厂;留存删除走它的 `retention-delete` 臂)。`endedSpaces` 读部署那一半收到的行。
|
|
421
|
+
*/
|
|
422
|
+
export declare function createSqlRetentionCallHooks(db: SqlDriver, opts: RetentionExecutorOptions, input: RetentionDestructiveInput): {
|
|
423
|
+
readonly hooks: SqlTransactionHooks;
|
|
424
|
+
endedSpaces(): readonly EndedSpace[];
|
|
425
|
+
};
|
|
426
|
+
export declare function createSqlRetentionExecutor(db: SqlDriver, opts: RetentionExecutorOptions): RetentionExecutor;
|
|
406
427
|
/** (c)(clay 拍 a+c,2026-07-27;[ref] 换店后域=file_history_blob,门与旋钮名不变)云形 blob 姿势门——
|
|
407
428
|
* boot 时调用(boot/stores.ts),纯函数可单测。SQL 后端(mysql|pg)把 blob 字节落单行的形已被两役
|
|
408
429
|
* 实证撞 mysql-协议包墙(D-1 附件 → 对象存储裁定):大字节归对象存储。per-file 历史的 blob=单文件
|
|
@@ -471,7 +492,13 @@ export declare function createStoreBackend(config: ServiceConfig, onWarn?: BootL
|
|
|
471
492
|
* 而 LocalBackend 的 `ensureSchema` 是**空实现**,真正会抛的 mkdir + 数据根 BootLock 在构造函数里、
|
|
472
493
|
* 落在 try 之外。于是那条降级臂对 local 形从来没生效过,注释宣称的行为与代码真做的事撕裂。
|
|
473
494
|
*
|
|
474
|
-
* **降级臂只有一条:缺省推导的 local
|
|
495
|
+
* **降级臂只有一条:缺省推导的 local 且数据根上什么都没有**(`dbBackend=local && !dbBackendExplicit`,数据根不存在或是空目录 —— 开店之前判)。
|
|
496
|
+
* 判据看的是**数据根的状态**,不是错误的种类:数据根上已有东西 ⇒ 这台部署有过持久面,开它时的**任何**失败(权限 / 只读挂载 / 子目录建不出 /
|
|
497
|
+
* 另一实例持锁 / adoption 在飞 / 账本重放不了 …)都按显式 `DB_BACKEND=local` 同待遇 —— 原样抛、拒启,不退内存(退了 = 已有的会话 / run 账本 /
|
|
498
|
+
* 问账整片看不见、新写只进内存,而 `/health` 照样 200)。只有「数据根不存在 / 空」那一形是「这台机器存不了盘」的诚实等价物,才许退内存 + 一行 warn。
|
|
499
|
+
* 修前按错误种类逐个豁免(adoption 一条、File 店族拒启一条、再往各店构造器里逐处包),漏一处就是一条 fail-open;按状态判之后,新店的新失败默认落在拒启一侧。
|
|
500
|
+
* 1.292 的口径据此收窄:只读挂载 / 建不出的根**在空 / 不存在时**仍退内存;已有数据的根拒启(出路:修好权限 / 挂载 / 停掉持锁的另一实例;要内存就显式写
|
|
501
|
+
* `DB_BACKEND=memory`;要另起一个空根就把 `LOCAL_DATA_ROOT` 指过去)。🔴 **SQL 族没有降级臂** —— 配了 DSN 就是要这只库:
|
|
475
502
|
* `SESSION_BACKEND=auto` 与显式 `DB_BACKEND=mysql|pg` 同一待遇,库当下打不开 ⇒ 在 `STORE_LOCK_WAIT_MS` 的窗内重试
|
|
476
503
|
* ({@link openWithinWait}),到窗仍打不开 ⇒ 拒启(拒句 {@link buildSqlStoreOpenRefusal} 点名后端与库的显示安全形)。修前 `auto` 在这里
|
|
477
504
|
* 静默落内存(只留一行 warn):会话 / 停驻 / run 账本进进程内存、重启即丢,而 `/health` 照样 200 —— [ref] P 类 fail-open。
|
|
@@ -2,7 +2,7 @@ import { homedir } from "node:os";
|
|
|
2
2
|
import { createCorruptReadSeat, createDurableAbsenceSeat } from "../observability/corrupt-read-seat.js";
|
|
3
3
|
import { createLogger } from "../observability/logger.js";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
-
import { existsSync } from "node:fs";
|
|
5
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
6
6
|
import { AdoptionError, FileStorageBackend } from "@sema-agent/core";
|
|
7
7
|
import { FileWorkflowJournalStore } from "@sema-agent/core";
|
|
8
8
|
import { fileSessionCaptureRecordStore } from "@sema-agent/core";
|
|
@@ -34,10 +34,11 @@ import { TiDBUserInputLedgerStore, PgUserInputLedgerStore } from "./user-input-l
|
|
|
34
34
|
import { TiDBResumeAnchorStore, PgResumeAnchorStore } from "./resume-anchor-store-sql.js";
|
|
35
35
|
import { TiDBSessionPolicyStore, PgSessionPolicyStore } from "../stores-sql/session-policy-store-sql.js";
|
|
36
36
|
import { TiDBWorkflowJournalStore, PgWorkflowJournalStore } from "../stores-sql/workflow-journal-store-sql.js";
|
|
37
|
-
import { TiDBFileHistoryStore, PgFileHistoryStore,
|
|
38
|
-
import {
|
|
37
|
+
import { TiDBFileHistoryStore, PgFileHistoryStore, FILE_HISTORY_BLOB_KEY_PREFIX } from "../stores-sql/file-history-store-sql.js";
|
|
38
|
+
import { SqlBlobIndex } from "../stores-sql/blob-index-sql.js";
|
|
39
|
+
import { MinioBlobBackend } from "./blob-backend.js";
|
|
39
40
|
import { buildDisplaySafeUrl } from "../trace/redact.js";
|
|
40
|
-
import { fileMemoryControlDirFor } from "../memory-scope.js";
|
|
41
|
+
import { fileMemoryControlDirFor, memoryEngineRootFor } from "../memory-scope.js";
|
|
41
42
|
import { createTidbPool, ensureSchema as ensureTidbSchema } from "./tidb-pool.js";
|
|
42
43
|
import { createPgPool, ensurePgSchema, pgPoolOptions } from "./pg-pool.js";
|
|
43
44
|
import { TiDBRunStore, PgRunStore } from "./run-store-sql.js";
|
|
@@ -52,48 +53,62 @@ import { TiDBCostQuota } from "./tidb-cost-quota.js";
|
|
|
52
53
|
import { PgCostQuota } from "./pg-cost-quota.js";
|
|
53
54
|
import { TiDBRateLimiter } from "./tidb-rate-limiter.js";
|
|
54
55
|
import { PgRateLimiter } from "./pg-rate-limiter.js";
|
|
55
|
-
import { TiDBSessionStore } from "
|
|
56
|
-
import { PgSessionStore } from "
|
|
56
|
+
import { TiDBSessionStore } from "../stores-sql/tidb-session-store.js";
|
|
57
|
+
import { PgSessionStore } from "../stores-sql/pg-session-storage.js";
|
|
58
|
+
import { SqlSessionStore } from "./session-store-sql.js";
|
|
57
59
|
import { TiDBSharedMemoryStore, PgSharedMemoryStore } from "./shared-memory-store-sql.js";
|
|
58
60
|
import { TiDBAdoptionLogStore, PgAdoptionLogStore } from "./adoption-log-sql.js";
|
|
59
|
-
import {
|
|
61
|
+
import { SqlRetentionStore } from "../stores-sql/retention-store-sql.js";
|
|
62
|
+
import { sqlStoreRetention } from "./retention-declaration.js";
|
|
63
|
+
import { createRetentionDeploymentHooks } from "./retention-deployment.js";
|
|
64
|
+
import { createSqlSessionWriteHooks } from "./session-store-sql.js";
|
|
60
65
|
import { TiDBRetentionLaneStore, PgRetentionLaneStore } from "./retention-lane-store-sql.js";
|
|
61
66
|
import { createSqlPermissionRuleStores } from "./permission-rule-store-sql.js";
|
|
62
67
|
import { FILE_PERMISSION_RULE_DIR, createFilePermissionRuleStores, fileRuleBucketOwners, isFileBucketDamaged } from "./permission-rule-store-file.js";
|
|
63
68
|
import { retireImportedLayerRootAllows } from "./imported-layer-root-retirement.js";
|
|
69
|
+
import { buildDataDirLayout, tightenLocalDataDirModes } from "./local-data-dir-modes-m39.js";
|
|
70
|
+
import { holdEngineHighWater } from "./local-engine-high-water.js";
|
|
71
|
+
import { serviceVersion } from "../service-version.js";
|
|
64
72
|
import { mysqlDriver, pgDriver } from "./sql-driver.js";
|
|
65
73
|
import { storeDegradedReasonFor } from "../store-posture.js";
|
|
66
74
|
import { openWithinWait } from "./store-open-wait.js";
|
|
67
75
|
export function workflowJournalOf(config, backend) {
|
|
68
76
|
return config.selfOrchestrationEnabled && backend ? backend.workflowJournal() : undefined;
|
|
69
77
|
}
|
|
70
|
-
function
|
|
78
|
+
function fileHistoryOptions(config) {
|
|
71
79
|
const s = config.snapshotBlobStore;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
const placement = s
|
|
81
|
+
? {
|
|
82
|
+
blobs: new MinioBlobBackend({
|
|
83
|
+
endpoint: s.endpoint,
|
|
84
|
+
bucket: s.bucket,
|
|
85
|
+
accessKey: s.accessKey,
|
|
86
|
+
secretKey: s.secretKey,
|
|
87
|
+
...(s.region ? { region: s.region } : {}),
|
|
88
|
+
keyPrefix: `${s.keyPrefix ?? ""}${FILE_HISTORY_BLOB_KEY_PREFIX}`,
|
|
89
|
+
...(s.presignTtlSec ? { presignTtlSec: s.presignTtlSec } : {}),
|
|
90
|
+
}),
|
|
91
|
+
}
|
|
92
|
+
: {
|
|
93
|
+
...(config.snapshotBlobSqlMaxBytes !== undefined ? { blobSqlMaxBytes: config.snapshotBlobSqlMaxBytes } : {}),
|
|
94
|
+
log: createLogger(config.logLevel),
|
|
95
|
+
};
|
|
96
|
+
return { ...config.fileHistory, ...placement };
|
|
83
97
|
}
|
|
84
|
-
function
|
|
98
|
+
function legacyBlobIndex(config, dialect, pool) {
|
|
85
99
|
const s = config.snapshotBlobStore;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
const bytes = s
|
|
101
|
+
? new MinioBlobBackend({
|
|
102
|
+
endpoint: s.endpoint,
|
|
103
|
+
bucket: s.bucket,
|
|
104
|
+
accessKey: s.accessKey,
|
|
105
|
+
secretKey: s.secretKey,
|
|
106
|
+
...(s.region ? { region: s.region } : {}),
|
|
107
|
+
...(s.keyPrefix ? { keyPrefix: s.keyPrefix } : {}),
|
|
108
|
+
...(s.presignTtlSec ? { presignTtlSec: s.presignTtlSec } : {}),
|
|
109
|
+
})
|
|
110
|
+
: undefined;
|
|
111
|
+
return new SqlBlobIndex(dialect, pool, { table: "snapshot_blob", ...(bytes !== undefined ? { bytes } : {}), log: createLogger(config.logLevel) });
|
|
97
112
|
}
|
|
98
113
|
async function legacySweepImpl(config, dialect, pool) {
|
|
99
114
|
const sql = "SELECT blob_hash FROM snapshot_blob";
|
|
@@ -108,7 +123,38 @@ async function legacySweepImpl(config, dialect, pool) {
|
|
|
108
123
|
}
|
|
109
124
|
if (orphans.length === 0)
|
|
110
125
|
return 0;
|
|
111
|
-
return
|
|
126
|
+
return legacyBlobIndex(config, dialect, pool).sweep(orphans);
|
|
127
|
+
}
|
|
128
|
+
export function createSqlRetentionCallHooks(db, opts, input) {
|
|
129
|
+
const deployment = createRetentionDeploymentHooks(db.dialect, opts, input);
|
|
130
|
+
return { hooks: { retention: deployment.hooks.retention, session: createSqlSessionWriteHooks(db) }, endedSpaces: deployment.endedSpaces };
|
|
131
|
+
}
|
|
132
|
+
export function createSqlRetentionExecutor(db, opts) {
|
|
133
|
+
const logged = opts.logger !== undefined ? { logger: opts.logger } : {};
|
|
134
|
+
const reads = new SqlRetentionStore(db, logged);
|
|
135
|
+
const forCall = (input) => {
|
|
136
|
+
const hooks = createSqlRetentionCallHooks(db, opts, input);
|
|
137
|
+
return { store: new SqlRetentionStore(db, { ...logged, transactionHooks: hooks.hooks }), hooks, call: { domain: input.domain, cutoffMs: input.cutoffMs } };
|
|
138
|
+
};
|
|
139
|
+
return {
|
|
140
|
+
retention: reads.retention,
|
|
141
|
+
listRetentionDomains: () => reads.listRetentionDomains(),
|
|
142
|
+
previewRetention: (input) => reads.previewRetention(input),
|
|
143
|
+
expireCheckpoints: async (input) => {
|
|
144
|
+
const one = forCall(input);
|
|
145
|
+
return one.store.expireCheckpoints(one.call);
|
|
146
|
+
},
|
|
147
|
+
deleteExpiredSessions: async (input) => {
|
|
148
|
+
const one = forCall(input);
|
|
149
|
+
const receipt = await one.store.deleteExpiredSessions(one.call);
|
|
150
|
+
const endedSpaces = one.hooks.endedSpaces();
|
|
151
|
+
return endedSpaces.length > 0 ? { ...receipt, endedSpaces } : receipt;
|
|
152
|
+
},
|
|
153
|
+
deleteOrphanToolResults: async (input) => {
|
|
154
|
+
const one = forCall(input);
|
|
155
|
+
return one.store.deleteOrphanToolResults(one.call);
|
|
156
|
+
},
|
|
157
|
+
};
|
|
112
158
|
}
|
|
113
159
|
export function assertCloudSnapshotBlobPosture(kind, config) {
|
|
114
160
|
if (kind === "local" || config.snapshotBlobStore || config.snapshotBlobAllowSql)
|
|
@@ -141,12 +187,12 @@ class TiDBBackend {
|
|
|
141
187
|
sendFileLedger() { return new TiDBSendFileLedger(this.pool); }
|
|
142
188
|
userInputLedger() { return new TiDBUserInputLedgerStore(this.pool); }
|
|
143
189
|
sessionPolicy(logger) { return new TiDBSessionPolicyStore(this.pool, logger); }
|
|
144
|
-
fileHistory() { return new TiDBFileHistoryStore(this.pool,
|
|
190
|
+
fileHistory() { return new TiDBFileHistoryStore(this.pool, fileHistoryOptions(this.config)); }
|
|
145
191
|
memoryOptOutGrant() { return new TiDBMemoryOptOutGrantStore(this.pool); }
|
|
146
192
|
sessionCaptureRecords() { return () => (this.captureRecordsInst ??= new TiDBSessionCaptureRecordStore(this.pool)); }
|
|
147
193
|
captureRecordsInst;
|
|
148
194
|
legacySnapshotBlobSweep() { return legacySweepImpl(this.config, "mysql", this.pool); }
|
|
149
|
-
runOneTimeMigrations() { return runSqlOneTimeMigrations("mysql", this.pool, { lanes: deployedExecutionLanes(this.config) }); }
|
|
195
|
+
runOneTimeMigrations() { return runSqlOneTimeMigrations("mysql", this.pool, { lanes: deployedExecutionLanes(this.config), liveRunWindowMs: this.config.runStaleSec * 1000 }); }
|
|
150
196
|
workflowJournal() { return new TiDBWorkflowJournalStore(this.pool); }
|
|
151
197
|
outcomeSink() { return new TiDBOutcomeLedger(this.pool); }
|
|
152
198
|
workflowRun(onWarn) { return new TiDBWorkflowRunStore(this.pool, onWarn); }
|
|
@@ -163,12 +209,12 @@ class TiDBBackend {
|
|
|
163
209
|
imageBake() { return new TiDBImageBake(this.pool); }
|
|
164
210
|
leaderRun() { return new TiDBLeaderRunStore(this.pool); }
|
|
165
211
|
device() { return new TiDBDeviceStore(this.pool); }
|
|
166
|
-
retention(opts) { return
|
|
212
|
+
retention(opts) { return createSqlRetentionExecutor(mysqlDriver(this.pool), opts); }
|
|
167
213
|
retentionLane() { return new TiDBRetentionLaneStore(this.pool); }
|
|
168
214
|
breaker(onWriteFail) { return new TiDBBreakerState(this.pool, onWriteFail); }
|
|
169
215
|
costQuota(limitMicroUsd, windowMs, onDegraded) { return new TiDBCostQuota(this.pool, limitMicroUsd, windowMs, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
|
|
170
216
|
rateLimiter(limit, onDegraded) { return new TiDBRateLimiter(this.pool, limit, undefined, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
|
|
171
|
-
session() { return new TiDBSessionStore(this.pool, { retention: sqlStoreRetention(this.config.retentionSweep) }); }
|
|
217
|
+
session() { return new SqlSessionStore(mysqlDriver(this.pool), (hooks) => new TiDBSessionStore(this.pool, { retention: sqlStoreRetention(this.config.retentionSweep), hooks })); }
|
|
172
218
|
adoptionLog() { return new TiDBAdoptionLogStore(this.pool); }
|
|
173
219
|
mysqlPool() { return this.pool; }
|
|
174
220
|
pgPool() { return undefined; }
|
|
@@ -195,12 +241,12 @@ class PgBackend {
|
|
|
195
241
|
sendFileLedger() { return new PgSendFileLedger(this.pool); }
|
|
196
242
|
userInputLedger() { return new PgUserInputLedgerStore(this.pool); }
|
|
197
243
|
sessionPolicy(logger) { return new PgSessionPolicyStore(this.pool, logger); }
|
|
198
|
-
fileHistory() { return new PgFileHistoryStore(this.pool,
|
|
244
|
+
fileHistory() { return new PgFileHistoryStore(this.pool, fileHistoryOptions(this.config)); }
|
|
199
245
|
memoryOptOutGrant() { return new PgMemoryOptOutGrantStore(this.pool); }
|
|
200
246
|
sessionCaptureRecords() { return () => (this.captureRecordsInst ??= new PgSessionCaptureRecordStore(this.pool)); }
|
|
201
247
|
captureRecordsInst;
|
|
202
248
|
legacySnapshotBlobSweep() { return legacySweepImpl(this.config, "pg", this.pool); }
|
|
203
|
-
runOneTimeMigrations() { return runSqlOneTimeMigrations("pg", this.pool, { lanes: deployedExecutionLanes(this.config) }); }
|
|
249
|
+
runOneTimeMigrations() { return runSqlOneTimeMigrations("pg", this.pool, { lanes: deployedExecutionLanes(this.config), liveRunWindowMs: this.config.runStaleSec * 1000 }); }
|
|
204
250
|
workflowJournal() { return new PgWorkflowJournalStore(this.pool); }
|
|
205
251
|
outcomeSink() { return new PgOutcomeLedger(this.pool); }
|
|
206
252
|
workflowRun(onWarn) { return new PgWorkflowRunStore(this.pool, onWarn); }
|
|
@@ -217,12 +263,12 @@ class PgBackend {
|
|
|
217
263
|
imageBake() { return new PgImageBake(this.pool); }
|
|
218
264
|
leaderRun() { return new PgLeaderRunStore(this.pool); }
|
|
219
265
|
device() { return new PgDeviceStore(this.pool); }
|
|
220
|
-
retention(opts) { return
|
|
266
|
+
retention(opts) { return createSqlRetentionExecutor(pgDriver(this.pool), opts); }
|
|
221
267
|
retentionLane() { return new PgRetentionLaneStore(this.pool); }
|
|
222
268
|
breaker(onWriteFail) { return new PgBreakerState(this.pool, onWriteFail); }
|
|
223
269
|
costQuota(limitMicroUsd, windowMs, onDegraded) { return new PgCostQuota(this.pool, limitMicroUsd, windowMs, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
|
|
224
270
|
rateLimiter(limit, onDegraded) { return new PgRateLimiter(this.pool, limit, undefined, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
|
|
225
|
-
session() { return new PgSessionStore(this.pool, { retention: sqlStoreRetention(this.config.retentionSweep) }); }
|
|
271
|
+
session() { return new SqlSessionStore(pgDriver(this.pool), (hooks) => new PgSessionStore(this.pool, { retention: sqlStoreRetention(this.config.retentionSweep), hooks })); }
|
|
226
272
|
adoptionLog() { return new PgAdoptionLogStore(this.pool); }
|
|
227
273
|
mysqlPool() { return undefined; }
|
|
228
274
|
pgPool() { return this.pool; }
|
|
@@ -250,26 +296,16 @@ class LocalBackend {
|
|
|
250
296
|
discloseWarn;
|
|
251
297
|
parkDecisionLedgerRoot;
|
|
252
298
|
executionLanes;
|
|
253
|
-
|
|
299
|
+
dataDirLayout;
|
|
300
|
+
constructor(fileBackend, config, discloseWarn, onWarn, onError) {
|
|
254
301
|
this.executionLanes = deployedExecutionLanes(config);
|
|
255
302
|
this.onWarn = onWarn;
|
|
256
|
-
this.discloseWarn =
|
|
303
|
+
this.discloseWarn = discloseWarn;
|
|
257
304
|
this.onError = onError;
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
root,
|
|
261
|
-
...(config.fileHistory !== undefined ? { fileHistory: config.fileHistory } : {}),
|
|
262
|
-
onCorruptRead: createDurableAbsenceSeat((msg, fields) => this.discloseWarn(msg, fields), root, "file-history = a rewind boundary or scope read as missing"),
|
|
263
|
-
}), config.storeLockWaitMs, (fields) => this.onWarn?.("store_dir_lock_wait", { ...fields }));
|
|
264
|
-
}
|
|
265
|
-
catch (e) {
|
|
266
|
-
if (e instanceof AdoptionError)
|
|
267
|
-
throw e;
|
|
268
|
-
const tail = buildStoreOpenRefusalTail(e, "http");
|
|
269
|
-
throw new Error(`DB_BACKEND=local cannot open data dir ${root}: ${e instanceof Error ? e.message : String(e)}` +
|
|
270
|
-
(tail === undefined ? "" : ` ${tail}`));
|
|
271
|
-
}
|
|
305
|
+
this.fileBackend = fileBackend;
|
|
306
|
+
const root = localBackendRootOf(config);
|
|
272
307
|
const corruptReadWarn = (msg, fields) => this.discloseWarn(msg, fields);
|
|
308
|
+
this.dataDirLayout = buildDataDirLayout({ configuredRoot: root, physicalRoot: this.fileBackend.root, memoryEngineRoot: memoryEngineRootFor(config, root) });
|
|
273
309
|
this.runStore = new FileRunStore(this.fileBackend.root, {
|
|
274
310
|
error: (msg, fields) => void (this.onError ?? this.onWarn)?.(msg, fields),
|
|
275
311
|
strictHydrate: config.runStoreStrictHydrate,
|
|
@@ -297,22 +333,32 @@ class LocalBackend {
|
|
|
297
333
|
: (plane) => fileSessionCaptureRecordStore(plane?.controlDir ?? ownControlDir);
|
|
298
334
|
}
|
|
299
335
|
async ensureSchema() {
|
|
336
|
+
this.executionLaneWordsRenamed += await this.sessionStore.renameRetiredExecutionLaneWordM40();
|
|
300
337
|
await this.sessionStore.assertStrictSidecarsReadable();
|
|
301
338
|
await this.sessionStore.settleArchiveSnapshots();
|
|
302
339
|
}
|
|
340
|
+
executionLaneWordsRenamed = 0;
|
|
303
341
|
async runOneTimeMigrations() {
|
|
342
|
+
tightenLocalDataDirModes(this.dataDirLayout, {
|
|
343
|
+
tightened: (msg, meta) => this.onWarn?.(msg, meta),
|
|
344
|
+
refused: (msg, meta) => this.discloseWarn(msg, meta),
|
|
345
|
+
});
|
|
304
346
|
const archives = await this.sessionStore.migrateLocalArchives();
|
|
305
347
|
const placements = await backfillLocalExecutionPlacements(this.runStore.sessionIdsWithRuns(), this.sessionStore.executionPlacementBackfill, { lanes: this.executionLanes });
|
|
306
|
-
const importedLayerRoot = { importedLayerRootAllowsRetired: [], importedLayerRootBucketsSkipped: [] };
|
|
348
|
+
const importedLayerRoot = { importedLayerRootAllowsRetired: [], importedLayerRootBucketsSkipped: [], importedLayerRootBucketsUnnamed: 0 };
|
|
307
349
|
if (existsSync(join(this.fileBackend.root, FILE_PERMISSION_RULE_DIR))) {
|
|
308
350
|
const rules = this.permissionRule();
|
|
309
351
|
await retireImportedLayerRootAllows({ candidateOwners: () => fileRuleBucketOwners(rules), durable: rules.durable, isWholeBucketRefusal: isFileBucketDamaged, isVanishedBucket: () => false }, importedLayerRoot);
|
|
310
352
|
}
|
|
353
|
+
const executionLaneWordsRenamed = this.executionLaneWordsRenamed + this.approvalAskStore.renameRetiredExecutionLaneWordM40();
|
|
354
|
+
this.executionLaneWordsRenamed = 0;
|
|
355
|
+
const askExecutionLanesBackfilled = backfillLocalAskExecutionLanes(this.approvalAskStore, { lanes: this.executionLanes });
|
|
311
356
|
return {
|
|
312
357
|
...NO_SQL_MIGRATIONS,
|
|
313
358
|
executionPlacementsBackfilled: placements.backfilled,
|
|
314
359
|
executionPlacementSessionsUnreadable: placements.unreadable,
|
|
315
|
-
askExecutionLanesBackfilled
|
|
360
|
+
askExecutionLanesBackfilled,
|
|
361
|
+
executionLaneWordsRenamed,
|
|
316
362
|
askJournalRecordsUpgraded: this.approvalAskStore.upgradeJournalEnvelope(),
|
|
317
363
|
localArchiveRowFactsBackfilled: archives.rowFactsBackfilled,
|
|
318
364
|
localArchivesAnonymized: archives.anonymized,
|
|
@@ -396,9 +442,75 @@ class LocalBackend {
|
|
|
396
442
|
export function counterStoreLabel(store, kind) {
|
|
397
443
|
return store ? `shared(${kind ?? "unknown"})` : "in-process";
|
|
398
444
|
}
|
|
445
|
+
function openLocalBackend(config, onWarn, onError) {
|
|
446
|
+
const root = localBackendRootOf(config);
|
|
447
|
+
const discloseWarn = onWarn ?? ((msg, meta) => console.warn(msg, meta));
|
|
448
|
+
let fileBackend;
|
|
449
|
+
try {
|
|
450
|
+
fileBackend = acquireLocalBackendWithWait(() => new FileStorageBackend({
|
|
451
|
+
root,
|
|
452
|
+
...(config.fileHistory !== undefined ? { fileHistory: config.fileHistory } : {}),
|
|
453
|
+
onCorruptRead: createDurableAbsenceSeat(discloseWarn, root, "file-history = a rewind boundary or scope read as missing"),
|
|
454
|
+
}), config.storeLockWaitMs, (fields) => onWarn?.("store_dir_lock_wait", { ...fields }));
|
|
455
|
+
}
|
|
456
|
+
catch (e) {
|
|
457
|
+
if (e instanceof AdoptionError)
|
|
458
|
+
throw e;
|
|
459
|
+
const tail = buildStoreOpenRefusalTail(e, "http");
|
|
460
|
+
throw new Error(`DB_BACKEND=local cannot open data dir ${root}: ${e instanceof Error ? e.message : String(e)}` +
|
|
461
|
+
(tail === undefined ? "" : ` ${tail}`));
|
|
462
|
+
}
|
|
463
|
+
try {
|
|
464
|
+
holdEngineHighWater(fileBackend.root, serviceVersion());
|
|
465
|
+
}
|
|
466
|
+
catch (refusal) {
|
|
467
|
+
return new RefusedLocalBackend(fileBackend, refusal instanceof Error ? refusal : new Error(String(refusal)));
|
|
468
|
+
}
|
|
469
|
+
return new LocalBackend(fileBackend, config, discloseWarn, onWarn, onError);
|
|
470
|
+
}
|
|
471
|
+
class RefusedLocalBackend {
|
|
472
|
+
fileBackend;
|
|
473
|
+
refusal;
|
|
474
|
+
kind = "local";
|
|
475
|
+
constructor(fileBackend, refusal) {
|
|
476
|
+
this.fileBackend = fileBackend;
|
|
477
|
+
this.refusal = refusal;
|
|
478
|
+
}
|
|
479
|
+
refused() {
|
|
480
|
+
throw this.refusal;
|
|
481
|
+
}
|
|
482
|
+
async ensureSchema() {
|
|
483
|
+
return this.refused();
|
|
484
|
+
}
|
|
485
|
+
async runOneTimeMigrations() {
|
|
486
|
+
return this.refused();
|
|
487
|
+
}
|
|
488
|
+
async close() {
|
|
489
|
+
await this.fileBackend.dispose();
|
|
490
|
+
}
|
|
491
|
+
run() { return this.refused(); }
|
|
492
|
+
resumeAnchor() { return this.refused(); }
|
|
493
|
+
approvalExemption() { return this.refused(); }
|
|
494
|
+
approvalNonce() { return this.refused(); }
|
|
495
|
+
orgDeliveryQuota() { return this.refused(); }
|
|
496
|
+
approvalAsk() { return this.refused(); }
|
|
497
|
+
permissionRule() { return this.refused(); }
|
|
498
|
+
sendFileLedger() { return this.refused(); }
|
|
499
|
+
userInputLedger() { return this.refused(); }
|
|
500
|
+
sessionPolicy() { return this.refused(); }
|
|
501
|
+
fileHistory() { return this.refused(); }
|
|
502
|
+
memoryOptOutGrant() { return this.refused(); }
|
|
503
|
+
sessionCaptureRecords() { return this.refused(); }
|
|
504
|
+
workflowJournal() { return this.refused(); }
|
|
505
|
+
outcomeSink() { return this.refused(); }
|
|
506
|
+
checkpointReadView() { return this.refused(); }
|
|
507
|
+
session() { return this.refused(); }
|
|
508
|
+
mysqlPool() { return undefined; }
|
|
509
|
+
pgPool() { return undefined; }
|
|
510
|
+
}
|
|
399
511
|
export function createStoreBackend(config, onWarn, onError) {
|
|
400
512
|
if (config.dbBackend === "local")
|
|
401
|
-
return
|
|
513
|
+
return openLocalBackend(config, onWarn, onError);
|
|
402
514
|
if (config.dbBackend === "pg") {
|
|
403
515
|
if (!config.pg)
|
|
404
516
|
return undefined;
|
|
@@ -419,9 +531,21 @@ function withRetiredSchemaProbe(inner, target, executionPlacementSwitch) {
|
|
|
419
531
|
};
|
|
420
532
|
return guarded;
|
|
421
533
|
}
|
|
534
|
+
function localBackendRootOf(config) {
|
|
535
|
+
return config.localDataRoot ?? join(homedir(), ".ai-agent");
|
|
536
|
+
}
|
|
537
|
+
function localDataRootHoldsData(root) {
|
|
538
|
+
try {
|
|
539
|
+
return readdirSync(root).length > 0;
|
|
540
|
+
}
|
|
541
|
+
catch (e) {
|
|
542
|
+
const code = e.code;
|
|
543
|
+
return code !== "ENOENT" && code !== "ENOTDIR";
|
|
544
|
+
}
|
|
545
|
+
}
|
|
422
546
|
export async function openStoreBackendWithFallback(config, logger) {
|
|
423
547
|
const sqlEngine = config.dbBackend === "mysql" || config.dbBackend === "pg" ? config.dbBackend : undefined;
|
|
424
|
-
const mayFallback = config.dbBackend === "local" && !config.dbBackendExplicit;
|
|
548
|
+
const mayFallback = config.dbBackend === "local" && !config.dbBackendExplicit && !localDataRootHoldsData(localBackendRootOf(config));
|
|
425
549
|
let backend;
|
|
426
550
|
let inFlight;
|
|
427
551
|
try {
|
|
@@ -448,8 +572,6 @@ export async function openStoreBackendWithFallback(config, logger) {
|
|
|
448
572
|
}
|
|
449
573
|
catch (err) {
|
|
450
574
|
void inFlight?.close().catch(() => undefined);
|
|
451
|
-
if (err instanceof AdoptionError)
|
|
452
|
-
throw err;
|
|
453
575
|
if (err instanceof StoreBootRefusalError)
|
|
454
576
|
throw err;
|
|
455
577
|
if (!mayFallback) {
|