@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.
- package/README.md +24 -3
- package/dist/artifact.d.mts +118 -3
- package/dist/artifact.mjs +5 -3
- package/dist/{log-C0q5svm7.d.mts → backend-BKtJ5sO5.d.mts} +189 -291
- package/dist/backend-rdb-BDCntVDy.mjs +1341 -0
- package/dist/branch-CG1PUlO6.mjs +833 -0
- package/dist/deletion-SSX7IqU8.mjs +35 -0
- package/dist/deletion.d.mts +1 -3
- package/dist/deletion.mjs +2 -2
- package/dist/export-CfJQjQfr.mjs +123 -0
- package/dist/export.d.mts +1 -3
- package/dist/export.mjs +32 -57
- package/dist/import.d.mts +1 -3
- package/dist/import.mjs +32 -78
- package/dist/index-CUD2ZpTA.d.mts +71 -0
- package/dist/index.d.mts +20 -2
- package/dist/index.mjs +1562 -5
- package/dist/open-YoyD_kah.mjs +561 -0
- package/dist/organize.d.mts +9 -0
- package/dist/organize.mjs +30 -0
- package/dist/route-DpfY0zq-.mjs +114 -0
- package/dist/storage.d.mts +41 -50
- package/dist/storage.mjs +3 -1
- package/dist/testing.d.mts +9 -5
- package/dist/testing.mjs +27 -8
- package/dist/usage-row-BQQM-_t6.mjs +36 -0
- package/dist/usage.d.mts +1 -1
- package/dist/usage.mjs +8 -42
- package/dist/write-guard-CYrY58GM.mjs +174 -0
- package/package.json +32 -36
- package/src/artifact.ts +4 -1
- package/src/backend-rdb.ts +331 -0
- package/src/backend.ts +32 -15
- package/src/{branch.ts → branch/index.ts} +125 -112
- package/src/branch/port.ts +62 -0
- package/src/branch/semantics.ts +69 -0
- package/src/db/open.ts +180 -0
- package/src/db/stats.ts +449 -0
- package/src/deletion-error.ts +17 -0
- package/src/deletion.ts +19 -72
- package/src/entities/index.ts +16 -1
- package/src/entities/v3/event-usage.ts +3 -3
- package/src/entities/v3/events.ts +3 -3
- package/src/entities/v3/index.ts +4 -16
- package/src/entities/v3/persistence-state.ts +3 -3
- package/src/entities/v3/schema-meta.ts +3 -3
- package/src/entities/v3/session-counts.ts +3 -3
- package/src/entities/v3/session-events.ts +3 -3
- package/src/entities/v3/session-projcache-rows.ts +3 -3
- package/src/entities/v3/session-usage.ts +3 -3
- package/src/entities/v3/sessions.ts +3 -3
- package/src/entities/v3/storage-records.ts +17 -0
- package/src/entities/v3/storage-units.ts +3 -3
- package/src/{schema.ts → event-shape.ts} +0 -46
- package/src/export.ts +32 -78
- package/src/handles.ts +349 -0
- package/src/http/route.ts +178 -0
- package/src/import-storages.ts +5 -2
- package/src/import.ts +63 -125
- package/src/index.ts +15 -1630
- package/src/legacy.ts +3 -1
- package/src/live-routing.ts +205 -0
- package/src/log/export.ts +84 -0
- package/src/{log.ts → log/repair.ts} +1 -272
- package/src/log/rows.ts +107 -0
- package/src/log/usage-row.ts +64 -0
- package/src/migrations.ts +196 -0
- package/src/organize.ts +38 -0
- package/src/read-path.ts +190 -0
- package/src/routes.ts +2 -1
- package/src/rows.ts +25 -77
- package/src/session-ops.ts +444 -0
- package/src/session-query.ts +17 -4
- package/src/session-store.ts +675 -0
- package/src/stats-fold.ts +44 -0
- package/src/storage-takeover/index.ts +2 -5
- package/src/storage-takeover/legacy-domain-migration.ts +118 -0
- package/src/storage-takeover/projection-cache.ts +139 -77
- package/src/storage-takeover/read-model.ts +189 -0
- package/src/storage-takeover/repository.ts +238 -425
- package/src/storage-takeover/storage-backend.ts +47 -149
- package/src/storage-takeover/types.ts +45 -14
- package/src/storage-takeover/workspace-documents.ts +65 -0
- package/src/storage.ts +4 -2
- package/src/testing.ts +21 -1
- package/src/usage.ts +11 -65
- package/src/version.ts +13 -0
- package/src/write-path.ts +286 -0
- package/dist/branch-DbFW3rJX.mjs +0 -391
- package/dist/deletion-ODZFcbZm.mjs +0 -2218
- package/dist/gc.d.mts +0 -6
- package/dist/gc.mjs +0 -49
- package/dist/log-DYxdjJ-l.mjs +0 -562
- package/dist/routes-DGBlBE_I.mjs +0 -10
- package/dist/sqlite-DjOnMRh2.mjs +0 -1777
- package/drizzle/postgres/20260908072805_v2_initial/migration.sql +0 -58
- package/drizzle/postgres/20260908072805_v2_initial/snapshot.json +0 -686
- package/drizzle/postgres/20260908072806_v3_drop_original_seq/migration.sql +0 -1
- package/drizzle/postgres/20260908072806_v3_drop_original_seq/snapshot.json +0 -673
- package/drizzle/postgres/20260910120001_v3_storage_tables/migration.sql +0 -65
- package/drizzle/postgres/20260910120001_v3_storage_tables/snapshot.json +0 -1183
- package/drizzle/postgres/20260910130001_v3_session_title_backfill/migration.sql +0 -10
- package/drizzle/postgres/20260910130001_v3_session_title_backfill/snapshot.json +0 -1183
- package/drizzle/postgres/20260918120000_v3_event_usage/migration.sql +0 -14
- package/drizzle/postgres/20260918120000_v3_event_usage/snapshot.json +0 -1309
- package/drizzle/postgres/20260921075900_v3_agent_preset/migration.sql +0 -1
- package/drizzle/postgres/20260922090001_v3_pinned_seq/migration.sql +0 -2
- package/drizzle/postgres/20260922093001_v3_last_event_at/migration.sql +0 -10
- package/drizzle/postgres/20260923120000_v3_usage_materialized/migration.sql +0 -48
- package/drizzle/postgres/20261008103001_v3_schedule_tasks/migration.sql +0 -11
- package/drizzle/sqlite/20260908072751_v2_initial/migration.sql +0 -53
- package/drizzle/sqlite/20260908072751_v2_initial/snapshot.json +0 -492
- package/drizzle/sqlite/20260908072752_v3_drop_original_seq/migration.sql +0 -6
- package/drizzle/sqlite/20260908072752_v3_drop_original_seq/snapshot.json +0 -513
- package/drizzle/sqlite/20260910120000_v3_storage_tables/migration.sql +0 -66
- package/drizzle/sqlite/20260910120000_v3_storage_tables/snapshot.json +0 -905
- package/drizzle/sqlite/20260910130000_v3_session_title_backfill/migration.sql +0 -13
- package/drizzle/sqlite/20260910130000_v3_session_title_backfill/snapshot.json +0 -905
- package/drizzle/sqlite/20260918120000_v3_event_usage/migration.sql +0 -14
- package/drizzle/sqlite/20260918120000_v3_event_usage/snapshot.json +0 -1031
- package/drizzle/sqlite/20260921075855_v3_agent_preset/migration.sql +0 -7
- package/drizzle/sqlite/20260921075855_v3_agent_preset/snapshot.json +0 -1041
- package/drizzle/sqlite/20260922090000_v3_pinned_seq/migration.sql +0 -4
- package/drizzle/sqlite/20260922093000_v3_last_event_at/migration.sql +0 -13
- package/drizzle/sqlite/20260923120000_v3_usage_materialized/migration.sql +0 -48
- package/drizzle/sqlite/20261008103000_v3_schedule_tasks/migration.sql +0 -14
- package/src/adapters/index.ts +0 -12
- package/src/adapters/to-postgres.ts +0 -93
- package/src/adapters/to-sqlite.ts +0 -83
- package/src/adapters/types.ts +0 -44
- package/src/drizzle/postgres-v2.ts +0 -10
- package/src/drizzle/postgres-v3.ts +0 -18
- package/src/drizzle/sqlite-v2.ts +0 -9
- package/src/drizzle/sqlite-v3.ts +0 -18
- package/src/entities/v2/index.ts +0 -20
- package/src/entities/v2/session-events.ts +0 -10
- package/src/entities/v3/schedule-tasks.ts +0 -16
- package/src/entities/v3/workspace-sessions.ts +0 -19
- package/src/entities/v3/workspace-state.ts +0 -12
- package/src/entities/v3/workspaces.ts +0 -14
- package/src/gc.ts +0 -77
- package/src/postgres.ts +0 -1015
- 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
|
+
}
|