@morlay/session-rdb 0.0.19 → 0.0.21-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.
Files changed (70) hide show
  1. package/README.md +59 -31
  2. package/dist/artifact.d.mts +25 -65
  3. package/dist/artifact.mjs +3 -3
  4. package/dist/{schema-DPcuEh_a.d.mts → backend-DpdtxYpz.d.mts} +360 -107
  5. package/dist/branch-5JzX9rUq.mjs +390 -0
  6. package/dist/deletion.d.mts +7 -0
  7. package/dist/deletion.mjs +2 -0
  8. package/dist/dist-vIVO6bA-.mjs +1524 -0
  9. package/dist/import.d.mts +4 -4
  10. package/dist/import.mjs +214 -1
  11. package/dist/index.d.mts +2 -3
  12. package/dist/index.mjs +4 -1630
  13. package/dist/{log-DO69NQnn.mjs → log-CnYct2Dv.mjs} +37 -82
  14. package/dist/{sqlite-DYExtbLo.mjs → sqlite-fpvm5Dzs.mjs} +205 -75
  15. package/dist/src-CWTWV7vx.mjs +1904 -0
  16. package/dist/storage.d.mts +14 -5
  17. package/dist/storage.mjs +2 -2
  18. package/dist/testing.d.mts +2 -26
  19. package/dist/testing.mjs +10504 -9614
  20. package/drizzle/postgres/20260918120000_v3_event_usage/migration.sql +14 -0
  21. package/drizzle/postgres/20260918120000_v3_event_usage/snapshot.json +1309 -0
  22. package/drizzle/sqlite/20260918120000_v3_event_usage/migration.sql +14 -0
  23. package/drizzle/sqlite/20260918120000_v3_event_usage/snapshot.json +1031 -0
  24. package/package.json +29 -30
  25. package/src/adapters/to-postgres.ts +1 -3
  26. package/src/adapters/to-sqlite.ts +0 -2
  27. package/src/adapters/types.ts +0 -3
  28. package/src/artifact.ts +0 -2
  29. package/src/backend.ts +31 -2
  30. package/src/branch.ts +223 -135
  31. package/src/deletion.ts +87 -0
  32. package/src/drizzle/postgres-v2.ts +0 -1
  33. package/src/drizzle/postgres-v3.ts +0 -1
  34. package/src/drizzle/sqlite-v2.ts +0 -1
  35. package/src/drizzle/sqlite-v3.ts +0 -1
  36. package/src/entities/v2/session-events.ts +0 -1
  37. package/src/entities/v3/event-usage.ts +25 -0
  38. package/src/entities/v3/events.ts +1 -3
  39. package/src/entities/v3/index.ts +4 -0
  40. package/src/entities/v3/session-events.ts +1 -2
  41. package/src/entities/v3/session-projcache-rows.ts +0 -8
  42. package/src/entities/v3/sessions.ts +3 -3
  43. package/src/entities/v3/storage-units.ts +0 -1
  44. package/src/entities/v3/workspace-sessions.ts +0 -5
  45. package/src/entities/v3/workspace-state.ts +0 -6
  46. package/src/entities/v3/workspaces.ts +0 -5
  47. package/src/export.ts +103 -0
  48. package/src/gc.ts +76 -0
  49. package/src/import-storages.ts +4 -37
  50. package/src/import.ts +54 -31
  51. package/src/index.ts +150 -114
  52. package/src/legacy.ts +4 -42
  53. package/src/log.ts +63 -106
  54. package/src/postgres.ts +249 -22
  55. package/src/schema.ts +6 -6
  56. package/src/session-query.ts +0 -4
  57. package/src/sqlite.ts +231 -55
  58. package/src/storage-takeover/index.ts +2 -28
  59. package/src/storage-takeover/projection-cache.ts +30 -134
  60. package/src/storage-takeover/repository.ts +20 -59
  61. package/src/storage-takeover/storage-backend.ts +3 -33
  62. package/src/storage-takeover/types.ts +14 -56
  63. package/src/storage.ts +0 -2
  64. package/src/testing/contract.ts +19 -50
  65. package/src/testing/coordinator-contract.ts +10 -25
  66. package/src/testing.ts +2 -2
  67. package/src/usage.ts +191 -0
  68. package/dist/import-Bc2QQa5G.mjs +0 -473
  69. package/dist/index-CCcK9tia.d.mts +0 -270
  70. package/dist/magic-string.es-BgJoa-3K.mjs +0 -1017
@@ -1,10 +1,11 @@
1
1
  import z from "@deepseek-ai/schemastery";
2
- import { SessionStorageMetadata } from "@deepseek-ai/dsh-session-persistence";
2
+ import { SessionAccess, SessionHandle, SessionHandleAppendOptions, SessionHandleFlushOptions, SessionHandleReadOptions, SessionHandleReadResult, SessionPersistence, SessionPersistenceCreateOptions, SessionPersistenceListOptions, SessionPersistenceOpenOptions, SessionPersistenceRevision, SessionPersistenceSnapshot, SessionPersistenceStatOptions, SessionStorageMetadata } from "@deepseek-ai/dsh-session-persistence";
3
3
  import { Session, SessionEvent, SessionHeader, SessionId, SessionLogOffset, SessionSeq, SessionSeqCursor } from "@deepseek-ai/dsh-session";
4
+ import { BranchAnchorMode, BranchBoundary, ForkFromOptions, SessionBranch, SessionBranchProvider } from "@morlay/session-branch";
4
5
  import { KvUnit } from "@deepseek-ai/dsh-storage";
5
6
  import { Context, Service } from "@deepseek-ai/cordis";
6
7
  import { SessionId as SessionId$1 } from "@deepseek-ai/dsh-session/types";
7
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/core/json-schema.d.cts
8
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/json-schema.d.cts
8
9
  type _JSONSchema = boolean | JSONSchema;
9
10
  type SchemaType = "object" | "array" | "string" | "number" | "boolean" | "null" | "integer";
10
11
  type JSONSchema = {
@@ -73,7 +74,7 @@ type JSONSchema = {
73
74
  };
74
75
  type BaseSchema = JSONSchema;
75
76
  //#endregion
76
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/core/standard-schema.d.cts
77
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/standard-schema.d.cts
77
78
  /** The Standard interface. */
78
79
  interface StandardTypedV1<Input = unknown, Output = Input> {
79
80
  /** The Standard properties. */
@@ -192,7 +193,7 @@ declare namespace StandardJSONSchemaV1 {
192
193
  }
193
194
  interface StandardSchemaWithJSONProps<Input = unknown, Output = Input> extends StandardSchemaV1.Props<Input, Output>, StandardJSONSchemaV1.Props<Input, Output> {}
194
195
  //#endregion
195
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/core/registries.d.cts
196
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/registries.d.cts
196
197
  declare const $output: unique symbol;
197
198
  type $output = typeof $output;
198
199
  declare const $input: unique symbol;
@@ -219,7 +220,7 @@ interface JSONSchemaMeta {
219
220
  }
220
221
  interface GlobalMeta extends JSONSchemaMeta {}
221
222
  //#endregion
222
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/core/to-json-schema.d.cts
223
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/to-json-schema.d.cts
223
224
  type Processor<T extends $ZodType = $ZodType> = (schema: T, ctx: ToJSONSchemaContext, json: BaseSchema, params: ProcessParams) => void;
224
225
  /**
225
226
  * Called for each schema that has no JSON Schema equivalent. Return a JSON Schema to use in its
@@ -341,7 +342,7 @@ interface ZodStandardJSONSchemaPayload<T> extends BaseSchema {
341
342
  "~standard": ZodStandardSchemaWithJSON$1<T>;
342
343
  }
343
344
  //#endregion
344
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/core/util.d.cts
345
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/util.d.cts
345
346
  type JWTAlgorithm = "HS256" | "HS384" | "HS512" | "RS256" | "RS384" | "RS512" | "ES256" | "ES384" | "ES512" | "PS256" | "PS384" | "PS512" | "EdDSA" | (string & {});
346
347
  type MimeTypes = "application/json" | "application/xml" | "application/x-www-form-urlencoded" | "application/javascript" | "application/pdf" | "application/zip" | "application/vnd.ms-excel" | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | "application/msword" | "application/vnd.openxmlformats-officedocument.wordprocessingml.document" | "application/vnd.ms-powerpoint" | "application/vnd.openxmlformats-officedocument.presentationml.presentation" | "application/octet-stream" | "application/graphql" | "text/html" | "text/plain" | "text/css" | "text/javascript" | "text/csv" | "image/png" | "image/jpeg" | "image/gif" | "image/svg+xml" | "image/webp" | "audio/mpeg" | "audio/ogg" | "audio/wav" | "audio/webm" | "video/mp4" | "video/webm" | "video/ogg" | "font/woff" | "font/woff2" | "font/ttf" | "font/otf" | "multipart/form-data" | (string & {});
347
348
  type IsAny<T> = 0 extends 1 & T ? true : false;
@@ -384,14 +385,14 @@ declare abstract class Class {
384
385
  /** A trait's prototype members: a partial view of its own interface, with `this` typed as the instance. */
385
386
  type ProtoOf<T> = { [K in keyof T]?: (T[K] extends ((...args: infer A) => infer R) ? (...args: A) => R : T[K]) | undefined; } & ThisType<T>;
386
387
  //#endregion
387
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/core/versions.d.cts
388
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/versions.d.cts
388
389
  declare const version: {
389
390
  readonly major: 4;
390
391
  readonly minor: 6;
391
392
  readonly patch: number;
392
393
  };
393
394
  //#endregion
394
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/core/schemas.d.cts
395
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/schemas.d.cts
395
396
  interface ParseContext<T extends $ZodIssueBase = never> {
396
397
  /** Customize error messages. */
397
398
  readonly error?: $ZodErrorMap<T>;
@@ -1412,7 +1413,7 @@ interface $ZodCustom<O = unknown, I = unknown> extends $ZodType {
1412
1413
  declare const $ZodCustom: $constructor<$ZodCustom>;
1413
1414
  type $ZodTypes = $ZodString | $ZodNumber | $ZodBigInt | $ZodBoolean | $ZodDate | $ZodSymbol | $ZodUndefined | $ZodNullable | $ZodNull | $ZodAny | $ZodUnknown | $ZodNever | $ZodVoid | $ZodArray | $ZodObject | $ZodUnion | $ZodIntersection | $ZodTuple | $ZodRecord | $ZodMap | $ZodSet | $ZodLiteral | $ZodEnum | $ZodFunction | $ZodPromise | $ZodLazy | $ZodOptional | $ZodDefault | $ZodPrefault | $ZodTemplateLiteral | $ZodCustom | $ZodTransform | $ZodNonOptional | $ZodReadonly | $ZodNaN | $ZodPipe | $ZodSuccess | $ZodCatch | $ZodFile;
1414
1415
  //#endregion
1415
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/core/checks.d.cts
1416
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/checks.d.cts
1416
1417
  interface $ZodCheckDef {
1417
1418
  check: string;
1418
1419
  error?: $ZodErrorMap<never> | undefined;
@@ -1594,7 +1595,7 @@ interface $ZodCheckEndsWith extends $ZodCheckInternals<string> {
1594
1595
  }
1595
1596
  declare const $ZodCheckEndsWith: $constructor<$ZodCheckEndsWith>;
1596
1597
  //#endregion
1597
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/core/errors.d.cts
1598
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/errors.d.cts
1598
1599
  interface $ZodIssueBase {
1599
1600
  readonly code?: string;
1600
1601
  readonly input?: unknown;
@@ -1723,7 +1724,7 @@ type $ZodFormattedError<T, U = string> = {
1723
1724
  _errors: U[];
1724
1725
  } & Flatten<_ZodFormattedError<T, U>>;
1725
1726
  //#endregion
1726
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/core/core.d.cts
1727
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/core.d.cts
1727
1728
  type ZodTrait = {
1728
1729
  _zod: {
1729
1730
  def: any;
@@ -1769,7 +1770,7 @@ type output<T> = T extends {
1769
1770
  };
1770
1771
  } ? T["_zod"]["output"] : unknown;
1771
1772
  //#endregion
1772
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/core/api.d.cts
1773
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/api.d.cts
1773
1774
  type Params<T extends $ZodType | $ZodCheck, IssueTypes extends $ZodIssueBase, OmitKeys extends keyof T["_zod"]["def"] = never> = Flatten<Partial<EmptyToNever<Omit<T["_zod"]["def"], OmitKeys> & ([IssueTypes] extends [never] ? {} : {
1774
1775
  error?: string | $ZodErrorMap<IssueTypes> | undefined;
1775
1776
  /** @deprecated This parameter is deprecated. Use `error` instead. */
@@ -1841,7 +1842,7 @@ interface $ZodSuperRefineParams {
1841
1842
  when?: ((payload: ParsePayload) => boolean) | undefined;
1842
1843
  }
1843
1844
  //#endregion
1844
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/classic/errors.d.cts
1845
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/errors.d.cts
1845
1846
  /** An Error-like class used to store Zod validation issues. */
1846
1847
  interface ZodError<T = unknown> extends $ZodError<T> {
1847
1848
  /** @deprecated Use the `z.treeifyError(err)` function instead. */
@@ -1859,7 +1860,7 @@ interface ZodError<T = unknown> extends $ZodError<T> {
1859
1860
  }
1860
1861
  declare const ZodError: $constructor<ZodError>;
1861
1862
  //#endregion
1862
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/classic/parse.d.cts
1863
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/parse.d.cts
1863
1864
  type ZodSafeParseResult<T> = ZodSafeParseSuccess<T> | ZodSafeParseError<T>;
1864
1865
  type ZodSafeParseSuccess<T> = {
1865
1866
  success: true;
@@ -1872,7 +1873,7 @@ type ZodSafeParseError<T> = {
1872
1873
  error: ZodError<T>;
1873
1874
  };
1874
1875
  //#endregion
1875
- //#region ../../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/classic/schemas.d.cts
1876
+ //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/schemas.d.cts
1876
1877
  type ZodStandardSchemaWithJSON<T> = StandardSchemaWithJSONProps<input<T>, output<T>>;
1877
1878
  interface ZodType<out Output = unknown, out Input = unknown, out Internals extends $ZodTypeInternals<Output, Input> = $ZodTypeInternals<Output, Input>> extends $ZodType<Output, Input, Internals> {
1878
1879
  def: Internals["def"];
@@ -2775,13 +2776,13 @@ declare module '@deepseek-ai/cordis' {
2775
2776
  * it per domain name. A route naming an unregistered backend fails loud at
2776
2777
  * `open` with `backend-not-found`.
2777
2778
  */
2778
- interface Config$2 {
2779
+ interface Config$3 {
2779
2780
  /** Default backend name for every domain without an explicit route. Required: there is no universally correct medium. */
2780
2781
  backend: string;
2781
2782
  /** Per-domain overrides: domain name → backend name. */
2782
2783
  routes?: Record<string, string>;
2783
2784
  }
2784
- declare const Config$2: z<Config$2>;
2785
+ declare const Config$3: z<Config$3>;
2785
2786
  /**
2786
2787
  * The mounted domain facility. Opens declared domains over routed backends;
2787
2788
  * one facility instance owns the open-domain table and enforces single-open
@@ -2798,7 +2799,7 @@ declare class DomainFacility {
2798
2799
  * events attach here.
2799
2800
  * @param config - Validated plugin config.
2800
2801
  */
2801
- constructor(ctx: Context, config: Config$2);
2802
+ constructor(ctx: Context, config: Config$3);
2802
2803
  /**
2803
2804
  * Open one declared domain. Steps, each failing the whole call: reject a
2804
2805
  * name that is already open (`already-open`); resolve the backend route
@@ -2876,13 +2877,13 @@ declare module '@deepseek-ai/cordis' {
2876
2877
  * `turn/end`, and session disposal) are policy, not tunables, and always
2877
2878
  * fire.
2878
2879
  */
2879
- interface Config$1 {
2880
+ interface Config$2 {
2880
2881
  /** Committed events per session that force a durable checkpoint write between mandatory points. */
2881
2882
  writeEveryEvents: number;
2882
2883
  /** Longest time (milliseconds) a dirty checkpoint may stay unwritten between mandatory points. */
2883
2884
  writeIntervalMs: number;
2884
2885
  }
2885
- declare const Config$1: z<Config$1>;
2886
+ declare const Config$2: z<Config$2>;
2886
2887
  /**
2887
2888
  * The persisted projection cache service. Opens the `session_projcache`
2888
2889
  * domain at init, checkpoints live sessions on a throttled write-behind
@@ -2893,12 +2894,12 @@ declare const Config$1: z<Config$1>;
2893
2894
  * failures log a warning and the cache self-heals on the next write.
2894
2895
  */
2895
2896
  declare class SessionProjectionCache extends Service {
2896
- config: Config$1;
2897
+ config: Config$2;
2897
2898
  static inject: string[];
2898
- static Config: z<Config$1>;
2899
+ static Config: z<Config$2>;
2899
2900
  private table?;
2900
2901
  private readonly dirty;
2901
- constructor(ctx: Context, config: Config$1);
2902
+ constructor(ctx: Context, config: Config$2);
2902
2903
  /** Open the domain and install the write-behind listeners. */
2903
2904
  protected [Service.init](): Promise<void>;
2904
2905
  /**
@@ -3242,6 +3243,17 @@ declare class WorkspaceRegistry extends Service {
3242
3243
  * @returns resolution after durability.
3243
3244
  */
3244
3245
  archiveSession(sessionId: SessionId): Promise<void>;
3246
+ /**
3247
+ * Unarchive one session durably by dropping it from the registry-global
3248
+ * archive set; the accounting slot was never touched, so the session
3249
+ * returns to its recorded position. Unarchiving runs no session-existence
3250
+ * check because removing an id cannot introduce an unknown one, so an
3251
+ * entry whose session is gone still resolves. An id that is not archived
3252
+ * resolves without writing.
3253
+ * @param sessionId - The session to unarchive.
3254
+ * @returns resolution after durability.
3255
+ */
3256
+ unarchiveSession(sessionId: SessionId): Promise<void>;
3245
3257
  /**
3246
3258
  * Whether a session is live, header-indexed, or present in a fresh
3247
3259
  * persistence listing. Only a definite miss returns false — a failing
@@ -3283,75 +3295,337 @@ declare class WorkspaceRegistry extends Service {
3283
3295
  }
3284
3296
  //#endregion
3285
3297
  //#region src/storage-takeover/types.d.ts
3286
- /**
3287
- * 一个会话的完整 checkpoint:上游 `CheckpointIdentity`(日志身份,唯一权威定义
3288
- * 在被替换的 projcache spec 里)+ 上游 `ProjectionCheckpoint`(逐 key 行)+ 会话键。
3289
- */
3290
3298
  interface StoredProjcacheEntry {
3291
3299
  sessionId: SessionId;
3292
3300
  identity: CheckpointIdentity;
3293
3301
  rows: ProjectionCheckpoint;
3294
3302
  }
3295
- /**
3296
- * storages 接管表的方言无关访问层:SQLite 与 PostgreSQL 两个 Backend 各提供
3297
- * 同一实现,调用方(KV 后端与投影缓存服务)不感知介质差异。读方法返回持久
3298
- * 值的语义视图,workspace 的写入在介质事务内整体替换。
3299
- */
3300
3303
  interface StorageRepository {
3301
- /** 读一个域的版本戳;域从未打开时 undefined。 */
3302
3304
  readUnitVersion(name: string): Promise<number | undefined>;
3303
- /** 写入域的首次版本戳;已存在时保持原值。 */
3304
3305
  insertUnitVersion(name: string, version: number): Promise<void>;
3305
- /** 读全部 workspace 记录(按 workspace id)。 */
3306
3306
  listWorkspaces(): Promise<Array<{
3307
3307
  id: string;
3308
3308
  record: WorkspaceRecord;
3309
3309
  }>>;
3310
- /** 覆盖写一条 workspace 记录(含归属行)。 */
3311
3310
  putWorkspace(id: string, record: WorkspaceRecord): Promise<void>;
3312
- /** 删除一条 workspace 记录(缺失为 no-op)。 */
3313
3311
  deleteWorkspace(id: string): Promise<void>;
3314
- /** 读 workspace 单例;从未写入时 null。 */
3315
3312
  readWorkspaceState(): Promise<WorkspaceDomainState | null>;
3316
- /** 覆盖写 workspace 单例(显示顺序与归档集一并整体替换)。 */
3317
3313
  writeWorkspaceState(state: WorkspaceDomainState): Promise<void>;
3318
- /** 读全部投影 checkpoint(含逐 key 行)。 */
3319
3314
  loadProjcache(): Promise<StoredProjcacheEntry[]>;
3320
- /**
3321
- * 同步读一个会话的 checkpoint:只有同步驱动(SQLite)提供,读路径直接落到
3322
- * 介质;异步驱动(PostgreSQL)缺席,调用方退化为写穿镜像。上游的
3323
- * `cachedSnapshot` 系列是同步签名,这里的存在性就是"能否直读库"的开关。
3324
- * @param sessionId - 会话 id。
3325
- * @returns 该会话的 checkpoint,缺失时 `undefined`。
3326
- */
3327
- readProjcacheSync?(sessionId: string): StoredProjcacheEntry | undefined;
3328
- /**
3329
- * 同步读一个会话的标题列(`t_sessions.f_title` / `f_title_seq`,rdb 写路径与
3330
- * rewind 维护):只有同步驱动提供,列表消费直接取会话数据,不依赖 checkpoint
3331
- * 行是否存在。
3332
- * @param sessionId - 会话 id。
3333
- * @returns 标题与其事件 seq,未写过标题时 `undefined`。
3334
- */
3335
- readSessionTitleSync?(sessionId: string): {
3315
+ /** 不经 await、直接读的路径(供同步的 `cachedSnapshot` 消费);宿主提供不了则缺省。 */
3316
+ readProjcacheDirect?(sessionId: string): StoredProjcacheEntry | undefined;
3317
+ readSessionTitleDirect?(sessionId: string): {
3336
3318
  title: string;
3337
3319
  seq: number;
3338
3320
  } | undefined;
3339
- /**
3340
- * 覆盖写一个会话的 checkpoint 行(先清旧行再写新行,同一事务)。记录头
3341
- * 不在这里:它与 `t_sessions` 行 1:1,identity 直接复用该行的列。
3342
- * @param sessionId - 会话 id。
3343
- * @param rows - 每个投影 key 一行。
3344
- */
3345
3321
  putProjcache(sessionId: string, rows: ProjectionCheckpoint): Promise<void>;
3346
- /**
3347
- * 清理陈旧 checkpoint 行:水位为负却已有事件的会话(旧版写入路径的产物,
3348
- * 会把有对话的会话误判为空白)。缓存是派生数据,删除只让该会话回到
3349
- * 「未知即可见」并等待下一次强制点重写。
3350
- * @returns 删除的行数。
3351
- */
3352
3322
  pruneStaleProjcache(): Promise<number>;
3353
3323
  }
3354
3324
  //#endregion
3325
+ //#region src/write-guard.d.ts
3326
+ declare class WriteGuard {
3327
+ private readonly headSeqs;
3328
+ confirmHead(id: SessionId, head: number): void;
3329
+ assertNoConcurrentWriter(id: SessionId, storedHead: number): void;
3330
+ }
3331
+ //#endregion
3332
+ //#region src/schema.d.ts
3333
+ declare const SCHEMA_VERSION = 3;
3334
+ declare const SESSION_PERSISTENCE_SQLITE_APPLICATION_ID = 1146308688;
3335
+ declare const EVENT_ENCODING = "json";
3336
+ declare const tPersistenceState: any;
3337
+ declare const tSchemaMeta: any;
3338
+ declare const tSessions: any;
3339
+ declare const tEvents: any;
3340
+ declare const tSessionEvents: any;
3341
+ declare const tStorageUnits: any;
3342
+ declare const tWorkspaces: any;
3343
+ declare const tWorkspaceSessions: any;
3344
+ declare const tWorkspaceState: any;
3345
+ declare const tSessionProjcacheRows: any;
3346
+ declare const tEventUsage: any;
3347
+ type JournalMode = "wal" | "delete" | "truncate" | "persist";
3348
+ declare const DEFAULT_BUSY_TIMEOUT_MS = 5000;
3349
+ type EventKind = "message" | "thinking" | "turn" | "tool" | "request" | "config" | "audit" | "lifecycle" | "inbox" | "compaction" | "llm" | "subagent" | "team" | "workflow" | "goal" | "schedule" | "todo" | "web";
3350
+ type EventRole = "user" | "assistant" | "tool";
3351
+ declare function eventKind(event: {
3352
+ type: string;
3353
+ data?: unknown;
3354
+ }): EventKind | "";
3355
+ declare function eventDimensions(event: SessionEvent): {
3356
+ kind: string;
3357
+ role: string;
3358
+ name: string;
3359
+ actionId: string;
3360
+ };
3361
+ //#endregion
3362
+ //#region src/branch.d.ts
3363
+ declare function locateTurnEnd(events: readonly SessionEvent[], atSeq?: number, mode?: BranchAnchorMode): number;
3364
+ interface LiveSessionHooks {
3365
+ getSession(id: SessionId): Session | undefined;
3366
+ getAgent(id: SessionId): LiveAgentLike | undefined;
3367
+ flush(session: Session): Promise<boolean>;
3368
+ warn?(message: string): void;
3369
+ resetProjections?(session: Session): void;
3370
+ resetTokenMeter?(session: Session): void;
3371
+ refreshProjectionCache?(session: ProjectionCacheSession): Promise<void>;
3372
+ }
3373
+ interface ProjectionCacheSession {
3374
+ readonly id: SessionId;
3375
+ readonly header: SessionHeader;
3376
+ readonly inheritedEventCount: SessionLogOffset;
3377
+ readonly headSeq?: number;
3378
+ snapshotEvents(): readonly SessionEvent[];
3379
+ }
3380
+ interface LiveAgentLike {
3381
+ session: Session;
3382
+ requestHeaderLogged?: boolean;
3383
+ inbox?: {
3384
+ clear(): void;
3385
+ };
3386
+ }
3387
+ declare function truncateLiveSession(session: Session, newLength: number): void;
3388
+ declare class SessionBranchRdbProvider implements SessionBranchProvider {
3389
+ private readonly persistence;
3390
+ private readonly live;
3391
+ readonly name = "session-rdb";
3392
+ constructor(persistence: SessionPersistenceRdb, live?: LiveSessionHooks);
3393
+ readBranchPrefix(id: SessionId, atSeq?: number, mode?: BranchAnchorMode, signal?: AbortSignal): Promise<BranchBoundary>;
3394
+ readRawEvents(id: SessionId, signal?: AbortSignal): Promise<{
3395
+ meta: SessionHeader;
3396
+ events: readonly SessionEvent[];
3397
+ }>;
3398
+ forkFrom(sourceId: SessionId, options?: ForkFromOptions, signal?: AbortSignal): Promise<SessionId>;
3399
+ rewind(id: SessionId, toBoundary: number, signal?: AbortSignal): Promise<SessionPersistenceSnapshot>;
3400
+ private rewindKeepLength;
3401
+ private refreshProjectionCache;
3402
+ }
3403
+ declare class SessionBranchRdb extends SessionBranch {
3404
+ static inject: string[];
3405
+ private readonly warned;
3406
+ constructor(ctx: import("@deepseek-ai/cordis").Context);
3407
+ resetLiveDerivedState(session: Session): void;
3408
+ private warnOnce;
3409
+ private resetProjectionCells;
3410
+ private resetTokenMeterFold;
3411
+ private readonly provider;
3412
+ readBranchPrefix(id: SessionId, atSeq?: number, mode?: BranchAnchorMode, signal?: AbortSignal): Promise<BranchBoundary>;
3413
+ readRawEvents(id: SessionId, signal?: AbortSignal): Promise<{
3414
+ meta: SessionHeader;
3415
+ events: readonly SessionEvent[];
3416
+ }>;
3417
+ forkFrom(sourceId: SessionId, options?: ForkFromOptions, signal?: AbortSignal): Promise<SessionId>;
3418
+ rewind(id: SessionId, toBoundary: number, signal?: AbortSignal): Promise<SessionPersistenceSnapshot>;
3419
+ timeline(sessionId: SessionId, signal?: AbortSignal): Promise<import("@morlay/session-branch").BranchTimeline>;
3420
+ }
3421
+ //#endregion
3422
+ //#region src/index.d.ts
3423
+ interface SessionPersistenceRdbInternals {
3424
+ readonly backend: Backend;
3425
+ readonly writeGuard: WriteGuard;
3426
+ create(meta: SessionHeader, inheritedEventCount?: number): Promise<SessionHandle>;
3427
+ append(id: SessionId, events: readonly SessionEvent[]): Promise<void>;
3428
+ load(id: SessionId): Promise<import("@deepseek-ai/dsh-session-persistence").SessionInspection>;
3429
+ inspect(id: SessionId, signal?: AbortSignal): Promise<import("@deepseek-ai/dsh-session-persistence").SessionInspection>;
3430
+ readFrom(id: SessionId, fromSeq: number, signal?: AbortSignal): Promise<{
3431
+ meta: SessionHeader;
3432
+ inheritedEventCount: number;
3433
+ events: readonly SessionEvent[];
3434
+ }>;
3435
+ listSnapshots(signal?: AbortSignal): Promise<SessionPersistenceSnapshot[]>;
3436
+ readStoredRevision(id: SessionId, signal?: AbortSignal): Promise<import("@deepseek-ai/dsh-session-persistence").SessionPersistenceRevision | undefined>;
3437
+ registerReuseEventIds(childId: SessionId, map: ReadonlyMap<number, string>): void;
3438
+ }
3439
+ interface ProjectionCacheOptions {
3440
+ writeEveryEvents?: number;
3441
+ writeIntervalMs?: number;
3442
+ }
3443
+ type Config$1 = {
3444
+ type: "sqlite";
3445
+ path: string;
3446
+ journalMode?: JournalMode;
3447
+ busyTimeout?: number;
3448
+ projectionCache?: ProjectionCacheOptions;
3449
+ } | {
3450
+ type: "postgres";
3451
+ connectionString: string;
3452
+ schema?: string;
3453
+ projectionCache?: ProjectionCacheOptions;
3454
+ };
3455
+ type SessionDeletionErrorCode = "SESSION_NOT_FOUND" | "SESSION_NOT_ARCHIVED" | "SESSION_LIVE";
3456
+ declare class SessionDeletionError extends Error {
3457
+ readonly code: SessionDeletionErrorCode;
3458
+ constructor(message: string, code: SessionDeletionErrorCode);
3459
+ }
3460
+ interface PendingSession {
3461
+ readonly header: SessionHeader;
3462
+ readonly revision: SessionPersistenceRevision;
3463
+ readonly inheritedEventCount: SessionLogOffset;
3464
+ readonly cursor: number;
3465
+ readonly everAppended: boolean;
3466
+ }
3467
+ declare class RdbBackendTracker {
3468
+ private readonly name;
3469
+ private readonly writers;
3470
+ private readonly pending;
3471
+ private readonly openHandles;
3472
+ private counter;
3473
+ constructor(name: string);
3474
+ registerCreated(header: SessionHeader, inheritedEventCount: SessionLogOffset): void;
3475
+ updatePending(id: SessionId, cursor: number, everAppended: boolean): void;
3476
+ claimWrite(id: SessionId): void;
3477
+ releaseClaim(id: SessionId): void;
3478
+ pendingOf(id: SessionId): PendingSession | undefined;
3479
+ hasPending(id: SessionId): boolean;
3480
+ pendingEntries(): IterableIterator<[SessionId, PendingSession]>;
3481
+ materialized(id: SessionId): void;
3482
+ adopt(handle: RdbSessionHandle): RdbSessionHandle;
3483
+ release(handle: RdbSessionHandle, materialized: boolean): void;
3484
+ writerOf(id: SessionId): RdbSessionHandle | undefined;
3485
+ hasOpenHandle(id: SessionId): boolean;
3486
+ flushAll(): Promise<void>;
3487
+ closeAll(): Promise<void>;
3488
+ }
3489
+ declare class RdbSessionHandle implements SessionHandle {
3490
+ private readonly persistence;
3491
+ readonly id: SessionId;
3492
+ readonly header: SessionHeader;
3493
+ readonly access: SessionAccess;
3494
+ private readonly state;
3495
+ private chain;
3496
+ private closing;
3497
+ private cursor;
3498
+ private materialized;
3499
+ private buffered;
3500
+ private batchTimer;
3501
+ private drainPaused;
3502
+ private draining;
3503
+ private tornTruncateTo;
3504
+ private everAppended;
3505
+ constructor(persistence: SessionPersistenceRdb, id: SessionId, header: SessionHeader, access: SessionAccess, state: {
3506
+ cursor: number;
3507
+ materialized: boolean;
3508
+ inheritedEventCount: SessionLogOffset;
3509
+ tornTruncateTo?: number;
3510
+ });
3511
+ get inheritedEventCount(): SessionLogOffset;
3512
+ get cursorValue(): number;
3513
+ read(offset?: number, length?: number, options?: SessionHandleReadOptions): Promise<SessionHandleReadResult>;
3514
+ append(events: readonly SessionEvent[], options?: SessionHandleAppendOptions): Promise<void>;
3515
+ flush(options?: SessionHandleFlushOptions): Promise<void>;
3516
+ close(): Promise<void>;
3517
+ [Symbol.asyncDispose](): Promise<void>;
3518
+ enqueueLive(event: SessionEvent, reportBackgroundFailure: (error: unknown) => void): void;
3519
+ resetAfterRewind(cursor: number, inheritedEventCount?: number): void;
3520
+ drainLive(): Promise<void>;
3521
+ private drainBuffered;
3522
+ private enqueueChain;
3523
+ private run;
3524
+ private assertOpen;
3525
+ static readonly LIVE_WRITE_BATCH_MAX_DELAY_MS = 200;
3526
+ }
3527
+ declare class SessionPersistenceRdb extends SessionPersistence {
3528
+ config: Config$1;
3529
+ static inject: string[];
3530
+ static Config: z<Config$1>;
3531
+ static readonly settingsNs = "session-rdb";
3532
+ readonly name = "session-rdb";
3533
+ readonly tracker: RdbBackendTracker;
3534
+ private readonly backend;
3535
+ private storeIdentity;
3536
+ private readonly ready;
3537
+ private readonly writeGuard;
3538
+ private readonly reuseEventIds;
3539
+ private readonly liveBuffers;
3540
+ private readonly liveReady;
3541
+ constructor(ctx: Context, config: Config$1, injectedBackend?: Backend);
3542
+ private init;
3543
+ create(header: SessionHeader, options?: SessionPersistenceCreateOptions): Promise<SessionHandle>;
3544
+ open(id: SessionId, access: SessionAccess, options?: SessionPersistenceOpenOptions): Promise<SessionHandle>;
3545
+ flush(): Promise<void>;
3546
+ stat(id: SessionId, options?: SessionPersistenceStatOptions): Promise<SessionPersistenceSnapshot | undefined>;
3547
+ list(options?: SessionPersistenceListOptions): Promise<readonly SessionPersistenceSnapshot[]>;
3548
+ deleteSession(id: SessionId, signal?: AbortSignal): Promise<void>;
3549
+ /** GC 通道:回收已无桥接行引用的事件行(孤儿),返回删除行数。 */
3550
+ collectOrphans(): Promise<number>;
3551
+ /** GC 通道:回收父已不存在的 subagent 会话(live 的跳过),返回删除的会话数。 */
3552
+ collectOrphanSessions(): Promise<number>;
3553
+ /** 用量统计:SQL 聚合的按天 × 模型桶与按会话行(事件行去重、排除孤儿行)。 */
3554
+ usageReport(sinceMs?: number): Promise<UsageAggregate>;
3555
+ /** GC 通道:VACUUM;调用方需先停止运行中的写路径(见 `registerSessionGc`)。 */
3556
+ vacuum(): Promise<void>;
3557
+ private unarchiveBeforeDeletion;
3558
+ readRaw(id: SessionId, signal?: AbortSignal): Promise<{
3559
+ meta: SessionHeader;
3560
+ inheritedEventCount: number;
3561
+ filename: string;
3562
+ content: string;
3563
+ } | undefined>;
3564
+ materializeEmpty(meta: SessionHeader, inheritedEventCount: SessionLogOffset): Promise<void>;
3565
+ appendBatch(meta: SessionHeader, inheritedEventCount: SessionLogOffset, events: readonly SessionEvent[], tornTruncateTo?: number): Promise<boolean>;
3566
+ readLog(id: SessionId, options?: {
3567
+ fromSeq?: number;
3568
+ }, signal?: AbortSignal): Promise<{
3569
+ meta: SessionHeader;
3570
+ inheritedEventCount: number;
3571
+ events: SessionEvent[];
3572
+ tornFrom?: number;
3573
+ incarnation: string;
3574
+ revision: number;
3575
+ storedCount: number;
3576
+ migrated: boolean;
3577
+ } | undefined>;
3578
+ private rewriteMigratedLog;
3579
+ listSnapshots(signal?: AbortSignal): Promise<Array<SessionPersistenceSnapshot & {
3580
+ inheritedEventCount: number;
3581
+ }>>;
3582
+ readStoredRevision(id: SessionId, signal?: AbortSignal): Promise<SessionPersistenceRevision | undefined>;
3583
+ createAndAppend(header: SessionHeader, events: readonly SessionEvent[], inheritedEventCount?: number): Promise<void>;
3584
+ load(id: SessionId, signal?: AbortSignal): Promise<import("@deepseek-ai/dsh-session-persistence").SessionInspection>;
3585
+ append(id: SessionId, events: readonly SessionEvent[]): Promise<void>;
3586
+ readFrom(id: SessionId, fromSeq: number, signal?: AbortSignal): Promise<{
3587
+ meta: SessionHeader;
3588
+ inheritedEventCount: number;
3589
+ events: readonly SessionEvent[];
3590
+ }>;
3591
+ close(): Promise<void>;
3592
+ registerReuseEventIds(childId: SessionId, map: ReadonlyMap<number, string>): void;
3593
+ internals(): SessionPersistenceRdbInternals;
3594
+ private rowRevision;
3595
+ private installLiveRouting;
3596
+ private ensureLiveHandle;
3597
+ }
3598
+ //#endregion
3599
+ //#region src/usage.d.ts
3600
+ /** 一段用量合计(token 字段直接取事件里模型报的 usage)。 */
3601
+ interface UsageTotals {
3602
+ events: number;
3603
+ inputTokens: number;
3604
+ outputTokens: number;
3605
+ cacheReadTokens: number;
3606
+ reasoningTokens: number;
3607
+ totalTokens: number;
3608
+ }
3609
+ /** 一天 × 一个模型 × 是否子代理 的用量桶:总览、按天、按模型都由它折叠。 */
3610
+ interface UsageBucket extends UsageTotals {
3611
+ day: string;
3612
+ provider: string | null;
3613
+ model: string | null;
3614
+ subagent: boolean;
3615
+ }
3616
+ /** 一条会话的用量行。 */
3617
+ interface UsageSessionRow extends UsageTotals {
3618
+ sessionId: string;
3619
+ title: string | null;
3620
+ subagent: boolean;
3621
+ archived: boolean;
3622
+ }
3623
+ /** 后端的原始聚合结果。 */
3624
+ interface UsageAggregate {
3625
+ buckets: UsageBucket[];
3626
+ sessions: UsageSessionRow[];
3627
+ }
3628
+ //#endregion
3355
3629
  //#region src/backend.d.ts
3356
3630
  interface SessionRow {
3357
3631
  fSessionId: string;
@@ -3366,6 +3640,7 @@ interface SessionRow {
3366
3640
  fDelegationDepth: number | null;
3367
3641
  fIncarnation: string;
3368
3642
  fRevision: number;
3643
+ fArchivedAt: number | null;
3369
3644
  }
3370
3645
  interface EventInsert {
3371
3646
  fEventId: string;
@@ -3396,7 +3671,6 @@ interface BackendTx {
3396
3671
  getHead(id: SessionId): Promise<Pick<SessionRow, "fHeadEventId" | "fHeadSequence">>;
3397
3672
  getSeedLength(id: SessionId): Promise<number | null>;
3398
3673
  updateSeedLength(id: SessionId, seedLength: number): Promise<void>;
3399
- /** 从事件表重算会话标题(最后一条 `session/title`)并写回会话行。 */
3400
3674
  refreshTitle(id: SessionId): Promise<void>;
3401
3675
  insertEvents(events: EventInsert[]): Promise<void>;
3402
3676
  insertBridges(rows: Array<{
@@ -3412,54 +3686,33 @@ interface BackendTx {
3412
3686
  fEventId: string;
3413
3687
  fSequence: number;
3414
3688
  } | undefined>;
3689
+ deleteSession(id: SessionId): Promise<void>;
3690
+ /** 批量删除整条会话:桥接行、workspace 归属行、投影行与会话行。 */
3691
+ deleteSessions(ids: SessionId[]): Promise<number>;
3415
3692
  }
3416
3693
  interface Backend {
3417
3694
  readonly kind: "sqlite" | "postgres";
3418
3695
  readonly storeIdentity: string;
3419
- /** storages 接管表(workspace 域与投影 checkpoint)的访问层:与事件日志同介质。 */
3420
3696
  readonly storage: StorageRepository;
3421
3697
  open(): Promise<void>;
3422
3698
  getSession(id: SessionId): Promise<SessionRow | undefined>;
3423
3699
  getEventRows(id: SessionId, fromSequence?: number): Promise<EventRow[]>;
3700
+ getEventTypeAt(id: SessionId, sequence: number): Promise<string | undefined>;
3701
+ getEventTypesBefore(id: SessionId, beforeSequence: number, limit: number): Promise<Array<Pick<EventRow, "fSequence" | "fType">>>;
3424
3702
  listSessions(): Promise<SessionRow[]>;
3425
3703
  transaction<T>(fn: (tx: BackendTx) => Promise<T>): Promise<T>;
3704
+ /** 删除已无桥接行引用的事件行(孤儿),返回删除行数。 */
3705
+ collectOrphans(): Promise<number>;
3706
+ /** 父会话已不存在(或没有父)的 subagent 会话:父被删后它们成了孤儿。 */
3707
+ listOrphanSubagentSessions(): Promise<SessionId[]>;
3708
+ /**
3709
+ * 用量统计的原始聚合:按天×模型×subagent 的桶与按会话的行(事件行去重、排除孤儿)。
3710
+ * @param sinceMs - 只算该时刻(含)之后的事件行;省略即全量。
3711
+ */
3712
+ usageReport(sinceMs?: number): Promise<UsageAggregate>;
3713
+ /** 回收空间与统计(含 VACUUM);不得在事务内执行。 */
3714
+ vacuum(): Promise<void>;
3426
3715
  close(): Promise<void>;
3427
3716
  }
3428
3717
  //#endregion
3429
- //#region src/write-guard.d.ts
3430
- declare class WriteGuard {
3431
- private readonly headSeqs;
3432
- confirmHead(id: SessionId, head: number): void;
3433
- assertNoConcurrentWriter(id: SessionId, storedHead: number): void;
3434
- }
3435
- //#endregion
3436
- //#region src/schema.d.ts
3437
- declare const SCHEMA_VERSION = 3;
3438
- declare const SESSION_PERSISTENCE_SQLITE_APPLICATION_ID = 1146308688;
3439
- declare const EVENT_ENCODING = "json";
3440
- declare const tPersistenceState: any;
3441
- declare const tSchemaMeta: any;
3442
- declare const tSessions: any;
3443
- declare const tEvents: any;
3444
- declare const tSessionEvents: any;
3445
- declare const tStorageUnits: any;
3446
- declare const tWorkspaces: any;
3447
- declare const tWorkspaceSessions: any;
3448
- declare const tWorkspaceState: any;
3449
- declare const tSessionProjcacheRows: any;
3450
- type JournalMode = "wal" | "delete" | "truncate" | "persist";
3451
- declare const DEFAULT_BUSY_TIMEOUT_MS = 5000;
3452
- type EventKind = "message" | "thinking" | "turn" | "tool" | "request" | "config" | "audit" | "lifecycle" | "inbox" | "compaction" | "llm" | "subagent" | "team" | "workflow" | "goal" | "schedule" | "todo" | "web";
3453
- type EventRole = "user" | "assistant" | "tool";
3454
- declare function eventKind(event: {
3455
- type: string;
3456
- data?: unknown;
3457
- }): EventKind | "";
3458
- declare function eventDimensions(event: SessionEvent): {
3459
- kind: string;
3460
- role: string;
3461
- name: string;
3462
- actionId: string;
3463
- };
3464
- //#endregion
3465
- export { EventRow as C, BackendTx as S, StorageRepository as T, tWorkspaceSessions as _, JournalMode as a, WriteGuard as b, eventDimensions as c, tPersistenceState as d, tSchemaMeta as f, tStorageUnits as g, tSessions as h, EventRole as i, eventKind as l, tSessionProjcacheRows as m, EVENT_ENCODING as n, SCHEMA_VERSION as o, tSessionEvents as p, EventKind as r, SESSION_PERSISTENCE_SQLITE_APPLICATION_ID as s, DEFAULT_BUSY_TIMEOUT_MS as t, tEvents as u, tWorkspaceState as v, SessionRow as w, Backend as x, tWorkspaces as y };
3718
+ export { tSessionProjcacheRows as A, eventDimensions as C, tPersistenceState as D, tEvents as E, tWorkspaces as F, WriteGuard as I, StorageRepository as L, tStorageUnits as M, tWorkspaceSessions as N, tSchemaMeta as O, tWorkspaceState as P, SESSION_PERSISTENCE_SQLITE_APPLICATION_ID as S, tEventUsage as T, EVENT_ENCODING as _, UsageAggregate as a, JournalMode as b, SessionDeletionError as c, SessionPersistenceRdbInternals as d, SessionBranchRdb as f, DEFAULT_BUSY_TIMEOUT_MS as g, truncateLiveSession as h, SessionRow as i, tSessions as j, tSessionEvents as k, SessionDeletionErrorCode as l, locateTurnEnd as m, BackendTx as n, Config$1 as o, SessionBranchRdbProvider as p, EventRow as r, ProjectionCacheOptions as s, Backend as t, SessionPersistenceRdb as u, EventKind as v, eventKind as w, SCHEMA_VERSION as x, EventRole as y };