@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,7 +2,7 @@ import { redactErrorMessage, redactLedgerEventData, sealRunRowResult } from "../
|
|
|
2
2
|
import { outwardPlane } from "../terminal.js";
|
|
3
3
|
import { projectUsageStats, USAGE_SCAN_LIMIT } from "../usage-analytics.js";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
-
import { existsSync,
|
|
5
|
+
import { existsSync, readFileSync, readdirSync, renameSync, rmSync, statSync } from "node:fs";
|
|
6
6
|
import { randomBytes } from "node:crypto";
|
|
7
7
|
import { AppendLog, atomicWriteFile, ensureDir, isProcessLive, processFingerprint, sanitizePathComponent, sanitizeScope, writeThenLink } from "@sema-agent/core";
|
|
8
8
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
@@ -58,6 +58,9 @@ const PARK_ORPHAN_SETTLE_MS = 30_000;
|
|
|
58
58
|
export class RunStoreStrictHydrateError extends StoreBootRefusalError {
|
|
59
59
|
name = "RunStoreStrictHydrateError";
|
|
60
60
|
}
|
|
61
|
+
export function fileRunStoreDirsFor(root) {
|
|
62
|
+
return { runs: join(root, "runs"), active: join(root, "runs", "active"), tmp: join(root, "tmp"), spaceCommits: join(root, "space-commits") };
|
|
63
|
+
}
|
|
61
64
|
export class FileRunStore {
|
|
62
65
|
runsDir;
|
|
63
66
|
activeDir;
|
|
@@ -81,15 +84,16 @@ export class FileRunStore {
|
|
|
81
84
|
constructor(root, opts) {
|
|
82
85
|
this.logger = opts;
|
|
83
86
|
this.strictHydrate = opts?.strictHydrate === true;
|
|
84
|
-
|
|
85
|
-
this.
|
|
86
|
-
this.
|
|
87
|
+
const dirs = fileRunStoreDirsFor(root);
|
|
88
|
+
this.runsDir = dirs.runs;
|
|
89
|
+
this.activeDir = dirs.active;
|
|
90
|
+
this.tmpDir = dirs.tmp;
|
|
87
91
|
this.blobsDir = join(root, "run-blobs");
|
|
88
|
-
this.spaceCommitsDir =
|
|
92
|
+
this.spaceCommitsDir = dirs.spaceCommits;
|
|
89
93
|
this.spaceCommits = createInProcessSpaceCommitTable({
|
|
90
94
|
load: (spaceKey) => this.loadSpaceCommit(spaceKey),
|
|
91
95
|
save: (record) => {
|
|
92
|
-
|
|
96
|
+
ensureDir(this.spaceCommitsDir);
|
|
93
97
|
atomicWriteFile(this.tmpDir, this.spaceCommitPath(record.spaceKey), `${JSON.stringify(record)}\n`);
|
|
94
98
|
},
|
|
95
99
|
remove: (spaceKey) => rmSync(this.spaceCommitPath(spaceKey), { force: true }),
|
|
@@ -353,17 +357,21 @@ export class FileRunStore {
|
|
|
353
357
|
}
|
|
354
358
|
}
|
|
355
359
|
writeRunFile(r) {
|
|
356
|
-
|
|
360
|
+
ensureDir(this.runDir(r.taskId));
|
|
357
361
|
atomicWriteFile(this.tmpDir, this.runJsonPath(r.taskId), `${JSON.stringify(this.toDisk(r))}\n`);
|
|
358
362
|
}
|
|
359
|
-
persist(
|
|
360
|
-
this.writeRunFile(
|
|
361
|
-
this.runs.
|
|
363
|
+
persist(draft) {
|
|
364
|
+
this.writeRunFile(draft);
|
|
365
|
+
const live = this.runs.get(draft.taskId);
|
|
366
|
+
if (live === undefined)
|
|
367
|
+
this.runs.set(draft.taskId, draft);
|
|
368
|
+
else
|
|
369
|
+
Object.assign(live, draft);
|
|
362
370
|
}
|
|
363
371
|
eventLogFor(taskId) {
|
|
364
372
|
let log = this.eventLogs.get(taskId);
|
|
365
373
|
if (!log) {
|
|
366
|
-
|
|
374
|
+
ensureDir(this.runDir(taskId));
|
|
367
375
|
log = new AppendLog(this.eventsPath(taskId));
|
|
368
376
|
this.eventLogs.set(taskId, log);
|
|
369
377
|
}
|
|
@@ -434,15 +442,13 @@ export class FileRunStore {
|
|
|
434
442
|
const r = this.runs.get(taskId);
|
|
435
443
|
if (!r || r.objectivePreview !== null)
|
|
436
444
|
return;
|
|
437
|
-
this.
|
|
438
|
-
r.objectivePreview = preview;
|
|
445
|
+
this.persist({ ...r, objectivePreview: preview });
|
|
439
446
|
}
|
|
440
447
|
async requestCancel(taskId, owner) {
|
|
441
448
|
const r = this.runs.get(taskId);
|
|
442
449
|
if (!r || !ownerEq(r.owner, owner) || r.status !== "running")
|
|
443
450
|
return false;
|
|
444
|
-
r
|
|
445
|
-
this.persist(r);
|
|
451
|
+
this.persist({ ...r, cancelRequested: true });
|
|
446
452
|
return true;
|
|
447
453
|
}
|
|
448
454
|
async isCancelRequested(taskId, owner) {
|
|
@@ -453,8 +459,7 @@ export class FileRunStore {
|
|
|
453
459
|
const r = this.runs.get(taskId);
|
|
454
460
|
if (!r || !ownerEq(r.owner, owner) || r.status !== "running")
|
|
455
461
|
return false;
|
|
456
|
-
r
|
|
457
|
-
this.persist(r);
|
|
462
|
+
this.persist({ ...r, preemptRequested: true });
|
|
458
463
|
return true;
|
|
459
464
|
}
|
|
460
465
|
async isPreemptRequested(taskId, owner) {
|
|
@@ -463,10 +468,8 @@ export class FileRunStore {
|
|
|
463
468
|
}
|
|
464
469
|
async heartbeat(taskId, owner) {
|
|
465
470
|
const r = this.runs.get(taskId);
|
|
466
|
-
if (r && ownerEq(r.owner, owner) && r.status === "running")
|
|
467
|
-
r
|
|
468
|
-
this.persist(r);
|
|
469
|
-
}
|
|
471
|
+
if (r && ownerEq(r.owner, owner) && r.status === "running")
|
|
472
|
+
this.persist({ ...r, updatedAt: new Date() });
|
|
470
473
|
}
|
|
471
474
|
async appendEvent(taskId, seq, type, data) {
|
|
472
475
|
data = redactLedgerEventData(type, data);
|
|
@@ -569,12 +572,8 @@ export class FileRunStore {
|
|
|
569
572
|
}
|
|
570
573
|
let pending;
|
|
571
574
|
if (r.status === "running" || r.status === "suspended" || r.status === "needs_review") {
|
|
572
|
-
|
|
573
|
-
r
|
|
574
|
-
r.error = error;
|
|
575
|
-
r.errorCode = result === null ? null : (outwardPlane(result.terminal).errorCode ?? null);
|
|
576
|
-
r.updatedAt = new Date();
|
|
577
|
-
this.persist(r);
|
|
575
|
+
const errorCode = result === null ? null : (outwardPlane(result.terminal).errorCode ?? null);
|
|
576
|
+
this.persist({ ...r, status, result, error, errorCode, updatedAt: new Date() });
|
|
578
577
|
pending = {
|
|
579
578
|
runId: taskId,
|
|
580
579
|
sessionId: r.sessionId,
|
|
@@ -582,7 +581,7 @@ export class FileRunStore {
|
|
|
582
581
|
status,
|
|
583
582
|
resultTaskId: result?.taskId,
|
|
584
583
|
model: result?.model,
|
|
585
|
-
errorCode:
|
|
584
|
+
errorCode: errorCode ?? undefined,
|
|
586
585
|
errorMessage: (result === null ? undefined : outwardPlane(result.terminal).errorMessage) ?? error ?? undefined,
|
|
587
586
|
elapsedMs: Math.max(0, Date.now() - r.createdAt.getTime()),
|
|
588
587
|
};
|
|
@@ -597,33 +596,29 @@ export class FileRunStore {
|
|
|
597
596
|
const sealed = sealRunRowResult(result);
|
|
598
597
|
const r = this.runs.get(taskId);
|
|
599
598
|
if (r && (r.status === "running" || r.status === "suspended")) {
|
|
600
|
-
r
|
|
601
|
-
r.result = sealed;
|
|
602
|
-
r.updatedAt = new Date();
|
|
603
|
-
this.persist(r);
|
|
599
|
+
this.persist({ ...r, status: "suspended", result: sealed, updatedAt: new Date() });
|
|
604
600
|
}
|
|
605
601
|
}
|
|
606
602
|
async setNeedsReview(taskId, result) {
|
|
607
603
|
const sealed = sealRunRowResult(result);
|
|
608
604
|
const r = this.runs.get(taskId);
|
|
609
605
|
if (r && (r.status === "running" || r.status === "needs_review")) {
|
|
610
|
-
r
|
|
611
|
-
r.result = sealed;
|
|
612
|
-
r.updatedAt = new Date();
|
|
613
|
-
this.persist(r);
|
|
606
|
+
this.persist({ ...r, status: "needs_review", result: sealed, updatedAt: new Date() });
|
|
614
607
|
}
|
|
615
608
|
}
|
|
616
609
|
async markResuming(taskId, instanceId) {
|
|
617
610
|
const r = this.runs.get(taskId);
|
|
618
611
|
if (!r || (r.status !== "suspended" && r.status !== "needs_review"))
|
|
619
612
|
return false;
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
613
|
+
this.persist({
|
|
614
|
+
...r,
|
|
615
|
+
status: "running",
|
|
616
|
+
result: null,
|
|
617
|
+
instanceId,
|
|
618
|
+
cancelRequested: false,
|
|
619
|
+
preemptRequested: false,
|
|
620
|
+
updatedAt: new Date(),
|
|
621
|
+
});
|
|
627
622
|
return true;
|
|
628
623
|
}
|
|
629
624
|
async getActiveTaskId(sessionId) {
|
|
@@ -633,8 +628,7 @@ export class FileRunStore {
|
|
|
633
628
|
const r = this.runs.get(taskId);
|
|
634
629
|
if (this.active.get(sessionId) !== taskId || r === undefined || r.status !== "running")
|
|
635
630
|
return false;
|
|
636
|
-
r
|
|
637
|
-
this.persist(r);
|
|
631
|
+
this.persist({ ...r, updatedAt: new Date() });
|
|
638
632
|
write({ instanceId: r.instanceId });
|
|
639
633
|
return true;
|
|
640
634
|
}
|
|
@@ -806,12 +800,14 @@ export class FileRunStore {
|
|
|
806
800
|
let reaped = 0;
|
|
807
801
|
for (const r of this.runs.values()) {
|
|
808
802
|
if (r.status === "running" && pred(r)) {
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
803
|
+
this.persist({
|
|
804
|
+
...r,
|
|
805
|
+
status: "failed",
|
|
806
|
+
result: null,
|
|
807
|
+
error: reason,
|
|
808
|
+
errorCode: code,
|
|
809
|
+
updatedAt: new Date(),
|
|
810
|
+
});
|
|
815
811
|
reaped += 1;
|
|
816
812
|
}
|
|
817
813
|
}
|
|
@@ -829,12 +825,14 @@ export class FileRunStore {
|
|
|
829
825
|
orphans.push(r);
|
|
830
826
|
}
|
|
831
827
|
for (const r of orphans) {
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
828
|
+
this.persist({
|
|
829
|
+
...r,
|
|
830
|
+
status: "failed",
|
|
831
|
+
result: null,
|
|
832
|
+
error: RUN_ORPHANED_ERROR,
|
|
833
|
+
errorCode: RUN_HOLDER_DEATH_CODES.orphaned,
|
|
834
|
+
updatedAt: new Date(),
|
|
835
|
+
});
|
|
838
836
|
}
|
|
839
837
|
this.sweepClaims();
|
|
840
838
|
return orphans.length;
|
|
@@ -843,12 +841,14 @@ export class FileRunStore {
|
|
|
843
841
|
this.checkpointProbe = probe;
|
|
844
842
|
}
|
|
845
843
|
failExpiredPark(r) {
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
844
|
+
this.persist({
|
|
845
|
+
...r,
|
|
846
|
+
status: "failed",
|
|
847
|
+
result: null,
|
|
848
|
+
error: "approval expired before decision",
|
|
849
|
+
errorCode: "approval.expired",
|
|
850
|
+
updatedAt: new Date(),
|
|
851
|
+
});
|
|
852
852
|
}
|
|
853
853
|
async reapSuspended(olderThanMs) {
|
|
854
854
|
const probe = this.checkpointProbe;
|
|
@@ -16,10 +16,12 @@
|
|
|
16
16
|
* 一律问**店**:它能叫出名字的每一只桶,判据在桶里判(不在桶外按「谁可能有」预筛)。
|
|
17
17
|
* · SQL:规则表里的每一只桶(`listRuleBucketOwners`,按 `owner_key` 分页)。不从审批记录推 —— 收编把规则桶整桶改键到新身份、审批史留在旧身份名下,
|
|
18
18
|
* 从记录推出的属主集在收编之后漏掉新桶。
|
|
19
|
-
* · File
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
19
|
+
* · File:引擎 File 分区后端的列桶口一次答(`FileDurableRulePartitionProvider.listBucketOwners({ knownOwners })`):目录自己叫得出名字的属主(本机属主那只桶、
|
|
20
|
+
* 收编标记点名的身份 —— 收编把桶改名到一个没有任何导入记录点名的身份之后,那只桶照样被叫出来、被读),加上本店导入记录点名过的身份里桶文件在场的那些
|
|
21
|
+
* (`knownOwners` = `FileRuleApprovalRecordStore.importRecordOwners` 的身份名;`imported-cc` 只由导入记录派生,记录是只增日志;桶名由引擎的那一只摘要算,本仓不算)。
|
|
22
|
+
* **两者都叫不出属主的桶**(桶文件按属主名的单向摘要命名)本步读不到 —— 引擎在同一次答里给出它们的个数(`unnamedBuckets`),本步原样记进报告
|
|
23
|
+
* (`importedLayerRootBucketsUnnamed`),非零每次起服 warn 一行;它不是「空」,是本步的普查缺了这么多只。
|
|
24
|
+
* 一种店一个来源、一次答 ⇒ 属主不重(引擎:同名给两次、或收编标记也点了它,是一个属主;SQL:按 `owner_key` 分页,键唯一)。
|
|
23
25
|
*
|
|
24
26
|
* ## 写在哪里(一处)
|
|
25
27
|
* 墓碑经**这只桶自己的写面**落(`writerOf(partition).apply({ kind: "tighten-delete" })`,引擎的写面契约)—— SQL 两孪生走 `SqlDurableRulePartition` 的那只
|
|
@@ -63,14 +65,21 @@ export interface ImportedLayerRootBucketSkipped {
|
|
|
63
65
|
* 原句由店自己的披露口说,File 店的 `permission_rule_store_disclosure`、SQL 店的整桶拒句);写面拒的是闭集词,原样带。 */
|
|
64
66
|
readonly why: string;
|
|
65
67
|
}
|
|
66
|
-
/**
|
|
68
|
+
/** 本步记进收据账的三格(`OneTimeMigrationReport` 的三只键;前两格随提交追加,第三格在列桶那一刻落定)。 */
|
|
67
69
|
export interface ImportedLayerRootReadings {
|
|
68
70
|
importedLayerRootAllowsRetired: ImportedLayerRootAllowRetired[];
|
|
69
71
|
importedLayerRootBucketsSkipped: ImportedLayerRootBucketSkipped[];
|
|
72
|
+
/** 店在场却叫不出属主、本步因此没读的桶数(见头注「读哪些桶」;SQL 恒 0)。 */
|
|
73
|
+
importedLayerRootBucketsUnnamed: number;
|
|
70
74
|
}
|
|
71
|
-
/**
|
|
75
|
+
/** 一种店的桶普查(一次答):叫得出名字的属主,与在场却叫不出名字的桶数。 */
|
|
76
|
+
export interface RuleBucketCensus {
|
|
77
|
+
readonly owners: readonly RuleOwner[];
|
|
78
|
+
readonly unnamedBuckets: number;
|
|
79
|
+
}
|
|
80
|
+
/** 一种店交给本步的三样东西:它的桶普查(见头注「读哪些桶」)、它的 durable 分区后端(读桶、写墓碑)、它的整桶拒判别(见头注「失败方向」)。 */
|
|
72
81
|
export interface ImportedLayerRootRetirementSource {
|
|
73
|
-
candidateOwners(): Promise<
|
|
82
|
+
candidateOwners(): Promise<RuleBucketCensus>;
|
|
74
83
|
readonly durable: DurableRulePartitionProvider;
|
|
75
84
|
/** 这只读桶抛出物是不是店的唯一判官的**确定性**整桶拒(真 ⇒ 点名跳过、读下一只桶;假 ⇒ 原样抛、起服拒)。判的是读面**真往外交的**抛出物的类,不按文案。 */
|
|
76
85
|
isWholeBucketRefusal(e: unknown): boolean;
|
|
@@ -79,6 +88,6 @@ export interface ImportedLayerRootRetirementSource {
|
|
|
79
88
|
}
|
|
80
89
|
/** 判据(引擎 §5.14 那一句,逐字):这一行里该退役的 add;不选 ⇒ 空。 */
|
|
81
90
|
export declare function importedLayerRootAddsOf(row: PersistedRule): readonly RuleAdd[];
|
|
82
|
-
/** 跑一遍:读店叫得出名字的每只桶(`candidateOwners()
|
|
91
|
+
/** 跑一遍:读店叫得出名字的每只桶(`candidateOwners()` 一次答,见头注「读哪些桶」),退役判据选中的 add;叫不出名字的桶数记进 `into`。读数随每次提交记进 `into`。 */
|
|
83
92
|
export declare function retireImportedLayerRootAllows(source: ImportedLayerRootRetirementSource, into: ImportedLayerRootReadings): Promise<void>;
|
|
84
93
|
//# sourceMappingURL=imported-layer-root-retirement.d.ts.map
|
|
@@ -7,14 +7,10 @@ export function importedLayerRootAddsOf(row) {
|
|
|
7
7
|
return row.adds.filter((a) => a.origin === "imported-cc");
|
|
8
8
|
}
|
|
9
9
|
export async function retireImportedLayerRootAllows(source, into) {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
continue;
|
|
15
|
-
seen.add(ownerKey);
|
|
16
|
-
await retireInBucket(source, owner, ownerKey, into);
|
|
17
|
-
}
|
|
10
|
+
const census = await source.candidateOwners();
|
|
11
|
+
into.importedLayerRootBucketsUnnamed = census.unnamedBuckets;
|
|
12
|
+
for (const owner of census.owners)
|
|
13
|
+
await retireInBucket(source, owner, buildRuleOwnerKey(owner), into);
|
|
18
14
|
}
|
|
19
15
|
async function retireInBucket(source, owner, ownerKey, into) {
|
|
20
16
|
const durable = source.durable;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** 两方言的列类型词(键表对 {@link SqlDialect} 闭合:加一种方言 ⇒ 编译红)。 */
|
|
2
|
+
export declare const INBOX_PAYLOAD_COLUMN_TYPE: {
|
|
3
|
+
readonly mysql: "TEXT";
|
|
4
|
+
readonly pg: "TEXT";
|
|
5
|
+
};
|
|
6
|
+
/** 列定义(两方言 DDL 内插;存量库缺列由起服列册对账拒启,拒句里的 ALTER 由建表语句生成)。 */
|
|
7
|
+
export declare const INBOX_PAYLOAD_COLUMN: {
|
|
8
|
+
readonly name: "payload";
|
|
9
|
+
readonly mysql: "payload TEXT NULL";
|
|
10
|
+
readonly pg: "payload TEXT COLLATE \"C\"";
|
|
11
|
+
};
|
|
12
|
+
/** 收件条目 `payload` 的字节预算(UTF-8 字节,量最终 JSON)= 各方言 `payload` 列容量的最小值。 */
|
|
13
|
+
export declare const INBOX_PAYLOAD_MAX_BYTES: number;
|
|
14
|
+
//# sourceMappingURL=inbox-payload-column.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { TEXT_COLUMN_TYPE_MAX_BYTES } from "./text-column-capacity.js";
|
|
2
|
+
export const INBOX_PAYLOAD_COLUMN_TYPE = { mysql: "TEXT", pg: "TEXT" };
|
|
3
|
+
export const INBOX_PAYLOAD_COLUMN = {
|
|
4
|
+
name: "payload",
|
|
5
|
+
mysql: `payload ${INBOX_PAYLOAD_COLUMN_TYPE.mysql} NULL`,
|
|
6
|
+
pg: `payload ${INBOX_PAYLOAD_COLUMN_TYPE.pg} COLLATE "C"`,
|
|
7
|
+
};
|
|
8
|
+
const INBOX_PAYLOAD_COLUMN_MAX_BYTES = {
|
|
9
|
+
mysql: TEXT_COLUMN_TYPE_MAX_BYTES.mysql[INBOX_PAYLOAD_COLUMN_TYPE.mysql],
|
|
10
|
+
pg: TEXT_COLUMN_TYPE_MAX_BYTES.pg[INBOX_PAYLOAD_COLUMN_TYPE.pg],
|
|
11
|
+
};
|
|
12
|
+
export const INBOX_PAYLOAD_MAX_BYTES = Math.min(...Object.values(INBOX_PAYLOAD_COLUMN_MAX_BYTES));
|
|
13
|
+
//# sourceMappingURL=inbox-payload-column.js.map
|
|
@@ -11,6 +11,11 @@ export interface LocalCheckpointStoreOptions {
|
|
|
11
11
|
/** ctx 改写的认领栅栏({@link LocalCheckpointStore.rewriteCtxWhileClaimed}):同一数据根上的文件 run 店(进程内栅栏形)。缺席 ⇒ 那一口响亮抛(装配缺陷)。 */
|
|
12
12
|
claims?: InProcessClaimFence;
|
|
13
13
|
}
|
|
14
|
+
/** checkpoint 店在数据根下自己铸的目录(构造器与一次性迁移 M39 的名册同读这一只)。 */
|
|
15
|
+
export declare function localCheckpointStoreDirsFor(root: string): {
|
|
16
|
+
readonly ctx: string;
|
|
17
|
+
readonly tmp: string;
|
|
18
|
+
};
|
|
14
19
|
export declare class LocalCheckpointStore {
|
|
15
20
|
/** [ref] 车1:托管留存声明 —— **诚实的 none**(与 local session 店同一条判据:本店的行没有按期删除的腿;
|
|
16
21
|
* 留存三方法只实现在 SQL 聚合店上)。locked policy + 本店 ⇒ core 的门拒启,那是契约的正确行为。 */
|
|
@@ -3,14 +3,14 @@ import { denySweepOwns, parkedApprovalCard } from "../approval-content-kind.js";
|
|
|
3
3
|
import { parkRowFacts, skillCardFacts } from "../approval-card.js";
|
|
4
4
|
import { durableRowIdentity } from "../checkpoint-identity.js";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
|
-
import { existsSync, readFileSync, readdirSync, unlinkSync
|
|
6
|
+
import { existsSync, readFileSync, readdirSync, unlinkSync } from "node:fs";
|
|
7
7
|
import { join } from "node:path";
|
|
8
|
-
import { CHECKPOINT_LIST_LIMITS, FileCheckpointStore, atomicWriteFile, executionVerdict, sanitizePathComponent, } from "@sema-agent/core";
|
|
8
|
+
import { CHECKPOINT_LIST_LIMITS, FileCheckpointStore, atomicWriteFile, ensureDir, executionVerdict, sanitizePathComponent, } from "@sema-agent/core";
|
|
9
9
|
import { approvalPayloadFingerprint } from "./approval-payload-fingerprint.js";
|
|
10
10
|
import { approvalDecisionOfWinner, boundedRuleOffers, boundedToolInput, candidateIdentityOf, pendingRowPrecedes, queueRowGateKind, TERMINAL_BACKSTOP_MS, TERMINAL_GRACE_MS } from "./checkpoint-store-face.js";
|
|
11
11
|
import { quarantineUnreadableSidecar } from "./local-sidecar-quarantine.js";
|
|
12
12
|
import { createZodColumnReader, decodeJsonColumn, foldJsonColumn, readStringArrayColumn } from "./sql-json-column.js";
|
|
13
|
-
import { UNMANAGED_RETENTION } from "./retention-
|
|
13
|
+
import { UNMANAGED_RETENTION } from "./retention-declaration.js";
|
|
14
14
|
import { assertJsonColumnWritable, createObjectColumnReader } from "./sql-json-column.js";
|
|
15
15
|
import { FENCE_LANDED } from "./store-contracts.js";
|
|
16
16
|
function terminalAtOf(cp) {
|
|
@@ -47,6 +47,9 @@ function refusingCtx(sessionId, read) {
|
|
|
47
47
|
throw foldJsonColumn(e, (m) => `LocalCheckpointStore: ${m} — refusing rather than serve a resume context nobody can read (session ${JSON.stringify(sessionId)})`);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
+
export function localCheckpointStoreDirsFor(root) {
|
|
51
|
+
return { ctx: join(root, "checkpoint-ctx"), tmp: join(root, ".tmp") };
|
|
52
|
+
}
|
|
50
53
|
export class LocalCheckpointStore {
|
|
51
54
|
retention = UNMANAGED_RETENTION;
|
|
52
55
|
durability = "durable";
|
|
@@ -65,10 +68,11 @@ export class LocalCheckpointStore {
|
|
|
65
68
|
this.opts = opts;
|
|
66
69
|
this.scopesPath = join(root, "checkpoint-scopes.json");
|
|
67
70
|
this.sessionTokensPath = join(root, "checkpoint-session-tokens.json");
|
|
68
|
-
|
|
69
|
-
this.
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
const dirs = localCheckpointStoreDirsFor(root);
|
|
72
|
+
this.ctxDir = dirs.ctx;
|
|
73
|
+
this.tmpDir = dirs.tmp;
|
|
74
|
+
ensureDir(this.ctxDir);
|
|
75
|
+
ensureDir(this.tmpDir);
|
|
72
76
|
if (existsSync(this.scopesPath)) {
|
|
73
77
|
try {
|
|
74
78
|
for (const s of decodeJsonColumn(readFileSync(this.scopesPath, "utf8"), readScopeRegistry, "checkpoint-scopes.json (the local scope registry)"))
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** 披露码:路径(含数据根自身、名册目录的子项)经符号链接 —— 不跟,这一条不走(「不在根内」一类,不按链接指向哪里特判)。 */
|
|
2
|
+
export declare const SYMLINK_IN_PATH = "SYMLINK_IN_PATH";
|
|
3
|
+
/**
|
|
4
|
+
* 本迁移看的两只根:数据根(`LocalBackend` 持锁的那一只物理路径 —— core `resolveDataRoot` 的 `physicalPathOf` 拼写 = 店构造时拿到的值;身份核拿它当「根内」的唯一判据,
|
|
5
|
+
* 不是物理拼写的值 ⇒ 每一只目录都过不了核、逐个进披露行)与记忆引擎根(boot 的 `memoryEngineRootFor` 推导,同步游标在它下面;
|
|
6
|
+
* 调用方先把它换成与数据根同一种拼写 —— 见 `LocalBackend` 的 `dataDirLayout`)。名册包含关系按字面判:引擎根经数据根之外的别名拼写 ⇒ 当作在数据根之外(不进名册)。
|
|
7
|
+
*/
|
|
8
|
+
export interface DataDirLayout {
|
|
9
|
+
readonly dataRoot: string;
|
|
10
|
+
readonly memoryEngineRoot: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 布局只在这里铸一次(`LocalBackend` 取锁之后调):数据根 = 持锁的物理路径(配置里的拼写若经链接,事后改指也不影响);
|
|
14
|
+
* 记忆引擎根落在配置拼写的数据根之下 ⇒ 换成物理拼写(同一只目录只认一种拼写),否则原样(在数据根之外,名册不收)。
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildDataDirLayout(a: {
|
|
17
|
+
readonly configuredRoot: string;
|
|
18
|
+
readonly physicalRoot: string;
|
|
19
|
+
readonly memoryEngineRoot: string;
|
|
20
|
+
}): DataDirLayout;
|
|
21
|
+
export interface DataDirModeRefusal {
|
|
22
|
+
/** 相对数据根的路径。 */
|
|
23
|
+
readonly path: string;
|
|
24
|
+
/** 错误码(`EPERM` / `EACCES` / `ESTALE` / …)或 {@link SYMLINK_IN_PATH};没有码的错误记 `UNKNOWN`。 */
|
|
25
|
+
readonly code: string;
|
|
26
|
+
}
|
|
27
|
+
export interface DataDirModeReading {
|
|
28
|
+
/** 本次收紧成 0o700 的目录(相对数据根)。 */
|
|
29
|
+
readonly tightened: readonly string[];
|
|
30
|
+
/** 本次没能收紧 / 没能看见 / 没有走的目录。 */
|
|
31
|
+
readonly refused: readonly DataDirModeRefusal[];
|
|
32
|
+
}
|
|
33
|
+
/** 两只日志座:成功提示与失败披露各一(失败那只由调用方接**不可缺席**的口)。 */
|
|
34
|
+
export interface DataDirModeSinks {
|
|
35
|
+
readonly tightened: (msg: string, meta: Record<string, unknown>) => void;
|
|
36
|
+
readonly refused: (msg: string, meta: Record<string, unknown>) => void;
|
|
37
|
+
}
|
|
38
|
+
/** 测试座:收紧动作(默认对过了身份核的 fd `fchmod`)与平台(默认 `IS_WIN32`)。 */
|
|
39
|
+
export interface DataDirModeSeats {
|
|
40
|
+
readonly fchmod?: (fd: number, mode: number, rel: string) => void;
|
|
41
|
+
readonly win32?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 把数据根下名册里的 0755 店目录一次收紧成 0o700。起服时调(`LocalBackend.runOneTimeMigrations`,任何读者之前);数据根独占 ⇒ 没有滚动升级窗,不需要读侧半场。
|
|
45
|
+
* 失败不抛(见头注);读数也由两只日志座打出。
|
|
46
|
+
*/
|
|
47
|
+
export declare function tightenLocalDataDirModes(layout: DataDirLayout, sinks: DataDirModeSinks, seats?: DataDirModeSeats): DataDirModeReading;
|
|
48
|
+
//# sourceMappingURL=local-data-dir-modes-m39.d.ts.map
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { closeSync, constants as FS, fchmodSync, fstatSync, lstatSync, openSync, readdirSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
3
|
+
import { physicalPathOf } from "@sema-agent/core";
|
|
4
|
+
import { IS_WIN32 } from "./host-platform.js";
|
|
5
|
+
import { fileRunStoreDirsFor } from "./file-run-store.js";
|
|
6
|
+
import { localCheckpointStoreDirsFor } from "./local-checkpoint-store.js";
|
|
7
|
+
import { attachmentStoreDirFor } from "./local-task-attachment-store.js";
|
|
8
|
+
import { scratchpadRootFor } from "../env-facts.js";
|
|
9
|
+
import { pluginCacheRootFor } from "../capabilities/center-plugins.js";
|
|
10
|
+
import { memorySyncCursorDirFor } from "../memory-sync-client.js";
|
|
11
|
+
const DIR_MODE = 0o700;
|
|
12
|
+
const GROUP_OTHER_BITS = 0o077;
|
|
13
|
+
const TIGHTENED_EXAMPLES = 5;
|
|
14
|
+
const REFUSED_LISTED = 10;
|
|
15
|
+
export const SYMLINK_IN_PATH = "SYMLINK_IN_PATH";
|
|
16
|
+
export function buildDataDirLayout(a) {
|
|
17
|
+
const rel = relative(resolve(a.configuredRoot), resolve(a.memoryEngineRoot));
|
|
18
|
+
const underConfigured = rel === "" || (rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel));
|
|
19
|
+
return { dataRoot: a.physicalRoot, memoryEngineRoot: underConfigured ? join(a.physicalRoot, rel) : a.memoryEngineRoot };
|
|
20
|
+
}
|
|
21
|
+
function rosterFor(layout) {
|
|
22
|
+
const run = fileRunStoreDirsFor(layout.dataRoot);
|
|
23
|
+
const checkpoint = localCheckpointStoreDirsFor(layout.dataRoot);
|
|
24
|
+
return [
|
|
25
|
+
{ abs: run.runs, children: 1 },
|
|
26
|
+
{ abs: run.tmp, children: 0 },
|
|
27
|
+
{ abs: run.spaceCommits, children: 0 },
|
|
28
|
+
{ abs: checkpoint.ctx, children: 0 },
|
|
29
|
+
{ abs: checkpoint.tmp, children: 0 },
|
|
30
|
+
{ abs: attachmentStoreDirFor(layout.dataRoot), children: 0 },
|
|
31
|
+
{ abs: scratchpadRootFor(layout.dataRoot), children: 1 },
|
|
32
|
+
{ abs: pluginCacheRootFor(layout.dataRoot), children: 2 },
|
|
33
|
+
{ abs: memorySyncCursorDirFor(layout.memoryEngineRoot), children: 0 },
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
function segmentsUnder(root, abs) {
|
|
37
|
+
const rel = relative(resolve(root), resolve(abs));
|
|
38
|
+
if (rel === "" || rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel))
|
|
39
|
+
return undefined;
|
|
40
|
+
return rel.split(sep);
|
|
41
|
+
}
|
|
42
|
+
const codeOf = (e) => (typeof e === "object" && e !== null && "code" in e && typeof e.code === "string" ? e.code : "UNKNOWN");
|
|
43
|
+
const emit = (sink, msg, meta) => {
|
|
44
|
+
try {
|
|
45
|
+
sink(msg, meta);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
console.warn(msg, meta);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const sameObject = (a, b) => a.dev === b.dev && a.ino === b.ino;
|
|
52
|
+
function inRootBreak(root, segs, fd) {
|
|
53
|
+
try {
|
|
54
|
+
const held = fstatSync(fd, { bigint: true });
|
|
55
|
+
const physical = physicalPathOf(join(root, ...segs));
|
|
56
|
+
if (segmentsUnder(root, physical) === undefined)
|
|
57
|
+
return SYMLINK_IN_PATH;
|
|
58
|
+
if (!sameObject(lstatSync(physical, { bigint: true }), held))
|
|
59
|
+
return "ESTALE";
|
|
60
|
+
for (let i = 0; i <= segs.length; i += 1) {
|
|
61
|
+
const st = lstatSync(join(root, ...segs.slice(0, i)), { bigint: true });
|
|
62
|
+
if (st.isSymbolicLink())
|
|
63
|
+
return SYMLINK_IN_PATH;
|
|
64
|
+
if (!st.isDirectory())
|
|
65
|
+
return "ESTALE";
|
|
66
|
+
}
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
return codeOf(e);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export function tightenLocalDataDirModes(layout, sinks, seats = {}) {
|
|
74
|
+
if (seats.win32 ?? IS_WIN32)
|
|
75
|
+
return { tightened: [], refused: [] };
|
|
76
|
+
const fchmod = seats.fchmod ?? ((fd, mode) => fchmodSync(fd, mode));
|
|
77
|
+
const root = layout.dataRoot;
|
|
78
|
+
const tightened = [];
|
|
79
|
+
const refused = [];
|
|
80
|
+
const refuse = (rel, code) => {
|
|
81
|
+
if (code !== "ENOENT")
|
|
82
|
+
refused.push({ path: rel, code });
|
|
83
|
+
};
|
|
84
|
+
const tighten = (segs, rel) => {
|
|
85
|
+
let fd;
|
|
86
|
+
try {
|
|
87
|
+
fd = openSync(join(root, ...segs), FS.O_RDONLY | FS.O_DIRECTORY | FS.O_NOFOLLOW);
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
refuse(rel, codeOf(e));
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const broken = inRootBreak(root, segs, fd);
|
|
95
|
+
if (broken !== undefined) {
|
|
96
|
+
refuse(rel, broken);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
fchmod(fd, DIR_MODE, rel);
|
|
100
|
+
tightened.push(rel);
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
refuse(rel, codeOf(e));
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
closeSync(fd);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const step = (parent, name, more, depth) => {
|
|
110
|
+
const segs = [...parent, name];
|
|
111
|
+
const rel = join(...segs);
|
|
112
|
+
let mode;
|
|
113
|
+
try {
|
|
114
|
+
const st = lstatSync(join(root, ...segs));
|
|
115
|
+
if (st.isSymbolicLink()) {
|
|
116
|
+
refused.push({ path: rel, code: SYMLINK_IN_PATH });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (!st.isDirectory())
|
|
120
|
+
return;
|
|
121
|
+
mode = st.mode;
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
refuse(rel, codeOf(e));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const [next, ...rest] = more;
|
|
128
|
+
if (next !== undefined) {
|
|
129
|
+
step(segs, next, rest, depth);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if ((mode & GROUP_OTHER_BITS) !== 0)
|
|
133
|
+
tighten(segs, rel);
|
|
134
|
+
if (depth === 0)
|
|
135
|
+
return;
|
|
136
|
+
let entries;
|
|
137
|
+
try {
|
|
138
|
+
entries = readdirSync(join(root, ...segs), { withFileTypes: true });
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
refuse(rel, codeOf(e));
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
for (const entry of entries) {
|
|
145
|
+
if (entry.isDirectory() || entry.isSymbolicLink())
|
|
146
|
+
step(segs, entry.name, [], depth - 1);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
let rootIntact = false;
|
|
150
|
+
try {
|
|
151
|
+
if (lstatSync(root).isSymbolicLink())
|
|
152
|
+
refused.push({ path: ".", code: SYMLINK_IN_PATH });
|
|
153
|
+
else
|
|
154
|
+
rootIntact = true;
|
|
155
|
+
}
|
|
156
|
+
catch (e) {
|
|
157
|
+
refuse(".", codeOf(e));
|
|
158
|
+
}
|
|
159
|
+
for (const { abs, children } of rootIntact ? rosterFor(layout) : []) {
|
|
160
|
+
const [first, ...rest] = segmentsUnder(root, abs) ?? [];
|
|
161
|
+
if (first !== undefined)
|
|
162
|
+
step([], first, rest, children);
|
|
163
|
+
}
|
|
164
|
+
if (refused.length > 0) {
|
|
165
|
+
emit(sinks.refused, "local_data_dir_mode_refused", {
|
|
166
|
+
count: refused.length,
|
|
167
|
+
mode: "0700",
|
|
168
|
+
entries: refused.slice(0, REFUSED_LISTED),
|
|
169
|
+
remedy: "these directories (relative to the data root) could not be tightened or read, or are reached through a symbolic link (SYMLINK_IN_PATH: links are never followed, the data root itself included) — as the owner of the real directory run `chmod 700` on it (or chown it to the server's user) and restart; the server keeps serving meanwhile",
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
if (tightened.length > 0) {
|
|
173
|
+
emit(sinks.tightened, "local_data_dir_modes_tightened", {
|
|
174
|
+
count: tightened.length,
|
|
175
|
+
mode: "0700",
|
|
176
|
+
examples: tightened.slice(0, TIGHTENED_EXAMPLES),
|
|
177
|
+
note: "store directories created by earlier versions with the default mode were tightened to 0700 once; later boots find them tight",
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
return { tightened, refused };
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=local-data-dir-modes-m39.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** marker 的文件名(数据根顶层;公开契约)。 */
|
|
2
|
+
export declare const ENGINE_HIGH_WATER_FILE = "engine-high-water.json";
|
|
3
|
+
/**
|
|
4
|
+
* **判与抬**(唯一的座;唯一调用点 `openLocalBackend`,数据根锁在手、本仓任何一只店建起之前):
|
|
5
|
+
* ① 本构建版本 `engine` 按发布线读不出({@link buildReleaseTriple})⇒ 抛 {@link StoreBootRefusalError}(marker 不读、不写);
|
|
6
|
+
* ② 读 `<root>/engine-high-water.json`:读不出 / 高水位高于本构建 ⇒ 抛 {@link LocalDataRootSchemaMismatchError}(`boot` 形;文件原地不动,不抬);
|
|
7
|
+
* ③ 缺席或低于本构建 ⇒ 原子写 `{"highWater": <本构建的纯三段>}`(`required`);相等 ⇒ 不写,只过持久化屏障(读到的可能是上一次没证完的那份)。写不进 / 证不了 ⇒ 抛(点名路径与原因)。
|
|
8
|
+
* 同步:它在后端打开的同步段里跑(建店之前),拒在这里就不会有一只店被建起。
|
|
9
|
+
*/
|
|
10
|
+
export declare function holdEngineHighWater(root: string, engine: string): void;
|
|
11
|
+
//# sourceMappingURL=local-engine-high-water.d.ts.map
|