@morlay/session-rdb 0.0.21-alpha.7 → 0.0.21-alpha.9

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 (45) hide show
  1. package/README.md +31 -12
  2. package/dist/artifact.d.mts +2 -101
  3. package/dist/artifact.mjs +2 -2
  4. package/dist/{branch-BjUR6wfe.mjs → branch-D4nVzQQM.mjs} +3 -3
  5. package/dist/deletion.d.mts +1 -1
  6. package/dist/deletion.mjs +1 -1
  7. package/dist/{dist-vIVO6bA-.mjs → dist-DHer1cql.mjs} +14 -7
  8. package/dist/export.d.mts +8 -0
  9. package/dist/export.mjs +76 -0
  10. package/dist/gc.d.mts +8 -0
  11. package/dist/gc.mjs +51 -0
  12. package/dist/import.d.mts +1 -1
  13. package/dist/import.mjs +1 -1
  14. package/dist/index.d.mts +2 -2
  15. package/dist/index.mjs +3 -3
  16. package/dist/{log-qCNkDjh5.mjs → log-BWVFYAh5.mjs} +39 -12
  17. package/dist/{backend-E0bmTXpz.d.mts → log-CUjKQbOR.d.mts} +222 -39
  18. package/dist/{sqlite-zcXVyMxr.mjs → sqlite-SCiSnwaz.mjs} +321 -259
  19. package/dist/{src-B9X8BKyh.mjs → src-BZ1tffd5.mjs} +342 -310
  20. package/dist/storage.d.mts +20 -7
  21. package/dist/storage.mjs +2 -2
  22. package/dist/testing.d.mts +1 -1
  23. package/dist/testing.mjs +48 -29
  24. package/dist/usage.d.mts +2 -0
  25. package/dist/usage.mjs +152 -0
  26. package/drizzle/postgres/20260923120000_v3_usage_materialized/migration.sql +48 -0
  27. package/drizzle/sqlite/20260923120000_v3_usage_materialized/migration.sql +48 -0
  28. package/package.json +25 -30
  29. package/src/backend.ts +41 -17
  30. package/src/branch.ts +4 -4
  31. package/src/drizzle/postgres-v3.ts +2 -0
  32. package/src/drizzle/sqlite-v3.ts +2 -0
  33. package/src/entities/v3/event-usage.ts +8 -1
  34. package/src/entities/v3/index.ts +8 -0
  35. package/src/entities/v3/session-counts.ts +23 -0
  36. package/src/entities/v3/session-usage.ts +29 -0
  37. package/src/index.ts +230 -88
  38. package/src/log.ts +58 -17
  39. package/src/postgres.ts +248 -149
  40. package/src/rows.ts +2 -1
  41. package/src/schema.ts +4 -0
  42. package/src/sqlite.ts +263 -124
  43. package/src/storage-takeover/repository.ts +1 -4
  44. package/src/usage.ts +10 -6
  45. package/cordis.patch.yml +0 -13
@@ -5,6 +5,7 @@ import { BranchAnchorMode, BranchBoundary, ForkFromOptions, SessionBranch, Sessi
5
5
  import { KvUnit } from "@deepseek-ai/dsh-storage";
6
6
  import { Context, Service } from "@deepseek-ai/cordis";
7
7
  import { SessionId as SessionId$1 } from "@deepseek-ai/dsh-session/types";
8
+ import { Volatile } from "@deepseek-ai/cosmokit";
8
9
  //#region ../../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/json-schema.d.cts
9
10
  type _JSONSchema = boolean | JSONSchema;
10
11
  type SchemaType = "object" | "array" | "string" | "number" | "boolean" | "null" | "integer";
@@ -3285,16 +3286,15 @@ declare class WorkspaceRegistry extends Service {
3285
3286
  * Initialize the default Workspace only while both the registry and Session
3286
3287
  * history are empty. Repeated requests reuse its durable identity; deleting
3287
3288
  * that registration permanently disables automatic creation.
3288
- * @param resolveDirectory - resolve the absolute directory and initial title;
3289
- * called only for eligible creation, inside the registry mutation queue.
3290
- * Missing directories are created recursively before registration.
3289
+ * @param resolveDirectory - resolve the absolute directory; called only for
3290
+ * eligible creation, inside the registry mutation queue. Missing directories
3291
+ * are created recursively before registration, and the initial title is the
3292
+ * requested directory's own final segment — not the canonical one, so a
3293
+ * symlink at that path does not retitle the Workspace after its target.
3291
3294
  * After resolution, caller cancellation does not roll back creation or registration.
3292
3295
  * @returns the initialized Workspace, or undefined when automatic creation is ineligible.
3293
3296
  */
3294
- initializeDefault(resolveDirectory: () => Promise<{
3295
- path: string;
3296
- title: string;
3297
- }>): Promise<Workspace | undefined>;
3297
+ initializeDefault(resolveDirectory: () => Promise<string>): Promise<Workspace | undefined>;
3298
3298
  /**
3299
3299
  * Look up a workspace by id.
3300
3300
  * @param id - Workspace id.
@@ -3478,6 +3478,8 @@ declare const tWorkspaceSessions: any;
3478
3478
  declare const tWorkspaceState: any;
3479
3479
  declare const tSessionProjcacheRows: any;
3480
3480
  declare const tEventUsage: any;
3481
+ declare const tSessionUsage: any;
3482
+ declare const tSessionCounts: any;
3481
3483
  type JournalMode = "wal" | "delete" | "truncate" | "persist";
3482
3484
  declare const DEFAULT_BUSY_TIMEOUT_MS = 5000;
3483
3485
  type EventKind = "message" | "thinking" | "turn" | "tool" | "request" | "config" | "audit" | "lifecycle" | "inbox" | "compaction" | "llm" | "subagent" | "team" | "workflow" | "goal" | "schedule" | "todo" | "web";
@@ -3608,15 +3610,17 @@ interface ProjectionCacheOptions {
3608
3610
  type Config$1 = {
3609
3611
  type: "sqlite";
3610
3612
  path: string;
3611
- journalMode?: JournalMode;
3612
- busyTimeout?: number;
3613
- projectionCache?: ProjectionCacheOptions;
3613
+ journalMode?: JournalMode | undefined;
3614
+ busyTimeout?: number | undefined;
3615
+ projectionCache?: ProjectionCacheOptions | undefined;
3614
3616
  } | {
3615
3617
  type: "postgres";
3616
3618
  connectionString: string;
3617
- schema?: string;
3618
- projectionCache?: ProjectionCacheOptions;
3619
+ schema?: string | undefined;
3620
+ projectionCache?: ProjectionCacheOptions | undefined;
3619
3621
  };
3622
+ /** schema 解析之后的形状:整段 Config 是 **volatile 稳定引用**(页面可编辑),读它要过 `.get()`。 */
3623
+ type ResolvedConfig = Volatile<Config$1>;
3620
3624
  type SessionDeletionErrorCode = "SESSION_NOT_FOUND" | "SESSION_NOT_ARCHIVED" | "SESSION_LIVE";
3621
3625
  declare class SessionDeletionError extends Error {
3622
3626
  readonly code: SessionDeletionErrorCode;
@@ -3690,9 +3694,8 @@ declare class RdbSessionHandle implements SessionHandle {
3690
3694
  static readonly LIVE_WRITE_BATCH_MAX_DELAY_MS = 200;
3691
3695
  }
3692
3696
  declare class SessionPersistenceRdb extends SessionPersistence {
3693
- config: Config$1;
3694
3697
  static inject: string[];
3695
- static Config: z<Config$1>;
3698
+ static Config: z<Config$1, ResolvedConfig>;
3696
3699
  readonly name = "session-rdb";
3697
3700
  readonly tracker: RdbBackendTracker;
3698
3701
  private readonly backend;
@@ -3702,7 +3705,9 @@ declare class SessionPersistenceRdb extends SessionPersistence {
3702
3705
  private readonly reuseEventIds;
3703
3706
  private readonly liveBuffers;
3704
3707
  private readonly liveReady;
3705
- constructor(ctx: Context, config: Config$1, injectedBackend?: Backend);
3708
+ /** 本次装配用的配置快照(整段 Config 是 volatile,重挂会给新的)。 */
3709
+ readonly config: Config$1;
3710
+ constructor(ctx: Context, config: ResolvedConfig, injectedBackend?: Backend);
3706
3711
  private init;
3707
3712
  create(header: SessionHeader, options?: SessionPersistenceCreateOptions): Promise<SessionHandle>;
3708
3713
  open(id: SessionId, access: SessionAccess, options?: SessionPersistenceOpenOptions): Promise<SessionHandle>;
@@ -3740,14 +3745,18 @@ declare class SessionPersistenceRdb extends SessionPersistence {
3740
3745
  migrated: boolean;
3741
3746
  } | undefined>;
3742
3747
  /**
3743
- * 活动计数**旁路累加**:不在写事务里、失败只 warn——`t_event_counts` 是可销毁重建的派生表,
3744
- * 丢几次累加不影响可用性(需要时用 `rebuildEventCounts` 重算)。
3748
+ * 统计衍生表的**旁路累加**:不在写事务里、失败只 warn——两张会话汇总表都是可销毁重建的
3749
+ * 派生表,丢几次累加不影响可用性(需要时用 `rebuildSessionStats` 重算)。
3750
+ * token 走写路径已折好的用量行,活动计数走本批事件类型。
3751
+ */
3752
+ private recordSessionStats;
3753
+ /**
3754
+ * 重算一个会话的统计(rewind / fork 之后;best-effort,同 `recordSessionStats`):
3755
+ * 两张汇总表按会话重算,用量行的引用标记全量重算(引用可能跨会话消失)。
3745
3756
  */
3746
- private recordEventCounts;
3747
- /** 重算一个会话的活动计数(rewind / fork 之后;best-effort,同 `recordEventCounts`)。 */
3748
- rebuildEventCounts(id: SessionId): Promise<void>;
3749
- /** 会话删除时清掉它的活动计数行(best-effort)。 */
3750
- private deleteEventCounts;
3757
+ rebuildSessionStats(id: SessionId): Promise<void>;
3758
+ /** 会话删除时清掉它的汇总行,并重算用量行的引用标记(被删会话引用的行要立刻退出统计)。 */
3759
+ private dropSessionStats;
3751
3760
  private rewriteMigratedLog;
3752
3761
  listSnapshots(signal?: AbortSignal): Promise<Array<SessionPersistenceSnapshot & {
3753
3762
  inheritedEventCount: number;
@@ -3775,6 +3784,21 @@ declare class SessionPersistenceRdb extends SessionPersistence {
3775
3784
  }
3776
3785
  //#endregion
3777
3786
  //#region src/usage.d.ts
3787
+ declare const SESSION_USAGE_PATH = "/api/session.usage";
3788
+ /**
3789
+ * 时间范围的语义键:`all` 不限;`day` / `week` 是**本地自然日 / 自然周**(周一起算);
3790
+ * `7d` / `30d` / `90d` 是**最近 N 个自然日**(含今天)。
3791
+ */
3792
+ type UsageRangeKey = "all" | "day" | "week" | "7d" | "30d" | "90d";
3793
+ /**
3794
+ * 范围起点(含),不限时为 undefined。**所有起点都对齐到 host 本地时区的零点**——`day` / `week` 是
3795
+ * 今天 / 本周一的零点,`7d` / `30d` / `90d` 是「今天零点往前 N-1 天」(含今天共 N 个自然日)。
3796
+ * 对齐的意义:事件级表按毫秒过滤、会话汇总表按本地日过滤,两者因此严格等价。
3797
+ * @param range - 语义键。
3798
+ * @param now - 当前时刻。
3799
+ * @returns 起点毫秒时间戳,或 undefined。
3800
+ */
3801
+ declare function resolveUsageSince(range: UsageRangeKey, now: number): number | undefined;
3778
3802
  /** 一段 token 用量(字段直接取事件里模型报的 usage)。 */
3779
3803
  interface UsageTokenTotals {
3780
3804
  inputTokens: number;
@@ -3820,6 +3844,24 @@ interface UsageAggregate {
3820
3844
  buckets: UsageBucket[];
3821
3845
  sessions: UsageSessionRow[];
3822
3846
  }
3847
+ /** 一次统计请求的完整回报。 */
3848
+ type SessionUsageReport = UsageAggregate;
3849
+ /** 计入活动计数的事件类型(轮次 / 步骤 / 用户输入 / 工具调用)。 */
3850
+ declare const COUNTED_EVENT_TYPES: readonly ["turn/start", "step/start", "user/message", "tool/call"];
3851
+ /** 按事件类型把计数累加到活动指标上(表里按类型存,读的时候折成四项)。 */
3852
+ declare function addActivityCount(target: UsageActivityTotals, type: string, count: number): UsageActivityTotals;
3853
+ /** 毫秒时间戳 → host 本地日(`YYYY-MM-DD`,与 SQL 的 localtime 口径一致)。 */
3854
+ declare function localDayKey(ms: number): string;
3855
+ declare function emptyTotals(): UsageTotals;
3856
+ declare function addTokenTotals(target: UsageTokenTotals, row: UsageTokenTotals): UsageTokenTotals;
3857
+ declare function addActivityTotals(target: UsageActivityTotals, row: UsageActivityTotals): UsageActivityTotals;
3858
+ /** 把一行的整套指标累加进目标(后端合并「是否子代理」两组时用)。 */
3859
+ declare function addTotals(target: UsageTotals, row: UsageTotals): UsageTotals;
3860
+ /**
3861
+ * 用量统计通道:一次请求回报总览(含 subagent 拆分)、按天 × 模型的桶与按会话的行。
3862
+ * 聚合只算被会话引用的事件行——fork 共享行因此只计一次,已删会话留下的孤儿行不计。
3863
+ */
3864
+ declare function registerSessionUsage(ctx: Context, persistence: SessionPersistenceRdb): void;
3823
3865
  //#endregion
3824
3866
  //#region src/backend.d.ts
3825
3867
  interface SessionRow {
@@ -3870,7 +3912,11 @@ interface BackendTx {
3870
3912
  getSeedLength(id: SessionId): Promise<number | null>;
3871
3913
  updateSeedLength(id: SessionId, seedLength: number): Promise<void>;
3872
3914
  refreshTitle(id: SessionId): Promise<void>;
3873
- insertEvents(events: EventInsert[]): Promise<void>;
3915
+ /**
3916
+ * 插入事件行与它们的用量行(`usageRows` 由写路径一次折好,读侧维度已物化在行上)。
3917
+ * 这一批事件与桥接行同事务,提交即「被引用」。
3918
+ */
3919
+ insertEvents(events: EventInsert[], usageRows: readonly EventUsageRow[]): Promise<void>;
3874
3920
  insertBridges(rows: Array<{
3875
3921
  fSessionId: SessionId;
3876
3922
  fEventId: string;
@@ -3922,11 +3968,15 @@ interface SessionListRowsPage {
3922
3968
  /** 过滤后的总数(分页前的),前端据此算页数。 */
3923
3969
  total: number;
3924
3970
  }
3925
- /** 活动计数的一个桶:本地日 + 事件类型 + 计数。 */
3926
- interface EventCountBucket {
3971
+ /** 活动计数的一个桶:本地日 + 四项计数(轮次 / 步骤 / 用户输入 / 工具调用)。 */
3972
+ interface SessionCountBucket extends UsageActivityTotals {
3927
3973
  day: string;
3928
- type: string;
3929
- count: number;
3974
+ }
3975
+ /** 用量累加的一个桶:本地日 + 模型归属 + 五个 token 列。 */
3976
+ interface SessionUsageBucket extends UsageTokenTotals {
3977
+ day: string;
3978
+ provider: string | null;
3979
+ model: string | null;
3930
3980
  }
3931
3981
  interface Backend {
3932
3982
  readonly kind: "sqlite" | "postgres";
@@ -3944,30 +3994,163 @@ interface Backend {
3944
3994
  /** 父会话已不存在(或没有父)的 subagent 会话:父被删后它们成了孤儿。 */
3945
3995
  listOrphanSubagentSessions(): Promise<SessionId[]>;
3946
3996
  /**
3947
- * 用量统计的原始聚合:token 用量读 `t_event_usage`、活动计数读派生表 `t_event_counts`,
3948
- * 加按天×模型的桶与按会话的行(事件行去重、排除孤儿)。
3949
- * @param sinceMs - 只算该时刻(含)之后的事件行;省略即全量。
3997
+ * 用量统计的原始聚合:读三张派生统计表(`t_event_usage` + 两张会话汇总表),
3998
+ * 给出总量 / subagent 拆分、按天×模型的桶与按会话的行(事件行去重、排除孤儿)。
3999
+ * @param sinceMs - 只算该时刻(含)之后的用量;省略即全量。会话汇总表按本地日过滤,
4000
+ * 与毫秒过滤等价的前提是调用方把起点对齐到本地零点(见 `resolveUsageSince`)。
3950
4001
  */
3951
4002
  usageReport(sinceMs?: number): Promise<UsageAggregate>;
3952
4003
  /** 管理面的会话行列表:完整语料(含归档)+ 标题 + 最后活动时间,按活动倒序分页。 */
3953
4004
  listSessionRows(query?: SessionListRowsQuery): Promise<SessionListRowsPage>;
3954
4005
  /**
3955
- * 活动计数**旁路累加**(派生表 `t_event_counts`,不参与写事务、失败可丢——表可销毁重建):
3956
- * 每个 (会话, 本地日, 事件类型) 记一行计数。
4006
+ * token 用量**旁路累加**(派生表 `t_session_usage`,不参与写事务、失败可丢——表可销毁重建):
4007
+ * 每个 (会话, 本地日, 模型) 记一行累加。
3957
4008
  * @param id - 会话 id。
3958
- * @param buckets - 本批要累加的 (day, type, count)。
4009
+ * @param buckets - 本批要累加的 (day, provider, model, tokens)。
3959
4010
  */
3960
- incrementEventCounts(id: SessionId, buckets: readonly EventCountBucket[]): Promise<void>;
4011
+ incrementSessionUsage(id: SessionId, buckets: readonly SessionUsageBucket[]): Promise<void>;
3961
4012
  /**
3962
- * 按会话从事件表重算活动计数(rewind / fork 之后调用):先删该会话的行再重算。
4013
+ * 活动计数**旁路累加**(派生表 `t_session_counts`,同上):每个 (会话, 本地日) 累加四项计数。
3963
4014
  * @param id - 会话 id。
4015
+ * @param buckets - 本批要累加的 (day, turns, steps, userInputs, toolCalls)。
3964
4016
  */
3965
- rebuildEventCounts(id: SessionId): Promise<void>;
3966
- /** 删掉一个会话的活动计数行(会话删除时)。 */
3967
- deleteEventCounts(id: SessionId): Promise<void>;
4017
+ incrementSessionCounts(id: SessionId, buckets: readonly SessionCountBucket[]): Promise<void>;
4018
+ /**
4019
+ * 按会话从事件表重算两张会话汇总表(rewind / fork 之后调用):先删该会话的行再重算。
4020
+ * @param id - 会话 id。
4021
+ */
4022
+ rebuildSessionStats(id: SessionId): Promise<void>;
4023
+ /**
4024
+ * 全量重算 `t_event_usage` 的引用标记(`f_referenced` / `f_subagent`):rewind / fork / 会话删除之后调用。
4025
+ * 引用可能跨会话消失(截断、删除),只按本会话判定不够,故这里是全量。
4026
+ */
4027
+ refreshEventUsageFlags(): Promise<void>;
4028
+ /** 删掉一个会话的汇总行(会话删除时;外键 CASCADE 之外再显式清一次)。 */
4029
+ deleteSessionStats(id: SessionId): Promise<void>;
3968
4030
  /** 回收空间与统计(含 VACUUM);不得在事务内执行。 */
3969
4031
  vacuum(): Promise<void>;
3970
4032
  close(): Promise<void>;
3971
4033
  }
3972
4034
  //#endregion
3973
- export { eventKind as A, tWorkspaceState as B, EVENT_ENCODING as C, SCHEMA_VERSION as D, JournalMode as E, tSessionEvents as F, WriteGuard as H, tSessionProjcacheRows as I, tSessions as L, tEvents as M, tPersistenceState as N, SESSION_PERSISTENCE_SQLITE_APPLICATION_ID as O, tSchemaMeta as P, tStorageUnits as R, DEFAULT_BUSY_TIMEOUT_MS as S, EventRole as T, StorageRepository as U, tWorkspaces as V, locateTurnEnd as _, SessionListRowsPage as a, SessionRowsItem as b, UsageAggregate as c, SessionDeletionError as d, SessionDeletionErrorCode as f, SessionBranchRdbProvider as g, SessionBranchRdb as h, EventRow as i, tEventUsage as j, eventDimensions as k, Config$1 as l, SessionPersistenceRdbInternals as m, BackendTx as n, SessionListRowsQuery as o, SessionPersistenceRdb as p, EventCountBucket as r, SessionRow as s, Backend as t, ProjectionCacheOptions as u, truncateLiveSession as v, EventKind as w, SessionRowsValue as x, SESSION_ROWS_PATH as y, tWorkspaceSessions as z };
4035
+ //#region src/log.d.ts
4036
+ declare function rowToMeta(row: SessionRow): SessionHeader;
4037
+ declare function sessionInsertRow(storage: SessionStorageMetadata, incarnation: string): {
4038
+ fSessionId: string;
4039
+ fHeadEventId: string;
4040
+ fHeadSequence: number;
4041
+ fVersion: number;
4042
+ fCreatedAt: number;
4043
+ fCwd: string | null;
4044
+ fParentSession: string | null;
4045
+ fSeedLength: number | null;
4046
+ fOrigin: string | null;
4047
+ fDelegationDepth: number | null;
4048
+ fAgentPreset: string | null;
4049
+ fIncarnation: string;
4050
+ fRevision: number;
4051
+ };
4052
+ declare function sessionConflictRow(storage: SessionStorageMetadata): {
4053
+ fVersion: number;
4054
+ fCreatedAt: number;
4055
+ fCwd: string | null;
4056
+ fParentSession: string | null;
4057
+ fSeedLength: number | null;
4058
+ fOrigin: string | null;
4059
+ fDelegationDepth: number | null;
4060
+ fAgentPreset: string | null;
4061
+ };
4062
+ declare function rowToEvent(row: EventRow): SessionEvent;
4063
+ declare function recomputeReplaceProvenance(events: SessionEvent[]): void;
4064
+ declare function findSurfaceRepairs(events: readonly SessionEvent[]): {
4065
+ degradeToAppend: Set<number>;
4066
+ addAppendMarker: Set<number>;
4067
+ clearSurfaceOp: Set<number>;
4068
+ clampEnd: Map<number, number>;
4069
+ };
4070
+ declare function repairSurfaceOps(events: SessionEvent[]): void;
4071
+ declare function repairAssistantSettlement(events: SessionEvent[]): void;
4072
+ declare function repairRequestHeaders(events: SessionEvent[]): void;
4073
+ declare function syncMeteringRanges(events: SessionEvent[]): void;
4074
+ declare function renameLegacyPtcEvents(events: SessionEvent[]): void;
4075
+ /**
4076
+ * 把**旧代(v3 及更早)的消息形状**归一到当前格式(v4):迁移链(严格)拒绝那些形状时,读路径仍要
4077
+ * 能把它们读出来——只动字段与标记,不改坐标、不改内容。
4078
+ *
4079
+ * 三件事:
4080
+ * - `system/message` 的 source:`{ kind: 'plugin', plugin: '@deepseek-ai/dsh-system-prompt' }` → `{ kind: 'system-prompt' }`
4081
+ * (v4 起 system 消息只认这个 kind);
4082
+ * - `tool/result` 的消息:v3 是 user 角色、结果块包在 `content[0]`;v4 是 `role: 'tool'` + 顶层
4083
+ * `toolCallId` + `content` 就是结果块;
4084
+ * - **本仓库自造、上游不认识的事件类型**(见 `OWN_EVENT_TYPES`:历史遗留的与我们当前在写的)标
4085
+ * `ignorable: true`——v4 的校验对未知类型只接受可忽略信封。
4086
+ *
4087
+ * 只认这张白名单:**其它未知类型保持 fail loud**(那是「数据来自更新的 harness」的信号,不能吞掉)。
4088
+ */
4089
+ declare function normalizeToCurrentShape(events: SessionEvent[]): void;
4090
+ /**
4091
+ * 落库前给**本仓库自造的事件类型**补上 `ignorable: true` 信封。
4092
+ *
4093
+ * 上游的持久化校验(`validateStoredEvents`)只放行「已知类型」或「带可忽略信封的未知类型」,我们的类型
4094
+ * 按构造就在已知表之外——不补的话连**写入**都会被拒(`appendBatch` 里那道校验)。上游 `Session.append`
4095
+ * 没有承载这个信封的口子(第三个参数只服务 surface 事件),所以这一笔由持久化层补:canonical log 里的
4096
+ * 形状不变,落库的那一份带上信封。
4097
+ * @param events - 即将落库的批次(`materializeAppendBatch` 的 JSON 快照副本,可写)。
4098
+ */
4099
+ declare function sealOwnEvents(events: readonly SessionEvent[]): void;
4100
+ /**
4101
+ * 本仓库自造、上游不认识的事件类型:读的时候标 `ignorable: true`,v4 的持久化校验才肯跳过它们
4102
+ * (`validateStoredEvents` 只放行「已知类型」或「带可忽略信封的未知类型」)。
4103
+ *
4104
+ * 两类都在这张表里:
4105
+ * - **历史遗留**:写过、后来连同机制一起删除的(`session-branch/version`);
4106
+ * - **当前在写**:本仓库的插件自己声明的事件类型(`session-mode/selected`)——上游的
4107
+ * `KNOWN_SESSION_EVENT_TYPES` 由上游仓库的声明生成,外部插件的事件按构造就在它之外。
4108
+ *
4109
+ * 新增自造事件类型时**必须**登记到这里,否则读路径 fail loud(真回归:`session-mode/selected` 漏登记,
4110
+ * 会话打不开)。**不要**用「所有未知类型」代替(那会掩盖更新版本的未知事件——那种必须拒读)。
4111
+ */
4112
+ declare const OWN_EVENT_TYPES: ReadonlySet<string>;
4113
+ /** 这批事件是否需要按当前形状归一(旧代消息形状,或尚未标 `ignorable` 的自造事件类型)——写路径曾把回退
4114
+ * 视图的结果以当前版本号落库,所以**版本号不可信**,读之前要按内容判一次。 */
4115
+ declare function needsShapeAdoption(events: readonly SessionEvent[]): boolean;
4116
+ declare function repairReadView(events: SessionEvent[]): void;
4117
+ declare function orphanInboxSpliceSeqs(events: readonly SessionEvent[]): Set<number>;
4118
+ declare function repairOrphanInboxSplices(events: SessionEvent[]): void;
4119
+ declare function scanRows(rows: readonly EventRow[], base?: number): {
4120
+ preserved: SessionEvent[];
4121
+ tornFrom?: number;
4122
+ };
4123
+ declare function toJsonlArtifact(meta: SessionHeader, inheritedEventCount: number, events: readonly SessionEvent[]): string;
4124
+ declare function titleOfEventData(data: string): string | undefined;
4125
+ /** 用量行的列(`t_event_usage`):读侧维度(本地日与两个归属标记)在写入时一起物化。 */
4126
+ interface EventUsageRow {
4127
+ fEventId: string;
4128
+ fCreatedAt: number;
4129
+ fDay: string;
4130
+ fProvider: string | null;
4131
+ fModel: string | null;
4132
+ fReferenced: number;
4133
+ fSubagent: number;
4134
+ fInputTokens: number;
4135
+ fOutputTokens: number;
4136
+ fCacheReadTokens: number;
4137
+ fReasoningTokens: number;
4138
+ fTotalTokens: number;
4139
+ }
4140
+ /**
4141
+ * 一条事件行的用量(只有带 `usage` 的 `assistant/message` 才有):写路径据此记录
4142
+ * `t_event_usage`,统计因此不必逐行解析 JSON。两种 `f_data` 结构(带信封 / 老格式)都认。
4143
+ * 读侧维度一起物化:本地日由事件时间算,`f_referenced` 直接 1(这一批事件行与桥接行同事务,
4144
+ * 提交即被引用),`f_subagent` 取写入它的会话是否子代理。
4145
+ * @param event - 待写入的事件行。
4146
+ * @param subagent - 写入它的会话是否 `origin === 'subagent'`。
4147
+ * @returns 用量行,或该事件没有用量时的 undefined。
4148
+ */
4149
+ declare function usageRowOf(event: {
4150
+ fEventId: string;
4151
+ fCreatedAt: number;
4152
+ fType: string;
4153
+ fData: string;
4154
+ }, subagent: boolean): EventUsageRow | undefined;
4155
+ //#endregion
4156
+ export { SessionDeletionError as $, SessionRow as A, tWorkspaceState as At, UsageTokenTotals as B, usageRowOf as C, tSessionCounts as Ct, SessionCountBucket as D, tSessions as Dt, EventRow as E, tSessionUsage as Et, UsageActivityTotals as F, addTotals as G, addActivityCount as H, UsageAggregate as I, registerSessionUsage as J, emptyTotals as K, UsageBucket as L, COUNTED_EVENT_TYPES as M, WriteGuard as Mt, SESSION_USAGE_PATH as N, StorageRepository as Nt, SessionListRowsPage as O, tStorageUnits as Ot, SessionUsageReport as P, ResolvedConfig as Q, UsageRangeKey as R, toJsonlArtifact as S, tSchemaMeta as St, BackendTx as T, tSessionProjcacheRows as Tt, addActivityTotals as U, UsageTotals as V, addTokenTotals as W, Config$1 as X, resolveUsageSince as Y, ProjectionCacheOptions as Z, sealOwnEvents as _, eventDimensions as _t, normalizeToCurrentShape as a, locateTurnEnd as at, syncMeteringRanges as b, tEvents as bt, renameLegacyPtcEvents as c, SessionRowsItem as ct, repairReadView as d, EVENT_ENCODING as dt, SessionDeletionErrorCode as et, repairRequestHeaders as f, EventKind as ft, scanRows as g, SESSION_PERSISTENCE_SQLITE_APPLICATION_ID as gt, rowToMeta as h, SCHEMA_VERSION as ht, needsShapeAdoption as i, SessionBranchRdbProvider as it, SessionUsageBucket as j, tWorkspaces as jt, SessionListRowsQuery as k, tWorkspaceSessions as kt, repairAssistantSettlement as l, SessionRowsValue as lt, rowToEvent as m, JournalMode as mt, OWN_EVENT_TYPES as n, SessionPersistenceRdbInternals as nt, orphanInboxSpliceSeqs as o, truncateLiveSession as ot, repairSurfaceOps as p, EventRole as pt, localDayKey as q, findSurfaceRepairs as r, SessionBranchRdb as rt, recomputeReplaceProvenance as s, SESSION_ROWS_PATH as st, EventUsageRow as t, SessionPersistenceRdb as tt, repairOrphanInboxSplices as u, DEFAULT_BUSY_TIMEOUT_MS as ut, sessionConflictRow as v, eventKind as vt, Backend as w, tSessionEvents as wt, titleOfEventData as x, tPersistenceState as xt, sessionInsertRow as y, tEventUsage as yt, UsageSessionRow as z };