@sema-agent/server 7.139.0 → 7.140.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 +181 -0
- package/USAGE.md +19 -13
- package/dist/adoption/runner.js +1 -1
- package/dist/adoption/sql.js +1 -1
- package/dist/approval-card.d.ts +6 -6
- 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/execution-env.js +12 -10
- package/dist/boot/execution-lane.d.ts +8 -0
- package/dist/boot/execution-lane.js +6 -1
- package/dist/boot/memory-boundary.d.ts +14 -51
- package/dist/boot/memory-boundary.js +10 -20
- package/dist/boot/memory-consolidation.d.ts +15 -11
- package/dist/boot/memory-consolidation.js +23 -12
- package/dist/boot/resolve-spec.d.ts +3 -5
- package/dist/boot/resolve-spec.js +2 -4
- package/dist/boot/runner-deps.d.ts +3 -3
- package/dist/boot/runner-deps.js +1 -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-06-runners.d.ts +2 -6
- package/dist/boot/stage-06-runners.js +2 -2
- package/dist/boot/stage-07-capability-layer.d.ts +2 -6
- package/dist/boot/stage-08-reapers.d.ts +2 -6
- package/dist/boot/stage-09-leader.d.ts +2 -6
- package/dist/boot/stage-10-http-server.d.ts +2 -6
- package/dist/boot/stage-10-http-server.js +5 -4
- package/dist/boot/stores.d.ts +3 -6
- package/dist/boot/stores.js +27 -40
- 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 +35 -9
- package/dist/capabilities/execution-lane.d.ts +2 -2
- package/dist/config-catalog.js +2 -1
- package/dist/config-provider.d.ts +14 -13
- package/dist/config-provider.js +24 -18
- package/dist/config-types.d.ts +11 -2
- package/dist/config.js +2 -1
- package/dist/delegated-session-owner.d.ts +2 -1
- package/dist/delegated-session-owner.js +1 -1
- package/dist/deployment-shape.d.ts +9 -8
- package/dist/deployment-shape.js +4 -4
- package/dist/execution-lane-caps.d.ts +97 -106
- package/dist/execution-lane-caps.js +67 -83
- 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 +13 -16
- package/dist/http/retired-service-deps.d.ts +1 -1
- package/dist/http/retired-service-deps.js +1 -1
- package/dist/http/routes/adoption.js +1 -1
- package/dist/http/routes/memory-bundle.js +3 -0
- package/dist/http/routes/memory-compliance.js +8 -1
- 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 +5 -0
- package/dist/http/routes/sessions.js +28 -11
- package/dist/http/routes/tasks.js +4 -2
- package/dist/http/server.d.ts +5 -25
- package/dist/http/server.js +2 -2
- package/dist/identity-source.d.ts +1 -1
- package/dist/identity-source.js +1 -1
- 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/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-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 +29 -5
- package/dist/memory-scope.js +16 -4
- package/dist/memory-sync-client.d.ts +20 -7
- package/dist/memory-sync-client.js +31 -13
- 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/checkpoint-index-columns.js +2 -2
- package/dist/plugins/checkpoint-store-sql.js +16 -16
- package/dist/plugins/device-store-sql.js +19 -19
- package/dist/plugins/ensure-index.d.ts +1 -2
- package/dist/plugins/execution-placement-sql.d.ts +8 -8
- package/dist/plugins/execution-placement-sql.js +8 -8
- package/dist/plugins/file-history-store-sql.d.ts +2 -2
- package/dist/plugins/file-history-store-sql.js +4 -4
- package/dist/plugins/image-bake-store-sql.js +9 -9
- package/dist/plugins/image-index-sql.js +11 -11
- package/dist/plugins/leader-run-store-sql.js +4 -4
- 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-sync-store-tidb.js +3 -3
- package/dist/plugins/one-time-migrations.d.ts +10 -9
- package/dist/plugins/one-time-migrations.js +36 -36
- 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/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 +18 -26
- package/dist/plugins/remote-env-e2b.js +51 -4
- 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 +3 -14
- package/dist/plugins/remote-env-k8s.js +3 -2
- package/dist/plugins/remote-env-local-docker.d.ts +4 -15
- package/dist/plugins/remote-env-local-docker.js +5 -4
- 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.js +15 -15
- 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-rules-column.d.ts +1 -1
- package/dist/plugins/session-rules-column.js +1 -1
- 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 +4 -6
- package/dist/plugins/store-backend.js +6 -6
- package/dist/plugins/task-list-store-sql.js +11 -11
- package/dist/plugins/tidb-pool.js +5 -5
- package/dist/plugins/tidb-session-storage.js +4 -4
- package/dist/plugins/tidb-session-store.js +13 -13
- 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-local.js +14 -19
- package/dist/runs.d.ts +8 -4
- package/dist/runs.js +49 -65
- package/dist/session-incarnation.d.ts +1 -1
- package/dist/session-incarnation.js +1 -1
- package/dist/session-policy-wire.d.ts +1 -1
- package/dist/sql-engine-posture.d.ts +1 -1
- package/dist/sql-engine-posture.js +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.js +5 -6
- package/dist/task-mcp.d.ts +20 -7
- package/dist/task-mcp.js +17 -9
- package/dist/terminal.d.ts +27 -0
- package/dist/terminal.js +6 -0
- package/dist/trace/redact.d.ts +3 -1
- package/dist/trace/redact.js +80 -28
- package/dist/trace/self-minted-wire.d.ts +58 -0
- package/dist/trace/self-minted-wire.js +16 -0
- 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/package.json +2 -2
- package/wire-changes/server@7.140.0.json +184 -0
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
*/
|
|
51
51
|
import type { Pool as MysqlPool } from "mysql2/promise";
|
|
52
52
|
import type { Pool as PgPool } from "pg";
|
|
53
|
-
import {
|
|
53
|
+
import type { SqlDialect } from "./sql-driver.js";
|
|
54
54
|
import { type SchemaProbeRead } from "./schema-live-columns.js";
|
|
55
55
|
import { StoreBootRefusalError } from "./store-contracts.js";
|
|
56
56
|
/** 一列:名字 + 它在 `CREATE TABLE` 里的**原样定义文本**(生成 ADD COLUMN 指路用,不另手写)。 */
|
|
@@ -72,7 +72,7 @@ export interface ParsedTable {
|
|
|
72
72
|
*/
|
|
73
73
|
export declare function parseCreateTable(stmt: string): ParsedTable | undefined;
|
|
74
74
|
/** 启动时真会建出来的**全部**表形(录制 → 解析)。同名表二次出现以**先到**为准(`IF NOT EXISTS` 的真语义)。 */
|
|
75
|
-
export declare function expectedTableShapes(dialect:
|
|
75
|
+
export declare function expectedTableShapes(dialect: SqlDialect): Promise<Map<string, ParsedTable>>;
|
|
76
76
|
/** 拒启码(机读)。附录 A / 拒启码表的登记名。 */
|
|
77
77
|
export declare const SCHEMA_MISMATCH_ERROR_CODE = "config.schema_mismatch";
|
|
78
78
|
/** 一张表的对账结论。 */
|
|
@@ -96,13 +96,13 @@ export declare function diffSchema(expected: Map<string, ParsedTable>, live: Map
|
|
|
96
96
|
*/
|
|
97
97
|
export declare function describeMismatchedTables(mismatches: readonly TableMismatch[]): string[];
|
|
98
98
|
/** 拒启文案(表头 + 逐表段与闭集三条出路 {@link describeMismatchedTables})。 */
|
|
99
|
-
export declare function describeSchemaMismatch(dialect:
|
|
99
|
+
export declare function describeSchemaMismatch(dialect: SqlDialect, mismatches: readonly TableMismatch[]): string;
|
|
100
100
|
/**
|
|
101
101
|
* 启动期对账:**建表之后**跑,不符即抛(= 拒启)。两方言 + InnoDB 同腿(MySQL 协议共用 `mysql` 臂)。
|
|
102
102
|
*
|
|
103
103
|
* 失败方向见文件头注:读抛 / 整库零行 ⇒ 拒。
|
|
104
104
|
*/
|
|
105
|
-
export declare function assertSchemaMatchesCode(read: SchemaProbeRead, dialect:
|
|
105
|
+
export declare function assertSchemaMatchesCode(read: SchemaProbeRead, dialect: SqlDialect): Promise<void>;
|
|
106
106
|
/**
|
|
107
107
|
* 跳版升级的库的拒启:退役 schema(快照索引表 / 单座列)任一仍在。**具名类型**:锚类型不锚文案(日志消费端与测试按 `code` / 类型分派);
|
|
108
108
|
* 码取列册对账同一个 `config.schema_mismatch`,运维面一个拒启码一个读法。拒句点名在场的坐标、说明第三条(旧拼法改写)同样没跑过、给出路。
|
|
@@ -119,10 +119,10 @@ export declare class RetiredSchemaPresentError extends StoreBootRefusalError {
|
|
|
119
119
|
* 快照索引表 / 单座列任一在场 ⇒ 抛 {@link RetiredSchemaPresentError}。新库(建表之前一列都没有)⇒ 不在场、过。读抛 ⇒ 原样上抛(拒启;不是确定的拒启表态,
|
|
120
120
|
* 开库等待窗照常重试 —— 与修前两条目录探针抛出时同一个去向)。
|
|
121
121
|
*/
|
|
122
|
-
export declare function assertRetiredSchemaAbsent(read: SchemaProbeRead, dialect:
|
|
122
|
+
export declare function assertRetiredSchemaAbsent(read: SchemaProbeRead, dialect: SqlDialect): Promise<void>;
|
|
123
123
|
/** 探针口的池参数:方言与它的池一起走(判别联合 ⇒ 不靠调用方断言「这个池是哪种」)。 */
|
|
124
124
|
export type RetiredSchemaProbeTarget = {
|
|
125
|
-
readonly dialect: "
|
|
125
|
+
readonly dialect: "mysql";
|
|
126
126
|
readonly pool: MysqlPool;
|
|
127
127
|
} | {
|
|
128
128
|
readonly dialect: "pg";
|
|
@@ -199,7 +199,7 @@ export async function assertRetiredSchemaAbsent(read, dialect) {
|
|
|
199
199
|
throw new RetiredSchemaPresentError(found);
|
|
200
200
|
}
|
|
201
201
|
export async function assertRetiredSchemaAbsentOnPool(target) {
|
|
202
|
-
if (target.dialect === "
|
|
202
|
+
if (target.dialect === "mysql") {
|
|
203
203
|
const conn = await target.pool.getConnection();
|
|
204
204
|
try {
|
|
205
205
|
await assertRetiredSchemaAbsent(async (sql) => (await conn.query(sql))[0], "mysql");
|
|
@@ -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 {
|
|
@@ -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
|
|
@@ -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;
|
|
@@ -16,7 +16,7 @@ import { type MemoryOptOutGrantStore } from "./memory-optout-grant-store-sql.js"
|
|
|
16
16
|
import { type SendFileLedger } from "./send-file-ledger.js";
|
|
17
17
|
import type { UserInputLedgerStore } from "../user-input-ledger.js";
|
|
18
18
|
import { TiDBResumeAnchorStore, PgResumeAnchorStore } from "./resume-anchor-store-sql.js";
|
|
19
|
-
import { type SessionPolicyStoreLogger } from "
|
|
19
|
+
import { type SessionPolicyStoreLogger } from "../stores-sql/session-policy-store-sql.js";
|
|
20
20
|
import type { ServiceConfig } from "../config-types.js";
|
|
21
21
|
import { TiDBRunStore, PgRunStore } from "./run-store-sql.js";
|
|
22
22
|
import { TiDBCheckpointStore, PgCheckpointStore } from "./checkpoint-store-sql.js";
|
|
@@ -256,11 +256,9 @@ export interface StoreBackend {
|
|
|
256
256
|
* `fileSessionCaptureRecordStore(controlDir)` 按平面现造,依托是**记忆引擎的控制面目录** ⇒ 记忆面暗的
|
|
257
257
|
* 部署上该平面不存在,于是这一支**随引擎接线门缺席**(唯一的 `undefined` 成因,逐字理由见 LocalBackend 的实装注)。
|
|
258
258
|
*
|
|
259
|
-
* 🔴
|
|
260
|
-
*
|
|
261
|
-
* (
|
|
262
|
-
* `isRemoteExecutionEnv` 的接口形鸭子判(`remote-env.js`)把本仓 host lane 一并算作 remote,
|
|
263
|
-
* 于是单机默认部署上 `memoryCapture:"off"` 两条 ingress 结构性不可达([ref])。
|
|
259
|
+
* 🔴 local 不能答 `undefined`:引擎的 `captureCarrierUnsupported`(`prepare-task.js`)判的是「这个席位在不在」而不是「文件形能不能用」,
|
|
260
|
+
* 叠上执行环境块 `hostLocalPaths` 为假 —— 本地后端上跑沙箱 / 远端车道的部署,席位缺席 ⇒ `memoryCapture:"off"` 两条 ingress 结构性不可达。
|
|
261
|
+
* (引擎按接口形判 remote 的那些版本里 host 车道也在射程;今天按块判,host 不在,供店对它是无害的同址声明。)
|
|
264
262
|
* 刻意仍不给 local 一个**内存** twin:内存形会在重启时把一条隐私记录静默丢掉(比文件三腿严格更差)。 */
|
|
265
263
|
sessionCaptureRecords(): SessionCaptureRecordSource | undefined;
|
|
266
264
|
/** Retired-epoch byte hygiene: GC grace-passed orphan `snapshot_blob` rows/objects — the whole-tree snapshot
|
|
@@ -30,7 +30,7 @@ import { TiDBSendFileLedger, PgSendFileLedger, FileSendFileLedger } from "./send
|
|
|
30
30
|
import { FileUserInputLedgerStore } from "./user-input-ledger-file.js";
|
|
31
31
|
import { TiDBUserInputLedgerStore, PgUserInputLedgerStore } from "./user-input-ledger-sql.js";
|
|
32
32
|
import { TiDBResumeAnchorStore, PgResumeAnchorStore } from "./resume-anchor-store-sql.js";
|
|
33
|
-
import { TiDBSessionPolicyStore, PgSessionPolicyStore } from "
|
|
33
|
+
import { TiDBSessionPolicyStore, PgSessionPolicyStore } from "../stores-sql/session-policy-store-sql.js";
|
|
34
34
|
import { TiDBWorkflowJournalStore, PgWorkflowJournalStore } from "./workflow-journal-store-sql.js";
|
|
35
35
|
import { TiDBFileHistoryStore, PgFileHistoryStore, FILE_HISTORY_BLOB_TABLE, FILE_HISTORY_BLOB_KEY_PREFIX } from "./file-history-store-sql.js";
|
|
36
36
|
import { MinioBlobBackend, SqlBlobBackend } from "./blob-backend.js";
|
|
@@ -92,7 +92,7 @@ function legacyBlobBackend(config, dialect, pool) {
|
|
|
92
92
|
async function legacySweepImpl(config, dialect, pool) {
|
|
93
93
|
const sql = "SELECT blob_hash FROM snapshot_blob";
|
|
94
94
|
let orphans;
|
|
95
|
-
if (dialect === "
|
|
95
|
+
if (dialect === "mysql") {
|
|
96
96
|
const [rows] = await pool.query(sql);
|
|
97
97
|
orphans = rows.map((r) => String(r.blob_hash));
|
|
98
98
|
}
|
|
@@ -135,12 +135,12 @@ class TiDBBackend {
|
|
|
135
135
|
sendFileLedger() { return new TiDBSendFileLedger(this.pool); }
|
|
136
136
|
userInputLedger() { return new TiDBUserInputLedgerStore(this.pool); }
|
|
137
137
|
sessionPolicy(logger) { return new TiDBSessionPolicyStore(this.pool, logger); }
|
|
138
|
-
fileHistory() { return new TiDBFileHistoryStore(this.pool, historyBlobBackend(this.config, "
|
|
138
|
+
fileHistory() { return new TiDBFileHistoryStore(this.pool, historyBlobBackend(this.config, "mysql", this.pool), this.config.fileHistory); }
|
|
139
139
|
memoryOptOutGrant() { return new TiDBMemoryOptOutGrantStore(this.pool); }
|
|
140
140
|
sessionCaptureRecords() { return () => (this.captureRecordsInst ??= new TiDBSessionCaptureRecordStore(this.pool)); }
|
|
141
141
|
captureRecordsInst;
|
|
142
|
-
legacySnapshotBlobSweep() { return legacySweepImpl(this.config, "
|
|
143
|
-
runOneTimeMigrations() { return runSqlOneTimeMigrations("
|
|
142
|
+
legacySnapshotBlobSweep() { return legacySweepImpl(this.config, "mysql", this.pool); }
|
|
143
|
+
runOneTimeMigrations() { return runSqlOneTimeMigrations("mysql", this.pool, { lanes: deployedExecutionLanes(this.config) }); }
|
|
144
144
|
workflowJournal() { return new TiDBWorkflowJournalStore(this.pool); }
|
|
145
145
|
outcomeSink() { return new TiDBOutcomeLedger(this.pool); }
|
|
146
146
|
workflowRun(onWarn) { return new TiDBWorkflowRunStore(this.pool, onWarn); }
|
|
@@ -380,7 +380,7 @@ export function createStoreBackend(config, onWarn, onError) {
|
|
|
380
380
|
if (!config.tidb)
|
|
381
381
|
return undefined;
|
|
382
382
|
const pool = createTidbPool(config);
|
|
383
|
-
return withRetiredSchemaProbe(new TiDBBackend(pool, config), { dialect: "
|
|
383
|
+
return withRetiredSchemaProbe(new TiDBBackend(pool, config), { dialect: "mysql", pool }, { lanes: deployedExecutionLanes(config) });
|
|
384
384
|
}
|
|
385
385
|
function withRetiredSchemaProbe(inner, target, executionPlacementSwitch) {
|
|
386
386
|
const guarded = Object.create(inner);
|
|
@@ -68,33 +68,33 @@ export async function ensurePgTaskListSchema(q) {
|
|
|
68
68
|
)`);
|
|
69
69
|
}
|
|
70
70
|
async function ensureMeta(exec, dialect, listKey) {
|
|
71
|
-
await exec(dialect === "
|
|
71
|
+
await exec(dialect === "mysql"
|
|
72
72
|
? `INSERT INTO ${TASK_LIST_META_TABLE} (list_key, next_id, next_sort) VALUES (?, 1, 1) ON DUPLICATE KEY UPDATE list_key = list_key`
|
|
73
73
|
: `INSERT INTO ${TASK_LIST_META_TABLE} (list_key, next_id, next_sort) VALUES ($1, 1, 1) ON CONFLICT (list_key) DO NOTHING`, [listKey]);
|
|
74
74
|
}
|
|
75
75
|
async function allocateOn(exec, dialect, listKey) {
|
|
76
76
|
await ensureMeta(exec, dialect, listKey);
|
|
77
|
-
const rows = await exec(dialect === "
|
|
77
|
+
const rows = await exec(dialect === "mysql"
|
|
78
78
|
? `SELECT next_id FROM ${TASK_LIST_META_TABLE} WHERE list_key = ? FOR UPDATE`
|
|
79
79
|
: `SELECT next_id FROM ${TASK_LIST_META_TABLE} WHERE list_key = $1 FOR UPDATE`, [listKey]);
|
|
80
80
|
const id = Number(rows[0].next_id);
|
|
81
|
-
await exec(dialect === "
|
|
81
|
+
await exec(dialect === "mysql"
|
|
82
82
|
? `UPDATE ${TASK_LIST_META_TABLE} SET next_id = ? WHERE list_key = ?`
|
|
83
83
|
: `UPDATE ${TASK_LIST_META_TABLE} SET next_id = $1 WHERE list_key = $2`, [id + 1, listKey]);
|
|
84
84
|
return String(id);
|
|
85
85
|
}
|
|
86
86
|
async function setOn(exec, dialect, listKey, id, itemJson) {
|
|
87
87
|
await ensureMeta(exec, dialect, listKey);
|
|
88
|
-
const rows = await exec(dialect === "
|
|
88
|
+
const rows = await exec(dialect === "mysql"
|
|
89
89
|
? `SELECT next_sort FROM ${TASK_LIST_META_TABLE} WHERE list_key = ? FOR UPDATE`
|
|
90
90
|
: `SELECT next_sort FROM ${TASK_LIST_META_TABLE} WHERE list_key = $1 FOR UPDATE`, [listKey]);
|
|
91
91
|
const sort = Number(rows[0].next_sort);
|
|
92
|
-
await exec(dialect === "
|
|
92
|
+
await exec(dialect === "mysql"
|
|
93
93
|
? `INSERT INTO ${TASK_LIST_ITEM_TABLE} (list_key, id, id_num, sort_seq, item_json) VALUES (?, ?, ?, ?, ?)
|
|
94
94
|
ON DUPLICATE KEY UPDATE item_json = VALUES(item_json)`
|
|
95
95
|
: `INSERT INTO ${TASK_LIST_ITEM_TABLE} (list_key, id, id_num, sort_seq, item_json) VALUES ($1, $2, $3, $4, $5)
|
|
96
96
|
ON CONFLICT (list_key, id) DO UPDATE SET item_json = EXCLUDED.item_json`, [listKey, id, arrayIndexOf(id), sort, itemJson]);
|
|
97
|
-
await exec(dialect === "
|
|
97
|
+
await exec(dialect === "mysql"
|
|
98
98
|
? `UPDATE ${TASK_LIST_META_TABLE} SET next_sort = ? WHERE list_key = ?`
|
|
99
99
|
: `UPDATE ${TASK_LIST_META_TABLE} SET next_sort = $1 WHERE list_key = $2`, [sort + 1, listKey]);
|
|
100
100
|
}
|
|
@@ -160,29 +160,29 @@ export function createTiDBTaskListStore(pool, listKey) {
|
|
|
160
160
|
};
|
|
161
161
|
const build = (q, inTx) => ({
|
|
162
162
|
get: async (id) => {
|
|
163
|
-
const [rows] = (await q.query(`SELECT ${jsonColumnText("
|
|
163
|
+
const [rows] = (await q.query(`SELECT ${jsonColumnText("mysql", "item_json")} FROM ${TASK_LIST_ITEM_TABLE} WHERE list_key = ? AND id = ?${inTx ? " FOR UPDATE" : ""}`, [listKey, id]));
|
|
164
164
|
return rows.length > 0 ? parseItem(rows[0].item_json, `for list ${listKey} item ${JSON.stringify(id)}`) : undefined;
|
|
165
165
|
},
|
|
166
166
|
set: async (id, item) => {
|
|
167
167
|
if (item.metadata)
|
|
168
168
|
assertJsonMetadata(item.metadata);
|
|
169
169
|
const json = JSON.stringify(item);
|
|
170
|
-
await (inTx ? setOn(execOn(q), "
|
|
170
|
+
await (inTx ? setOn(execOn(q), "mysql", listKey, id, json) : tx((c) => setOn(execOn(c), "mysql", listKey, id, json)));
|
|
171
171
|
},
|
|
172
172
|
delete: async (id) => {
|
|
173
173
|
const [res] = (await q.query(`DELETE FROM ${TASK_LIST_ITEM_TABLE} WHERE list_key = ? AND id = ?`, [listKey, id]));
|
|
174
174
|
return res.affectedRows === 1;
|
|
175
175
|
},
|
|
176
176
|
list: async () => {
|
|
177
|
-
const [rows] = (await q.query(`SELECT ${jsonColumnText("
|
|
177
|
+
const [rows] = (await q.query(`SELECT ${jsonColumnText("mysql", "item_json")} FROM ${TASK_LIST_ITEM_TABLE} WHERE list_key = ? ORDER BY id_num IS NULL, id_num, sort_seq${inTx ? " FOR UPDATE" : ""}`, [listKey]));
|
|
178
178
|
return rows.map((r) => parseItem(r.item_json, `for list ${listKey} (enumeration)`));
|
|
179
179
|
},
|
|
180
|
-
allocateId: async () => (inTx ? allocateOn(execOn(q), "
|
|
180
|
+
allocateId: async () => (inTx ? allocateOn(execOn(q), "mysql", listKey) : tx((c) => allocateOn(execOn(c), "mysql", listKey))),
|
|
181
181
|
...(inTx
|
|
182
182
|
? {}
|
|
183
183
|
: {
|
|
184
184
|
mutate: (fn) => tx(async (c) => {
|
|
185
|
-
await ensureMeta(execOn(c), "
|
|
185
|
+
await ensureMeta(execOn(c), "mysql", listKey);
|
|
186
186
|
await c.query(`SELECT next_id FROM ${TASK_LIST_META_TABLE} WHERE list_key = ? FOR UPDATE`, [listKey]);
|
|
187
187
|
return fn(build(c, true));
|
|
188
188
|
}),
|
|
@@ -79,7 +79,7 @@ export const SCHEMA_STATEMENTS = [
|
|
|
79
79
|
-- NULL = 还没有任何腿记过;唯一写者 = 腿的记录座(src/session-workspace.ts),列属主 = src/plugins/session-workspace-cell.ts
|
|
80
80
|
-- (列定义、形读者、编解码;存量库缺这一列 ⇒ 起服列册对账拒启,拒句里给出 ALTER)。下一条腿的 TaskSpec.projectId 读它的 project.id。
|
|
81
81
|
-- 服务端元数据:不进 wire 会话面、不进模型上下文;住在会话行上 ⇒ 随会话删除 / 留存清扫一起消失,fork 出的新行为 NULL。
|
|
82
|
-
${SESSION_META_WORKSPACE_COLUMN.
|
|
82
|
+
${SESSION_META_WORKSPACE_COLUMN.mysql},
|
|
83
83
|
-- #292 C18(core 5.48.0 design/323)subagent 转录持久化 —— placement 元组,**创建时一次落行、
|
|
84
84
|
-- first-write 不可变**(register 的 ON DUPLICATE 臂永不重写这六列)。判别位 = placement_kind:
|
|
85
85
|
-- 在场 ⇒ 该会话住在 placement 分区里(不上宿主枚举、claim 形 acquire 恒拒、release=真删除、
|
|
@@ -96,12 +96,12 @@ export const SCHEMA_STATEMENTS = [
|
|
|
96
96
|
-- 无 id 创建 / fork / 导入新行),删除随行消失,同 id 重登记铸新的;'' = 没铸过,读口响亮拒。列定义的唯一属主 =
|
|
97
97
|
-- src/session-incarnation.ts 的 SESSION_META_INCARNATION_COLUMN(存量库缺这一列 ⇒ 起服列册对账拒启,拒句里的 ALTER 由本建表语句生成)。
|
|
98
98
|
-- 不上 wire、不进模型上下文、日志只打前 8 位。
|
|
99
|
-
${SESSION_META_INCARNATION_COLUMN.
|
|
99
|
+
${SESSION_META_INCARNATION_COLUMN.mysql},
|
|
100
100
|
-- 执行放置:根会话行上**这一位住客**的一格 —— execution_role('writer' | 'mirror' | NULL = absent)、execution_lane、device 车道的设备与绑定属主、
|
|
101
101
|
-- 放下时刻、换绑序号;写只按住客谓词 (session_id, incarnation, owner) ∧ placement_kind IS NULL(换了住客 = 这一格不在)。fork_key = 建这一行的那次
|
|
102
102
|
-- fork 请求的键(只由 fork 创建点写,此后每个写携带)。规则在 src/execution-placement.ts,列定义与语句的唯一属主 = src/plugins/execution-placement-sql.ts
|
|
103
103
|
-- (存量库缺这些列 ⇒ 起服列册对账拒启;加列只由一次性迁移做)。
|
|
104
|
-
${sessionMetaPlacementColumnsDdl("
|
|
104
|
+
${sessionMetaPlacementColumnsDdl("mysql")},
|
|
105
105
|
PRIMARY KEY (session_id),
|
|
106
106
|
KEY idx_session_meta_owner (owner),
|
|
107
107
|
-- listPlaced 的检索腿(kind + 租户 + 年龄升序);普通会话这三列全 NULL ⇒ 不占索引选择性。
|
|
@@ -173,7 +173,7 @@ export const SCHEMA_STATEMENTS = [
|
|
|
173
173
|
-- (rows from before these columns, unauthenticated-write acceptance, a run someone else accepted on the owner's behalf) ⇒ not
|
|
174
174
|
-- qualified. Column definitions' single owner = src/identity-source.ts RUN_IDENTITY_COLUMNS (the boot column probe derives its
|
|
175
175
|
-- ALTER suggestion from this statement). \`source\` above is attribution only, never an authentication source.
|
|
176
|
-
${RUN_IDENTITY_COLUMNS.
|
|
176
|
+
${RUN_IDENTITY_COLUMNS.mysql},
|
|
177
177
|
-- objective_preview: the list's "what is this task" glance — redacted + truncated at write.
|
|
178
178
|
objective_preview VARCHAR(160) NULL,
|
|
179
179
|
-- cancel_requested: durable cross-replica CANCEL flag. The running instance's heartbeat tick honors it
|
|
@@ -463,7 +463,7 @@ export const SCHEMA_STATEMENTS = [
|
|
|
463
463
|
principal VARCHAR(190) NULL,
|
|
464
464
|
-- 会话规则(三只桶,引擎的规则条目文法)。列定义唯一属主 = src/plugins/session-rules-column.ts 的 SESSION_RULES_COLUMN(一列一文法:
|
|
465
465
|
-- 7.128.x 及以前这一列叫 rules、按整串工具名读;存量库由一次性迁移 M17 改名,带退役命令桶的行原样留着、读回判坏并逐行点名,见那份文件与 one-time-migrations.ts)。
|
|
466
|
-
${SESSION_RULES_COLUMN.
|
|
466
|
+
${SESSION_RULES_COLUMN.mysql},
|
|
467
467
|
rev BIGINT NOT NULL,
|
|
468
468
|
-- gen (core 7.25.0 StoredSessionRules.gen, S-529 二期):这一行的**血统**。rev 只在一条血统内计数,
|
|
469
469
|
-- deleteBySession 终结血统并把下一代的号留在 session_policy_rev_mark.gen 上,于是活规则读者能把
|
|
@@ -9,8 +9,8 @@ import { jsonColumnText } from "./sql-json-column.js";
|
|
|
9
9
|
import { incarnationFromCell } from "../session-incarnation.js";
|
|
10
10
|
const SESSION_EVENT_BY_TYPE_HINT = "/*+ USE_INDEX(session_event, idx_session_event_type) */";
|
|
11
11
|
export const SESSION_EVENT_LATEST_BY_TYPE_SQL = {
|
|
12
|
-
floor: `SELECT ${SESSION_EVENT_BY_TYPE_HINT} ${jsonColumnText("
|
|
13
|
-
epochAnchor: `SELECT ${SESSION_EVENT_BY_TYPE_HINT} seq, ${jsonColumnText("
|
|
12
|
+
floor: `SELECT ${SESSION_EVENT_BY_TYPE_HINT} ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? AND type = 'compaction' ORDER BY seq DESC LIMIT 1`,
|
|
13
|
+
epochAnchor: `SELECT ${SESSION_EVENT_BY_TYPE_HINT} seq, ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? AND seq < ? AND type IN ('prompt_epoch','compaction') ORDER BY seq DESC LIMIT 100`,
|
|
14
14
|
};
|
|
15
15
|
const isDupKey = isMysqlDupKeyError;
|
|
16
16
|
export class TiDBSessionStorage extends BaseSessionStorage {
|
|
@@ -35,7 +35,7 @@ export class TiDBSessionStorage extends BaseSessionStorage {
|
|
|
35
35
|
if (!meta)
|
|
36
36
|
return null;
|
|
37
37
|
const { floorEntryId, floorSeq } = await TiDBSessionStorage.computeFloor(pool, sessionId);
|
|
38
|
-
const [eventRows] = await pool.query(`SELECT seq, ${jsonColumnText("
|
|
38
|
+
const [eventRows] = await pool.query(`SELECT seq, ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? AND seq >= ? ORDER BY seq ASC`, [sessionId, floorSeq]);
|
|
39
39
|
const entries = eventRows.map((r) => decodeSessionEventPayload(r.payload, sessionId, r.seq));
|
|
40
40
|
const placement = placementFromRow(meta);
|
|
41
41
|
const metadata = { id: sessionId, createdAt: toIso(meta.created_at), incarnation: incarnationFromCell(sessionId, meta.incarnation), ...(placement !== undefined ? { placement } : {}) };
|
|
@@ -58,7 +58,7 @@ export class TiDBSessionStorage extends BaseSessionStorage {
|
|
|
58
58
|
const inMem = await super.getEntry(id);
|
|
59
59
|
if (inMem)
|
|
60
60
|
return inMem;
|
|
61
|
-
const [rows] = await this.pool.query(`SELECT ${jsonColumnText("
|
|
61
|
+
const [rows] = await this.pool.query(`SELECT ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? AND entry_id = ?`, [this.sessionId, id]);
|
|
62
62
|
if (rows[0] === undefined)
|
|
63
63
|
return undefined;
|
|
64
64
|
return decodeSessionEventPayload(rows[0].payload, this.sessionId, id);
|
|
@@ -89,7 +89,7 @@ export class TiDBSessionStore {
|
|
|
89
89
|
}, this.log);
|
|
90
90
|
}
|
|
91
91
|
async claimOwnerless(sessionId, incarnation, owner) {
|
|
92
|
-
const [res] = await this.pool.query(CLAIM_OWNERLESS_PLACED_SQL.
|
|
92
|
+
const [res] = await this.pool.query(CLAIM_OWNERLESS_PLACED_SQL.mysql, [...claimOwnerlessParams(sessionId, incarnation, owner)]);
|
|
93
93
|
return res.affectedRows > 0;
|
|
94
94
|
}
|
|
95
95
|
async sourceFaces(ids) {
|
|
@@ -256,7 +256,7 @@ export class TiDBSessionStore {
|
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
async readSessionWorkspace(sessionId) {
|
|
259
|
-
const [rows] = await this.pool.query(`SELECT ${jsonColumnText("
|
|
259
|
+
const [rows] = await this.pool.query(`SELECT ${jsonColumnText("mysql", "workspace")} FROM session_meta WHERE session_id = ?`, [sessionId]);
|
|
260
260
|
const row = rows[0];
|
|
261
261
|
return row === undefined ? undefined : decodeSessionWorkspaceCell(row.workspace, sessionId);
|
|
262
262
|
}
|
|
@@ -284,7 +284,7 @@ export class TiDBSessionStore {
|
|
|
284
284
|
if (storage === null)
|
|
285
285
|
return null;
|
|
286
286
|
const point = await forkPointOf(storage);
|
|
287
|
-
const [allRows] = await this.pool.query(`SELECT entry_id, parent_id, type, ${jsonColumnText("
|
|
287
|
+
const [allRows] = await this.pool.query(`SELECT entry_id, parent_id, type, ${jsonColumnText("mysql", "payload")}, ts FROM session_event WHERE session_id = ? ORDER BY seq ASC`, [sourceId]);
|
|
288
288
|
const { rows: eventRows, leafId: forkLeafId } = selectForkRows(allRows, leafId, point, FORK_LOG_ROW_SHAPE);
|
|
289
289
|
const now = new Date();
|
|
290
290
|
const conn = await this.pool.getConnection();
|
|
@@ -329,7 +329,7 @@ export class TiDBSessionStore {
|
|
|
329
329
|
const [metaRows] = await this.pool.query("SELECT 1 FROM session_meta WHERE session_id = ?", [sessionId]);
|
|
330
330
|
if (!metaRows[0])
|
|
331
331
|
return null;
|
|
332
|
-
const [eventRows] = await this.pool.query(`SELECT seq, entry_id, parent_id, type, ${jsonColumnText("
|
|
332
|
+
const [eventRows] = await this.pool.query(`SELECT seq, entry_id, parent_id, type, ${jsonColumnText("mysql", "payload")}, ts FROM session_event WHERE session_id = ? ORDER BY seq ASC`, [sessionId]);
|
|
333
333
|
return eventRows.map((r) => decodeSessionEventPayload(r.payload, sessionId, r.seq));
|
|
334
334
|
}
|
|
335
335
|
async listEntryIds(sessionId) {
|
|
@@ -348,7 +348,7 @@ export class TiDBSessionStore {
|
|
|
348
348
|
async function* gen() {
|
|
349
349
|
let cursor = opts?.afterSeq ?? -1;
|
|
350
350
|
for (;;) {
|
|
351
|
-
const [rows] = await pool.query(`SELECT seq, ${jsonColumnText("
|
|
351
|
+
const [rows] = await pool.query(`SELECT seq, ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? AND seq > ? ORDER BY seq ASC LIMIT ?`, [sessionId, cursor, batchSize]);
|
|
352
352
|
for (const r of rows)
|
|
353
353
|
yield decodeSessionEventPayload(r.payload, sessionId, r.seq);
|
|
354
354
|
if (rows.length < batchSize)
|
|
@@ -431,7 +431,7 @@ export class TiDBSessionStore {
|
|
|
431
431
|
throw new SessionError("storage", `import of session ${sessionId} failed`, new Error(`session ${sessionId} already exists — importEntries only creates a session (replaceEntries rewrites one); nothing was written`));
|
|
432
432
|
}
|
|
433
433
|
}
|
|
434
|
-
const claim = await lockRootAndReadClaim(rowsOnConnection(conn), "
|
|
434
|
+
const claim = await lockRootAndReadClaim(rowsOnConnection(conn), "mysql", sessionId);
|
|
435
435
|
if (claim.activeTaskId !== null)
|
|
436
436
|
throw new SessionActiveRunError(sessionId, claim.activeTaskId);
|
|
437
437
|
if (mode === "replace")
|
|
@@ -451,7 +451,7 @@ export class TiDBSessionStore {
|
|
|
451
451
|
}
|
|
452
452
|
}
|
|
453
453
|
async readStagedEntries(stagingId) {
|
|
454
|
-
const [rows] = await this.pool.query(`SELECT seq, ${jsonColumnText("
|
|
454
|
+
const [rows] = await this.pool.query(`SELECT seq, ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? ORDER BY seq ASC`, [stagingId]);
|
|
455
455
|
return rows.map((r) => decodeSessionEventPayload(r.payload, stagingId, r.seq));
|
|
456
456
|
}
|
|
457
457
|
async sweepStagingSessions() {
|
|
@@ -470,7 +470,7 @@ export class TiDBSessionStore {
|
|
|
470
470
|
const conn = await this.pool.getConnection();
|
|
471
471
|
try {
|
|
472
472
|
await conn.beginTransaction();
|
|
473
|
-
const claim = await lockRootAndReadClaim(rowsOnConnection(conn), "
|
|
473
|
+
const claim = await lockRootAndReadClaim(rowsOnConnection(conn), "mysql", sessionId);
|
|
474
474
|
if (claim.activeTaskId !== null) {
|
|
475
475
|
await conn.rollback();
|
|
476
476
|
throw new SessionActiveRunError(sessionId, claim.activeTaskId);
|
|
@@ -553,7 +553,7 @@ class TiDBStagingHandle {
|
|
|
553
553
|
throw new StagedCommitOwnerChangedError(this.realSessionId);
|
|
554
554
|
}
|
|
555
555
|
}
|
|
556
|
-
const claim = await lockRootAndReadClaim(rowsOnConnection(conn), "
|
|
556
|
+
const claim = await lockRootAndReadClaim(rowsOnConnection(conn), "mysql", this.realSessionId);
|
|
557
557
|
if (claim.activeTaskId !== null) {
|
|
558
558
|
await conn.rollback();
|
|
559
559
|
throw new SessionActiveRunError(this.realSessionId, claim.activeTaskId);
|
|
@@ -573,8 +573,8 @@ class TiDBStagingHandle {
|
|
|
573
573
|
throw new SyncConflictError(this.realSessionId, rel);
|
|
574
574
|
}
|
|
575
575
|
if (rel.relation === "fast_forward" && opts.resolution !== "overwrite-dst" && dstIds !== null && dstIds.length > 0) {
|
|
576
|
-
const [dstFull] = await conn.query(`SELECT seq, ${jsonColumnText("
|
|
577
|
-
const [stagedFull] = await conn.query(`SELECT entry_id, ${jsonColumnText("
|
|
576
|
+
const [dstFull] = await conn.query(`SELECT seq, ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? ORDER BY seq ASC FOR UPDATE`, [this.realSessionId]);
|
|
577
|
+
const [stagedFull] = await conn.query(`SELECT entry_id, ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? ORDER BY seq ASC FOR UPDATE`, [this.stagingId]);
|
|
578
578
|
const dstSet = new Set(dstIds);
|
|
579
579
|
const dstEntries = dstFull.map((r) => decodeSessionEventPayload(r.payload, this.realSessionId, r.seq));
|
|
580
580
|
const stagedShared = stagedFull
|
|
@@ -588,13 +588,13 @@ class TiDBStagingHandle {
|
|
|
588
588
|
}
|
|
589
589
|
await conn.query("DELETE FROM session_event WHERE session_id = ?", [this.realSessionId]);
|
|
590
590
|
await conn.query("UPDATE session_event SET session_id = ? WHERE session_id = ?", [this.realSessionId, this.stagingId]);
|
|
591
|
-
const [lastRow] = await conn.query(`SELECT ${jsonColumnText("
|
|
591
|
+
const [lastRow] = await conn.query(`SELECT ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? ORDER BY seq DESC LIMIT 1 FOR UPDATE`, [this.realSessionId]);
|
|
592
592
|
let leafId = null;
|
|
593
593
|
if (lastRow[0])
|
|
594
594
|
leafId = leafIdAfterEntry(decodeSessionEventPayload(lastRow[0].payload, this.realSessionId, "last staged row"));
|
|
595
595
|
const [settle] = await conn.query(`UPDATE session_meta SET owner = ?, updated_at = ?, leaf_id = ?, leaf_seq = ?, ${MIRROR_ON_COMMIT_SET} WHERE session_id = ? AND ${MIRROR_ON_COMMIT_GUARD}`, [owner, now, leafId, srcIds.length, this.realSessionId]);
|
|
596
596
|
if (settle.affectedRows !== 1) {
|
|
597
|
-
const locked = readPlacementRowStatement("
|
|
597
|
+
const locked = readPlacementRowStatement("mysql", this.realSessionId, { lock: true });
|
|
598
598
|
const [lockedRows] = await conn.query(locked.text, [...locked.values]);
|
|
599
599
|
const cell = lockedRows[0] === undefined ? undefined : placementCellFromRow(this.realSessionId, lockedRows[0]);
|
|
600
600
|
await conn.rollback();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ToolResultProvenance, ToolResultStore, ToolResultSlice, ToolResultDeletionReport } from "@sema-agent/core";
|
|
2
2
|
import type { Pool as MySqlPool } from "mysql2/promise";
|
|
3
3
|
import type { Pool as PgPool, PoolClient as PgPoolClient } from "pg";
|
|
4
|
-
import { type SqlDriver } from "./sql-driver.js";
|
|
4
|
+
import { type SqlDriver, type SqlDialect } from "./sql-driver.js";
|
|
5
5
|
import type { RetentionDeclaration } from "@sema-agent/core";
|
|
6
6
|
import { type IndexSpec } from "./ensure-index.js";
|
|
7
7
|
/** PG schema for the tool_result table — the PG translation of tidb-pool.ts's tool_result DDL
|
|
@@ -27,7 +27,7 @@ export declare function ensureSchema(pool: PgPool | PgPoolClient): Promise<void>
|
|
|
27
27
|
*/
|
|
28
28
|
export declare function assertToolResultProvenanceSchema(query: (sql: string) => Promise<{
|
|
29
29
|
rows: Record<string, unknown>[];
|
|
30
|
-
}>, dialect:
|
|
30
|
+
}>, dialect: SqlDialect): Promise<void>;
|
|
31
31
|
/** Dual-dialect durable ToolResultStore. See the file header for the dialect-delta ledger. */
|
|
32
32
|
export declare class SqlToolResultStore implements ToolResultStore {
|
|
33
33
|
protected readonly db: SqlDriver;
|