@sema-agent/server 7.148.0 → 7.150.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 +551 -9
- package/README.md +17 -2
- package/README.zh-CN.md +5 -1
- package/USAGE.md +126 -68
- package/dist/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +33 -33
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/approval-leg-origin.d.ts +33 -0
- package/dist/approval-leg-origin.js +4 -0
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +2 -2
- package/dist/auth-bridge.d.ts +9 -1
- package/dist/auth-bridge.js +4 -4
- package/dist/auth-keys.d.ts +10 -1
- package/dist/auth-keys.js +8 -0
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
- package/dist/boot/deferred-sandbox-path-env.js +1 -2
- package/dist/boot/execution-env.js +10 -11
- package/dist/boot/execution-lane.d.ts +6 -4
- package/dist/boot/execution-lane.js +3 -1
- package/dist/boot/org-delivery.d.ts +3 -2
- package/dist/boot/parked-revive-gate.d.ts +5 -5
- package/dist/boot/parked-revive-gate.js +2 -3
- package/dist/boot/resolve-spec.d.ts +4 -5
- package/dist/boot/resolve-spec.js +66 -28
- package/dist/boot/retention-lane.d.ts +1 -1
- package/dist/boot/runner-deps.js +3 -1
- package/dist/boot/session-faces.js +21 -21
- package/dist/boot/stage-01-config.d.ts +1 -0
- package/dist/boot/stage-01-config.js +4 -3
- package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
- package/dist/boot/stage-02-web-admin-pull.js +10 -2
- package/dist/boot/stage-03-store-backend.d.ts +1 -0
- package/dist/boot/stage-03-store-backend.js +4 -4
- package/dist/boot/stage-04-stores.d.ts +1 -0
- package/dist/boot/stage-05-execution-env.d.ts +1 -0
- package/dist/boot/stage-06-runners.d.ts +2 -1
- package/dist/boot/stage-06-runners.js +1 -2
- package/dist/boot/stage-07-capability-layer.d.ts +2 -1
- package/dist/boot/stage-07-capability-layer.js +1 -1
- package/dist/boot/stage-08-reapers.d.ts +2 -1
- package/dist/boot/stage-09-leader.d.ts +2 -1
- package/dist/boot/stage-10-http-server.d.ts +35 -2
- package/dist/boot/stage-10-http-server.js +9 -4
- package/dist/boot/stores.d.ts +3 -0
- package/dist/boot/stores.js +22 -19
- package/dist/boot/web-admin.d.ts +1 -1
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/capability-facts.d.ts +70 -60
- package/dist/capability-facts.js +45 -49
- package/dist/card-settle-stored-scope.d.ts +56 -0
- package/dist/card-settle-stored-scope.js +27 -0
- package/dist/card-void.d.ts +7 -12
- package/dist/card-void.js +2 -7
- package/dist/config-catalog.d.ts +12 -0
- package/dist/config-catalog.js +37 -33
- package/dist/config-invariants.d.ts +5 -4
- package/dist/config-invariants.js +4 -4
- package/dist/config-types.d.ts +49 -16
- package/dist/config.d.ts +6 -5
- package/dist/config.js +35 -24
- package/dist/context-window-notice.d.ts +31 -0
- package/dist/context-window-notice.js +28 -0
- package/dist/deployment-governance.d.ts +7 -28
- package/dist/deployment-governance.js +1 -14
- package/dist/deployment-shape.d.ts +20 -11
- package/dist/deployment-shape.js +1 -0
- package/dist/device-ws-hub.d.ts +1 -0
- package/dist/device-ws-hub.js +64 -28
- package/dist/device-ws-protocol.d.ts +20 -6
- package/dist/device-ws-protocol.js +9 -2
- package/dist/engine-identity.d.ts +7 -1
- package/dist/engine-identity.js +5 -0
- package/dist/env-name-allowlist-knobs.d.ts +6 -5
- package/dist/env-name-allowlist-knobs.js +5 -0
- package/dist/execution-lane-caps.d.ts +20 -5
- package/dist/execution-lane-caps.js +18 -4
- package/dist/field-conflict.d.ts +2 -2
- package/dist/fleet/engine-signal.d.ts +14 -1
- package/dist/fleet/engine-signal.js +5 -1
- package/dist/fleet/fleet-reconciler.d.ts +1 -1
- package/dist/fleet/serving-lease.d.ts +18 -3
- package/dist/fleet/serving-lease.js +81 -35
- package/dist/fleet-client.d.ts +13 -11
- package/dist/fleet-client.js +53 -33
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +1 -3
- package/dist/hitl-delivery.js +1 -1
- package/dist/hooks/command-spawn.d.ts +7 -2
- package/dist/hooks/command-spawn.js +13 -6
- package/dist/hooks/hook-runner.d.ts +5 -0
- package/dist/hooks/hook-runner.js +11 -7
- package/dist/http/active-run-conflict.d.ts +3 -7
- package/dist/http/active-run-conflict.js +2 -2
- package/dist/http/admission.js +5 -5
- package/dist/http/approval-sweeps.js +5 -3
- package/dist/http/caller-trust.d.ts +2 -2
- package/dist/http/caller-trust.js +3 -3
- package/dist/http/checkpoint-ctx.d.ts +18 -63
- package/dist/http/checkpoint-ctx.js +1 -24
- package/dist/http/claim-heartbeat.d.ts +6 -6
- package/dist/http/claim-heartbeat.js +6 -6
- package/dist/http/claimed-run.d.ts +16 -9
- package/dist/http/claimed-run.js +8 -0
- package/dist/http/dispatch.js +7 -5
- package/dist/http/durable-run-leg.d.ts +8 -1
- package/dist/http/durable-run-leg.js +34 -15
- package/dist/http/execution-context.d.ts +115 -14
- package/dist/http/execution-context.js +130 -40
- package/dist/http/owner-access.d.ts +246 -21
- package/dist/http/owner-access.js +186 -8
- package/dist/http/principal-gate.d.ts +18 -11
- package/dist/http/principal-gate.js +3 -1
- package/dist/http/readiness.d.ts +4 -2
- package/dist/http/resume-ctx-read.d.ts +14 -3
- package/dist/http/resume-ctx-read.js +24 -3
- package/dist/http/resume-legs.d.ts +35 -3
- package/dist/http/resume-legs.js +262 -106
- package/dist/http/route-ctx.d.ts +29 -11
- package/dist/http/routes/a2a-serve.js +17 -14
- package/dist/http/routes/approvals-assistant.d.ts +3 -2
- package/dist/http/routes/approvals-assistant.js +11 -11
- package/dist/http/routes/capabilities.js +5 -4
- package/dist/http/routes/config-catalog.d.ts +1 -1
- package/dist/http/routes/diagnostics.d.ts +3 -1
- package/dist/http/routes/diagnostics.js +30 -5
- package/dist/http/routes/mcp-reconnect.js +2 -2
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/notify-wake.js +2 -3
- package/dist/http/routes/principal-inbox.d.ts +3 -1
- package/dist/http/routes/principal-inbox.js +3 -2
- package/dist/http/routes/projects.d.ts +1 -0
- package/dist/http/routes/projects.js +5 -3
- package/dist/http/routes/retention-ops.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +1 -1
- package/dist/http/routes/runs.js +33 -37
- package/dist/http/routes/session-memory-sync.js +4 -5
- package/dist/http/routes/session-sync.d.ts +24 -5
- package/dist/http/routes/session-sync.js +45 -37
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions.d.ts +1 -1
- package/dist/http/routes/sessions.js +18 -44
- package/dist/http/routes/tasks.js +136 -101
- package/dist/http/routes/trace-usage.js +14 -14
- package/dist/http/routes/workflows.d.ts +1 -0
- package/dist/http/routes/workflows.js +20 -38
- package/dist/http/server.d.ts +12 -9
- package/dist/http/server.js +35 -6
- package/dist/http/stored-body-replay.d.ts +3 -24
- package/dist/http/stored-body-replay.js +2 -12
- package/dist/http/submit-ctx.d.ts +2 -2
- package/dist/http/submit-ctx.js +5 -5
- package/dist/http/submit-replay.d.ts +15 -2
- package/dist/http/submit-replay.js +10 -4
- package/dist/http/wire-types.d.ts +6 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/leader/endpoint.js +9 -8
- package/dist/leg-facts.d.ts +13 -2
- package/dist/leg-facts.js +2 -0
- package/dist/local-store-declaration.d.ts +54 -0
- package/dist/local-store-declaration.js +59 -0
- package/dist/mcp-assertion-header.d.ts +1 -1
- package/dist/mcp-assertion-header.js +1 -1
- package/dist/mcp-authorization-face.d.ts +18 -14
- package/dist/mcp-authorization-face.js +3 -2
- package/dist/memory-project-layer.js +1 -1
- package/dist/memory-scope.d.ts +4 -4
- package/dist/memory-scope.js +4 -4
- package/dist/memory-store-refusal.d.ts +1 -1
- package/dist/memory-sync-client.js +2 -2
- package/dist/model-context-window.d.ts +50 -11
- package/dist/model-context-window.js +20 -1
- package/dist/model-entry-refusal.d.ts +5 -4
- package/dist/model-entry-refusal.js +17 -3
- package/dist/model-reach-scope.d.ts +2 -1
- package/dist/observability/corrupt-read-seat.d.ts +1 -1
- package/dist/observability/fail-open.d.ts +19 -7
- package/dist/observability/fail-open.js +19 -7
- package/dist/observability/logger.d.ts +7 -0
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -1
- package/dist/observability/run-terminal.d.ts +1 -1
- package/dist/observability/run-terminal.js +1 -0
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/secret-env-scrub.js +1 -1
- package/dist/org-delivery-gate.d.ts +31 -6
- package/dist/org-delivery-gate.js +7 -4
- package/dist/owner-faces.d.ts +30 -5
- package/dist/owner-faces.js +2 -0
- package/dist/park-row-commit.d.ts +67 -0
- package/dist/park-row-commit.js +76 -0
- package/dist/parked-decide.d.ts +9 -7
- package/dist/parked-decide.js +25 -6
- package/dist/peer-directory.d.ts +1 -1
- package/dist/peer-seat.d.ts +1 -1
- package/dist/peer-seat.js +52 -59
- package/dist/plugins/adoption-log-sql.d.ts +3 -3
- package/dist/plugins/adoption-log-sql.js +19 -19
- package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
- package/dist/plugins/approval-ask-store-sql.js +3 -5
- package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
- package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
- package/dist/plugins/approval-exemption-skill-m46.d.ts +0 -6
- package/dist/plugins/approval-exemption-skill-m46.js +6 -10
- package/dist/plugins/approval-exemption-store.d.ts +26 -1
- package/dist/plugins/approval-exemption-store.js +28 -19
- package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -3
- package/dist/plugins/ensure-schema-lock-policy.js +75 -9
- package/dist/plugins/exec-path-law.d.ts +34 -0
- package/dist/plugins/exec-path-law.js +13 -0
- package/dist/plugins/file-run-store.d.ts +22 -9
- package/dist/plugins/file-run-store.js +51 -23
- package/dist/plugins/local-checkpoint-store.d.ts +8 -1
- package/dist/plugins/local-checkpoint-store.js +5 -1
- package/dist/plugins/local-data-root-admission.d.ts +52 -0
- package/dist/plugins/local-data-root-admission.js +100 -0
- package/dist/plugins/local-engine-high-water.d.ts +28 -7
- package/dist/plugins/local-engine-high-water.js +27 -22
- package/dist/plugins/local-session-store.d.ts +134 -49
- package/dist/plugins/local-session-store.js +149 -108
- package/dist/plugins/memory-run-store.d.ts +14 -9
- package/dist/plugins/memory-run-store.js +48 -22
- package/dist/plugins/one-time-migration-marker.d.ts +19 -3
- package/dist/plugins/one-time-migration-marker.js +7 -1
- package/dist/plugins/one-time-migrations.d.ts +110 -59
- package/dist/plugins/one-time-migrations.js +224 -136
- package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
- package/dist/plugins/org-delivery-quota-store.js +29 -14
- package/dist/plugins/permission-rule-store-sql.d.ts +1 -1
- package/dist/plugins/permission-rule-store-sql.js +5 -9
- package/dist/plugins/pg-pool.d.ts +1 -1
- package/dist/plugins/pg-pool.js +14 -12
- package/dist/plugins/posix-shell-fs.js +4 -2
- package/dist/plugins/remote-env-adb.js +3 -2
- package/dist/plugins/remote-env-device.d.ts +3 -2
- package/dist/plugins/remote-env-device.js +8 -6
- package/dist/plugins/remote-env-e2b.d.ts +4 -8
- package/dist/plugins/remote-env-e2b.js +21 -15
- package/dist/plugins/remote-env-host.d.ts +51 -10
- package/dist/plugins/remote-env-host.js +97 -31
- package/dist/plugins/remote-env-k8s.js +7 -4
- package/dist/plugins/remote-env-local-docker.d.ts +6 -3
- package/dist/plugins/remote-env-local-docker.js +11 -25
- package/dist/plugins/remote-env-ssh.js +4 -3
- package/dist/plugins/remote-shell.d.ts +3 -1
- package/dist/plugins/remote-shell.js +3 -3
- package/dist/plugins/replica-registration.d.ts +35 -0
- package/dist/plugins/replica-registration.js +48 -0
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/run-store-sql.d.ts +27 -8
- package/dist/plugins/run-store-sql.js +46 -18
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +8 -12
- package/dist/plugins/scenario-prefix-switch-m42.js +9 -6
- package/dist/plugins/schema-consistency.d.ts +91 -5
- package/dist/plugins/schema-consistency.js +189 -7
- package/dist/plugins/schema-drift-sentence.d.ts +6 -5
- package/dist/plugins/schema-drift-sentence.js +13 -5
- package/dist/plugins/serving-requirement.d.ts +49 -0
- package/dist/plugins/serving-requirement.js +53 -0
- package/dist/plugins/session-placement.d.ts +5 -4
- package/dist/plugins/shell-sentinel-owner-m48.d.ts +22 -0
- package/dist/plugins/shell-sentinel-owner-m48.js +6 -0
- package/dist/plugins/stop-then-start-sentence.d.ts +55 -0
- package/dist/plugins/stop-then-start-sentence.js +51 -0
- package/dist/plugins/store-backend.d.ts +23 -9
- package/dist/plugins/store-backend.js +58 -24
- package/dist/plugins/store-contracts.d.ts +45 -5
- package/dist/plugins/store-contracts.js +19 -0
- package/dist/plugins/tidb-pool.d.ts +11 -6
- package/dist/plugins/tidb-pool.js +22 -12
- package/dist/plugins/workspace-custody.d.ts +44 -0
- package/dist/plugins/workspace-custody.js +47 -0
- package/dist/process-instance.d.ts +3 -0
- package/dist/process-instance.js +7 -0
- package/dist/project-context.d.ts +66 -0
- package/dist/project-context.js +70 -0
- package/dist/project-identity.d.ts +8 -7
- package/dist/project-identity.js +40 -17
- package/dist/project-layer-key.d.ts +13 -2
- package/dist/project-layer-key.js +9 -1
- package/dist/question.d.ts +9 -21
- package/dist/question.js +28 -19
- package/dist/read-deny-floor-notice.d.ts +36 -0
- package/dist/read-deny-floor-notice.js +40 -0
- package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
- package/dist/request-declaration-disposition.js +39 -0
- package/dist/run-cancel-card.d.ts +28 -0
- package/dist/run-cancel-card.js +20 -0
- package/dist/run-cancel-context.d.ts +10 -0
- package/dist/run-cancel-context.js +1 -0
- package/dist/run-local.js +28 -13
- package/dist/runs.d.ts +31 -7
- package/dist/runs.js +34 -16
- package/dist/security.d.ts +3 -3
- package/dist/server-secret-env.d.ts +34 -20
- package/dist/server-secret-env.js +61 -18
- package/dist/session-agent.d.ts +4 -12
- package/dist/session-agent.js +0 -6
- package/dist/session-children-retire.d.ts +6 -3
- package/dist/session-children-retire.js +2 -5
- package/dist/session-incarnation.d.ts +18 -4
- package/dist/session-incarnation.js +4 -1
- package/dist/session-notify-door.d.ts +4 -4
- package/dist/session-notify-door.js +5 -6
- package/dist/session-rules-seat.d.ts +4 -3
- package/dist/session-rules-seat.js +3 -11
- package/dist/session-sync.js +3 -3
- package/dist/session-workspace.d.ts +3 -3
- package/dist/store-admission.d.ts +33 -0
- package/dist/store-admission.js +49 -0
- package/dist/store-posture.d.ts +5 -0
- package/dist/store-posture.js +18 -1
- package/dist/stores-sql/checkpoint-store-sql.d.ts +22 -3
- package/dist/stores-sql/checkpoint-store-sql.js +109 -23
- package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
- package/dist/stores-sql/file-history-store-sql.js +3 -5
- package/dist/stores-sql/retention-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.js +4 -6
- package/dist/task-a2a.d.ts +3 -8
- package/dist/task-a2a.js +25 -27
- package/dist/task-cwd.d.ts +27 -10
- package/dist/task-cwd.js +3 -0
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-mcp.js +1 -1
- package/dist/task-settings.d.ts +13 -0
- package/dist/task-settings.js +14 -7
- package/dist/terminal.d.ts +2 -0
- package/dist/terminal.js +21 -6
- package/dist/tool-approval.d.ts +50 -41
- package/dist/tool-approval.js +96 -73
- package/dist/trace/engine-notice-wire.d.ts +38 -21
- package/dist/trace/engine-notice-wire.js +25 -4
- package/dist/trace/ledger-sink.d.ts +3 -1
- package/dist/trace/project.d.ts +8 -5
- package/dist/trace/project.js +11 -9
- package/dist/trace/projection-table.d.ts +33 -2
- package/dist/trace/redact.d.ts +12 -0
- package/dist/trace/redact.js +5 -1
- package/dist/trace/self-minted-wire.d.ts +268 -56
- package/dist/trace/self-minted-wire.js +110 -40
- package/dist/trace/tool-card.d.ts +3 -0
- package/dist/trace/tool-card.js +24 -0
- package/dist/trace/tool-output-media.d.ts +2 -1
- package/dist/unattended-permission-mode.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.js +22 -9
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -29
- package/docs/error-text-lexicon.json +317 -0
- package/package.json +4 -2
- package/scripts/embed-minimal.mjs +183 -0
- package/wire-changes/server@7.149.0.json +372 -0
- package/wire-changes/server@7.150.0.json +335 -0
- package/dist/plain-string-record.js +0 -70
|
@@ -9,6 +9,7 @@ import { type RunStallWiring } from "./store-contracts.js";
|
|
|
9
9
|
import { type StoreOpenLane } from "./store-open-refusal.js";
|
|
10
10
|
import { type OneTimeMigrationReport, type SqlOneTimeMigrationInput } from "./one-time-migrations.js";
|
|
11
11
|
import { LocalSessionStore } from "./local-session-store.js";
|
|
12
|
+
import { type LocalStoreDeclaration } from "../local-store-declaration.js";
|
|
12
13
|
import type { LocalSessionRows } from "./local-session-window.js";
|
|
13
14
|
import type { SessionHeadReader } from "./caching-session-store.js";
|
|
14
15
|
import { LocalCheckpointStore } from "./local-checkpoint-store.js";
|
|
@@ -41,9 +42,10 @@ import { type SqlTransactionHooks } from "../stores-sql/retention-store-sql.js";
|
|
|
41
42
|
import type { SessionEraser } from "../session-erase.js";
|
|
42
43
|
import { type RetentionDestructiveInput, type RetentionExecutor, type RetentionExecutorOptions } from "./retention-deployment.js";
|
|
43
44
|
import { type RetentionLaneStore } from "./retention-lane-store-sql.js";
|
|
45
|
+
import { type LocalDataRootAdmission } from "./local-data-root-admission.js";
|
|
44
46
|
import type { PermissionRuleStoreBundle } from "../rules-consent.js";
|
|
45
47
|
import { type SqlDriver } from "./sql-driver.js";
|
|
46
|
-
import { type StoreDegradedReason } from "../store-posture.js";
|
|
48
|
+
import { type StoreDegradedReason, type StoreDurability as MediumDurability } from "../store-posture.js";
|
|
47
49
|
/** boot 期的一条日志座(级别由**座位**决定,不由参数携带):`createStoreBackend` 的 `onWarn` / `onError`
|
|
48
50
|
* 两参与 `LocalBackend` 的同名字段共用此形。装配层把它们分别接到 `logger.warn` / `logger.error` 上。 */
|
|
49
51
|
export type BootLogSink = (msg: string, meta?: Record<string, unknown>) => void;
|
|
@@ -54,6 +56,10 @@ export type BootLogSink = (msg: string, meta?: Record<string, unknown>) => void;
|
|
|
54
56
|
export interface StoreBackendObservers {
|
|
55
57
|
readonly runStallVerdicts?: (landed: number) => void;
|
|
56
58
|
}
|
|
59
|
+
/** 开店时递进来的起服事实(只 local 腿读):数据根介质的判定(起服第 2 段的取证;缺席 = 这条入口没有起服证据 ⇒ 按 `unknown` 读 —— 判不出的介质不放宽 local 店的声明)。 */
|
|
60
|
+
export interface StoreOpenFacts {
|
|
61
|
+
readonly dataRootMedium?: MediumDurability;
|
|
62
|
+
}
|
|
57
63
|
/** run 店落死亡判决的两样:窗 = 后端持有的配置对象的 `runStaleSec`(热发布原地改写 ⇒ getter 读到热值;判活窗只有这一个来源)+ 计数座。 */
|
|
58
64
|
export declare function createRunStallWiring(config: Pick<ServiceConfig, "runStaleSec">, observers: StoreBackendObservers | undefined): RunStallWiring;
|
|
59
65
|
export type RunStore = TiDBRunStore | PgRunStore | FileRunStore;
|
|
@@ -426,6 +432,8 @@ export interface StoreBackend {
|
|
|
426
432
|
* 拒绝句不带盘上位置)的同时,路径进本 backend 的 `file_store_corrupt_read` 披露座(逐命中 warn)。修前 `boot/stores.ts` 在同一数据根上自己
|
|
427
433
|
* `new FileUsageWindowStore(root)` 第二只实例、不接座 ⇒ 坏值只拒不披露,运维找不到是哪只文件。SQL 后端省略(它们有自己的 usage-window 双方言店)。 */
|
|
428
434
|
fileUsageWindowStore?(): UsageWindowStore;
|
|
435
|
+
/** **local 后端专有**:构造时交给两半店(会话店顶层、检查点店)的那一份声明(唯一读者 `localStoreDeclarationOf`)—— 装配值从这里读回,不重算。SQL 后端省略。 */
|
|
436
|
+
localStoreDeclaration?(): LocalStoreDeclaration;
|
|
429
437
|
}
|
|
430
438
|
/**
|
|
431
439
|
* 托管留存执行器的**组合**:引擎座表那一半(`SqlRetentionStore`,事务属主)+ 部署那一半(hold / 审计 / 认领判 / 十三张部署表,
|
|
@@ -459,7 +467,7 @@ export declare function createSqlSessionEraser(db: SqlDriver, opts: RetentionExe
|
|
|
459
467
|
* ({@link SQL_BLOB_POSTURE_FACTS})。云形缺 MinIO ⇒ fail-loud(启动了才是假安全);`SNAPSHOT_BLOB_ALLOW_SQL_BYTES=true` =
|
|
460
468
|
* 显式接受 SQL 店 + per-blob 帽(单机/测试台形;pg 上帽只来自 `SNAPSHOT_BLOB_SQL_MAX_BYTES`)。local 后端不经此门(file 店,无 SQL 包墙)。 */
|
|
461
469
|
export declare function assertCloudSnapshotBlobPosture(kind: "mysql" | "pg" | "local", config: Pick<ServiceConfig, "snapshotBlobStore" | "snapshotBlobAllowSql">): void;
|
|
462
|
-
/** SQL 一次性迁移段的输入(两只 SQL 后端同一份;各条目那一半的来源见 `SqlOneTimeMigrationInput`):M32 的车道表 ·
|
|
470
|
+
/** SQL 一次性迁移段的输入(两只 SQL 后端同一份;各条目那一半的来源见 `SqlOneTimeMigrationInput`):M32 的车道表 · M52 的判活窗(停-迁-起证据的心跳一半)= 收割器的同一个窗 · M48 的部署形读数(表里那一行)。 */
|
|
463
471
|
export declare function buildSqlOneTimeMigrationInput(config: ServiceConfig): SqlOneTimeMigrationInput;
|
|
464
472
|
/**
|
|
465
473
|
* LOCAL backend (clay 2026-06-25 seamless local↔cloud; P0.5 variant-2 + variant-1 file-backed 2026-06-26): a DB-less StoreBackend
|
|
@@ -517,25 +525,31 @@ export interface LocalStoreBackend extends StoreBackend {
|
|
|
517
525
|
toolResult(): ToolResultStoreFull;
|
|
518
526
|
/** local 后端恒有(引擎 File 后端的用量窗账本;接口上可选的那一口在这里必在)。 */
|
|
519
527
|
fileUsageWindowStore(): UsageWindowStore;
|
|
528
|
+
/** local 后端恒有(构造时交给两半店的声明;接口上可选的那一口在这里必在)。 */
|
|
529
|
+
localStoreDeclaration(): LocalStoreDeclaration;
|
|
520
530
|
}
|
|
521
531
|
/** 引擎 File 后端上会话店之外、本仓没有自己一份口的店(run-local 的 Runner 接它们;工具结果 / 用量窗 / 会话规则走既有的 `toolResult()` / `fileUsageWindowStore()` / `sessionPolicy()` 口)。 */
|
|
522
532
|
export type LocalEngineFileStores = Pick<FileStorageBackend, "checkpointStore" | "backgroundAgentStore" | "mailboxStore" | "rosterStore">;
|
|
523
533
|
/** 打开 local 数据根的入口参数:哪条路在开(只决定拒句的措辞 —— 表头与「换根」半句)与三只 boot 期日志座(见 {@link createStoreBackend})。 */
|
|
524
534
|
export interface LocalBackendOpenOptions {
|
|
525
535
|
readonly lane: StoreOpenLane;
|
|
536
|
+
/** 这只根的数据根准入读数(必填;{@link admitLocalDataRoot} 铸,调用方在它对这只根的第一笔写之前取 —— 打开就是第一笔写的调用方当场取,见 {@link createStoreBackend})。 */
|
|
537
|
+
readonly admission: LocalDataRootAdmission;
|
|
526
538
|
readonly onWarn?: BootLogSink;
|
|
527
539
|
readonly onError?: BootLogSink;
|
|
528
540
|
readonly observers?: StoreBackendObservers;
|
|
541
|
+
/** 起服事实(数据根介质的判定;HTTP 服务递第 2 段的取证,缺席 ⇒ `unknown`)。 */
|
|
542
|
+
readonly facts?: StoreOpenFacts;
|
|
529
543
|
}
|
|
530
544
|
/**
|
|
531
545
|
* **local 后端打开数据根**(唯一的路 —— 本仓每一条打开 local 数据根的入口都经它:`createStoreBackend` 的 local 腿(HTTP 服务)与 run-local;一个数据根一只会话行店、一份装配):
|
|
532
|
-
*
|
|
546
|
+
* 数据根准入(调用方交来的读数 `opts.admission`,判已在本进程第一笔写之前做完)→ 取锁(引擎 File 后端:建根、锁文件、引擎自己的店目录与空账本)→
|
|
547
|
+
* **锁内一步**({@link holdLocalDataRootAdmission}:核物理数据根与准入那一次观察都没动 → 跳版臂记 / 销账 → 抬引擎版本高水位)→ 本仓的店。
|
|
533
548
|
* 打开之后的公开序列两条入口相同:`ensureSchema()`(起服对账)→ `runOneTimeMigrations()` → 才读会话。
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
*
|
|
537
|
-
*
|
|
538
|
-
* 残余(如实):引擎 `FileStorageBackend` 的构造把取锁与它自己的店放在同一步(建子目录、店目录锁、撕裂账本尾的收拢)—— 那几笔在判之前,本仓在两者之间没有座(要 core 给)。
|
|
549
|
+
* 抬住在这里而不是 `ensureSchema()` 里,因为围栏以**第一笔落盘**界定:本仓的店在构造里就会写(撕裂的问账日志留证 + 压实、撕裂的 run 认领挪开、会话收尾的活跃边档落盘),
|
|
550
|
+
* 抬必须先于它们(写到一半崩了,水位已是本构建)。所以这一段之后才有店,没有任何一只店先于它。
|
|
551
|
+
* 锁内一步拒(准入判过的输入在准入之后被另一只引擎动过 / 记账或抬写不进)或本仓的店构造时抛 ⇒ 交回一只 {@link RefusedLocalBackend}:只握着锁,`ensureSchema()` 交出那一只拒
|
|
552
|
+
* (公开序列在它该在的那一步拒,降级臂按拒的族判),`close()` 只放锁 —— 没有店、没有收尾写。
|
|
539
553
|
*/
|
|
540
554
|
export declare function openLocalBackend(config: ServiceConfig, opts: LocalBackendOpenOptions): LocalStoreBackend;
|
|
541
555
|
/** Build the durable-store backend for `config.dbBackend`. Does NOT connect (the pool connects lazily); the next
|
|
@@ -573,7 +587,7 @@ export declare function localBackendRootOf(config: Pick<ServiceConfig, "localDat
|
|
|
573
587
|
export declare function openStoreBackendWithFallback(config: ServiceConfig, logger: {
|
|
574
588
|
warn: (msg: string, meta?: Record<string, unknown>) => void;
|
|
575
589
|
error?: (msg: string, meta?: Record<string, unknown>) => void;
|
|
576
|
-
}, observers?: StoreBackendObservers): Promise<{
|
|
590
|
+
}, observers?: StoreBackendObservers, localAdmission?: LocalDataRootAdmission, facts?: StoreOpenFacts): Promise<{
|
|
577
591
|
backend: StoreBackend | undefined;
|
|
578
592
|
degradedReason: StoreDegradedReason | undefined;
|
|
579
593
|
}>;
|
|
@@ -15,15 +15,18 @@ import { StoreBootRefusalError } from "./store-contracts.js";
|
|
|
15
15
|
import { databaseAnswerCodesOf, isDeploymentFaultError } from "./sql-errors.js";
|
|
16
16
|
import { buildStoreOpenRefusalTail } from "./store-open-refusal.js";
|
|
17
17
|
import { acquireLocalBackendWithWait } from "./store-lock-wait.js";
|
|
18
|
-
import { NO_SQL_MIGRATIONS, assertExecutionPlacementSwitchAdmissibleOnPool, backfillLocalAskExecutionLanes, backfillLocalExecutionPlacements, runSqlOneTimeMigrations } from "./one-time-migrations.js";
|
|
18
|
+
import { NO_SQL_MIGRATIONS, migrationCarried, assertExecutionPlacementSwitchAdmissibleOnPool, backfillLocalAskExecutionLanes, backfillLocalExecutionPlacements, runSqlOneTimeMigrations } from "./one-time-migrations.js";
|
|
19
19
|
import { deployedExecutionLanes } from "../execution-lane-caps.js";
|
|
20
20
|
import { DEPLOYMENT_SHAPE_PREDICATES } from "../deployment-shape.js";
|
|
21
21
|
import { LOCAL_MARKER_FILE, switchLocalScenarioPrefixM42 } from "./scenario-prefix-switch-m42.js";
|
|
22
|
-
import {
|
|
22
|
+
import { dropLocalLegacySkillExemptionsM46 } from "./approval-exemption-skill-m46.js";
|
|
23
|
+
import { LOCAL_SKILL_EXEMPTION_CUTOFF_FILE, assertSkillExemptionCutoffHeldOnPool } from "./approval-exemption-skill-cutoff.js";
|
|
24
|
+
import { SKILL_EXEMPTION_CUTOFF_ID } from "./one-time-migration-marker.js";
|
|
23
25
|
import { LocalTaskAttachmentStore } from "./local-task-attachment-store.js";
|
|
24
26
|
import { assertRetiredSchemaAbsentOnPool } from "./schema-consistency.js";
|
|
25
|
-
import { LocalSessionStore,
|
|
26
|
-
import {
|
|
27
|
+
import { LocalSessionStore, createLocalSessionRepo } from "./local-session-store.js";
|
|
28
|
+
import { localStoreDeclarationOf } from "../local-store-declaration.js";
|
|
29
|
+
import { SESSION_PLACEMENTS } from "./session-placement.js";
|
|
27
30
|
import { LocalCheckpointStore, dropLocalCheckpointCtxStrict } from "./local-checkpoint-store.js";
|
|
28
31
|
import { FileResumeAnchorStore } from "./file-resume-anchor-store.js";
|
|
29
32
|
import { TiDBApprovalExemptionStore, PgApprovalExemptionStore, FileApprovalExemptionStore } from "./approval-exemption-store.js";
|
|
@@ -76,8 +79,7 @@ import { createSqlPermissionRuleStores } from "./permission-rule-store-sql.js";
|
|
|
76
79
|
import { FILE_PERMISSION_RULE_DIR, createFilePermissionRuleStores, fileRuleBucketOwners, isFileBucketDamaged } from "./permission-rule-store-file.js";
|
|
77
80
|
import { retireImportedLayerRootAllows } from "./imported-layer-root-retirement.js";
|
|
78
81
|
import { buildDataDirLayout, tightenLocalDataDirModes } from "./local-data-dir-modes-m39.js";
|
|
79
|
-
import {
|
|
80
|
-
import { serviceVersion } from "../service-version.js";
|
|
82
|
+
import { admitLocalDataRoot, holdLocalDataRootAdmission } from "./local-data-root-admission.js";
|
|
81
83
|
import { mysqlDriver, pgDriver } from "./sql-driver.js";
|
|
82
84
|
import { localDataRootHoldsData, storeDegradedReasonFor } from "../store-posture.js";
|
|
83
85
|
import { openWithinWait } from "./store-open-wait.js";
|
|
@@ -377,10 +379,12 @@ class LocalBackend {
|
|
|
377
379
|
parkDecisionLedgerRoot;
|
|
378
380
|
executionLanes;
|
|
379
381
|
identityBoundary;
|
|
382
|
+
storeDeclaration;
|
|
380
383
|
dataDirLayout;
|
|
381
|
-
constructor(fileBackend, config, discloseWarn, onWarn, onError, observers) {
|
|
384
|
+
constructor(fileBackend, config, discloseWarn, onWarn, onError, observers, facts) {
|
|
382
385
|
this.executionLanes = deployedExecutionLanes(config);
|
|
383
386
|
this.identityBoundary = DEPLOYMENT_SHAPE_PREDICATES.identityBoundary.holds(config);
|
|
387
|
+
this.storeDeclaration = localStoreDeclarationOf(config, facts?.dataRootMedium ?? "unknown");
|
|
384
388
|
this.onWarn = onWarn;
|
|
385
389
|
this.discloseWarn = discloseWarn;
|
|
386
390
|
this.onError = onError;
|
|
@@ -397,7 +401,7 @@ class LocalBackend {
|
|
|
397
401
|
const physicalRoot = this.fileBackend.root;
|
|
398
402
|
this.sessionStore = new LocalSessionStore(createLocalSessionRepo(physicalRoot), this.runStore, physicalRoot, {
|
|
399
403
|
log: createLogger(config.logLevel),
|
|
400
|
-
durability:
|
|
404
|
+
durability: this.storeDeclaration.durability,
|
|
401
405
|
placements: SESSION_PLACEMENTS,
|
|
402
406
|
withdrawCheckpointCtx: (sessionId) => dropLocalCheckpointCtxStrict(physicalRoot, sessionId),
|
|
403
407
|
});
|
|
@@ -420,7 +424,6 @@ class LocalBackend {
|
|
|
420
424
|
}
|
|
421
425
|
async ensureSchema() {
|
|
422
426
|
this.executionLaneWordsRenamed += await this.sessionStore.renameRetiredExecutionLaneWordM40();
|
|
423
|
-
await this.sessionStore.assertStrictSidecarsReadable();
|
|
424
427
|
await this.sessionStore.finishPendingDrops();
|
|
425
428
|
await this.sessionStore.settleArchiveSnapshots();
|
|
426
429
|
const adoption = await this.sessionStore.adoptArchiveTokensM47();
|
|
@@ -443,11 +446,24 @@ class LocalBackend {
|
|
|
443
446
|
});
|
|
444
447
|
const runErrorCodeColumnRewritten = this.runStore.migrateRunErrorCodeColumnM44();
|
|
445
448
|
const runObjectivePreviewRewritten = this.runStore.migrateRunObjectivePreviewM45();
|
|
446
|
-
const
|
|
449
|
+
const shellSentinelOwnerRowsRetained = [];
|
|
450
|
+
let shellSentinelOwnersCleared = 0;
|
|
451
|
+
if (this.identityBoundary) {
|
|
452
|
+
for (const [surface, rows] of [
|
|
453
|
+
["session_meta", await this.sessionStore.countShellSentinelOwnersM48()],
|
|
454
|
+
["task_run", this.runStore.countShellSentinelOwnersM48()],
|
|
455
|
+
]) {
|
|
456
|
+
if (rows > 0)
|
|
457
|
+
shellSentinelOwnerRowsRetained.push({ surface, rows });
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
shellSentinelOwnersCleared = (await this.sessionStore.clearShellSentinelOwnersM48()) + this.runStore.clearShellSentinelOwnersM48();
|
|
462
|
+
}
|
|
447
463
|
const checkpointHostSessionsBackfilled = existsSync(join(this.fileBackend.root, "checkpoint-session-tokens.json")) || existsSync(join(this.fileBackend.root, "checkpoint-scopes.json"))
|
|
448
464
|
? await this.checkpointStoreOf().backfillHostSessionsM49()
|
|
449
465
|
: 0;
|
|
450
|
-
const legacySkillExemptionsDropped = dropLocalLegacySkillExemptionsM46(join(this.fileBackend.root,
|
|
466
|
+
const legacySkillExemptionsDropped = dropLocalLegacySkillExemptionsM46(join(this.fileBackend.root, LOCAL_SKILL_EXEMPTION_CUTOFF_FILE), this.approvalExemptionStore);
|
|
451
467
|
const archives = await this.sessionStore.migrateLocalArchives();
|
|
452
468
|
const placements = await backfillLocalExecutionPlacements(this.runStore.sessionIdsWithRuns(), this.sessionStore.executionPlacementBackfill, { lanes: this.executionLanes });
|
|
453
469
|
const importedLayerRoot = { importedLayerRootAllowsRetired: [], importedLayerRootBucketsSkipped: [], importedLayerRootBucketsUnnamed: 0 };
|
|
@@ -467,6 +483,7 @@ class LocalBackend {
|
|
|
467
483
|
runErrorCodeColumnRewritten,
|
|
468
484
|
runObjectivePreviewRewritten,
|
|
469
485
|
shellSentinelOwnersCleared,
|
|
486
|
+
shellSentinelOwnerRowsRetained,
|
|
470
487
|
checkpointHostSessionsBackfilled,
|
|
471
488
|
legacySkillExemptionsDropped,
|
|
472
489
|
executionPlacementsBackfilled: placements.backfilled,
|
|
@@ -524,6 +541,7 @@ class LocalBackend {
|
|
|
524
541
|
userInputLedger() { return this.userInputLedgerStore; }
|
|
525
542
|
checkpointStoreOf() {
|
|
526
543
|
return (this.checkpointStoreInst ??= new LocalCheckpointStore(this.fileBackend.root, {
|
|
544
|
+
durability: this.storeDeclaration.durability,
|
|
527
545
|
getActiveTaskId: (sessionId) => this.runStore.getActiveTaskId(sessionId),
|
|
528
546
|
readSessionOwner: async (sessionId) => (await this.sessionStore.headOf(sessionId))?.owner,
|
|
529
547
|
}));
|
|
@@ -544,6 +562,7 @@ class LocalBackend {
|
|
|
544
562
|
checkpointStoreInst;
|
|
545
563
|
sessionPolicy() { return (this.sessionPolicyInst ??= createClientCountedPolicyStore(this.fileBackend.sessionPolicyStore, this.sessionStore)); }
|
|
546
564
|
sessionPolicyInst;
|
|
565
|
+
localStoreDeclaration() { return this.storeDeclaration; }
|
|
547
566
|
fileUsageWindowStore() { return this.fileBackend.usageWindowStore; }
|
|
548
567
|
fileHistory() { return this.fileBackend.fileHistoryStore; }
|
|
549
568
|
memoryOptOutGrant() { return undefined; }
|
|
@@ -568,7 +587,7 @@ const LOCAL_OPEN_REFUSAL_HEAD = {
|
|
|
568
587
|
"run-local": (root) => `cannot open local data dir ${root}`,
|
|
569
588
|
};
|
|
570
589
|
export function openLocalBackend(config, opts) {
|
|
571
|
-
const { lane, onWarn, onError, observers } = opts;
|
|
590
|
+
const { lane, admission, onWarn, onError, observers, facts } = opts;
|
|
572
591
|
const root = localBackendRootOf(config);
|
|
573
592
|
const discloseWarn = onWarn ?? createLogger().warn;
|
|
574
593
|
let fileBackend;
|
|
@@ -587,25 +606,24 @@ export function openLocalBackend(config, opts) {
|
|
|
587
606
|
(tail === undefined ? "" : ` ${tail}`));
|
|
588
607
|
}
|
|
589
608
|
try {
|
|
590
|
-
|
|
591
|
-
holdEngineHighWater(physicalRoot, serviceVersion(), (prior) => holdArchiveTokenAdoptionDuty(physicalRoot, prior, archiveTokenAdoptionCarried()));
|
|
609
|
+
holdLocalDataRootAdmission(fileBackend.root, admission);
|
|
592
610
|
}
|
|
593
611
|
catch (refusal) {
|
|
594
|
-
return new RefusedLocalBackend(fileBackend, refusal instanceof Error ? refusal : new Error(String(refusal)));
|
|
612
|
+
return new RefusedLocalBackend(() => fileBackend.dispose(), refusal instanceof Error ? refusal : new Error(String(refusal)));
|
|
595
613
|
}
|
|
596
614
|
try {
|
|
597
|
-
return new LocalBackend(fileBackend, config, discloseWarn, onWarn, onError, observers);
|
|
615
|
+
return new LocalBackend(fileBackend, config, discloseWarn, onWarn, onError, observers, facts);
|
|
598
616
|
}
|
|
599
617
|
catch (failure) {
|
|
600
|
-
return new RefusedLocalBackend(fileBackend, failure instanceof Error ? failure : new Error(String(failure)));
|
|
618
|
+
return new RefusedLocalBackend(() => fileBackend.dispose(), failure instanceof Error ? failure : new Error(String(failure)));
|
|
601
619
|
}
|
|
602
620
|
}
|
|
603
621
|
class RefusedLocalBackend {
|
|
604
|
-
|
|
622
|
+
release;
|
|
605
623
|
refusal;
|
|
606
624
|
kind = "local";
|
|
607
|
-
constructor(
|
|
608
|
-
this.
|
|
625
|
+
constructor(release, refusal) {
|
|
626
|
+
this.release = release;
|
|
609
627
|
this.refusal = refusal;
|
|
610
628
|
}
|
|
611
629
|
refused() {
|
|
@@ -618,7 +636,7 @@ class RefusedLocalBackend {
|
|
|
618
636
|
return this.refused();
|
|
619
637
|
}
|
|
620
638
|
async close() {
|
|
621
|
-
await this.
|
|
639
|
+
await this.release();
|
|
622
640
|
}
|
|
623
641
|
run() { return this.refused(); }
|
|
624
642
|
resumeAnchor() { return this.refused(); }
|
|
@@ -640,12 +658,13 @@ class RefusedLocalBackend {
|
|
|
640
658
|
engineFileStores() { return this.refused(); }
|
|
641
659
|
toolResult() { return this.refused(); }
|
|
642
660
|
fileUsageWindowStore() { return this.refused(); }
|
|
661
|
+
localStoreDeclaration() { return this.refused(); }
|
|
643
662
|
mysqlPool() { return undefined; }
|
|
644
663
|
pgPool() { return undefined; }
|
|
645
664
|
}
|
|
646
665
|
export function createStoreBackend(config, onWarn, onError, observers) {
|
|
647
666
|
if (config.dbBackend === "local")
|
|
648
|
-
return
|
|
667
|
+
return openAdmittedLocalBackend(config, undefined, { onWarn, onError, observers });
|
|
649
668
|
if (config.dbBackend === "pg") {
|
|
650
669
|
if (!config.pg)
|
|
651
670
|
return undefined;
|
|
@@ -657,11 +676,24 @@ export function createStoreBackend(config, onWarn, onError, observers) {
|
|
|
657
676
|
const pool = createTidbPool(config);
|
|
658
677
|
return withRetiredSchemaProbe(new TiDBBackend(pool, config, observers), { dialect: "mysql", pool }, { lanes: deployedExecutionLanes(config) });
|
|
659
678
|
}
|
|
679
|
+
function openAdmittedLocalBackend(config, admission, sinks) {
|
|
680
|
+
let admitted = admission;
|
|
681
|
+
if (admitted === undefined) {
|
|
682
|
+
try {
|
|
683
|
+
admitted = admitLocalDataRoot(localBackendRootOf(config));
|
|
684
|
+
}
|
|
685
|
+
catch (refusal) {
|
|
686
|
+
return new RefusedLocalBackend(async () => undefined, refusal instanceof Error ? refusal : new Error(String(refusal)));
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
return openLocalBackend(config, { lane: "http", admission: admitted, ...sinks });
|
|
690
|
+
}
|
|
660
691
|
function withRetiredSchemaProbe(inner, target, executionPlacementSwitch) {
|
|
661
692
|
const guarded = Object.create(inner);
|
|
662
693
|
guarded.ensureSchema = async () => {
|
|
663
694
|
await assertRetiredSchemaAbsentOnPool(target);
|
|
664
695
|
await assertExecutionPlacementSwitchAdmissibleOnPool(target.dialect, target.pool, executionPlacementSwitch);
|
|
696
|
+
await assertSkillExemptionCutoffHeldOnPool(target, migrationCarried(SKILL_EXEMPTION_CUTOFF_ID));
|
|
665
697
|
await inner.ensureSchema();
|
|
666
698
|
};
|
|
667
699
|
return guarded;
|
|
@@ -669,7 +701,7 @@ function withRetiredSchemaProbe(inner, target, executionPlacementSwitch) {
|
|
|
669
701
|
export function localBackendRootOf(config) {
|
|
670
702
|
return config.localDataRoot ?? join(homedir(), ".ai-agent");
|
|
671
703
|
}
|
|
672
|
-
export async function openStoreBackendWithFallback(config, logger, observers) {
|
|
704
|
+
export async function openStoreBackendWithFallback(config, logger, observers, localAdmission, facts) {
|
|
673
705
|
const sqlEngine = config.dbBackend === "mysql" || config.dbBackend === "pg" ? config.dbBackend : undefined;
|
|
674
706
|
const mayFallback = config.dbBackend === "local" && !config.dbBackendExplicit && !localDataRootHoldsData(localBackendRootOf(config));
|
|
675
707
|
let backend;
|
|
@@ -678,7 +710,9 @@ export async function openStoreBackendWithFallback(config, logger, observers) {
|
|
|
678
710
|
const attempt = async () => {
|
|
679
711
|
let built;
|
|
680
712
|
try {
|
|
681
|
-
|
|
713
|
+
const onWarn = (msg, meta) => logger.warn(msg, meta);
|
|
714
|
+
const onError = logger.error === undefined ? undefined : (msg, meta) => logger.error(msg, meta);
|
|
715
|
+
built = config.dbBackend === "local" ? openAdmittedLocalBackend(config, localAdmission, { onWarn, onError, observers, ...(facts !== undefined ? { facts } : {}) }) : createStoreBackend(config, onWarn, onError, observers);
|
|
682
716
|
inFlight = built;
|
|
683
717
|
if (built)
|
|
684
718
|
await built.ensureSchema();
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
import type { PeerSessionTempo, TaskResult, TaskStatus } from "@sema-agent/core";
|
|
22
22
|
import type { RunIdentity } from "../identity-source.js";
|
|
23
23
|
import type { SessionUnreadable } from "../session-error-wire.js";
|
|
24
|
+
import type { ReadDenyFloorSummary } from "../read-deny-floor-notice.js";
|
|
24
25
|
/**
|
|
25
26
|
* **File 店族的 boot 期拒启基类**([ref];把 `RunStoreStrictHydrateError` 的那条论证升成一条族规)。
|
|
26
27
|
*
|
|
@@ -50,6 +51,19 @@ export declare class StoreBootRefusalError extends Error {
|
|
|
50
51
|
* 会话部署格旁表建不出(`session-ext-table.ts`)、local 数据根的严格边档对账(`local-session-store.ts`)。码住在族基类旁边:读它的几只模块彼此不必互相 import。
|
|
51
52
|
*/
|
|
52
53
|
export declare const SCHEMA_MISMATCH_ERROR_CODE = "config.schema_mismatch";
|
|
54
|
+
/**
|
|
55
|
+
* **SQL 库的列形不是本构建读得动的形 ⇒ 起服拒**的唯一出口:整库列册对账的三条拒(列集不符 / information_schema 读不出 / 整库零行,`schema-consistency.ts`)与六只单表探针的拒启
|
|
56
|
+
* (`checkpoint` · `tool_result` · `file_history_*` · `approval_ask` · `permission_rule_approval` · `permission_rule_ticket`)都经这一只类抛 —— 运维按码(`code` 字段 + 消息首词,同一个
|
|
57
|
+
* {@link SCHEMA_MISMATCH_ERROR_CODE})判「要跑 ALTER」,不必先猜是哪一只判官拒的。两只判官答同一问(这张表缺不缺列),出口只有一个。
|
|
58
|
+
*
|
|
59
|
+
* 属 {@link StoreBootRefusalError} 族:这是一句**确定**的拒启表态(再等也等不来另一个答案)—— 判官万一挪进 `ensureSchema()` 的开库等待窗,它不被重试、不被改写成「库打不开」。
|
|
60
|
+
* 消息**必须**以码领头:调用方交整句(对账的 `describeSchemaMismatch`、探针的 `probedMissingColumnRefusal` 都是码领头的整句),构造期核一次 —— 缺码 = 编程错,当场响,不是静默补一个。
|
|
61
|
+
*/
|
|
62
|
+
export declare class SchemaMismatchRefusedError extends StoreBootRefusalError {
|
|
63
|
+
/** 机读码(与退役 schema / 旁表建不出 / local 数据根的拒启同一个)。 */
|
|
64
|
+
readonly code = "config.schema_mismatch";
|
|
65
|
+
constructor(message: string, options?: ErrorOptions);
|
|
66
|
+
}
|
|
53
67
|
/**
|
|
54
68
|
* 取消便签里的**大脑相位**快照 —— core `BrainStatus` 帧经 `brainStatusEventData` 投影后的五键子集。
|
|
55
69
|
*
|
|
@@ -142,6 +156,14 @@ export type AbortCause = (typeof ABORT_CAUSES)[number];
|
|
|
142
156
|
export interface PersistedResultSideKeys {
|
|
143
157
|
cancelContext?: RunCancelContext;
|
|
144
158
|
abortCause?: AbortCause;
|
|
159
|
+
/**
|
|
160
|
+
* 这条 run **照跑了**,而它的读拒行不按字节守:读拒表有行、执行环境不守读拒字节地板、部署没要求地板(`READ_DENY_FLOOR_REQUIRED` 未设)。
|
|
161
|
+
* `{ code: "config.read_deny_floor_unkept", message }` —— 与这条 run 事件流上那一帧 `engine_notice` 同码同句(句子点名 `REMOTE_EXEC=<车道>` 与出路
|
|
162
|
+
* `READ_DENY_FLOOR_REQUIRED=true`)。判官是引擎(每 run 准备期一次,结果按 `runId` 接上);说法的唯一属主 `read-deny-floor-notice.ts`,挂点 = 出口封口
|
|
163
|
+
* (`terminal.ts` 的 `sealResultForExit`)。拒起的 run 不带它(那一句在失败终局的句子里)。为什么属于 run 账本而不属于 core 的任务结果:引擎只发通告、
|
|
164
|
+
* 不在结果上留这件事,而句子里的执行环境与旋钮名是本仓的部署事实。
|
|
165
|
+
*/
|
|
166
|
+
readDenyFloor?: ReadDenyFloorSummary;
|
|
145
167
|
}
|
|
146
168
|
/**
|
|
147
169
|
* 落库/上 wire 的终局结果 = core 的 `TaskResult` **加上** server 自铸的可缺席侧记键({@link PersistedResultSideKeys})。
|
|
@@ -226,11 +248,15 @@ export interface RunRecord {
|
|
|
226
248
|
* MY replica" (consult the in-process inflight/steerable map authoritatively) from "held elsewhere" (fall
|
|
227
249
|
* back to the durable cross-replica flag). null for pre-column rows. */
|
|
228
250
|
instanceId: string | null;
|
|
251
|
+
/** **持有腿**(`task_run.leg_id`):此刻持有这条行的那一条腿的身份 —— 认领铸它({@link mintRunLegId}:建行 = 首腿、续跑认领 = 新腿),交回给认领者;
|
|
252
|
+
* 停驻写的 CAS 只许持有腿落下(`setSuspended` / `setNeedsReview` 的 `legId`)。与 {@link instanceId} 是两件事:那一列答「活腿在哪台副本上」(路由),
|
|
253
|
+
* 这一列答「是不是这一条腿」。`null` = 没有持有腿的记录(列之前的行;更早版本的副本建 / 认领的行)—— 本版的腿从不持有它。不上 wire。 */
|
|
254
|
+
legId: string | null;
|
|
229
255
|
/** 🔴 [ref] P-45 —— 这条 run 上**挂没挂着取消请求**(耐久 `cancel_requested` 列的投影,跨副本)。
|
|
230
256
|
*
|
|
231
257
|
* 语义就是那一列的字节:`POST /v1/runs/:id/cancel` 的 running 臂 CAS 成功即置位,持有副本的心跳拍
|
|
232
|
-
* poll 到它就 abort
|
|
233
|
-
*
|
|
258
|
+
* poll 到它就 abort;旗是对**持有腿**的请求 —— 停驻写不落在挂着的旗上(停驻 CAS 认它,停驻提交读到旗就以取消收场),
|
|
259
|
+
* `markResuming`(续跑认领 = 换持有腿)把它清零,旗随旧腿去。
|
|
234
260
|
*
|
|
235
261
|
* 为什么是**行上的一位**而不是读面再查一次:列早就在(三个后端同名),只是行投影没带它 —— 正是
|
|
236
262
|
* 本仓 L1 键集门盯的那族「投影剥键」。读面每次 poll 再发一条 `isCancelRequested` 查询,是给热路径
|
|
@@ -275,9 +301,12 @@ export interface NewRunMeta {
|
|
|
275
301
|
objectivePreview?: string | null;
|
|
276
302
|
idem?: RunIdemBinding | null;
|
|
277
303
|
}
|
|
304
|
+
/** 铸一只持有腿({@link RunRecord.legId})—— 三只 run 店的两个认领口(`createRun` / `markResuming`)都调它,别处不铸。唯一值而非计数:同一 `taskId` 的行被删后重建,
|
|
305
|
+
* 新行的持有腿与旧腿的永不相等(旧腿迟到的停驻写不会落到新行上);认领者随写拿到它,不必读回。 */
|
|
306
|
+
export declare function mintRunLegId(): string;
|
|
278
307
|
/**
|
|
279
308
|
* `RunStore.createRun` 的结局 —— 四形,一形一句话:
|
|
280
|
-
* · `{ ok: true }` —— 新行已建、会话 claim
|
|
309
|
+
* · `{ ok: true, legId }` —— 新行已建、会话 claim 已拿;`legId` = 这次认领铸下的持有腿({@link RunRecord.legId}),首腿的停驻写凭它;
|
|
281
310
|
* · `{ ok: false, existing }` —— 这次提交的一把**幂等钥匙**已经指向一条行:`idem_key`(`Idempotency-Key`)或
|
|
282
311
|
* `task_id`(调用方自铸的 `body.taskId`)—— 两把钥匙是**同一条律**(资源行上的唯一键),先认 `idem_key` 再认 `task_id`。
|
|
283
312
|
* 这是「原子赢或观察」的**观察**臂:行原样交回,没建新行、没动会话;回执由提交面的唯一回执函数判。
|
|
@@ -288,6 +317,7 @@ export interface NewRunMeta {
|
|
|
288
317
|
*/
|
|
289
318
|
export type CreateRunOutcome = {
|
|
290
319
|
ok: true;
|
|
320
|
+
legId: string;
|
|
291
321
|
existing?: undefined;
|
|
292
322
|
activeTaskId?: undefined;
|
|
293
323
|
sessionAbsent?: undefined;
|
|
@@ -309,10 +339,14 @@ export type CreateRunOutcome = {
|
|
|
309
339
|
};
|
|
310
340
|
/**
|
|
311
341
|
* 认领栅栏交给 `write` 的那一行 run 此刻的事实(SQL = 锁住那一行读的;进程内 = 同步段里读的)。认领与 `running` 只认 taskId,而续跑腿让同一个 taskId
|
|
312
|
-
* 停驻之后回到 `running`、认领仍在 —— 「接下这笔写的那条腿还是不是这条 run
|
|
342
|
+
* 停驻之后回到 `running`、认领仍在 —— 「接下这笔写的那条腿还是不是这条 run 的腿」要按腿问的写者拿它问:
|
|
343
|
+
* · `legId` = 行此刻的持有腿({@link RunRecord.legId},认领铸、交给认领者)。持认领的腿自己的写问「是不是我」—— 判据 {@link createLegCtxClaim},
|
|
344
|
+
* 与停驻写的 CAS(`setSuspended` / `setNeedsReview`)、撤回(`withdrawMintedRun`)同一只身份读法;
|
|
345
|
+
* · `instanceId` = 行此刻的副本。切档口(`routes/run-permission-mode.ts` `switchLegHolds`)问的是「是不是我切过的那条腿」,它手上是本副本活流登记簿里的流对象。
|
|
313
346
|
*/
|
|
314
347
|
export interface FencedRun {
|
|
315
348
|
readonly instanceId: string | null;
|
|
349
|
+
readonly legId: string | null;
|
|
316
350
|
}
|
|
317
351
|
/** SQL 认领栅栏的结局:`held: false` = 认领此刻不是这条 run 的(或它已不在跑),`write` 一次都没调。 */
|
|
318
352
|
export type ClaimFenced<T> = {
|
|
@@ -346,7 +380,7 @@ export type ClaimFenceStore = import("./run-store-sql.js").SqlRunStore | InProce
|
|
|
346
380
|
/**
|
|
347
381
|
* 🔴 [ref] **一笔续跑输入写所凭的那只认领**(检查点店的写口 `putCtx` 交认领的那一形与 `rewriteCtxWhileClaimed` 收它):
|
|
348
382
|
* `fence` = 写者持认领的那只 run 店(栅栏的来源就是认领本身 —— 检查点店不在构造期另绑一份 run 店),`taskId` = 持认领的 run,
|
|
349
|
-
* `legHolds` = 腿判据(在栅栏里对锁住 / 同步段里那一行同步问一次,只读、不许 await)。
|
|
383
|
+
* `legHolds` = 腿判据(在栅栏里对锁住 / 同步段里那一行同步问一次,只读、不许 await;持认领的腿经 {@link createLegCtxClaim} 按持有腿判)。
|
|
350
384
|
* 装配契约:SQL 检查点店只收同一库上的 SQL run 店(两店出自同一后端;店按判别位 `db` 判 SQL 形且方言同,错形响亮抛),local 检查点店只收进程内栅栏。
|
|
351
385
|
*/
|
|
352
386
|
export interface CtxWriteClaim {
|
|
@@ -354,6 +388,12 @@ export interface CtxWriteClaim {
|
|
|
354
388
|
readonly taskId: string;
|
|
355
389
|
readonly legHolds: (run: FencedRun) => boolean;
|
|
356
390
|
}
|
|
391
|
+
/**
|
|
392
|
+
* 持认领的腿写续跑输入所凭的那只认领(提交腿 `http/submit-ctx.ts` 与续跑腿的写回 `http/resume-legs.ts` 同调这一只):腿判据 = 「被锁那一行此刻的持有腿就是本腿」——
|
|
393
|
+
* `legId` = 认领交给本腿的那一只(建行 `createRun` 的 `{ ok: true, legId }` / 续跑认领 `markResuming` 的交回值)。同一副本上同一 taskId 被后来的腿重新认领 ⇒
|
|
394
|
+
* 持有腿已换 ⇒ 零写(副本没变,只问副本的判据分不开这两条腿)。
|
|
395
|
+
*/
|
|
396
|
+
export declare function createLegCtxClaim(fence: ClaimFenceStore, taskId: string, legId: string): CtxWriteClaim;
|
|
357
397
|
/**
|
|
358
398
|
* `RunRecord["status"]`(= `"running" | TaskStatus`)的**唯一分类表** —— 词表的属主 = 判据的属主,
|
|
359
399
|
* 与类型定义同住一个文件。四个类:
|
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import { RUN_STALE_SEC_DEFAULT } from "../run-stale-default.js";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
2
3
|
export class StoreBootRefusalError extends Error {
|
|
3
4
|
}
|
|
4
5
|
export const SCHEMA_MISMATCH_ERROR_CODE = "config.schema_mismatch";
|
|
6
|
+
export class SchemaMismatchRefusedError extends StoreBootRefusalError {
|
|
7
|
+
code = SCHEMA_MISMATCH_ERROR_CODE;
|
|
8
|
+
constructor(message, options) {
|
|
9
|
+
super(codeLed(message), options);
|
|
10
|
+
this.name = "SchemaMismatchRefusedError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function codeLed(message) {
|
|
14
|
+
if (!message.startsWith(`${SCHEMA_MISMATCH_ERROR_CODE}: `))
|
|
15
|
+
throw new TypeError(`a ${SCHEMA_MISMATCH_ERROR_CODE} refusal must lead with its code`);
|
|
16
|
+
return message;
|
|
17
|
+
}
|
|
5
18
|
export const ABORT_CAUSES = ["client_disconnected", "ask_park_grace_exhausted", "cancel_verb", "stall_verdict"];
|
|
6
19
|
export const RUN_STALLED_ERROR = "run stalled (instance lost?)";
|
|
7
20
|
export const RUN_ORPHANED_ERROR = "run orphaned by engine restart";
|
|
@@ -13,7 +26,13 @@ const RUN_HOLDER_DEATH_CODE_WORDS = new Set(Object.values(RUN_HOLDER_DEATH_CODES
|
|
|
13
26
|
export function isHolderDeathVerdict(run) {
|
|
14
27
|
return run.status === "failed" && run.errorCode !== null && RUN_HOLDER_DEATH_CODE_WORDS.has(run.errorCode);
|
|
15
28
|
}
|
|
29
|
+
export function mintRunLegId() {
|
|
30
|
+
return randomUUID();
|
|
31
|
+
}
|
|
16
32
|
export const FENCE_LANDED = Symbol("in-process-claim-fence.landed");
|
|
33
|
+
export function createLegCtxClaim(fence, taskId, legId) {
|
|
34
|
+
return { fence, taskId, legHolds: (run) => run.legId === legId };
|
|
35
|
+
}
|
|
17
36
|
export const RUN_STATUS_CLASS = {
|
|
18
37
|
running: "live",
|
|
19
38
|
completed: "succeeded",
|
|
@@ -51,7 +51,7 @@ export declare function createTidbPool(config: ServiceConfig): Pool;
|
|
|
51
51
|
* 3. 生成的全集 SQL 基线导出到 `docs/schema/baseline-mysql.sql`(由本数组机器生成;它是**产物**,不是真源
|
|
52
52
|
* —— 冲突时以本文件为准并重新生成)。
|
|
53
53
|
*
|
|
54
|
-
* 注意:`ensureSchema` 仍然保留(建表 + advisory lock + image_bake_admit
|
|
54
|
+
* 注意:`ensureSchema` 仍然保留(建表 + advisory lock + 两只种子行:image_bake_admit 与 `Skill` 豁免截点),语句数组是纯 CREATE。数组之外只有一只只读探针:会话部署格旁表
|
|
55
55
|
* `session_ext` 的外键列要抄被引列 `session_meta.session_id` 的字符集 / 排序规则(MySQL 外键两侧必须相同,而存量库上它随建库年代不同),建它之前读一次
|
|
56
56
|
* `information_schema.COLUMNS`(`session-ext-table.ts` 的 `ensureSessionExtTableMysql`;探针只读、不导出任何 ALTER)。
|
|
57
57
|
*/
|
|
@@ -59,17 +59,22 @@ export declare const SCHEMA_STATEMENTS: readonly string[];
|
|
|
59
59
|
/** Named MySQL/TiDB advisory lock that serializes the whole `ensureSchema` DDL run (see below). */
|
|
60
60
|
export declare const ENSURE_SCHEMA_LOCK = "sema_ensure_schema";
|
|
61
61
|
/** Acquire {@link ENSURE_SCHEMA_LOCK} on `conn` (the lock is CONNECTION-level, so the caller MUST then run all the
|
|
62
|
-
* serialized work on this SAME connection and release with {@link releaseEnsureSchemaLock}).
|
|
63
|
-
*
|
|
62
|
+
* serialized work on this SAME connection and release with {@link releaseEnsureSchemaLock}). Resolves once the lock is
|
|
63
|
+
* held. Exported so test setup that does ad-hoc DDL (e.g. a DROP-then-recreate) can serialize against
|
|
64
64
|
* ensureSchema runs using the IDENTICAL lock.
|
|
65
65
|
*
|
|
66
66
|
* Under heavy concurrency (the integration suite fans ~20 callers at the SAME named lock; or a fleet boots N
|
|
67
67
|
* replicas at once) a BLOCKING GET_LOCK(name, 30) would park ~19 sessions in a pessimistic WAIT on TiDB's advisory-
|
|
68
68
|
* lock row — which both exhausts TiDB's "pessimistic lock retry limit" (surfacing as a thrown error) AND starves the
|
|
69
|
-
* app's OWN `SELECT … FOR UPDATE` paths (image-bake admission/lease) of pessimistic-lock budget. So
|
|
70
|
-
* NON-BLOCKING (GET_LOCK(name, 0) returns 0 immediately if held) and
|
|
69
|
+
* app's OWN `SELECT … FOR UPDATE` paths (image-bake admission/lease) of pessimistic-lock budget. So the lock is taken
|
|
70
|
+
* NON-BLOCKING (GET_LOCK(name, 0) returns 0 immediately if held) and POLLED with jittered backoff: one holder, the
|
|
71
71
|
* rest sleeping (not blocked in-DB). Polls until acquired (7.83.0: never degrades to unserialized — the [ref]
|
|
72
|
-
* `ADD INDEX` leg is not race-safe); a connection whose probe keeps throwing surfaces as a boot failure.
|
|
72
|
+
* `ADD INDEX` leg is not race-safe); a connection whose probe keeps throwing surfaces as a boot failure.
|
|
73
|
+
*
|
|
74
|
+
* The probe statement, the reading of its answer, the engine's "pessimistic lock retry limit reached" sentence (read as
|
|
75
|
+
* "somebody else is on the lock row" — the same fact as `got = 0`, NOT a broken connection) and the polling law all
|
|
76
|
+
* live in ONE place, `ensure-schema-lock-policy.ts`; every other lock in this repo (the adoption arc lock) is taken
|
|
77
|
+
* through the same acquirer. */
|
|
73
78
|
export declare function acquireEnsureSchemaLock(conn: PoolConnection, tag?: string): Promise<void>;
|
|
74
79
|
/** Release {@link ENSURE_SCHEMA_LOCK} on `conn` (best-effort — the lock also auto-frees when the connection closes). */
|
|
75
80
|
export declare function releaseEnsureSchemaLock(conn: PoolConnection, tag?: string): Promise<void>;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { writeLogText } from "../observability/logger.js";
|
|
2
1
|
import mysql from "mysql2/promise";
|
|
3
2
|
import { TIDB_APPROVAL_ASK_STATEMENTS } from "./approval-ask-store-sql.js";
|
|
4
3
|
import { TIDB_MEMORY_OPTOUT_GRANT_STATEMENTS } from "./memory-optout-grant-store-sql.js";
|
|
@@ -30,7 +29,10 @@ import { PERMISSION_RULE_INDEXES } from "./permission-rule-store-sql.js";
|
|
|
30
29
|
import { RETENTION_TOMBSTONE_INDEXES } from "../stores-sql/retention-store-sql.js";
|
|
31
30
|
import { RETENTION_LANE_INDEXES } from "./retention-lane-store-sql.js";
|
|
32
31
|
import { LEADER_RUN_INDEXES } from "./leader-run-store-sql.js";
|
|
33
|
-
import {
|
|
32
|
+
import { acquireAdvisoryLock, releaseAdvisoryLock } from "./ensure-schema-lock-policy.js";
|
|
33
|
+
import { SKILL_EXEMPTION_CUTOFF_ID, markIfAbsentSql, migrationMarkerDdl } from "./one-time-migration-marker.js";
|
|
34
|
+
import { replicaRegistrationDdl } from "./replica-registration.js";
|
|
35
|
+
import { servingRequirementDdl } from "./serving-requirement.js";
|
|
34
36
|
import { createCloseAwarePool } from "./sql-driver.js";
|
|
35
37
|
export function tidbPoolOptions(tidb) {
|
|
36
38
|
const { host, port, user, password, database, connectionLimit } = tidb;
|
|
@@ -149,6 +151,11 @@ export const SCHEMA_STATEMENTS = [
|
|
|
149
151
|
-- deliberately-absent idx_error_code note below.
|
|
150
152
|
error_code VARCHAR(64) NULL,
|
|
151
153
|
instance_id VARCHAR(64) NULL,
|
|
154
|
+
-- leg_id: the HOLDING LEG — minted at every claim (createRun = first leg, markResuming = the resuming leg) and handed to the claimer; a park
|
|
155
|
+
-- write lands only for the leg that holds the row (setSuspended / setNeedsReview CAS on it). instance_id says WHERE the live leg is (routing),
|
|
156
|
+
-- leg_id says WHICH leg it is. NULL = no holding leg on record (a row written before the column existed, or created by an earlier-version
|
|
157
|
+
-- replica; an earlier-version replica's resume claim leaves the column as it found it).
|
|
158
|
+
leg_id VARCHAR(36) NULL,
|
|
152
159
|
-- job_id (work-view correlation substrate): groups the runs of one logical task across BOTH client doors.
|
|
153
160
|
job_id VARCHAR(64) NULL,
|
|
154
161
|
-- source (credential-derived system identity, clay 2026-06-12): which door submitted the run
|
|
@@ -774,6 +781,9 @@ export const SCHEMA_STATEMENTS = [
|
|
|
774
781
|
pool VARCHAR(32) NOT NULL,
|
|
775
782
|
PRIMARY KEY (pool)
|
|
776
783
|
) COLLATE utf8mb4_bin`,
|
|
784
|
+
migrationMarkerDdl("mysql"),
|
|
785
|
+
replicaRegistrationDdl("mysql"),
|
|
786
|
+
servingRequirementDdl("mysql"),
|
|
777
787
|
...TIDB_APPROVAL_ASK_STATEMENTS,
|
|
778
788
|
...TIDB_MEMORY_OPTOUT_GRANT_STATEMENTS,
|
|
779
789
|
...TIDB_SESSION_CAPTURE_OPTOUT_STATEMENTS,
|
|
@@ -817,19 +827,18 @@ export const SCHEMA_STATEMENTS = [
|
|
|
817
827
|
...TIDB_RETENTION_TOMBSTONE_STATEMENTS,
|
|
818
828
|
];
|
|
819
829
|
export const ENSURE_SCHEMA_LOCK = "sema_ensure_schema";
|
|
830
|
+
const ENSURE_SCHEMA_LOCK_ID = { dialect: "mysql", name: ENSURE_SCHEMA_LOCK };
|
|
831
|
+
const lockConnOf = (conn) => ({
|
|
832
|
+
query: async (sql, params) => {
|
|
833
|
+
const [rows] = await conn.query(sql, params);
|
|
834
|
+
return { rows };
|
|
835
|
+
},
|
|
836
|
+
});
|
|
820
837
|
export async function acquireEnsureSchemaLock(conn, tag = "ensureSchema") {
|
|
821
|
-
await
|
|
822
|
-
const [rows] = await conn.query("SELECT GET_LOCK(?, 0) AS got", [ENSURE_SCHEMA_LOCK]);
|
|
823
|
-
return Number(rows[0]?.got) === 1;
|
|
824
|
-
}, { tag, label: `GET_LOCK('${ENSURE_SCHEMA_LOCK}')` });
|
|
838
|
+
await acquireAdvisoryLock(lockConnOf(conn), ENSURE_SCHEMA_LOCK_ID, tag);
|
|
825
839
|
}
|
|
826
840
|
export async function releaseEnsureSchemaLock(conn, tag = "ensureSchema") {
|
|
827
|
-
|
|
828
|
-
await conn.query("SELECT RELEASE_LOCK(?)", [ENSURE_SCHEMA_LOCK]);
|
|
829
|
-
}
|
|
830
|
-
catch (err) {
|
|
831
|
-
writeLogText("stderr", `[${tag}] RELEASE_LOCK('${ENSURE_SCHEMA_LOCK}') failed (lock auto-frees on connection close):`, err);
|
|
832
|
-
}
|
|
841
|
+
await releaseAdvisoryLock(lockConnOf(conn), ENSURE_SCHEMA_LOCK_ID, tag);
|
|
833
842
|
}
|
|
834
843
|
export const SCHEMA_INDEXES = [
|
|
835
844
|
...CENTRAL_SCHEMA_INDEXES,
|
|
@@ -861,6 +870,7 @@ export async function ensureSchema(pool) {
|
|
|
861
870
|
return Array.isArray(rows) ? rows : [];
|
|
862
871
|
});
|
|
863
872
|
await conn.query("INSERT IGNORE INTO image_bake_admit (pool) VALUES ('standard')");
|
|
873
|
+
await conn.query(markIfAbsentSql("mysql"), [SKILL_EXEMPTION_CUTOFF_ID, Date.now()]);
|
|
864
874
|
await ensureIndexes((text, params) => conn.query(text, params), "mysql", SCHEMA_INDEXES);
|
|
865
875
|
}
|
|
866
876
|
finally {
|