@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
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
-- 「最后活动时间」物化到会话行:管理面的会话列表要按它排序 + 分页,原先每行一次「该会话最后事件时间」的
|
|
2
|
-
-- 相关子查询(真实库 243 行 = 4.2s)在分页下也救不了——排序要求全表先把值算出来。加列后排序与分页都只
|
|
3
|
-
-- 碰 t_sessions(毫秒级),写路径负责维护;这里一次性回填,没有事件的会话留 NULL(读时回落 createdAt)。
|
|
4
|
-
-- 类型写 `integer`(不是 `bigint`):STRICT 表只认固定类型名,`bigint` 会被拒。
|
|
5
|
-
ALTER TABLE `t_sessions` ADD `f_last_event_at` integer;
|
|
6
|
-
--> statement-breakpoint
|
|
7
|
-
UPDATE `t_sessions`
|
|
8
|
-
SET `f_last_event_at` = (
|
|
9
|
-
SELECT MAX(e.f_created_at)
|
|
10
|
-
FROM t_session_events se
|
|
11
|
-
JOIN t_events e ON e.f_event_id = se.f_event_id
|
|
12
|
-
WHERE se.f_session_id = t_sessions.f_session_id
|
|
13
|
-
);
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
-- 统计衍生表:纯派生数据(打开库时按事件表全量回填),迁移直接先删后建,
|
|
2
|
-
-- 不做 ALTER / 数据搬迁。结构与取舍见 ADR-统计衍生表物化归属与汇总。
|
|
3
|
-
DROP TABLE IF EXISTS `t_event_usage`;--> statement-breakpoint
|
|
4
|
-
DROP TABLE IF EXISTS `t_event_counts`;--> statement-breakpoint
|
|
5
|
-
DROP TABLE IF EXISTS `t_session_usage`;--> statement-breakpoint
|
|
6
|
-
DROP TABLE IF EXISTS `t_session_counts`;--> statement-breakpoint
|
|
7
|
-
CREATE TABLE `t_event_usage` (
|
|
8
|
-
`f_event_id` text PRIMARY KEY NOT NULL,
|
|
9
|
-
`f_created_at` bigint NOT NULL,
|
|
10
|
-
`f_day` text NOT NULL,
|
|
11
|
-
`f_provider` text,
|
|
12
|
-
`f_model` text,
|
|
13
|
-
`f_referenced` integer DEFAULT 0 NOT NULL,
|
|
14
|
-
`f_subagent` integer DEFAULT 0 NOT NULL,
|
|
15
|
-
`f_input_tokens` integer DEFAULT 0 NOT NULL,
|
|
16
|
-
`f_output_tokens` integer DEFAULT 0 NOT NULL,
|
|
17
|
-
`f_cache_read_tokens` integer DEFAULT 0 NOT NULL,
|
|
18
|
-
`f_reasoning_tokens` integer DEFAULT 0 NOT NULL,
|
|
19
|
-
`f_total_tokens` integer DEFAULT 0 NOT NULL,
|
|
20
|
-
CONSTRAINT `fk_t_event_usage_f_event_id_t_events_f_event_id_fk` FOREIGN KEY (`f_event_id`) REFERENCES `t_events`(`f_event_id`) ON DELETE CASCADE
|
|
21
|
-
);
|
|
22
|
-
--> statement-breakpoint
|
|
23
|
-
CREATE INDEX `idx_event_usage_created_at` ON `t_event_usage` (`f_created_at`);--> statement-breakpoint
|
|
24
|
-
CREATE TABLE `t_session_usage` (
|
|
25
|
-
`f_session_id` text NOT NULL,
|
|
26
|
-
`f_day` text NOT NULL,
|
|
27
|
-
`f_provider` text DEFAULT '' NOT NULL,
|
|
28
|
-
`f_model` text DEFAULT '' NOT NULL,
|
|
29
|
-
`f_input_tokens` integer DEFAULT 0 NOT NULL,
|
|
30
|
-
`f_output_tokens` integer DEFAULT 0 NOT NULL,
|
|
31
|
-
`f_cache_read_tokens` integer DEFAULT 0 NOT NULL,
|
|
32
|
-
`f_reasoning_tokens` integer DEFAULT 0 NOT NULL,
|
|
33
|
-
`f_total_tokens` integer DEFAULT 0 NOT NULL,
|
|
34
|
-
CONSTRAINT `fk_t_session_usage_f_session_id_t_sessions_f_session_id_fk` FOREIGN KEY (`f_session_id`) REFERENCES `t_sessions`(`f_session_id`) ON DELETE CASCADE
|
|
35
|
-
);
|
|
36
|
-
--> statement-breakpoint
|
|
37
|
-
CREATE UNIQUE INDEX `uq_session_usage_key` ON `t_session_usage` (`f_session_id`,`f_day`,`f_provider`,`f_model`);--> statement-breakpoint
|
|
38
|
-
CREATE TABLE `t_session_counts` (
|
|
39
|
-
`f_session_id` text NOT NULL,
|
|
40
|
-
`f_day` text NOT NULL,
|
|
41
|
-
`f_turns` integer DEFAULT 0 NOT NULL,
|
|
42
|
-
`f_steps` integer DEFAULT 0 NOT NULL,
|
|
43
|
-
`f_user_inputs` integer DEFAULT 0 NOT NULL,
|
|
44
|
-
`f_tool_calls` integer DEFAULT 0 NOT NULL,
|
|
45
|
-
CONSTRAINT `fk_t_session_counts_f_session_id_t_sessions_f_session_id_fk` FOREIGN KEY (`f_session_id`) REFERENCES `t_sessions`(`f_session_id`) ON DELETE CASCADE
|
|
46
|
-
);
|
|
47
|
-
--> statement-breakpoint
|
|
48
|
-
CREATE UNIQUE INDEX `uq_session_counts_key` ON `t_session_counts` (`f_session_id`,`f_day`);
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
-- 官方 `schedule` 域(`dsh-schedule` 的 `tasks` 表)落进本库:web-app 在每份 profile 里挂那一行,
|
|
2
|
-
-- 而 `storage-domain` 的 backend 路由指向 rdb——一个提醒一行,归属会话与状态是列,记录与投递回执存 JSON。
|
|
3
|
-
-- 手写迁移(生成器产不出可用 diff,见 `.agents/debts/20260921-drizzle生成器与实体定义对不上.md`):
|
|
4
|
-
-- 本文件只含这次的真实改动,没有需要说明的略过段。
|
|
5
|
-
CREATE TABLE `t_schedule_tasks` (
|
|
6
|
-
`f_id` text PRIMARY KEY,
|
|
7
|
-
`f_session_id` text NOT NULL,
|
|
8
|
-
`f_status` text NOT NULL,
|
|
9
|
-
`f_record` text NOT NULL,
|
|
10
|
-
`f_last_delivery` text,
|
|
11
|
-
`f_delivery_history` text
|
|
12
|
-
);
|
|
13
|
-
--> statement-breakpoint
|
|
14
|
-
CREATE INDEX `idx_schedule_tasks_session_id` ON `t_schedule_tasks` (`f_session_id`);
|
package/src/adapters/index.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export { toSqliteSchema } from "./to-sqlite.ts";
|
|
2
|
-
export { toPostgresSchema } from "./to-postgres.ts";
|
|
3
|
-
export type {
|
|
4
|
-
ColumnDef,
|
|
5
|
-
TableDef,
|
|
6
|
-
CheckDef,
|
|
7
|
-
UniqueDef,
|
|
8
|
-
IndexDef,
|
|
9
|
-
ColumnTypeName,
|
|
10
|
-
DeleteAction,
|
|
11
|
-
} from "./types.ts";
|
|
12
|
-
export { toProperty } from "./types.ts";
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { sql } from "drizzle-orm";
|
|
2
|
-
import {
|
|
3
|
-
bigint,
|
|
4
|
-
check as pgCheck,
|
|
5
|
-
index,
|
|
6
|
-
integer,
|
|
7
|
-
pgSchema,
|
|
8
|
-
pgTable,
|
|
9
|
-
serial,
|
|
10
|
-
text,
|
|
11
|
-
unique,
|
|
12
|
-
type AnyPgColumn,
|
|
13
|
-
type AnyPgColumnBuilder,
|
|
14
|
-
type AnyPgTable,
|
|
15
|
-
} from "drizzle-orm/pg-core";
|
|
16
|
-
import { toProperty, type ColumnDef, type TableDef } from "./types.ts";
|
|
17
|
-
|
|
18
|
-
type TableRegistry = Record<string, AnyPgTable>;
|
|
19
|
-
|
|
20
|
-
function buildColumn(name: string, c: ColumnDef, tables: TableRegistry): AnyPgColumnBuilder {
|
|
21
|
-
let col: any;
|
|
22
|
-
switch (c.type) {
|
|
23
|
-
case "text": {
|
|
24
|
-
const built = text(name);
|
|
25
|
-
col = c.primaryKey ? built.primaryKey() : built;
|
|
26
|
-
break;
|
|
27
|
-
}
|
|
28
|
-
case "serial":
|
|
29
|
-
col = serial(name).primaryKey();
|
|
30
|
-
break;
|
|
31
|
-
case "integer": {
|
|
32
|
-
const built = integer(name);
|
|
33
|
-
col = c.primaryKey ? built.primaryKey() : built;
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
case "bigint": {
|
|
37
|
-
const built = bigint(name, { mode: "number" });
|
|
38
|
-
col = c.primaryKey ? built.primaryKey() : built;
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
if (c.notNull) col = col.notNull();
|
|
43
|
-
if (c.default !== undefined) col = col.default(c.default);
|
|
44
|
-
if (c.unique) col = col.unique();
|
|
45
|
-
if (c.references) {
|
|
46
|
-
const { table, column, onDelete } = c.references;
|
|
47
|
-
col = col.references(
|
|
48
|
-
() => (tables[table] as unknown as Record<string, AnyPgColumn>)[toProperty(column)],
|
|
49
|
-
{ onDelete },
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
return col;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function toPostgresSchema(
|
|
56
|
-
defs: readonly TableDef[],
|
|
57
|
-
schemaName = "public",
|
|
58
|
-
): Record<string, AnyPgTable> {
|
|
59
|
-
const tables: TableRegistry = {};
|
|
60
|
-
|
|
61
|
-
const table = schemaName === "public" ? pgTable : pgSchema(schemaName).table;
|
|
62
|
-
for (const def of defs) {
|
|
63
|
-
const columns: Record<string, AnyPgColumnBuilder> = {};
|
|
64
|
-
for (const [name, c] of Object.entries(def.columns)) {
|
|
65
|
-
columns[toProperty(name)] = buildColumn(name, c, tables);
|
|
66
|
-
}
|
|
67
|
-
const extra = (self: Record<string, unknown>) => [
|
|
68
|
-
...Object.entries(def.checks ?? {}).map(([name, c]) => pgCheck(name, sql.raw(c.expression))),
|
|
69
|
-
...Object.entries(def.uniques ?? {}).map(([name, u]) =>
|
|
70
|
-
unique(name).on(
|
|
71
|
-
...(u.columns.map((n) => self[toProperty(n)] as AnyPgColumn) as [
|
|
72
|
-
AnyPgColumn,
|
|
73
|
-
...AnyPgColumn[],
|
|
74
|
-
]),
|
|
75
|
-
),
|
|
76
|
-
),
|
|
77
|
-
...Object.entries(def.indexes ?? {}).map(([name, i]) =>
|
|
78
|
-
index(name).on(
|
|
79
|
-
...(i.columns.map((n) => self[toProperty(n)] as AnyPgColumn) as [
|
|
80
|
-
AnyPgColumn,
|
|
81
|
-
...AnyPgColumn[],
|
|
82
|
-
]),
|
|
83
|
-
),
|
|
84
|
-
),
|
|
85
|
-
];
|
|
86
|
-
tables[def.name] = (table as typeof pgTable)(
|
|
87
|
-
def.name,
|
|
88
|
-
columns as Record<string, AnyPgColumnBuilder>,
|
|
89
|
-
extra as never,
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
return tables;
|
|
93
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { sql } from "drizzle-orm";
|
|
2
|
-
import {
|
|
3
|
-
check as sqliteCheck,
|
|
4
|
-
index,
|
|
5
|
-
integer,
|
|
6
|
-
sqliteTable,
|
|
7
|
-
text,
|
|
8
|
-
unique,
|
|
9
|
-
type AnySQLiteColumn,
|
|
10
|
-
type AnySQLiteTable,
|
|
11
|
-
type SQLiteColumnBuilder,
|
|
12
|
-
} from "drizzle-orm/sqlite-core";
|
|
13
|
-
import { toProperty, type ColumnDef, type TableDef } from "./types.ts";
|
|
14
|
-
|
|
15
|
-
type TableRegistry = Record<string, AnySQLiteTable>;
|
|
16
|
-
|
|
17
|
-
function buildColumn(name: string, c: ColumnDef, tables: TableRegistry): SQLiteColumnBuilder {
|
|
18
|
-
let col: any;
|
|
19
|
-
switch (c.type) {
|
|
20
|
-
case "text": {
|
|
21
|
-
const built = text(name);
|
|
22
|
-
col = c.primaryKey ? built.primaryKey() : built;
|
|
23
|
-
break;
|
|
24
|
-
}
|
|
25
|
-
case "serial":
|
|
26
|
-
col = integer(name).primaryKey({ autoIncrement: true });
|
|
27
|
-
break;
|
|
28
|
-
case "integer":
|
|
29
|
-
case "bigint": {
|
|
30
|
-
const built = integer(name);
|
|
31
|
-
col = c.primaryKey ? built.primaryKey() : built;
|
|
32
|
-
break;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
if (c.notNull) col = col.notNull();
|
|
36
|
-
if (c.default !== undefined) col = col.default(c.default);
|
|
37
|
-
if (c.unique) col = col.unique();
|
|
38
|
-
if (c.references) {
|
|
39
|
-
const { table, column, onDelete } = c.references;
|
|
40
|
-
col = col.references(
|
|
41
|
-
() => (tables[table] as unknown as Record<string, AnySQLiteColumn>)[toProperty(column)],
|
|
42
|
-
{ onDelete },
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
return col as SQLiteColumnBuilder;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function toSqliteSchema(defs: readonly TableDef[]): Record<string, AnySQLiteTable> {
|
|
49
|
-
const tables: TableRegistry = {};
|
|
50
|
-
for (const def of defs) {
|
|
51
|
-
const columns: Record<string, SQLiteColumnBuilder> = {};
|
|
52
|
-
for (const [name, c] of Object.entries(def.columns)) {
|
|
53
|
-
columns[toProperty(name)] = buildColumn(name, c, tables);
|
|
54
|
-
}
|
|
55
|
-
const extra = (self: Record<string, unknown>) => [
|
|
56
|
-
...Object.entries(def.checks ?? {}).map(([name, c]) =>
|
|
57
|
-
sqliteCheck(name, sql.raw(c.expression)),
|
|
58
|
-
),
|
|
59
|
-
...Object.entries(def.uniques ?? {}).map(([name, u]) =>
|
|
60
|
-
unique(name).on(
|
|
61
|
-
...(u.columns.map((n) => self[toProperty(n)] as AnySQLiteColumn) as [
|
|
62
|
-
AnySQLiteColumn,
|
|
63
|
-
...AnySQLiteColumn[],
|
|
64
|
-
]),
|
|
65
|
-
),
|
|
66
|
-
),
|
|
67
|
-
...Object.entries(def.indexes ?? {}).map(([name, i]) =>
|
|
68
|
-
index(name).on(
|
|
69
|
-
...(i.columns.map((n) => self[toProperty(n)] as AnySQLiteColumn) as [
|
|
70
|
-
AnySQLiteColumn,
|
|
71
|
-
...AnySQLiteColumn[],
|
|
72
|
-
]),
|
|
73
|
-
),
|
|
74
|
-
),
|
|
75
|
-
];
|
|
76
|
-
tables[def.name] = sqliteTable(
|
|
77
|
-
def.name,
|
|
78
|
-
columns as Record<string, SQLiteColumnBuilder>,
|
|
79
|
-
extra as never,
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
return tables;
|
|
83
|
-
}
|
package/src/adapters/types.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
export type ColumnTypeName = "serial" | "integer" | "bigint" | "text";
|
|
2
|
-
|
|
3
|
-
export type DeleteAction = "cascade" | "set null" | "restrict" | "no action";
|
|
4
|
-
|
|
5
|
-
export interface ColumnDef {
|
|
6
|
-
type: ColumnTypeName;
|
|
7
|
-
notNull?: boolean;
|
|
8
|
-
|
|
9
|
-
primaryKey?: boolean;
|
|
10
|
-
|
|
11
|
-
default?: string | number;
|
|
12
|
-
|
|
13
|
-
unique?: boolean;
|
|
14
|
-
|
|
15
|
-
references?: {
|
|
16
|
-
table: string;
|
|
17
|
-
column: string;
|
|
18
|
-
onDelete?: DeleteAction;
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface CheckDef {
|
|
23
|
-
expression: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface UniqueDef {
|
|
27
|
-
columns: string[];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface IndexDef {
|
|
31
|
-
columns: string[];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface TableDef {
|
|
35
|
-
name: string;
|
|
36
|
-
columns: Record<string, ColumnDef>;
|
|
37
|
-
checks?: Record<string, CheckDef>;
|
|
38
|
-
uniques?: Record<string, UniqueDef>;
|
|
39
|
-
indexes?: Record<string, IndexDef>;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function toProperty(name: string): string {
|
|
43
|
-
return name.replace(/_([a-z])/g, (_match, char: string) => char.toUpperCase());
|
|
44
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { toPostgresSchema } from "../adapters/to-postgres.ts";
|
|
2
|
-
import { postgresTableDefsV2 } from "../entities/v2/index.ts";
|
|
3
|
-
|
|
4
|
-
const tables = toPostgresSchema(postgresTableDefsV2);
|
|
5
|
-
|
|
6
|
-
export const tPersistenceState = tables["t_persistence_state"]!;
|
|
7
|
-
export const tSchemaMeta = tables["t_schema_meta"]!;
|
|
8
|
-
export const tSessions = tables["t_sessions"]!;
|
|
9
|
-
export const tEvents = tables["t_events"]!;
|
|
10
|
-
export const tSessionEvents = tables["t_session_events"]!;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { toPostgresSchema } from "../adapters/to-postgres.ts";
|
|
2
|
-
import { postgresTableDefs } from "../entities/v3/index.ts";
|
|
3
|
-
|
|
4
|
-
const tables = toPostgresSchema(postgresTableDefs);
|
|
5
|
-
|
|
6
|
-
export const tPersistenceState = tables["t_persistence_state"]!;
|
|
7
|
-
export const tSchemaMeta = tables["t_schema_meta"]!;
|
|
8
|
-
export const tSessions = tables["t_sessions"]!;
|
|
9
|
-
export const tEvents = tables["t_events"]!;
|
|
10
|
-
export const tSessionEvents = tables["t_session_events"]!;
|
|
11
|
-
export const tStorageUnits = tables["t_storage_units"]!;
|
|
12
|
-
export const tWorkspaces = tables["t_workspaces"]!;
|
|
13
|
-
export const tWorkspaceSessions = tables["t_workspace_sessions"]!;
|
|
14
|
-
export const tWorkspaceState = tables["t_workspace_state"]!;
|
|
15
|
-
export const tSessionProjcacheRows = tables["t_session_projcache_row"]!;
|
|
16
|
-
export const tEventUsage = tables["t_event_usage"]!;
|
|
17
|
-
export const tSessionUsage = tables["t_session_usage"]!;
|
|
18
|
-
export const tSessionCounts = tables["t_session_counts"]!;
|
package/src/drizzle/sqlite-v2.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { toSqliteSchema } from "../adapters/to-sqlite.ts";
|
|
2
|
-
import { sqliteTableDefsV2 } from "../entities/v2/index.ts";
|
|
3
|
-
|
|
4
|
-
const tables = toSqliteSchema(sqliteTableDefsV2);
|
|
5
|
-
|
|
6
|
-
export const tPersistenceState = tables["t_persistence_state"]!;
|
|
7
|
-
export const tSessions = tables["t_sessions"]!;
|
|
8
|
-
export const tEvents = tables["t_events"]!;
|
|
9
|
-
export const tSessionEvents = tables["t_session_events"]!;
|
package/src/drizzle/sqlite-v3.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { toSqliteSchema } from "../adapters/to-sqlite.ts";
|
|
2
|
-
import { sqliteTableDefs } from "../entities/v3/index.ts";
|
|
3
|
-
|
|
4
|
-
const tables = toSqliteSchema(sqliteTableDefs);
|
|
5
|
-
|
|
6
|
-
export const tPersistenceState = tables["t_persistence_state"]!;
|
|
7
|
-
export const tSchemaMeta = tables["t_schema_meta"]!;
|
|
8
|
-
export const tSessions = tables["t_sessions"]!;
|
|
9
|
-
export const tEvents = tables["t_events"]!;
|
|
10
|
-
export const tSessionEvents = tables["t_session_events"]!;
|
|
11
|
-
export const tStorageUnits = tables["t_storage_units"]!;
|
|
12
|
-
export const tWorkspaces = tables["t_workspaces"]!;
|
|
13
|
-
export const tWorkspaceSessions = tables["t_workspace_sessions"]!;
|
|
14
|
-
export const tWorkspaceState = tables["t_workspace_state"]!;
|
|
15
|
-
export const tSessionProjcacheRows = tables["t_session_projcache_row"]!;
|
|
16
|
-
export const tEventUsage = tables["t_event_usage"]!;
|
|
17
|
-
export const tSessionUsage = tables["t_session_usage"]!;
|
|
18
|
-
export const tSessionCounts = tables["t_session_counts"]!;
|
package/src/entities/v2/index.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { persistenceState } from "../v3/persistence-state.ts";
|
|
2
|
-
import { schemaMeta } from "../v3/schema-meta.ts";
|
|
3
|
-
import { sessions } from "../v3/sessions.ts";
|
|
4
|
-
import { events } from "../v3/events.ts";
|
|
5
|
-
import { sessionEvents } from "./session-events.ts";
|
|
6
|
-
|
|
7
|
-
export { persistenceState };
|
|
8
|
-
export { schemaMeta };
|
|
9
|
-
export { sessions };
|
|
10
|
-
export { events };
|
|
11
|
-
export { sessionEvents };
|
|
12
|
-
|
|
13
|
-
export const sqliteTableDefsV2 = [persistenceState, sessions, events, sessionEvents] as const;
|
|
14
|
-
export const postgresTableDefsV2 = [
|
|
15
|
-
persistenceState,
|
|
16
|
-
schemaMeta,
|
|
17
|
-
sessions,
|
|
18
|
-
events,
|
|
19
|
-
sessionEvents,
|
|
20
|
-
] as const;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { TableDef } from "../../adapters/types.ts";
|
|
2
|
-
import { sessionEvents as v3SessionEvents } from "../v3/session-events.ts";
|
|
3
|
-
|
|
4
|
-
export const sessionEvents: TableDef = {
|
|
5
|
-
...v3SessionEvents,
|
|
6
|
-
columns: {
|
|
7
|
-
...v3SessionEvents.columns,
|
|
8
|
-
f_original_seq: { type: "integer", notNull: true },
|
|
9
|
-
},
|
|
10
|
-
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { TableDef } from "../../adapters/types.ts";
|
|
2
|
-
|
|
3
|
-
// 官方 `schedule` 域的 `tasks` 表:一个提醒一行(key = `ScheduleId`)。归属会话与状态是可查的列,
|
|
4
|
-
// 记录本体与投递回执按上游契约原样存 JSON(它们只有上游 `dsh-schedule` 自己消费,拆列没有第二个读法)。
|
|
5
|
-
export const scheduleTasks: TableDef = {
|
|
6
|
-
name: "t_schedule_tasks",
|
|
7
|
-
columns: {
|
|
8
|
-
f_id: { type: "text", primaryKey: true },
|
|
9
|
-
f_session_id: { type: "text", notNull: true },
|
|
10
|
-
f_status: { type: "text", notNull: true },
|
|
11
|
-
f_record: { type: "text", notNull: true },
|
|
12
|
-
f_last_delivery: { type: "text" },
|
|
13
|
-
f_delivery_history: { type: "text" },
|
|
14
|
-
},
|
|
15
|
-
indexes: { idx_schedule_tasks_session_id: { columns: ["f_session_id"] } },
|
|
16
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { TableDef } from "../../adapters/types.ts";
|
|
2
|
-
|
|
3
|
-
export const workspaceSessions: TableDef = {
|
|
4
|
-
name: "t_workspace_sessions",
|
|
5
|
-
columns: {
|
|
6
|
-
f_id: { type: "serial", primaryKey: true },
|
|
7
|
-
f_workspace_id: {
|
|
8
|
-
type: "text",
|
|
9
|
-
notNull: true,
|
|
10
|
-
references: { table: "t_workspaces", column: "f_workspace_id", onDelete: "cascade" },
|
|
11
|
-
},
|
|
12
|
-
f_session_id: { type: "text", notNull: true },
|
|
13
|
-
f_position: { type: "integer", notNull: true },
|
|
14
|
-
},
|
|
15
|
-
uniques: {
|
|
16
|
-
uq_workspace_sessions_workspace_session: { columns: ["f_workspace_id", "f_session_id"] },
|
|
17
|
-
},
|
|
18
|
-
indexes: { idx_workspace_sessions_session_id: { columns: ["f_session_id"] } },
|
|
19
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { TableDef } from "../../adapters/types.ts";
|
|
2
|
-
|
|
3
|
-
export const workspaceState: TableDef = {
|
|
4
|
-
name: "t_workspace_state",
|
|
5
|
-
columns: {
|
|
6
|
-
f_singleton: { type: "integer", primaryKey: true },
|
|
7
|
-
f_initialized: { type: "integer", notNull: true },
|
|
8
|
-
f_pending_operation: { type: "text" },
|
|
9
|
-
f_pending_workspace_id: { type: "text" },
|
|
10
|
-
},
|
|
11
|
-
checks: { ck_workspace_state_singleton: { expression: "f_singleton = 1" } },
|
|
12
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { TableDef } from "../../adapters/types.ts";
|
|
2
|
-
|
|
3
|
-
export const workspaces: TableDef = {
|
|
4
|
-
name: "t_workspaces",
|
|
5
|
-
columns: {
|
|
6
|
-
f_id: { type: "serial", primaryKey: true },
|
|
7
|
-
f_workspace_id: { type: "text", notNull: true, unique: true },
|
|
8
|
-
f_path: { type: "text", notNull: true },
|
|
9
|
-
f_title: { type: "text", notNull: true },
|
|
10
|
-
f_created_at: { type: "text", notNull: true },
|
|
11
|
-
f_updated_at: { type: "text", notNull: true },
|
|
12
|
-
f_position: { type: "integer", notNull: true, default: -1 },
|
|
13
|
-
},
|
|
14
|
-
};
|
package/src/gc.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import type { Context } from "@deepseek-ai/cordis";
|
|
2
|
-
import { SESSION_GC_PATH } from "./routes.ts";
|
|
3
|
-
import type { SessionPersistenceRdb } from "./index.ts";
|
|
4
|
-
|
|
5
|
-
export { SESSION_GC_PATH };
|
|
6
|
-
|
|
7
|
-
interface GcAgentLike {
|
|
8
|
-
cancel?(cause: { kind: "user" }, options?: { keepInbox?: boolean }): void;
|
|
9
|
-
whenIdle(): Promise<void>;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// 让所有运行中的 agent 先退场:GC 要重写事件表,运行中的写路径必须停下来。
|
|
13
|
-
async function stopRunningAgents(ctx: Context): Promise<number> {
|
|
14
|
-
const agents = ctx.get("agents") as { list(): GcAgentLike[] } | undefined;
|
|
15
|
-
const running = agents?.list() ?? [];
|
|
16
|
-
for (const agent of running) agent.cancel?.({ kind: "user" }, { keepInbox: true });
|
|
17
|
-
await Promise.all(running.map((agent) => agent.whenIdle()));
|
|
18
|
-
return running.length;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// GC 通道:停 agent → 回收孤儿事件行 → VACUUM,一次请求完成。
|
|
22
|
-
export function registerSessionGc(ctx: Context, persistence: SessionPersistenceRdb): void {
|
|
23
|
-
ctx.inject(["webServer", "connection"] as const, (webCtx) => {
|
|
24
|
-
const webServer = webCtx.webServer as unknown as {
|
|
25
|
-
register(route: {
|
|
26
|
-
kind: "exact";
|
|
27
|
-
path: string;
|
|
28
|
-
handler: (
|
|
29
|
-
req: import("node:http").IncomingMessage,
|
|
30
|
-
res: import("node:http").ServerResponse,
|
|
31
|
-
) => void | Promise<void>;
|
|
32
|
-
}): () => void;
|
|
33
|
-
};
|
|
34
|
-
const connection = webCtx.get("connection") as unknown as {
|
|
35
|
-
requestRejection(request: {
|
|
36
|
-
headers: import("node:http").IncomingHttpHeaders;
|
|
37
|
-
}): number | undefined;
|
|
38
|
-
};
|
|
39
|
-
return webCtx.effect(
|
|
40
|
-
() =>
|
|
41
|
-
webServer.register({
|
|
42
|
-
kind: "exact",
|
|
43
|
-
path: SESSION_GC_PATH,
|
|
44
|
-
handler: async (req, res) => {
|
|
45
|
-
const rejection = connection.requestRejection(req);
|
|
46
|
-
if (rejection !== undefined) {
|
|
47
|
-
res.writeHead(rejection);
|
|
48
|
-
res.end(rejection === 401 ? "unauthorized" : "forbidden");
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
if (req.method !== "POST") {
|
|
52
|
-
res.writeHead(405, { "content-type": "application/json" });
|
|
53
|
-
res.end(JSON.stringify({ error: "method not allowed" }));
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
try {
|
|
57
|
-
const stoppedAgents = await stopRunningAgents(webCtx);
|
|
58
|
-
// 先回收孤儿会话,再回收事件行:被删会话独占的事件行才刚成为孤儿。
|
|
59
|
-
const orphanSessions = await persistence.collectOrphanSessions();
|
|
60
|
-
const orphanEvents = await persistence.collectOrphans();
|
|
61
|
-
await persistence.vacuum();
|
|
62
|
-
res.writeHead(200, { "content-type": "application/json" });
|
|
63
|
-
res.end(
|
|
64
|
-
JSON.stringify({ orphanSessions, orphanEvents, stoppedAgents, vacuumed: true }),
|
|
65
|
-
);
|
|
66
|
-
} catch (error: unknown) {
|
|
67
|
-
res.writeHead(500, { "content-type": "application/json" });
|
|
68
|
-
res.end(
|
|
69
|
-
JSON.stringify({ error: error instanceof Error ? error.message : "gc failed" }),
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
}),
|
|
74
|
-
`session-rdb: ${SESSION_GC_PATH} route`,
|
|
75
|
-
);
|
|
76
|
-
});
|
|
77
|
-
}
|