@sema-agent/server 7.150.0 → 7.151.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +185 -0
- package/USAGE.md +53 -25
- package/deploy/sema-up/README.md +7 -1
- package/deploy/sema-up/chart/Chart.yaml +1 -1
- package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
- package/deploy/sema-up/chart/templates/server.yaml +5 -3
- package/deploy/sema-up/chart/values-full-single.yaml +3 -1
- package/deploy/sema-up/chart/values.yaml +8 -1
- package/deploy/sema-up/cluster-up.sh +1 -0
- package/deploy/sema-up/kube-up.sh +1 -1
- package/deploy/sema-up/lib/flagshape.sh +1 -1
- package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
- package/deploy/sema-up/lib/helm-values-kube.py +2 -0
- package/dist/adoption/import.js +3 -3
- package/dist/approval-ask-machine.d.ts +1 -1
- package/dist/approval-card.d.ts +2 -2
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/auth-bridge.d.ts +20 -0
- package/dist/auth-bridge.js +9 -0
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/bake-runner/main.d.ts +4 -2
- package/dist/bind-host.d.ts +2 -3
- package/dist/bind-host.js +2 -4
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/engine-lease.d.ts +5 -0
- package/dist/boot/engine-lease.js +1 -0
- package/dist/boot/execution-env.d.ts +8 -14
- package/dist/boot/execution-env.js +54 -17
- package/dist/boot/execution-lane.js +32 -5
- package/dist/boot/late-binds.d.ts +8 -4
- package/dist/boot/late-binds.js +7 -1
- package/dist/boot/memory-consolidation.d.ts +3 -2
- package/dist/boot/memory-consolidation.js +6 -6
- package/dist/boot/reapers.d.ts +5 -0
- package/dist/boot/reapers.js +12 -1
- package/dist/boot/resolve-spec.d.ts +3 -3
- package/dist/boot/resolve-spec.js +31 -22
- package/dist/boot/runner-deps.d.ts +9 -2
- package/dist/boot/runner-deps.js +3 -3
- package/dist/boot/session-age-out.d.ts +36 -0
- package/dist/boot/session-age-out.js +101 -0
- package/dist/boot/session-faces.d.ts +5 -14
- package/dist/boot/session-faces.js +9 -5
- package/dist/boot/stage-01-config.js +2 -0
- package/dist/boot/stage-05-execution-env.d.ts +5 -3
- package/dist/boot/stage-05-execution-env.js +2 -2
- package/dist/boot/stage-06-runners.d.ts +7 -4
- package/dist/boot/stage-06-runners.js +15 -6
- package/dist/boot/stage-07-capability-layer.d.ts +7 -4
- package/dist/boot/stage-07-capability-layer.js +2 -1
- package/dist/boot/stage-08-reapers.d.ts +7 -4
- package/dist/boot/stage-08-reapers.js +4 -2
- package/dist/boot/stage-09-leader.d.ts +11 -5
- package/dist/boot/stage-09-leader.js +12 -3
- package/dist/boot/stage-10-http-server.d.ts +11 -5
- package/dist/boot/stage-10-http-server.js +3 -6
- package/dist/boot/web-admin.js +3 -1
- package/dist/boot/workflow-orchestration.d.ts +7 -2
- package/dist/boot/workflow-orchestration.js +24 -7
- package/dist/bounded-rotation.d.ts +29 -0
- package/dist/bounded-rotation.js +24 -0
- package/dist/capability-facts.d.ts +22 -13
- package/dist/capability-facts.js +28 -18
- package/dist/center-credential.d.ts +25 -6
- package/dist/center-credential.js +25 -5
- package/dist/config-catalog.d.ts +26 -7
- package/dist/config-catalog.js +14 -11
- package/dist/config-invariants.d.ts +2 -1
- package/dist/config-invariants.js +4 -4
- package/dist/config-types.d.ts +10 -4
- package/dist/config.d.ts +51 -2
- package/dist/config.js +35 -24
- package/dist/deployment-shape.d.ts +9 -1
- package/dist/deployment-shape.js +2 -1
- package/dist/device-protocol.d.ts +5 -4
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.js +3 -2
- package/dist/device-ws-protocol.d.ts +63 -10
- package/dist/device-ws-protocol.js +56 -25
- package/dist/engine-identity.d.ts +19 -7
- package/dist/engine-identity.js +10 -2
- package/dist/entry-mode-clamp-notice.d.ts +2 -1
- package/dist/execution-env-refusal.d.ts +23 -0
- package/dist/execution-env-refusal.js +5 -0
- package/dist/execution-lane-caps.d.ts +3 -1
- package/dist/field-conflict.d.ts +1 -1
- package/dist/file-history-capture.d.ts +11 -4
- package/dist/file-history-capture.js +9 -6
- package/dist/file-history-disclosure.d.ts +7 -5
- package/dist/file-history-disclosure.js +7 -5
- package/dist/fleet/drain-entry.d.ts +4 -0
- package/dist/hooks/hook-runner.js +2 -2
- package/dist/host-lsp-manager.d.ts +2 -2
- package/dist/http/admission.js +17 -2
- package/dist/http/approval-sweeps.js +5 -5
- package/dist/http/checkpoint-ctx.d.ts +2 -0
- package/dist/http/checkpoint-ctx.js +1 -0
- package/dist/http/dispatch.d.ts +2 -1
- package/dist/http/dispatch.js +34 -27
- package/dist/http/durable-run-leg.js +16 -16
- package/dist/http/health-self-report.d.ts +9 -1
- package/dist/http/health-self-report.js +2 -0
- package/dist/http/owner-access.d.ts +31 -11
- package/dist/http/owner-access.js +37 -6
- package/dist/http/resume-ctx-read.js +25 -3
- package/dist/http/resume-legs.d.ts +2 -1
- package/dist/http/resume-legs.js +259 -79
- package/dist/http/route-ctx.d.ts +18 -8
- package/dist/http/route-table.d.ts +1 -1
- package/dist/http/routes/admin-memory-optout.d.ts +1 -1
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.js +4 -3
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/capabilities.js +8 -5
- package/dist/http/routes/fleet.js +10 -8
- package/dist/http/routes/projects.d.ts +3 -2
- package/dist/http/routes/projects.js +4 -5
- package/dist/http/routes/runs.js +102 -36
- package/dist/http/routes/session-sync.d.ts +4 -3
- package/dist/http/routes/session-sync.js +172 -77
- package/dist/http/routes/sessions-list.js +13 -7
- package/dist/http/routes/sessions.js +10 -6
- package/dist/http/routes/tasks.js +30 -16
- package/dist/http/routes/trace-usage.js +2 -2
- package/dist/http/server.d.ts +21 -27
- package/dist/http/server.js +2 -2
- package/dist/http/submit-ctx.js +5 -4
- package/dist/http/wire-types.d.ts +14 -4
- package/dist/identity-source.d.ts +20 -3
- package/dist/identity-source.js +14 -0
- package/dist/index.d.ts +4 -0
- package/dist/lane-home-probe.d.ts +3 -7
- package/dist/lane-home-probe.js +0 -1
- package/dist/leader/leader.d.ts +2 -1
- package/dist/leg-facts.d.ts +13 -5
- package/dist/leg-facts.js +2 -1
- package/dist/memory-scope.d.ts +5 -4
- package/dist/memory-scope.js +4 -4
- package/dist/memory-sync-client.d.ts +30 -2
- package/dist/memory-sync-client.js +16 -9
- package/dist/observability/err-text.d.ts +7 -0
- package/dist/observability/err-text.js +5 -0
- package/dist/observability/fail-open.d.ts +7 -3
- package/dist/observability/fail-open.js +7 -3
- package/dist/observability/metrics.js +1 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
- package/dist/orchestration/workflow-notify-journal.js +12 -1
- package/dist/orchestration/workflow-park-decision.d.ts +70 -18
- package/dist/orchestration/workflow-park-decision.js +49 -10
- package/dist/orchestration/workflow-park-holder.d.ts +65 -0
- package/dist/orchestration/workflow-park-holder.js +98 -0
- package/dist/orchestration/workflow-record-fence.d.ts +36 -0
- package/dist/orchestration/workflow-record-fence.js +42 -0
- package/dist/owner-faces.d.ts +1 -1
- package/dist/parked-decide.d.ts +104 -53
- package/dist/parked-decide.js +153 -117
- package/dist/peer-directory.d.ts +2 -2
- package/dist/peer-inbound-face.d.ts +2 -6
- package/dist/peer-inbound-face.js +0 -3
- package/dist/permission-mode-admission.d.ts +41 -5
- package/dist/permission-mode-admission.js +29 -3
- package/dist/plugins/adoption-log-sql.d.ts +3 -1
- package/dist/plugins/adoption-log-sql.js +7 -1
- package/dist/plugins/approval-ask-store-file.d.ts +10 -2
- package/dist/plugins/approval-ask-store-file.js +8 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +6 -1
- package/dist/plugins/approval-ask-store-memory.js +28 -9
- package/dist/plugins/approval-ask-store-sql.d.ts +43 -2
- package/dist/plugins/approval-ask-store-sql.js +34 -5
- package/dist/plugins/approval-exemption-store.js +3 -0
- package/dist/plugins/approval-nonce-store.js +2 -0
- package/dist/plugins/breaker-state-sql.js +2 -0
- package/dist/plugins/caching-session-store.d.ts +9 -15
- package/dist/plugins/caching-session-store.js +6 -0
- package/dist/plugins/device-store-sql.js +6 -0
- package/dist/plugins/error-origin.d.ts +18 -0
- package/dist/plugins/error-origin.js +10 -0
- package/dist/plugins/execution-placement-sql.js +6 -6
- package/dist/plugins/image-bake-store-sql.js +6 -0
- package/dist/plugins/image-index-sql.js +4 -0
- package/dist/plugins/landed-attendants.d.ts +212 -0
- package/dist/plugins/landed-attendants.js +161 -0
- package/dist/plugins/leader-run-store-sql.js +4 -0
- package/dist/plugins/local-session-live-reference.d.ts +40 -0
- package/dist/plugins/local-session-live-reference.js +39 -0
- package/dist/plugins/local-session-store.d.ts +71 -33
- package/dist/plugins/local-session-store.js +129 -27
- package/dist/plugins/memory-engine-pg.js +4 -0
- package/dist/plugins/memory-engine-sql-apply.js +5 -2
- package/dist/plugins/memory-engine-tidb.js +4 -0
- package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
- package/dist/plugins/memory-sync-store-pg.js +5 -0
- package/dist/plugins/memory-sync-store-tidb.js +5 -0
- package/dist/plugins/one-time-migrations.d.ts +57 -63
- package/dist/plugins/one-time-migrations.js +162 -90
- package/dist/plugins/org-delivery-quota-store.js +4 -1
- package/dist/plugins/outcome-ledger-sql.js +2 -0
- package/dist/plugins/permission-rule-store-sql.js +11 -4
- package/dist/plugins/pg-cost-quota.js +4 -0
- package/dist/plugins/pg-pool.js +24 -1
- package/dist/plugins/pg-rate-limiter.js +2 -0
- package/dist/plugins/posix-shell-fs.d.ts +6 -1
- package/dist/plugins/posix-shell-fs.js +4 -1
- package/dist/plugins/remote-env-adb.d.ts +19 -15
- package/dist/plugins/remote-env-adb.js +41 -15
- package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
- package/dist/plugins/remote-env-connect-seat.js +72 -0
- package/dist/plugins/remote-env-device.d.ts +22 -5
- package/dist/plugins/remote-env-device.js +106 -8
- package/dist/plugins/remote-env-e2b.d.ts +15 -6
- package/dist/plugins/remote-env-e2b.js +42 -32
- package/dist/plugins/remote-env-file-error.js +6 -2
- package/dist/plugins/remote-env-host.d.ts +17 -0
- package/dist/plugins/remote-env-host.js +30 -38
- package/dist/plugins/remote-env-k8s.d.ts +41 -39
- package/dist/plugins/remote-env-k8s.js +53 -30
- package/dist/plugins/remote-env-local-docker.d.ts +13 -8
- package/dist/plugins/remote-env-local-docker.js +34 -41
- package/dist/plugins/remote-env-ssh.d.ts +18 -12
- package/dist/plugins/remote-env-ssh.js +60 -59
- package/dist/plugins/remote-shell.d.ts +98 -1
- package/dist/plugins/remote-shell.js +218 -0
- package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
- package/dist/plugins/resume-anchor-store-sql.js +12 -5
- package/dist/plugins/retention-lane-store-sql.js +4 -0
- package/dist/plugins/retention-sql.d.ts +20 -2
- package/dist/plugins/retention-sql.js +11 -0
- package/dist/plugins/run-store-sql.d.ts +21 -2
- package/dist/plugins/run-store-sql.js +31 -7
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
- package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
- package/dist/plugins/schema-consistency.d.ts +4 -2
- package/dist/plugins/schema-consistency.js +19 -2
- package/dist/plugins/send-file-ledger.js +3 -0
- package/dist/plugins/serving-requirement.d.ts +26 -7
- package/dist/plugins/serving-requirement.js +11 -4
- package/dist/plugins/session-birth.d.ts +6 -2
- package/dist/plugins/session-capture-record-store-sql.js +2 -0
- package/dist/plugins/session-ext-table.d.ts +14 -1
- package/dist/plugins/session-ext-table.js +5 -1
- package/dist/plugins/session-row-sql.d.ts +49 -2
- package/dist/plugins/session-row-sql.js +56 -13
- package/dist/plugins/session-store-sql.d.ts +34 -18
- package/dist/plugins/session-store-sql.js +98 -17
- package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
- package/dist/plugins/shared-memory-store-sql.js +6 -2
- package/dist/plugins/sql-driver.d.ts +2 -1
- package/dist/plugins/sql-driver.js +18 -3
- package/dist/plugins/sql-errors.d.ts +11 -6
- package/dist/plugins/sql-errors.js +5 -6
- package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
- package/dist/plugins/stop-then-start-sentence.js +14 -10
- package/dist/plugins/stop-then-start.d.ts +109 -0
- package/dist/plugins/stop-then-start.js +104 -0
- package/dist/plugins/store-backend.d.ts +40 -13
- package/dist/plugins/store-backend.js +169 -27
- package/dist/plugins/store-boundary.d.ts +57 -0
- package/dist/plugins/store-boundary.js +139 -0
- package/dist/plugins/store-contracts.d.ts +17 -0
- package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
- package/dist/plugins/store-fault-sentence-m53.js +25 -0
- package/dist/plugins/store-fault.d.ts +26 -7
- package/dist/plugins/store-fault.js +18 -2
- package/dist/plugins/task-attachment-store.js +9 -0
- package/dist/plugins/task-list-store-sql.d.ts +2 -2
- package/dist/plugins/task-list-store-sql.js +10 -8
- package/dist/plugins/tidb-cost-quota.js +4 -0
- package/dist/plugins/tidb-pool.js +2 -1
- package/dist/plugins/tidb-rate-limiter.js +4 -0
- package/dist/plugins/user-input-ledger-sql.js +4 -0
- package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
- package/dist/plugins/workflow-run-store-sql.js +64 -4
- package/dist/plugins/workspace-fill.d.ts +4 -7
- package/dist/plugins/workspace-fill.js +2 -1
- package/dist/plugins/write-behind-counter.js +5 -0
- package/dist/project-context.d.ts +0 -2
- package/dist/project-context.js +4 -8
- package/dist/project-registry.d.ts +46 -0
- package/dist/project-registry.js +44 -0
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +4 -0
- package/dist/request-value-closure.js +10 -0
- package/dist/run-acceptance.d.ts +3 -2
- package/dist/run-acceptance.js +4 -6
- package/dist/run-local.js +1 -0
- package/dist/runs.d.ts +37 -8
- package/dist/runs.js +53 -12
- package/dist/runtime-governance.d.ts +5 -4
- package/dist/security.d.ts +30 -32
- package/dist/security.js +41 -7
- package/dist/server-secret-env.d.ts +12 -10
- package/dist/server-secret-env.js +24 -15
- package/dist/session-bindings.d.ts +82 -0
- package/dist/session-bindings.js +18 -0
- package/dist/session-children-retire.d.ts +2 -2
- package/dist/session-children-retire.js +2 -6
- package/dist/session-deletion.d.ts +16 -1
- package/dist/session-error-wire.d.ts +3 -3
- package/dist/session-error-wire.js +3 -3
- package/dist/session-incarnation.d.ts +10 -0
- package/dist/session-incarnation.js +10 -1
- package/dist/session-kind.d.ts +57 -0
- package/dist/session-kind.js +22 -0
- package/dist/session-row.d.ts +21 -1
- package/dist/session-row.js +7 -1
- package/dist/session-sync-kernel.d.ts +24 -14
- package/dist/session-sync-kernel.js +3 -6
- package/dist/session-sync.d.ts +4 -98
- package/dist/session-sync.js +1 -71
- package/dist/session-titler.d.ts +10 -3
- package/dist/session-titler.js +19 -6
- package/dist/ssh-host-key.d.ts +5 -0
- package/dist/ssh-host-key.js +3 -0
- package/dist/stores-sql/file-history-store-sql.d.ts +52 -2
- package/dist/stores-sql/file-history-store-sql.js +108 -70
- package/dist/stores-sql/pg-session-storage.d.ts +34 -7
- package/dist/stores-sql/pg-session-storage.js +37 -13
- package/dist/stores-sql/retention-store-sql.d.ts +1 -9
- package/dist/stores-sql/retention-store-sql.js +2 -10
- package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
- package/dist/stores-sql/session-policy-store-sql.js +61 -44
- package/dist/stores-sql/session-write-hooks.d.ts +11 -0
- package/dist/stores-sql/tidb-session-store.d.ts +58 -7
- package/dist/stores-sql/tidb-session-store.js +37 -13
- package/dist/submission-exit.d.ts +3 -2
- package/dist/submission-exit.js +9 -1
- package/dist/task-cwd.d.ts +2 -2
- package/dist/task-settings.d.ts +6 -5
- package/dist/terminal.d.ts +33 -2
- package/dist/terminal.js +139 -9
- package/dist/tool-approval.d.ts +140 -6
- package/dist/tool-approval.js +165 -72
- package/dist/trace/self-minted-wire.d.ts +290 -27
- package/dist/trace/self-minted-wire.js +101 -13
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +78 -27
- package/package.json +2 -2
- package/wire-changes/server@7.151.0.json +762 -0
- package/dist/http/session-inherit-env.d.ts +0 -36
- package/dist/http/session-inherit-env.js +0 -6
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { FileSessionRepo, type AcquiredSession, type PlacedSessionRow, type SessionHead, type SessionPlacementRecord, type SessionStore, type SessionRepo, type SessionMetadata, type SessionTreeEntry, type StoreDurability } from "@sema-agent/core";
|
|
2
2
|
import { type PlacementAcquireOpts } from "./session-placement.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import { StoreBootRefusalError, type SessionRootRows, type SessionRunClaimSource, type SessionRunRollupSource, type SessionSummary } from "./store-contracts.js";
|
|
5
|
-
import { type ClientSessionRowWrite, type ReplaySessionRowWrite, type ReplaySessionRowWriteOutcome, type SessionRowAnswer, type SessionRowPatch, type SessionRowWriteOutcome } from "../session-row.js";
|
|
4
|
+
import { StoreBootRefusalError, type SessionRootRows, type SessionRunClaimSource, type SessionRunRollupSource, type SessionListQuery, type SessionSummary } from "./store-contracts.js";
|
|
5
|
+
import { type ClientSessionRowWrite, type ReplaySessionRowWrite, type ReplaySessionRowWriteOutcome, type SessionRowAnswer, type SessionRowPatch, type SessionRowWriteOutcome, type LandedOutcome } from "../session-row.js";
|
|
6
6
|
import { type SqlJsonColumnProblem } from "./sql-json-column.js";
|
|
7
7
|
import { type LocalArchiveKeptStamped, type LocalArchiveUnreadable } from "./one-time-migrations.js";
|
|
8
8
|
import { type ReleaseTriple } from "./release-version.js";
|
|
9
9
|
import { type Logger } from "../observability/logger.js";
|
|
10
10
|
import type { SessionOccupant } from "../session-erase.js";
|
|
11
11
|
import { type RegisterReceipt, type SessionBirth, type SessionFace, type WithdrawOutcome } from "../session-incarnation.js";
|
|
12
|
+
import { type LocalSessionLiveReferenceReaders } from "./local-session-live-reference.js";
|
|
13
|
+
import { type IdleSession, type IdleSessionCursor, type SessionKind, type SessionKindReading } from "../session-kind.js";
|
|
12
14
|
import type { SessionDeletionFace } from "../session-deletion.js";
|
|
13
15
|
import { type ExecutionLane } from "../execution-lane-caps.js";
|
|
14
16
|
import { type ExecutionPlacementSeat, type LocalPlacementBackfillSeat } from "../execution-placement.js";
|
|
15
17
|
import { type ForkPlacement, type ForkTarget, type ForkToOutcome } from "./session-fork.js";
|
|
16
18
|
import { type InstructionSourceBaseline } from "../instruction-source-notice.js";
|
|
17
19
|
import type { SessionWorkspace } from "../session-workspace.js";
|
|
18
|
-
import { type StagedCommitOptions, type StagingHandle, type SyncRelation } from "../session-sync-kernel.js";
|
|
20
|
+
import { type EntriesStreamOptions, type StagedCommitOptions, type StagingHandle, type SyncRelation } from "../session-sync-kernel.js";
|
|
19
21
|
/**
|
|
20
22
|
* 本店执行格的形(会话元数据那一格的 `execution` 位;规则在 `src/execution-placement.ts`):`writer(L)` | `mirror`;缺 = absent。
|
|
21
23
|
* local 车道没有 device 表 ⇒ 不设任何设备位(writer 只带车道)。`forking` 不是存下的值,是「fork 创建的格({@link isForkCreatedCell})而存档不在」的读法。
|
|
@@ -59,6 +61,11 @@ interface SessionMetaCellObject {
|
|
|
59
61
|
* 撤回对它一律答「留」(`upgrade_pending`)。不需要一次性升级:撤回的候选只可能是本版登记新铸的格(化身比对,`session-birth.ts`),缺这一位的格永远不是候选。
|
|
60
62
|
*/
|
|
61
63
|
readonly clientWrites?: number;
|
|
64
|
+
/**
|
|
65
|
+
* 会话种类(律 `src/session-kind.ts`;SQL 孪生 `session_ext.session_kind`):只由登记新行那一笔写下(带种类的提交建的会话),此后无写口;缺 = 顶层对话。
|
|
66
|
+
* 半建形(登记写下了格、建存档那一步失败)之后同 id 的缺档新建臂随属主一起带过它(两位都是登记那一笔写下的出生事实)。
|
|
67
|
+
*/
|
|
68
|
+
readonly sessionKind?: SessionKind;
|
|
62
69
|
}
|
|
63
70
|
/**
|
|
64
71
|
* 会话元数据边档(`session-incarnations.json`)的一格 —— SQL 孪生 `session_meta` 行在本店的对位(同一行 ⇒ 同一格、同一次落盘):属主 / 化身 / 执行放置 / `fork_key` /
|
|
@@ -93,6 +100,9 @@ export declare const SESSION_META_CELL_OBJECT: z.ZodObject<{
|
|
|
93
100
|
dropping: z.ZodOptional<z.ZodLiteral<true>>;
|
|
94
101
|
deleting: z.ZodOptional<z.ZodString>;
|
|
95
102
|
clientWrites: z.ZodOptional<z.ZodNumber>;
|
|
103
|
+
sessionKind: z.ZodOptional<z.ZodEnum<{
|
|
104
|
+
sidechain: "sidechain";
|
|
105
|
+
}>>;
|
|
96
106
|
}, z.core.$strict>;
|
|
97
107
|
/**
|
|
98
108
|
* 数据根对账里一只文件的读数(拒句的逐文件一段;{@link LocalDataRootSchemaMismatchError.findings}):严格边档清册里的一只边档,或引擎版本高水位 marker
|
|
@@ -328,6 +338,14 @@ export interface SessionRunWithdrawSource {
|
|
|
328
338
|
export interface LocalSessionWithdrawDeclaration {
|
|
329
339
|
readonly withdrawCheckpointCtx?: (sessionId: string) => void;
|
|
330
340
|
}
|
|
341
|
+
/**
|
|
342
|
+
* 本店的老化装配(装配方给;会话种类的律在 `src/session-kind.ts`):活引用判除认领之外的三只读口(检查点 / 后台子代 / workflow 晚绑座,`local-session-live-reference.ts`;
|
|
343
|
+
* 认领那一腿读本店自己的 run 店)。**显式声明才有老化**:缺这一格 ⇒ 本店不交老化候选面 ⇒ 这台部署记不了种类(能力位 `sessionKinds` 为空、带键提交 400)——
|
|
344
|
+
* 不按「没说 = 没有引用」放行一条删用户数据的腿;每一腿逐只声明(`"none"` = 这台部署确实没有那只店)。
|
|
345
|
+
*/
|
|
346
|
+
export interface LocalSessionAgeOutDeclaration {
|
|
347
|
+
readonly liveReferences?: Omit<LocalSessionLiveReferenceReaders, "claim">;
|
|
348
|
+
}
|
|
331
349
|
export declare class LocalSessionStore implements SessionStore, SessionRootRows {
|
|
332
350
|
private readonly repo;
|
|
333
351
|
private readonly runs;
|
|
@@ -436,6 +454,13 @@ export declare class LocalSessionStore implements SessionStore, SessionRootRows
|
|
|
436
454
|
private archiveSnapshotsSettled;
|
|
437
455
|
/** 撤回时本会话续跑输入的严格删法({@link LocalSessionWithdrawDeclaration};缺 = 没有可删的)。 */
|
|
438
456
|
private readonly withdrawCheckpointCtx;
|
|
457
|
+
/** 活引用判({@link LocalSessionAgeOutDeclaration};缺 = 本店不老化 —— 老化围栏对带条件的删除一律答「不删」)。 */
|
|
458
|
+
private readonly liveReferenceOf;
|
|
459
|
+
/** 老化候选面(`OwnerAwareSessionStore.listIdleOfKind`;只在声明了老化装配时交 —— {@link LocalSessionAgeOutDeclaration})。 */
|
|
460
|
+
readonly listIdleOfKind?: (kind: SessionKind, idleBefore: Date, page: {
|
|
461
|
+
readonly after?: IdleSessionCursor;
|
|
462
|
+
readonly limit: number;
|
|
463
|
+
}) => Promise<IdleSession[]>;
|
|
439
464
|
/** @param repo the core SessionRepo this store projects into the §0.5 SessionStore shape.
|
|
440
465
|
* @param runs the run store whose per-session projection is the ONLY source of a row's `runCount` / `lastStatus` / `lastRunId` /
|
|
441
466
|
* `lastTaskRunId` (LocalBackend passes its `FileRunStore`). Required — a run-less local session store does not exist.
|
|
@@ -447,7 +472,7 @@ export declare class LocalSessionStore implements SessionStore, SessionRootRows
|
|
|
447
472
|
* @param opts.durability / opts.placements the deployment's declaration ({@link LocalSessionStoreDeclaration}; see the two fields). */
|
|
448
473
|
constructor(repo: HeadReadingSessionRepo & Partial<PlacementRecordingRepo>, runs: SessionRunRollupSource & SessionRunClaimSource, dataDir?: string, opts?: {
|
|
449
474
|
log?: Pick<Logger, "info" | "warn">;
|
|
450
|
-
} & LocalSessionStoreDeclaration & LocalSessionWithdrawDeclaration);
|
|
475
|
+
} & LocalSessionStoreDeclaration & LocalSessionWithdrawDeclaration & LocalSessionAgeOutDeclaration);
|
|
451
476
|
/**
|
|
452
477
|
* 🔴 一次性迁移 **M40 的 local 会话腿**(窗口见 `plugins/one-time-migrations.ts` 登记表 M40 行;唯一调用点 `LocalBackend.ensureSchema()` 的**第一步**,
|
|
453
478
|
* 先于任何读会话元数据的店步骤 —— 严格读的执行位只认本版车道词;数据根准入的那一读在内存里先套同一只内核 {@link renameRetiredExecutionLaneWordsInCellsM40},零写):会话元数据边档里 `execution` 位记成退役词的
|
|
@@ -616,11 +641,13 @@ export declare class LocalSessionStore implements SessionStore, SessionRootRows
|
|
|
616
641
|
* 别的读者一律读作不在(读者律);门对别的属主答「不在」的同一句,所以不可探测。SQL 孪生同交这一口(座的原始头读)。
|
|
617
642
|
*/
|
|
618
643
|
deletionHeadOf(sessionId: string): Promise<SessionHead | undefined>;
|
|
644
|
+
/** 按 id 的种类读(`session-kind.ts` 的 `SessionKindFace`):行事实那一格(属主与化身的唯一读口 {@link metaOf} 的同一次观察)上的住客与种类。不在 ⇒ `undefined`。 */
|
|
645
|
+
sessionKindOf(sessionId: string): Promise<SessionKindReading | undefined>;
|
|
619
646
|
/**
|
|
620
647
|
* 引擎仓存档的头(core `SessionRepo.headOf`:日志首记录与尾,不重放)—— 本店按 id 读存档头的**唯一**一处。存档头在本店只有三种读法:叶子(读内容的人要的那一格)、
|
|
621
648
|
* 行代号(暂存提交落点 / 一次性迁移 M33 的 `expect.row`、迁移判「有没有、读不读得出」)与带戳判({@link assertArchiveAnonymous};读的是存档的**形** —— 头上有没有属主戳 —— 不是属主事实);
|
|
622
649
|
* 属主 / 化身 / 建档时刻 / 谱系作为行事实从不从这里读(规则一,行事实只住边档);例外只有窗内无格存档长第一格的那一读({@link firstCellIncarnationHeld},M47 在树时;
|
|
623
|
-
* M47 的起服扫经列表面的行集读同一只令牌)。
|
|
650
|
+
* M47 的起服扫经列表面的行集读同一只令牌);会话老化的候选面也经它问「存档在不在」(行集没交它的时刻时,{@link idleOfKind})。
|
|
624
651
|
*/
|
|
625
652
|
private archiveHeadOf;
|
|
626
653
|
/**
|
|
@@ -641,7 +668,7 @@ export declare class LocalSessionStore implements SessionStore, SessionRootRows
|
|
|
641
668
|
* failure keeps the in-memory title (degrades to re-title after restart). Runs under this session's write lock — the
|
|
642
669
|
* user's conditional write ({@link writeSessionRowCells}) judges its row tag and writes under the same lock, so the two
|
|
643
670
|
* writers of the title cell never interleave between a judgement and its write (the SQL twins get this from the row lock). */
|
|
644
|
-
setTitleIfNull(sessionId: string, title: string): Promise<boolean>;
|
|
671
|
+
setTitleIfNull(sessionId: string, title: string, landed: SessionFace): Promise<boolean>;
|
|
645
672
|
/**
|
|
646
673
|
* 会话行格写原语 —— 用户标题 / 置顶的**唯一**写口(SQL 孪生 `writeSessionRowCells` 的 local 对位;规则与判序:`src/session-row.ts` 头注「写原语」)。
|
|
647
674
|
* **整段在这只会话的写锁里**({@link withSessionWriteLock}):读出锁住的那一行(会话元数据那一格的属主 + 化身 + 执行位、列表面上有它、两只边档的格)→
|
|
@@ -811,7 +838,7 @@ export declare class LocalSessionStore implements SessionStore, SessionRootRows
|
|
|
811
838
|
* 出生回执面(`session-birth.ts`):与 {@link register} 同一笔写。**只有新建会话那一臂**(存档不在 ∧ 这一笔真写下了新格)交回候选 —— 化身是这一笔里铸的那一只,
|
|
812
839
|
* 不复读;已记下属主(并发登记里后到的那一只)/ 只补化身 ⇒ 不交候选。新格同一笔写下客户端写计数 `0`(版本位,见 {@link SessionMetaCellObject.clientWrites})。
|
|
813
840
|
*/
|
|
814
|
-
registerWithReceipt(sessionId: string, owner: string | null): Promise<RegisterReceipt>;
|
|
841
|
+
registerWithReceipt(sessionId: string, owner: string | null, kind?: SessionKind): Promise<RegisterReceipt>;
|
|
815
842
|
touch(sessionId: string): Promise<void>;
|
|
816
843
|
/**
|
|
817
844
|
* 普通会话:durable 史留在 repo,只丢 in-flight 那一格(义务 3,与 SQL 孪生同)。
|
|
@@ -847,34 +874,17 @@ export declare class LocalSessionStore implements SessionStore, SessionRootRows
|
|
|
847
874
|
* Keyset matches the contract: STRICTLY older than the cursor, ties broken by id DESC; `limit` is honored after
|
|
848
875
|
* the in-memory sort. Cheap (a local single-user store holds few sessions).
|
|
849
876
|
*/
|
|
850
|
-
listSessions(opts:
|
|
851
|
-
owner?: string;
|
|
852
|
-
/** [ref] 窄互认第二臂的第三条件(SQL 孪生里是 `owner IS NULL` 谓词;此处是同义的 `owner === null` 放行)。 */
|
|
853
|
-
includeUnowned?: boolean;
|
|
854
|
-
cursor?: {
|
|
855
|
-
lastActivityAt: string;
|
|
856
|
-
sessionId: string;
|
|
857
|
-
};
|
|
858
|
-
limit: number;
|
|
859
|
-
q?: string;
|
|
860
|
-
}): Promise<SessionSummary[]>;
|
|
877
|
+
listSessions(opts: SessionListQuery): Promise<SessionSummary[]>;
|
|
861
878
|
/** {@link listSessions} 带每行的住客(属主 + 化身那一格,与行同一刻读)—— `OwnerAwareSessionStore.listSessionRows`;化身不进行本身。 */
|
|
862
|
-
listSessionRows(opts:
|
|
863
|
-
owner?: string;
|
|
864
|
-
includeUnowned?: boolean;
|
|
865
|
-
cursor?: {
|
|
866
|
-
lastActivityAt: string;
|
|
867
|
-
sessionId: string;
|
|
868
|
-
};
|
|
869
|
-
limit: number;
|
|
870
|
-
q?: string;
|
|
871
|
-
}): Promise<Array<SessionRowAnswer<SessionSummary>>>;
|
|
879
|
+
listSessionRows(opts: SessionListQuery): Promise<Array<SessionRowAnswer<SessionSummary>>>;
|
|
872
880
|
/** 列表行要读的边档一次装齐(lastActivity / 标题 / 置顶 / 会话元数据);各自记忆化,只有第一次真读盘。 */
|
|
873
881
|
private loadRowSidecars;
|
|
874
882
|
/** 列表行上的属主:那一格的属主(没有格 / 属主从没被记下 ⇒ null —— 与 `headOf(id)?.owner` 同答;列表不补铸缺的格,`headOf` 在第一次读时补)。 */
|
|
875
883
|
private ownerCellOf;
|
|
876
884
|
/** 一只会话的列表行 —— {@link listSessions} 与 {@link sessionSummaryOf} 的**同一只**合成(字段来源逐位见 listSessions 的头注)。调用方先 {@link loadRowSidecars}。 */
|
|
877
885
|
private summaryOf;
|
|
886
|
+
/** 列表行的 `sessionKind` 键:那一格的种类(没有那一格 / 顶层 ⇒ 键缺席)。 */
|
|
887
|
+
private listedKindOf;
|
|
878
888
|
/** 列表行的 `forkedFrom` 键:那一格的谱系经三店唯一的读法 `forkLineageOfRow`(没有那一格 / 不是 fork ⇒ 键缺席;住客令牌不上列表行)。 */
|
|
879
889
|
private listedLineageOf;
|
|
880
890
|
/** 列表行的 `rowTag` 键(规则 `session-row.ts`):化身出自会话元数据那一格(与写原语锁住的那一行同读),属主与两格由调用方交 —— 就是这一行交出去的那两位(同一刻读);没有那一格 ⇒ 键缺席。 */
|
|
@@ -939,10 +949,7 @@ export declare class LocalSessionStore implements SessionStore, SessionRootRows
|
|
|
939
949
|
* resume is always same-backend), so the local 0-based-index base needn't match the durable backends' `seq` column
|
|
940
950
|
* base. Resolves to null (NOT an empty iterable) for an unknown session — mirrors {@link exportEntries}.
|
|
941
951
|
* `opts.batchSize` is accepted for API parity but has no effect locally (the whole log is already in hand). */
|
|
942
|
-
exportEntriesStream(sessionId: string, opts
|
|
943
|
-
afterSeq?: number;
|
|
944
|
-
batchSize?: number;
|
|
945
|
-
}): Promise<AsyncIterable<SessionTreeEntry> | null>;
|
|
952
|
+
exportEntriesStream(sessionId: string, opts: EntriesStreamOptions): Promise<AsyncIterable<SessionTreeEntry> | null>;
|
|
946
953
|
/**
|
|
947
954
|
* 2c session-sync — IMPORT a verbatim entry log into a **new** session `sessionId`(`owner` = 鉴权过的导入者)。按接口句(`importEntries` 只建新会话;改写既有会话走
|
|
948
955
|
* {@link replaceEntries} / 暂存提交),SQL 孪生同判(占行不成 ⇒ 拒):id 上已有行(或格缺而存档在)⇒ `conflict`,一个字节不写;新行的属主 = 导入者、铸一只化身、
|
|
@@ -1044,7 +1051,7 @@ export declare class LocalSessionStore implements SessionStore, SessionRootRows
|
|
|
1044
1051
|
assertArchiveAnonymous(sessionId: string): Promise<void>;
|
|
1045
1052
|
/**
|
|
1046
1053
|
* {@link LocalStagingHandle.commit} 的整段 —— **一次持锁**(这只会话的写锁,{@link withSessionWriteLock}):属主 CAS(此刻的属主格 = 这次导入的门判过的那一格,
|
|
1047
|
-
* 否则抛 {@link
|
|
1054
|
+
* 否则抛 {@link StagedCommitOccupantChangedError},一个字节不写;在判目的端日志之前判,SQL 孪生同序)→ 分区判 → 提交时重新分类(目的端此刻的日志 vs staged)→
|
|
1048
1055
|
* 这一提交要换日志(不是「id 与内容都相同」那一支)⇒ 带戳存档判({@link assertArchiveAnonymous};只有 local 店有带戳存档,SQL 孪生没有这一步)→
|
|
1049
1056
|
* 拒未经同意的 fork / stale / 载荷分叉(带戳判在它们之前:带戳存档上日志换不了,同步冲突与载荷分叉的出路 —— 带同意重来 —— 无从谈起)→ 准入({@link admitImportHeld}:读认领 → 本处写者 / fork 中间态 → 拒;fork 中间态的拒也在这一处,不再在提交入口另判一遍)→ 换装(导入写序 ①②③,落点 `judged` = 上面这一判;化身与 fork 键按换装律沿用)或 identical 且内容相同时日志不动、
|
|
1050
1057
|
* 行照样落(② 那一格:重戳属主 + mirror)→ 两支同记新近(推送即活动)→ **在同一次持锁里**
|
|
@@ -1073,6 +1080,21 @@ export declare class LocalSessionStore implements SessionStore, SessionRootRows
|
|
|
1073
1080
|
private deletingTokenOf;
|
|
1074
1081
|
/** 删除面(会话三态的围栏 / 复核 / 收尾输入;律在 `src/session-deletion.ts`)。 */
|
|
1075
1082
|
readonly sessionDeletion: SessionDeletionFace;
|
|
1083
|
+
/**
|
|
1084
|
+
* 老化候选面的体({@link listIdleOfKind};律 `src/session-kind.ts`):会话元数据格里种类为 `kind` 的行(活格与在删格 —— 在删的照交,交给围栏接管;标记格不交:
|
|
1085
|
+
* 店内删序正在收它)× 时钟锚({@link ageAnchorOf}:新近标记 / 存档的最后写时刻 / 建档时刻里最晚的那一个)早于视界 × 当下无活引用。最老先出、keyset 续页(序的唯一判 `idleSessionAfter`)。
|
|
1086
|
+
* 先按格判(同步、零 I/O:新近标记与建档时刻都早于视界是必要条件);过了的格有一只才读一遍 repo 行集取存档时刻(`lastActiveAt`);行集里没有它的格(半建 / 存档读不出被行集跳过)
|
|
1087
|
+
* 再经存档头读口探一次:存档在而时刻读不到 ⇒ 不交(说不准就护住)。
|
|
1088
|
+
*/
|
|
1089
|
+
private idleOfKind;
|
|
1090
|
+
/**
|
|
1091
|
+
* 老化的时钟锚(epoch ms;候选面与围栏同读):新近标记(本进程的 touch / 边档)· 存档的最后写时刻(`archived`:repo 行的 `lastActiveAt` = 日志 mtime,持久 —— 边档读不出、
|
|
1092
|
+
* 最后几次 touch 没落盘时它仍在)· 行上的建档时刻,**取最晚的那一个**。新近标记的持久是尽力的(边档撕裂 ⇒ 空表、去抖窗内崩 ⇒ 丢最后几笔),删用户数据的判不单读它。
|
|
1093
|
+
* 一个读得出的时刻都没有 ⇒ `+∞`(永不闲置)。调用方先 {@link loadRowSidecars}。
|
|
1094
|
+
*/
|
|
1095
|
+
private ageAnchorOf;
|
|
1096
|
+
/** 新近标记此刻是否仍早于视界(没有标记 = 本进程没见过它的活动 ⇒ 仍早于)。同步读 —— 围栏在令牌落盘那一节里读它,与 touch 不交错。 */
|
|
1097
|
+
private unTouchedSince;
|
|
1076
1098
|
/** 一只在删格上的属主(遗留行围栏时没有记下属主 ⇒ 读作无主,与删除门的读法同)。 */
|
|
1077
1099
|
private deletionOwnerOf;
|
|
1078
1100
|
/**
|
|
@@ -1083,6 +1105,13 @@ export declare class LocalSessionStore implements SessionStore, SessionRootRows
|
|
|
1083
1105
|
* 写令牌 `required`(文件 + 目录 fsync):落不了 ⇒ 抛,什么都没删(围栏没立)。遗留行铸一格(化身新铸、只带令牌;回执的化身 `undefined` —— 它的住客从没被记下,没有空间)。
|
|
1084
1106
|
*/
|
|
1085
1107
|
private fenceDeletionHeld;
|
|
1108
|
+
/**
|
|
1109
|
+
* 老化条件的锁内判(`session-deletion.ts` 的 `SessionAgeOutExpectation`;调用方持这只会话的写锁):活格 ∧ 住客仍是候选那一位 ∧ 种类仍是它 ∧ 时钟锚仍早于视界 ∧ 当下无活引用
|
|
1110
|
+
* (本店的活引用判;没有老化装配 ⇒ 一律不成立)。遗留行(没有格)没有种类 ⇒ 不成立。
|
|
1111
|
+
* 时钟锚在这里读新近标记与建档时刻({@link ageAnchorOf},存档时刻不重读 —— 候选面读过它;本进程独占数据根,之后存档的每一次写都随一次 touch:run 收场、导入、同步推送);
|
|
1112
|
+
* 新近标记在令牌落盘那一节里还要再读一次({@link fenceDeletionHeld})。
|
|
1113
|
+
*/
|
|
1114
|
+
private ageOutHoldsHeld;
|
|
1086
1115
|
/**
|
|
1087
1116
|
* 客户端写计数 +1(锁内一形,调用方持这只会话的写锁):活格 ⇒ `clientWrites` = 原值(缺 ⇒ 0)+ 1,**落盘必须成功**(`required`;落不了 ⇒ 抛,调用方的写不发生);
|
|
1088
1117
|
* 没有活格(行不在 / 遗留行)⇒ 不计(没有可撤的候选)。
|
|
@@ -1095,6 +1124,15 @@ export declare class LocalSessionStore implements SessionStore, SessionRootRows
|
|
|
1095
1124
|
* `write` 不得回到本店上锁的公开口(锁不可重入);`count` 只在这一节里有效(节外调用 ⇒ 抛)。
|
|
1096
1125
|
*/
|
|
1097
1126
|
withClientWrite<T>(sessionId: string, write: (count: () => Promise<void>) => Promise<T>): Promise<T>;
|
|
1127
|
+
/**
|
|
1128
|
+
* **落定段**的 local 实现(SQL 孪生 `plugins/session-row-sql.ts` 的 `withLandedRow`;律在 `plugins/landed-attendants.ts` 头注):这只会话的写锁一节 —— 节首收尾待删(既有)→
|
|
1129
|
+
* 读出锁住的那一行(与行格写原语同一读 {@link lockedRowOf})→ 同一只判官 `judgeLandedRow`(行在 ∧ 非在删 ∧ 属主与化身整对同)→ 是 ⇒ `body(count)` 在同一节里跑完 ⇒
|
|
1130
|
+
* `{ landed: true, value }`;不是 ⇒ `{ landed: false }`,`body` 一个字节都不跑。与 {@link withClientWrite} 是**同一把锁、同一只计数口**(两只入口一只实现:
|
|
1131
|
+
* 后者不判住客);与删净段 `deleteSession` 同锁 ⇒ 删除与落定写互不穿插。`body` 不得回到本店上锁的公开口(锁不可重入),只调各附随店的动词(锁序 会话 → 店)。
|
|
1132
|
+
*/
|
|
1133
|
+
withLanded<T>(sessionId: string, landed: SessionFace, body: (count: () => Promise<void>) => Promise<T>): Promise<LandedOutcome<T>>;
|
|
1134
|
+
/** 持锁的一节里交出那只客户端写计数口(节外调用 ⇒ 抛)。 */
|
|
1135
|
+
private countedSectionHeld;
|
|
1098
1136
|
/**
|
|
1099
1137
|
* 条件撤回面(`session-birth.ts` 头注的判序;SQL 孪生的一只事务 = 本店这只会话的写锁一节):
|
|
1100
1138
|
* 节首收掉了这只 id 的待删 / 行不在 ⇒ `absent`;遗留行、化身或属主不是候选 ⇒ `incarnation`;没有计数版本位 ⇒ `upgrade_pending`;存档里有可撤集合之外的条目 ⇒ `content`;
|
|
@@ -15,7 +15,7 @@ import { z } from "zod";
|
|
|
15
15
|
import { contentForkRelation, fastForwardSharedContentDiverged, identicalIdsAlsoIdenticalContent } from "../session-sync-content.js";
|
|
16
16
|
import { SCHEMA_MISMATCH_ERROR_CODE, StoreBootRefusalError } from "./store-contracts.js";
|
|
17
17
|
import { entryTypeWithdrawable } from "./session-birth.js";
|
|
18
|
-
import { judgeSessionRowWrite, sessionRowTagKey, settleSessionRowWrite, } from "../session-row.js";
|
|
18
|
+
import { judgeLandedRow, judgeSessionRowWrite, sessionRowTagKey, settleSessionRowWrite, } from "../session-row.js";
|
|
19
19
|
import { quarantineUnreadableSidecar } from "./local-sidecar-quarantine.js";
|
|
20
20
|
import { createZodColumnReader, decodeJsonColumn, isJsonColumnBodyProblem, isJsonObject, readJsonObjectColumn, readStringRecordColumn, SqlJsonColumnError } from "./sql-json-column.js";
|
|
21
21
|
import { RENAMED_EXECUTION_LANE_M40, RETIRED_EXECUTION_LANE_WORD_M40 } from "./execution-lane-rename-m40.js";
|
|
@@ -26,13 +26,15 @@ import { recordFailOpen } from "../observability/fail-open.js";
|
|
|
26
26
|
import { createLogger, writeLogText } from "../observability/logger.js";
|
|
27
27
|
import { UNMANAGED_RETENTION } from "./retention-declaration.js";
|
|
28
28
|
import { UnreadableLeaf, carriedRowCells, forkLineageOfRow, headFromRow, incarnationFromCell, mintSessionIncarnation, sessionFaceFromRow } from "../session-incarnation.js";
|
|
29
|
+
import { createLocalSessionLiveReference } from "./local-session-live-reference.js";
|
|
30
|
+
import { SESSION_KINDS, idleSessionAfter, sessionKindListed } from "../session-kind.js";
|
|
29
31
|
import { isExecutionLane } from "../execution-lane-caps.js";
|
|
30
|
-
import { SessionForkInProgressError, WRITABLE, assertPlaceableLane, judgeSessionWrite, settledMirrorOutcome, settledPlaceOutcome, SessionDeletingError, } from "../execution-placement.js";
|
|
32
|
+
import { SessionForkInProgressError, WRITABLE, assertPlaceableLane, judgeSessionWrite, sameOccupant, settledMirrorOutcome, settledPlaceOutcome, SessionDeletingError, } from "../execution-placement.js";
|
|
31
33
|
import { classifyForkTarget, forkByFreshId } from "./session-fork.js";
|
|
32
34
|
import { decodeInstructionSource, encodeInstructionSource, sameInstructionSourceBaseline } from "../instruction-source-notice.js";
|
|
33
35
|
import { decodeSessionWorkspaceCell, encodeSessionWorkspaceCell } from "./session-workspace-cell.js";
|
|
34
36
|
import { createCorruptReadFailOpenSeat } from "../observability/corrupt-read-seat.js";
|
|
35
|
-
import { classifySyncRelationshipByIds,
|
|
37
|
+
import { classifySyncRelationshipByIds, SyncConflictError, StagedCommitOccupantChangedError, stagingIdFor, } from "../session-sync-kernel.js";
|
|
36
38
|
const ownerEq = (a, b) => (a ?? null) === (b ?? null);
|
|
37
39
|
const isNotFound = (e) => e instanceof SessionError && e.code === "not_found";
|
|
38
40
|
function archiveFaultWord(code) {
|
|
@@ -76,8 +78,8 @@ const readPinnedSidecar = createZodColumnReader(z.record(z.string(), z.literal(t
|
|
|
76
78
|
const MIRROR_CELL = { role: "mirror" };
|
|
77
79
|
function readSessionMetaCell(cell) {
|
|
78
80
|
return typeof cell === "string"
|
|
79
|
-
? { incarnation: cell, owner: undefined, execution: undefined, forkKey: undefined, createdAt: undefined, forkedFrom: undefined, forkedFromIncarnation: undefined, dropping: false, deleting: undefined, clientWrites: undefined }
|
|
80
|
-
: { incarnation: cell.incarnation, owner: cell.owner, execution: cell.execution, forkKey: cell.forkKey, createdAt: cell.createdAt, forkedFrom: cell.forkedFrom, forkedFromIncarnation: cell.forkedFromIncarnation, dropping: cell.dropping === true, deleting: cell.deleting, clientWrites: cell.clientWrites };
|
|
81
|
+
? { incarnation: cell, owner: undefined, execution: undefined, forkKey: undefined, createdAt: undefined, forkedFrom: undefined, forkedFromIncarnation: undefined, dropping: false, deleting: undefined, clientWrites: undefined, sessionKind: undefined }
|
|
82
|
+
: { incarnation: cell.incarnation, owner: cell.owner, execution: cell.execution, forkKey: cell.forkKey, createdAt: cell.createdAt, forkedFrom: cell.forkedFrom, forkedFromIncarnation: cell.forkedFromIncarnation, dropping: cell.dropping === true, deleting: cell.deleting, clientWrites: cell.clientWrites, sessionKind: cell.sessionKind };
|
|
81
83
|
}
|
|
82
84
|
function shellSentinelCellIdsM48(cells) {
|
|
83
85
|
const ids = [];
|
|
@@ -168,6 +170,7 @@ export const SESSION_META_CELL_OBJECT = z
|
|
|
168
170
|
dropping: z.literal(true).optional(),
|
|
169
171
|
deleting: z.string().min(1).optional(),
|
|
170
172
|
clientWrites: z.number().int().nonnegative().optional(),
|
|
173
|
+
sessionKind: z.enum(SESSION_KINDS).optional(),
|
|
171
174
|
})
|
|
172
175
|
.strict();
|
|
173
176
|
const SESSION_META_SIDECAR = z.record(z.string(), z.union([z.string(), SESSION_META_CELL_OBJECT]));
|
|
@@ -719,11 +722,19 @@ export class LocalSessionStore {
|
|
|
719
722
|
dataRoot;
|
|
720
723
|
archiveSnapshotsSettled = 0;
|
|
721
724
|
withdrawCheckpointCtx;
|
|
725
|
+
liveReferenceOf;
|
|
726
|
+
listIdleOfKind;
|
|
722
727
|
constructor(repo, runs, dataDir, opts) {
|
|
723
728
|
this.repo = repo;
|
|
724
729
|
this.runs = runs;
|
|
725
730
|
this.sidecarPath = dataDir ? join(dataDir, "session-last-activity.json") : undefined;
|
|
726
731
|
this.withdrawCheckpointCtx = opts?.withdrawCheckpointCtx;
|
|
732
|
+
const liveReferences = opts?.liveReferences;
|
|
733
|
+
if (liveReferences !== undefined) {
|
|
734
|
+
const live = createLocalSessionLiveReference({ ...liveReferences, claim: (id) => runs.getActiveTaskId(id) });
|
|
735
|
+
this.liveReferenceOf = live;
|
|
736
|
+
this.listIdleOfKind = (kind, idleBefore, page) => this.idleOfKind(kind, idleBefore, page, live);
|
|
737
|
+
}
|
|
727
738
|
this.log = opts?.log ?? createLogger();
|
|
728
739
|
const repoPlacementOf = repo.placementOf;
|
|
729
740
|
const repoListPlaced = repo.listPlaced;
|
|
@@ -1078,6 +1089,10 @@ export class LocalSessionStore {
|
|
|
1078
1089
|
return headFromRow(sessionId, cell.meta.owner ?? null, cell.meta.incarnation, null);
|
|
1079
1090
|
return this.headOf(sessionId);
|
|
1080
1091
|
}
|
|
1092
|
+
async sessionKindOf(sessionId) {
|
|
1093
|
+
const meta = await this.metaOf(sessionId);
|
|
1094
|
+
return meta === undefined ? undefined : { incarnation: incarnationFromCell(sessionId, meta.incarnation, "absent"), kind: meta.sessionKind };
|
|
1095
|
+
}
|
|
1081
1096
|
archiveHeadOf(sessionId) {
|
|
1082
1097
|
return this.repo.headOf(sessionId);
|
|
1083
1098
|
}
|
|
@@ -1095,10 +1110,8 @@ export class LocalSessionStore {
|
|
|
1095
1110
|
await this.titles.ensureLoaded();
|
|
1096
1111
|
return this.titles.state.entries.has(sessionId) ? "titled" : "untitled";
|
|
1097
1112
|
}
|
|
1098
|
-
async setTitleIfNull(sessionId, title) {
|
|
1099
|
-
|
|
1100
|
-
if (!(await this.rowPresentHeld(sessionId)))
|
|
1101
|
-
return false;
|
|
1113
|
+
async setTitleIfNull(sessionId, title, landed) {
|
|
1114
|
+
const out = await this.withLanded(sessionId, landed, async () => {
|
|
1102
1115
|
await this.titles.ensureLoaded();
|
|
1103
1116
|
const entries = this.titles.state.entries;
|
|
1104
1117
|
if (entries.has(sessionId))
|
|
@@ -1107,6 +1120,7 @@ export class LocalSessionStore {
|
|
|
1107
1120
|
await this.titles.persist();
|
|
1108
1121
|
return true;
|
|
1109
1122
|
});
|
|
1123
|
+
return out.landed && out.value;
|
|
1110
1124
|
}
|
|
1111
1125
|
async writeSessionRowCells(sessionId, cells, how) {
|
|
1112
1126
|
return this.withSessionWriteLock(sessionId, async () => {
|
|
@@ -1140,7 +1154,7 @@ export class LocalSessionStore {
|
|
|
1140
1154
|
const meta = this.liveCellOf(sessionId);
|
|
1141
1155
|
if (meta === undefined || (await this.rowHeaderOf(sessionId)) === undefined)
|
|
1142
1156
|
return undefined;
|
|
1143
|
-
return { owner: meta.owner ?? null, incarnation: incarnationFromCell(sessionId, meta.incarnation, "absent"), placed: false, mirror: meta.execution?.role === "mirror", cells: this.rowCellsOf(sessionId) };
|
|
1157
|
+
return { owner: meta.owner ?? null, incarnation: incarnationFromCell(sessionId, meta.incarnation, "absent"), placed: false, deleting: false, mirror: meta.execution?.role === "mirror", cells: this.rowCellsOf(sessionId) };
|
|
1144
1158
|
}
|
|
1145
1159
|
rowCellsOf(sessionId) {
|
|
1146
1160
|
return { title: this.titles.state.entries.get(sessionId) ?? null, pinned: this.pinned.state.entries.get(sessionId) === true };
|
|
@@ -1394,7 +1408,10 @@ export class LocalSessionStore {
|
|
|
1394
1408
|
if (placement !== undefined)
|
|
1395
1409
|
return this.createPlacedHeld(sessionId, placement, opts ?? {});
|
|
1396
1410
|
const session = await this.repo.create({ id: sessionId });
|
|
1397
|
-
await this.writeMeta(sessionId, (before) =>
|
|
1411
|
+
await this.writeMeta(sessionId, (before) => {
|
|
1412
|
+
const born = before !== undefined && ownerRecorded(before) ? readSessionMetaCell(before) : undefined;
|
|
1413
|
+
return { incarnation: mintSessionIncarnation(), owner: born?.owner ?? null, createdAt: rowBornNow(), ...(born?.sessionKind !== undefined ? { sessionKind: born.sessionKind } : {}) };
|
|
1414
|
+
});
|
|
1398
1415
|
return this.handOut(sessionId, session);
|
|
1399
1416
|
});
|
|
1400
1417
|
}
|
|
@@ -1456,7 +1473,7 @@ export class LocalSessionStore {
|
|
|
1456
1473
|
async register(sessionId, owner) {
|
|
1457
1474
|
await this.registerWithReceipt(sessionId, owner);
|
|
1458
1475
|
}
|
|
1459
|
-
async registerWithReceipt(sessionId, owner) {
|
|
1476
|
+
async registerWithReceipt(sessionId, owner, kind) {
|
|
1460
1477
|
return this.withSessionWriteLock(sessionId, async () => {
|
|
1461
1478
|
await this.meta.ensureLoaded();
|
|
1462
1479
|
if (this.cellStateOf(sessionId).state === "deleting")
|
|
@@ -1473,7 +1490,7 @@ export class LocalSessionStore {
|
|
|
1473
1490
|
if (ownerRecorded(before))
|
|
1474
1491
|
return undefined;
|
|
1475
1492
|
if (!existed)
|
|
1476
|
-
return { incarnation: born, owner, createdAt: rowBornNow(), clientWrites: 0 };
|
|
1493
|
+
return { incarnation: born, owner, createdAt: rowBornNow(), clientWrites: 0, ...(kind !== undefined ? { sessionKind: kind } : {}) };
|
|
1477
1494
|
return before === undefined ? { incarnation: first ?? cellChangedUnderLock(sessionId) } : undefined;
|
|
1478
1495
|
});
|
|
1479
1496
|
if (!existed && wrote)
|
|
@@ -1484,6 +1501,7 @@ export class LocalSessionStore {
|
|
|
1484
1501
|
async touch(sessionId) {
|
|
1485
1502
|
this.lastActivity.set(sessionId, new Date().toISOString());
|
|
1486
1503
|
this.scheduleFlush();
|
|
1504
|
+
await this.repo.touch?.(sessionId);
|
|
1487
1505
|
}
|
|
1488
1506
|
async release(sessionId) {
|
|
1489
1507
|
this.pending.delete(sessionId);
|
|
@@ -1516,6 +1534,8 @@ export class LocalSessionStore {
|
|
|
1516
1534
|
if (opts.owner !== undefined && owner !== opts.owner && !(opts.includeUnowned === true && owner === null))
|
|
1517
1535
|
continue;
|
|
1518
1536
|
const meta = this.liveCellOf(row.sessionId);
|
|
1537
|
+
if (!sessionKindListed(meta?.sessionKind, opts.sessionKind))
|
|
1538
|
+
continue;
|
|
1519
1539
|
const incarnation = meta === undefined ? undefined : incarnationFromCell(row.sessionId, meta.incarnation, "absent");
|
|
1520
1540
|
all.push({ row: this.summaryOf(row, rollups), occupant: { owner, incarnation } });
|
|
1521
1541
|
}
|
|
@@ -1555,8 +1575,13 @@ export class LocalSessionStore {
|
|
|
1555
1575
|
...rowTag,
|
|
1556
1576
|
...("unreadable" in listed ? { unreadable: sessionUnreadableOf(listed.unreadable) } : {}),
|
|
1557
1577
|
...this.listedLineageOf(sessionId),
|
|
1578
|
+
...this.listedKindOf(sessionId),
|
|
1558
1579
|
};
|
|
1559
1580
|
}
|
|
1581
|
+
listedKindOf(sessionId) {
|
|
1582
|
+
const kind = this.liveCellOf(sessionId)?.sessionKind;
|
|
1583
|
+
return kind !== undefined ? { sessionKind: kind } : {};
|
|
1584
|
+
}
|
|
1560
1585
|
listedLineageOf(sessionId) {
|
|
1561
1586
|
const lineage = forkLineageOfRow(sessionId, this.liveCellOf(sessionId)?.forkedFrom, undefined);
|
|
1562
1587
|
return lineage.forkedFrom !== undefined ? { forkedFrom: lineage.forkedFrom } : {};
|
|
@@ -1679,9 +1704,11 @@ export class LocalSessionStore {
|
|
|
1679
1704
|
const entries = await this.exportEntries(sessionId);
|
|
1680
1705
|
if (entries === null)
|
|
1681
1706
|
return null;
|
|
1682
|
-
const afterSeq = opts
|
|
1707
|
+
const afterSeq = opts.afterSeq ?? -1;
|
|
1683
1708
|
const slice = entries.slice(afterSeq + 1);
|
|
1684
1709
|
async function* gen() {
|
|
1710
|
+
if (slice.length > 0)
|
|
1711
|
+
await opts.recheck();
|
|
1685
1712
|
for (const e of slice)
|
|
1686
1713
|
yield e;
|
|
1687
1714
|
}
|
|
@@ -1808,8 +1835,9 @@ export class LocalSessionStore {
|
|
|
1808
1835
|
async commitStagedImport(sessionId, owner, staged, opts) {
|
|
1809
1836
|
return this.withImportLock(sessionId, owner, async (importer) => {
|
|
1810
1837
|
const current = await this.metaHeld(sessionId);
|
|
1811
|
-
|
|
1812
|
-
|
|
1838
|
+
const held = current === undefined ? undefined : { owner: current.owner ?? null, incarnation: incarnationFromCell(sessionId, current.incarnation, "absent") };
|
|
1839
|
+
if (opts.expectedOccupant === undefined ? held !== undefined : held === undefined || !sameOccupant(opts.expectedOccupant, held))
|
|
1840
|
+
throw new StagedCommitOccupantChangedError(sessionId);
|
|
1813
1841
|
await this.assertNotPlacedHeld(sessionId);
|
|
1814
1842
|
const dstEntries = await this.exportEntries(sessionId);
|
|
1815
1843
|
const rel = classifySyncRelationshipByIds(staged.map((e) => e.id), dstEntries === null ? null : dstEntries.map((e) => e.id));
|
|
@@ -1873,6 +1901,52 @@ export class LocalSessionStore {
|
|
|
1873
1901
|
return this.deletingIds().map((sessionId) => ({ sessionId, owner: this.deletionOwnerOf(sessionId), token: this.deletingTokenOf(sessionId) }));
|
|
1874
1902
|
},
|
|
1875
1903
|
};
|
|
1904
|
+
async idleOfKind(kind, idleBefore, page, live) {
|
|
1905
|
+
await this.loadRowSidecars();
|
|
1906
|
+
const maybe = [];
|
|
1907
|
+
for (const sessionId of [...this.liveCellIds(), ...this.deletingIds()]) {
|
|
1908
|
+
const cell = this.cellStateOf(sessionId);
|
|
1909
|
+
if (cell.state === "none" || cell.state === "dropping" || cell.meta.sessionKind !== kind)
|
|
1910
|
+
continue;
|
|
1911
|
+
if (this.ageAnchorOf(sessionId, cell.meta, undefined) < idleBefore.getTime())
|
|
1912
|
+
maybe.push({ sessionId, meta: cell.meta });
|
|
1913
|
+
}
|
|
1914
|
+
if (maybe.length === 0)
|
|
1915
|
+
return [];
|
|
1916
|
+
const recorded = new Map((await this.repo.list()).map((r) => [r.id, r.lastActiveAt]));
|
|
1917
|
+
const seen = [];
|
|
1918
|
+
for (const { sessionId, meta } of maybe) {
|
|
1919
|
+
let archived = recorded.get(sessionId);
|
|
1920
|
+
if (!recorded.has(sessionId) && (await this.archiveHeadOf(sessionId).catch(() => "unreadable")) !== undefined)
|
|
1921
|
+
continue;
|
|
1922
|
+
if (archived !== undefined && !Number.isFinite(archived))
|
|
1923
|
+
archived = undefined;
|
|
1924
|
+
const anchor = this.ageAnchorOf(sessionId, meta, archived);
|
|
1925
|
+
if (!(anchor < idleBefore.getTime()))
|
|
1926
|
+
continue;
|
|
1927
|
+
seen.push({ sessionId, owner: meta.owner ?? null, incarnation: incarnationFromCell(sessionId, meta.incarnation, "absent"), lastActivityAt: new Date(anchor).toISOString() });
|
|
1928
|
+
}
|
|
1929
|
+
seen.sort((a, b) => (a.lastActivityAt !== b.lastActivityAt ? (a.lastActivityAt < b.lastActivityAt ? -1 : 1) : a.sessionId < b.sessionId ? -1 : 1));
|
|
1930
|
+
const out = [];
|
|
1931
|
+
for (const row of seen) {
|
|
1932
|
+
if (out.length >= page.limit)
|
|
1933
|
+
break;
|
|
1934
|
+
if (!idleSessionAfter(row, page.after))
|
|
1935
|
+
continue;
|
|
1936
|
+
if (await live(row.sessionId, row.owner))
|
|
1937
|
+
continue;
|
|
1938
|
+
out.push(row);
|
|
1939
|
+
}
|
|
1940
|
+
return out;
|
|
1941
|
+
}
|
|
1942
|
+
ageAnchorOf(sessionId, meta, archived) {
|
|
1943
|
+
const marks = [Date.parse(this.lastActivity.get(sessionId) ?? ""), archived ?? Number.NaN, Date.parse(rowCreatedAtOf(sessionId, meta))].filter((t) => Number.isFinite(t));
|
|
1944
|
+
return marks.length === 0 ? Number.POSITIVE_INFINITY : Math.max(...marks);
|
|
1945
|
+
}
|
|
1946
|
+
unTouchedSince(sessionId, idleBefore) {
|
|
1947
|
+
const touched = this.lastActivity.get(sessionId);
|
|
1948
|
+
return touched === undefined || Date.parse(touched) < idleBefore.getTime();
|
|
1949
|
+
}
|
|
1876
1950
|
deletionOwnerOf(sessionId) {
|
|
1877
1951
|
const cell = this.cellStateOf(sessionId);
|
|
1878
1952
|
return cell.state === "none" ? null : (cell.meta.owner ?? null);
|
|
@@ -1903,23 +1977,42 @@ export class LocalSessionStore {
|
|
|
1903
1977
|
return { inProgress: true };
|
|
1904
1978
|
}
|
|
1905
1979
|
else {
|
|
1980
|
+
if (opts.ageOut !== undefined && !(await this.ageOutHoldsHeld(sessionId, current, opts.ageOut)))
|
|
1981
|
+
return undefined;
|
|
1906
1982
|
const verdict = await judgeSessionWrite({ op: "delete", rootSessionId: sessionId }, { claim: () => this.runs.getActiveTaskId(sessionId), cell: async () => ({ role: "absent" }), deleting: async () => this.deletingTokenOf(sessionId) });
|
|
1907
1983
|
if (verdict !== "proceed")
|
|
1908
1984
|
throw verdict.refuse;
|
|
1909
1985
|
}
|
|
1910
1986
|
const token = uuidv7();
|
|
1911
1987
|
let incarnation;
|
|
1988
|
+
let touchedMeanwhile = false;
|
|
1912
1989
|
const committed = await this.meta.commit((draft) => {
|
|
1990
|
+
if (opts.ageOut !== undefined && state.state !== "deleting" && !this.unTouchedSince(sessionId, opts.ageOut.idleBefore)) {
|
|
1991
|
+
touchedMeanwhile = true;
|
|
1992
|
+
return false;
|
|
1993
|
+
}
|
|
1913
1994
|
const before = draft.get(sessionId);
|
|
1914
1995
|
const base = before === undefined ? { incarnation: mintSessionIncarnation() } : cellObjectOf(before);
|
|
1915
1996
|
incarnation = before === undefined ? undefined : base.incarnation;
|
|
1916
1997
|
draft.set(sessionId, { ...base, deleting: token });
|
|
1917
1998
|
return true;
|
|
1918
1999
|
}, "required");
|
|
2000
|
+
if (touchedMeanwhile)
|
|
2001
|
+
return undefined;
|
|
1919
2002
|
if (!committed)
|
|
1920
2003
|
throw new SessionError("storage", `LocalSessionStore: the deletion fence of session ${sessionId} could not be made durable — nothing of the session was removed; retry the delete`);
|
|
1921
2004
|
return { token, incarnation };
|
|
1922
2005
|
}
|
|
2006
|
+
async ageOutHoldsHeld(sessionId, current, ageOut) {
|
|
2007
|
+
if (current === undefined || this.liveReferenceOf === undefined)
|
|
2008
|
+
return false;
|
|
2009
|
+
if (incarnationFromCell(sessionId, current.incarnation, "absent") !== ageOut.incarnation || current.sessionKind !== ageOut.kind)
|
|
2010
|
+
return false;
|
|
2011
|
+
await this.loadRowSidecars();
|
|
2012
|
+
if (!(this.ageAnchorOf(sessionId, current, undefined) < ageOut.idleBefore.getTime()))
|
|
2013
|
+
return false;
|
|
2014
|
+
return !(await this.liveReferenceOf(sessionId, current.owner ?? null));
|
|
2015
|
+
}
|
|
1923
2016
|
async bumpClientWritesHeld(sessionId) {
|
|
1924
2017
|
await this.meta.ensureLoaded();
|
|
1925
2018
|
if (this.cellStateOf(sessionId).state === "deleting")
|
|
@@ -1940,20 +2033,29 @@ export class LocalSessionStore {
|
|
|
1940
2033
|
throw new SessionError("storage", `LocalSessionStore: the client-write count of session ${sessionId} could not be made durable — the write was not made; retry it`);
|
|
1941
2034
|
}
|
|
1942
2035
|
async withClientWrite(sessionId, write) {
|
|
2036
|
+
return this.withSessionWriteLock(sessionId, () => this.countedSectionHeld(sessionId, write));
|
|
2037
|
+
}
|
|
2038
|
+
async withLanded(sessionId, landed, body) {
|
|
1943
2039
|
return this.withSessionWriteLock(sessionId, async () => {
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
return
|
|
1947
|
-
|
|
1948
|
-
throw new Error(`LocalSessionStore.withClientWrite: session ${sessionId}'s client-write count was taken after its lock section ended`);
|
|
1949
|
-
await this.bumpClientWritesHeld(sessionId);
|
|
1950
|
-
});
|
|
1951
|
-
}
|
|
1952
|
-
finally {
|
|
1953
|
-
open = false;
|
|
1954
|
-
}
|
|
2040
|
+
await this.loadRowSidecars();
|
|
2041
|
+
if (!judgeLandedRow(sessionId, landed, await this.lockedRowOf(sessionId)))
|
|
2042
|
+
return { landed: false };
|
|
2043
|
+
return { landed: true, value: await this.countedSectionHeld(sessionId, body) };
|
|
1955
2044
|
});
|
|
1956
2045
|
}
|
|
2046
|
+
async countedSectionHeld(sessionId, body) {
|
|
2047
|
+
let open = true;
|
|
2048
|
+
try {
|
|
2049
|
+
return await body(async () => {
|
|
2050
|
+
if (!open)
|
|
2051
|
+
throw new Error(`LocalSessionStore: session ${sessionId}'s client-write count was taken after its lock section ended`);
|
|
2052
|
+
await this.bumpClientWritesHeld(sessionId);
|
|
2053
|
+
});
|
|
2054
|
+
}
|
|
2055
|
+
finally {
|
|
2056
|
+
open = false;
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
1957
2059
|
async withdrawBirth(birth, ownTaskId) {
|
|
1958
2060
|
const runs = this.runs;
|
|
1959
2061
|
return this.withSessionWriteLock(birth.sessionId, async (dropped) => {
|
|
@@ -9,6 +9,7 @@ import { assertMemoryScopeWidth } from "./memory-key-guards.js";
|
|
|
9
9
|
import { exposureBandOf, exposureCarriage, originMarkedSqlPredicate, distilledCarriage } from "./memory-origin-law.js";
|
|
10
10
|
import { applySqlPatches, } from "./memory-engine-sql-apply.js";
|
|
11
11
|
import { ensureIndexes } from "./ensure-index.js";
|
|
12
|
+
import { sealStoreClass } from "./store-boundary.js";
|
|
12
13
|
export const PG_MEMORY_ENGINE_TABLES = {
|
|
13
14
|
entry: "agent_memory_engine_entry",
|
|
14
15
|
cursor: "agent_memory_engine_cursor",
|
|
@@ -301,4 +302,7 @@ export class PgMemoryEngineBackend {
|
|
|
301
302
|
ON CONFLICT (scope) DO UPDATE SET cursor = $2`, [scope, cursor]);
|
|
302
303
|
}
|
|
303
304
|
}
|
|
305
|
+
sealStoreClass(PgMemoryEngineBackend, "pg-memory-engine-backend", {
|
|
306
|
+
listHeaders: "exit", getByIds: "exit", search: "exit", applyPatches: "exit", getConsolidationCursor: "exit", setConsolidationCursor: "exit",
|
|
307
|
+
});
|
|
304
308
|
//# sourceMappingURL=memory-engine-pg.js.map
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { LandingsNeedAdmission, admittingLandings, computeEntryRev, requireLandingsAdmitted, } from "@sema-agent/core";
|
|
2
2
|
import { memoryEntryKeyWidthRefusal } from "./memory-key-guards.js";
|
|
3
3
|
import { pgHasUnstorable } from "./pg-safe-json.js";
|
|
4
|
+
import { storeBoundaryFault } from "../terminal.js";
|
|
5
|
+
import { markErrorOrigin } from "./error-origin.js";
|
|
4
6
|
import { ambiguousOriginRefusal, createBatchCommittedBaseline, distilledWhitewashRefusal, originWhitewashRefusal, rememberBatchCommitted, unknownPatchOpRefusal, } from "./memory-origin-law.js";
|
|
5
7
|
const FIRST_SUFFIX_STEP = 2;
|
|
6
8
|
const candidateAt = (slug, n) => (n === FIRST_SUFFIX_STEP ? slug : `${slug}-${n - 1}`);
|
|
@@ -317,7 +319,8 @@ export async function applySqlPatches(patches, opts, leg) {
|
|
|
317
319
|
throw err;
|
|
318
320
|
if (issued)
|
|
319
321
|
mayHaveWritten = true;
|
|
320
|
-
|
|
322
|
+
const seen = storeBoundaryFault(err, "memory-engine.applyPatches");
|
|
323
|
+
report.conflicts.push({ op: patch.op, id: patch.id, reason: `io error: ${seen instanceof Error ? seen.message : String(seen)}` });
|
|
321
324
|
return [];
|
|
322
325
|
}
|
|
323
326
|
};
|
|
@@ -345,7 +348,7 @@ export async function applySqlPatches(patches, opts, leg) {
|
|
|
345
348
|
await admittingLandings(admit, attempt);
|
|
346
349
|
}
|
|
347
350
|
catch (err) {
|
|
348
|
-
throw err instanceof CallerThrow ? err.thrown : err;
|
|
351
|
+
throw err instanceof CallerThrow ? markErrorOrigin(err.thrown, "caller") : err;
|
|
349
352
|
}
|
|
350
353
|
finally {
|
|
351
354
|
if (leg.appendHistory && history.length > 0)
|
|
@@ -9,6 +9,7 @@ import { applySqlPatches, } from "./memory-engine-sql-apply.js";
|
|
|
9
9
|
import { isMysqlDupKeyError } from "./sql-errors.js";
|
|
10
10
|
import { ensureIndexes } from "./ensure-index.js";
|
|
11
11
|
import { MEMORY_ENGINE_INDEXES, PG_MEMORY_ENGINE_TABLES } from "./memory-engine-pg.js";
|
|
12
|
+
import { sealStoreClass } from "./store-boundary.js";
|
|
12
13
|
export const TIDB_MEMORY_ENGINE_TABLES = {
|
|
13
14
|
entry: "agent_memory_engine_entry",
|
|
14
15
|
cursor: "agent_memory_engine_cursor",
|
|
@@ -265,4 +266,7 @@ export class TiDBMemoryEngineBackend {
|
|
|
265
266
|
await this.write(`INSERT INTO ${TIDB_MEMORY_ENGINE_TABLES.cursor} (scope, \`cursor\`) VALUES (?, ?) ON DUPLICATE KEY UPDATE \`cursor\` = VALUES(\`cursor\`)`, [scope, cursor]);
|
|
266
267
|
}
|
|
267
268
|
}
|
|
269
|
+
sealStoreClass(TiDBMemoryEngineBackend, "tidb-memory-engine-backend", {
|
|
270
|
+
listHeaders: "exit", getByIds: "exit", search: "exit", applyPatches: "exit", getConsolidationCursor: "exit", setConsolidationCursor: "exit",
|
|
271
|
+
});
|
|
268
272
|
//# sourceMappingURL=memory-engine-tidb.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mysqlDriver, pgDriver } from "./sql-driver.js";
|
|
2
2
|
import { PRINCIPAL_MAX_BYTES, RESERVED_PRINCIPALS, RESERVED_PRINCIPAL_PREFIXES } from "../principal-shape.js";
|
|
3
|
+
import { sealStoreClass } from "./store-boundary.js";
|
|
3
4
|
export const MEMORY_OPTOUT_GRANT_TABLE = "memory_optout_grant";
|
|
4
5
|
export const MEMORY_OPTOUT_DEFAULT_PRINCIPAL = "";
|
|
5
6
|
export function buildMemoryOptOutVerdict(rows, principal) {
|
|
@@ -124,6 +125,9 @@ export class SqlMemoryOptOutGrantStore {
|
|
|
124
125
|
return { principal, allow: input.allow, updatedAtMs: at, updatedBy: input.updatedBy, ...(note !== null ? { note } : {}) };
|
|
125
126
|
}
|
|
126
127
|
}
|
|
128
|
+
sealStoreClass(SqlMemoryOptOutGrantStore, "sql-memory-opt-out-grant-store", {
|
|
129
|
+
resolveAllow: "exit", list: "exit", putDefault: "exit", putOverride: "exit", deleteOverride: "exit",
|
|
130
|
+
});
|
|
127
131
|
export class TiDBMemoryOptOutGrantStore extends SqlMemoryOptOutGrantStore {
|
|
128
132
|
constructor(pool, now) {
|
|
129
133
|
super(mysqlDriver(pool), "mysql", now);
|