@sema-agent/server 7.139.0 → 7.141.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 +471 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +94 -26
- package/dist/adoption/runner.js +1 -1
- package/dist/adoption/sql.js +1 -1
- package/dist/approval-batch-census.d.ts +27 -0
- package/dist/approval-batch-census.js +27 -0
- package/dist/approval-card.d.ts +37 -22
- package/dist/approval-card.js +6 -3
- package/dist/approval.d.ts +15 -0
- package/dist/approval.js +10 -0
- package/dist/audit.d.ts +4 -2
- package/dist/audit.js +2 -2
- package/dist/bench/s1/live-deps.js +3 -2
- package/dist/bench/s1/row.d.ts +5 -2
- package/dist/bench/s1/row.js +2 -22
- package/dist/boot/adoption.js +1 -1
- package/dist/boot/device-lane.d.ts +11 -0
- package/dist/boot/device-lane.js +16 -0
- package/dist/boot/engine-lease.d.ts +24 -3
- package/dist/boot/engine-lease.js +9 -2
- package/dist/boot/execution-env.js +18 -12
- package/dist/boot/execution-lane.d.ts +8 -0
- package/dist/boot/execution-lane.js +6 -1
- package/dist/boot/memory-boundary.d.ts +16 -53
- package/dist/boot/memory-boundary.js +10 -20
- package/dist/boot/memory-consolidation.d.ts +16 -12
- package/dist/boot/memory-consolidation.js +24 -13
- package/dist/boot/reapers.d.ts +2 -2
- package/dist/boot/resolve-spec.d.ts +3 -5
- package/dist/boot/resolve-spec.js +9 -8
- package/dist/boot/runner-deps.d.ts +3 -3
- package/dist/boot/runner-deps.js +1 -0
- package/dist/boot/session-faces.d.ts +1 -1
- package/dist/boot/session-faces.js +4 -3
- package/dist/boot/shutdown.js +5 -0
- package/dist/boot/stage-03-store-backend.d.ts +2 -6
- package/dist/boot/stage-03-store-backend.js +2 -3
- package/dist/boot/stage-04-stores.d.ts +2 -6
- package/dist/boot/stage-04-stores.js +5 -5
- package/dist/boot/stage-05-execution-env.d.ts +2 -6
- package/dist/boot/stage-05-execution-env.js +3 -1
- package/dist/boot/stage-06-runners.d.ts +2 -8
- package/dist/boot/stage-06-runners.js +3 -3
- package/dist/boot/stage-07-capability-layer.d.ts +2 -7
- package/dist/boot/stage-07-capability-layer.js +8 -10
- package/dist/boot/stage-08-reapers.d.ts +2 -7
- package/dist/boot/stage-09-leader.d.ts +2 -7
- package/dist/boot/stage-10-http-server.d.ts +2 -7
- package/dist/boot/stage-10-http-server.js +6 -4
- package/dist/boot/stores.d.ts +3 -6
- package/dist/boot/stores.js +37 -44
- package/dist/boot/task-list-lane.d.ts +1 -1
- package/dist/boot/task-list-lane.js +1 -1
- package/dist/boot/web-admin.js +36 -9
- package/dist/capabilities/execution-lane.d.ts +2 -2
- package/dist/capabilities/scenarios.d.ts +1 -1
- package/dist/capability-facts.d.ts +9 -0
- package/dist/capability-facts.js +9 -0
- package/dist/card-void.d.ts +38 -0
- package/dist/card-void.js +23 -0
- package/dist/config-catalog.js +12 -8
- package/dist/config-provider.d.ts +18 -17
- package/dist/config-provider.js +28 -36
- package/dist/config-types.d.ts +36 -9
- package/dist/config.js +56 -46
- package/dist/delegated-session-owner.d.ts +23 -20
- package/dist/delegated-session-owner.js +2 -2
- package/dist/deployment-shape.d.ts +9 -8
- package/dist/deployment-shape.js +4 -4
- package/dist/device-store.d.ts +7 -0
- package/dist/device-store.js +3 -0
- package/dist/execution-config-root.d.ts +22 -0
- package/dist/execution-config-root.js +35 -0
- package/dist/execution-lane-caps.d.ts +145 -107
- package/dist/execution-lane-caps.js +144 -83
- package/dist/execution-placement.d.ts +3 -0
- package/dist/execution-placement.js +7 -0
- package/dist/fleet/drain-entry.d.ts +3 -0
- package/dist/hosted-posture.d.ts +8 -0
- package/dist/hosted-posture.js +4 -0
- package/dist/http/admission.js +3 -3
- package/dist/http/caller-trust.d.ts +3 -2
- package/dist/http/caller-trust.js +2 -1
- package/dist/http/dispatch.js +4 -0
- package/dist/http/live-frame.d.ts +24 -0
- package/dist/http/live-frame.js +16 -0
- package/dist/http/memory-compliance-failure-reply.d.ts +3 -1
- package/dist/http/memory-compliance-failure-reply.js +5 -0
- package/dist/http/memory-layer-reply.d.ts +30 -0
- package/dist/http/memory-layer-reply.js +24 -0
- package/dist/http/resume-legs.js +49 -35
- package/dist/http/retired-service-deps.d.ts +1 -1
- package/dist/http/retired-service-deps.js +1 -1
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/adoption.js +1 -1
- package/dist/http/routes/approvals-assistant.js +1 -0
- package/dist/http/routes/capabilities.js +5 -4
- package/dist/http/routes/diagnostics.d.ts +0 -19
- package/dist/http/routes/diagnostics.js +16 -2
- package/dist/http/routes/memory-bundle.d.ts +2 -2
- package/dist/http/routes/memory-bundle.js +4 -1
- package/dist/http/routes/memory-compliance.js +9 -2
- package/dist/http/routes/memory-consolidation.js +12 -1
- package/dist/http/routes/memory-origin.js +14 -2
- package/dist/http/routes/memory-policy.js +7 -2
- package/dist/http/routes/run-permission-mode.d.ts +75 -0
- package/dist/http/routes/run-permission-mode.js +170 -0
- package/dist/http/routes/session-sync.d.ts +3 -6
- package/dist/http/routes/session-sync.js +7 -2
- package/dist/http/routes/sessions.js +33 -15
- package/dist/http/routes/tasks.js +67 -68
- package/dist/http/run-read-face.js +3 -3
- package/dist/http/send.d.ts +1 -1
- package/dist/http/send.js +2 -2
- package/dist/http/server.d.ts +14 -27
- package/dist/http/server.js +2 -2
- package/dist/http/sse-log.d.ts +3 -8
- package/dist/http/stored-body-replay.d.ts +3 -3
- package/dist/http/stored-body-replay.js +3 -1
- package/dist/identity-source.d.ts +1 -1
- package/dist/identity-source.js +1 -1
- package/dist/instruction-source-notice.d.ts +7 -0
- package/dist/instruction-source-notice.js +6 -6
- package/dist/lane-home-probe.d.ts +68 -42
- package/dist/lane-home-probe.js +53 -30
- package/dist/leader/wire.js +5 -4
- package/dist/mcp-assertion-header.d.ts +4 -0
- package/dist/mcp-assertion-header.js +5 -0
- package/dist/memory-bundle-engine.d.ts +16 -9
- package/dist/memory-bundle-engine.js +29 -6
- package/dist/memory-operator-faces.d.ts +85 -30
- package/dist/memory-operator-faces.js +136 -30
- package/dist/memory-posture.d.ts +1 -1
- package/dist/memory-project-layer.d.ts +3 -21
- package/dist/memory-project-layer.js +11 -8
- package/dist/memory-scope-stores.d.ts +73 -0
- package/dist/memory-scope-stores.js +86 -0
- package/dist/memory-scope.d.ts +33 -9
- package/dist/memory-scope.js +17 -5
- package/dist/memory-sync-client.d.ts +34 -9
- package/dist/memory-sync-client.js +108 -28
- package/dist/observability/fail-open.d.ts +30 -2
- package/dist/observability/fail-open.js +30 -2
- package/dist/observability/metrics.js +0 -1
- package/dist/observability/run-terminal.d.ts +6 -2
- package/dist/observability/run-terminal.js +25 -26
- package/dist/observability/secret-env-scrub.d.ts +20 -1
- package/dist/observability/secret-env-scrub.js +14 -0
- package/dist/orchestration/workflow-completion-inbox.d.ts +5 -2
- package/dist/orchestration/workflow-completion-inbox.js +13 -5
- package/dist/orchestration/workflow-notify-journal.d.ts +5 -3
- package/dist/orchestration/workflow-notify-journal.js +2 -1
- package/dist/permission-mode-admission.d.ts +68 -0
- package/dist/permission-mode-admission.js +23 -0
- package/dist/permission-rule-list.d.ts +55 -6
- package/dist/permission-rule-list.js +52 -5
- package/dist/plugins/adoption-log-sql.js +4 -4
- package/dist/plugins/approval-ask-store-sql.js +14 -14
- package/dist/plugins/approval-nonce-store.js +4 -4
- package/dist/plugins/blob-backend.d.ts +4 -4
- package/dist/plugins/blob-backend.js +7 -7
- package/dist/plugins/breaker-state-sql.js +2 -2
- package/dist/plugins/caching-session-store.d.ts +6 -0
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-index-columns.js +2 -2
- package/dist/plugins/checkpoint-store-sql.d.ts +65 -17
- package/dist/plugins/checkpoint-store-sql.js +90 -19
- package/dist/plugins/device-store-sql.d.ts +5 -2
- package/dist/plugins/device-store-sql.js +23 -20
- package/dist/plugins/ensure-index.d.ts +1 -2
- package/dist/plugins/execution-placement-sql.d.ts +19 -9
- package/dist/plugins/execution-placement-sql.js +20 -9
- package/dist/plugins/file-history-store-sql.d.ts +2 -2
- package/dist/plugins/file-history-store-sql.js +4 -4
- package/dist/plugins/file-run-store.d.ts +2 -2
- package/dist/plugins/file-run-store.js +1 -1
- package/dist/plugins/fork-routing-session-store.d.ts +10 -32
- package/dist/plugins/fork-routing-session-store.js +2 -61
- package/dist/plugins/image-bake-store-sql.js +9 -9
- package/dist/plugins/image-index-sql.js +11 -11
- package/dist/plugins/k8s-exec-protocol.d.ts +4 -1
- package/dist/plugins/k8s-exec-protocol.js +6 -1
- package/dist/plugins/leader-run-store-sql.js +4 -4
- package/dist/plugins/local-checkpoint-store.d.ts +10 -1
- package/dist/plugins/local-checkpoint-store.js +22 -0
- package/dist/plugins/local-session-store.d.ts +227 -35
- package/dist/plugins/local-session-store.js +518 -37
- package/dist/plugins/local-session-window.d.ts +17 -3
- package/dist/plugins/local-session-window.js +7 -13
- package/dist/plugins/mailbox-store-sql.d.ts +2 -1
- package/dist/plugins/mailbox-store-sql.js +4 -4
- package/dist/plugins/memory-engine-tidb.js +5 -5
- package/dist/plugins/memory-optout-grant-store-sql.js +1 -1
- package/dist/plugins/memory-run-store.d.ts +2 -2
- package/dist/plugins/memory-run-store.js +1 -1
- package/dist/plugins/memory-sync-store-tidb.js +3 -3
- package/dist/plugins/one-time-migrations.d.ts +52 -11
- package/dist/plugins/one-time-migrations.js +101 -39
- package/dist/plugins/org-delivery-quota-store.js +2 -2
- package/dist/plugins/outcome-ledger-sql.js +2 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +4 -4
- package/dist/plugins/permission-rule-store-sql.js +16 -16
- package/dist/plugins/pg-pool.js +3 -2
- package/dist/plugins/pg-session-storage.d.ts +2 -0
- package/dist/plugins/pg-session-storage.js +3 -2
- package/dist/plugins/remote-env-adb.d.ts +7 -24
- package/dist/plugins/remote-env-adb.js +22 -5
- package/dist/plugins/remote-env-device.d.ts +2 -28
- package/dist/plugins/remote-env-device.js +2 -1
- package/dist/plugins/remote-env-e2b.d.ts +40 -27
- package/dist/plugins/remote-env-e2b.js +180 -20
- package/dist/plugins/remote-env-file-error.d.ts +1 -1
- package/dist/plugins/remote-env-file-error.js +8 -2
- package/dist/plugins/remote-env-host.d.ts +19 -35
- package/dist/plugins/remote-env-host.js +26 -3
- package/dist/plugins/remote-env-k8s.d.ts +22 -14
- package/dist/plugins/remote-env-k8s.js +150 -26
- package/dist/plugins/remote-env-local-docker.d.ts +27 -24
- package/dist/plugins/remote-env-local-docker.js +91 -24
- package/dist/plugins/remote-env-ssh.d.ts +4 -24
- package/dist/plugins/remote-env-ssh.js +4 -3
- package/dist/plugins/resume-anchor-store-sql.js +2 -2
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/retention-lane-store-sql.js +2 -2
- package/dist/plugins/retention-store-sql.d.ts +1 -1
- package/dist/plugins/retention-store-sql.js +6 -6
- package/dist/plugins/run-store-sql.d.ts +3 -3
- package/dist/plugins/run-store-sql.js +19 -18
- package/dist/plugins/sandbox-read-floor.d.ts +273 -0
- package/dist/plugins/sandbox-read-floor.js +608 -0
- package/dist/plugins/schema-consistency.d.ts +6 -6
- package/dist/plugins/schema-consistency.js +1 -1
- package/dist/plugins/schema-ensure-legs.d.ts +2 -3
- package/dist/plugins/schema-ensure-legs.js +2 -2
- package/dist/plugins/schema-live-columns.d.ts +1 -1
- package/dist/plugins/session-capture-record-store-sql.js +1 -1
- package/dist/plugins/session-ownership.d.ts +2 -1
- package/dist/plugins/session-placement.d.ts +17 -4
- package/dist/plugins/session-placement.js +2 -1
- package/dist/plugins/session-rules-column.d.ts +1 -1
- package/dist/plugins/session-rules-column.js +1 -1
- package/dist/plugins/session-store.d.ts +18 -20
- package/dist/plugins/session-store.js +4 -12
- package/dist/plugins/session-workspace-cell.d.ts +1 -1
- package/dist/plugins/session-workspace-cell.js +1 -1
- package/dist/plugins/shared-memory-store-sql.js +2 -2
- package/dist/plugins/sql-driver.d.ts +10 -5
- package/dist/plugins/sql-driver.js +6 -6
- package/dist/plugins/sql-errors.js +1 -1
- package/dist/plugins/store-backend.d.ts +35 -6
- package/dist/plugins/store-backend.js +27 -10
- package/dist/plugins/store-contracts.d.ts +9 -2
- package/dist/plugins/task-list-store-sql.js +11 -11
- package/dist/plugins/tidb-pool.js +7 -6
- package/dist/plugins/tidb-session-storage.js +4 -4
- package/dist/plugins/tidb-session-store.d.ts +4 -1
- package/dist/plugins/tidb-session-store.js +16 -15
- package/dist/plugins/tool-result-store-sql.d.ts +2 -2
- package/dist/plugins/tool-result-store-sql.js +3 -3
- package/dist/plugins/user-input-ledger-sql.js +2 -2
- package/dist/plugins/workflow-journal-store-sql.js +5 -5
- package/dist/plugins/workflow-run-store-sql.js +19 -19
- package/dist/plugins/write-behind-counter.d.ts +2 -3
- package/dist/plugins/write-behind-counter.js +5 -5
- package/dist/resource-suspend.d.ts +14 -12
- package/dist/resource-suspend.js +1 -1
- package/dist/resource-window.d.ts +4 -3
- package/dist/run-cancel-context.d.ts +34 -0
- package/dist/run-cancel-context.js +7 -0
- package/dist/run-local.js +14 -19
- package/dist/runs.d.ts +47 -16
- package/dist/runs.js +112 -113
- package/dist/security.d.ts +2 -2
- package/dist/server-secret-env.d.ts +2 -1
- package/dist/server-secret-env.js +2 -4
- package/dist/session-error-wire.d.ts +22 -4
- package/dist/session-error-wire.js +16 -0
- package/dist/session-incarnation.d.ts +10 -4
- package/dist/session-incarnation.js +1 -1
- package/dist/session-policy-wire.d.ts +1 -1
- package/dist/session-sync-kernel.d.ts +42 -1
- package/dist/session-sync-kernel.js +17 -0
- package/dist/session-sync.js +16 -4
- package/dist/sql-engine-coordinates.d.ts +49 -0
- package/dist/sql-engine-coordinates.js +27 -0
- package/dist/sql-engine-posture.d.ts +1 -1
- package/dist/sql-engine-posture.js +1 -1
- package/dist/standing-answer-grant.d.ts +31 -2
- package/dist/standing-answer-grant.js +14 -2
- package/dist/store-posture.d.ts +1 -1
- package/dist/{plugins → stores-sql}/background-agent-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/background-agent-store-sql.js +8 -8
- package/dist/{plugins → stores-sql}/session-policy-store-sql.d.ts +7 -5
- package/dist/{plugins → stores-sql}/session-policy-store-sql.js +12 -12
- package/dist/{plugins → stores-sql}/usage-window-store-sql.d.ts +1 -1
- package/dist/{plugins → stores-sql}/usage-window-store-sql.js +3 -3
- package/dist/task-a2a.d.ts +1 -1
- package/dist/task-a2a.js +5 -6
- package/dist/task-mcp.d.ts +21 -8
- package/dist/task-mcp.js +17 -9
- package/dist/task-settings.d.ts +52 -25
- package/dist/task-settings.js +91 -28
- package/dist/terminal.d.ts +103 -19
- package/dist/terminal.js +72 -20
- package/dist/trace/core-keyset-guard.d.ts +79 -2
- package/dist/trace/exit-seat.d.ts +7 -0
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/model-segment.d.ts +2 -2
- package/dist/trace/redact.d.ts +3 -1
- package/dist/trace/redact.js +395 -110
- package/dist/trace/self-minted-wire.d.ts +226 -2
- package/dist/trace/self-minted-wire.js +79 -0
- package/dist/verifier-pause-card.d.ts +8 -0
- package/dist/verifier-pause-card.js +19 -0
- package/dist/web-admin-client/apply-effective.d.ts +5 -7
- package/dist/web-admin-client/apply-effective.js +2 -2
- package/dist/web-admin-client/candidate-gate.d.ts +11 -7
- package/dist/web-admin-client/candidate-gate.js +1 -1
- package/dist/web-admin-client/http-client.d.ts +5 -4
- package/dist/web-admin-client/http-client.js +2 -2
- package/dist/web-admin-client/read-warnings.d.ts +7 -17
- package/dist/web-admin-client/read-warnings.js +5 -9
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -2
- package/package.json +2 -2
- package/wire-changes/server@7.140.0.json +184 -0
- package/wire-changes/server@7.141.0.json +367 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { PgQueryFn } from "./pg-query.js";
|
|
2
|
-
|
|
3
|
-
export type SchemaDialect = "mysql" | "pg";
|
|
2
|
+
import type { SqlDialect } from "./sql-driver.js";
|
|
4
3
|
/** advisory lock 语句 —— 与 schema 无关,录制时跳过(但要答成功,否则 ensure* 走降级告警路径)。 */
|
|
5
4
|
export declare const LOCK_RE: RegExp;
|
|
6
5
|
/**
|
|
@@ -51,5 +50,5 @@ export declare const DRIVEN_ENSURES: {
|
|
|
51
50
|
readonly pg: readonly string[];
|
|
52
51
|
};
|
|
53
52
|
/** 跑一遍一条方言的真 `ensure*` 全腿,返回**录制到的语句流**(顺序即执行顺序)。纯内存,不碰数据库。 */
|
|
54
|
-
export declare function recordEnsureStatements(dialect:
|
|
53
|
+
export declare function recordEnsureStatements(dialect: SqlDialect): Promise<string[]>;
|
|
55
54
|
//# sourceMappingURL=schema-ensure-legs.d.ts.map
|
|
@@ -6,10 +6,10 @@ import { ensurePgMemoryEmbedderMetaSchema } from "./memory-embedder-fingerprint.
|
|
|
6
6
|
import { ensureTiDBMemorySyncSchema, ensureTiDBMemoryHistorySchema } from "./memory-sync-store-tidb.js";
|
|
7
7
|
import { ensurePgMemorySyncSchema, ensurePgMemoryHistorySchema } from "./memory-sync-store-pg.js";
|
|
8
8
|
import { ensureTiDBRosterSchema, ensurePgRosterSchema } from "./roster-store-sql.js";
|
|
9
|
-
import { ensureTiDBBackgroundAgentSchema, ensurePgBackgroundAgentSchema } from "
|
|
9
|
+
import { ensureTiDBBackgroundAgentSchema, ensurePgBackgroundAgentSchema } from "../stores-sql/background-agent-store-sql.js";
|
|
10
10
|
import { ensureTiDBMailboxSchema, ensurePgMailboxSchema } from "./mailbox-store-sql.js";
|
|
11
11
|
import { ensureTiDBTaskAttachmentSchema, ensurePgTaskAttachmentSchema } from "./task-attachment-store.js";
|
|
12
|
-
import { ensureTiDBUsageWindowSchema, ensurePgUsageWindowSchema } from "
|
|
12
|
+
import { ensureTiDBUsageWindowSchema, ensurePgUsageWindowSchema } from "../stores-sql/usage-window-store-sql.js";
|
|
13
13
|
import { ensureTiDBTaskListSchema, ensurePgTaskListSchema } from "./task-list-store-sql.js";
|
|
14
14
|
import { ensureTiDBDeviceSchema, ensurePgDeviceSchema } from "./device-store-sql.js";
|
|
15
15
|
export const LOCK_RE = /GET_LOCK|RELEASE_LOCK|pg_(try_)?advisory/i;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* 缺这条索引的列」也读它)。叶子模块:不值依赖任何模块(列册探针那边经录制驱动 / 建表腿值依赖 `ensure-index.ts`,读者若住在那边,
|
|
4
4
|
* `ensure-index.ts` 读它就是一个运行时环)。方言词是 `ensure-index.ts` 的闭集(类型边,擦除)。
|
|
5
5
|
*/
|
|
6
|
-
import type { SqlDialect } from "./
|
|
6
|
+
import type { SqlDialect } from "./sql-driver.js";
|
|
7
7
|
/** 探针读口:一条 SQL → 行数组(两方言由调用方各自绑)。 */
|
|
8
8
|
export type SchemaProbeRead = (sql: string) => Promise<Array<Record<string, unknown>>>;
|
|
9
9
|
/**
|
|
@@ -83,7 +83,7 @@ export class SqlSessionCaptureRecordStore {
|
|
|
83
83
|
}
|
|
84
84
|
export class TiDBSessionCaptureRecordStore extends SqlSessionCaptureRecordStore {
|
|
85
85
|
constructor(pool) {
|
|
86
|
-
super(mysqlDriver(pool), "
|
|
86
|
+
super(mysqlDriver(pool), "mysql");
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
export class PgSessionCaptureRecordStore extends SqlSessionCaptureRecordStore {
|
|
@@ -25,7 +25,8 @@ export declare function assertFirstOwnerWritable(sessionId: string, owner: unkno
|
|
|
25
25
|
/**
|
|
26
26
|
* 导入者的属主 —— 换装的写腿(公开 `importEntries` / `replaceEntries` 与暂存提交)把调用方给的属主重戳进会话行之前的唯一读法:
|
|
27
27
|
* 主体名或 `null`(匿名)⇒ 原样交回;别的一切(空串、空白串、带控制 / 分隔 / 非连接符格式字符的串、非串)⇒ `TypeError` 响亮拒 ——
|
|
28
|
-
* 与引擎导入口拒同一类值时同一类错、同一句开头(
|
|
28
|
+
* 与引擎导入口拒同一类值时同一类错、同一句开头(引擎那一判只作用于交给它的属主,而 local 店交给引擎仓的属主恒缺席 —— 引擎仓是匿名内容仓,属主只在本店的行上 ——
|
|
29
|
+
* 所以这一判在本仓)。
|
|
29
30
|
* 调用方在读写任何东西之前判,拒了就一个字节没写。判官 = {@link isSessionOwnerValue}(core `principalNameOf`),不在本仓另写规则。
|
|
30
31
|
*/
|
|
31
32
|
export declare function importerOwnerOf(owner: unknown): string | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* [ref] C18(core 5.48.0 [ref]「不造新店」提货批,黑板 [ref] 点名义务)——**subagent 转录持久化**
|
|
3
|
-
* 的 placement
|
|
3
|
+
* 的 placement 语义,三只会话店(SQL 两孪生 + local)共用的一份声明与判据。
|
|
4
4
|
*
|
|
5
5
|
* ## 这是什么
|
|
6
6
|
*
|
|
@@ -35,16 +35,29 @@
|
|
|
35
35
|
*/
|
|
36
36
|
import { type PlacedSessionRow, type SessionPlacement, type SessionPlacementRecord, type SessionStore } from "@sema-agent/core";
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
38
|
+
* 三只持久会话店(SQL 两孪生 + local 后端)的**会话耐久声明**(core `SessionStore.durability`:未 placed 的会话活不活过进程重启)——
|
|
39
|
+
* **单源**:三处声明(两孪生类上的顶层 `durability`、`LocalBackend` 交给店的顶层 `durability`)与委派分区的 {@link SESSION_PLACEMENTS}
|
|
40
|
+
* 引用的都是这一只常量,源码里不再有第二份 `"durable"` 字面(`test/session-store-durability-declaration.test.ts` 的 AST 钉)。
|
|
41
|
+
*
|
|
42
|
+
* 为什么必须声明:core 的静态装配对**缺席**折 `"process-local"`(它不能替没表态的店猜),接线清单 `session.store` 与起服自检读的就是它 ——
|
|
43
|
+
* 不声明 ⇒ 一个真持久的 SQL 部署读成「重启即丢」,没有任何一处报错。依据同下面分区声明那一段:两孪生的会话史落在 `session_meta` + `session_event` 两张真表,
|
|
44
|
+
* local 的会话史落在数据根下的会话存档,进程重启后都能把已有会话取回来。包装层(缓存层)逐字转发;fork 路由层不声明(它自己的未 placed 会话住进程内短 TTL 店,
|
|
45
|
+
* 顶层耐久只说未 placed 的会话——见 `fork-routing-session-store.ts` 头注)。
|
|
46
|
+
*/
|
|
47
|
+
export declare const SESSION_DURABILITY: "durable";
|
|
48
|
+
/**
|
|
49
|
+
* 三只持久会话店的 placement **声明**(core `SessionStore.placements`):两支 SQL 孪生(类上的字段)与 local 后端
|
|
50
|
+
* (`LocalBackend` 装配 `LocalSessionStore` 时交进去 —— 值与 core `FileStorageBackend` 对同一种文件 repo 的声明同)。
|
|
39
51
|
*
|
|
40
52
|
* 🔴 声明制,不是鸭子类型:core 的铸造门判「row store ∧ session 店声明」,不声明的店**不收** placed
|
|
41
53
|
* 语义(合法降级:placement 参数被忽略,会话就是普通会话)。所以这一格只有在上面六条义务**全部**在
|
|
42
54
|
* 本店实装之后才允许存在——它是一句关于本店行为的承诺,不是一个功能开关。
|
|
43
55
|
* `durable` 的依据:两支孪生的会话史落在 `session_meta`+`session_event` 两张真表上,进程重启后
|
|
44
56
|
* `acquire(id,{requireExisting:true})` 从事件日志重放(义务 1 的机器证在
|
|
45
|
-
* `test/session-placement-db-integration.test.ts` 的跨进程复活格)
|
|
57
|
+
* `test/session-placement-db-integration.test.ts` 的跨进程复活格);local 的会话史落在数据根下的会话存档
|
|
58
|
+
* (元组在存档行头),属主与化身在同一数据根的会话元数据边档(机器证在 `test/local-session-placement.test.ts` 的重启格)。
|
|
46
59
|
*/
|
|
47
|
-
export declare const
|
|
60
|
+
export declare const SESSION_PLACEMENTS: {
|
|
48
61
|
readonly subagent: {
|
|
49
62
|
readonly durability: "durable";
|
|
50
63
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SessionError } from "@sema-agent/core";
|
|
2
|
-
export const
|
|
2
|
+
export const SESSION_DURABILITY = "durable";
|
|
3
|
+
export const SESSION_PLACEMENTS = { subagent: { durability: SESSION_DURABILITY } };
|
|
3
4
|
export const PLACEMENT_SELECT_COLUMNS = "placement_kind, placement_scope, placement_parent_session_id, placement_root_session_id, placement_handle, placed_at";
|
|
4
5
|
function toEpochMs(v) {
|
|
5
6
|
if (v == null)
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export declare const SESSION_RULES_COLUMN: {
|
|
12
12
|
readonly name: "rule_entries";
|
|
13
|
-
readonly
|
|
13
|
+
readonly mysql: "rule_entries JSON NOT NULL";
|
|
14
14
|
readonly pg: "rule_entries JSONB NOT NULL";
|
|
15
15
|
};
|
|
16
16
|
//# sourceMappingURL=session-rules-column.d.ts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type SessionStore } from "@sema-agent/core";
|
|
2
2
|
import type { ServiceConfig } from "../config-types.js";
|
|
3
3
|
import type { StoreBackend } from "./store-backend.js";
|
|
4
|
-
import { type DelegationRootWitness, type
|
|
4
|
+
import { type DelegationRootWitness, type OrphanOwnerLog } from "../delegated-session-owner.js";
|
|
5
5
|
import type { OwnerAwareSessionStore } from "../security.js";
|
|
6
6
|
/**
|
|
7
7
|
* Session-store plugin seam.
|
|
@@ -37,31 +37,29 @@ export declare function createSessionStore(config: Pick<ServiceConfig, "sessionB
|
|
|
37
37
|
* (`evictPolicy="delete"`)。本函数自己**不做**、也无法通用地做"这个 store 实例的 release 是否安全"的
|
|
38
38
|
* 判别(`SessionStore` 接口没有暴露这个信息,类型层面区分不了两种店形)——上文"误判方向永远偏保守"
|
|
39
39
|
* 只覆盖 `getLeafId` 那道校验,不覆盖"传了一个 release=delete 的店进来"这个前提违反。**调用方必须
|
|
40
|
-
* 保证只在真正 durable(release 非破坏性)的店上调用本函数**——server 侧的强制点在
|
|
41
|
-
* `ensureChildSessionDurable`
|
|
40
|
+
* 保证只在真正 durable(release 非破坏性)的店上调用本函数**——server 侧的强制点在 stage-07 装配区:
|
|
41
|
+
* `ensureChildSessionDurable` 闭包只在部署的子代转录档位是 `full` 时构造(core `resolveSubagentTranscriptTier`:会话店声明了 durable 的委派分区 ——
|
|
42
|
+
* 三只持久会话店;无 repo 的内存店不声明,档位不是 `full`,挂点不装)。
|
|
42
43
|
*/
|
|
43
44
|
export declare function ensureSessionDurable(hostStore: SessionStore, sessionId: string): Promise<void>;
|
|
44
45
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
46
|
+
* core `SubagentToolOptions.background.ensureChildSessionDurable` 的实现体 —— 停驻挂点的**见证**:这只后台子代的转录此刻是 host 店里一只有真内容、
|
|
47
|
+
* 属主按委派继承律定得下来的会话,才放行停驻;任何一步不成立 ⇒ 抛 = 否决(core 收 veto 即 expire checkpoint + settle failed,pre-153 行为,不放大)。
|
|
48
|
+
*
|
|
49
|
+
* 规则(`fork-routing-session-store.ts` 头注):一只后台子代的 durable 行在,它的转录就是 host 店委派分区里的一只 placed 行。挂点只装在声明了
|
|
50
|
+
* durable 委派分区的部署上(stage-07:core `resolveSubagentTranscriptTier(...) === "full"`),那里 core 给每只新起的后台子代铸 placement、
|
|
51
|
+
* 转录生来就在 host 店 —— 所以这里**只验、不搬**(此前的「晋升」把私店的转录整树拷进 host 店,随这条规则退役)。
|
|
52
|
+
* 0. 属主(`delegated-session-owner.ts`):按委派继承律判一次(唯一判据 `judgeDelegatedOwner`)—— 来源集 = 见证的根这一只(调用方交出的委派树根 + 调用方判断那一刻
|
|
49
53
|
* 读到的根行住客:请求腿 = 本请求经鉴权解析的会话与受理时那一读,`/decide` 赎回腿 = 行上的 `rootSessionId` 与写口放行的那一位(认领之前解析器那一读);core 的挂点签名只给子代 id,
|
|
50
|
-
* 场景层把见证绑进闭包交下来)。此刻根行在而住客不是见证的那一位(删了、同 id 被重新登记)⇒ **拒**(`assertRootStillWitnessed
|
|
54
|
+
* 场景层把见证绑进闭包交下来)。此刻根行在而住客不是见证的那一位(删了、同 id 被重新登记)⇒ **拒**(`assertRootStillWitnessed`);
|
|
51
55
|
* 缺席(行上没有根)或根行此刻不在 ⇒ 孤行哨兵。
|
|
52
|
-
* 1.
|
|
53
|
-
* (
|
|
54
|
-
*
|
|
55
|
-
* 2.
|
|
56
|
-
*
|
|
57
|
-
* 3. 复验:同一把 `ensureSessionDurable` 严检(leaf 非空)+ 同一只属主定夺 —— 晋升产物必须达到与快路完全相同的
|
|
58
|
-
* 标准,任何一步失败=如实 reject=veto=pre-153 行为(不放大)。
|
|
56
|
+
* 1. 在不在、有没有真内容:{@link ensureSessionDurable}(`requireExisting` 打开 + 叶子非空 + forget 收尾)。任何失败(不在、空壳、读故障)⇒ 原样上抛 = 否决
|
|
57
|
+
* (读故障也否决:说不准转录在不在,就不让一次审批押在它上面)。这里**不判它是不是 placed 行**:复活的是旧行时 id 取行上的会话(升级前停驻、当年晋升进来的普通行),
|
|
58
|
+
* 它照样是这只子代的转录;判据只问「host 店里有这份真内容」。
|
|
59
|
+
* 2. 属主定夺(`settleDelegatedOwner`):记着别的委派树 ⇒ 抛;记着这一棵 ⇒ 按它记录的根、父再判一次(与 M23 同读数),无主 ⇒ 认领(CAS 子行,写判断时的读数)、没落下 ⇒ 抛;
|
|
60
|
+
* 此刻属主不是律给的那一只 ⇒ 那是别人的同 id 会话,不是这只子代的转录 ⇒ 抛 = 停驻否决。认领写下的是哨兵 ⇒ 写落下之后一行 warn(`site: "park"`)。
|
|
59
61
|
* 宿主店必须读得出属主(`delegatedOwnerHostOf`:`headOf`;记录委派树的店另交 `placementOf` + `claimOwnerless`,两只同在或同缺;生产的 SQL / local 店与缓存包装层都满足),
|
|
60
62
|
* 否则响亮拒。
|
|
61
|
-
* 调用方纪律与 {@link ensureSessionDurable} 同款:hostStore 必须是 release 非破坏性的真 durable 店
|
|
62
|
-
* (stage-07 的 `config.sessionBackend === "tidb"` 门不变 —— 该词在 local 后端上同样归一成 `tidb`,所以本腿在 local 宿主店上也跑)。
|
|
63
63
|
*/
|
|
64
|
-
export declare function
|
|
65
|
-
promoteToHost(sessionId: string, owner: string | null, tree: DelegationTree): Promise<void>;
|
|
66
|
-
}, sessionId: string, root: DelegationRootWitness | undefined, log: OrphanOwnerLog): Promise<void>;
|
|
64
|
+
export declare function attestChildSessionDurable(hostStore: OwnerAwareSessionStore, sessionId: string, root: DelegationRootWitness | undefined, log: OrphanOwnerLog): Promise<void>;
|
|
67
65
|
//# sourceMappingURL=session-store.d.ts.map
|
|
@@ -23,24 +23,16 @@ export async function ensureSessionDurable(hostStore, sessionId) {
|
|
|
23
23
|
await hostStore.forget?.(acquired.sessionId);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
export async function
|
|
26
|
+
export async function attestChildSessionDurable(hostStore, sessionId, root, log) {
|
|
27
27
|
const host = delegatedOwnerHostOf(hostStore);
|
|
28
28
|
if (host === undefined) {
|
|
29
29
|
throw new Error(`session "${sessionId}" cannot be parked: the host session store cannot read a session's owner (headOf), or records delegation trees without being able to claim under them (placementOf / claimOwnerless), so the delegated transcript's owner cannot be derived or checked`);
|
|
30
30
|
}
|
|
31
31
|
const judged = await readDelegatedOwner(sessionId, root === undefined ? {} : { rootSessionId: root.sessionId }, sourceFacesVia(host.headOf));
|
|
32
32
|
assertRootStillWitnessed(sessionId, root, judged);
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
await ensureSessionDurable(hostStore, sessionId);
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
await routing.promoteToHost(sessionId, judged.inherited.owner, judged.tree);
|
|
39
|
-
await ensureSessionDurable(hostStore, sessionId);
|
|
40
|
-
promoted = true;
|
|
41
|
-
}
|
|
33
|
+
await ensureSessionDurable(hostStore, sessionId);
|
|
42
34
|
const settled = await settleDelegatedOwner(host, sessionId, judged.inherited.owner, judged.tree);
|
|
43
|
-
if (
|
|
44
|
-
reportWrittenOwner(log, "
|
|
35
|
+
if (settled.claimed)
|
|
36
|
+
reportWrittenOwner(log, "park", sessionId, settled.judged ?? judged);
|
|
45
37
|
}
|
|
46
38
|
//# sourceMappingURL=session-store.js.map
|
|
@@ -3,7 +3,7 @@ import { type JsonColumnReader } from "./sql-json-column.js";
|
|
|
3
3
|
/** 列定义的唯一属主(两方言 DDL 内插它;存量库缺这一列 ⇒ 起服列册对账拒启,拒句里的 ALTER 由建表语句生成)。 */
|
|
4
4
|
export declare const SESSION_META_WORKSPACE_COLUMN: {
|
|
5
5
|
readonly name: "workspace";
|
|
6
|
-
readonly
|
|
6
|
+
readonly mysql: "workspace JSON NULL";
|
|
7
7
|
readonly pg: "workspace JSONB";
|
|
8
8
|
};
|
|
9
9
|
/** 这一格的形读者(三只店与帧投影同一只;写前也过它 —— 写得进的就是读得出的)。 */
|
|
@@ -4,7 +4,7 @@ import { recordFailOpen } from "../observability/fail-open.js";
|
|
|
4
4
|
import { assertJsonColumnWritable, createZodColumnReader, decodeJsonColumn, isJsonColumnBodyProblem } from "./sql-json-column.js";
|
|
5
5
|
export const SESSION_META_WORKSPACE_COLUMN = {
|
|
6
6
|
name: "workspace",
|
|
7
|
-
|
|
7
|
+
mysql: "workspace JSON NULL",
|
|
8
8
|
pg: "workspace JSONB",
|
|
9
9
|
};
|
|
10
10
|
const SESSION_WORKSPACE_SHAPE = z.object({
|
|
@@ -106,8 +106,8 @@ export class SqlSharedMemoryStore {
|
|
|
106
106
|
this.now = opts.now ?? Date.now;
|
|
107
107
|
this.maxListLimit = opts.maxListLimit ?? DEFAULT_MAX_LIST_LIMIT;
|
|
108
108
|
}
|
|
109
|
-
q(
|
|
110
|
-
return this.db.dialect === "
|
|
109
|
+
q(mysql, pg) {
|
|
110
|
+
return this.db.dialect === "mysql" ? mysql : pg;
|
|
111
111
|
}
|
|
112
112
|
async snapshot(ctx, opts) {
|
|
113
113
|
throwIfAborted(opts.signal);
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
* ─────────────────────────────────────────────────────────────────────────────────────────────────
|
|
69
69
|
* Reference collapses: image-bake-store-sql.ts (class + transactions) and checkpoint-store-sql.ts
|
|
70
70
|
* (class, no transactions). Function-style stores follow task-list-store-sql.ts instead (inline
|
|
71
|
-
* `dialect === "
|
|
71
|
+
* `dialect === "mysql" ? … : …` ternaries, no driver object) — pick the shape the pair already has.
|
|
72
72
|
*
|
|
73
73
|
* STEPS
|
|
74
74
|
* 1. Read BOTH twins end to end first. List every method and mark it identical / SQL-text-only /
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
* 3. Per statement, write BOTH texts at the call site via a 2-arg `q(tidbSql, pgSql)` helper.
|
|
80
80
|
* Never build one text with a placeholder-numbering loop — the point is that a reviewer sees
|
|
81
81
|
* the two statements adjacent.
|
|
82
|
-
* 4. Genuinely-divergent algorithms get an `if (dialect === "
|
|
82
|
+
* 4. Genuinely-divergent algorithms get an `if (dialect === "mysql") { … } else { … }` block with a
|
|
83
83
|
* 🔴 comment saying WHY both are correct. Never "unify" them by picking one engine's algorithm.
|
|
84
84
|
* 5. Old files become thin re-export shims. Class names, ctor arity, exported constants/types and
|
|
85
85
|
* helper names stay EXACTLY as they were — consumers and tests must not move.
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
* (pgSafeJsonStringify / pgProtocolJsonStringify / pgSanitizeText / pgHasUnstorable) · DDL. Each arm's
|
|
99
99
|
* BEHAVIOR (what pgSafeJsonStringify/pgProtocolJsonStringify actually do to the bytes) stays written out
|
|
100
100
|
* in `pg-safe-json.ts`, untouched — `dialectJsonEncoder`/`dialectProtocolJsonEncoder` below ([ref]
|
|
101
|
-
* redesign①) only collect the identical `dialect === "
|
|
101
|
+
* redesign①) only collect the identical `dialect === "mysql" ? JSON.stringify(v) : pgSafe…(v)` DISPATCH
|
|
102
102
|
* ternary that five call sites duplicated verbatim; they are not a new abstraction over the encodings
|
|
103
103
|
* themselves, so this does not violate the rule above.
|
|
104
104
|
*
|
|
@@ -112,7 +112,12 @@
|
|
|
112
112
|
import type { Pool as MySqlPool } from "mysql2/promise";
|
|
113
113
|
import type { Pool as PgPool } from "pg";
|
|
114
114
|
import type { Logger } from "../observability/logger.js";
|
|
115
|
-
|
|
115
|
+
/**
|
|
116
|
+
* SQL **文本**的语法族(调用方说,不探):`mysql` = MySQL 协议(TiDB / MySQL InnoDB / MariaDB 同一套语句),`pg` = PostgreSQL。
|
|
117
|
+
* 与 `@sema-agent/core-stores-sql` 公面的 `SqlDialect` 同词同集 —— 部署词 / 引擎词都不是它的别名:谁在答是另一轴 {@link SqlEngine}(驱动探)。
|
|
118
|
+
* 本仓只这一份方言闭集(加腿 = 编译错,不是运行期的 `default` 臂)。
|
|
119
|
+
*/
|
|
120
|
+
export type SqlDialect = "mysql" | "pg";
|
|
116
121
|
export type SqlRow = Record<string, unknown>;
|
|
117
122
|
/** Normalized statement result: `rows` for SELECTs, `affected` for INSERT/UPDATE/DELETE. */
|
|
118
123
|
export interface SqlResult {
|
|
@@ -337,7 +342,7 @@ export declare function sqlWallsOf(engine: SqlEngineReading | undefined): SqlWal
|
|
|
337
342
|
* 放在某一只店里会让下一个需要它的店要么 import 一整只无关的店、要么自己抄一份(抄出来的两份会漂)。
|
|
338
343
|
*/
|
|
339
344
|
export declare const SQL_DB_NOW_MS: {
|
|
340
|
-
readonly
|
|
345
|
+
readonly mysql: "CAST(UNIX_TIMESTAMP(NOW(3)) * 1000 AS SIGNED)";
|
|
341
346
|
readonly pg: "(EXTRACT(EPOCH FROM clock_timestamp()) * 1000)::bigint";
|
|
342
347
|
};
|
|
343
348
|
/**
|
|
@@ -48,7 +48,7 @@ export function sqlWallsOf(engine) {
|
|
|
48
48
|
switch (engine.dialect) {
|
|
49
49
|
case "pg":
|
|
50
50
|
return NO_WALLS;
|
|
51
|
-
case "
|
|
51
|
+
case "mysql":
|
|
52
52
|
return SQL_FACTS_ABSENT_WALLS;
|
|
53
53
|
default: {
|
|
54
54
|
const unhandled = engine.dialect;
|
|
@@ -57,11 +57,11 @@ export function sqlWallsOf(engine) {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
export const SQL_DB_NOW_MS = {
|
|
60
|
-
|
|
60
|
+
mysql: "CAST(UNIX_TIMESTAMP(NOW(3)) * 1000 AS SIGNED)",
|
|
61
61
|
pg: "(EXTRACT(EPOCH FROM clock_timestamp()) * 1000)::bigint",
|
|
62
62
|
};
|
|
63
63
|
export async function sqlDbNowMs(db, subject) {
|
|
64
|
-
const sql =
|
|
64
|
+
const sql = `SELECT ${SQL_DB_NOW_MS[db.dialect]} AS db_now_ms`;
|
|
65
65
|
const { rows } = await db.query(sql, []);
|
|
66
66
|
const n = Number(rows[0]?.["db_now_ms"] ?? Number.NaN);
|
|
67
67
|
if (!Number.isFinite(n))
|
|
@@ -375,7 +375,7 @@ export function createCloseAwarePool(pool) {
|
|
|
375
375
|
export function mysqlDriver(pool) {
|
|
376
376
|
const session = poolSession(pool);
|
|
377
377
|
return {
|
|
378
|
-
dialect: "
|
|
378
|
+
dialect: "mysql",
|
|
379
379
|
get facts() {
|
|
380
380
|
return session.facts;
|
|
381
381
|
},
|
|
@@ -471,6 +471,6 @@ export function pgDriver(pool) {
|
|
|
471
471
|
},
|
|
472
472
|
};
|
|
473
473
|
}
|
|
474
|
-
export const dialectJsonEncoder = (dialect) => dialect === "
|
|
475
|
-
export const dialectProtocolJsonEncoder = (dialect) => dialect === "
|
|
474
|
+
export const dialectJsonEncoder = (dialect) => dialect === "mysql" ? JSON.stringify : pgSafeJsonStringify;
|
|
475
|
+
export const dialectProtocolJsonEncoder = (dialect) => dialect === "mysql" ? (v) => JSON.stringify(v) : pgProtocolJsonStringify;
|
|
476
476
|
//# sourceMappingURL=sql-driver.js.map
|
|
@@ -13,7 +13,7 @@ export function isPgUniqueViolation(err) {
|
|
|
13
13
|
return String(keyOf(err, "code")) === PG_UNIQUE_VIOLATION_SQLSTATE;
|
|
14
14
|
}
|
|
15
15
|
export function isDupKeyError(dialect, err) {
|
|
16
|
-
return dialect === "
|
|
16
|
+
return dialect === "mysql" ? isMysqlDupKeyError(err) : isPgUniqueViolation(err);
|
|
17
17
|
}
|
|
18
18
|
export const PG_UNDEFINED_COLUMN_SQLSTATE = "42703";
|
|
19
19
|
export const MYSQL_ER_BAD_FIELD_ERRNO = 1054;
|
|
@@ -5,6 +5,7 @@ import { type OutcomeSink } from "./file-outcome-sink.js";
|
|
|
5
5
|
import { type InboxWarn } from "./workflow-run-store-sql.js";
|
|
6
6
|
import { FileRunStore } from "./file-run-store.js";
|
|
7
7
|
import { type OneTimeMigrationReport } from "./one-time-migrations.js";
|
|
8
|
+
import type { LocalSessionRows } from "./local-session-window.js";
|
|
8
9
|
import type { SessionHeadReader } from "./caching-session-store.js";
|
|
9
10
|
import { LocalCheckpointStore } from "./local-checkpoint-store.js";
|
|
10
11
|
import { FileResumeAnchorStore } from "./file-resume-anchor-store.js";
|
|
@@ -16,7 +17,7 @@ import { type MemoryOptOutGrantStore } from "./memory-optout-grant-store-sql.js"
|
|
|
16
17
|
import { type SendFileLedger } from "./send-file-ledger.js";
|
|
17
18
|
import type { UserInputLedgerStore } from "../user-input-ledger.js";
|
|
18
19
|
import { TiDBResumeAnchorStore, PgResumeAnchorStore } from "./resume-anchor-store-sql.js";
|
|
19
|
-
import { type SessionPolicyStoreLogger } from "
|
|
20
|
+
import { type SessionPolicyStoreLogger } from "../stores-sql/session-policy-store-sql.js";
|
|
20
21
|
import type { ServiceConfig } from "../config-types.js";
|
|
21
22
|
import { TiDBRunStore, PgRunStore } from "./run-store-sql.js";
|
|
22
23
|
import { TiDBCheckpointStore, PgCheckpointStore } from "./checkpoint-store-sql.js";
|
|
@@ -256,11 +257,9 @@ export interface StoreBackend {
|
|
|
256
257
|
* `fileSessionCaptureRecordStore(controlDir)` 按平面现造,依托是**记忆引擎的控制面目录** ⇒ 记忆面暗的
|
|
257
258
|
* 部署上该平面不存在,于是这一支**随引擎接线门缺席**(唯一的 `undefined` 成因,逐字理由见 LocalBackend 的实装注)。
|
|
258
259
|
*
|
|
259
|
-
* 🔴
|
|
260
|
-
*
|
|
261
|
-
* (
|
|
262
|
-
* `isRemoteExecutionEnv` 的接口形鸭子判(`remote-env.js`)把本仓 host lane 一并算作 remote,
|
|
263
|
-
* 于是单机默认部署上 `memoryCapture:"off"` 两条 ingress 结构性不可达([ref])。
|
|
260
|
+
* 🔴 local 不能答 `undefined`:引擎的 `captureCarrierUnsupported`(`prepare-task.js`)判的是「这个席位在不在」而不是「文件形能不能用」,
|
|
261
|
+
* 叠上执行环境块 `hostLocalPaths` 为假 —— 本地后端上跑沙箱 / 远端车道的部署,席位缺席 ⇒ `memoryCapture:"off"` 两条 ingress 结构性不可达。
|
|
262
|
+
* (引擎按接口形判 remote 的那些版本里 host 车道也在射程;今天按块判,host 不在,供店对它是无害的同址声明。)
|
|
264
263
|
* 刻意仍不给 local 一个**内存** twin:内存形会在重启时把一条隐私记录静默丢掉(比文件三腿严格更差)。 */
|
|
265
264
|
sessionCaptureRecords(): SessionCaptureRecordSource | undefined;
|
|
266
265
|
/** Retired-epoch byte hygiene: GC grace-passed orphan `snapshot_blob` rows/objects — the whole-tree snapshot
|
|
@@ -410,6 +409,36 @@ export interface StoreBackend {
|
|
|
410
409
|
* 编辑被拒)。云形缺 MinIO ⇒ fail-loud(启动了才是假安全);`SNAPSHOT_BLOB_ALLOW_SQL_BYTES=true` =
|
|
411
410
|
* 显式接受 SQL 店 + per-blob 帽(单机/测试台形)。local 后端不经此门(file 店,无 SQL 包墙)。 */
|
|
412
411
|
export declare function assertCloudSnapshotBlobPosture(kind: "mysql" | "pg" | "local", config: Pick<ServiceConfig, "snapshotBlobStore" | "snapshotBlobAllowSql">): void;
|
|
412
|
+
/**
|
|
413
|
+
* LOCAL backend (clay 2026-06-25 seamless local↔cloud; P0.5 variant-2 + variant-1 file-backed 2026-06-26): a DB-less StoreBackend
|
|
414
|
+
* so a locally-run HTTP service serves the SAME contract a cloud worker does (runs + trace + sessions + resume;
|
|
415
|
+
* long-term memory rides the [ref] memory ENGINE, not this backend). Sessions / per-session policy / file snapshots are
|
|
416
|
+
* FILE-BACKED via core's `FileStorageBackend` over `root`, so a session SURVIVES a process restart and the resume
|
|
417
|
+
* picker (GET /v1/sessions → LocalSessionStore.listSessions) is restart-visible — the 2c "first local, then sync"
|
|
418
|
+
* hard prerequisite.
|
|
419
|
+
*
|
|
420
|
+
* The session store stays the §0.5 owner-aware {@link LocalSessionStore} wrapper, but over a fresh `FileSessionRepo`
|
|
421
|
+
* (NOT `fileBackend.sessionStore`, which is core's bare `TtlSessionStore` lacking the §0.5 owner/list/fork/delete
|
|
422
|
+
* ops); policy/snapshot delegate to the fileBackend's own file stores. The fileBackend takes a coarse boot
|
|
423
|
+
* single-instance lock on `root/LOCK` (an `O_EXCL`+`linkSync` PIDFILE, not flock — [ref] F4; same-host only:
|
|
424
|
+
* liveness = `process.kill(pid,0)`, so a foreign PID namespace or NFS defeats it, see DEPLOY-PREREQS) —
|
|
425
|
+
* `close()` MUST `dispose()` it so a graceful restart can
|
|
426
|
+
* re-acquire (a stale lock from a dead PID is pruned by core, but graceful restart relies on the release).
|
|
427
|
+
*
|
|
428
|
+
* P0.5 variant-1 (clay 2026-06-26): `run()`/`resumeAnchor()` are now FILE-backed too (FileRunStore /
|
|
429
|
+
* FileResumeAnchorStore over core 1.138.0's crash-safe fs primitives — atomicWriteFile/writeThenLink/AppendLog), so the
|
|
430
|
+
* runs ledger + trace event log + E18 anchors SURVIVE a process restart, completing variant-2's promised follow-on. The
|
|
431
|
+
* picker still lists from the session abstraction (variant-2), but a restart now also re-reads run history + resume
|
|
432
|
+
* anchors. Session owners are persisted too (7.119.0: in the session-meta sidecar, next to the incarnation — see
|
|
433
|
+
* LocalSessionStore), so an owner survives a restart like the SQL twins' column does. The cloud-only stores
|
|
434
|
+
* (checkpoint/approval/toolResult/imageIndex/imageBake/breaker/costQuota/rateLimiter) are OMITTED → the consumers'
|
|
435
|
+
* `backend?.X?.()` gates degrade them exactly like a no-DB env.
|
|
436
|
+
*/
|
|
437
|
+
/**
|
|
438
|
+
* The local session store's rows for the session view's window (`local-session-window.ts`): the local backend's own session store — its row
|
|
439
|
+
* projection and its log export — and `undefined` on any other backend. The one place that answers "is there a local store to read rows from".
|
|
440
|
+
*/
|
|
441
|
+
export declare function localSessionRowsOf(backend: StoreBackend | undefined): LocalSessionRows | undefined;
|
|
413
442
|
/**
|
|
414
443
|
* 启动日志里「跨副本 or 进程内」那一格的标签。
|
|
415
444
|
*
|
|
@@ -17,6 +17,7 @@ import { NO_SQL_MIGRATIONS, assertExecutionPlacementSwitchAdmissibleOnPool, back
|
|
|
17
17
|
import { deployedExecutionLanes } from "../execution-lane-caps.js";
|
|
18
18
|
import { assertRetiredSchemaAbsentOnPool } from "./schema-consistency.js";
|
|
19
19
|
import { LocalSessionStore, createLocalSessionRepo } from "./local-session-store.js";
|
|
20
|
+
import { SESSION_DURABILITY, SESSION_PLACEMENTS } from "./session-placement.js";
|
|
20
21
|
import { LocalCheckpointStore } from "./local-checkpoint-store.js";
|
|
21
22
|
import { FileResumeAnchorStore } from "./file-resume-anchor-store.js";
|
|
22
23
|
import { TiDBApprovalExemptionStore, PgApprovalExemptionStore, FileApprovalExemptionStore } from "./approval-exemption-store.js";
|
|
@@ -30,7 +31,7 @@ import { TiDBSendFileLedger, PgSendFileLedger, FileSendFileLedger } from "./send
|
|
|
30
31
|
import { FileUserInputLedgerStore } from "./user-input-ledger-file.js";
|
|
31
32
|
import { TiDBUserInputLedgerStore, PgUserInputLedgerStore } from "./user-input-ledger-sql.js";
|
|
32
33
|
import { TiDBResumeAnchorStore, PgResumeAnchorStore } from "./resume-anchor-store-sql.js";
|
|
33
|
-
import { TiDBSessionPolicyStore, PgSessionPolicyStore } from "
|
|
34
|
+
import { TiDBSessionPolicyStore, PgSessionPolicyStore } from "../stores-sql/session-policy-store-sql.js";
|
|
34
35
|
import { TiDBWorkflowJournalStore, PgWorkflowJournalStore } from "./workflow-journal-store-sql.js";
|
|
35
36
|
import { TiDBFileHistoryStore, PgFileHistoryStore, FILE_HISTORY_BLOB_TABLE, FILE_HISTORY_BLOB_KEY_PREFIX } from "./file-history-store-sql.js";
|
|
36
37
|
import { MinioBlobBackend, SqlBlobBackend } from "./blob-backend.js";
|
|
@@ -92,7 +93,7 @@ function legacyBlobBackend(config, dialect, pool) {
|
|
|
92
93
|
async function legacySweepImpl(config, dialect, pool) {
|
|
93
94
|
const sql = "SELECT blob_hash FROM snapshot_blob";
|
|
94
95
|
let orphans;
|
|
95
|
-
if (dialect === "
|
|
96
|
+
if (dialect === "mysql") {
|
|
96
97
|
const [rows] = await pool.query(sql);
|
|
97
98
|
orphans = rows.map((r) => String(r.blob_hash));
|
|
98
99
|
}
|
|
@@ -135,12 +136,12 @@ class TiDBBackend {
|
|
|
135
136
|
sendFileLedger() { return new TiDBSendFileLedger(this.pool); }
|
|
136
137
|
userInputLedger() { return new TiDBUserInputLedgerStore(this.pool); }
|
|
137
138
|
sessionPolicy(logger) { return new TiDBSessionPolicyStore(this.pool, logger); }
|
|
138
|
-
fileHistory() { return new TiDBFileHistoryStore(this.pool, historyBlobBackend(this.config, "
|
|
139
|
+
fileHistory() { return new TiDBFileHistoryStore(this.pool, historyBlobBackend(this.config, "mysql", this.pool), this.config.fileHistory); }
|
|
139
140
|
memoryOptOutGrant() { return new TiDBMemoryOptOutGrantStore(this.pool); }
|
|
140
141
|
sessionCaptureRecords() { return () => (this.captureRecordsInst ??= new TiDBSessionCaptureRecordStore(this.pool)); }
|
|
141
142
|
captureRecordsInst;
|
|
142
|
-
legacySnapshotBlobSweep() { return legacySweepImpl(this.config, "
|
|
143
|
-
runOneTimeMigrations() { return runSqlOneTimeMigrations("
|
|
143
|
+
legacySnapshotBlobSweep() { return legacySweepImpl(this.config, "mysql", this.pool); }
|
|
144
|
+
runOneTimeMigrations() { return runSqlOneTimeMigrations("mysql", this.pool, { lanes: deployedExecutionLanes(this.config) }); }
|
|
144
145
|
workflowJournal() { return new TiDBWorkflowJournalStore(this.pool); }
|
|
145
146
|
outcomeSink() { return new TiDBOutcomeLedger(this.pool); }
|
|
146
147
|
workflowRun(onWarn) { return new TiDBWorkflowRunStore(this.pool, onWarn); }
|
|
@@ -150,7 +151,7 @@ class TiDBBackend {
|
|
|
150
151
|
workflowParkDecisions() { return (this.parkDecisionsInst ??= new SqlWorkflowParkDecisionStore(this.run())); }
|
|
151
152
|
parkDecisionsInst;
|
|
152
153
|
sharedMemoryStore(authorizer) { return new TiDBSharedMemoryStore(this.pool, authorizer); }
|
|
153
|
-
checkpoint(logger) { return new TiDBCheckpointStore(this.pool, logger, { retention: sqlStoreRetention(this.config.retentionSweep) }); }
|
|
154
|
+
checkpoint(logger) { return new TiDBCheckpointStore(this.pool, logger, { retention: sqlStoreRetention(this.config.retentionSweep), claims: this.run() }); }
|
|
154
155
|
checkpointReadView() { return this.checkpoint(); }
|
|
155
156
|
toolResult() { return new TiDBToolResultStore(this.pool, { retention: sqlStoreRetention(this.config.retentionSweep) }); }
|
|
156
157
|
imageIndex() { return new TiDBImageIndex(this.pool); }
|
|
@@ -204,7 +205,7 @@ class PgBackend {
|
|
|
204
205
|
workflowParkDecisions() { return (this.parkDecisionsInst ??= new SqlWorkflowParkDecisionStore(this.run())); }
|
|
205
206
|
parkDecisionsInst;
|
|
206
207
|
sharedMemoryStore(authorizer) { return new PgSharedMemoryStore(this.pool, authorizer); }
|
|
207
|
-
checkpoint(logger) { return new PgCheckpointStore(this.pool, logger, { retention: sqlStoreRetention(this.config.retentionSweep) }); }
|
|
208
|
+
checkpoint(logger) { return new PgCheckpointStore(this.pool, logger, { retention: sqlStoreRetention(this.config.retentionSweep), claims: this.run() }); }
|
|
208
209
|
checkpointReadView() { return this.checkpoint(); }
|
|
209
210
|
toolResult() { return new PgToolResultStore(this.pool, { retention: sqlStoreRetention(this.config.retentionSweep) }); }
|
|
210
211
|
imageIndex() { return new PgImageIndex(this.pool); }
|
|
@@ -222,6 +223,9 @@ class PgBackend {
|
|
|
222
223
|
pgPool() { return this.pool; }
|
|
223
224
|
async dbNowMs() { const res = await this.pool.query("SELECT ROUND(EXTRACT(EPOCH FROM now())*1000) AS ms"); return Number(res.rows[0]?.ms); }
|
|
224
225
|
}
|
|
226
|
+
export function localSessionRowsOf(backend) {
|
|
227
|
+
return backend instanceof LocalBackend ? backend.session() : undefined;
|
|
228
|
+
}
|
|
225
229
|
class LocalBackend {
|
|
226
230
|
kind = "local";
|
|
227
231
|
fileBackend;
|
|
@@ -265,7 +269,11 @@ class LocalBackend {
|
|
|
265
269
|
error: (msg, fields) => void (this.onError ?? this.onWarn)?.(msg, fields),
|
|
266
270
|
strictHydrate: config.runStoreStrictHydrate,
|
|
267
271
|
});
|
|
268
|
-
this.sessionStore = new LocalSessionStore(createLocalSessionRepo(this.fileBackend.root), this.runStore, this.fileBackend.root, {
|
|
272
|
+
this.sessionStore = new LocalSessionStore(createLocalSessionRepo(this.fileBackend.root), this.runStore, this.fileBackend.root, {
|
|
273
|
+
log: createLogger(config.logLevel),
|
|
274
|
+
durability: SESSION_DURABILITY,
|
|
275
|
+
placements: SESSION_PLACEMENTS,
|
|
276
|
+
});
|
|
269
277
|
this.parkDecisionLedgerRoot = config.workflowRunStoreBackend === "memory" ? undefined : join(this.fileBackend.root, "workflows");
|
|
270
278
|
this.resumeAnchorStore = new FileResumeAnchorStore(this.fileBackend.root);
|
|
271
279
|
this.approvalExemptionStore = new FileApprovalExemptionStore(this.fileBackend.root, { warn: corruptReadWarn });
|
|
@@ -283,9 +291,12 @@ class LocalBackend {
|
|
|
283
291
|
? undefined
|
|
284
292
|
: (plane) => fileSessionCaptureRecordStore(plane?.controlDir ?? ownControlDir);
|
|
285
293
|
}
|
|
286
|
-
async ensureSchema() {
|
|
294
|
+
async ensureSchema() {
|
|
295
|
+
await this.sessionStore.settleArchiveSnapshots();
|
|
296
|
+
}
|
|
287
297
|
async runOneTimeMigrations() {
|
|
288
298
|
const holderDeathCodeRowsBackfilled = this.runStore.migrateLegacyHolderDeathCodes();
|
|
299
|
+
const archives = await this.sessionStore.migrateLocalArchives();
|
|
289
300
|
const placements = await backfillLocalExecutionPlacements(this.runStore.sessionIdsWithRuns(), this.sessionStore.executionPlacementBackfill, { lanes: this.executionLanes });
|
|
290
301
|
return {
|
|
291
302
|
...NO_SQL_MIGRATIONS,
|
|
@@ -293,6 +304,11 @@ class LocalBackend {
|
|
|
293
304
|
executionPlacementsBackfilled: placements.backfilled,
|
|
294
305
|
executionPlacementSessionsUnreadable: placements.unreadable,
|
|
295
306
|
askExecutionLanesBackfilled: backfillLocalAskExecutionLanes(this.approvalAskStore, { lanes: this.executionLanes }),
|
|
307
|
+
localArchiveRowFactsBackfilled: archives.rowFactsBackfilled,
|
|
308
|
+
localArchivesAnonymized: archives.anonymized,
|
|
309
|
+
localArchivesKeptStamped: archives.keptStamped,
|
|
310
|
+
localArchivesUnreadable: archives.unreadable,
|
|
311
|
+
localArchiveSnapshotsRecovered: archives.snapshotsRecovered,
|
|
296
312
|
};
|
|
297
313
|
}
|
|
298
314
|
async close() {
|
|
@@ -336,6 +352,7 @@ class LocalBackend {
|
|
|
336
352
|
return (this.checkpointStoreInst ??= new LocalCheckpointStore(this.fileBackend.root, {
|
|
337
353
|
getActiveTaskId: (sessionId) => this.runStore.getActiveTaskId(sessionId),
|
|
338
354
|
readSessionOwner: async (sessionId) => (await this.sessionStore.headOf(sessionId))?.owner,
|
|
355
|
+
claims: this.runStore,
|
|
339
356
|
}));
|
|
340
357
|
}
|
|
341
358
|
checkpoint() {
|
|
@@ -380,7 +397,7 @@ export function createStoreBackend(config, onWarn, onError) {
|
|
|
380
397
|
if (!config.tidb)
|
|
381
398
|
return undefined;
|
|
382
399
|
const pool = createTidbPool(config);
|
|
383
|
-
return withRetiredSchemaProbe(new TiDBBackend(pool, config), { dialect: "
|
|
400
|
+
return withRetiredSchemaProbe(new TiDBBackend(pool, config), { dialect: "mysql", pool }, { lanes: deployedExecutionLanes(config) });
|
|
384
401
|
}
|
|
385
402
|
function withRetiredSchemaProbe(inner, target, executionPlacementSwitch) {
|
|
386
403
|
const guarded = Object.create(inner);
|
|
@@ -307,6 +307,13 @@ export type CreateRunOutcome = {
|
|
|
307
307
|
activeTaskId?: undefined;
|
|
308
308
|
sessionAbsent: true;
|
|
309
309
|
};
|
|
310
|
+
/**
|
|
311
|
+
* 认领栅栏交给 `write` 的那一行 run 此刻的事实(SQL = 锁住那一行读的;进程内 = 同步段里读的)。认领与 `running` 只认 taskId,而续跑腿让同一个 taskId
|
|
312
|
+
* 停驻之后回到 `running`、认领仍在 —— 「接下这笔写的那条腿还是不是这条 run 的腿」要按腿问的写者拿它问(今天:副本 `instanceId`,续跑的 CAS 赢点把它改成接手的副本)。
|
|
313
|
+
*/
|
|
314
|
+
export interface FencedRun {
|
|
315
|
+
readonly instanceId: string | null;
|
|
316
|
+
}
|
|
310
317
|
/** SQL 认领栅栏的结局:`held: false` = 认领此刻不是这条 run 的(或它已不在跑),`write` 一次都没调。 */
|
|
311
318
|
export type ClaimFenced<T> = {
|
|
312
319
|
readonly held: true;
|
|
@@ -325,13 +332,13 @@ export type FenceLanded = typeof FENCE_LANDED;
|
|
|
325
332
|
* **宿主会话的认领当写栅栏用 —— 进程内那一形**(属主 = run 店;Memory / File 两孪生同律)。认领 = 会话 → 持有它的 taskId,
|
|
326
333
|
* 由 {@link CreateRunOutcome} 的建行(或续跑腿的 markResuming)取得、终局 / 收割放掉 —— 「这次受理还持有会话吗」只问它,不另记身份。
|
|
327
334
|
*
|
|
328
|
-
* `whileHoldingClaim(sessionId, taskId, write)`:**只有** `taskId` 此刻持有 `sessionId` 的认领、且这条 run 是活的(`running`)时才调 `write
|
|
335
|
+
* `whileHoldingClaim(sessionId, taskId, write)`:**只有** `taskId` 此刻持有 `sessionId` 的认领、且这条 run 是活的(`running`)时才调 `write`(交给它那一行的 {@link FencedRun})、答 `true`,
|
|
329
336
|
* 同一拍把这条 run 的活性戳刷新(一次栅栏写也是一次心跳);否则一次都不调、答 `false`。整只是**同步**的 —— `write` 也是:判、刷新、`write` 落定是同一个同步段,
|
|
330
337
|
* 中间没有让出,所以认领在 `write` 落定之前挪不动(这一条由类型担保 —— `write` 必须同步交回 {@link FENCE_LANDED},不靠「这里恰好没有 await」)。
|
|
331
338
|
* SQL 孪生的栅栏是一个事务(`run-store-sql.ts` `SqlRunStore.whileHoldingClaim`,`write` 收那只事务连接,结局 {@link ClaimFenced}),不是本型。
|
|
332
339
|
*/
|
|
333
340
|
export interface InProcessClaimFence {
|
|
334
|
-
whileHoldingClaim(sessionId: string, taskId: string, write: () => FenceLanded): boolean;
|
|
341
|
+
whileHoldingClaim(sessionId: string, taskId: string, write: (run: FencedRun) => FenceLanded): boolean;
|
|
335
342
|
}
|
|
336
343
|
/**
|
|
337
344
|
* `RunRecord["status"]`(= `"running" | TaskStatus`)的**唯一分类表** —— 词表的属主 = 判据的属主,
|