@morlay/session-rdb 0.0.18 → 0.0.19

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.
@@ -1,4 +1,4 @@
1
- import { C as EventRow, w as SessionRow } from "./schema-Bo6Hy5gW.mjs";
1
+ import { C as EventRow, w as SessionRow } from "./schema-DPcuEh_a.mjs";
2
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
4
  import { SessionEvent, SessionHeader } from "@deepseek-ai/dsh-session";
package/dist/artifact.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  import { _ as toJsonlArtifact, a as repairAssistantSettlement, c as repairRequestHeaders, d as rowToMeta, f as scanRows, g as titleOfEventData, h as syncMeteringRanges, i as renameLegacyPtcEvents, l as repairSurfaceOps, m as sessionInsertRow, n as orphanInboxSpliceSeqs, o as repairOrphanInboxSplices, p as sessionConflictRow, r as recomputeReplaceProvenance, s as repairReadView, t as findSurfaceRepairs, u as rowToEvent } from "./log-DO69NQnn.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-DZIAjOUr.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-Bc2QQa5G.mjs";
3
3
  export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME, findSurfaceRepairs, orphanInboxSpliceSeqs, parseImportZip, parseJsonlArtifact, persistImport, recomputeReplaceProvenance, registerSessionImport, renameLegacyPtcEvents, repairAssistantSettlement, repairOrphanInboxSplices, repairReadView, repairRequestHeaders, repairSurfaceOps, rowToEvent, rowToMeta, scanRows, sessionConflictRow, sessionInsertRow, syncMeteringRanges, titleOfEventData, toJsonlArtifact };
@@ -1,6 +1,7 @@
1
1
  import { d as rowToMeta } from "./log-DO69NQnn.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { SESSION_FORMAT_VERSION, SessionLogOffset } from "@deepseek-ai/dsh-session";
4
+ import { parseSessionFormatLogFilename } from "@deepseek-ai/dsh-session-format";
4
5
  import { sessionFormatCatalog } from "@deepseek-ai/dsh-session-format-catalog";
5
6
  import { SessionBranch, SessionBranchError, balanceRewindPrefix, buildTimeline } from "@morlay/session-branch";
6
7
  import { unzipSync } from "fflate";
@@ -279,6 +280,7 @@ var SessionBranchRdb = class extends SessionBranch {
279
280
  };
280
281
  //#endregion
281
282
  //#region src/import.ts
283
+ /** 当前世代产物的文件名(读入侧接受任意 canonical 世代名,见 parseImportZip)。 */
282
284
  const SESSION_LOG_ARTIFACT_FILENAME = "session.jsonl";
283
285
  const SESSION_IMPORT_PATH = "/api/session.import";
284
286
  const MAX_IMPORT_ZIP_BYTES = 67108864;
@@ -348,14 +350,21 @@ function parseImportZip(zip) {
348
350
  } catch {
349
351
  throw new Error("imported zip is not a valid ZIP archive");
350
352
  }
351
- const artifact = entries[SESSION_LOG_ARTIFACT_FILENAME];
352
- if (artifact === void 0) throw new Error(`imported zip is missing ${SESSION_LOG_ARTIFACT_FILENAME}`);
353
- return parseJsonlArtifact(new TextDecoder().decode(artifact));
353
+ const artifact = Object.entries(entries).find(([name]) => parseSessionFormatLogFilename(name) !== void 0);
354
+ if (artifact === void 0) throw new Error(`imported zip has no session log artifact (expected ${SESSION_LOG_ARTIFACT_FILENAME} or a canonical session.vN.jsonl)`);
355
+ return parseJsonlArtifact(new TextDecoder().decode(artifact[1]));
354
356
  }
355
- async function persistImport(persistence, branch, imported, targetId, sessions) {
357
+ async function stopAgentLoop(ctx, sessionId) {
358
+ const agent = ctx.get("agents")?.get(sessionId);
359
+ if (agent === void 0) return;
360
+ agent.cancel?.({ kind: "user" }, { keepInbox: true });
361
+ await agent.whenIdle();
362
+ }
363
+ async function persistImport(persistence, branch, imported, targetId, sessions, stopLoop) {
356
364
  const id = targetId ?? `session-${randomUUID()}`;
357
365
  if (targetId !== void 0) {
358
366
  if (branch === void 0) throw new Error("sessionBranch service is unavailable");
367
+ if (stopLoop !== void 0) await stopLoop(targetId);
359
368
  await branch.rewind(targetId, -1);
360
369
  const liveHandle = persistence.tracker.writerOf(targetId);
361
370
  if (liveHandle !== void 0) {
@@ -442,7 +451,7 @@ function registerSessionImport(ctx, persistence) {
442
451
  const branch = webCtx.get("sessionBranch");
443
452
  try {
444
453
  const sessions = webCtx.get("sessions");
445
- const id = await persistImport(persistence, branch, imported, targetId, sessions);
454
+ const id = await persistImport(persistence, branch, imported, targetId, sessions, (sessionId) => stopAgentLoop(webCtx, sessionId));
446
455
  res.writeHead(200, { "content-type": "application/json" });
447
456
  res.end(JSON.stringify({ sessionId: id }));
448
457
  } catch (error) {
package/dist/import.d.mts CHANGED
@@ -1,8 +1,9 @@
1
- import { r as SessionPersistenceRdb } from "./index-BEKoV1Uy.mjs";
1
+ import { r as SessionPersistenceRdb } from "./index-CCcK9tia.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
+ /** 当前世代产物的文件名(读入侧接受任意 canonical 世代名,见 parseImportZip)。 */
6
7
  declare const SESSION_LOG_ARTIFACT_FILENAME = "session.jsonl";
7
8
  declare const SESSION_IMPORT_PATH = "/api/session.import";
8
9
  declare function parseJsonlArtifact(content: string): SessionStorageMetadata & {
@@ -17,7 +18,7 @@ declare function persistImport(persistence: SessionPersistenceRdb, branch: {
17
18
  events: SessionEvent[];
18
19
  }, targetId?: SessionId, sessions?: {
19
20
  get(id: SessionId): Session | undefined;
20
- }): Promise<SessionId>;
21
+ }, stopLoop?: (id: SessionId) => Promise<void>): Promise<SessionId>;
21
22
  declare function registerSessionImport(ctx: Context, persistence: SessionPersistenceRdb): void;
22
23
  //#endregion
23
24
  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 persistImport, i as parseJsonlArtifact, n as SESSION_LOG_ARTIFACT_FILENAME, o as registerSessionImport, r as parseImportZip, t as SESSION_IMPORT_PATH } from "./import-DZIAjOUr.mjs";
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-Bc2QQa5G.mjs";
2
2
  export { SESSION_IMPORT_PATH, SESSION_LOG_ARTIFACT_FILENAME, parseImportZip, parseJsonlArtifact, persistImport, registerSessionImport };
@@ -1,4 +1,4 @@
1
- import { a as JournalMode, b as WriteGuard, x as Backend } from "./schema-Bo6Hy5gW.mjs";
1
+ import { a as JournalMode, b as WriteGuard, x as Backend } from "./schema-DPcuEh_a.mjs";
2
2
  import z from "@deepseek-ai/schemastery";
3
3
  import { SessionAccess, SessionHandle, SessionHandleAppendOptions, SessionHandleFlushOptions, SessionHandleReadOptions, SessionHandleReadResult, SessionPersistence, SessionPersistenceCreateOptions, SessionPersistenceListOptions, SessionPersistenceOpenOptions, SessionPersistenceRevision, SessionPersistenceSnapshot, SessionPersistenceStatOptions } from "@deepseek-ai/dsh-session-persistence";
4
4
  import { Session, SessionEvent, SessionHeader, SessionId, SessionLogOffset } from "@deepseek-ai/dsh-session";
@@ -203,7 +203,7 @@ declare class SessionPersistenceRdb extends SessionPersistence {
203
203
  flush(): Promise<void>;
204
204
  stat(id: SessionId, options?: SessionPersistenceStatOptions): Promise<SessionPersistenceSnapshot | undefined>;
205
205
  list(options?: SessionPersistenceListOptions): Promise<readonly SessionPersistenceSnapshot[]>;
206
- /** 导出 artifact(jsonl v2 文本),视图只读不落库。 */
206
+ /** 导出当前世代的 jsonl artifact,视图只读不落库。 */
207
207
  readRaw(id: SessionId, signal?: AbortSignal): Promise<{
208
208
  meta: SessionHeader;
209
209
  inheritedEventCount: number;
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { o as SCHEMA_VERSION } from "./schema-Bo6Hy5gW.mjs";
2
- import { a as SessionBranchRdb, i as SessionPersistenceRdbInternals, n as ProjectionCacheOptions, o as SessionBranchRdbProvider, r as SessionPersistenceRdb, s as locateTurnEnd, t as Config } from "./index-BEKoV1Uy.mjs";
1
+ import { o as SCHEMA_VERSION } from "./schema-DPcuEh_a.mjs";
2
+ import { a as SessionBranchRdb, i as SessionPersistenceRdbInternals, n as ProjectionCacheOptions, o as SessionBranchRdbProvider, r as SessionPersistenceRdb, s as locateTurnEnd, t as Config } from "./index-CCcK9tia.mjs";
3
3
  export { Config, ProjectionCacheOptions, SCHEMA_VERSION, SessionBranchRdb, SessionBranchRdbProvider, SessionPersistenceRdb, SessionPersistenceRdb as default, SessionPersistenceRdbInternals, locateTurnEnd };
package/dist/index.mjs CHANGED
@@ -1,17 +1,19 @@
1
- import { S as WriteGuard, a as EVENT_ENCODING, b as postgresTableDefs, c as eventDimensions, i as DEFAULT_BUSY_TIMEOUT_MS, o as SCHEMA_VERSION, r as createStorageRepository, t as SqliteBackend, x as toPostgresSchema } from "./sqlite-BIPdMNQb.mjs";
1
+ import { S as WriteGuard, a as EVENT_ENCODING, b as postgresTableDefs, c as eventDimensions, i as DEFAULT_BUSY_TIMEOUT_MS, o as SCHEMA_VERSION, r as createStorageRepository, t as SqliteBackend, x as toPostgresSchema } from "./sqlite-DYExtbLo.mjs";
2
2
  import { _ as toJsonlArtifact, c as repairRequestHeaders, d as rowToMeta, f as scanRows, g as titleOfEventData, m as sessionInsertRow, p as sessionConflictRow, s as repairReadView } from "./log-DO69NQnn.mjs";
3
- import { c as SessionBranchRdbProvider, l as locateTurnEnd, o as registerSessionImport, s as SessionBranchRdb } from "./import-DZIAjOUr.mjs";
3
+ import { c as SessionBranchRdbProvider, l as locateTurnEnd, o as registerSessionImport, s as SessionBranchRdb } from "./import-Bc2QQa5G.mjs";
4
4
  import z from "@deepseek-ai/schemastery";
5
5
  import { randomUUID } from "node:crypto";
6
6
  import { Pool } from "pg";
7
7
  import { drizzle } from "drizzle-orm/node-postgres";
8
8
  import { SessionAlreadyExistsError, SessionAlreadyOwnedError, SessionHandleClosedError, SessionPersistence, SessionPersistenceNotFoundError, SessionPersistenceRevision, SessionReadOnlyError, assertContiguous, assertVersion, materializeAppendBatch, materializeCreateHeader, validateStoredEvents } from "@deepseek-ai/dsh-session-persistence";
9
9
  import { SESSION_FORMAT_VERSION, SessionLogOffset } from "@deepseek-ai/dsh-session";
10
+ import { sessionFormatLogFilename } from "@deepseek-ai/dsh-session-format";
10
11
  import { sessionFormatCatalog } from "@deepseek-ai/dsh-session-format-catalog";
11
12
  import { and, desc, eq, gte, sql } from "drizzle-orm";
12
13
  import { readdirSync } from "node:fs";
13
14
  import { fileURLToPath } from "node:url";
14
15
  import { migrate } from "drizzle-orm/node-postgres/migrator";
16
+ import { SessionQueryEngine, SessionQueryError } from "@deepseek-ai/dsh-session-query";
15
17
  import { StorageError, storageBackendServiceKey } from "@deepseek-ai/dsh-storage";
16
18
  import { Service } from "@deepseek-ai/cordis";
17
19
  //#region src/postgres.ts
@@ -49,7 +51,7 @@ var PostgresBackend = class PostgresBackend {
49
51
  } finally {
50
52
  this.txOverride = previous;
51
53
  }
52
- }),
54
+ }, { isolationLevel: "serializable" }),
53
55
  tables: this.tables
54
56
  });
55
57
  }
@@ -212,6 +214,22 @@ var PostgresBackend = class PostgresBackend {
212
214
  }
213
215
  };
214
216
  //#endregion
217
+ //#region src/session-query.ts
218
+ var SessionQueryRdb = class extends SessionQueryEngine {
219
+ constructor(ctx, config = {}) {
220
+ super(ctx, config);
221
+ }
222
+ async searchSessions() {
223
+ throw searchDisabled();
224
+ }
225
+ async searchEvents() {
226
+ throw searchDisabled();
227
+ }
228
+ };
229
+ function searchDisabled() {
230
+ return new SessionQueryError("session search is disabled: this deployment serves session queries from the rdb backend without a full-text index", "SESSION_QUERY_SEARCH_DISABLED");
231
+ }
232
+ //#endregion
215
233
  //#region src/legacy.ts
216
234
  /** 重建 v0/v1/v2 物理 header 记录(RDB 行 → 物理 JSON 对象)。 */
217
235
  function physicalHeader(row) {
@@ -319,36 +337,41 @@ const SESSION_PROJECTION_CACHE_SERVICE = "sessionProjectionCache";
319
337
  const PREDECESSOR_TITLE_KEY = "title";
320
338
  /** rdb 持久化的投影 checkpoint 服务:同步驱动直读介质,异步驱动用写穿镜像支撑同步签名。 */
321
339
  var SessionProjectionCacheRdb = class extends Service {
322
- config;
323
- repository;
324
- ready;
325
340
  static inject = ["sessionProjections", "sessions"];
326
341
  /** 异步驱动(PostgreSQL)的同步读镜像:同步驱动(SQLite)直读介质,这里恒为空。 */
327
342
  records = /* @__PURE__ */ new Map();
328
343
  dirty = /* @__PURE__ */ new Map();
329
344
  /** 读路径是否直读介质(`readProjcacheSync` 存在即同步驱动)。 */
330
345
  directReads;
346
+ config;
347
+ repository;
348
+ ready;
331
349
  /**
332
- * @param ctx - 插件上下文(须已注入 sessionProjections 与 sessions)。
333
- * @param config - 写节流参数。
334
- * @param repository - storages 接管表访问层。
335
- * @param ready - 介质就绪信号(直读介质前必须等到)。
350
+ * 本类按 cordis class plugin 装载(`ctx.plugin(SessionProjectionCacheRdb, options)`):
351
+ * `static inject` 等依赖就绪后构造,构造后框架调用 `[Service.init]` 安装写入
352
+ * 路径——直接 `new` 不会触发 init,写入路径会静默缺失。
353
+ * @param ctx - 插件上下文(已注入 sessionProjections 与 sessions)。
354
+ * @param options - 写节流 + storages 接管访问层 + 介质就绪信号。
336
355
  */
337
- constructor(ctx, config, repository, ready) {
356
+ constructor(ctx, options) {
338
357
  super(ctx, SESSION_PROJECTION_CACHE_SERVICE);
339
- this.config = config;
340
- this.repository = repository;
341
- this.ready = ready;
342
- this.directReads = repository.readProjcacheSync !== void 0;
358
+ this.config = options;
359
+ this.repository = options.repository;
360
+ this.ready = options.ready;
361
+ this.directReads = options.repository.readProjcacheSync !== void 0;
343
362
  }
344
363
  /**
345
- * Wait for the medium, then install the write path. Only the async driver
346
- * needs a startup mirror: the sync driver serves every read from the table.
364
+ * Install the write path before the async medium wait: listeners must exist
365
+ * from plugin activation on, or sessions created while the medium settles
366
+ * lose their mandatory checkpoints. Only the async driver needs the startup
367
+ * mirror; the sync driver serves every read from the table.
347
368
  */
348
369
  async [Service.init]() {
370
+ this.installWritePath();
349
371
  await this.ready;
372
+ const pruned = await this.repository.pruneStaleProjcache();
373
+ if (pruned > 0) this.ctx.logger.info(`session projection cache: pruned stale snapshot(s) for ${String(pruned)} session(s)`);
350
374
  if (!this.directReads) for (const entry of await this.repository.loadProjcache()) this.records.set(entry.sessionId, entry);
351
- this.installWritePath();
352
375
  }
353
376
  /** Read one session's stored record: straight from the medium, or from the async mirror. */
354
377
  lookup(id) {
@@ -601,8 +624,8 @@ const WORKSPACE_TABLE = "workspaces";
601
624
  var RdbStorageBackend = class {
602
625
  repository;
603
626
  kv = { open: (descriptor) => this.openUnit(descriptor) };
604
- /** 已打开(或打开中)的 unit 名;重复 open 是调用方 bug。 */
605
- open = /* @__PURE__ */ new Set();
627
+ /** 已打开(或打开中)的 unit;重复 open 是调用方 bug。 */
628
+ open = /* @__PURE__ */ new Map();
606
629
  closed = false;
607
630
  /**
608
631
  * @param repository - storages 接管表访问层(与事件日志同介质)。
@@ -614,35 +637,52 @@ var RdbStorageBackend = class {
614
637
  if (this.closed) throw new StorageError("closed", "rdb storage backend is closed");
615
638
  if (descriptor.name !== WORKSPACE_UNIT) throw new Error(`rdb storage backend serves only the '${WORKSPACE_UNIT}' domain (requested '${descriptor.name}')`);
616
639
  if (!descriptor.tables.includes(WORKSPACE_TABLE) || descriptor.hasGlobal !== true) throw new Error(`rdb storage backend expects the '${WORKSPACE_UNIT}' domain shape (table '${WORKSPACE_TABLE}' plus a global slot)`);
640
+ if (descriptor.layout !== void 0 && descriptor.layout !== "single") throw new Error(`rdb storage backend serves only the 'single' layout (domain '${descriptor.name}' declares '${descriptor.layout}')`);
617
641
  if (this.open.has(descriptor.name)) throw new Error(`kv unit '${descriptor.name}' is already open (double-open is a caller bug)`);
618
- const stored = await this.repository.readUnitVersion(descriptor.name);
619
- if (stored === void 0) await this.repository.insertUnitVersion(descriptor.name, descriptor.version);
620
- else if (stored !== descriptor.version) throw new StorageError("version-mismatch", `kv unit '${descriptor.name}' is stamped version ${stored} on the medium, incompatible with descriptor version ${descriptor.version}`);
621
- this.open.add(descriptor.name);
622
- return new WorkspaceKvUnit(this.repository, descriptor, () => {
642
+ const unit = new WorkspaceKvUnit(this.repository, descriptor);
643
+ this.open.set(descriptor.name, unit);
644
+ try {
645
+ const stored = await this.repository.readUnitVersion(descriptor.name);
646
+ if (stored === void 0) await this.repository.insertUnitVersion(descriptor.name, descriptor.version);
647
+ else if (stored !== descriptor.version) throw new StorageError("version-mismatch", `kv unit '${descriptor.name}' is stamped version ${stored} on the medium, incompatible with descriptor version ${descriptor.version}`);
648
+ } catch (error) {
649
+ this.open.delete(descriptor.name);
650
+ throw error;
651
+ }
652
+ unit.onClose(() => {
623
653
  this.open.delete(descriptor.name);
624
654
  });
655
+ return unit;
625
656
  }
626
657
  /**
627
- * Release the backend. The medium (the session database) belongs to the
628
- * owning session-rdb plugin, so closing open units here does not close it.
629
- * @returns resolution after the name table is cleared.
658
+ * Release the backend. New writes are rejected immediately; already-queued
659
+ * unit writes drain first (upstream backend contract). The medium (the
660
+ * session database) belongs to the owning session-rdb plugin, so closing
661
+ * open units here does not close it.
662
+ * @returns resolution after every open unit drained.
630
663
  */
631
664
  async close() {
632
665
  this.closed = true;
666
+ const units = [...this.open.values()];
633
667
  this.open.clear();
668
+ await Promise.all(units.map((unit) => unit.close()));
634
669
  }
635
670
  };
636
671
  /** workspace 域的 KV unit:每个原语一条 SQL 语句,值形状与上游记录一致。 */
637
672
  var WorkspaceKvUnit = class {
638
673
  repository;
639
674
  descriptor;
640
- onClose;
641
675
  closed = false;
642
- constructor(repository, descriptor, onClose) {
676
+ /** 在途写操作:close 先拒绝新写,再 drain 它们(不丢已受理的写)。 */
677
+ inflight = /* @__PURE__ */ new Set();
678
+ onClosed;
679
+ constructor(repository, descriptor) {
643
680
  this.repository = repository;
644
681
  this.descriptor = descriptor;
645
- this.onClose = onClose;
682
+ }
683
+ /** Install the name-release callback after the backend registered this unit. */
684
+ onClose(release) {
685
+ this.onClosed = release;
646
686
  }
647
687
  async loadAll() {
648
688
  this.assertOpen();
@@ -657,21 +697,32 @@ var WorkspaceKvUnit = class {
657
697
  async putRecord(table, key, value) {
658
698
  this.assertOpen();
659
699
  this.assertTable(table);
660
- await this.repository.putWorkspace(key, workspaceRecordOf(value));
700
+ await this.track(this.repository.putWorkspace(key, workspaceRecordOf(value)));
661
701
  }
662
702
  async deleteRecord(table, key) {
663
703
  this.assertOpen();
664
704
  this.assertTable(table);
665
- await this.repository.deleteWorkspace(key);
705
+ await this.track(this.repository.deleteWorkspace(key));
666
706
  }
667
707
  async setGlobal(value) {
668
708
  this.assertOpen();
669
- await this.repository.writeWorkspaceState(workspaceStateOf(value));
709
+ await this.track(this.repository.writeWorkspaceState(workspaceStateOf(value)));
670
710
  }
671
711
  async close() {
672
712
  if (this.closed) return;
673
713
  this.closed = true;
674
- this.onClose();
714
+ while (this.inflight.size > 0) await Promise.allSettled(this.inflight);
715
+ this.onClosed?.();
716
+ }
717
+ /** Register one accepted write so close can drain it. */
718
+ async track(operation) {
719
+ const settled = operation.then(() => void 0, () => void 0);
720
+ this.inflight.add(settled);
721
+ try {
722
+ await operation;
723
+ } finally {
724
+ this.inflight.delete(settled);
725
+ }
675
726
  }
676
727
  assertOpen() {
677
728
  if (this.closed) throw new StorageError("closed", `kv unit '${this.descriptor.name}' is closed`);
@@ -722,8 +773,10 @@ function installStorageTakeover(ctx, options) {
722
773
  }, "session-rdb.storageBackend");
723
774
  storageCtx.provide(storageBackendServiceKey("rdb"), backend);
724
775
  });
725
- ctx.inject(["sessionProjections"], (projectionCtx) => {
726
- new SessionProjectionCacheRdb(projectionCtx, options.projectionCache, options.repository, options.ready);
776
+ ctx.plugin(SessionProjectionCacheRdb, {
777
+ ...options.projectionCache,
778
+ repository: options.repository,
779
+ ready: options.ready
727
780
  });
728
781
  }
729
782
  //#endregion
@@ -1047,6 +1100,7 @@ var SessionPersistenceRdb = class SessionPersistenceRdb extends SessionPersisten
1047
1100
  this.ready = this.init();
1048
1101
  this.installLiveRouting(ctx);
1049
1102
  new SessionBranchRdb(this.ctx);
1103
+ this.ctx.plugin(SessionQueryRdb, {});
1050
1104
  registerSessionImport(this.ctx, this);
1051
1105
  installStorageTakeover(this.ctx, {
1052
1106
  repository: this.backend.storage,
@@ -1166,7 +1220,7 @@ var SessionPersistenceRdb = class SessionPersistenceRdb extends SessionPersisten
1166
1220
  }
1167
1221
  return snapshots;
1168
1222
  }
1169
- /** 导出 artifact(jsonl v2 文本),视图只读不落库。 */
1223
+ /** 导出当前世代的 jsonl artifact,视图只读不落库。 */
1170
1224
  async readRaw(id, signal) {
1171
1225
  signal?.throwIfAborted();
1172
1226
  await this.ready;
@@ -1178,7 +1232,7 @@ var SessionPersistenceRdb = class SessionPersistenceRdb extends SessionPersisten
1178
1232
  return {
1179
1233
  meta: log.meta,
1180
1234
  inheritedEventCount,
1181
- filename: "session.jsonl",
1235
+ filename: sessionFormatLogFilename(SESSION_FORMAT_VERSION),
1182
1236
  content: toJsonlArtifact(log.meta, inheritedEventCount, log.events)
1183
1237
  };
1184
1238
  }
@@ -1,4 +1,4 @@
1
- //#region ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.6.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
1
+ //#region ../../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.6.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
2
2
  var comma = ",".charCodeAt(0);
3
3
  var semicolon = ";".charCodeAt(0);
4
4
  var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -78,7 +78,7 @@ function encode(decoded) {
78
78
  return writer.flush();
79
79
  }
80
80
  //#endregion
81
- //#region ../../node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.mjs
81
+ //#region ../../../node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.mjs
82
82
  var BitSet = class BitSet {
83
83
  constructor(arg) {
84
84
  this.bits = arg instanceof BitSet ? arg.bits.slice() : [];