@morlay/session-rdb 0.0.16-alpha.1 → 0.0.16-alpha.4
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/dist/artifact.d.mts +22 -3
- package/dist/artifact.mjs +3 -3
- package/dist/{import-mZZgDBLd.mjs → import-BPEHfHNk.mjs} +40 -5
- package/dist/import.d.mts +1 -1
- package/dist/import.mjs +1 -1
- package/dist/{index-GdKkSSb-.d.mts → index-CgAqCQAb.d.mts} +27 -5
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +31 -19
- package/dist/{log-DBFUBPhv.mjs → log-BIuXv09P.mjs} +143 -20
- package/dist/{sqlite-CnWwGToZ.mjs → sqlite-IH5I48aL.mjs} +3 -2
- package/dist/storage.mjs +1 -1
- package/dist/testing.mjs +4 -4
- package/package.json +17 -12
- package/src/branch.ts +99 -3
- package/src/index.ts +19 -13
- package/src/legacy.ts +32 -14
- package/src/log.ts +160 -17
- package/src/postgres.ts +2 -1
- package/src/sqlite.ts +2 -1
- package/src/testing/contract.ts +1 -1
package/dist/artifact.d.mts
CHANGED
|
@@ -54,6 +54,14 @@ declare function repairSurfaceOps(events: SessionEvent[]): void;
|
|
|
54
54
|
* 三者齐备,缺失会让整个会话加载失败。
|
|
55
55
|
*/
|
|
56
56
|
declare function repairAssistantSettlement(events: SessionEvent[]): void;
|
|
57
|
+
/**
|
|
58
|
+
* 读取时把旧格式 `request/header` 归一为当前格式:v3 起 system prompt 由
|
|
59
|
+
* surface 上的 `system/message` 承载,header 必须省略 `system`,空 `tools` /
|
|
60
|
+
* `adapterDefaults` 也必须省略(上游 v3 事件校验 fail loud)。混合世代回退
|
|
61
|
+
* 视图直接采用存储行,不归一会让整个会话加载失败。system prompt 因此不再
|
|
62
|
+
* 进入模型请求;会话下次运行由 v3 的 system/message 机制重建。
|
|
63
|
+
*/
|
|
64
|
+
declare function repairRequestHeaders(events: SessionEvent[]): void;
|
|
57
65
|
/**
|
|
58
66
|
* 把紧邻 replace 的 metering 事件的 `shadowedRange` / `shadowedSeqs` 对齐到
|
|
59
67
|
* replace 最终的稠密 range。
|
|
@@ -67,8 +75,19 @@ declare function repairAssistantSettlement(events: SessionEvent[]): void;
|
|
|
67
75
|
*/
|
|
68
76
|
declare function syncMeteringRanges(events: SessionEvent[]): void;
|
|
69
77
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
78
|
+
* 读取时把 v2 时代的 PTC 词汇归一为当前词汇。
|
|
79
|
+
*
|
|
80
|
+
* 上游 v2→v3 迁移把 `tool/code-dispatch(-start)` 改名为
|
|
81
|
+
* `tool/ptc-dispatch(-start)`、把 `tools-code-mode` 插件来源改名为 `tools-ptc`、
|
|
82
|
+
* 把 agent preset 值 `code` 改名为 `ptc`。混合世代回退视图直接采用存储行,
|
|
83
|
+
* 不重命名会被上游 v3 校验以「unknown event type」拒绝整个会话。词汇改写
|
|
84
|
+
* 与上游迁移链的 renamePtcEvent 对齐。
|
|
85
|
+
*/
|
|
86
|
+
declare function renameLegacyPtcEvents(events: SessionEvent[]): void;
|
|
87
|
+
/**
|
|
88
|
+
* 读取视图修复总入口:形状补全(结算字段 / request header)→ PTC 词汇归一
|
|
89
|
+
* → surface 语义修复 → metering 对齐 → provenance 重算 → 孤儿 inbox splice
|
|
90
|
+
* 改写。全部只作用于内存视图,不落库。
|
|
72
91
|
*/
|
|
73
92
|
declare function repairReadView(events: SessionEvent[]): void;
|
|
74
93
|
/**
|
|
@@ -88,4 +107,4 @@ declare function scanRows(rows: readonly EventRow[], base?: number): {
|
|
|
88
107
|
};
|
|
89
108
|
declare function toJsonlArtifact(meta: SessionHeader, inheritedEventCount: number, events: readonly SessionEvent[]): string;
|
|
90
109
|
//#endregion
|
|
91
|
-
export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME, findSurfaceRepairs, orphanInboxSpliceSeqs, parseImportZip, parseJsonlArtifact, persistImport, recomputeReplaceProvenance, registerSessionImport, repairAssistantSettlement, repairOrphanInboxSplices, repairReadView, repairSurfaceOps, rowToEvent, rowToMeta, scanRows, sessionConflictRow, sessionInsertRow, syncMeteringRanges, toJsonlArtifact };
|
|
110
|
+
export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME, findSurfaceRepairs, orphanInboxSpliceSeqs, parseImportZip, parseJsonlArtifact, persistImport, recomputeReplaceProvenance, registerSessionImport, renameLegacyPtcEvents, repairAssistantSettlement, repairOrphanInboxSplices, repairReadView, repairRequestHeaders, repairSurfaceOps, rowToEvent, rowToMeta, scanRows, sessionConflictRow, sessionInsertRow, syncMeteringRanges, toJsonlArtifact };
|
package/dist/artifact.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { a as persistImport, i as parseJsonlArtifact, n as SESSION_LOG_ARTIFACT_FILENAME, o as registerSessionImport, r as parseImportZip, t as SESSION_IMPORT_PATH } from "./import-
|
|
3
|
-
export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME, findSurfaceRepairs, orphanInboxSpliceSeqs, parseImportZip, parseJsonlArtifact, persistImport, recomputeReplaceProvenance, registerSessionImport, repairAssistantSettlement, repairOrphanInboxSplices, repairReadView, repairSurfaceOps, rowToEvent, rowToMeta, scanRows, sessionConflictRow, sessionInsertRow, syncMeteringRanges, toJsonlArtifact };
|
|
1
|
+
import { a as repairAssistantSettlement, c as repairRequestHeaders, d as rowToMeta, f as scanRows, g as toJsonlArtifact, h as syncMeteringRanges, i as renameLegacyPtcEvents, l as repairSurfaceOps, m as sessionInsertRow, n as orphanInboxSpliceSeqs, o as repairOrphanInboxSplices, p as sessionConflictRow, r as recomputeReplaceProvenance, s as repairReadView, t as findSurfaceRepairs, u as rowToEvent } from "./log-BIuXv09P.mjs";
|
|
2
|
+
import { a as persistImport, i as parseJsonlArtifact, n as SESSION_LOG_ARTIFACT_FILENAME, o as registerSessionImport, r as parseImportZip, t as SESSION_IMPORT_PATH } from "./import-BPEHfHNk.mjs";
|
|
3
|
+
export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME, findSurfaceRepairs, orphanInboxSpliceSeqs, parseImportZip, parseJsonlArtifact, persistImport, recomputeReplaceProvenance, registerSessionImport, renameLegacyPtcEvents, repairAssistantSettlement, repairOrphanInboxSplices, repairReadView, repairRequestHeaders, repairSurfaceOps, rowToEvent, rowToMeta, scanRows, sessionConflictRow, sessionInsertRow, syncMeteringRanges, toJsonlArtifact };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { d as rowToMeta } from "./log-BIuXv09P.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { SESSION_FORMAT_VERSION, SessionLogOffset } from "@deepseek-ai/dsh-session";
|
|
4
4
|
import { sessionFormatCatalog } from "@deepseek-ai/dsh-session-format-catalog";
|
|
@@ -142,7 +142,8 @@ var SessionBranchRdbProvider = class {
|
|
|
142
142
|
if (!Number.isSafeInteger(toBoundary) || toBoundary < -1) throw new SessionBranchError(`rewind boundary must be a non-negative safe integer, got ${toBoundary}`, "INVALID_BOUNDARY");
|
|
143
143
|
const live = this.live.getSession(id);
|
|
144
144
|
if (live !== void 0) await this.live.flush(live);
|
|
145
|
-
const raw = live === void 0 ? await this.
|
|
145
|
+
const raw = live === void 0 ? await this.persistence.readLog(id, {}, signal) : void 0;
|
|
146
|
+
if (live === void 0 && raw === void 0) throw new SessionBranchError(`session "${id}" not found`, "SESSION_NOT_FOUND");
|
|
146
147
|
const inspection = live === void 0 ? void 0 : await this.persistence.internals().inspect(id, signal);
|
|
147
148
|
const events = live === void 0 ? raw.events : inspection.events;
|
|
148
149
|
const meta = live === void 0 ? raw.meta : inspection.meta;
|
|
@@ -150,7 +151,8 @@ var SessionBranchRdbProvider = class {
|
|
|
150
151
|
if (toBoundary === -1) {} else if (boundaryEvent === void 0) throw new SessionBranchError(`rewind boundary ${toBoundary} does not exist in session "${id}"`, "INVALID_BOUNDARY");
|
|
151
152
|
else if (boundaryEvent.type !== "turn/end" && boundaryEvent.type !== "user/message") throw new SessionBranchError(`rewind boundary ${toBoundary} is not a turn/end or user/message (${boundaryEvent.type})`, "INVALID_BOUNDARY");
|
|
152
153
|
const rawKeepLength = toBoundary === -1 ? 0 : boundaryEvent.type === "turn/end" ? toBoundary + 1 : toBoundary;
|
|
153
|
-
const
|
|
154
|
+
const kept = balanceRewindPrefix(events.slice(0, rawKeepLength));
|
|
155
|
+
const keepLength = kept.length;
|
|
154
156
|
const internals = this.persistence.internals();
|
|
155
157
|
const denseBoundary = keepLength - 1;
|
|
156
158
|
const newSeedLength = await internals.backend.transaction(async (tx) => {
|
|
@@ -175,6 +177,7 @@ var SessionBranchRdbProvider = class {
|
|
|
175
177
|
internals.writeGuard.confirmHead(id, denseBoundary);
|
|
176
178
|
if (live !== void 0) {
|
|
177
179
|
truncateLiveSession(live, keepLength);
|
|
180
|
+
this.live.resetProjections?.(live);
|
|
178
181
|
const agent = this.live.getAgent(id);
|
|
179
182
|
if (agent !== void 0) {
|
|
180
183
|
agent.requestHeaderLogged = false;
|
|
@@ -184,7 +187,15 @@ var SessionBranchRdbProvider = class {
|
|
|
184
187
|
}
|
|
185
188
|
const handle = this.persistence.tracker.writerOf(id);
|
|
186
189
|
if (handle !== void 0) handle.resetAfterRewind(keepLength, newSeedLength === null ? void 0 : newSeedLength);
|
|
187
|
-
|
|
190
|
+
agent?.inbox?.clear();
|
|
191
|
+
await this.live.flush(live);
|
|
192
|
+
await this.refreshProjectionCache(live);
|
|
193
|
+
} else await this.refreshProjectionCache({
|
|
194
|
+
id,
|
|
195
|
+
header: meta,
|
|
196
|
+
inheritedEventCount: SessionLogOffset(raw.inheritedEventCount),
|
|
197
|
+
snapshotEvents: () => kept
|
|
198
|
+
});
|
|
188
199
|
const row = await internals.backend.getSession(id);
|
|
189
200
|
if (row === void 0) return {
|
|
190
201
|
header: {
|
|
@@ -205,6 +216,16 @@ var SessionBranchRdbProvider = class {
|
|
|
205
216
|
revision: await internals.readStoredRevision(id)
|
|
206
217
|
};
|
|
207
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* 让持久化投影检查点跟随截断后的 log(见 {@link LiveSessionHooks.refreshProjectionCache})。
|
|
221
|
+
* 缓存是派生数据:刷新失败只让缓存多滞后一轮,不能让 rewind 失败。
|
|
222
|
+
*/
|
|
223
|
+
async refreshProjectionCache(session) {
|
|
224
|
+
if (this.live.refreshProjectionCache === void 0) return;
|
|
225
|
+
try {
|
|
226
|
+
await this.live.refreshProjectionCache(session);
|
|
227
|
+
} catch {}
|
|
228
|
+
}
|
|
208
229
|
};
|
|
209
230
|
var SessionBranchRdb = class extends SessionBranch {
|
|
210
231
|
static inject = ["sessionPersistence", "sessions"];
|
|
@@ -216,7 +237,21 @@ var SessionBranchRdb = class extends SessionBranch {
|
|
|
216
237
|
getAgent: (id) => {
|
|
217
238
|
return this.ctx.get("agents")?.get(id);
|
|
218
239
|
},
|
|
219
|
-
flush: (session) => this.ctx.sessions.flush(session)
|
|
240
|
+
flush: (session) => this.ctx.sessions.flush(session),
|
|
241
|
+
resetProjections: (session) => {
|
|
242
|
+
const registry = this.ctx.get("sessionProjections");
|
|
243
|
+
if (registry?.registrations === void 0) return;
|
|
244
|
+
for (const registration of registry.registrations.values()) registration.cells.delete(session);
|
|
245
|
+
},
|
|
246
|
+
refreshProjectionCache: async (session) => {
|
|
247
|
+
const cache = this.ctx.get("sessionProjectionCache");
|
|
248
|
+
if (cache === void 0) return;
|
|
249
|
+
try {
|
|
250
|
+
await cache.write(session);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
this.ctx.logger.warn(`session-rdb: projection cache refresh after rewind for "${session.id}" failed (cache stays stale): ${String(error)}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
220
255
|
});
|
|
221
256
|
readBranchPrefix(id, atSeq, mode, signal) {
|
|
222
257
|
return this.provider.readBranchPrefix(id, atSeq, mode, signal);
|
package/dist/import.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as SessionPersistenceRdb } from "./index-
|
|
1
|
+
import { n as SessionPersistenceRdb } from "./index-CgAqCQAb.mjs";
|
|
2
2
|
import { SessionStorageMetadata } from "@deepseek-ai/dsh-session-persistence";
|
|
3
3
|
import { Session, SessionEvent, SessionId } from "@deepseek-ai/dsh-session";
|
|
4
4
|
import { Context } from "@deepseek-ai/cordis";
|
package/dist/import.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as persistImport, i as parseJsonlArtifact, n as SESSION_LOG_ARTIFACT_FILENAME, o as registerSessionImport, r as parseImportZip, t as SESSION_IMPORT_PATH } from "./import-
|
|
1
|
+
import { a as persistImport, i as parseJsonlArtifact, n as SESSION_LOG_ARTIFACT_FILENAME, o as registerSessionImport, r as parseImportZip, t as SESSION_IMPORT_PATH } from "./import-BPEHfHNk.mjs";
|
|
2
2
|
export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME, parseImportZip, parseJsonlArtifact, persistImport, registerSessionImport };
|
|
@@ -10,10 +10,27 @@ interface LiveSessionHooks {
|
|
|
10
10
|
getSession(id: SessionId): Session | undefined;
|
|
11
11
|
getAgent(id: SessionId): LiveAgentLike | undefined;
|
|
12
12
|
flush(session: Session): Promise<boolean>;
|
|
13
|
+
resetProjections?(session: Session): void;
|
|
14
|
+
refreshProjectionCache?(session: ProjectionCacheSession): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 投影检查点刷新所需的最小会话面:cold rewind 没有 live Session 可复用,
|
|
18
|
+
* 而截断后的前缀未必是合法的独立会话(surface 引用可能悬空),不能走
|
|
19
|
+
* `Session.create` 的校验;缓存服务只读 id / header / inheritedEventCount
|
|
20
|
+
* 与事件前缀,用普通对象承载即可。
|
|
21
|
+
*/
|
|
22
|
+
interface ProjectionCacheSession {
|
|
23
|
+
readonly id: SessionId;
|
|
24
|
+
readonly header: SessionHeader;
|
|
25
|
+
readonly inheritedEventCount: SessionLogOffset;
|
|
26
|
+
snapshotEvents(): readonly SessionEvent[];
|
|
13
27
|
}
|
|
14
28
|
interface LiveAgentLike {
|
|
15
29
|
session: Session;
|
|
16
30
|
requestHeaderLogged?: boolean;
|
|
31
|
+
inbox?: {
|
|
32
|
+
clear(): void;
|
|
33
|
+
};
|
|
17
34
|
}
|
|
18
35
|
declare class SessionBranchRdbProvider implements SessionBranchProvider {
|
|
19
36
|
private readonly persistence;
|
|
@@ -27,6 +44,11 @@ declare class SessionBranchRdbProvider implements SessionBranchProvider {
|
|
|
27
44
|
}>;
|
|
28
45
|
forkFrom(sourceId: SessionId, options?: ForkFromOptions, signal?: AbortSignal): Promise<SessionId>;
|
|
29
46
|
rewind(id: SessionId, toBoundary: number, signal?: AbortSignal): Promise<SessionPersistenceSnapshot>;
|
|
47
|
+
/**
|
|
48
|
+
* 让持久化投影检查点跟随截断后的 log(见 {@link LiveSessionHooks.refreshProjectionCache})。
|
|
49
|
+
* 缓存是派生数据:刷新失败只让缓存多滞后一轮,不能让 rewind 失败。
|
|
50
|
+
*/
|
|
51
|
+
private refreshProjectionCache;
|
|
30
52
|
}
|
|
31
53
|
declare class SessionBranchRdb extends SessionBranch {
|
|
32
54
|
static inject: string[];
|
|
@@ -182,9 +204,9 @@ declare class SessionPersistenceRdb extends SessionPersistence {
|
|
|
182
204
|
/** 空会话 materialize(flush 的持久化屏障)。 */
|
|
183
205
|
materializeEmpty(meta: SessionHeader, inheritedEventCount: SessionLogOffset): Promise<void>;
|
|
184
206
|
/** 原样 append 落库(handle 已校验 contiguity;torn tail 先截断)。
|
|
185
|
-
* 与上游 JSONL 一致:ignorable
|
|
186
|
-
*
|
|
187
|
-
*
|
|
207
|
+
* 与上游 JSONL 一致:ignorable 事件原样存储,不做过滤。写路径校验当前
|
|
208
|
+
* 格式形状(fail-closed):未知类型(非 ignorable)与非法消息形状拒绝入库;
|
|
209
|
+
* 非当前格式(v0/v1/v2)数据只在读取时经 legacy 转换链动态转换,不落新库。 */
|
|
188
210
|
appendBatch(meta: SessionHeader, inheritedEventCount: SessionLogOffset, events: readonly SessionEvent[], tornTruncateTo?: number): Promise<boolean>;
|
|
189
211
|
/** 读取一个会话的稠密 log(含 torn tail 检测,不含修复改写)。 */
|
|
190
212
|
readLog(id: SessionId, options?: {
|
|
@@ -198,11 +220,11 @@ declare class SessionPersistenceRdb extends SessionPersistence {
|
|
|
198
220
|
revision: number;
|
|
199
221
|
/** 存储桥接行数(迁移链可能生成/合并事件,与 `events.length` 不同)。 */
|
|
200
222
|
storedCount: number;
|
|
201
|
-
/**
|
|
223
|
+
/** 是否经上游迁移链转换(非当前格式 → 当前格式)。 */
|
|
202
224
|
migrated: boolean;
|
|
203
225
|
} | undefined>;
|
|
204
226
|
/**
|
|
205
|
-
*
|
|
227
|
+
* 把迁移链读出的当前格式视图整体落库(非当前格式会话写打开时的一次性迁移)。
|
|
206
228
|
*
|
|
207
229
|
* 迁移链会生成/合并事件(end-seed / attempt / chunk 合并),事件 seq 空间
|
|
208
230
|
* 与存储桥接行数不再相等;写路径以存储 head 为锚点重编号,二者不一致会让
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { o as SCHEMA_VERSION } from "./schema-COK7-wRV.mjs";
|
|
2
|
-
import { a as SessionBranchRdbProvider, i as SessionBranchRdb, n as SessionPersistenceRdb, o as locateTurnEnd, r as SessionPersistenceRdbInternals, t as Config } from "./index-
|
|
2
|
+
import { a as SessionBranchRdbProvider, i as SessionBranchRdb, n as SessionPersistenceRdb, o as locateTurnEnd, r as SessionPersistenceRdbInternals, t as Config } from "./index-CgAqCQAb.mjs";
|
|
3
3
|
export { Config, SCHEMA_VERSION, SessionBranchRdb, SessionBranchRdbProvider, SessionPersistenceRdb, SessionPersistenceRdb as default, SessionPersistenceRdbInternals, locateTurnEnd };
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as SCHEMA_VERSION, g as WriteGuard, h as toPostgresSchema, i as EVENT_ENCODING, m as postgresTableDefs, r as DEFAULT_BUSY_TIMEOUT_MS, s as eventDimensions, t as SqliteBackend } from "./sqlite-
|
|
2
|
-
import { d as
|
|
3
|
-
import { c as SessionBranchRdbProvider, l as locateTurnEnd, o as registerSessionImport, s as SessionBranchRdb } from "./import-
|
|
1
|
+
import { a as SCHEMA_VERSION, g as WriteGuard, h as toPostgresSchema, i as EVENT_ENCODING, m as postgresTableDefs, r as DEFAULT_BUSY_TIMEOUT_MS, s as eventDimensions, t as SqliteBackend } from "./sqlite-IH5I48aL.mjs";
|
|
2
|
+
import { c as repairRequestHeaders, d as rowToMeta, f as scanRows, g as toJsonlArtifact, m as sessionInsertRow, p as sessionConflictRow, s as repairReadView } from "./log-BIuXv09P.mjs";
|
|
3
|
+
import { c as SessionBranchRdbProvider, l as locateTurnEnd, o as registerSessionImport, s as SessionBranchRdb } from "./import-BPEHfHNk.mjs";
|
|
4
4
|
import z from "@deepseek-ai/schemastery";
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
6
6
|
import { Pool } from "pg";
|
|
@@ -10,10 +10,11 @@ import { SESSION_FORMAT_VERSION, SessionLogOffset } from "@deepseek-ai/dsh-sessi
|
|
|
10
10
|
import { sessionFormatCatalog } from "@deepseek-ai/dsh-session-format-catalog";
|
|
11
11
|
import { and, eq, gte, sql } from "drizzle-orm";
|
|
12
12
|
import { readdirSync } from "node:fs";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
13
14
|
import { migrate } from "drizzle-orm/node-postgres/migrator";
|
|
14
15
|
//#region src/postgres.ts
|
|
15
16
|
/** drizzle-kit 生成的迁移目录(随包根 drizzle/ 发布;src/dist 形态经相对 URL 统一解析)。 */
|
|
16
|
-
const postgresMigrationsDir = new URL("../drizzle/postgres/", import.meta.url)
|
|
17
|
+
const postgresMigrationsDir = fileURLToPath(new URL("../drizzle/postgres/", import.meta.url));
|
|
17
18
|
var PostgresBackend = class PostgresBackend {
|
|
18
19
|
db;
|
|
19
20
|
options;
|
|
@@ -161,35 +162,43 @@ var PostgresBackend = class PostgresBackend {
|
|
|
161
162
|
};
|
|
162
163
|
//#endregion
|
|
163
164
|
//#region src/legacy.ts
|
|
164
|
-
/** 重建 v0/v1 物理 header 记录(RDB 行 → 物理 JSON 对象)。 */
|
|
165
|
+
/** 重建 v0/v1/v2 物理 header 记录(RDB 行 → 物理 JSON 对象)。 */
|
|
165
166
|
function physicalHeader(row) {
|
|
166
|
-
|
|
167
|
+
const common = {
|
|
167
168
|
type: "session",
|
|
168
169
|
version: row.fVersion,
|
|
169
170
|
id: row.fSessionId,
|
|
170
171
|
createdAt: row.fCreatedAt,
|
|
171
172
|
...row.fCwd !== null ? { cwd: row.fCwd } : {},
|
|
172
173
|
...row.fParentSession !== null ? { parentSession: row.fParentSession } : {},
|
|
173
|
-
...row.fSeedLength !== null ? { seedLength: row.fSeedLength } : {},
|
|
174
174
|
...row.fOrigin !== null ? { origin: row.fOrigin } : {},
|
|
175
175
|
delegationDepth: row.fDelegationDepth ?? 0
|
|
176
176
|
};
|
|
177
|
+
return row.fVersion < 2 ? {
|
|
178
|
+
...common,
|
|
179
|
+
...row.fSeedLength !== null ? { seedLength: row.fSeedLength } : {}
|
|
180
|
+
} : {
|
|
181
|
+
...common,
|
|
182
|
+
isSeeded: row.fSeedLength !== null
|
|
183
|
+
};
|
|
177
184
|
}
|
|
178
|
-
/** 重建一条 v0/v1 物理事件记录(桥接行 + 事件行 → 物理 JSON 对象)。 */
|
|
185
|
+
/** 重建一条 v0/v1/v2 物理事件记录(桥接行 + 事件行 → 物理 JSON 对象)。 */
|
|
179
186
|
function physicalEvent(row) {
|
|
187
|
+
const stored = JSON.parse(row.fData);
|
|
188
|
+
const full = typeof stored === "object" && stored !== null && !Array.isArray(stored) && typeof stored["type"] === "string" && "data" in stored;
|
|
180
189
|
return {
|
|
181
190
|
type: row.fType,
|
|
182
191
|
seq: row.fSequence,
|
|
183
192
|
time: row.fCreatedAt,
|
|
184
|
-
data:
|
|
193
|
+
data: full ? stored["data"] : stored,
|
|
185
194
|
...row.fSurfaceOp !== null ? { surfaceOp: JSON.parse(row.fSurfaceOp) } : {}
|
|
186
195
|
};
|
|
187
196
|
}
|
|
188
197
|
/**
|
|
189
|
-
*
|
|
190
|
-
* @param row - 会话行(f_version <
|
|
198
|
+
* 把非当前格式(v0/v1/v2)行转换为当前逻辑事件与 header。
|
|
199
|
+
* @param row - 会话行(f_version < SESSION_FORMAT_VERSION)。
|
|
191
200
|
* @param eventRows - 已扫描保留的桥接行(稠密 seq,torn tail 已剔除)。
|
|
192
|
-
* @returns
|
|
201
|
+
* @returns 当前逻辑 header、继承前缀长度与事件。
|
|
193
202
|
* @throws 迁移链拒绝(格式损坏 / 无法迁移)时原样抛出。
|
|
194
203
|
*/
|
|
195
204
|
function convertLegacyRows(row, eventRows) {
|
|
@@ -205,9 +214,9 @@ function convertLegacyRows(row, eventRows) {
|
|
|
205
214
|
events: artifact.events
|
|
206
215
|
};
|
|
207
216
|
}
|
|
208
|
-
/**
|
|
217
|
+
/** 会话行是否携带非当前格式(f_version < SESSION_FORMAT_VERSION)数据。 */
|
|
209
218
|
function isLegacyVersion(version) {
|
|
210
|
-
return version <
|
|
219
|
+
return version < SESSION_FORMAT_VERSION;
|
|
211
220
|
}
|
|
212
221
|
/**
|
|
213
222
|
* 迁移链拒绝后,把旧格式行直接当**当前格式**事件视图采用。
|
|
@@ -221,7 +230,7 @@ function isLegacyVersion(version) {
|
|
|
221
230
|
* 调用方须在此之后执行 `validateStoredEvents`:真正属于旧格式的类型
|
|
222
231
|
* (`assistant/chunk` / `compact/*` 等)仍会被 fail-loud 拒绝。
|
|
223
232
|
*
|
|
224
|
-
* @param row - 会话行(f_version <
|
|
233
|
+
* @param row - 会话行(f_version < SESSION_FORMAT_VERSION)。
|
|
225
234
|
* @param eventRows - 该会话全部桥接行(按 f_sequence 升序)。
|
|
226
235
|
* @returns 当前格式 header(version 归一到 SESSION_FORMAT_VERSION)、收缩后的
|
|
227
236
|
* 继承前缀长度、稠密事件与可选 torn tail 起点。
|
|
@@ -229,6 +238,7 @@ function isLegacyVersion(version) {
|
|
|
229
238
|
*/
|
|
230
239
|
function adoptLegacyRows(row, eventRows) {
|
|
231
240
|
const { preserved, tornFrom } = scanRows(eventRows, 0);
|
|
241
|
+
repairRequestHeaders(preserved);
|
|
232
242
|
return {
|
|
233
243
|
meta: {
|
|
234
244
|
...rowToMeta(row),
|
|
@@ -578,6 +588,7 @@ var SessionPersistenceRdb = class SessionPersistenceRdb extends SessionPersisten
|
|
|
578
588
|
}));
|
|
579
589
|
const log = await this.readLog(id, {}, options?.signal);
|
|
580
590
|
if (log === void 0) throw new SessionPersistenceNotFoundError(id);
|
|
591
|
+
repairReadView(log.events);
|
|
581
592
|
validateStoredEvents(log.meta, log.events);
|
|
582
593
|
return this.tracker.adopt(new RdbSessionHandle(this, id, log.meta, "read", {
|
|
583
594
|
cursor: log.events.length,
|
|
@@ -594,6 +605,7 @@ var SessionPersistenceRdb = class SessionPersistenceRdb extends SessionPersisten
|
|
|
594
605
|
}));
|
|
595
606
|
const log = await this.readLog(id, {}, options?.signal);
|
|
596
607
|
if (log === void 0) throw new SessionPersistenceNotFoundError(id);
|
|
608
|
+
repairReadView(log.events);
|
|
597
609
|
validateStoredEvents(log.meta, log.events);
|
|
598
610
|
if (log.migrated && log.events.length !== log.storedCount) await this.rewriteMigratedLog(id, log);
|
|
599
611
|
this.writeGuard.confirmHead(id, log.events.at(-1)?.seq ?? -1);
|
|
@@ -682,9 +694,9 @@ var SessionPersistenceRdb = class SessionPersistenceRdb extends SessionPersisten
|
|
|
682
694
|
this.writeGuard.confirmHead(meta.id, -1);
|
|
683
695
|
}
|
|
684
696
|
/** 原样 append 落库(handle 已校验 contiguity;torn tail 先截断)。
|
|
685
|
-
* 与上游 JSONL 一致:ignorable
|
|
686
|
-
*
|
|
687
|
-
*
|
|
697
|
+
* 与上游 JSONL 一致:ignorable 事件原样存储,不做过滤。写路径校验当前
|
|
698
|
+
* 格式形状(fail-closed):未知类型(非 ignorable)与非法消息形状拒绝入库;
|
|
699
|
+
* 非当前格式(v0/v1/v2)数据只在读取时经 legacy 转换链动态转换,不落新库。 */
|
|
688
700
|
async appendBatch(meta, inheritedEventCount, events, tornTruncateTo) {
|
|
689
701
|
await this.ready;
|
|
690
702
|
if (events.length === 0) return false;
|
|
@@ -765,7 +777,7 @@ var SessionPersistenceRdb = class SessionPersistenceRdb extends SessionPersisten
|
|
|
765
777
|
};
|
|
766
778
|
}
|
|
767
779
|
/**
|
|
768
|
-
*
|
|
780
|
+
* 把迁移链读出的当前格式视图整体落库(非当前格式会话写打开时的一次性迁移)。
|
|
769
781
|
*
|
|
770
782
|
* 迁移链会生成/合并事件(end-seed / attempt / chunk 合并),事件 seq 空间
|
|
771
783
|
* 与存储桥接行数不再相等;写路径以存储 head 为锚点重编号,二者不一致会让
|
|
@@ -1,5 +1,27 @@
|
|
|
1
|
+
import { SessionSeq } from "@deepseek-ai/dsh-session";
|
|
1
2
|
import { sessionFormatCatalog } from "@deepseek-ai/dsh-session-format-catalog";
|
|
2
3
|
//#region src/log.ts
|
|
4
|
+
/**
|
|
5
|
+
* 把桥接行列里的 replace surfaceOp 归一到当前字段名。
|
|
6
|
+
*
|
|
7
|
+
* v2 时代落库的 JSON 用 `start`/`end`,当前格式用 `startSeq`/`endSeq`;
|
|
8
|
+
* 混合世代回退路径直接采用存储行,必须在此归一,否则上游 v3 surface 校验
|
|
9
|
+
* 以「invalid replace surfaceOp」拒绝整个会话。非 replace 形状原样返回,
|
|
10
|
+
* 由读取视图修复决定降级。
|
|
11
|
+
*/
|
|
12
|
+
function normalizeSurfaceOp(value) {
|
|
13
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return value;
|
|
14
|
+
const record = value;
|
|
15
|
+
if (record["op"] !== "replace") return value;
|
|
16
|
+
const startSeq = record["startSeq"] ?? record["start"];
|
|
17
|
+
const endSeq = record["endSeq"] ?? record["end"];
|
|
18
|
+
if (typeof startSeq !== "number" || typeof endSeq !== "number") return value;
|
|
19
|
+
return {
|
|
20
|
+
op: "replace",
|
|
21
|
+
startSeq: SessionSeq(startSeq),
|
|
22
|
+
endSeq: SessionSeq(endSeq)
|
|
23
|
+
};
|
|
24
|
+
}
|
|
3
25
|
function rowToMeta(row) {
|
|
4
26
|
if (!Number.isSafeInteger(row.fCreatedAt) || row.fCreatedAt < 0) throw new Error("stored session createdAt must be a non-negative safe integer");
|
|
5
27
|
return {
|
|
@@ -43,7 +65,7 @@ function sessionConflictRow(storage) {
|
|
|
43
65
|
};
|
|
44
66
|
}
|
|
45
67
|
function rowToEvent(row) {
|
|
46
|
-
const surfaceOp = row.fSurfaceOp !== null ? JSON.parse(row.fSurfaceOp) : void 0;
|
|
68
|
+
const surfaceOp = row.fSurfaceOp !== null ? normalizeSurfaceOp(JSON.parse(row.fSurfaceOp)) : void 0;
|
|
47
69
|
const record = JSON.parse(row.fData);
|
|
48
70
|
if (typeof record === "object" && record !== null && !Array.isArray(record) && typeof record["type"] === "string" && typeof record["seq"] === "number" && typeof record["time"] === "number" && "data" in record) return {
|
|
49
71
|
...record,
|
|
@@ -60,6 +82,7 @@ function rowToEvent(row) {
|
|
|
60
82
|
};
|
|
61
83
|
}
|
|
62
84
|
const SURFACE_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
85
|
+
"system/message",
|
|
63
86
|
"user/message",
|
|
64
87
|
"assistant/message",
|
|
65
88
|
"tool/result"
|
|
@@ -82,7 +105,7 @@ function recomputeReplaceProvenance(events) {
|
|
|
82
105
|
const raw = events[i];
|
|
83
106
|
const op = raw.surfaceOp;
|
|
84
107
|
if (typeof op !== "object" || op === null || op.op !== "replace") continue;
|
|
85
|
-
const {
|
|
108
|
+
const { startSeq, endSeq } = op;
|
|
86
109
|
const metering = i > 0 ? events[i - 1] : void 0;
|
|
87
110
|
const meteringData = metering !== void 0 && METERING_EVENT_TYPES.has(metering.type) ? metering.data : void 0;
|
|
88
111
|
if (meteringData?.shadowedSeqs !== void 0) {
|
|
@@ -90,7 +113,7 @@ function recomputeReplaceProvenance(events) {
|
|
|
90
113
|
continue;
|
|
91
114
|
}
|
|
92
115
|
const refs = [];
|
|
93
|
-
for (const candidate of events) if (candidate.seq >=
|
|
116
|
+
for (const candidate of events) if (candidate.seq >= startSeq && candidate.seq <= endSeq && SURFACE_EVENT_TYPES.has(candidate.type)) refs.push(candidate.seq);
|
|
94
117
|
raw.sourceEventSeqs = refs;
|
|
95
118
|
}
|
|
96
119
|
}
|
|
@@ -163,8 +186,8 @@ function findSurfaceRepairs(events) {
|
|
|
163
186
|
continue;
|
|
164
187
|
}
|
|
165
188
|
const replace = typeof op === "object" && op !== null && !Array.isArray(op) ? op : void 0;
|
|
166
|
-
const start = replace?.["
|
|
167
|
-
const end = replace?.["
|
|
189
|
+
const start = replace?.["startSeq"];
|
|
190
|
+
const end = replace?.["endSeq"];
|
|
168
191
|
const shapeOk = replace !== void 0 && replace["op"] === "replace" && isEventSeqLike(start) && isEventSeqLike(end);
|
|
169
192
|
const startIdx = shapeOk ? nodes.indexOf(start) : -1;
|
|
170
193
|
let endIdx = shapeOk ? nodes.indexOf(end) : -1;
|
|
@@ -174,6 +197,7 @@ function findSurfaceRepairs(events) {
|
|
|
174
197
|
if (clamped !== void 0) endIdx = nodes.indexOf(clamped);
|
|
175
198
|
}
|
|
176
199
|
const rangeOk = shapeOk && startIdx !== -1 && endIdx !== -1 && startIdx <= endIdx;
|
|
200
|
+
const provenanceOk = event.type !== "assistant/message";
|
|
177
201
|
let rewriteOk = true;
|
|
178
202
|
if (rangeOk && event.type === "tool/result") {
|
|
179
203
|
const shadowed = nodes.slice(startIdx, endIdx + 1);
|
|
@@ -183,7 +207,7 @@ function findSurfaceRepairs(events) {
|
|
|
183
207
|
rewriteOk = original?.type === "tool/result" && toolResultRewriteContentOnly(original, event);
|
|
184
208
|
}
|
|
185
209
|
}
|
|
186
|
-
if (!rangeOk || !rewriteOk) {
|
|
210
|
+
if (!rangeOk || !rewriteOk || !provenanceOk) {
|
|
187
211
|
degradeToAppend.add(event.seq);
|
|
188
212
|
nodes.push(event.seq);
|
|
189
213
|
continue;
|
|
@@ -220,12 +244,14 @@ function repairSurfaceOps(events) {
|
|
|
220
244
|
const raw = event;
|
|
221
245
|
const clamped = repairs.clampEnd.get(event.seq);
|
|
222
246
|
if (repairs.degradeToAppend.has(event.seq)) raw.surfaceOp = "append";
|
|
223
|
-
else if (clamped !== void 0)
|
|
224
|
-
op
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
247
|
+
else if (clamped !== void 0) {
|
|
248
|
+
const op = raw.surfaceOp;
|
|
249
|
+
raw.surfaceOp = {
|
|
250
|
+
op: "replace",
|
|
251
|
+
startSeq: SessionSeq(op.startSeq),
|
|
252
|
+
endSeq: SessionSeq(clamped)
|
|
253
|
+
};
|
|
254
|
+
} else if (repairs.addAppendMarker.has(event.seq)) raw.surfaceOp = "append";
|
|
229
255
|
else if (repairs.clearSurfaceOp.has(event.seq)) delete raw.surfaceOp;
|
|
230
256
|
}
|
|
231
257
|
}
|
|
@@ -242,6 +268,25 @@ function repairAssistantSettlement(events) {
|
|
|
242
268
|
}
|
|
243
269
|
}
|
|
244
270
|
/**
|
|
271
|
+
* 读取时把旧格式 `request/header` 归一为当前格式:v3 起 system prompt 由
|
|
272
|
+
* surface 上的 `system/message` 承载,header 必须省略 `system`,空 `tools` /
|
|
273
|
+
* `adapterDefaults` 也必须省略(上游 v3 事件校验 fail loud)。混合世代回退
|
|
274
|
+
* 视图直接采用存储行,不归一会让整个会话加载失败。system prompt 因此不再
|
|
275
|
+
* 进入模型请求;会话下次运行由 v3 的 system/message 机制重建。
|
|
276
|
+
*/
|
|
277
|
+
function repairRequestHeaders(events) {
|
|
278
|
+
for (const event of events) {
|
|
279
|
+
if (event.type !== "request/header") continue;
|
|
280
|
+
const header = event.data["header"];
|
|
281
|
+
if (typeof header !== "object" || header === null || Array.isArray(header)) continue;
|
|
282
|
+
const record = header;
|
|
283
|
+
delete record["system"];
|
|
284
|
+
if (Array.isArray(record["tools"]) && record["tools"].length === 0) delete record["tools"];
|
|
285
|
+
const defaults = record["adapterDefaults"];
|
|
286
|
+
if (typeof defaults === "object" && defaults !== null && !Array.isArray(defaults) && Object.keys(defaults).length === 0) delete record["adapterDefaults"];
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
245
290
|
* 把紧邻 replace 的 metering 事件的 `shadowedRange` / `shadowedSeqs` 对齐到
|
|
246
291
|
* replace 最终的稠密 range。
|
|
247
292
|
*
|
|
@@ -258,22 +303,100 @@ function syncMeteringRanges(events) {
|
|
|
258
303
|
if (!METERING_EVENT_TYPES.has(metering.type)) continue;
|
|
259
304
|
const op = events[i].surfaceOp;
|
|
260
305
|
if (typeof op !== "object" || op === null || op.op !== "replace") continue;
|
|
261
|
-
const {
|
|
306
|
+
const { startSeq, endSeq } = op;
|
|
262
307
|
const data = metering.data;
|
|
263
|
-
if (data.shadowedRange?.start ===
|
|
308
|
+
if (data.shadowedRange?.start === startSeq && data.shadowedRange.end === endSeq) continue;
|
|
264
309
|
data.shadowedRange = {
|
|
265
|
-
start,
|
|
266
|
-
end
|
|
310
|
+
start: startSeq,
|
|
311
|
+
end: endSeq
|
|
267
312
|
};
|
|
268
|
-
data.shadowedSeqs = events.filter((candidate) => candidate.seq >=
|
|
313
|
+
data.shadowedSeqs = events.filter((candidate) => candidate.seq >= startSeq && candidate.seq <= endSeq && SURFACE_EVENT_TYPES.has(candidate.type)).map((candidate) => candidate.seq);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const PTC_EVENT_RENAMES = {
|
|
317
|
+
"tool/code-dispatch-start": "tool/ptc-dispatch-start",
|
|
318
|
+
"tool/code-dispatch": "tool/ptc-dispatch"
|
|
319
|
+
};
|
|
320
|
+
/** 把消息的 `tools-code-mode` 插件来源改写为 `tools-ptc`(非该来源原样返回)。 */
|
|
321
|
+
function renamePtcMessageSource(message) {
|
|
322
|
+
if (typeof message !== "object" || message === null || Array.isArray(message)) return message;
|
|
323
|
+
const record = message;
|
|
324
|
+
const source = record["source"];
|
|
325
|
+
if (typeof source !== "object" || source === null || Array.isArray(source)) return message;
|
|
326
|
+
const sourceRecord = source;
|
|
327
|
+
if (sourceRecord["kind"] !== "plugin" || sourceRecord["plugin"] !== "tools-code-mode") return message;
|
|
328
|
+
return {
|
|
329
|
+
...record,
|
|
330
|
+
source: {
|
|
331
|
+
...sourceRecord,
|
|
332
|
+
plugin: "tools-ptc"
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* 读取时把 v2 时代的 PTC 词汇归一为当前词汇。
|
|
338
|
+
*
|
|
339
|
+
* 上游 v2→v3 迁移把 `tool/code-dispatch(-start)` 改名为
|
|
340
|
+
* `tool/ptc-dispatch(-start)`、把 `tools-code-mode` 插件来源改名为 `tools-ptc`、
|
|
341
|
+
* 把 agent preset 值 `code` 改名为 `ptc`。混合世代回退视图直接采用存储行,
|
|
342
|
+
* 不重命名会被上游 v3 校验以「unknown event type」拒绝整个会话。词汇改写
|
|
343
|
+
* 与上游迁移链的 renamePtcEvent 对齐。
|
|
344
|
+
*/
|
|
345
|
+
function renameLegacyPtcEvents(events) {
|
|
346
|
+
for (let index = 0; index < events.length; index++) {
|
|
347
|
+
const event = events[index];
|
|
348
|
+
const renamedType = PTC_EVENT_RENAMES[event.type];
|
|
349
|
+
if (renamedType !== void 0) {
|
|
350
|
+
events[index] = {
|
|
351
|
+
...event,
|
|
352
|
+
type: renamedType
|
|
353
|
+
};
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
if (event.type === "agent-preset/selected") {
|
|
357
|
+
const data = event.data;
|
|
358
|
+
if (data["agentPreset"] === "code") events[index] = {
|
|
359
|
+
...event,
|
|
360
|
+
data: {
|
|
361
|
+
...data,
|
|
362
|
+
agentPreset: "ptc"
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
if (event.type === "user/message") {
|
|
368
|
+
const renamed = renamePtcMessageSource(event.data);
|
|
369
|
+
if (renamed !== event.data) events[index] = {
|
|
370
|
+
...event,
|
|
371
|
+
data: renamed
|
|
372
|
+
};
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
if (event.type === "agent/inbox/spliced" || event.type === "session/title-llm-request") {
|
|
376
|
+
const data = event.data;
|
|
377
|
+
const key = event.type === "agent/inbox/spliced" ? "inserted" : "messages";
|
|
378
|
+
const list = data[key];
|
|
379
|
+
if (!Array.isArray(list)) continue;
|
|
380
|
+
const renamed = list.map(renamePtcMessageSource);
|
|
381
|
+
if (renamed.some((message, position) => message !== list[position])) events[index] = {
|
|
382
|
+
...event,
|
|
383
|
+
data: {
|
|
384
|
+
...data,
|
|
385
|
+
[key]: renamed
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
}
|
|
269
389
|
}
|
|
270
390
|
}
|
|
271
391
|
/**
|
|
272
|
-
*
|
|
273
|
-
* provenance 重算 → 孤儿 inbox splice
|
|
392
|
+
* 读取视图修复总入口:形状补全(结算字段 / request header)→ PTC 词汇归一
|
|
393
|
+
* → surface 语义修复 → metering 对齐 → provenance 重算 → 孤儿 inbox splice
|
|
394
|
+
* 改写。全部只作用于内存视图,不落库。
|
|
274
395
|
*/
|
|
275
396
|
function repairReadView(events) {
|
|
276
397
|
repairAssistantSettlement(events);
|
|
398
|
+
repairRequestHeaders(events);
|
|
399
|
+
renameLegacyPtcEvents(events);
|
|
277
400
|
repairSurfaceOps(events);
|
|
278
401
|
syncMeteringRanges(events);
|
|
279
402
|
recomputeReplaceProvenance(events);
|
|
@@ -391,4 +514,4 @@ function toJsonlArtifact(meta, inheritedEventCount, events) {
|
|
|
391
514
|
return lines.join("\n");
|
|
392
515
|
}
|
|
393
516
|
//#endregion
|
|
394
|
-
export {
|
|
517
|
+
export { repairAssistantSettlement as a, repairRequestHeaders as c, rowToMeta as d, scanRows as f, toJsonlArtifact as g, syncMeteringRanges as h, renameLegacyPtcEvents as i, repairSurfaceOps as l, sessionInsertRow as m, orphanInboxSpliceSeqs as n, repairOrphanInboxSplices as o, sessionConflictRow as p, recomputeReplaceProvenance as r, repairReadView as s, findSurfaceRepairs as t, rowToEvent as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { m as sessionInsertRow, p as sessionConflictRow } from "./log-BIuXv09P.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { and, eq, gte, sql } from "drizzle-orm";
|
|
4
4
|
import { check, index, integer, sqliteTable, text, unique } from "drizzle-orm/sqlite-core";
|
|
@@ -6,6 +6,7 @@ import { bigint, check as check$1, index as index$1, integer as integer$1, pgSch
|
|
|
6
6
|
import { readdirSync, statSync } from "node:fs";
|
|
7
7
|
import { mkdir, open } from "node:fs/promises";
|
|
8
8
|
import { dirname, resolve } from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
9
10
|
import { DatabaseSync } from "node:sqlite";
|
|
10
11
|
import { drizzle } from "drizzle-orm/node-sqlite";
|
|
11
12
|
import { migrate } from "drizzle-orm/node-sqlite/migrator";
|
|
@@ -482,7 +483,7 @@ function eventDimensions(event) {
|
|
|
482
483
|
//#endregion
|
|
483
484
|
//#region src/sqlite.ts
|
|
484
485
|
/** drizzle-kit 生成的迁移目录(随包根 drizzle/ 发布;src/dist 形态经相对 URL 统一解析)。 */
|
|
485
|
-
const sqliteMigrationsDir = new URL("../drizzle/sqlite/", import.meta.url)
|
|
486
|
+
const sqliteMigrationsDir = fileURLToPath(new URL("../drizzle/sqlite/", import.meta.url));
|
|
486
487
|
const sqliteTxQueues = /* @__PURE__ */ new Map();
|
|
487
488
|
function enqueueSqliteTx(path, fn) {
|
|
488
489
|
const run = (sqliteTxQueues.get(path) ?? Promise.resolve()).then(fn);
|
package/dist/storage.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as SCHEMA_VERSION, c as eventKind, d as tSchemaMeta, f as tSessionEvents, g as WriteGuard, i as EVENT_ENCODING, l as tEvents, n as openDatabase, o as SESSION_PERSISTENCE_SQLITE_APPLICATION_ID, p as tSessions, r as DEFAULT_BUSY_TIMEOUT_MS, s as eventDimensions, t as SqliteBackend, u as tPersistenceState } from "./sqlite-
|
|
1
|
+
import { a as SCHEMA_VERSION, c as eventKind, d as tSchemaMeta, f as tSessionEvents, g as WriteGuard, i as EVENT_ENCODING, l as tEvents, n as openDatabase, o as SESSION_PERSISTENCE_SQLITE_APPLICATION_ID, p as tSessions, r as DEFAULT_BUSY_TIMEOUT_MS, s as eventDimensions, t as SqliteBackend, u as tPersistenceState } from "./sqlite-IH5I48aL.mjs";
|
|
2
2
|
export { DEFAULT_BUSY_TIMEOUT_MS, EVENT_ENCODING, SCHEMA_VERSION, SESSION_PERSISTENCE_SQLITE_APPLICATION_ID, SqliteBackend, WriteGuard, eventDimensions, eventKind, openDatabase, tEvents, tPersistenceState, tSchemaMeta, tSessionEvents, tSessions };
|