@morlay/session-rdb 0.0.15 → 0.0.16-alpha.1

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.
Files changed (65) hide show
  1. package/README.md +11 -13
  2. package/dist/artifact.d.mts +30 -16
  3. package/dist/artifact.mjs +3 -3
  4. package/dist/{import-DFed8DBt.mjs → import-mZZgDBLd.mjs} +73 -83
  5. package/dist/import.d.mts +2 -3
  6. package/dist/import.mjs +2 -2
  7. package/dist/index-GdKkSSb-.d.mts +239 -0
  8. package/dist/index.d.mts +3 -3
  9. package/dist/index.mjs +763 -168
  10. package/dist/log-DBFUBPhv.mjs +394 -0
  11. package/dist/{schema-CFXZURX7.d.mts → schema-COK7-wRV.d.mts} +3 -15
  12. package/dist/sqlite-CnWwGToZ.mjs +698 -0
  13. package/dist/storage.d.mts +2 -7
  14. package/dist/storage.mjs +2 -3
  15. package/dist/testing.d.mts +30 -1
  16. package/dist/testing.mjs +676 -1991
  17. package/drizzle/postgres/20260908072805_v2_initial/migration.sql +58 -0
  18. package/drizzle/postgres/20260908072805_v2_initial/snapshot.json +686 -0
  19. package/drizzle/postgres/20260908072806_v3_drop_original_seq/migration.sql +1 -0
  20. package/drizzle/postgres/20260908072806_v3_drop_original_seq/snapshot.json +673 -0
  21. package/drizzle/sqlite/20260908072751_v2_initial/migration.sql +53 -0
  22. package/drizzle/sqlite/20260908072751_v2_initial/snapshot.json +492 -0
  23. package/drizzle/sqlite/20260908072752_v3_drop_original_seq/migration.sql +6 -0
  24. package/drizzle/sqlite/20260908072752_v3_drop_original_seq/snapshot.json +513 -0
  25. package/package.json +17 -12
  26. package/src/adapters/index.ts +10 -2
  27. package/src/adapters/to-postgres.ts +19 -15
  28. package/src/adapters/to-sqlite.ts +20 -14
  29. package/src/{entities → adapters}/types.ts +7 -8
  30. package/src/backend.ts +0 -7
  31. package/src/branch.ts +29 -110
  32. package/src/drizzle/postgres-v2.ts +11 -0
  33. package/src/drizzle/postgres-v3.ts +11 -0
  34. package/src/drizzle/sqlite-v2.ts +10 -0
  35. package/src/drizzle/sqlite-v3.ts +11 -0
  36. package/src/entities/index.ts +2 -30
  37. package/src/entities/v2/index.ts +20 -0
  38. package/src/entities/v2/session-events.ts +11 -0
  39. package/src/entities/v3/events.ts +27 -0
  40. package/src/entities/v3/index.ts +27 -0
  41. package/src/entities/v3/persistence-state.ts +10 -0
  42. package/src/entities/v3/schema-meta.ts +9 -0
  43. package/src/entities/v3/session-events.ts +26 -0
  44. package/src/entities/v3/sessions.ts +20 -0
  45. package/src/import.ts +65 -57
  46. package/src/index.ts +929 -227
  47. package/src/invariant.ts +0 -2
  48. package/src/legacy.ts +110 -0
  49. package/src/log.ts +143 -91
  50. package/src/postgres.ts +75 -93
  51. package/src/schema.ts +3 -14
  52. package/src/sqlite.ts +59 -46
  53. package/src/testing/contract.ts +460 -375
  54. package/src/testing/coordinator-contract.ts +108 -1374
  55. package/src/testing.ts +1 -6
  56. package/dist/index-uUvn6gYp.d.mts +0 -111
  57. package/dist/schema-vwzwEXNE.mjs +0 -878
  58. package/dist/sqlite-CG_Qcx5C.mjs +0 -356
  59. package/src/adapters/ddl.ts +0 -77
  60. package/src/entities/events.ts +0 -27
  61. package/src/entities/persistence-state.ts +0 -10
  62. package/src/entities/schema-meta.ts +0 -9
  63. package/src/entities/session-events.ts +0 -29
  64. package/src/entities/sessions.ts +0 -20
  65. package/src/migrate.ts +0 -137
@@ -0,0 +1,239 @@
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
+ /** 存储桥接行数(迁移链可能生成/合并事件,与 `events.length` 不同)。 */
200
+ storedCount: number;
201
+ /** 是否经上游迁移链转换(v0/v1 → 当前格式)。 */
202
+ migrated: boolean;
203
+ } | undefined>;
204
+ /**
205
+ * 把迁移链读出的 v2 视图整体落库(旧格式会话写打开时的一次性迁移)。
206
+ *
207
+ * 迁移链会生成/合并事件(end-seed / attempt / chunk 合并),事件 seq 空间
208
+ * 与存储桥接行数不再相等;写路径以存储 head 为锚点重编号,二者不一致会让
209
+ * append 撞上已有行。这里在同一事务内删光本会话桥接行、按迁移视图重建
210
+ * (新事件行,完整信封),并更新 head 与 revision;旧事件行保留(可能被
211
+ * fork 子会话引用,孤儿由惰性 GC 处理)。
212
+ */
213
+ private rewriteMigratedLog;
214
+ listSnapshots(signal?: AbortSignal): Promise<Array<SessionPersistenceSnapshot & {
215
+ inheritedEventCount: number;
216
+ }>>;
217
+ readStoredRevision(id: SessionId, signal?: AbortSignal): Promise<SessionPersistenceRevision | undefined>;
218
+ /** 便捷:create + append + close(测试与导入路径共用)。 */
219
+ createAndAppend(header: SessionHeader, events: readonly SessionEvent[], inheritedEventCount?: number): Promise<void>;
220
+ /** 便捷:open(read) + read 全量 + close。 */
221
+ load(id: SessionId, signal?: AbortSignal): Promise<import("@deepseek-ai/dsh-session-persistence").SessionInspection>;
222
+ /** 便捷:open(write) + append + close。 */
223
+ append(id: SessionId, events: readonly SessionEvent[]): Promise<void>;
224
+ /** 便捷:readFrom(稠密后缀)。 */
225
+ readFrom(id: SessionId, fromSeq: number, signal?: AbortSignal): Promise<{
226
+ meta: SessionHeader;
227
+ inheritedEventCount: number;
228
+ events: readonly SessionEvent[];
229
+ }>;
230
+ close(): Promise<void>;
231
+ registerReuseEventIds(childId: SessionId, map: ReadonlyMap<number, string>): void;
232
+ internals(): SessionPersistenceRdbInternals;
233
+ private rowRevision;
234
+ private installLiveRouting;
235
+ /** session/created 后为 live 会话建立 write handle(create 或 adopt)。 */
236
+ private ensureLiveHandle;
237
+ }
238
+ //#endregion
239
+ 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 { n as EPHEMERAL_EVENT_TYPES, s as SCHEMA_VERSION } from "./schema-CFXZURX7.mjs";
2
- import { a as SessionBranchRdbProvider, i as SessionBranchRdb, n as SessionPersistenceRdb, o as locateTurnEnd, r as SessionPersistenceRdbInternals, t as Config } from "./index-uUvn6gYp.mjs";
3
- export { Config, EPHEMERAL_EVENT_TYPES, SCHEMA_VERSION, SessionBranchRdb, SessionBranchRdbProvider, SessionPersistenceRdb, SessionPersistenceRdb as default, SessionPersistenceRdbInternals, locateTurnEnd };
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-GdKkSSb-.mjs";
3
+ export { Config, SCHEMA_VERSION, SessionBranchRdb, SessionBranchRdbProvider, SessionPersistenceRdb, SessionPersistenceRdb as default, SessionPersistenceRdbInternals, locateTurnEnd };