@morlay/session-rdb 0.1.9 → 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 (143) hide show
  1. package/README.md +24 -3
  2. package/dist/artifact.d.mts +118 -3
  3. package/dist/artifact.mjs +5 -3
  4. package/dist/{log-C0q5svm7.d.mts → backend-BKtJ5sO5.d.mts} +189 -291
  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 -3
  9. package/dist/deletion.mjs +2 -2
  10. package/dist/export-CfJQjQfr.mjs +123 -0
  11. package/dist/export.d.mts +1 -3
  12. package/dist/export.mjs +32 -57
  13. package/dist/import.d.mts +1 -3
  14. package/dist/import.mjs +32 -78
  15. package/dist/index-CUD2ZpTA.d.mts +71 -0
  16. package/dist/index.d.mts +20 -2
  17. package/dist/index.mjs +1562 -5
  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 -50
  23. package/dist/storage.mjs +3 -1
  24. package/dist/testing.d.mts +9 -5
  25. package/dist/testing.mjs +27 -8
  26. package/dist/usage-row-BQQM-_t6.mjs +36 -0
  27. package/dist/usage.d.mts +1 -1
  28. package/dist/usage.mjs +8 -42
  29. package/dist/write-guard-CYrY58GM.mjs +174 -0
  30. package/package.json +32 -36
  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} +125 -112
  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 -1630
  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 -272
  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-query.ts +17 -4
  74. package/src/session-store.ts +675 -0
  75. package/src/stats-fold.ts +44 -0
  76. package/src/storage-takeover/index.ts +2 -5
  77. package/src/storage-takeover/legacy-domain-migration.ts +118 -0
  78. package/src/storage-takeover/projection-cache.ts +139 -77
  79. package/src/storage-takeover/read-model.ts +189 -0
  80. package/src/storage-takeover/repository.ts +238 -425
  81. package/src/storage-takeover/storage-backend.ts +47 -149
  82. package/src/storage-takeover/types.ts +45 -14
  83. package/src/storage-takeover/workspace-documents.ts +65 -0
  84. package/src/storage.ts +4 -2
  85. package/src/testing.ts +21 -1
  86. package/src/usage.ts +11 -65
  87. package/src/version.ts +13 -0
  88. package/src/write-path.ts +286 -0
  89. package/dist/branch-DbFW3rJX.mjs +0 -391
  90. package/dist/deletion-ODZFcbZm.mjs +0 -2218
  91. package/dist/gc.d.mts +0 -6
  92. package/dist/gc.mjs +0 -49
  93. package/dist/log-DYxdjJ-l.mjs +0 -562
  94. package/dist/routes-DGBlBE_I.mjs +0 -10
  95. package/dist/sqlite-DjOnMRh2.mjs +0 -1777
  96. package/drizzle/postgres/20260908072805_v2_initial/migration.sql +0 -58
  97. package/drizzle/postgres/20260908072805_v2_initial/snapshot.json +0 -686
  98. package/drizzle/postgres/20260908072806_v3_drop_original_seq/migration.sql +0 -1
  99. package/drizzle/postgres/20260908072806_v3_drop_original_seq/snapshot.json +0 -673
  100. package/drizzle/postgres/20260910120001_v3_storage_tables/migration.sql +0 -65
  101. package/drizzle/postgres/20260910120001_v3_storage_tables/snapshot.json +0 -1183
  102. package/drizzle/postgres/20260910130001_v3_session_title_backfill/migration.sql +0 -10
  103. package/drizzle/postgres/20260910130001_v3_session_title_backfill/snapshot.json +0 -1183
  104. package/drizzle/postgres/20260918120000_v3_event_usage/migration.sql +0 -14
  105. package/drizzle/postgres/20260918120000_v3_event_usage/snapshot.json +0 -1309
  106. package/drizzle/postgres/20260921075900_v3_agent_preset/migration.sql +0 -1
  107. package/drizzle/postgres/20260922090001_v3_pinned_seq/migration.sql +0 -2
  108. package/drizzle/postgres/20260922093001_v3_last_event_at/migration.sql +0 -10
  109. package/drizzle/postgres/20260923120000_v3_usage_materialized/migration.sql +0 -48
  110. package/drizzle/postgres/20261008103001_v3_schedule_tasks/migration.sql +0 -11
  111. package/drizzle/sqlite/20260908072751_v2_initial/migration.sql +0 -53
  112. package/drizzle/sqlite/20260908072751_v2_initial/snapshot.json +0 -492
  113. package/drizzle/sqlite/20260908072752_v3_drop_original_seq/migration.sql +0 -6
  114. package/drizzle/sqlite/20260908072752_v3_drop_original_seq/snapshot.json +0 -513
  115. package/drizzle/sqlite/20260910120000_v3_storage_tables/migration.sql +0 -66
  116. package/drizzle/sqlite/20260910120000_v3_storage_tables/snapshot.json +0 -905
  117. package/drizzle/sqlite/20260910130000_v3_session_title_backfill/migration.sql +0 -13
  118. package/drizzle/sqlite/20260910130000_v3_session_title_backfill/snapshot.json +0 -905
  119. package/drizzle/sqlite/20260918120000_v3_event_usage/migration.sql +0 -14
  120. package/drizzle/sqlite/20260918120000_v3_event_usage/snapshot.json +0 -1031
  121. package/drizzle/sqlite/20260921075855_v3_agent_preset/migration.sql +0 -7
  122. package/drizzle/sqlite/20260921075855_v3_agent_preset/snapshot.json +0 -1041
  123. package/drizzle/sqlite/20260922090000_v3_pinned_seq/migration.sql +0 -4
  124. package/drizzle/sqlite/20260922093000_v3_last_event_at/migration.sql +0 -13
  125. package/drizzle/sqlite/20260923120000_v3_usage_materialized/migration.sql +0 -48
  126. package/drizzle/sqlite/20261008103000_v3_schedule_tasks/migration.sql +0 -14
  127. package/src/adapters/index.ts +0 -12
  128. package/src/adapters/to-postgres.ts +0 -93
  129. package/src/adapters/to-sqlite.ts +0 -83
  130. package/src/adapters/types.ts +0 -44
  131. package/src/drizzle/postgres-v2.ts +0 -10
  132. package/src/drizzle/postgres-v3.ts +0 -18
  133. package/src/drizzle/sqlite-v2.ts +0 -9
  134. package/src/drizzle/sqlite-v3.ts +0 -18
  135. package/src/entities/v2/index.ts +0 -20
  136. package/src/entities/v2/session-events.ts +0 -10
  137. package/src/entities/v3/schedule-tasks.ts +0 -16
  138. package/src/entities/v3/workspace-sessions.ts +0 -19
  139. package/src/entities/v3/workspace-state.ts +0 -12
  140. package/src/entities/v3/workspaces.ts +0 -14
  141. package/src/gc.ts +0 -77
  142. package/src/postgres.ts +0 -1015
  143. package/src/sqlite.ts +0 -1086
@@ -0,0 +1,189 @@
1
+ import type { Database } from "@morlay/rdbkit";
2
+ import {
3
+ and,
4
+ E,
5
+ eq,
6
+ gte,
7
+ isNull,
8
+ lt,
9
+ notInSubquery,
10
+ or,
11
+ type Condition,
12
+ type ExprOperand,
13
+ } from "@morlay/rdbkit";
14
+ import type { EventRow, ReadModel, SessionRow } from "../backend.ts";
15
+ import { events, sessionEvents, sessions } from "../entities/index.ts";
16
+
17
+ export type { ReadModel };
18
+
19
+ export function createReadModel(database: Database): ReadModel {
20
+ const sessionsTable = sessions.table(database);
21
+ const eventsTable = events.table(database);
22
+ const links = sessionEvents.table(database);
23
+
24
+ return {
25
+ async getSession(id) {
26
+ for await (const row of sessionsTable.select().where(eq(sessionsTable.f_session_id, id))) {
27
+ return sessionRowOf(row);
28
+ }
29
+ return undefined;
30
+ },
31
+
32
+ async getEventRows(id, fromSequence) {
33
+ const rows: EventRow[] = [];
34
+ const condition =
35
+ fromSequence === undefined
36
+ ? eq(links.f_session_id, id)
37
+ : and(eq(links.f_session_id, id), gte(links.f_sequence, fromSequence));
38
+ for await (const row of links
39
+ .select({
40
+ fEventId: links.f_event_id,
41
+ fSequence: links.f_sequence,
42
+ fType: eventsTable.f_type,
43
+ fKind: eventsTable.f_kind,
44
+ fRole: eventsTable.f_role,
45
+ fName: eventsTable.f_name,
46
+ fActionId: eventsTable.f_action_id,
47
+ fCreatedAt: eventsTable.f_created_at,
48
+ fData: eventsTable.f_data,
49
+ fSurfaceOp: links.f_surface_op,
50
+ })
51
+ .join(events, eq(eventsTable.f_event_id, links.f_event_id))
52
+ .where(condition)
53
+ .orderBy("f_sequence")) {
54
+ rows.push(eventRowOf(row));
55
+ }
56
+ return rows;
57
+ },
58
+
59
+ async getEventTypeAt(id, sequence) {
60
+ for await (const row of links
61
+ .select({ fType: eventsTable.f_type })
62
+ .join(events, eq(eventsTable.f_event_id, links.f_event_id))
63
+ .where(and(eq(links.f_session_id, id), eq(links.f_sequence, sequence)))
64
+ .limit(1)) {
65
+ return row.fType;
66
+ }
67
+ return undefined;
68
+ },
69
+
70
+ async getEventTypesBefore(id, beforeSequence, limit) {
71
+ const rows: Array<Pick<EventRow, "fSequence" | "fType">> = [];
72
+ for await (const row of links
73
+ .select({ fSequence: links.f_sequence, fType: eventsTable.f_type })
74
+ .join(events, eq(eventsTable.f_event_id, links.f_event_id))
75
+ .where(and(eq(links.f_session_id, id), lt(links.f_sequence, beforeSequence)))
76
+ .orderBy("f_sequence", "desc")
77
+ .limit(limit)) {
78
+ rows.push({ fSequence: Number(row.fSequence), fType: row.fType });
79
+ }
80
+ return rows;
81
+ },
82
+
83
+ async listSessions() {
84
+ const rows: SessionRow[] = [];
85
+ for await (const row of sessionsTable.select()) rows.push(sessionRowOf(row));
86
+ return rows;
87
+ },
88
+
89
+ async latestTitleEvent(id) {
90
+ for await (const row of links
91
+ .select({ fSequence: links.f_sequence, fData: eventsTable.f_data })
92
+ .join(events, eq(eventsTable.f_event_id, links.f_event_id))
93
+ .where(and(eq(links.f_session_id, id), eq(eventsTable.f_type, "session/title")))
94
+ .orderBy("f_sequence", "desc")
95
+ .limit(1)) {
96
+ return { fSequence: Number(row.fSequence), fData: row.fData };
97
+ }
98
+ return undefined;
99
+ },
100
+
101
+ async listOrphanSubagentSessions() {
102
+ const ids: string[] = [];
103
+ for await (const row of sessionsTable
104
+ .select({ id: sessionsTable.f_session_id })
105
+ .where(
106
+ and(
107
+ eq(sessionsTable.f_origin, "subagent"),
108
+ or(
109
+ isNull(sessionsTable.f_parent_session),
110
+ notInSubquery(
111
+ sessionsTable.f_parent_session,
112
+ sessionsTable.select({ id: sessionsTable.f_session_id }).toFragment(),
113
+ ),
114
+ ),
115
+ ),
116
+ )) {
117
+ ids.push(row.id);
118
+ }
119
+ return ids;
120
+ },
121
+ };
122
+ }
123
+
124
+ /** `f_last_event_at` 的「只增不减」(两方言同一份表达式,值走绑定)。 */
125
+ export function lastEventAtExpr(value: number): ExprOperand<number> {
126
+ return E.maxOf(E.column("f_last_event_at"), value);
127
+ }
128
+
129
+ /** header 的「变了才写」条件:逐列 `IS DISTINCT FROM` 的 OR(值全部走绑定参数)。 */
130
+ export function headerChangedCondition(
131
+ header: Readonly<Record<string, string | number | null>>,
132
+ ): Condition {
133
+ return E.or(
134
+ ...Object.entries(header).map(([name, value]) =>
135
+ E.isDistinctFrom(E.column(name, "t_sessions"), value),
136
+ ),
137
+ );
138
+ }
139
+
140
+ /**
141
+ * 事件行的数值列统一收回 number:`f_created_at` 在表定义里是 `bigint`(rdbkit 读回 BigInt),
142
+ * 事件坐标与毫秒时间都在安全整数范围内。
143
+ */
144
+ function eventRowOf(row: {
145
+ fEventId: string;
146
+ fSequence: number | bigint;
147
+ fType: string;
148
+ fKind: string;
149
+ fRole: string;
150
+ fName: string;
151
+ fActionId: string;
152
+ fCreatedAt: number | bigint;
153
+ fData: string;
154
+ fSurfaceOp: string | null;
155
+ }): EventRow {
156
+ return {
157
+ fEventId: row.fEventId,
158
+ fSequence: Number(row.fSequence),
159
+ fType: row.fType,
160
+ fKind: row.fKind,
161
+ fRole: row.fRole,
162
+ fName: row.fName,
163
+ fActionId: row.fActionId,
164
+ fCreatedAt: Number(row.fCreatedAt),
165
+ fData: row.fData,
166
+ fSurfaceOp: row.fSurfaceOp,
167
+ };
168
+ }
169
+
170
+ /** 列名原样 → 会话行的 camelCase(列名由表定义固定,这里是唯一一处映射)。 */
171
+ export function sessionRowOf(row: Record<string, unknown>): SessionRow { return {
172
+ fSessionId: String(row["f_session_id"]),
173
+ fHeadEventId: String(row["f_head_event_id"]),
174
+ fHeadSequence: Number(row["f_head_sequence"]),
175
+ fVersion: Number(row["f_version"]),
176
+ fCreatedAt: Number(row["f_created_at"]),
177
+ fCwd: (row["f_cwd"] as string | null) ?? null,
178
+ fParentSession: (row["f_parent_session"] as string | null) ?? null,
179
+ fSeedLength: row["f_seed_length"] === null ? null : Number(row["f_seed_length"]),
180
+ fOrigin: (row["f_origin"] as string | null) ?? null,
181
+ fDelegationDepth: row["f_delegation_depth"] === null ? null : Number(row["f_delegation_depth"]),
182
+ fAgentPreset: (row["f_agent_preset"] as string | null) ?? null,
183
+ fIncarnation: String(row["f_incarnation"]),
184
+ fRevision: Number(row["f_revision"]),
185
+ fArchivedAt: row["f_archived_at"] === null ? null : Number(row["f_archived_at"]),
186
+ fPinnedSeq: row["f_pinned_seq"] === null ? null : Number(row["f_pinned_seq"]),
187
+ fLastEventAt: row["f_last_event_at"] === null ? null : Number(row["f_last_event_at"]),
188
+ };
189
+ }