@morlay/session-rdb 0.0.21-alpha.2 → 0.0.21-alpha.4

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 { g as titleOfEventData, m as sessionInsertRow, p as sessionConflictRow, v as usageRowOf } from "./log-CnYct2Dv.mjs";
1
+ import { g as titleOfEventData, m as sessionInsertRow, p as sessionConflictRow, v as usageRowOf } from "./log-C-rbdFwK.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { SESSION_FORMAT_VERSION, SessionId, SessionLogOffset, SessionSeq } from "@deepseek-ai/dsh-session";
4
4
  import { and, desc, eq, gte, inArray, isNotNull, lt, notInArray, sql } from "drizzle-orm";
@@ -461,7 +461,7 @@ const eventUsage = {
461
461
  }
462
462
  },
463
463
  f_created_at: {
464
- type: "integer",
464
+ type: "bigint",
465
465
  notNull: true
466
466
  },
467
467
  f_provider: { type: "text" },
@@ -691,6 +691,152 @@ function eventDimensions(event) {
691
691
  }
692
692
  }
693
693
  //#endregion
694
+ //#region src/usage.ts
695
+ const SESSION_USAGE_PATH = "/api/session.usage";
696
+ const DAY_MS = 864e5;
697
+ const ROLLING_DAYS = {
698
+ "7d": 7,
699
+ "30d": 30,
700
+ "90d": 90
701
+ };
702
+ function localDayStart(now) {
703
+ const start = new Date(now);
704
+ start.setHours(0, 0, 0, 0);
705
+ return start;
706
+ }
707
+ /**
708
+ * 范围起点(含),不限时为 undefined。自然日 / 自然周按 host 的本地时区算,周边界是周一 00:00。
709
+ * @param range - 语义键。
710
+ * @param now - 当前时刻。
711
+ * @returns 起点毫秒时间戳,或 undefined。
712
+ */
713
+ function resolveUsageSince(range, now) {
714
+ switch (range) {
715
+ case "all": return;
716
+ case "day": return localDayStart(now).getTime();
717
+ case "week": {
718
+ const start = localDayStart(now);
719
+ start.setDate(start.getDate() - (start.getDay() + 6) % 7);
720
+ return start.getTime();
721
+ }
722
+ default: return now - ROLLING_DAYS[range] * DAY_MS;
723
+ }
724
+ }
725
+ function parseUsageRange(value) {
726
+ return value === "day" || value === "week" || value === "7d" || value === "30d" || value === "90d" ? value : "all";
727
+ }
728
+ /** 计入活动计数的事件类型(轮次 / 步骤 / 用户输入 / 工具调用)。 */
729
+ const COUNTED_EVENT_TYPES = [
730
+ "turn/start",
731
+ "step/start",
732
+ "user/message",
733
+ "tool/call"
734
+ ];
735
+ /** 按事件类型把计数累加到活动指标上(表里按类型存,读的时候折成四项)。 */
736
+ function addActivityCount(target, type, count) {
737
+ switch (type) {
738
+ case "turn/start":
739
+ target.turns += count;
740
+ return target;
741
+ case "step/start":
742
+ target.steps += count;
743
+ return target;
744
+ case "user/message":
745
+ target.userInputs += count;
746
+ return target;
747
+ case "tool/call":
748
+ target.toolCalls += count;
749
+ return target;
750
+ default: return target;
751
+ }
752
+ }
753
+ /** 毫秒时间戳 → host 本地日(`YYYY-MM-DD`,与 SQL 的 localtime 口径一致)。 */
754
+ function localDayKey(ms) {
755
+ const date = new Date(ms);
756
+ const pad = (value) => String(value).padStart(2, "0");
757
+ return `${String(date.getFullYear())}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
758
+ }
759
+ function emptyTotals() {
760
+ return {
761
+ turns: 0,
762
+ steps: 0,
763
+ userInputs: 0,
764
+ toolCalls: 0,
765
+ inputTokens: 0,
766
+ outputTokens: 0,
767
+ cacheReadTokens: 0,
768
+ reasoningTokens: 0,
769
+ totalTokens: 0
770
+ };
771
+ }
772
+ function addTokenTotals(target, row) {
773
+ target.inputTokens += row.inputTokens;
774
+ target.outputTokens += row.outputTokens;
775
+ target.cacheReadTokens += row.cacheReadTokens;
776
+ target.reasoningTokens += row.reasoningTokens;
777
+ target.totalTokens += row.totalTokens;
778
+ return target;
779
+ }
780
+ function addActivityTotals(target, row) {
781
+ target.turns += row.turns;
782
+ target.steps += row.steps;
783
+ target.userInputs += row.userInputs;
784
+ target.toolCalls += row.toolCalls;
785
+ return target;
786
+ }
787
+ /** 把一行的整套指标累加进目标(后端合并「是否子代理」两组时用)。 */
788
+ function addTotals(target, row) {
789
+ addActivityTotals(target, row);
790
+ addTokenTotals(target, row);
791
+ return target;
792
+ }
793
+ /**
794
+ * 用量统计通道:一次请求回报总览(含 subagent 拆分)、按天 × 模型的桶与按会话的行。
795
+ * 聚合只算被会话引用的事件行——fork 共享行因此只计一次,已删会话留下的孤儿行不计。
796
+ */
797
+ function registerSessionUsage(ctx, persistence) {
798
+ ctx.inject(["webServer", "connection"], (webCtx) => {
799
+ const webServer = webCtx.webServer;
800
+ const connection = webCtx.get("connection");
801
+ return webCtx.effect(() => webServer.register({
802
+ kind: "exact",
803
+ path: SESSION_USAGE_PATH,
804
+ handler: async (req, res) => {
805
+ const rejection = connection.requestRejection(req);
806
+ if (rejection !== void 0) {
807
+ res.writeHead(rejection);
808
+ res.end(rejection === 401 ? "unauthorized" : "forbidden");
809
+ return;
810
+ }
811
+ if (req.method !== "POST") {
812
+ res.writeHead(405, { "content-type": "application/json" });
813
+ res.end(JSON.stringify({ error: "method not allowed" }));
814
+ return;
815
+ }
816
+ const chunks = [];
817
+ for await (const chunk of req) chunks.push(chunk);
818
+ const raw = Buffer.concat(chunks).toString("utf8");
819
+ let envelope = {};
820
+ if (raw !== "") try {
821
+ envelope = JSON.parse(raw);
822
+ } catch {
823
+ res.writeHead(400, { "content-type": "application/json" });
824
+ res.end(JSON.stringify({ error: "request body is not JSON" }));
825
+ return;
826
+ }
827
+ try {
828
+ const report = await persistence.usageReport(resolveUsageSince(parseUsageRange(envelope.range), Date.now()));
829
+ res.writeHead(200, { "content-type": "application/json" });
830
+ res.end(JSON.stringify(report));
831
+ } catch (error) {
832
+ res.writeHead(500, { "content-type": "application/json" });
833
+ res.end(JSON.stringify({ error: error instanceof Error ? error.message : "usage report failed" }));
834
+ }
835
+ }
836
+ }), `session-rdb: ${SESSION_USAGE_PATH} route`);
837
+ });
838
+ }
839
+ //#endregion
694
840
  //#region src/storage-takeover/repository.ts
695
841
  async function allRows(query) {
696
842
  const q = query;
@@ -941,6 +1087,32 @@ function createStorageRepository(host) {
941
1087
  }
942
1088
  //#endregion
943
1089
  //#region src/sqlite.ts
1090
+ /** 活动计数的派生表:可销毁重建(不在 drizzle schema / 迁移里,建表幂等)。 */
1091
+ function ensureEventCountsTable(db) {
1092
+ db.exec(`CREATE TABLE IF NOT EXISTS t_event_counts (
1093
+ f_id INTEGER PRIMARY KEY AUTOINCREMENT,
1094
+ f_session_id TEXT NOT NULL,
1095
+ f_day TEXT NOT NULL,
1096
+ f_type TEXT NOT NULL,
1097
+ f_count INTEGER NOT NULL DEFAULT 0
1098
+ );
1099
+ CREATE UNIQUE INDEX IF NOT EXISTS uq_event_counts_session_day_type
1100
+ ON t_event_counts(f_session_id, f_day, f_type);
1101
+ CREATE INDEX IF NOT EXISTS idx_event_counts_day ON t_event_counts(f_day);`);
1102
+ }
1103
+ /** 一次性回填活动计数(表为空时从事件表重算;幂等)。 */
1104
+ function backfillEventCounts(db) {
1105
+ if (db.prepare("SELECT count(*) AS n FROM t_event_counts").get().n > 0) return;
1106
+ db.exec(`INSERT OR IGNORE INTO t_event_counts (f_session_id, f_day, f_type, f_count)
1107
+ SELECT b.f_session_id,
1108
+ date(e.f_created_at / 1000, 'unixepoch', 'localtime'),
1109
+ e.f_type,
1110
+ count(*)
1111
+ FROM t_session_events b
1112
+ JOIN t_events e ON e.f_event_id = b.f_event_id
1113
+ WHERE e.f_type IN (${COUNTED_EVENT_TYPE_SQL})
1114
+ GROUP BY 1, 2, 3`);
1115
+ }
944
1116
  /**
945
1117
  * 一次性回填:旧库的用量从未写过 `t_event_usage`,建表后按事件行补一次(幂等:表非空即跳过)。
946
1118
  */
@@ -970,9 +1142,8 @@ function backfillEventUsage(db) {
970
1142
  OR json_extract(e.f_data, '$.usage') IS NOT NULL)`);
971
1143
  }
972
1144
  /** SQL 的缺失求和是 NULL:没有 usage 字段的行使该字段计 0。 */
973
- function totalsOf(row) {
1145
+ function tokenTotalsOf(row) {
974
1146
  return {
975
- events: row.events,
976
1147
  inputTokens: row.input_tokens ?? 0,
977
1148
  outputTokens: row.output_tokens ?? 0,
978
1149
  cacheReadTokens: row.cache_read_tokens ?? 0,
@@ -980,6 +1151,26 @@ function totalsOf(row) {
980
1151
  totalTokens: row.total_tokens ?? 0
981
1152
  };
982
1153
  }
1154
+ /** 一行的整套指标:token 用量 + 活动计数(轮次 / 步骤 / 用户输入 / 工具调用)。 */
1155
+ function emptyActivity() {
1156
+ return {
1157
+ turns: 0,
1158
+ steps: 0,
1159
+ userInputs: 0,
1160
+ toolCalls: 0
1161
+ };
1162
+ }
1163
+ /** 有 token 用量的会话:活动计数与列表都限定在这一批会话里,口径一致。 */
1164
+ function hasUsageSession(column) {
1165
+ return `EXISTS (SELECT 1 FROM t_session_events ub
1166
+ JOIN t_event_usage uu ON uu.f_event_id = ub.f_event_id
1167
+ WHERE ub.f_session_id = ${column})`;
1168
+ }
1169
+ const SUBAGENT_OF_EVENT = `EXISTS (SELECT 1 FROM t_session_events sb
1170
+ JOIN t_sessions ss ON ss.f_session_id = sb.f_session_id
1171
+ WHERE sb.f_event_id = %EVENT% AND ss.f_origin = 'subagent')`;
1172
+ /** `IN (...)` 用的类型字面量(与 `COUNTED_EVENT_TYPES` 同源)。 */
1173
+ const COUNTED_EVENT_TYPE_SQL = COUNTED_EVENT_TYPES.map((type) => `'${type}'`).join(", ");
983
1174
  const sqliteMigrationsDir = fileURLToPath(new URL("../drizzle/sqlite/", import.meta.url));
984
1175
  const sqliteTxQueues = /* @__PURE__ */ new Map();
985
1176
  function enqueueSqliteTx(path, fn) {
@@ -1002,6 +1193,8 @@ async function openDatabase(path, journalMode, busyTimeout = DEFAULT_BUSY_TIMEOU
1002
1193
  const { user_version: onDisk } = db.prepare("PRAGMA user_version").get();
1003
1194
  if (onDisk === 2 && !hasMigrationsTable(db)) await baselineV2(db);
1004
1195
  migrate(dbx, { migrationsFolder: sqliteMigrationsDir });
1196
+ ensureEventCountsTable(db);
1197
+ backfillEventCounts(db);
1005
1198
  backfillEventUsage(db);
1006
1199
  dbx.insert(tPersistenceState).values({
1007
1200
  fSingleton: 1,
@@ -1142,10 +1335,13 @@ var SqliteBackend = class SqliteBackend {
1142
1335
  return (fromSequence === void 0 ? this.eventRows().where(eq(tSessionEvents.fSessionId, id)) : this.eventRows().where(and(eq(tSessionEvents.fSessionId, id), gte(tSessionEvents.fSequence, fromSequence)))).orderBy(tSessionEvents.fSequence).all();
1143
1336
  }
1144
1337
  async getEventTypeAt(id, sequence) {
1145
- return this.eventRows().where(and(eq(tSessionEvents.fSessionId, id), eq(tSessionEvents.fSequence, sequence))).get()?.fType;
1338
+ return this.db.select({ fType: tEvents.fType }).from(tSessionEvents).innerJoin(tEvents, eq(tSessionEvents.fEventId, tEvents.fEventId)).where(and(eq(tSessionEvents.fSessionId, id), eq(tSessionEvents.fSequence, sequence))).get()?.fType;
1146
1339
  }
1147
1340
  async getEventTypesBefore(id, beforeSequence, limit) {
1148
- return this.eventRows().where(and(eq(tSessionEvents.fSessionId, id), lt(tSessionEvents.fSequence, beforeSequence))).orderBy(desc(tSessionEvents.fSequence)).limit(limit).all();
1341
+ return this.db.select({
1342
+ fSequence: tSessionEvents.fSequence,
1343
+ fType: tEvents.fType
1344
+ }).from(tSessionEvents).innerJoin(tEvents, eq(tSessionEvents.fEventId, tEvents.fEventId)).where(and(eq(tSessionEvents.fSessionId, id), lt(tSessionEvents.fSequence, beforeSequence))).orderBy(desc(tSessionEvents.fSequence)).limit(limit).all();
1149
1345
  }
1150
1346
  async listSessions() {
1151
1347
  return this.db.select().from(tSessions).all();
@@ -1273,30 +1469,49 @@ var SqliteBackend = class SqliteBackend {
1273
1469
  const info = this.db.delete(tSessions).where(inArray(tSessions.fSessionId, ids)).run();
1274
1470
  return Number(info.changes);
1275
1471
  }
1276
- /** 用量聚合:只读 `t_event_usage`;可选只算 `sinceMs` 之后的事件行。 */
1472
+ /**
1473
+ * 用量聚合:token 用量沿 `t_event_usage` 的用量行,活动计数(轮次 / 步骤 / 用户输入 / 工具调用)
1474
+ * 沿 `t_events` 的事件类型数——两者限定在**有 token 用量的会话**里,时间范围各自按自己的
1475
+ * `f_created_at`(同一时刻写入,口径一致)。
1476
+ */
1277
1477
  async usageReport(sinceMs) {
1278
- const sinceClause = sinceMs === void 0 ? "" : " AND u.f_created_at >= ?";
1279
- const sinceParams = sinceMs === void 0 ? [] : [sinceMs];
1478
+ const usageSince = sinceMs === void 0 ? "" : " AND u.f_created_at >= ?";
1479
+ const params = sinceMs === void 0 ? [] : [sinceMs];
1480
+ const daySince = sinceMs === void 0 ? "" : " AND c.f_day >= ?";
1481
+ const dayParams = sinceMs === void 0 ? [] : [localDayKey(sinceMs)];
1482
+ const subagentOfUsage = SUBAGENT_OF_EVENT.replace("%EVENT%", "u.f_event_id");
1280
1483
  const buckets = this.db.$client.prepare(`SELECT date(u.f_created_at / 1000, 'unixepoch', 'localtime') AS day,
1281
1484
  u.f_provider AS provider,
1282
1485
  u.f_model AS model,
1283
- EXISTS (SELECT 1 FROM t_session_events sb
1284
- JOIN t_sessions ss ON ss.f_session_id = sb.f_session_id
1285
- WHERE sb.f_event_id = u.f_event_id AND ss.f_origin = 'subagent') AS subagent,
1286
- count(*) AS events,
1486
+ ${subagentOfUsage} AS subagent,
1287
1487
  sum(u.f_input_tokens) AS input_tokens,
1288
1488
  sum(u.f_output_tokens) AS output_tokens,
1289
1489
  sum(u.f_cache_read_tokens) AS cache_read_tokens,
1290
1490
  sum(u.f_reasoning_tokens) AS reasoning_tokens,
1291
1491
  sum(u.f_total_tokens) AS total_tokens
1292
1492
  FROM t_event_usage u
1293
- WHERE EXISTS (SELECT 1 FROM t_session_events rb WHERE rb.f_event_id = u.f_event_id)${sinceClause}
1294
- GROUP BY day, provider, model, subagent`).all(...sinceParams);
1295
- const sessions = this.db.$client.prepare(`SELECT b.f_session_id AS session_id,
1493
+ WHERE EXISTS (SELECT 1 FROM t_session_events rb WHERE rb.f_event_id = u.f_event_id)${usageSince}
1494
+ GROUP BY day, provider, model, subagent`).all(...params);
1495
+ const tokenScope = this.db.$client.prepare(`SELECT ${subagentOfUsage} AS subagent,
1496
+ sum(u.f_input_tokens) AS input_tokens,
1497
+ sum(u.f_output_tokens) AS output_tokens,
1498
+ sum(u.f_cache_read_tokens) AS cache_read_tokens,
1499
+ sum(u.f_reasoning_tokens) AS reasoning_tokens,
1500
+ sum(u.f_total_tokens) AS total_tokens
1501
+ FROM t_event_usage u
1502
+ WHERE EXISTS (SELECT 1 FROM t_session_events rb WHERE rb.f_event_id = u.f_event_id)${usageSince}
1503
+ GROUP BY subagent`).all(...params);
1504
+ const activityScope = this.db.$client.prepare(`SELECT (s.f_origin = 'subagent') AS subagent,
1505
+ c.f_type AS f_type,
1506
+ sum(c.f_count) AS n
1507
+ FROM t_event_counts c
1508
+ JOIN t_sessions s ON s.f_session_id = c.f_session_id
1509
+ WHERE ${hasUsageSession("c.f_session_id")}${daySince}
1510
+ GROUP BY subagent, c.f_type`).all(...dayParams);
1511
+ const tokenSessions = this.db.$client.prepare(`SELECT b.f_session_id AS session_id,
1296
1512
  s.f_title AS title,
1297
1513
  (s.f_origin = 'subagent') AS subagent,
1298
1514
  (s.f_archived_at IS NOT NULL) AS archived,
1299
- count(*) AS events,
1300
1515
  sum(u.f_input_tokens) AS input_tokens,
1301
1516
  sum(u.f_output_tokens) AS output_tokens,
1302
1517
  sum(u.f_cache_read_tokens) AS cache_read_tokens,
@@ -1305,25 +1520,69 @@ var SqliteBackend = class SqliteBackend {
1305
1520
  FROM t_session_events b
1306
1521
  JOIN t_event_usage u ON u.f_event_id = b.f_event_id
1307
1522
  JOIN t_sessions s ON s.f_session_id = b.f_session_id
1308
- WHERE 1 = 1${sinceClause}
1309
- GROUP BY b.f_session_id, s.f_title, s.f_origin, s.f_archived_at`).all(...sinceParams);
1523
+ WHERE 1 = 1${usageSince}
1524
+ GROUP BY b.f_session_id, s.f_title, s.f_origin, s.f_archived_at`).all(...params);
1525
+ const activitySessions = this.db.$client.prepare(`SELECT c.f_session_id AS session_id,
1526
+ c.f_type AS f_type,
1527
+ sum(c.f_count) AS n
1528
+ FROM t_event_counts c
1529
+ WHERE ${hasUsageSession("c.f_session_id")}${daySince}
1530
+ GROUP BY c.f_session_id, c.f_type`).all(...dayParams);
1531
+ const human = emptyTotals();
1532
+ const subagent = emptyTotals();
1533
+ for (const row of tokenScope) addTokenTotals(row.subagent === 1 ? subagent : human, tokenTotalsOf(row));
1534
+ for (const row of activityScope) addActivityCount(row.subagent === 1 ? subagent : human, row.f_type, row.n ?? 0);
1535
+ const totals = addTotals(addTotals(emptyTotals(), human), subagent);
1536
+ const activityBySession = /* @__PURE__ */ new Map();
1537
+ for (const row of activitySessions) {
1538
+ const target = activityBySession.get(row.session_id) ?? emptyActivity();
1539
+ addActivityCount(target, row.f_type, row.n ?? 0);
1540
+ activityBySession.set(row.session_id, target);
1541
+ }
1310
1542
  return {
1543
+ totals,
1544
+ subagent,
1545
+ human,
1311
1546
  buckets: buckets.map((row) => ({
1312
1547
  day: row.day,
1313
1548
  provider: row.provider,
1314
1549
  model: row.model,
1315
1550
  subagent: row.subagent === 1,
1316
- ...totalsOf(row)
1551
+ ...tokenTotalsOf(row)
1317
1552
  })),
1318
- sessions: sessions.map((row) => ({
1553
+ sessions: tokenSessions.map((row) => ({
1319
1554
  sessionId: row.session_id,
1320
1555
  title: row.title,
1321
1556
  subagent: row.subagent === 1,
1322
1557
  archived: row.archived === 1,
1323
- ...totalsOf(row)
1558
+ ...tokenTotalsOf(row),
1559
+ ...activityBySession.get(row.session_id) ?? emptyActivity()
1324
1560
  }))
1325
1561
  };
1326
1562
  }
1563
+ /** 活动计数旁路累加:派生表 `t_event_counts`,不在写事务里(失败可丢,表可销毁重建)。 */
1564
+ async incrementEventCounts(id, buckets) {
1565
+ if (buckets.length === 0) return;
1566
+ const statement = this.db.$client.prepare(`INSERT INTO t_event_counts (f_session_id, f_day, f_type, f_count) VALUES (?, ?, ?, ?)
1567
+ ON CONFLICT(f_session_id, f_day, f_type) DO UPDATE SET f_count = f_count + excluded.f_count`);
1568
+ for (const bucket of buckets) statement.run(id, bucket.day, bucket.type, bucket.count);
1569
+ }
1570
+ /** 按会话重算活动计数(rewind / fork 之后):先删该会话的行,再从事件表重算。 */
1571
+ async rebuildEventCounts(id) {
1572
+ this.db.$client.prepare("DELETE FROM t_event_counts WHERE f_session_id = ?").run(id);
1573
+ this.db.$client.prepare(`INSERT INTO t_event_counts (f_session_id, f_day, f_type, f_count)
1574
+ SELECT b.f_session_id,
1575
+ date(e.f_created_at / 1000, 'unixepoch', 'localtime'),
1576
+ e.f_type,
1577
+ count(*)
1578
+ FROM t_session_events b
1579
+ JOIN t_events e ON e.f_event_id = b.f_event_id
1580
+ WHERE b.f_session_id = ? AND e.f_type IN (${COUNTED_EVENT_TYPE_SQL})
1581
+ GROUP BY 1, 2, 3`).run(id);
1582
+ }
1583
+ async deleteEventCounts(id) {
1584
+ this.db.$client.prepare("DELETE FROM t_event_counts WHERE f_session_id = ?").run(id);
1585
+ }
1327
1586
  async vacuum() {
1328
1587
  await enqueueSqliteTx(this.dbPath, async () => {
1329
1588
  this.db.$client.exec("VACUUM");
@@ -1345,4 +1604,4 @@ var SqliteBackend = class SqliteBackend {
1345
1604
  }
1346
1605
  };
1347
1606
  //#endregion
1348
- export { WriteGuard as C, toPostgresSchema as S, tStorageUnits as _, EVENT_ENCODING as a, tWorkspaces as b, eventDimensions as c, tEvents as d, tPersistenceState as f, tSessions as g, tSessionProjcacheRows as h, DEFAULT_BUSY_TIMEOUT_MS as i, eventKind as l, tSessionEvents as m, openDatabase as n, SCHEMA_VERSION as o, tSchemaMeta as p, createStorageRepository as r, SESSION_PERSISTENCE_SQLITE_APPLICATION_ID as s, SqliteBackend as t, tEventUsage as u, tWorkspaceSessions as v, postgresTableDefs as x, tWorkspaceState as y };
1607
+ export { WriteGuard as A, tSessions as C, tWorkspaces as D, tWorkspaceState as E, postgresTableDefs as O, tSessionProjcacheRows as S, tWorkspaceSessions as T, tEventUsage as _, addActivityCount as a, tSchemaMeta as b, emptyTotals as c, DEFAULT_BUSY_TIMEOUT_MS as d, EVENT_ENCODING as f, eventKind as g, eventDimensions as h, COUNTED_EVENT_TYPES as i, toPostgresSchema as k, localDayKey as l, SESSION_PERSISTENCE_SQLITE_APPLICATION_ID as m, openDatabase as n, addTokenTotals as o, SCHEMA_VERSION as p, createStorageRepository as r, addTotals as s, SqliteBackend as t, registerSessionUsage as u, tEvents as v, tStorageUnits as w, tSessionEvents as x, tPersistenceState as y };