@morlay/session-rdb 0.1.10-alpha.0 → 0.1.10-alpha.2

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 (142) hide show
  1. package/README.md +18 -3
  2. package/dist/artifact.d.mts +118 -2
  3. package/dist/artifact.mjs +5 -3
  4. package/dist/{log-TYgd8Xkr.d.mts → backend-BKtJ5sO5.d.mts} +183 -284
  5. package/dist/backend-rdb-BDCntVDy.mjs +1341 -0
  6. package/dist/branch-CG1PUlO6.mjs +833 -0
  7. package/dist/deletion-SSX7IqU8.mjs +35 -0
  8. package/dist/deletion.d.mts +1 -1
  9. package/dist/deletion.mjs +2 -2
  10. package/dist/export-CfJQjQfr.mjs +123 -0
  11. package/dist/export.d.mts +1 -1
  12. package/dist/export.mjs +31 -55
  13. package/dist/import.d.mts +1 -1
  14. package/dist/import.mjs +31 -76
  15. package/dist/index-CUD2ZpTA.d.mts +71 -0
  16. package/dist/index.d.mts +20 -2
  17. package/dist/index.mjs +1561 -4
  18. package/dist/open-YoyD_kah.mjs +561 -0
  19. package/dist/organize.d.mts +9 -0
  20. package/dist/organize.mjs +30 -0
  21. package/dist/route-DpfY0zq-.mjs +114 -0
  22. package/dist/storage.d.mts +41 -48
  23. package/dist/storage.mjs +3 -1
  24. package/dist/testing.d.mts +9 -1
  25. package/dist/testing.mjs +25 -4
  26. package/dist/usage-row-BQQM-_t6.mjs +36 -0
  27. package/dist/usage.d.mts +1 -1
  28. package/dist/usage.mjs +7 -40
  29. package/dist/write-guard-CYrY58GM.mjs +174 -0
  30. package/package.json +10 -14
  31. package/src/artifact.ts +4 -1
  32. package/src/backend-rdb.ts +331 -0
  33. package/src/backend.ts +32 -15
  34. package/src/{branch.ts → branch/index.ts} +109 -110
  35. package/src/branch/port.ts +62 -0
  36. package/src/branch/semantics.ts +69 -0
  37. package/src/db/open.ts +180 -0
  38. package/src/db/stats.ts +449 -0
  39. package/src/deletion-error.ts +17 -0
  40. package/src/deletion.ts +19 -72
  41. package/src/entities/index.ts +16 -1
  42. package/src/entities/v3/event-usage.ts +3 -3
  43. package/src/entities/v3/events.ts +3 -3
  44. package/src/entities/v3/index.ts +4 -16
  45. package/src/entities/v3/persistence-state.ts +3 -3
  46. package/src/entities/v3/schema-meta.ts +3 -3
  47. package/src/entities/v3/session-counts.ts +3 -3
  48. package/src/entities/v3/session-events.ts +3 -3
  49. package/src/entities/v3/session-projcache-rows.ts +3 -3
  50. package/src/entities/v3/session-usage.ts +3 -3
  51. package/src/entities/v3/sessions.ts +3 -3
  52. package/src/entities/v3/storage-records.ts +17 -0
  53. package/src/entities/v3/storage-units.ts +3 -3
  54. package/src/{schema.ts → event-shape.ts} +0 -46
  55. package/src/export.ts +32 -78
  56. package/src/handles.ts +349 -0
  57. package/src/http/route.ts +178 -0
  58. package/src/import-storages.ts +5 -2
  59. package/src/import.ts +63 -125
  60. package/src/index.ts +15 -1666
  61. package/src/legacy.ts +3 -1
  62. package/src/live-routing.ts +205 -0
  63. package/src/log/export.ts +84 -0
  64. package/src/{log.ts → log/repair.ts} +1 -268
  65. package/src/log/rows.ts +107 -0
  66. package/src/log/usage-row.ts +64 -0
  67. package/src/migrations.ts +196 -0
  68. package/src/organize.ts +38 -0
  69. package/src/read-path.ts +190 -0
  70. package/src/routes.ts +2 -1
  71. package/src/rows.ts +25 -77
  72. package/src/session-ops.ts +444 -0
  73. package/src/session-store.ts +675 -0
  74. package/src/stats-fold.ts +44 -0
  75. package/src/storage-takeover/index.ts +2 -5
  76. package/src/storage-takeover/legacy-domain-migration.ts +118 -0
  77. package/src/storage-takeover/projection-cache.ts +122 -71
  78. package/src/storage-takeover/read-model.ts +189 -0
  79. package/src/storage-takeover/repository.ts +236 -442
  80. package/src/storage-takeover/storage-backend.ts +44 -159
  81. package/src/storage-takeover/types.ts +45 -19
  82. package/src/storage-takeover/workspace-documents.ts +65 -0
  83. package/src/storage.ts +4 -2
  84. package/src/testing.ts +21 -1
  85. package/src/usage.ts +11 -65
  86. package/src/version.ts +13 -0
  87. package/src/write-path.ts +286 -0
  88. package/dist/branch-CoPCRKer.mjs +0 -401
  89. package/dist/deletion-CWl89TIR.mjs +0 -2249
  90. package/dist/gc.d.mts +0 -4
  91. package/dist/gc.mjs +0 -48
  92. package/dist/log-CcWy46VE.mjs +0 -558
  93. package/dist/routes-hZjTcX_R.mjs +0 -9
  94. package/dist/sqlite-BNRd1aqR.mjs +0 -1778
  95. package/drizzle/postgres/20260908072805_v2_initial/migration.sql +0 -58
  96. package/drizzle/postgres/20260908072805_v2_initial/snapshot.json +0 -686
  97. package/drizzle/postgres/20260908072806_v3_drop_original_seq/migration.sql +0 -1
  98. package/drizzle/postgres/20260908072806_v3_drop_original_seq/snapshot.json +0 -673
  99. package/drizzle/postgres/20260910120001_v3_storage_tables/migration.sql +0 -65
  100. package/drizzle/postgres/20260910120001_v3_storage_tables/snapshot.json +0 -1183
  101. package/drizzle/postgres/20260910130001_v3_session_title_backfill/migration.sql +0 -10
  102. package/drizzle/postgres/20260910130001_v3_session_title_backfill/snapshot.json +0 -1183
  103. package/drizzle/postgres/20260918120000_v3_event_usage/migration.sql +0 -14
  104. package/drizzle/postgres/20260918120000_v3_event_usage/snapshot.json +0 -1309
  105. package/drizzle/postgres/20260921075900_v3_agent_preset/migration.sql +0 -1
  106. package/drizzle/postgres/20260922090001_v3_pinned_seq/migration.sql +0 -2
  107. package/drizzle/postgres/20260922093001_v3_last_event_at/migration.sql +0 -10
  108. package/drizzle/postgres/20260923120000_v3_usage_materialized/migration.sql +0 -48
  109. package/drizzle/postgres/20261008103001_v3_schedule_tasks/migration.sql +0 -11
  110. package/drizzle/sqlite/20260908072751_v2_initial/migration.sql +0 -53
  111. package/drizzle/sqlite/20260908072751_v2_initial/snapshot.json +0 -492
  112. package/drizzle/sqlite/20260908072752_v3_drop_original_seq/migration.sql +0 -6
  113. package/drizzle/sqlite/20260908072752_v3_drop_original_seq/snapshot.json +0 -513
  114. package/drizzle/sqlite/20260910120000_v3_storage_tables/migration.sql +0 -66
  115. package/drizzle/sqlite/20260910120000_v3_storage_tables/snapshot.json +0 -905
  116. package/drizzle/sqlite/20260910130000_v3_session_title_backfill/migration.sql +0 -13
  117. package/drizzle/sqlite/20260910130000_v3_session_title_backfill/snapshot.json +0 -905
  118. package/drizzle/sqlite/20260918120000_v3_event_usage/migration.sql +0 -14
  119. package/drizzle/sqlite/20260918120000_v3_event_usage/snapshot.json +0 -1031
  120. package/drizzle/sqlite/20260921075855_v3_agent_preset/migration.sql +0 -7
  121. package/drizzle/sqlite/20260921075855_v3_agent_preset/snapshot.json +0 -1041
  122. package/drizzle/sqlite/20260922090000_v3_pinned_seq/migration.sql +0 -4
  123. package/drizzle/sqlite/20260922093000_v3_last_event_at/migration.sql +0 -13
  124. package/drizzle/sqlite/20260923120000_v3_usage_materialized/migration.sql +0 -48
  125. package/drizzle/sqlite/20261008103000_v3_schedule_tasks/migration.sql +0 -14
  126. package/src/adapters/index.ts +0 -12
  127. package/src/adapters/to-postgres.ts +0 -93
  128. package/src/adapters/to-sqlite.ts +0 -83
  129. package/src/adapters/types.ts +0 -44
  130. package/src/drizzle/postgres-v2.ts +0 -10
  131. package/src/drizzle/postgres-v3.ts +0 -18
  132. package/src/drizzle/sqlite-v2.ts +0 -9
  133. package/src/drizzle/sqlite-v3.ts +0 -18
  134. package/src/entities/v2/index.ts +0 -20
  135. package/src/entities/v2/session-events.ts +0 -10
  136. package/src/entities/v3/schedule-tasks.ts +0 -16
  137. package/src/entities/v3/workspace-sessions.ts +0 -19
  138. package/src/entities/v3/workspace-state.ts +0 -12
  139. package/src/entities/v3/workspaces.ts +0 -14
  140. package/src/gc.ts +0 -77
  141. package/src/postgres.ts +0 -1015
  142. package/src/sqlite.ts +0 -1096
package/src/deletion.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import type { Context } from "@deepseek-ai/cordis";
2
2
  import type { SessionId } from "@deepseek-ai/dsh-session";
3
- import { SessionDeletionError, type SessionPersistenceRdb } from "./index.ts";
3
+ import { SessionDeletionError } from "./deletion-error.ts";
4
+ import type { SessionPersistenceRdb } from "./session-store.ts";
4
5
  import { SESSION_DELETE_PATH } from "./routes.ts";
6
+ import { HttpError, mountJsonRoute } from "./http/route.ts";
5
7
 
6
8
  export { SESSION_DELETE_PATH };
7
9
 
@@ -12,77 +14,22 @@ const STATUS_OF_DELETION_ERROR: Record<SessionDeletionError["code"], number> = {
12
14
  };
13
15
 
14
16
  export function registerSessionDeletion(ctx: Context, persistence: SessionPersistenceRdb): void {
15
- ctx.inject(["webServer", "connection"] as const, (webCtx) => {
16
- const webServer = webCtx.webServer as unknown as {
17
- register(route: {
18
- kind: "exact";
19
- path: string;
20
- handler: (
21
- req: import("node:http").IncomingMessage,
22
- res: import("node:http").ServerResponse,
23
- ) => void | Promise<void>;
24
- }): () => void;
25
- };
26
- const connection = webCtx.get("connection") as unknown as {
27
- requestRejection(request: {
28
- headers: import("node:http").IncomingHttpHeaders;
29
- }): number | undefined;
30
- };
31
- return webCtx.effect(() =>
32
- webServer.register({
33
- kind: "exact",
34
- path: SESSION_DELETE_PATH,
35
- handler: async (req, res) => {
36
- const rejection = connection.requestRejection(req);
37
- if (rejection !== undefined) {
38
- res.writeHead(rejection);
39
- res.end(rejection === 401 ? "unauthorized" : "forbidden");
40
- return;
17
+ mountJsonRoute(ctx, {
18
+ path: SESSION_DELETE_PATH,
19
+ handle: async (body) => {
20
+ const { sessionId } = body as { sessionId?: unknown };
21
+ if (typeof sessionId !== "string" || sessionId === "") {
22
+ throw new HttpError(400, "missing sessionId field");
23
+ }
24
+ await persistence.deleteSession(sessionId as SessionId);
25
+ return { body: { deleted: sessionId } };
26
+ },
27
+ statusOfError: (error) =>
28
+ error instanceof SessionDeletionError
29
+ ? {
30
+ status: STATUS_OF_DELETION_ERROR[error.code],
31
+ body: { error: error.message, code: error.code },
41
32
  }
42
- if (req.method !== "POST") {
43
- res.writeHead(405, { "content-type": "application/json" });
44
- res.end(JSON.stringify({ error: "method not allowed" }));
45
- return;
46
- }
47
- const chunks: Buffer[] = [];
48
- for await (const chunk of req) chunks.push(chunk as Buffer);
49
- let envelope: { sessionId?: unknown };
50
- try {
51
- envelope = JSON.parse(Buffer.concat(chunks).toString("utf8")) as {
52
- sessionId?: unknown;
53
- };
54
- } catch {
55
- res.writeHead(400, { "content-type": "application/json" });
56
- res.end(JSON.stringify({ error: "request body is not JSON" }));
57
- return;
58
- }
59
- if (typeof envelope.sessionId !== "string" || envelope.sessionId === "") {
60
- res.writeHead(400, { "content-type": "application/json" });
61
- res.end(JSON.stringify({ error: "missing sessionId field" }));
62
- return;
63
- }
64
- try {
65
- await persistence.deleteSession(envelope.sessionId as SessionId);
66
- } catch (error: unknown) {
67
- if (error instanceof SessionDeletionError) {
68
- res.writeHead(STATUS_OF_DELETION_ERROR[error.code], {
69
- "content-type": "application/json",
70
- });
71
- res.end(JSON.stringify({ error: error.message, code: error.code }));
72
- return;
73
- }
74
- res.writeHead(500, { "content-type": "application/json" });
75
- res.end(
76
- JSON.stringify({
77
- error: error instanceof Error ? error.message : "session deletion failed",
78
- }),
79
- );
80
- return;
81
- }
82
- res.writeHead(200, { "content-type": "application/json" });
83
- res.end(JSON.stringify({ deleted: envelope.sessionId }));
84
- },
85
- }),
86
- );
33
+ : undefined,
87
34
  });
88
35
  }
@@ -1,2 +1,17 @@
1
+ import { defineCatalog } from "@morlay/rdbkit";
2
+ import { sqliteTableDefs } from "./v3/index.ts";
3
+
1
4
  export { sqliteTableDefs, postgresTableDefs } from "./v3/index.ts";
2
- export { sqliteTableDefsV2, postgresTableDefsV2 } from "./v2/index.ts";
5
+
6
+ /** 库结构的唯一事实来源(DDL、迁移与表句柄都从它算出来)。 */
7
+ export const catalog = defineCatalog(sqliteTableDefs);
8
+ export { storageRecords } from "./v3/storage-records.ts";
9
+ export { sessionProjcacheRows } from "./v3/session-projcache-rows.ts";
10
+ export { persistenceState } from "./v3/persistence-state.ts";
11
+ export { sessions } from "./v3/sessions.ts";
12
+ export { events } from "./v3/events.ts";
13
+ export { sessionEvents } from "./v3/session-events.ts";
14
+ export { eventUsage } from "./v3/event-usage.ts";
15
+ export { sessionUsage } from "./v3/session-usage.ts";
16
+ export { sessionCounts } from "./v3/session-counts.ts";
17
+ export { storageUnits } from "./v3/storage-units.ts";
@@ -1,9 +1,9 @@
1
- import type { TableDef } from "../../adapters/types.ts";
1
+ import { defineTable } from "@morlay/rdbkit";
2
2
 
3
3
  // 用量日志:一条 `assistant/message` 事件一行(按事件行唯一,fork 共享行不重复);读侧维度全部物化在行上
4
4
  // (本地日、是否被会话引用、是否被子代理会话引用),统计因此不做 `EXISTS` 判定、也不回连事件表。
5
5
  // 取舍见 ADR-统计衍生表物化归属与汇总。
6
- export const eventUsage: TableDef = {
6
+ export const eventUsage = defineTable({
7
7
  name: "t_event_usage",
8
8
  columns: {
9
9
  f_event_id: {
@@ -27,4 +27,4 @@ export const eventUsage: TableDef = {
27
27
  f_total_tokens: { type: "integer", notNull: true, default: 0 },
28
28
  },
29
29
  indexes: { idx_event_usage_created_at: { columns: ["f_created_at"] } },
30
- };
30
+ });
@@ -1,6 +1,6 @@
1
- import type { TableDef } from "../../adapters/types.ts";
1
+ import { defineTable } from "@morlay/rdbkit";
2
2
 
3
- export const events: TableDef = {
3
+ export const events = defineTable({
4
4
  name: "t_events",
5
5
  columns: {
6
6
  f_id: { type: "serial", primaryKey: true },
@@ -22,4 +22,4 @@ export const events: TableDef = {
22
22
  idx_events_name: { columns: ["f_name"] },
23
23
  idx_events_action_id: { columns: ["f_action_id"] },
24
24
  },
25
- };
25
+ });
@@ -4,10 +4,7 @@ import { sessions } from "./sessions.ts";
4
4
  import { events } from "./events.ts";
5
5
  import { sessionEvents } from "./session-events.ts";
6
6
  import { storageUnits } from "./storage-units.ts";
7
- import { workspaces } from "./workspaces.ts";
8
- import { workspaceSessions } from "./workspace-sessions.ts";
9
- import { workspaceState } from "./workspace-state.ts";
10
- import { scheduleTasks } from "./schedule-tasks.ts";
7
+ import { storageRecords } from "./storage-records.ts";
11
8
  import { sessionProjcacheRows } from "./session-projcache-rows.ts";
12
9
  import { eventUsage } from "./event-usage.ts";
13
10
  import { sessionUsage } from "./session-usage.ts";
@@ -19,10 +16,7 @@ export { sessions };
19
16
  export { events };
20
17
  export { sessionEvents };
21
18
  export { storageUnits };
22
- export { workspaces };
23
- export { workspaceSessions };
24
- export { workspaceState };
25
- export { scheduleTasks };
19
+ export { storageRecords };
26
20
  export { sessionProjcacheRows };
27
21
  export { eventUsage };
28
22
  export { sessionUsage };
@@ -35,10 +29,7 @@ export const sqliteTableDefs = [
35
29
  events,
36
30
  sessionEvents,
37
31
  storageUnits,
38
- workspaces,
39
- workspaceSessions,
40
- workspaceState,
41
- scheduleTasks,
32
+ storageRecords,
42
33
  sessionProjcacheRows,
43
34
  eventUsage,
44
35
  sessionUsage,
@@ -52,10 +43,7 @@ export const postgresTableDefs = [
52
43
  events,
53
44
  sessionEvents,
54
45
  storageUnits,
55
- workspaces,
56
- workspaceSessions,
57
- workspaceState,
58
- scheduleTasks,
46
+ storageRecords,
59
47
  sessionProjcacheRows,
60
48
  eventUsage,
61
49
  sessionUsage,
@@ -1,10 +1,10 @@
1
- import type { TableDef } from "../../adapters/types.ts";
1
+ import { defineTable } from "@morlay/rdbkit";
2
2
 
3
- export const persistenceState: TableDef = {
3
+ export const persistenceState = defineTable({
4
4
  name: "t_persistence_state",
5
5
  columns: {
6
6
  f_singleton: { type: "integer", primaryKey: true },
7
7
  f_store_id: { type: "text", notNull: true },
8
8
  },
9
9
  checks: { ck_persistence_state_singleton: { expression: "f_singleton = 1" } },
10
- };
10
+ });
@@ -1,9 +1,9 @@
1
- import type { TableDef } from "../../adapters/types.ts";
1
+ import { defineTable } from "@morlay/rdbkit";
2
2
 
3
- export const schemaMeta: TableDef = {
3
+ export const schemaMeta = defineTable({
4
4
  name: "t_schema_meta",
5
5
  columns: {
6
6
  f_key: { type: "text", primaryKey: true },
7
7
  f_value: { type: "text", notNull: true },
8
8
  },
9
- };
9
+ });
@@ -1,9 +1,9 @@
1
- import type { TableDef } from "../../adapters/types.ts";
1
+ import { defineTable } from "@morlay/rdbkit";
2
2
 
3
3
  // 会话 × 本地日的活动计数(派生统计表):轮次 / 步骤 / 用户输入 / 工具调用四列直接读,
4
4
  // 不再存事件类型、也不在读取时折。旁路累加、可按会话重建,读侧只读;
5
5
  // 取舍见 ADR-统计衍生表物化归属与汇总。
6
- export const sessionCounts: TableDef = {
6
+ export const sessionCounts = defineTable({
7
7
  name: "t_session_counts",
8
8
  columns: {
9
9
  f_session_id: {
@@ -18,4 +18,4 @@ export const sessionCounts: TableDef = {
18
18
  f_tool_calls: { type: "integer", notNull: true, default: 0 },
19
19
  },
20
20
  uniques: { uq_session_counts_key: { columns: ["f_session_id", "f_day"] } },
21
- };
21
+ });
@@ -1,6 +1,6 @@
1
- import type { TableDef } from "../../adapters/types.ts";
1
+ import { defineTable } from "@morlay/rdbkit";
2
2
 
3
- export const sessionEvents: TableDef = {
3
+ export const sessionEvents = defineTable({
4
4
  name: "t_session_events",
5
5
  columns: {
6
6
  f_id: { type: "serial", primaryKey: true },
@@ -22,4 +22,4 @@ export const sessionEvents: TableDef = {
22
22
  },
23
23
 
24
24
  indexes: { idx_session_events_event_id: { columns: ["f_event_id"] } },
25
- };
25
+ });
@@ -1,6 +1,6 @@
1
- import type { TableDef } from "../../adapters/types.ts";
1
+ import { defineTable } from "@morlay/rdbkit";
2
2
 
3
- export const sessionProjcacheRows: TableDef = {
3
+ export const sessionProjcacheRows = defineTable({
4
4
  name: "t_session_projcache_row",
5
5
  columns: {
6
6
  f_id: { type: "serial", primaryKey: true },
@@ -16,4 +16,4 @@ export const sessionProjcacheRows: TableDef = {
16
16
  },
17
17
  uniques: { uq_session_projcache_row_session_key: { columns: ["f_session_id", "f_key"] } },
18
18
  indexes: { idx_session_projcache_row_key: { columns: ["f_key"] } },
19
- };
19
+ });
@@ -1,9 +1,9 @@
1
- import type { TableDef } from "../../adapters/types.ts";
1
+ import { defineTable } from "@morlay/rdbkit";
2
2
 
3
3
  // 会话 × 本地日 × 模型的 token 汇总(派生统计表):**按会话的行**读它,因此保住
4
4
  // 「fork 子会话含继承前缀」的口径(各会话行之和 ≥ 总量)而不回连事件表。
5
5
  // 旁路累加、可按会话重建,读侧只读;取舍见 ADR-统计衍生表物化归属与汇总。
6
- export const sessionUsage: TableDef = {
6
+ export const sessionUsage = defineTable({
7
7
  name: "t_session_usage",
8
8
  columns: {
9
9
  f_session_id: {
@@ -24,4 +24,4 @@ export const sessionUsage: TableDef = {
24
24
  uniques: {
25
25
  uq_session_usage_key: { columns: ["f_session_id", "f_day", "f_provider", "f_model"] },
26
26
  },
27
- };
27
+ });
@@ -1,6 +1,6 @@
1
- import type { TableDef } from "../../adapters/types.ts";
1
+ import { defineTable } from "@morlay/rdbkit";
2
2
 
3
- export const sessions: TableDef = {
3
+ export const sessions = defineTable({
4
4
  name: "t_sessions",
5
5
  columns: {
6
6
  f_id: { type: "serial", primaryKey: true },
@@ -28,4 +28,4 @@ export const sessions: TableDef = {
28
28
 
29
29
  f_title_seq: { type: "integer" },
30
30
  },
31
- };
31
+ });
@@ -0,0 +1,17 @@
1
+ import { defineTable } from "@morlay/rdbkit";
2
+
3
+ // 所有 storage 域共用这一张表:(域, 表, 键) 一行,值是整份记录文档。域是行的一部分,所以新增域
4
+ // (不论它自带几张表、还是只有 global 槽)都不需要再建表——上游 `KvUnit` 的契约本来就只要求
5
+ // 「按表名读写记录 + 一个 global 单例」,行存储直接承载它。global 单例用 `f_table = ''`。
6
+ export const storageRecords = defineTable({
7
+ name: "t_storage_records",
8
+ columns: {
9
+ f_domain: { type: "text", notNull: true },
10
+ f_table: { type: "text", notNull: true },
11
+ f_key: { type: "text", notNull: true },
12
+ f_value: { type: "text", notNull: true },
13
+ },
14
+ uniques: {
15
+ uq_storage_records_domain_table_key: { columns: ["f_domain", "f_table", "f_key"] },
16
+ },
17
+ });
@@ -1,9 +1,9 @@
1
- import type { TableDef } from "../../adapters/types.ts";
1
+ import { defineTable } from "@morlay/rdbkit";
2
2
 
3
- export const storageUnits: TableDef = {
3
+ export const storageUnits = defineTable({
4
4
  name: "t_storage_units",
5
5
  columns: {
6
6
  f_name: { type: "text", primaryKey: true },
7
7
  f_version: { type: "integer", notNull: true },
8
8
  },
9
- };
9
+ });
@@ -1,50 +1,4 @@
1
1
  import type { SessionEvent } from "@deepseek-ai/dsh-session";
2
- import { toSqliteSchema } from "./adapters/index.ts";
3
- import { sqliteTableDefs } from "./entities/index.ts";
4
-
5
- export const SCHEMA_VERSION = 3;
6
-
7
- export const SESSION_PERSISTENCE_SQLITE_APPLICATION_ID = 0x44534850;
8
-
9
- export const EVENT_ENCODING = "json";
10
-
11
- const sqliteTables: Record<string, any> = toSqliteSchema(sqliteTableDefs);
12
-
13
- export const tPersistenceState = sqliteTables["t_persistence_state"]!;
14
-
15
- export const tSchemaMeta = sqliteTables["t_schema_meta"]!;
16
-
17
- export const tSessions = sqliteTables["t_sessions"]!;
18
-
19
- export const tEvents = sqliteTables["t_events"]!;
20
-
21
- export const tSessionEvents = sqliteTables["t_session_events"]!;
22
-
23
- export const tStorageUnits = sqliteTables["t_storage_units"]!;
24
-
25
- export const tWorkspaces = sqliteTables["t_workspaces"]!;
26
-
27
- export const tWorkspaceSessions = sqliteTables["t_workspace_sessions"]!;
28
-
29
- export const tWorkspaceState = sqliteTables["t_workspace_state"]!;
30
-
31
- export const tScheduleTasks = sqliteTables["t_schedule_tasks"]!;
32
-
33
- export const tSessionProjcacheRows = sqliteTables["t_session_projcache_row"]!;
34
-
35
- export const tEventUsage = sqliteTables["t_event_usage"]!;
36
-
37
- export const tSessionUsage = sqliteTables["t_session_usage"]!;
38
-
39
- export const tSessionCounts = sqliteTables["t_session_counts"]!;
40
-
41
- export type { SessionRow } from "./backend.ts";
42
-
43
- export type { EventRow } from "./backend.ts";
44
-
45
- export type JournalMode = "wal" | "delete" | "truncate" | "persist";
46
-
47
- export const DEFAULT_BUSY_TIMEOUT_MS = 5000;
48
2
 
49
3
  export type EventKind =
50
4
  | "message"
package/src/export.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { strToU8, zip } from "fflate";
2
2
  import type { Context } from "@deepseek-ai/cordis";
3
3
  import type { SessionId } from "@deepseek-ai/dsh-session";
4
- import type { SessionPersistenceRdb } from "./index.ts";
4
+ import type { SessionPersistenceRdb } from "./session-store.ts";
5
5
  import { SESSION_EXPORT_PATH } from "./routes.ts";
6
+ import { mountRoute } from "./http/route.ts";
6
7
 
7
8
  export { SESSION_EXPORT_PATH };
8
9
 
@@ -23,82 +24,35 @@ function zipBytes(files: Record<string, Uint8Array>): Promise<Uint8Array> {
23
24
 
24
25
  // 导出通道:直接把会话日志打成 zip 响应体,与导入通道读同一份 artifact。
25
26
  export function registerSessionExport(ctx: Context, persistence: SessionPersistenceRdb): void {
26
- ctx.inject(["webServer", "connection"] as const, (webCtx) => {
27
- const webServer = webCtx.webServer as unknown as {
28
- register(route: {
29
- kind: "exact";
30
- path: string;
31
- handler: (
32
- req: import("node:http").IncomingMessage,
33
- res: import("node:http").ServerResponse,
34
- ) => void | Promise<void>;
35
- }): () => void;
36
- };
37
- const connection = webCtx.get("connection") as unknown as {
38
- requestRejection(request: {
39
- headers: import("node:http").IncomingHttpHeaders;
40
- }): number | undefined;
41
- };
42
- return webCtx.effect(
43
- () =>
44
- webServer.register({
45
- kind: "exact",
46
- path: SESSION_EXPORT_PATH,
47
- handler: async (req, res) => {
48
- const rejection = connection.requestRejection(req);
49
- if (rejection !== undefined) {
50
- res.writeHead(rejection);
51
- res.end(rejection === 401 ? "unauthorized" : "forbidden");
52
- return;
53
- }
54
- if (req.method !== "POST") {
55
- res.writeHead(405, { "content-type": "application/json" });
56
- res.end(JSON.stringify({ error: "method not allowed" }));
57
- return;
58
- }
59
- const chunks: Buffer[] = [];
60
- for await (const chunk of req) chunks.push(chunk as Buffer);
61
- let envelope: { sessionId?: unknown };
62
- try {
63
- envelope = JSON.parse(Buffer.concat(chunks).toString("utf8")) as {
64
- sessionId?: unknown;
65
- };
66
- } catch {
67
- res.writeHead(400, { "content-type": "application/json" });
68
- res.end(JSON.stringify({ error: "request body is not JSON" }));
69
- return;
70
- }
71
- if (typeof envelope.sessionId !== "string" || envelope.sessionId === "") {
72
- res.writeHead(400, { "content-type": "application/json" });
73
- res.end(JSON.stringify({ error: "missing sessionId field" }));
74
- return;
75
- }
76
- const sessionId = envelope.sessionId;
77
- try {
78
- const raw = await persistence.readRaw(sessionId as SessionId);
79
- if (raw === undefined) {
80
- res.writeHead(404, { "content-type": "application/json" });
81
- res.end(JSON.stringify({ error: `session "${sessionId}" not found` }));
82
- return;
83
- }
84
- const zipFile = await zipBytes({ [raw.filename]: strToU8(raw.content) });
85
- res.writeHead(200, {
86
- "content-type": "application/zip",
87
- "content-length": String(zipFile.byteLength),
88
- "content-disposition": `attachment; filename="${safeFilename(sessionId)}.zip"`,
89
- });
90
- res.end(Buffer.from(zipFile));
91
- } catch (error: unknown) {
92
- res.writeHead(500, { "content-type": "application/json" });
93
- res.end(
94
- JSON.stringify({
95
- error: error instanceof Error ? error.message : "session export failed",
96
- }),
97
- );
98
- }
99
- },
100
- }),
101
- `session-rdb: ${SESSION_EXPORT_PATH} route`,
102
- );
27
+ mountRoute(ctx, SESSION_EXPORT_PATH, async (req, res) => {
28
+ const chunks: Buffer[] = [];
29
+ for await (const chunk of req) chunks.push(chunk as Buffer);
30
+ let envelope: { sessionId?: unknown };
31
+ try {
32
+ envelope = JSON.parse(Buffer.concat(chunks).toString("utf8")) as { sessionId?: unknown };
33
+ } catch {
34
+ res.writeHead(400, { "content-type": "application/json" });
35
+ res.end(JSON.stringify({ error: "request body is not JSON" }));
36
+ return;
37
+ }
38
+ if (typeof envelope.sessionId !== "string" || envelope.sessionId === "") {
39
+ res.writeHead(400, { "content-type": "application/json" });
40
+ res.end(JSON.stringify({ error: "missing sessionId field" }));
41
+ return;
42
+ }
43
+ const sessionId = envelope.sessionId;
44
+ const raw = await persistence.readRaw(sessionId as SessionId);
45
+ if (raw === undefined) {
46
+ res.writeHead(404, { "content-type": "application/json" });
47
+ res.end(JSON.stringify({ error: `session "${sessionId}" not found` }));
48
+ return;
49
+ }
50
+ const zipFile = await zipBytes({ [raw.filename]: strToU8(raw.content) });
51
+ res.writeHead(200, {
52
+ "content-type": "application/zip",
53
+ "content-length": String(zipFile.byteLength),
54
+ "content-disposition": `attachment; filename="${safeFilename(sessionId)}.zip"`,
55
+ });
56
+ res.end(Buffer.from(zipFile));
103
57
  });
104
58
  }