@co-engram/core 0.1.4 → 0.1.6
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/dist/dedup/hash.d.ts +8 -0
- package/dist/dedup/hash.d.ts.map +1 -1
- package/dist/dedup/hash.js +26 -2
- package/dist/dedup/hash.js.map +1 -1
- package/dist/dreaming/decay.d.ts.map +1 -1
- package/dist/dreaming/decay.js +1 -1
- package/dist/dreaming/decay.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +43 -16
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts +29 -9
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +43 -16
- package/dist/i18n/zh.js.map +1 -1
- package/dist/importance/vector.d.ts +4 -4
- package/dist/importance/vector.d.ts.map +1 -1
- package/dist/importance/vector.js +7 -12
- package/dist/importance/vector.js.map +1 -1
- package/dist/lifecycle/freshness.d.ts +25 -6
- package/dist/lifecycle/freshness.d.ts.map +1 -1
- package/dist/lifecycle/freshness.js +37 -21
- package/dist/lifecycle/freshness.js.map +1 -1
- package/dist/merge-driver.cjs +1 -1
- package/dist/observability/proposal-engine.d.ts +94 -10
- package/dist/observability/proposal-engine.d.ts.map +1 -1
- package/dist/observability/proposal-engine.js +169 -4
- package/dist/observability/proposal-engine.js.map +1 -1
- package/dist/prompt-builder/builder.d.ts +3 -0
- package/dist/prompt-builder/builder.d.ts.map +1 -1
- package/dist/prompt-builder/builder.js +45 -3
- package/dist/prompt-builder/builder.js.map +1 -1
- package/dist/prompt-builder/index.d.ts +1 -0
- package/dist/prompt-builder/index.d.ts.map +1 -1
- package/dist/prompt-builder/index.js +1 -0
- package/dist/prompt-builder/index.js.map +1 -1
- package/dist/prompt-builder/path-overview.d.ts +35 -0
- package/dist/prompt-builder/path-overview.d.ts.map +1 -0
- package/dist/prompt-builder/path-overview.js +44 -0
- package/dist/prompt-builder/path-overview.js.map +1 -0
- package/dist/prompt-builder/types.d.ts +11 -0
- package/dist/prompt-builder/types.d.ts.map +1 -1
- package/dist/retrieval/index.d.ts +2 -0
- package/dist/retrieval/index.d.ts.map +1 -1
- package/dist/retrieval/index.js +2 -0
- package/dist/retrieval/index.js.map +1 -1
- package/dist/retrieval/scoring.d.ts +7 -4
- package/dist/retrieval/scoring.d.ts.map +1 -1
- package/dist/retrieval/scoring.js +9 -16
- package/dist/retrieval/scoring.js.map +1 -1
- package/dist/retrieval/search-engine.d.ts +58 -0
- package/dist/retrieval/search-engine.d.ts.map +1 -0
- package/dist/retrieval/search-engine.js +53 -0
- package/dist/retrieval/search-engine.js.map +1 -0
- package/dist/retrieval/sqlite-orchestrator.d.ts +68 -0
- package/dist/retrieval/sqlite-orchestrator.d.ts.map +1 -0
- package/dist/retrieval/sqlite-orchestrator.js +148 -0
- package/dist/retrieval/sqlite-orchestrator.js.map +1 -0
- package/dist/storage/bootstrap.d.ts +31 -0
- package/dist/storage/bootstrap.d.ts.map +1 -0
- package/dist/storage/bootstrap.js +89 -0
- package/dist/storage/bootstrap.js.map +1 -0
- package/dist/storage/engram-index.d.ts +9 -0
- package/dist/storage/engram-index.d.ts.map +1 -1
- package/dist/storage/engram-index.js +38 -0
- package/dist/storage/engram-index.js.map +1 -1
- package/dist/storage/index-cleanup.d.ts +45 -0
- package/dist/storage/index-cleanup.d.ts.map +1 -0
- package/dist/storage/index-cleanup.js +186 -0
- package/dist/storage/index-cleanup.js.map +1 -0
- package/dist/storage/index-db-cursor.d.ts +27 -0
- package/dist/storage/index-db-cursor.d.ts.map +1 -0
- package/dist/storage/index-db-cursor.js +59 -0
- package/dist/storage/index-db-cursor.js.map +1 -0
- package/dist/storage/index-db.d.ts +112 -0
- package/dist/storage/index-db.d.ts.map +1 -0
- package/dist/storage/index-db.js +183 -0
- package/dist/storage/index-db.js.map +1 -0
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +6 -0
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/repository.d.ts +117 -21
- package/dist/storage/repository.d.ts.map +1 -1
- package/dist/storage/repository.js +222 -51
- package/dist/storage/repository.js.map +1 -1
- package/dist/tools/audit-query-tool.d.ts +2 -2
- package/dist/tools/doctor-tools.d.ts.map +1 -1
- package/dist/tools/doctor-tools.js +18 -3
- package/dist/tools/doctor-tools.js.map +1 -1
- package/dist/tools/engram-tools.d.ts.map +1 -1
- package/dist/tools/engram-tools.js +12 -2
- package/dist/tools/engram-tools.js.map +1 -1
- package/dist/tools/proposal-tools.d.ts +2 -0
- package/dist/tools/proposal-tools.d.ts.map +1 -1
- package/dist/tools/proposal-tools.js +19 -4
- package/dist/tools/proposal-tools.js.map +1 -1
- package/dist/tools/schemas.d.ts +78 -70
- package/dist/tools/schemas.d.ts.map +1 -1
- package/dist/tools/schemas.js +6 -0
- package/dist/tools/schemas.js.map +1 -1
- package/dist/tools/tool.d.ts +1 -1
- package/dist/tools/tool.d.ts.map +1 -1
- package/dist/types/repository-types.d.ts +1 -1
- package/dist/types/repository-types.d.ts.map +1 -1
- package/package.json +9 -9
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
declare const DatabaseSync: typeof import("node:sqlite").DatabaseSync;
|
|
2
|
+
type SqliteDb = InstanceType<typeof DatabaseSync>;
|
|
3
|
+
type Statement = ReturnType<SqliteDb["prepare"]>;
|
|
4
|
+
export interface IndexDbOptions {
|
|
5
|
+
readonly dbPath: string;
|
|
6
|
+
/** true = 删除现有 db 文件后重建(plan Task 1.3 暂未实现 reset 逻辑,占位字段) */
|
|
7
|
+
readonly reset?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* engram 在索引层的一份精简投影(只含搜索/排序/FTS 需要的字段)。
|
|
11
|
+
*
|
|
12
|
+
* domainTags 是多值字段,在 SQLite 端拆 engram_domains 表;其余标量字段直接落 engrams 主表。
|
|
13
|
+
* contentTokens 是已切分的纯文本(可能含空格分隔的 token),用于 FTS5 trigram 倒排。
|
|
14
|
+
*/
|
|
15
|
+
export interface EngramIndexEntry {
|
|
16
|
+
readonly id: string;
|
|
17
|
+
readonly title: string;
|
|
18
|
+
readonly kind: string;
|
|
19
|
+
readonly importance: number;
|
|
20
|
+
readonly confidence: number;
|
|
21
|
+
/** epoch ms */
|
|
22
|
+
readonly updatedAt: number;
|
|
23
|
+
readonly contentSize: number;
|
|
24
|
+
readonly visibility: string;
|
|
25
|
+
readonly status: string;
|
|
26
|
+
readonly domainTags: readonly string[];
|
|
27
|
+
readonly summary: string;
|
|
28
|
+
readonly contentTokens: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 突触(synapse)索引条目。外键 from_id / to_id 引用 engrams 主表,
|
|
32
|
+
* 删除任一端 engram 时由 ON DELETE CASCADE 自动清空。
|
|
33
|
+
*/
|
|
34
|
+
export interface SynapseIndexEntry {
|
|
35
|
+
readonly id: string;
|
|
36
|
+
readonly fromId: string;
|
|
37
|
+
readonly toId: string;
|
|
38
|
+
readonly kind: string;
|
|
39
|
+
readonly weight: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* SQLite 索引库封装:打开 / schema 初始化 / 显式事务。
|
|
43
|
+
*
|
|
44
|
+
* 设计要点:
|
|
45
|
+
* - WAL 模式:多读单写,显著降低并发读写冲突,适合 engram write-through 场景。
|
|
46
|
+
* - 显式 BEGIN/COMMIT/ROLLBACK:node:sqlite 默认隐式事务,显式包裹保证多语句原子性。
|
|
47
|
+
* - schema 通过外部 .sql 文件管理,便于审计和迁移工具比对。
|
|
48
|
+
*/
|
|
49
|
+
export declare class IndexDb {
|
|
50
|
+
private db;
|
|
51
|
+
private readonly opts;
|
|
52
|
+
constructor(opts: IndexDbOptions);
|
|
53
|
+
open(): void;
|
|
54
|
+
close(): void;
|
|
55
|
+
prepare(sql: string): Statement;
|
|
56
|
+
exec(sql: string): void;
|
|
57
|
+
/**
|
|
58
|
+
* 在事务中执行回调,失败 rollback。
|
|
59
|
+
* 注意:node:sqlite 的 DatabaseSync 默认每条语句隐式事务,
|
|
60
|
+
* 但我们用 BEGIN/COMMIT/ROLLBACK 显式包裹,确保多语句原子性。
|
|
61
|
+
*/
|
|
62
|
+
transaction<T>(fn: () => T): T;
|
|
63
|
+
private requireOpen;
|
|
64
|
+
/**
|
|
65
|
+
* UPSERT 一个 engram 索引条目:主表 + domains(全量替换)+ FTS(delete+insert)。
|
|
66
|
+
*
|
|
67
|
+
* 实现要点:
|
|
68
|
+
* - 整体在事务内,任一步失败 rollback,保证主表/domains/FTS 三地一致。
|
|
69
|
+
* - domains 用 DELETE+INSERT 而非 ON CONFLICT:语义上是"全量替换 tag 集合",
|
|
70
|
+
* 调用方传入的新集合就是真理源,旧 tag 不在该集合内就该被清掉。
|
|
71
|
+
* - FTS5 不支持 ON CONFLICT,只能 delete + insert;否则会有重复倒排项。
|
|
72
|
+
*/
|
|
73
|
+
upsertEngram(entry: EngramIndexEntry): void;
|
|
74
|
+
/**
|
|
75
|
+
* 内部 UPSERT(无事务包裹)。调用方必须已在外层 transaction 内。
|
|
76
|
+
*
|
|
77
|
+
* 单条写入走 upsertEngram;批量 cold start rebuild 走 rebuildFromEntries,
|
|
78
|
+
* 后者在单个 transaction 里循环调用本方法,避免每条都 BEGIN/COMMIT。
|
|
79
|
+
*/
|
|
80
|
+
private upsertEngramUnsafe;
|
|
81
|
+
/**
|
|
82
|
+
* Cold start 重建:用 entries 全量替换 SQLite 索引内容。
|
|
83
|
+
*
|
|
84
|
+
* 用例:host 启动时检测到 .co-engram/index.db 缺失或损坏 → 扫描所有
|
|
85
|
+
* engrams/*.md → 调本方法一次性灌入。
|
|
86
|
+
*
|
|
87
|
+
* 实现:
|
|
88
|
+
* - 单个 transaction 内:DELETE engrams(CASCADE 清 domains + synapses)
|
|
89
|
+
* + DELETE engram_fts(FTS 不参与外键,手动清)+ 批量 upsertEngramUnsafe。
|
|
90
|
+
* - 中途任一步失败 → rollback,SQLite 保持原状(数据可能旧但一致)。
|
|
91
|
+
* - 调用方决定是否清空 synapses:本方法不重建 synapses(它们由 synapse
|
|
92
|
+
* create 路径单独维护),CASCADE 会把它们一并清掉,rebuild 期间 synapse
|
|
93
|
+
* 数据丢失是可接受的(可以从 markdown frontmatter 重新解析)。
|
|
94
|
+
*/
|
|
95
|
+
rebuildFromEntries(entries: readonly EngramIndexEntry[]): void;
|
|
96
|
+
/**
|
|
97
|
+
* UPSERT 一条 synapse。无 FTS,单语句即可,不需要事务包裹。
|
|
98
|
+
*/
|
|
99
|
+
upsertSynapse(s: SynapseIndexEntry): void;
|
|
100
|
+
/**
|
|
101
|
+
* 删除一个 engram 及其所有派生数据。
|
|
102
|
+
*
|
|
103
|
+
* - engrams 主表:显式 DELETE。
|
|
104
|
+
* - engram_domains / synapses(from/to):外键 ON DELETE CASCADE 自动清。
|
|
105
|
+
* - engram_fts:FTS5 表不参与外键,必须显式 DELETE。
|
|
106
|
+
*
|
|
107
|
+
* 包在事务里:即便 FTS 删除失败,主表删除也会 rollback,保持一致。
|
|
108
|
+
*/
|
|
109
|
+
deleteEngram(engramId: string): void;
|
|
110
|
+
}
|
|
111
|
+
export {};
|
|
112
|
+
//# sourceMappingURL=index-db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-db.d.ts","sourceRoot":"","sources":["../../src/storage/index-db.ts"],"names":[],"mappings":"AAiBA,QAAA,MAAM,YAAY,2CAA4B,CAAC;AAI/C,KAAK,QAAQ,GAAG,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC;AAClD,KAAK,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAKjD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,eAAe;IACf,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;gBAE1B,IAAI,EAAE,cAAc;IAIhC,IAAI,IAAI,IAAI;IAaZ,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAK/B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKvB;;;;OAIG;IACH,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IAiB9B,OAAO,CAAC,WAAW;IAMnB;;;;;;;;OAQG;IACH,YAAY,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAI3C;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAuC1B;;;;;;;;;;;;;OAaG;IACH,kBAAkB,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,GAAG,IAAI;IAU9D;;OAEG;IACH,aAAa,CAAC,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAYzC;;;;;;;;OAQG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;CAMrC"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// packages/core/src/storage/index-db.ts
|
|
2
|
+
// 用 createRequire 绕过 Vite 静态分析:`import { DatabaseSync } from "node:sqlite"`
|
|
3
|
+
// 在 vitest 2.x 下会被 Vite resolver 拦截,报 `Failed to load url sqlite`
|
|
4
|
+
// (stripping `node:` prefix)。createRequire 在运行时调用,Vite 无法静态解析,
|
|
5
|
+
// 直接走 Node builtin resolver —— 同 test/storage/node-sqlite-smoke.test.ts 的 workaround。
|
|
6
|
+
//
|
|
7
|
+
// 字符串拼接 `"node:" + "sqlite"` 进一步防止 Vite 把整个 require 调用静态化为
|
|
8
|
+
// bare import 解析。type import 在编译时被擦除,不被 resolver 拦截,可以安全使用。
|
|
9
|
+
import { createRequire } from "node:module";
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
const require = createRequire(import.meta.url);
|
|
14
|
+
const SQLITE_MODULE = "node:" + "sqlite";
|
|
15
|
+
const sqliteModule = require(SQLITE_MODULE);
|
|
16
|
+
const DatabaseSync = sqliteModule.DatabaseSync;
|
|
17
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const SCHEMA_PATH = join(__dirname, "index-db-schema.sql");
|
|
19
|
+
/**
|
|
20
|
+
* SQLite 索引库封装:打开 / schema 初始化 / 显式事务。
|
|
21
|
+
*
|
|
22
|
+
* 设计要点:
|
|
23
|
+
* - WAL 模式:多读单写,显著降低并发读写冲突,适合 engram write-through 场景。
|
|
24
|
+
* - 显式 BEGIN/COMMIT/ROLLBACK:node:sqlite 默认隐式事务,显式包裹保证多语句原子性。
|
|
25
|
+
* - schema 通过外部 .sql 文件管理,便于审计和迁移工具比对。
|
|
26
|
+
*/
|
|
27
|
+
export class IndexDb {
|
|
28
|
+
db = null;
|
|
29
|
+
opts;
|
|
30
|
+
constructor(opts) {
|
|
31
|
+
this.opts = opts;
|
|
32
|
+
}
|
|
33
|
+
open() {
|
|
34
|
+
if (this.db)
|
|
35
|
+
return;
|
|
36
|
+
this.db = new DatabaseSync(this.opts.dbPath);
|
|
37
|
+
// WAL 模式 + 外键 + 性能调优
|
|
38
|
+
this.db.exec("PRAGMA journal_mode = WAL");
|
|
39
|
+
this.db.exec("PRAGMA synchronous = NORMAL");
|
|
40
|
+
this.db.exec("PRAGMA foreign_keys = ON");
|
|
41
|
+
this.db.exec("PRAGMA busy_timeout = 5000");
|
|
42
|
+
// 初始化 schema
|
|
43
|
+
const schema = readFileSync(SCHEMA_PATH, "utf8");
|
|
44
|
+
this.db.exec(schema);
|
|
45
|
+
}
|
|
46
|
+
close() {
|
|
47
|
+
if (!this.db)
|
|
48
|
+
return;
|
|
49
|
+
this.db.close();
|
|
50
|
+
this.db = null;
|
|
51
|
+
}
|
|
52
|
+
prepare(sql) {
|
|
53
|
+
this.requireOpen();
|
|
54
|
+
return this.db.prepare(sql);
|
|
55
|
+
}
|
|
56
|
+
exec(sql) {
|
|
57
|
+
this.requireOpen();
|
|
58
|
+
this.db.exec(sql);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 在事务中执行回调,失败 rollback。
|
|
62
|
+
* 注意:node:sqlite 的 DatabaseSync 默认每条语句隐式事务,
|
|
63
|
+
* 但我们用 BEGIN/COMMIT/ROLLBACK 显式包裹,确保多语句原子性。
|
|
64
|
+
*/
|
|
65
|
+
transaction(fn) {
|
|
66
|
+
this.requireOpen();
|
|
67
|
+
this.db.exec("BEGIN");
|
|
68
|
+
try {
|
|
69
|
+
const result = fn();
|
|
70
|
+
this.db.exec("COMMIT");
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
try {
|
|
75
|
+
this.db.exec("ROLLBACK");
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// ignore rollback failure
|
|
79
|
+
}
|
|
80
|
+
throw err;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
requireOpen() {
|
|
84
|
+
if (!this.db) {
|
|
85
|
+
throw new Error("IndexDb not opened. Call open() first.");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* UPSERT 一个 engram 索引条目:主表 + domains(全量替换)+ FTS(delete+insert)。
|
|
90
|
+
*
|
|
91
|
+
* 实现要点:
|
|
92
|
+
* - 整体在事务内,任一步失败 rollback,保证主表/domains/FTS 三地一致。
|
|
93
|
+
* - domains 用 DELETE+INSERT 而非 ON CONFLICT:语义上是"全量替换 tag 集合",
|
|
94
|
+
* 调用方传入的新集合就是真理源,旧 tag 不在该集合内就该被清掉。
|
|
95
|
+
* - FTS5 不支持 ON CONFLICT,只能 delete + insert;否则会有重复倒排项。
|
|
96
|
+
*/
|
|
97
|
+
upsertEngram(entry) {
|
|
98
|
+
this.transaction(() => this.upsertEngramUnsafe(entry));
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* 内部 UPSERT(无事务包裹)。调用方必须已在外层 transaction 内。
|
|
102
|
+
*
|
|
103
|
+
* 单条写入走 upsertEngram;批量 cold start rebuild 走 rebuildFromEntries,
|
|
104
|
+
* 后者在单个 transaction 里循环调用本方法,避免每条都 BEGIN/COMMIT。
|
|
105
|
+
*/
|
|
106
|
+
upsertEngramUnsafe(entry) {
|
|
107
|
+
this.prepare(`
|
|
108
|
+
INSERT INTO engrams (id, title, kind, importance, confidence, updated_at, content_size, visibility, status)
|
|
109
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
110
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
111
|
+
title = excluded.title,
|
|
112
|
+
kind = excluded.kind,
|
|
113
|
+
importance = excluded.importance,
|
|
114
|
+
confidence = excluded.confidence,
|
|
115
|
+
updated_at = excluded.updated_at,
|
|
116
|
+
content_size = excluded.content_size,
|
|
117
|
+
visibility = excluded.visibility,
|
|
118
|
+
status = excluded.status
|
|
119
|
+
`).run(entry.id, entry.title, entry.kind, entry.importance, entry.confidence, entry.updatedAt, entry.contentSize, entry.visibility, entry.status);
|
|
120
|
+
// domains 全量替换
|
|
121
|
+
this.prepare("DELETE FROM engram_domains WHERE engram_id = ?").run(entry.id);
|
|
122
|
+
const insertDomain = this.prepare("INSERT OR IGNORE INTO engram_domains (engram_id, domain) VALUES (?, ?)");
|
|
123
|
+
for (const d of entry.domainTags) {
|
|
124
|
+
insertDomain.run(entry.id, d);
|
|
125
|
+
}
|
|
126
|
+
// FTS5 不支持 ON CONFLICT,delete + insert
|
|
127
|
+
this.prepare("DELETE FROM engram_fts WHERE id = ?").run(entry.id);
|
|
128
|
+
this.prepare("INSERT INTO engram_fts (id, title, summary, content_tokens) VALUES (?, ?, ?, ?)").run(entry.id, entry.title, entry.summary, entry.contentTokens);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Cold start 重建:用 entries 全量替换 SQLite 索引内容。
|
|
132
|
+
*
|
|
133
|
+
* 用例:host 启动时检测到 .co-engram/index.db 缺失或损坏 → 扫描所有
|
|
134
|
+
* engrams/*.md → 调本方法一次性灌入。
|
|
135
|
+
*
|
|
136
|
+
* 实现:
|
|
137
|
+
* - 单个 transaction 内:DELETE engrams(CASCADE 清 domains + synapses)
|
|
138
|
+
* + DELETE engram_fts(FTS 不参与外键,手动清)+ 批量 upsertEngramUnsafe。
|
|
139
|
+
* - 中途任一步失败 → rollback,SQLite 保持原状(数据可能旧但一致)。
|
|
140
|
+
* - 调用方决定是否清空 synapses:本方法不重建 synapses(它们由 synapse
|
|
141
|
+
* create 路径单独维护),CASCADE 会把它们一并清掉,rebuild 期间 synapse
|
|
142
|
+
* 数据丢失是可接受的(可以从 markdown frontmatter 重新解析)。
|
|
143
|
+
*/
|
|
144
|
+
rebuildFromEntries(entries) {
|
|
145
|
+
this.transaction(() => {
|
|
146
|
+
this.exec("DELETE FROM engrams");
|
|
147
|
+
this.exec("DELETE FROM engram_fts");
|
|
148
|
+
for (const e of entries) {
|
|
149
|
+
this.upsertEngramUnsafe(e);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* UPSERT 一条 synapse。无 FTS,单语句即可,不需要事务包裹。
|
|
155
|
+
*/
|
|
156
|
+
upsertSynapse(s) {
|
|
157
|
+
this.prepare(`
|
|
158
|
+
INSERT INTO synapses (id, from_id, to_id, kind, weight)
|
|
159
|
+
VALUES (?, ?, ?, ?, ?)
|
|
160
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
161
|
+
from_id = excluded.from_id,
|
|
162
|
+
to_id = excluded.to_id,
|
|
163
|
+
kind = excluded.kind,
|
|
164
|
+
weight = excluded.weight
|
|
165
|
+
`).run(s.id, s.fromId, s.toId, s.kind, s.weight);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* 删除一个 engram 及其所有派生数据。
|
|
169
|
+
*
|
|
170
|
+
* - engrams 主表:显式 DELETE。
|
|
171
|
+
* - engram_domains / synapses(from/to):外键 ON DELETE CASCADE 自动清。
|
|
172
|
+
* - engram_fts:FTS5 表不参与外键,必须显式 DELETE。
|
|
173
|
+
*
|
|
174
|
+
* 包在事务里:即便 FTS 删除失败,主表删除也会 rollback,保持一致。
|
|
175
|
+
*/
|
|
176
|
+
deleteEngram(engramId) {
|
|
177
|
+
this.transaction(() => {
|
|
178
|
+
this.prepare("DELETE FROM engrams WHERE id = ?").run(engramId);
|
|
179
|
+
this.prepare("DELETE FROM engram_fts WHERE id = ?").run(engramId);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=index-db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-db.js","sourceRoot":"","sources":["../../src/storage/index-db.ts"],"names":[],"mappings":"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"}
|
package/dist/storage/index.d.ts
CHANGED
|
@@ -12,4 +12,8 @@ export * from "./git-stage.js";
|
|
|
12
12
|
export * from "./engram-index.js";
|
|
13
13
|
export * from "./repository.js";
|
|
14
14
|
export * from "./infra-doctor.js";
|
|
15
|
+
export * from "./index-cleanup.js";
|
|
16
|
+
export { IndexDb } from "./index-db.js";
|
|
17
|
+
export type { SynapseIndexEntry } from "./index-db.js";
|
|
18
|
+
export * from "./bootstrap.js";
|
|
15
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AAInC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,cAAc,gBAAgB,CAAC"}
|
package/dist/storage/index.js
CHANGED
|
@@ -12,4 +12,10 @@ export * from "./git-stage.js";
|
|
|
12
12
|
export * from "./engram-index.js";
|
|
13
13
|
export * from "./repository.js";
|
|
14
14
|
export * from "./infra-doctor.js";
|
|
15
|
+
export * from "./index-cleanup.js";
|
|
16
|
+
// index-db.js 显式 re-export:EngramIndexEntry 与 types/repository-types 的同名,
|
|
17
|
+
// 不能 export *;只 re-export 公共符号,需要 EngramIndexEntry 类型时直接从
|
|
18
|
+
// ./index-db.js import(避免命名冲突 + 保持 SQLite 索引层类型在受控范围)。
|
|
19
|
+
export { IndexDb } from "./index-db.js";
|
|
20
|
+
export * from "./bootstrap.js";
|
|
15
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,0EAA0E;AAC1E,0DAA0D;AAC1D,uDAAuD;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,cAAc,gBAAgB,CAAC"}
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
import type { Engram, EngramCatalogEntry, EngramCreateInput, EngramDigest, EngramFreshness, EngramStatus, EngramUpdateInput, ImportanceVector, VerificationStatus, Synapse, SynapseCreateInput, SynapseEvidence, SynapseKind, SynapseResolutionState, SynapseUpdateInput } from "../types/index.js";
|
|
16
16
|
import type { EngramIndexEntry, DoctorReport, PathTreeNode } from "../types/repository-types.js";
|
|
17
17
|
import { type Language } from "../i18n/index.js";
|
|
18
|
+
import { type EngramFile } from "./engram-store.js";
|
|
18
19
|
import { type EngramIndexMap } from "./engram-index.js";
|
|
20
|
+
import { IndexDb } from "./index-db.js";
|
|
19
21
|
/** Repository 配置 */
|
|
20
22
|
export interface RepositoryConfig {
|
|
21
23
|
/** 仓库根目录(~/team-memory/) */
|
|
@@ -31,13 +33,35 @@ export interface RepositoryConfig {
|
|
|
31
33
|
*/
|
|
32
34
|
readonly language?: Language;
|
|
33
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* 外部 .md 检测钩子参数:watcher 发现 dataRoot 下未追踪的 .md 文件时构造。
|
|
38
|
+
*
|
|
39
|
+
* - `absPath`:文件绝对路径,host 可读取内容做进一步处理
|
|
40
|
+
* - `relPath`:相对 rootPath 的路径(用于提案展示与去重命名空间)
|
|
41
|
+
* - `raw`:文件原始内容(避免 hook 反复读盘)
|
|
42
|
+
* - `parsed`:尝试解析 frontmatter 的结果;`null` 表示文件不是合法 engram
|
|
43
|
+
* 格式(无 frontmatter 或解析失败)—— host 通常应当跳过此类文件
|
|
44
|
+
*/
|
|
45
|
+
export interface ExternalMarkdownHookParams {
|
|
46
|
+
readonly absPath: string;
|
|
47
|
+
readonly relPath: string;
|
|
48
|
+
readonly raw: string;
|
|
49
|
+
readonly parsed: EngramFile | null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 外部 .md 检测钩子签名。
|
|
53
|
+
*
|
|
54
|
+
* 由 host 适配层(claude-code-mcp / openclaw-plugin)实现,绑定到
|
|
55
|
+
* ProposalEngine.proposeExternalMarkdown,把"未授权来源"的 .md 转成
|
|
56
|
+
* 待审批提案而非直接落库。
|
|
57
|
+
*/
|
|
58
|
+
export type ExternalMarkdownHook = (params: ExternalMarkdownHookParams) => void;
|
|
34
59
|
/**
|
|
35
60
|
* EngramRepository — per-edge synapse + ULID stable id + 单文件 engram
|
|
36
61
|
*
|
|
37
62
|
* 所有读取方法接受 stable id (ULID)。从 path 读 engram 用 readEngramByPath。
|
|
38
63
|
*/
|
|
39
64
|
export declare class EngramRepository {
|
|
40
|
-
private readonly config;
|
|
41
65
|
private indexCache;
|
|
42
66
|
/**
|
|
43
67
|
* 当前 indexCache 对应的 engram-index.json 磁盘 mtime。
|
|
@@ -60,17 +84,59 @@ export declare class EngramRepository {
|
|
|
60
84
|
/**
|
|
61
85
|
* 递归 fs.watch 句柄,监听 dataRoot 下所有 .md 文件变化(可选)。
|
|
62
86
|
*
|
|
63
|
-
* 触发场景(关键):git pull / git checkout / 手动编辑 / rsync
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
87
|
+
* 触发场景(关键):git pull / git checkout / 手动编辑 / rsync / 用户拷贝文件
|
|
88
|
+
* 等任何外部写入 .md 的途径,startWatching() 单独监听 index.json 看不到这些变化。
|
|
89
|
+
*
|
|
90
|
+
* 信任边界设计(关键安全语义):
|
|
91
|
+
* - git pull 来的 .md → 由 post-merge hook 调 runDoctor 自动接受(团队可信)
|
|
92
|
+
* - 其他来源的 .md(用户拷贝、IDE 写入等)→ **不**自动接受,通过
|
|
93
|
+
* externalMarkdownHook 通知 host 适配层形成 proposal,等用户审批
|
|
94
|
+
* - watcher 自身只做"扫描 + diff + 通知 hook",不写 index.json
|
|
95
|
+
* - 安全动机:防止恶意/误植的 .md 通过文件系统投毒直接进入团队记忆库
|
|
68
96
|
*/
|
|
69
97
|
private dataWatcher;
|
|
70
|
-
/** dataWatcher debounce 定时器。git pull
|
|
98
|
+
/** dataWatcher debounce 定时器。git pull 一次性触发大量事件,合并为一次扫描。 */
|
|
71
99
|
private dataRebuildTimer;
|
|
100
|
+
/**
|
|
101
|
+
* 外部 .md 检测钩子(由 host 适配层设置)。
|
|
102
|
+
*
|
|
103
|
+
* watcher 扫描发现"dataRoot 下存在但 index 中没有"的 .md 文件时调用。
|
|
104
|
+
* host 适配层通常把回调绑到 ProposalEngine.proposeExternalMarkdown,
|
|
105
|
+
* 让用户审批后再决定是否纳入团队记忆。
|
|
106
|
+
*
|
|
107
|
+
* 未设置时 → watcher 发现新 .md 仅记录 orphan,不自动接受(noop)。
|
|
108
|
+
*/
|
|
109
|
+
private externalMarkdownHook;
|
|
110
|
+
private readonly config;
|
|
72
111
|
private readonly language;
|
|
73
|
-
|
|
112
|
+
/**
|
|
113
|
+
* 可选 SQLite 索引层(用于 FTS 召回 / 排序)。
|
|
114
|
+
*
|
|
115
|
+
* 由 host adapter(claude-code-mcp / openclaw-plugin)在装配阶段注入。
|
|
116
|
+
* 未注入时(向后兼容)所有写入路径行为不变;注入后,createEngram /
|
|
117
|
+
* updateEngram / deleteEngram / mutateFrontmatter 在文件落盘成功后会
|
|
118
|
+
* 透明地把 engram 投影 upsert / delete 到 SQLite。
|
|
119
|
+
*
|
|
120
|
+
* 写失败由调用方决定是否致命:本 repository 默认 fail-silent(SQLite 是
|
|
121
|
+
* 派生数据,文件源真理仍然有效;doctor 自愈 + cold start rebuild 最终会
|
|
122
|
+
* 修复 SQLite 与文件的不一致)。
|
|
123
|
+
*/
|
|
124
|
+
private readonly indexDb?;
|
|
125
|
+
constructor(config: RepositoryConfig, indexDb?: IndexDb);
|
|
126
|
+
/**
|
|
127
|
+
* 把 EngramFrontmatter + content 投影成 EngramIndexEntry,同步到 SQLite。
|
|
128
|
+
*
|
|
129
|
+
* 字段映射决策:
|
|
130
|
+
* - contentTokens = content 全文。FTS5 trigram 主要用于召回,词频统计
|
|
131
|
+
* 不影响排序;SQLite page cache 自管索引大小。content 通常 < 2KB,
|
|
132
|
+
* 直接全量灌入。
|
|
133
|
+
* - updatedAt 由 ISO string 转 epoch ms(Date.parse),与 IndexDb 的
|
|
134
|
+
* INTEGER 列对齐。
|
|
135
|
+
* - status / visibility / kind 等 union 类型直接 stringify 落 VARCHAR。
|
|
136
|
+
*
|
|
137
|
+
* Fail-silent:SQLite 是派生层,任何写失败都不阻塞文件源真理。
|
|
138
|
+
*/
|
|
139
|
+
private syncEngramToIndex;
|
|
74
140
|
/** 当前写入语言(读取时自动兼容任意语言格式) */
|
|
75
141
|
get currentLanguage(): Language;
|
|
76
142
|
get rootPath(): string;
|
|
@@ -119,37 +185,67 @@ export declare class EngramRepository {
|
|
|
119
185
|
*
|
|
120
186
|
* 启动后:
|
|
121
187
|
* - index.json watcher:外部进程修改 index(创建/更新/删除 engram)→ 失效 cache
|
|
122
|
-
* - dataRoot .md watcher:任何途径(git pull / checkout / 手动编辑)
|
|
123
|
-
* → debounce
|
|
188
|
+
* - dataRoot .md watcher:任何途径(git pull / checkout / 手动编辑 / 用户拷贝)
|
|
189
|
+
* 写入 .md → debounce 后扫描,diff 出"未在 index 中的 .md"并通过
|
|
190
|
+
* externalMarkdownHook 通知 host 适配层。**watcher 自身不写 index**。
|
|
124
191
|
*
|
|
125
|
-
*
|
|
192
|
+
* 信任边界(安全关键):
|
|
193
|
+
* - git pull 来源由 post-merge hook 调 runDoctor 接受,不依赖 watcher
|
|
194
|
+
* - 其他来源由 host 通过 hook 决策(典型:形成 proposal 等待用户审批)
|
|
195
|
+
* - 防止"用户拷贝恶意 .md → 直接进团队记忆库"的攻击面
|
|
126
196
|
*
|
|
127
|
-
*
|
|
128
|
-
* dataRoot 时,确保各进程的缓存相互一致;同时覆盖 git pull 后索引漏更新
|
|
129
|
-
* 的 fail-silent 场景。
|
|
197
|
+
* 幂等:多次调用安全,只创建一个 watcher。
|
|
130
198
|
*
|
|
131
199
|
* 不需要显式停止 — 进程退出时 OS 自动回收 fd。stopWatching() 仅用于
|
|
132
200
|
* 测试 / 显式资源管理场景。
|
|
133
201
|
*/
|
|
134
202
|
startWatching(): void;
|
|
203
|
+
/**
|
|
204
|
+
* 注册外部 .md 检测钩子。host 适配层应在创建 repository + ProposalEngine
|
|
205
|
+
* 之后、调用 startWatching 之前设置钩子,以确保 watcher 触发时回调就绪。
|
|
206
|
+
*
|
|
207
|
+
* @returns 取消注册函数(测试隔离 / 资源释放用)
|
|
208
|
+
*/
|
|
209
|
+
setExternalMarkdownHook(hook: ExternalMarkdownHook): () => void;
|
|
135
210
|
/**
|
|
136
211
|
* 启动 dataRoot 下 .md 文件的递归 fs.watch。
|
|
137
212
|
*
|
|
138
213
|
* Node 22+ 在 Linux/macOS/Windows 都支持 `recursive: true`(Linux 通过 inotify)。
|
|
139
214
|
* 不支持的平台(NFS / 老 Node)→ catch 后 noop,startWatching 的 index.json
|
|
140
|
-
* watcher + getIndex 的 mtime
|
|
215
|
+
* watcher + getIndex 的 mtime 兜底仍然有效。
|
|
141
216
|
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
217
|
+
* 触发后 debounce 调用 scanForExternalMarkdown(只读 + hook 通知),
|
|
218
|
+
* **不**调用 rebuildIndex(避免 untrusted .md 直接落库)。
|
|
144
219
|
*/
|
|
145
220
|
private startDataRootWatcher;
|
|
146
221
|
/**
|
|
147
|
-
* Debounce
|
|
222
|
+
* Debounce 扫描,合并短时间内的多次 .md 变化事件。
|
|
223
|
+
*
|
|
224
|
+
* git pull / rsync 等批量操作会一次性产生几十~几百个事件,逐个扫描会卡死。
|
|
225
|
+
* 2000ms debounce 既合并事件,也给 post-merge hook(post-merge 在 git pull
|
|
226
|
+
* 完成后同步执行)足够时间完成可信路径的 index 写入,避免 watcher 与
|
|
227
|
+
* post-merge 同时处理同一批文件造成竞争。
|
|
228
|
+
*/
|
|
229
|
+
private scheduleDataScan;
|
|
230
|
+
/**
|
|
231
|
+
* 扫描 dataRoot 下所有 .md,diff 出"未在 index 中的 .md",逐个调用
|
|
232
|
+
* externalMarkdownHook(若设置)。
|
|
233
|
+
*
|
|
234
|
+
* 关键不变量:
|
|
235
|
+
* - **不**写 engram-index.json(防止 untrusted .md 直接进 index)
|
|
236
|
+
* - **不**调用 getIndex() — getIndex 在 index.json 缺失时会触发 rebuildIndex
|
|
237
|
+
* 把所有合法 .md 灌入,这会让"未追踪"判定全部失效。这里直接读
|
|
238
|
+
* index.json,不存在则视为空集合,所有 .md 都视为未追踪。
|
|
239
|
+
* - 已在 index.json 中的 .md → noop(post-merge 或 engram_create 已处理)
|
|
240
|
+
* - 未设置 hook → noop(等价于"未启用外部提案",安全默认)
|
|
241
|
+
* - hook 自身负责去重(典型:ProposalEngine.proposeExternalMarkdown
|
|
242
|
+
* 检查 proposal 状态:pending/accepted/dismissed 都返回 no-change)
|
|
148
243
|
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
244
|
+
* 性能:全量扫盘读所有 .md,大仓库(>10k 文件)可能耗时数百毫秒。
|
|
245
|
+
* 可接受因为:(1) 2s debounce 已经限频;(2) post-merge hook 通常先完成,
|
|
246
|
+
* 大部分 .md 已在 index,scan 仅对增量做 hook 调用。
|
|
151
247
|
*/
|
|
152
|
-
private
|
|
248
|
+
private scanForExternalMarkdown;
|
|
153
249
|
/** 停止 watcher(主要用于测试隔离) */
|
|
154
250
|
stopWatching(): void;
|
|
155
251
|
/** 失效缓存 — 下次 getIndex 从磁盘重读。同时通知 invalidate listeners。 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/storage/repository.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAeH,OAAO,KAAK,EACV,MAAM,EACN,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EAGf,YAAY,EACZ,iBAAiB,EAGjB,gBAAgB,EAChB,kBAAkB,EAClB,OAAO,EACP,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAEV,gBAAgB,EAChB,YAAY,EAEZ,YAAY,EACb,MAAM,8BAA8B,CAAC;AAWtC,OAAO,EAAoB,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/storage/repository.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAeH,OAAO,KAAK,EACV,MAAM,EACN,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EAGf,YAAY,EACZ,iBAAiB,EAGjB,gBAAgB,EAChB,kBAAkB,EAClB,OAAO,EACP,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAEV,gBAAgB,EAChB,YAAY,EAEZ,YAAY,EACb,MAAM,8BAA8B,CAAC;AAWtC,OAAO,EAAoB,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAEL,KAAK,UAAU,EAQhB,MAAM,mBAAmB,CAAC;AAc3B,OAAO,EAaL,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EACL,OAAO,EAER,MAAM,eAAe,CAAC;AAEvB,oBAAoB;AACpB,MAAM,WAAW,gBAAgB;IAC/B,4BAA4B;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;;;;;OAQG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CACpC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,0BAA0B,KAAK,IAAI,CAAC;AA4DhF;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,UAAU,CAA6B;IAC/C;;;;OAIG;IACH,OAAO,CAAC,eAAe,CAAqB;IAE5C;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAyB;IAE7D;;;OAGG;IACH,OAAO,CAAC,YAAY,CAAwB;IAE5C;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,WAAW,CAAwB;IAE3C,2DAA2D;IAC3D,OAAO,CAAC,gBAAgB,CAA4C;IAEpE;;;;;;;;OAQG;IACH,OAAO,CAAC,oBAAoB,CAAmC;IAE/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAE1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IAEpC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAU;gBAEvB,MAAM,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,OAAO;IAMvD;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,iBAAiB;IA0BzB,4BAA4B;IAC5B,IAAI,eAAe,IAAI,QAAQ,CAE9B;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAID;;;;;;;;;;OAUG;IACH,OAAO,CAAC,QAAQ;IA8BhB,sBAAsB;IACtB,YAAY,IAAI,cAAc;IAM9B;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;IAgBpB,uBAAuB;IACvB,OAAO,CAAC,gBAAgB;IAMxB,sBAAsB;IACtB,OAAO,CAAC,gBAAgB;IAMxB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,6BAA6B;IAcrC;;;;;;;;;;;;;;;;;;OAkBG;IACH,aAAa,IAAI,IAAI;IA8BrB;;;;;OAKG;IACH,uBAAuB,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,IAAI;IAS/D;;;;;;;;;OASG;IACH,OAAO,CAAC,oBAAoB;IAuB5B;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;IAYxB;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,uBAAuB;IAyC/B,2BAA2B;IAC3B,YAAY,IAAI,IAAI;IAuBpB,0DAA0D;IAC1D,OAAO,CAAC,oBAAoB;IAa5B;;;;;;;OAOG;IACH,qBAAqB,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAQjD,yBAAyB;IACzB,OAAO,CAAC,WAAW;IAgBnB,2BAA2B;IAC3B,OAAO,CAAC,YAAY;IAOpB;;;;;;;;OAQG;IACH,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAwFtE;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAUzB;;OAEG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAWpC;;OAEG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IASjC;;;;;;OAMG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,MAAM;IA4IhE,mCAAmC;IACnC,OAAO,CAAC,WAAW;IAMnB;;;;;;;OAOG;IACH,OAAO,CAAC,wBAAwB;IAahC;;;;;OAKG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAoCpC;;OAEG;IACH,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAa1D,+BAA+B;IAC/B,WAAW,IAAI,kBAAkB,EAAE;IAanC;;;;OAIG;IACH,wBAAwB,CACtB,QAAQ,EAAE,SAAS,kBAAkB,EAAE,GACtC,SAAS,MAAM,EAAE;IACpB,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,GAAG,SAAS,MAAM,EAAE;IAgBvE;;;;OAIG;IACH,eAAe,IAAI,SAAS,gBAAgB,EAAE;IAI9C,uBAAuB;IACvB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;IAY7D,yCAAyC;IACzC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAmBjD;;;;;OAKG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG;QAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;KAAE;IAI5E;;;;;OAKG;IACH,kBAAkB,IAAI,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAKjE,8BAA8B;IAC9B,sBAAsB,CACpB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,WAAW,GAChB,OAAO,GAAG,SAAS;IAItB,qBAAqB;IACrB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAIvD;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAS5B,6BAA6B;IAC7B,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;IAwCjD;;;;;OAKG;IACH,aAAa,CACX,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,kBAAkB,GACxB,OAAO;IA0CV,mBAAmB;IACnB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAWtC,gCAAgC;IAChC,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAgBhD;;;;;;;OAOG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO;IAuB7D;;;;OAIG;IACH,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAc9D;;;;OAIG;IACH,uBAAuB,CACrB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,sBAAsB,GAC3B,IAAI;IAoBP;;OAEG;IACH,sBAAsB,CACpB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,SAAS,eAAe,EAAE,GACnC,IAAI;IAoBP;;;;;;OAMG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI;IAiBtE;;;;;OAKG;IACH,kBAAkB,CAChB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE;QACL,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B,GACA,IAAI;IAyBP;;;;;;OAMG;IACH,eAAe,CACb,EAAE,EAAE,MAAM,EACV,MAAM,CAAC,EAAE,YAAY,EACrB,SAAS,CAAC,EAAE,eAAe,GAC1B,IAAI;IASP;;;;OAIG;IACH,sBAAsB,CACpB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE;QAAE,MAAM,EAAE,gBAAgB,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GACtD,IAAI;IAQP;;OAEG;IACH,wBAAwB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAUtE;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAsCzB;;;;;;;;;;OAUG;IACH,SAAS,CAAC,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,YAAY;IA8LhE;;;;;OAKG;IACH,YAAY,IAAI,YAAY;IAyC5B;;OAEG;IACH,OAAO,CAAC,cAAc;IAqFtB,OAAO,CAAC,gBAAgB;IAaxB,gCAAgC;IAChC,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAI1C;;;;;;;;;;OAUG;IACH,aAAa,CAAC,cAAc,EAAE,QAAQ,GAAG;QACvC,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,EAAE,CAAC;KAClB;CAkFF"}
|