@morlay/session-rdb 0.0.20 → 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.
- package/README.md +59 -31
- package/dist/artifact.d.mts +25 -65
- package/dist/artifact.mjs +2 -2
- package/dist/{schema-BkQN5GyT.d.mts → backend-DpdtxYpz.d.mts} +346 -93
- package/dist/{branch-Co6xlbi0.mjs → branch-5JzX9rUq.mjs} +163 -52
- package/dist/deletion.d.mts +7 -0
- package/dist/deletion.mjs +2 -0
- package/dist/dist-vIVO6bA-.mjs +1524 -0
- package/dist/import.d.mts +4 -4
- package/dist/import.mjs +28 -11
- package/dist/index.d.mts +2 -3
- package/dist/index.mjs +4 -1631
- package/dist/{log-DO69NQnn.mjs → log-CnYct2Dv.mjs} +37 -82
- package/dist/{sqlite-DYExtbLo.mjs → sqlite-fpvm5Dzs.mjs} +205 -75
- package/dist/src-CWTWV7vx.mjs +1904 -0
- package/dist/storage.d.mts +14 -5
- package/dist/storage.mjs +2 -2
- package/dist/testing.d.mts +1 -26
- package/dist/testing.mjs +10503 -9614
- package/drizzle/postgres/20260918120000_v3_event_usage/migration.sql +14 -0
- package/drizzle/postgres/20260918120000_v3_event_usage/snapshot.json +1309 -0
- package/drizzle/sqlite/20260918120000_v3_event_usage/migration.sql +14 -0
- package/drizzle/sqlite/20260918120000_v3_event_usage/snapshot.json +1031 -0
- package/package.json +28 -29
- package/src/adapters/to-postgres.ts +1 -3
- package/src/adapters/to-sqlite.ts +0 -2
- package/src/adapters/types.ts +0 -3
- package/src/artifact.ts +0 -2
- package/src/backend.ts +31 -2
- package/src/branch.ts +223 -135
- package/src/deletion.ts +87 -0
- package/src/drizzle/postgres-v2.ts +0 -1
- package/src/drizzle/postgres-v3.ts +0 -1
- package/src/drizzle/sqlite-v2.ts +0 -1
- package/src/drizzle/sqlite-v3.ts +0 -1
- package/src/entities/v2/session-events.ts +0 -1
- package/src/entities/v3/event-usage.ts +25 -0
- package/src/entities/v3/events.ts +1 -3
- package/src/entities/v3/index.ts +4 -0
- package/src/entities/v3/session-events.ts +1 -2
- package/src/entities/v3/session-projcache-rows.ts +0 -8
- package/src/entities/v3/sessions.ts +3 -3
- package/src/entities/v3/storage-units.ts +0 -1
- package/src/entities/v3/workspace-sessions.ts +0 -5
- package/src/entities/v3/workspace-state.ts +0 -6
- package/src/entities/v3/workspaces.ts +0 -5
- package/src/export.ts +103 -0
- package/src/gc.ts +76 -0
- package/src/import-storages.ts +4 -37
- package/src/import.ts +54 -31
- package/src/index.ts +150 -114
- package/src/legacy.ts +4 -42
- package/src/log.ts +63 -106
- package/src/postgres.ts +249 -22
- package/src/schema.ts +6 -6
- package/src/session-query.ts +0 -4
- package/src/sqlite.ts +231 -55
- package/src/storage-takeover/index.ts +2 -28
- package/src/storage-takeover/projection-cache.ts +30 -134
- package/src/storage-takeover/repository.ts +20 -59
- package/src/storage-takeover/storage-backend.ts +3 -33
- package/src/storage-takeover/types.ts +14 -56
- package/src/storage.ts +0 -2
- package/src/testing/contract.ts +19 -50
- package/src/testing/coordinator-contract.ts +10 -25
- package/src/testing.ts +1 -4
- package/src/usage.ts +191 -0
- package/dist/index-D55G9n4k.d.mts +0 -271
- package/dist/magic-string.es-BgJoa-3K.mjs +0 -1017
|
@@ -1,6 +1,7 @@
|
|
|
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";
|
|
@@ -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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
2897
|
+
config: Config$2;
|
|
2897
2898
|
static inject: string[];
|
|
2898
|
-
static Config: z<Config$
|
|
2899
|
+
static Config: z<Config$2>;
|
|
2899
2900
|
private table?;
|
|
2900
2901
|
private readonly dirty;
|
|
2901
|
-
constructor(ctx: Context, config: Config$
|
|
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
|
-
|
|
3322
|
-
|
|
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
|
-
|
|
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 };
|