@morlay/session-rdb 0.0.15 → 0.0.16-alpha.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/README.md +11 -13
- package/dist/artifact.d.mts +6 -16
- package/dist/artifact.mjs +3 -3
- package/dist/{import-DFed8DBt.mjs → import-CKrzjXVB.mjs} +73 -83
- package/dist/import.d.mts +2 -3
- package/dist/import.mjs +2 -2
- package/dist/index-CgGDHQSK.d.mts +225 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +694 -169
- package/dist/log-DTJsxMud.mjs +314 -0
- package/dist/{schema-CFXZURX7.d.mts → schema-COK7-wRV.d.mts} +3 -15
- package/dist/sqlite-DCy4VTD8.mjs +698 -0
- package/dist/storage.d.mts +2 -7
- package/dist/storage.mjs +2 -3
- package/dist/testing.d.mts +30 -1
- package/dist/testing.mjs +676 -1991
- package/drizzle/postgres/20260908072805_v2_initial/migration.sql +58 -0
- package/drizzle/postgres/20260908072805_v2_initial/snapshot.json +686 -0
- package/drizzle/postgres/20260908072806_v3_drop_original_seq/migration.sql +1 -0
- package/drizzle/postgres/20260908072806_v3_drop_original_seq/snapshot.json +673 -0
- package/drizzle/sqlite/20260908072751_v2_initial/migration.sql +53 -0
- package/drizzle/sqlite/20260908072751_v2_initial/snapshot.json +492 -0
- package/drizzle/sqlite/20260908072752_v3_drop_original_seq/migration.sql +6 -0
- package/drizzle/sqlite/20260908072752_v3_drop_original_seq/snapshot.json +513 -0
- package/package.json +17 -12
- package/src/adapters/index.ts +10 -2
- package/src/adapters/to-postgres.ts +19 -15
- package/src/adapters/to-sqlite.ts +20 -14
- package/src/{entities → adapters}/types.ts +7 -8
- package/src/backend.ts +0 -7
- package/src/branch.ts +29 -110
- package/src/drizzle/postgres-v2.ts +11 -0
- package/src/drizzle/postgres-v3.ts +11 -0
- package/src/drizzle/sqlite-v2.ts +10 -0
- package/src/drizzle/sqlite-v3.ts +11 -0
- package/src/entities/index.ts +2 -30
- package/src/entities/v2/index.ts +20 -0
- package/src/entities/v2/session-events.ts +11 -0
- package/src/entities/v3/events.ts +27 -0
- package/src/entities/v3/index.ts +27 -0
- package/src/entities/v3/persistence-state.ts +10 -0
- package/src/entities/v3/schema-meta.ts +9 -0
- package/src/entities/v3/session-events.ts +26 -0
- package/src/entities/v3/sessions.ts +20 -0
- package/src/import.ts +65 -57
- package/src/index.ts +868 -223
- package/src/invariant.ts +0 -2
- package/src/legacy.ts +67 -0
- package/src/log.ts +41 -87
- package/src/postgres.ts +75 -93
- package/src/schema.ts +3 -14
- package/src/sqlite.ts +59 -46
- package/src/testing/contract.ts +460 -375
- package/src/testing/coordinator-contract.ts +108 -1374
- package/src/testing.ts +1 -6
- package/dist/index-uUvn6gYp.d.mts +0 -111
- package/dist/schema-vwzwEXNE.mjs +0 -878
- package/dist/sqlite-CG_Qcx5C.mjs +0 -356
- package/src/adapters/ddl.ts +0 -77
- package/src/entities/events.ts +0 -27
- package/src/entities/persistence-state.ts +0 -10
- package/src/entities/schema-meta.ts +0 -9
- package/src/entities/session-events.ts +0 -29
- package/src/entities/sessions.ts +0 -20
- package/src/migrate.ts +0 -137
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# @morlay/session-rdb
|
|
2
2
|
|
|
3
|
-
RDB(SQLite / PostgreSQL)持久会话后端(`ctx.sessionPersistence
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
RDB(SQLite / PostgreSQL)持久会话后端(`ctx.sessionPersistence`):实现上游
|
|
4
|
+
`SessionHandle` 模型(`create`/`open`/`flush`/`stat`/`list`),支持配置选择
|
|
5
|
+
SQLite 或 PostgreSQL 后端。设计细节(表结构、原样存储、并发写、方言差异、
|
|
6
|
+
仓库结构)见 [docs/design.md](docs/design.md)。
|
|
7
7
|
|
|
8
8
|
## 配置
|
|
9
9
|
|
|
@@ -59,18 +59,16 @@ type Config =
|
|
|
59
59
|
provider 抽象并**随插件自动注册 `ctx.sessionBranch`**(`SessionBranchRdb`),
|
|
60
60
|
在不修改上游代码的前提下提供 `rewind / retry / fork` 的持久化闭环:
|
|
61
61
|
|
|
62
|
-
- **`forkFrom`**:走标准
|
|
62
|
+
- **`forkFrom`**:走标准 handle 路径(`create` + `append`)从闭合边界
|
|
63
63
|
派生新会话(纯 append,`parentSession` / `seedLength` lineage);
|
|
64
64
|
- **`rewind`**:直接操作后端事务截断到闭合边界(DELETE 尾部 + head 回退 +
|
|
65
|
-
revision bump
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
截断);
|
|
65
|
+
revision bump),并更新并发写检测 head;**支持 live 会话**(`ctx.sessions`
|
|
66
|
+
有 owner 时同样就地工作:先 flush write-behind 缓冲 → 截断 RDB → 截断
|
|
67
|
+
live 内存 log 并复位 surface/header/context/derived 派生缓存 → 重置 agent
|
|
68
|
+
请求头标记 → 对齐 handle cursor;不调用 `load`——live 时 load 会先 flush
|
|
69
|
+
撤销截断);
|
|
71
70
|
- **`timeline`**:`parentSession` + `seedLength` 版本树投影(live 会话含
|
|
72
|
-
版本效果;cold
|
|
73
|
-
lineage 骨架)。
|
|
71
|
+
版本效果;cold 会话版本事件原样落库,效果详情可恢复)。
|
|
74
72
|
|
|
75
73
|
上层编排(edit / reroll / retry / rewind / fork 完整功能)由
|
|
76
74
|
`@morlay/ui-conversation-message-actions` 提供,或直接在 `ctx.sessionBranch` /
|
package/dist/artifact.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME,
|
|
1
|
+
import { v as EventRow, y as SessionRow } from "./schema-COK7-wRV.mjs";
|
|
2
|
+
import { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME, parseImportZip, parseJsonlArtifact, persistImport, registerSessionImport } from "./import.mjs";
|
|
3
3
|
import { SessionStorageMetadata } from "@deepseek-ai/dsh-session-persistence";
|
|
4
|
-
import { SessionEvent, SessionHeader
|
|
4
|
+
import { SessionEvent, SessionHeader } from "@deepseek-ai/dsh-session";
|
|
5
5
|
//#region src/log.d.ts
|
|
6
6
|
declare function rowToMeta(row: SessionRow): SessionHeader;
|
|
7
7
|
declare function sessionInsertRow(storage: SessionStorageMetadata, incarnation: string): {
|
|
@@ -27,17 +27,7 @@ declare function sessionConflictRow(storage: SessionStorageMetadata): {
|
|
|
27
27
|
fOrigin: string | null;
|
|
28
28
|
fDelegationDepth: number | null;
|
|
29
29
|
};
|
|
30
|
-
declare function
|
|
31
|
-
declare function remapShadowedRange(range: {
|
|
32
|
-
start: number;
|
|
33
|
-
end: number;
|
|
34
|
-
}, remap: (seq: number) => number): {
|
|
35
|
-
start: number;
|
|
36
|
-
end: number;
|
|
37
|
-
};
|
|
38
|
-
declare function remapShadowedSeqs(seqs: readonly number[], seqMap: ReadonlyMap<number, number>): number[];
|
|
39
|
-
declare function rowToEvent(row: EventRow, seqMap: ReadonlyMap<number, number>): SessionEvent;
|
|
40
|
-
declare function buildSeqMap(rows: readonly Pick<EventRow, "fSequence" | "fOriginalSeq">[]): Map<number, number>;
|
|
30
|
+
declare function rowToEvent(row: EventRow): SessionEvent;
|
|
41
31
|
/**
|
|
42
32
|
* 读取时重计算 replace 的 sourceEventSeqs(sourceEventSeqs 不落库)。
|
|
43
33
|
*
|
|
@@ -68,10 +58,10 @@ declare function repairSurfaceOps(events: SessionEvent[]): void;
|
|
|
68
58
|
declare function orphanInboxSpliceSeqs(events: readonly SessionEvent[]): Set<number>;
|
|
69
59
|
/** 内存修复:把孤儿 inbox splice 改写为 no-op(调用方负责持久化)。 */
|
|
70
60
|
declare function repairOrphanInboxSplices(events: SessionEvent[]): void;
|
|
71
|
-
declare function scanRows(rows: readonly EventRow[], base?: number
|
|
61
|
+
declare function scanRows(rows: readonly EventRow[], base?: number): {
|
|
72
62
|
preserved: SessionEvent[];
|
|
73
63
|
tornFrom?: number;
|
|
74
64
|
};
|
|
75
65
|
declare function toJsonlArtifact(meta: SessionHeader, inheritedEventCount: number, events: readonly SessionEvent[]): string;
|
|
76
66
|
//#endregion
|
|
77
|
-
export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME,
|
|
67
|
+
export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME, findSurfaceRepairs, orphanInboxSpliceSeqs, parseImportZip, parseJsonlArtifact, persistImport, recomputeReplaceProvenance, registerSessionImport, repairOrphanInboxSplices, repairSurfaceOps, rowToEvent, rowToMeta, scanRows, sessionConflictRow, sessionInsertRow, toJsonlArtifact };
|
package/dist/artifact.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as
|
|
3
|
-
export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME,
|
|
1
|
+
import { a as repairSurfaceOps, c as scanRows, d as toJsonlArtifact, i as repairOrphanInboxSplices, l as sessionConflictRow, n as orphanInboxSpliceSeqs, o as rowToEvent, r as recomputeReplaceProvenance, s as rowToMeta, t as findSurfaceRepairs, u as sessionInsertRow } from "./log-DTJsxMud.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-CKrzjXVB.mjs";
|
|
3
|
+
export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME, findSurfaceRepairs, orphanInboxSpliceSeqs, parseImportZip, parseJsonlArtifact, persistImport, recomputeReplaceProvenance, registerSessionImport, repairOrphanInboxSplices, repairSurfaceOps, rowToEvent, rowToMeta, scanRows, sessionConflictRow, sessionInsertRow, toJsonlArtifact };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { s as rowToMeta } from "./log-DTJsxMud.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
|
-
import { SESSION_FORMAT_VERSION, SessionLogOffset
|
|
3
|
+
import { SESSION_FORMAT_VERSION, SessionLogOffset } from "@deepseek-ai/dsh-session";
|
|
4
|
+
import { sessionFormatCatalog } from "@deepseek-ai/dsh-session-format-catalog";
|
|
4
5
|
import { SessionBranch, SessionBranchError, balanceRewindPrefix, buildTimeline } from "@morlay/session-branch";
|
|
5
6
|
import { unzipSync } from "fflate";
|
|
6
7
|
//#region src/branch.ts
|
|
@@ -78,10 +79,7 @@ var SessionBranchRdbProvider = class {
|
|
|
78
79
|
constructor(persistence, live = {
|
|
79
80
|
getSession: () => void 0,
|
|
80
81
|
getAgent: () => void 0,
|
|
81
|
-
flush: async () => true
|
|
82
|
-
setCoordinatorCursor: () => {},
|
|
83
|
-
setCoordinatorState: () => {},
|
|
84
|
-
setCoordinatorSeedLength: () => {}
|
|
82
|
+
flush: async () => true
|
|
85
83
|
}) {
|
|
86
84
|
this.persistence = persistence;
|
|
87
85
|
this.live = live;
|
|
@@ -95,7 +93,7 @@ var SessionBranchRdbProvider = class {
|
|
|
95
93
|
};
|
|
96
94
|
}
|
|
97
95
|
async readRawEvents(id, signal) {
|
|
98
|
-
const stored = await this.persistence.
|
|
96
|
+
const stored = await this.persistence.readLog(id, {}, signal);
|
|
99
97
|
if (stored === void 0) throw new SessionBranchError(`session "${id}" not found`, "SESSION_NOT_FOUND");
|
|
100
98
|
return {
|
|
101
99
|
meta: stored.meta,
|
|
@@ -105,7 +103,8 @@ var SessionBranchRdbProvider = class {
|
|
|
105
103
|
async forkFrom(sourceId, options = {}, signal) {
|
|
106
104
|
signal?.throwIfAborted();
|
|
107
105
|
const { atSeq, anchorMode = "after", seedSuffix = [], childSessionId, meta = {} } = options;
|
|
108
|
-
const source = await this.persistence.
|
|
106
|
+
const source = await this.persistence.readLog(sourceId, {}, signal);
|
|
107
|
+
if (source === void 0) throw new SessionBranchError(`session "${sourceId}" not found`, "SESSION_NOT_FOUND");
|
|
109
108
|
const boundary = locateTurnEnd(source.events, atSeq, anchorMode);
|
|
110
109
|
const prefix = source.events.slice(0, boundary + 1);
|
|
111
110
|
const childId = childSessionId ?? mintSessionId();
|
|
@@ -123,15 +122,19 @@ var SessionBranchRdbProvider = class {
|
|
|
123
122
|
const seed = [...renumber(prefix, 0), ...renumber(seedSuffix, prefix.length)];
|
|
124
123
|
const internals = this.persistence.internals();
|
|
125
124
|
const sourceRows = await internals.backend.getEventRows(sourceId);
|
|
126
|
-
const sourceEventIds = new Map(sourceRows.map((row) => [row.
|
|
125
|
+
const sourceEventIds = new Map(sourceRows.map((row) => [row.fSequence, row.fEventId]));
|
|
127
126
|
const reuse = /* @__PURE__ */ new Map();
|
|
128
127
|
for (const event of prefix) {
|
|
129
128
|
const eventId = sourceEventIds.get(event.seq);
|
|
130
129
|
if (eventId !== void 0) reuse.set(event.seq, eventId);
|
|
131
130
|
}
|
|
132
131
|
internals.registerReuseEventIds(childId, reuse);
|
|
133
|
-
await this.persistence.create(childMeta, prefix.length);
|
|
134
|
-
|
|
132
|
+
const handle = await this.persistence.create(childMeta, { inheritedEventCount: SessionLogOffset(prefix.length) });
|
|
133
|
+
try {
|
|
134
|
+
if (seed.length > 0) await handle.append(seed);
|
|
135
|
+
} finally {
|
|
136
|
+
await handle.close();
|
|
137
|
+
}
|
|
135
138
|
return childId;
|
|
136
139
|
}
|
|
137
140
|
async rewind(id, toBoundary, signal) {
|
|
@@ -140,7 +143,7 @@ var SessionBranchRdbProvider = class {
|
|
|
140
143
|
const live = this.live.getSession(id);
|
|
141
144
|
if (live !== void 0) await this.live.flush(live);
|
|
142
145
|
const raw = live === void 0 ? await this.readRawEvents(id, signal) : void 0;
|
|
143
|
-
const inspection = live === void 0 ? void 0 : await this.persistence.inspect(id, signal);
|
|
146
|
+
const inspection = live === void 0 ? void 0 : await this.persistence.internals().inspect(id, signal);
|
|
144
147
|
const events = live === void 0 ? raw.events : inspection.events;
|
|
145
148
|
const meta = live === void 0 ? raw.meta : inspection.meta;
|
|
146
149
|
const boundaryEvent = events[toBoundary];
|
|
@@ -149,7 +152,7 @@ var SessionBranchRdbProvider = class {
|
|
|
149
152
|
const rawKeepLength = toBoundary === -1 ? 0 : boundaryEvent.type === "turn/end" ? toBoundary + 1 : toBoundary;
|
|
150
153
|
const keepLength = balanceRewindPrefix(events.slice(0, rawKeepLength)).length;
|
|
151
154
|
const internals = this.persistence.internals();
|
|
152
|
-
const denseBoundary =
|
|
155
|
+
const denseBoundary = keepLength - 1;
|
|
153
156
|
const newSeedLength = await internals.backend.transaction(async (tx) => {
|
|
154
157
|
signal?.throwIfAborted();
|
|
155
158
|
const head = await tx.getHead(id);
|
|
@@ -169,7 +172,6 @@ var SessionBranchRdbProvider = class {
|
|
|
169
172
|
await tx.bumpRevision(id);
|
|
170
173
|
return shrunk;
|
|
171
174
|
});
|
|
172
|
-
if (newSeedLength !== null) this.live.setCoordinatorSeedLength(id, newSeedLength);
|
|
173
175
|
internals.writeGuard.confirmHead(id, denseBoundary);
|
|
174
176
|
if (live !== void 0) {
|
|
175
177
|
truncateLiveSession(live, keepLength);
|
|
@@ -180,9 +182,9 @@ var SessionBranchRdbProvider = class {
|
|
|
180
182
|
const phase = agent.phase;
|
|
181
183
|
if (phase !== void 0) phase.lastTurn = lastTurn;
|
|
182
184
|
}
|
|
183
|
-
this.
|
|
184
|
-
|
|
185
|
-
|
|
185
|
+
const handle = this.persistence.tracker.writerOf(id);
|
|
186
|
+
if (handle !== void 0) handle.resetAfterRewind(keepLength, newSeedLength === null ? void 0 : newSeedLength);
|
|
187
|
+
}
|
|
186
188
|
const row = await internals.backend.getSession(id);
|
|
187
189
|
if (row === void 0) return {
|
|
188
190
|
header: {
|
|
@@ -214,29 +216,7 @@ var SessionBranchRdb = class extends SessionBranch {
|
|
|
214
216
|
getAgent: (id) => {
|
|
215
217
|
return this.ctx.get("agents")?.get(id);
|
|
216
218
|
},
|
|
217
|
-
flush: (session) => this.ctx.sessions.flush(session)
|
|
218
|
-
setCoordinatorCursor: (id, cursor) => {
|
|
219
|
-
const state = this.ctx.sessionPersistence.coordinator?.states?.get(id);
|
|
220
|
-
if (state !== void 0) state.cursor = cursor;
|
|
221
|
-
},
|
|
222
|
-
setCoordinatorState: (id, cursor, meta) => {
|
|
223
|
-
const states = this.ctx.sessionPersistence.coordinator?.states;
|
|
224
|
-
if (states === void 0) return;
|
|
225
|
-
const state = states.get(id);
|
|
226
|
-
if (state !== void 0) state.cursor = cursor;
|
|
227
|
-
else states.set(id, {
|
|
228
|
-
meta,
|
|
229
|
-
cursor,
|
|
230
|
-
materialized: true
|
|
231
|
-
});
|
|
232
|
-
},
|
|
233
|
-
setCoordinatorSeedLength: (id, seedLength) => {
|
|
234
|
-
const state = this.ctx.sessionPersistence.coordinator?.states?.get(id);
|
|
235
|
-
if (state?.storage !== void 0 && state.storage.inheritedEventCount > seedLength) state.storage = {
|
|
236
|
-
...state.storage,
|
|
237
|
-
inheritedEventCount: seedLength
|
|
238
|
-
};
|
|
239
|
-
}
|
|
219
|
+
flush: (session) => this.ctx.sessions.flush(session)
|
|
240
220
|
});
|
|
241
221
|
readBranchPrefix(id, atSeq, mode, signal) {
|
|
242
222
|
return this.provider.readBranchPrefix(id, atSeq, mode, signal);
|
|
@@ -250,22 +230,13 @@ var SessionBranchRdb = class extends SessionBranch {
|
|
|
250
230
|
rewind(id, toBoundary, signal) {
|
|
251
231
|
return this.provider.rewind(id, toBoundary, signal);
|
|
252
232
|
}
|
|
253
|
-
syncLiveCursor(sessionId) {
|
|
254
|
-
const live = this.ctx.sessions.get(sessionId);
|
|
255
|
-
if (live === void 0) return;
|
|
256
|
-
const state = this.ctx.sessionPersistence.coordinator?.states?.get(sessionId);
|
|
257
|
-
if (state === void 0) return;
|
|
258
|
-
let cursor = state.cursor;
|
|
259
|
-
while (live.snapshotEvents()[cursor]?.ignorable === true) cursor += 1;
|
|
260
|
-
state.cursor = cursor;
|
|
261
|
-
}
|
|
262
233
|
async timeline(sessionId, signal) {
|
|
263
234
|
const persistence = this.ctx.sessionPersistence;
|
|
264
235
|
const snapshots = await persistence.listSnapshots(signal);
|
|
265
236
|
const readOwnEvents = async (id, fromSeq, s) => {
|
|
266
237
|
const live = this.ctx.sessions.get(id);
|
|
267
238
|
if (live !== void 0) return live.snapshotEvents().slice(fromSeq);
|
|
268
|
-
return (await persistence.readFrom(id, fromSeq, s)).events;
|
|
239
|
+
return (await persistence.internals().readFrom(id, fromSeq, s)).events;
|
|
269
240
|
};
|
|
270
241
|
return buildTimeline(snapshots, readOwnEvents, sessionId, signal);
|
|
271
242
|
}
|
|
@@ -275,16 +246,6 @@ var SessionBranchRdb = class extends SessionBranch {
|
|
|
275
246
|
const SESSION_LOG_ARTIFACT_FILENAME = "session.jsonl";
|
|
276
247
|
const SESSION_IMPORT_PATH = "/api/session.import";
|
|
277
248
|
const MAX_IMPORT_ZIP_BYTES = 67108864;
|
|
278
|
-
function expandProvenanceFromStorage(parsed) {
|
|
279
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new TypeError("imported session records must be objects");
|
|
280
|
-
const record = parsed;
|
|
281
|
-
if (record.sourceEventSeqs === void 0) return parsed;
|
|
282
|
-
if (!Number.isSafeInteger(record.seq) || record.seq < 0) throw new TypeError("imported session event seq must be a non-negative safe integer");
|
|
283
|
-
return {
|
|
284
|
-
...record,
|
|
285
|
-
sourceEventSeqs: decodeSeqRanges(record.sourceEventSeqs, record.seq + 1)
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
249
|
function parseJsonlArtifact(content) {
|
|
289
250
|
const lines = content.split("\n");
|
|
290
251
|
if (lines.length === 0 || lines[0] === "") throw new Error("imported session log is empty");
|
|
@@ -294,10 +255,15 @@ function parseJsonlArtifact(content) {
|
|
|
294
255
|
} catch {
|
|
295
256
|
throw new Error("imported session log has an unparsable header line");
|
|
296
257
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
258
|
+
let restore;
|
|
259
|
+
try {
|
|
260
|
+
restore = sessionFormatCatalog.createRestore(header, {
|
|
261
|
+
recovery: "strict",
|
|
262
|
+
validation: "transformed"
|
|
263
|
+
});
|
|
264
|
+
} catch (error) {
|
|
265
|
+
throw new Error(`imported session log has an invalid header line: ${error instanceof Error ? error.message : String(error)}`);
|
|
266
|
+
}
|
|
301
267
|
for (let i = 1; i < lines.length; i++) {
|
|
302
268
|
const line = lines[i];
|
|
303
269
|
if (line === void 0 || line === "") continue;
|
|
@@ -307,23 +273,33 @@ function parseJsonlArtifact(content) {
|
|
|
307
273
|
} catch {
|
|
308
274
|
throw new Error(`imported session log has an unparsable event line at ${i}`);
|
|
309
275
|
}
|
|
310
|
-
|
|
276
|
+
try {
|
|
277
|
+
restore.decodeRow(parsed);
|
|
278
|
+
} catch (error) {
|
|
279
|
+
throw new Error(`imported session log has an invalid event line at ${i}: ${error instanceof Error ? error.message : String(error)}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
let artifact;
|
|
283
|
+
try {
|
|
284
|
+
artifact = restore.finish();
|
|
285
|
+
} catch (error) {
|
|
286
|
+
throw new Error(`imported session log is incomplete: ${error instanceof Error ? error.message : String(error)}`);
|
|
311
287
|
}
|
|
288
|
+
const meta = artifact.header;
|
|
289
|
+
const events = artifact.events;
|
|
312
290
|
for (let i = 0; i < events.length; i++) if (events[i].seq !== i) throw new Error(`imported session log seq gap at ${i} (got ${events[i].seq}); import requires a dense log`);
|
|
313
|
-
const
|
|
314
|
-
const delegationDepth = header["delegationDepth"];
|
|
315
|
-
const inheritedEventCount = Math.min(seedLength ?? 0, events.length);
|
|
291
|
+
const inheritedEventCount = Math.min(artifact.inheritedEventCount, events.length);
|
|
316
292
|
return {
|
|
317
293
|
meta: {
|
|
318
|
-
version:
|
|
319
|
-
id:
|
|
320
|
-
createdAt:
|
|
321
|
-
...
|
|
322
|
-
...
|
|
323
|
-
isSeeded:
|
|
324
|
-
...origin ===
|
|
325
|
-
...
|
|
326
|
-
...
|
|
294
|
+
version: SESSION_FORMAT_VERSION,
|
|
295
|
+
id: meta.id,
|
|
296
|
+
createdAt: meta.createdAt,
|
|
297
|
+
...meta.cwd === void 0 ? {} : { cwd: meta.cwd },
|
|
298
|
+
...meta.parentSession === void 0 ? {} : { parentSession: meta.parentSession },
|
|
299
|
+
isSeeded: meta.isSeeded,
|
|
300
|
+
...meta.origin === void 0 ? {} : { origin: meta.origin },
|
|
301
|
+
...meta.delegationDepth === void 0 ? {} : { delegationDepth: meta.delegationDepth },
|
|
302
|
+
...meta.agentPreset === void 0 ? {} : { agentPreset: meta.agentPreset }
|
|
327
303
|
},
|
|
328
304
|
inheritedEventCount: SessionLogOffset(inheritedEventCount),
|
|
329
305
|
events
|
|
@@ -345,11 +321,25 @@ async function persistImport(persistence, branch, imported, targetId, sessions)
|
|
|
345
321
|
if (targetId !== void 0) {
|
|
346
322
|
if (branch === void 0) throw new Error("sessionBranch service is unavailable");
|
|
347
323
|
await branch.rewind(targetId, -1);
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
324
|
+
const liveHandle = persistence.tracker.writerOf(targetId);
|
|
325
|
+
if (liveHandle !== void 0) {
|
|
326
|
+
if (imported.events.length > 0) await liveHandle.append(imported.events);
|
|
327
|
+
} else {
|
|
328
|
+
const handle = await persistence.open(targetId, "write");
|
|
329
|
+
try {
|
|
330
|
+
if (imported.events.length > 0) await handle.append(imported.events);
|
|
331
|
+
} finally {
|
|
332
|
+
await handle.close();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
} else {
|
|
336
|
+
const handle = await persistence.create({
|
|
337
|
+
...imported.meta,
|
|
338
|
+
id
|
|
339
|
+
}, { inheritedEventCount: imported.inheritedEventCount });
|
|
340
|
+
if (imported.events.length > 0) await handle.append(imported.events);
|
|
341
|
+
await handle.close();
|
|
342
|
+
}
|
|
353
343
|
if (targetId !== void 0) {
|
|
354
344
|
const live = sessions?.get(targetId);
|
|
355
345
|
if (live !== void 0) replaceLiveSessionLog(live, imported.events);
|
|
@@ -435,4 +425,4 @@ function registerSessionImport(ctx, persistence) {
|
|
|
435
425
|
});
|
|
436
426
|
}
|
|
437
427
|
//#endregion
|
|
438
|
-
export {
|
|
428
|
+
export { persistImport as a, SessionBranchRdbProvider as c, parseJsonlArtifact as i, locateTurnEnd as l, SESSION_LOG_ARTIFACT_FILENAME as n, registerSessionImport as o, parseImportZip as r, SessionBranchRdb as s, SESSION_IMPORT_PATH as t };
|
package/dist/import.d.mts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { n as SessionPersistenceRdb } from "./index-
|
|
1
|
+
import { n as SessionPersistenceRdb } from "./index-CgGDHQSK.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";
|
|
5
5
|
//#region src/import.d.ts
|
|
6
6
|
declare const SESSION_LOG_ARTIFACT_FILENAME = "session.jsonl";
|
|
7
7
|
declare const SESSION_IMPORT_PATH = "/api/session.import";
|
|
8
|
-
declare function expandProvenanceFromStorage(parsed: unknown): unknown;
|
|
9
8
|
declare function parseJsonlArtifact(content: string): SessionStorageMetadata & {
|
|
10
9
|
events: SessionEvent[];
|
|
11
10
|
};
|
|
@@ -21,4 +20,4 @@ declare function persistImport(persistence: SessionPersistenceRdb, branch: {
|
|
|
21
20
|
}): Promise<SessionId>;
|
|
22
21
|
declare function registerSessionImport(ctx: Context, persistence: SessionPersistenceRdb): void;
|
|
23
22
|
//#endregion
|
|
24
|
-
export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME,
|
|
23
|
+
export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME, parseImportZip, parseJsonlArtifact, persistImport, registerSessionImport };
|
package/dist/import.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME,
|
|
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-CKrzjXVB.mjs";
|
|
2
|
+
export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME, parseImportZip, parseJsonlArtifact, persistImport, registerSessionImport };
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { a as JournalMode, g as Backend, h as WriteGuard } from "./schema-COK7-wRV.mjs";
|
|
2
|
+
import z from "@deepseek-ai/schemastery";
|
|
3
|
+
import { SessionAccess, SessionHandle, SessionHandleAppendOptions, SessionHandleFlushOptions, SessionHandleReadOptions, SessionHandleReadResult, SessionPersistence, SessionPersistenceCreateOptions, SessionPersistenceListOptions, SessionPersistenceOpenOptions, SessionPersistenceRevision, SessionPersistenceSnapshot, SessionPersistenceStatOptions } from "@deepseek-ai/dsh-session-persistence";
|
|
4
|
+
import { Session, SessionEvent, SessionHeader, SessionId, SessionLogOffset } from "@deepseek-ai/dsh-session";
|
|
5
|
+
import { BranchAnchorMode, BranchBoundary, ForkFromOptions, SessionBranch, SessionBranchProvider } from "@morlay/session-branch";
|
|
6
|
+
import { Context } from "@deepseek-ai/cordis";
|
|
7
|
+
//#region src/branch.d.ts
|
|
8
|
+
declare function locateTurnEnd(events: readonly SessionEvent[], atSeq?: number, mode?: BranchAnchorMode): number;
|
|
9
|
+
interface LiveSessionHooks {
|
|
10
|
+
getSession(id: SessionId): Session | undefined;
|
|
11
|
+
getAgent(id: SessionId): LiveAgentLike | undefined;
|
|
12
|
+
flush(session: Session): Promise<boolean>;
|
|
13
|
+
}
|
|
14
|
+
interface LiveAgentLike {
|
|
15
|
+
session: Session;
|
|
16
|
+
requestHeaderLogged?: boolean;
|
|
17
|
+
}
|
|
18
|
+
declare class SessionBranchRdbProvider implements SessionBranchProvider {
|
|
19
|
+
private readonly persistence;
|
|
20
|
+
private readonly live;
|
|
21
|
+
readonly name = "session-rdb";
|
|
22
|
+
constructor(persistence: SessionPersistenceRdb, live?: LiveSessionHooks);
|
|
23
|
+
readBranchPrefix(id: SessionId, atSeq?: number, mode?: BranchAnchorMode, signal?: AbortSignal): Promise<BranchBoundary>;
|
|
24
|
+
readRawEvents(id: SessionId, signal?: AbortSignal): Promise<{
|
|
25
|
+
meta: SessionHeader;
|
|
26
|
+
events: readonly SessionEvent[];
|
|
27
|
+
}>;
|
|
28
|
+
forkFrom(sourceId: SessionId, options?: ForkFromOptions, signal?: AbortSignal): Promise<SessionId>;
|
|
29
|
+
rewind(id: SessionId, toBoundary: number, signal?: AbortSignal): Promise<SessionPersistenceSnapshot>;
|
|
30
|
+
}
|
|
31
|
+
declare class SessionBranchRdb extends SessionBranch {
|
|
32
|
+
static inject: string[];
|
|
33
|
+
constructor(ctx: import("@deepseek-ai/cordis").Context);
|
|
34
|
+
private readonly provider;
|
|
35
|
+
readBranchPrefix(id: SessionId, atSeq?: number, mode?: BranchAnchorMode, signal?: AbortSignal): Promise<BranchBoundary>;
|
|
36
|
+
readRawEvents(id: SessionId, signal?: AbortSignal): Promise<{
|
|
37
|
+
meta: SessionHeader;
|
|
38
|
+
events: readonly SessionEvent[];
|
|
39
|
+
}>;
|
|
40
|
+
forkFrom(sourceId: SessionId, options?: ForkFromOptions, signal?: AbortSignal): Promise<SessionId>;
|
|
41
|
+
rewind(id: SessionId, toBoundary: number, signal?: AbortSignal): Promise<SessionPersistenceSnapshot>;
|
|
42
|
+
timeline(sessionId: SessionId, signal?: AbortSignal): Promise<import("@morlay/session-branch").BranchTimeline>;
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/index.d.ts
|
|
46
|
+
interface SessionPersistenceRdbInternals {
|
|
47
|
+
readonly backend: Backend;
|
|
48
|
+
readonly writeGuard: WriteGuard;
|
|
49
|
+
create(meta: SessionHeader, inheritedEventCount?: number): Promise<SessionHandle>;
|
|
50
|
+
append(id: SessionId, events: readonly SessionEvent[]): Promise<void>;
|
|
51
|
+
load(id: SessionId): Promise<import("@deepseek-ai/dsh-session-persistence").SessionInspection>;
|
|
52
|
+
inspect(id: SessionId, signal?: AbortSignal): Promise<import("@deepseek-ai/dsh-session-persistence").SessionInspection>;
|
|
53
|
+
readFrom(id: SessionId, fromSeq: number, signal?: AbortSignal): Promise<{
|
|
54
|
+
meta: SessionHeader;
|
|
55
|
+
inheritedEventCount: number;
|
|
56
|
+
events: readonly SessionEvent[];
|
|
57
|
+
}>;
|
|
58
|
+
listSnapshots(signal?: AbortSignal): Promise<SessionPersistenceSnapshot[]>;
|
|
59
|
+
readStoredRevision(id: SessionId, signal?: AbortSignal): Promise<import("@deepseek-ai/dsh-session-persistence").SessionPersistenceRevision | undefined>;
|
|
60
|
+
registerReuseEventIds(childId: SessionId, map: ReadonlyMap<number, string>): void;
|
|
61
|
+
}
|
|
62
|
+
type Config = {
|
|
63
|
+
type: "sqlite";
|
|
64
|
+
path: string;
|
|
65
|
+
journalMode?: JournalMode;
|
|
66
|
+
busyTimeout?: number;
|
|
67
|
+
} | {
|
|
68
|
+
type: "postgres";
|
|
69
|
+
connectionString: string;
|
|
70
|
+
schema?: string;
|
|
71
|
+
};
|
|
72
|
+
/** 一个已创建但未 materialize 的会话(本进程可见,其他进程不可见)。 */
|
|
73
|
+
interface PendingSession {
|
|
74
|
+
readonly header: SessionHeader;
|
|
75
|
+
readonly revision: SessionPersistenceRevision;
|
|
76
|
+
readonly inheritedEventCount: SessionLogOffset;
|
|
77
|
+
/** 输入空间 cursor(全 delta 批次也推进)。 */
|
|
78
|
+
readonly cursor: number;
|
|
79
|
+
/** 是否调用过 append(close 时保留 pending)。 */
|
|
80
|
+
readonly everAppended: boolean;
|
|
81
|
+
}
|
|
82
|
+
/** 会话级写所有权与 live 路由簿记。 */
|
|
83
|
+
declare class RdbBackendTracker {
|
|
84
|
+
private readonly name;
|
|
85
|
+
/** 每个 id 的活跃 write handle;`null` 表示 claim 构造中。 */
|
|
86
|
+
private readonly writers;
|
|
87
|
+
private readonly pending;
|
|
88
|
+
private readonly openHandles;
|
|
89
|
+
private counter;
|
|
90
|
+
constructor(name: string);
|
|
91
|
+
registerCreated(header: SessionHeader, inheritedEventCount: SessionLogOffset): void;
|
|
92
|
+
/** 更新 pending 的 cursor / everAppended(handle append 后同步)。 */
|
|
93
|
+
updatePending(id: SessionId, cursor: number, everAppended: boolean): void;
|
|
94
|
+
claimWrite(id: SessionId): void;
|
|
95
|
+
releaseClaim(id: SessionId): void;
|
|
96
|
+
pendingOf(id: SessionId): PendingSession | undefined;
|
|
97
|
+
hasPending(id: SessionId): boolean;
|
|
98
|
+
pendingEntries(): IterableIterator<[SessionId, PendingSession]>;
|
|
99
|
+
materialized(id: SessionId): void;
|
|
100
|
+
adopt(handle: RdbSessionHandle): RdbSessionHandle;
|
|
101
|
+
release(handle: RdbSessionHandle, materialized: boolean): void;
|
|
102
|
+
writerOf(id: SessionId): RdbSessionHandle | undefined;
|
|
103
|
+
flushAll(): Promise<void>;
|
|
104
|
+
closeAll(): Promise<void>;
|
|
105
|
+
}
|
|
106
|
+
/** 一个打开会话的存储句柄:read / append / flush / close。 */
|
|
107
|
+
declare class RdbSessionHandle implements SessionHandle {
|
|
108
|
+
private readonly persistence;
|
|
109
|
+
readonly id: SessionId;
|
|
110
|
+
readonly header: SessionHeader;
|
|
111
|
+
readonly access: SessionAccess;
|
|
112
|
+
private readonly state;
|
|
113
|
+
private chain;
|
|
114
|
+
private closing;
|
|
115
|
+
/** 稠密 next-seq(输入空间计数,与旧版 coordinator cursor 同语义)。 */
|
|
116
|
+
private cursor;
|
|
117
|
+
private materialized;
|
|
118
|
+
/** live 路由缓冲(上游 seq 事件,drain 时过滤 delta 后重编号稠密)。 */
|
|
119
|
+
private buffered;
|
|
120
|
+
private batchTimer;
|
|
121
|
+
private drainPaused;
|
|
122
|
+
private draining;
|
|
123
|
+
/** write open 时发现的 torn tail 起点(append 前先截断)。 */
|
|
124
|
+
private tornTruncateTo;
|
|
125
|
+
/** 是否调用过 append(即使全 delta 未落库)——close 时保留 pending。 */
|
|
126
|
+
private everAppended;
|
|
127
|
+
constructor(persistence: SessionPersistenceRdb, id: SessionId, header: SessionHeader, access: SessionAccess, state: {
|
|
128
|
+
cursor: number;
|
|
129
|
+
materialized: boolean;
|
|
130
|
+
inheritedEventCount: SessionLogOffset;
|
|
131
|
+
tornTruncateTo?: number;
|
|
132
|
+
});
|
|
133
|
+
get inheritedEventCount(): SessionLogOffset;
|
|
134
|
+
/** 输入空间 cursor(下一个待落库的上游 seq)。 */
|
|
135
|
+
get cursorValue(): number;
|
|
136
|
+
read(offset?: number, length?: number, options?: SessionHandleReadOptions): Promise<SessionHandleReadResult>;
|
|
137
|
+
append(events: readonly SessionEvent[], options?: SessionHandleAppendOptions): Promise<void>;
|
|
138
|
+
flush(options?: SessionHandleFlushOptions): Promise<void>;
|
|
139
|
+
close(): Promise<void>;
|
|
140
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
141
|
+
/** live 路由:缓冲一个已发布事件(持久化自有副本),并启动批量窗口。 */
|
|
142
|
+
enqueueLive(event: SessionEvent, reportBackgroundFailure: (error: unknown) => void): void;
|
|
143
|
+
/** rewind 截断后对齐 handle 的稠密 cursor 与继承前缀(DB 已截断)。 */
|
|
144
|
+
resetAfterRewind(cursor: number, inheritedEventCount?: number): void;
|
|
145
|
+
/** 排空 live 缓冲(过滤 delta + 重编号稠密 + append)。 */
|
|
146
|
+
drainLive(): Promise<void>;
|
|
147
|
+
private drainBuffered;
|
|
148
|
+
private enqueueChain;
|
|
149
|
+
private run;
|
|
150
|
+
private assertOpen;
|
|
151
|
+
static readonly LIVE_WRITE_BATCH_MAX_DELAY_MS = 200;
|
|
152
|
+
}
|
|
153
|
+
declare class SessionPersistenceRdb extends SessionPersistence {
|
|
154
|
+
config: Config;
|
|
155
|
+
static inject: string[];
|
|
156
|
+
static Config: z<Config>;
|
|
157
|
+
static readonly settingsNs = "session-rdb";
|
|
158
|
+
readonly name = "session-rdb";
|
|
159
|
+
readonly tracker: RdbBackendTracker;
|
|
160
|
+
private readonly backend;
|
|
161
|
+
private storeIdentity;
|
|
162
|
+
private readonly ready;
|
|
163
|
+
private readonly writeGuard;
|
|
164
|
+
private readonly reuseEventIds;
|
|
165
|
+
/** live 路由:session/created 后 handle 就绪前的缓冲。 */
|
|
166
|
+
private readonly liveBuffers;
|
|
167
|
+
private readonly liveReady;
|
|
168
|
+
constructor(ctx: Context, config: Config, injectedBackend?: Backend);
|
|
169
|
+
private init;
|
|
170
|
+
create(header: SessionHeader, options?: SessionPersistenceCreateOptions): Promise<SessionHandle>;
|
|
171
|
+
open(id: SessionId, access: SessionAccess, options?: SessionPersistenceOpenOptions): Promise<SessionHandle>;
|
|
172
|
+
flush(): Promise<void>;
|
|
173
|
+
stat(id: SessionId, options?: SessionPersistenceStatOptions): Promise<SessionPersistenceSnapshot | undefined>;
|
|
174
|
+
list(options?: SessionPersistenceListOptions): Promise<readonly SessionPersistenceSnapshot[]>;
|
|
175
|
+
/** 导出 artifact(jsonl v2 文本),视图只读不落库。 */
|
|
176
|
+
readRaw(id: SessionId, signal?: AbortSignal): Promise<{
|
|
177
|
+
meta: SessionHeader;
|
|
178
|
+
inheritedEventCount: number;
|
|
179
|
+
filename: string;
|
|
180
|
+
content: string;
|
|
181
|
+
} | undefined>;
|
|
182
|
+
/** 空会话 materialize(flush 的持久化屏障)。 */
|
|
183
|
+
materializeEmpty(meta: SessionHeader, inheritedEventCount: SessionLogOffset): Promise<void>;
|
|
184
|
+
/** 原样 append 落库(handle 已校验 contiguity;torn tail 先截断)。
|
|
185
|
+
* 与上游 JSONL 一致:ignorable 事件原样存储,不做过滤。写路径校验 v2
|
|
186
|
+
* 形状(fail-closed):未知类型(非 ignorable)与非法消息形状拒绝入库;
|
|
187
|
+
* 旧格式(v0/v1)数据只在读取时经 legacy 转换链动态转换,不落新库。 */
|
|
188
|
+
appendBatch(meta: SessionHeader, inheritedEventCount: SessionLogOffset, events: readonly SessionEvent[], tornTruncateTo?: number): Promise<boolean>;
|
|
189
|
+
/** 读取一个会话的稠密 log(含 torn tail 检测,不含修复改写)。 */
|
|
190
|
+
readLog(id: SessionId, options?: {
|
|
191
|
+
fromSeq?: number;
|
|
192
|
+
}, signal?: AbortSignal): Promise<{
|
|
193
|
+
meta: SessionHeader;
|
|
194
|
+
inheritedEventCount: number;
|
|
195
|
+
events: SessionEvent[];
|
|
196
|
+
tornFrom?: number;
|
|
197
|
+
incarnation: string;
|
|
198
|
+
revision: number;
|
|
199
|
+
} | undefined>;
|
|
200
|
+
listSnapshots(signal?: AbortSignal): Promise<Array<SessionPersistenceSnapshot & {
|
|
201
|
+
inheritedEventCount: number;
|
|
202
|
+
}>>;
|
|
203
|
+
readStoredRevision(id: SessionId, signal?: AbortSignal): Promise<SessionPersistenceRevision | undefined>;
|
|
204
|
+
/** 便捷:create + append + close(测试与导入路径共用)。 */
|
|
205
|
+
createAndAppend(header: SessionHeader, events: readonly SessionEvent[], inheritedEventCount?: number): Promise<void>;
|
|
206
|
+
/** 便捷:open(read) + read 全量 + close。 */
|
|
207
|
+
load(id: SessionId, signal?: AbortSignal): Promise<import("@deepseek-ai/dsh-session-persistence").SessionInspection>;
|
|
208
|
+
/** 便捷:open(write) + append + close。 */
|
|
209
|
+
append(id: SessionId, events: readonly SessionEvent[]): Promise<void>;
|
|
210
|
+
/** 便捷:readFrom(稠密后缀)。 */
|
|
211
|
+
readFrom(id: SessionId, fromSeq: number, signal?: AbortSignal): Promise<{
|
|
212
|
+
meta: SessionHeader;
|
|
213
|
+
inheritedEventCount: number;
|
|
214
|
+
events: readonly SessionEvent[];
|
|
215
|
+
}>;
|
|
216
|
+
close(): Promise<void>;
|
|
217
|
+
registerReuseEventIds(childId: SessionId, map: ReadonlyMap<number, string>): void;
|
|
218
|
+
internals(): SessionPersistenceRdbInternals;
|
|
219
|
+
private rowRevision;
|
|
220
|
+
private installLiveRouting;
|
|
221
|
+
/** session/created 后为 live 会话建立 write handle(create 或 adopt)。 */
|
|
222
|
+
private ensureLiveHandle;
|
|
223
|
+
}
|
|
224
|
+
//#endregion
|
|
225
|
+
export { SessionBranchRdbProvider as a, SessionBranchRdb as i, SessionPersistenceRdb as n, locateTurnEnd as o, SessionPersistenceRdbInternals as r, Config as t };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as SessionBranchRdbProvider, i as SessionBranchRdb, n as SessionPersistenceRdb, o as locateTurnEnd, r as SessionPersistenceRdbInternals, t as Config } from "./index-
|
|
3
|
-
export { Config,
|
|
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-CgGDHQSK.mjs";
|
|
3
|
+
export { Config, SCHEMA_VERSION, SessionBranchRdb, SessionBranchRdbProvider, SessionPersistenceRdb, SessionPersistenceRdb as default, SessionPersistenceRdbInternals, locateTurnEnd };
|