@naveenadi/mnemonic 0.1.0
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 +93 -0
- package/SKILL.md +158 -0
- package/bin/mne +8 -0
- package/dist/chunker/index.d.ts +8 -0
- package/dist/chunker/index.d.ts.map +1 -0
- package/dist/chunker/index.js +157 -0
- package/dist/chunker/index.js.map +1 -0
- package/dist/cli/commands.d.ts +2 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +793 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/mne.d.ts +3 -0
- package/dist/cli/mne.d.ts.map +1 -0
- package/dist/cli/mne.js +7 -0
- package/dist/cli/mne.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/factory.d.ts +15 -0
- package/dist/llm/factory.d.ts.map +1 -0
- package/dist/llm/factory.js +60 -0
- package/dist/llm/factory.js.map +1 -0
- package/dist/llm/index.d.ts +19 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +18 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/node-llama-cpp.d.ts +30 -0
- package/dist/llm/node-llama-cpp.d.ts.map +1 -0
- package/dist/llm/node-llama-cpp.js +143 -0
- package/dist/llm/node-llama-cpp.js.map +1 -0
- package/dist/llm/ollama.d.ts +19 -0
- package/dist/llm/ollama.d.ts.map +1 -0
- package/dist/llm/ollama.js +99 -0
- package/dist/llm/ollama.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +360 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/pi-extension/index.d.ts +3 -0
- package/dist/pi-extension/index.d.ts.map +1 -0
- package/dist/pi-extension/index.js +193 -0
- package/dist/pi-extension/index.js.map +1 -0
- package/dist/search/fts.d.ts +17 -0
- package/dist/search/fts.d.ts.map +1 -0
- package/dist/search/fts.js +110 -0
- package/dist/search/fts.js.map +1 -0
- package/dist/search/fusion.d.ts +33 -0
- package/dist/search/fusion.d.ts.map +1 -0
- package/dist/search/fusion.js +97 -0
- package/dist/search/fusion.js.map +1 -0
- package/dist/search/pipeline.d.ts +34 -0
- package/dist/search/pipeline.d.ts.map +1 -0
- package/dist/search/pipeline.js +216 -0
- package/dist/search/pipeline.js.map +1 -0
- package/dist/search/vector.d.ts +20 -0
- package/dist/search/vector.d.ts.map +1 -0
- package/dist/search/vector.js +70 -0
- package/dist/search/vector.js.map +1 -0
- package/dist/store/collections.d.ts +23 -0
- package/dist/store/collections.d.ts.map +1 -0
- package/dist/store/collections.js +99 -0
- package/dist/store/collections.js.map +1 -0
- package/dist/store/database.d.ts +22 -0
- package/dist/store/database.d.ts.map +1 -0
- package/dist/store/database.js +209 -0
- package/dist/store/database.js.map +1 -0
- package/dist/store/documents.d.ts +68 -0
- package/dist/store/documents.d.ts.map +1 -0
- package/dist/store/documents.js +273 -0
- package/dist/store/documents.js.map +1 -0
- package/dist/types.d.ts +193 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { MnemonicDB } from './database.js';
|
|
2
|
+
import type { CollectionConfig, CollectionInfo } from '../types.js';
|
|
3
|
+
export declare class CollectionStore {
|
|
4
|
+
private db;
|
|
5
|
+
constructor(db: MnemonicDB);
|
|
6
|
+
/** Add or update a collection */
|
|
7
|
+
upsert(name: string, config: CollectionConfig): void;
|
|
8
|
+
/** Remove a collection */
|
|
9
|
+
remove(name: string): void;
|
|
10
|
+
/** Get a collection by name */
|
|
11
|
+
get(name: string): CollectionInfo | undefined;
|
|
12
|
+
/** List all collections */
|
|
13
|
+
list(): CollectionInfo[];
|
|
14
|
+
/** Rename a collection */
|
|
15
|
+
rename(oldName: string, newName: string): void;
|
|
16
|
+
/** Set includeByDefault */
|
|
17
|
+
setInclude(name: string, include: boolean): void;
|
|
18
|
+
/** Set update command */
|
|
19
|
+
setUpdateCmd(name: string, cmd: string | null): void;
|
|
20
|
+
/** Get names of collections included by default */
|
|
21
|
+
getDefaultNames(): string[];
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=collections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../../src/store/collections.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEpE,qBAAa,eAAe;IACd,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,UAAU;IAElC,iCAAiC;IACjC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAqCpD,0BAA0B;IAC1B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI1B,+BAA+B;IAC/B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IA0B7C,2BAA2B;IAC3B,IAAI,IAAI,cAAc,EAAE;IAwBxB,0BAA0B;IAC1B,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAM9C,2BAA2B;IAC3B,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAMhD,yBAAyB;IACzB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAMpD,mDAAmD;IACnD,eAAe,IAAI,MAAM,EAAE;CAM5B"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export class CollectionStore {
|
|
2
|
+
db;
|
|
3
|
+
constructor(db) {
|
|
4
|
+
this.db = db;
|
|
5
|
+
}
|
|
6
|
+
/** Add or update a collection */
|
|
7
|
+
upsert(name, config) {
|
|
8
|
+
const existing = this.db.db
|
|
9
|
+
.prepare('SELECT name FROM collections WHERE name = ?')
|
|
10
|
+
.get(name);
|
|
11
|
+
if (existing) {
|
|
12
|
+
this.db.db
|
|
13
|
+
.prepare(`UPDATE collections SET path = ?, glob_pattern = ?, ignore_pattern = ?,
|
|
14
|
+
include_by_default = ?, update_cmd = ?, last_modified = datetime('now')
|
|
15
|
+
WHERE name = ?`)
|
|
16
|
+
.run(config.path, config.pattern ?? '**/*.md', config.ignore?.join('\n') ?? null, config.includeByDefault !== false ? 1 : 0, config.updateCommand ?? null, name);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
this.db.db
|
|
20
|
+
.prepare(`INSERT INTO collections (name, path, glob_pattern, ignore_pattern, include_by_default, update_cmd)
|
|
21
|
+
VALUES (?, ?, ?, ?, ?, ?)`)
|
|
22
|
+
.run(name, config.path, config.pattern ?? '**/*.md', config.ignore?.join('\n') ?? null, config.includeByDefault !== false ? 1 : 0, config.updateCommand ?? null);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** Remove a collection */
|
|
26
|
+
remove(name) {
|
|
27
|
+
this.db.db.prepare('DELETE FROM collections WHERE name = ?').run(name);
|
|
28
|
+
}
|
|
29
|
+
/** Get a collection by name */
|
|
30
|
+
get(name) {
|
|
31
|
+
const row = this.db.db
|
|
32
|
+
.prepare(`SELECT c.*,
|
|
33
|
+
(SELECT COUNT(*) FROM documents WHERE collection = c.name) as doc_count,
|
|
34
|
+
(SELECT COUNT(*) FROM documents WHERE collection = c.name AND docid IN
|
|
35
|
+
(SELECT DISTINCT docid FROM chunks)) as active_count,
|
|
36
|
+
(SELECT COUNT(*) FROM contexts WHERE collection = c.name) as context_count
|
|
37
|
+
FROM collections c WHERE c.name = ?`)
|
|
38
|
+
.get(name);
|
|
39
|
+
if (!row)
|
|
40
|
+
return undefined;
|
|
41
|
+
return {
|
|
42
|
+
name: row.name,
|
|
43
|
+
path: row.path,
|
|
44
|
+
globPattern: row.glob_pattern,
|
|
45
|
+
docCount: Number(row.doc_count),
|
|
46
|
+
activeCount: Number(row.active_count),
|
|
47
|
+
lastModified: row.last_modified ?? '',
|
|
48
|
+
includeByDefault: row.include_by_default === 1,
|
|
49
|
+
contextCount: Number(row.context_count),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** List all collections */
|
|
53
|
+
list() {
|
|
54
|
+
const rows = this.db.db
|
|
55
|
+
.prepare(`SELECT c.*,
|
|
56
|
+
(SELECT COUNT(*) FROM documents WHERE collection = c.name) as doc_count,
|
|
57
|
+
(SELECT COUNT(*) FROM documents WHERE collection = c.name AND docid IN
|
|
58
|
+
(SELECT DISTINCT docid FROM chunks)) as active_count,
|
|
59
|
+
(SELECT COUNT(*) FROM contexts WHERE collection = c.name) as context_count
|
|
60
|
+
FROM collections c ORDER BY c.name`)
|
|
61
|
+
.all();
|
|
62
|
+
return rows.map((r) => ({
|
|
63
|
+
name: r.name,
|
|
64
|
+
path: r.path,
|
|
65
|
+
globPattern: r.glob_pattern,
|
|
66
|
+
docCount: Number(r.doc_count),
|
|
67
|
+
activeCount: Number(r.active_count),
|
|
68
|
+
lastModified: r.last_modified ?? '',
|
|
69
|
+
includeByDefault: r.include_by_default === 1,
|
|
70
|
+
contextCount: Number(r.context_count),
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
/** Rename a collection */
|
|
74
|
+
rename(oldName, newName) {
|
|
75
|
+
this.db.db
|
|
76
|
+
.prepare('UPDATE collections SET name = ? WHERE name = ?')
|
|
77
|
+
.run(newName, oldName);
|
|
78
|
+
}
|
|
79
|
+
/** Set includeByDefault */
|
|
80
|
+
setInclude(name, include) {
|
|
81
|
+
this.db.db
|
|
82
|
+
.prepare('UPDATE collections SET include_by_default = ? WHERE name = ?')
|
|
83
|
+
.run(include ? 1 : 0, name);
|
|
84
|
+
}
|
|
85
|
+
/** Set update command */
|
|
86
|
+
setUpdateCmd(name, cmd) {
|
|
87
|
+
this.db.db
|
|
88
|
+
.prepare('UPDATE collections SET update_cmd = ?, last_modified = datetime(\'now\') WHERE name = ?')
|
|
89
|
+
.run(cmd, name);
|
|
90
|
+
}
|
|
91
|
+
/** Get names of collections included by default */
|
|
92
|
+
getDefaultNames() {
|
|
93
|
+
const rows = this.db.db
|
|
94
|
+
.prepare('SELECT name FROM collections WHERE include_by_default = 1 ORDER BY name')
|
|
95
|
+
.all();
|
|
96
|
+
return rows.map((r) => r.name);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=collections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collections.js","sourceRoot":"","sources":["../../src/store/collections.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import type { CollectionConfig, StoreOptions } from '../types.js';
|
|
3
|
+
export declare class MnemonicDB {
|
|
4
|
+
db: Database.Database;
|
|
5
|
+
private dbPath;
|
|
6
|
+
constructor(dbPath: string);
|
|
7
|
+
/** Initialize schema */
|
|
8
|
+
init(): void;
|
|
9
|
+
/** Load sqlite-vec extension */
|
|
10
|
+
loadVectors(): Promise<void>;
|
|
11
|
+
/** Check if vector index exists */
|
|
12
|
+
hasVectorIndex(): boolean;
|
|
13
|
+
/** Create vector table with given dimension */
|
|
14
|
+
createVectorTable(dim: number): void;
|
|
15
|
+
/** Close database */
|
|
16
|
+
close(): void;
|
|
17
|
+
/** Get database file path */
|
|
18
|
+
getPath(): string;
|
|
19
|
+
}
|
|
20
|
+
/** Load collection config from YAML or inline options */
|
|
21
|
+
export declare function loadConfig(options: StoreOptions): Record<string, CollectionConfig>;
|
|
22
|
+
//# sourceMappingURL=database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/store/database.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAItC,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA0IlE,qBAAa,UAAU;IACd,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC;IAC7B,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM;IAO1B,wBAAwB;IACxB,IAAI,IAAI,IAAI;IAIZ,gCAAgC;IAC1B,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IASlC,mCAAmC;IACnC,cAAc,IAAI,OAAO;IASzB,+CAA+C;IAC/C,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAcpC,qBAAqB;IACrB,KAAK,IAAI,IAAI;IAIb,6BAA6B;IAC7B,OAAO,IAAI,MAAM;CAGlB;AAED,yDAAyD;AACzD,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAclF"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
3
|
+
import { parse as parseYaml } from 'yaml';
|
|
4
|
+
/** SQLite schema: all tables and indices */
|
|
5
|
+
const SCHEMA = `
|
|
6
|
+
-- Collections: indexed directories with name and glob patterns
|
|
7
|
+
CREATE TABLE IF NOT EXISTS collections (
|
|
8
|
+
name TEXT PRIMARY KEY,
|
|
9
|
+
path TEXT NOT NULL,
|
|
10
|
+
glob_pattern TEXT NOT NULL DEFAULT '**/*.md',
|
|
11
|
+
ignore_pattern TEXT,
|
|
12
|
+
include_by_default INTEGER NOT NULL DEFAULT 1,
|
|
13
|
+
update_cmd TEXT,
|
|
14
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
15
|
+
last_modified TEXT
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
-- Documents: files with content hash, title, path, metadata
|
|
19
|
+
CREATE TABLE IF NOT EXISTS documents (
|
|
20
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
21
|
+
docid TEXT NOT NULL UNIQUE,
|
|
22
|
+
collection TEXT NOT NULL,
|
|
23
|
+
path TEXT NOT NULL,
|
|
24
|
+
full_path TEXT NOT NULL,
|
|
25
|
+
title TEXT NOT NULL,
|
|
26
|
+
content TEXT NOT NULL,
|
|
27
|
+
checksum TEXT NOT NULL,
|
|
28
|
+
size INTEGER NOT NULL DEFAULT 0,
|
|
29
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
30
|
+
indexed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
31
|
+
frontmatter TEXT,
|
|
32
|
+
tags TEXT,
|
|
33
|
+
modified_at TEXT,
|
|
34
|
+
FOREIGN KEY (collection) REFERENCES collections(name) ON DELETE CASCADE
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
CREATE INDEX IF NOT EXISTS idx_docs_collection ON documents(collection);
|
|
38
|
+
CREATE INDEX IF NOT EXISTS idx_docs_path ON documents(collection, path);
|
|
39
|
+
|
|
40
|
+
-- FTS5 full-text index
|
|
41
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS documents_fts USING fts5(
|
|
42
|
+
title,
|
|
43
|
+
content,
|
|
44
|
+
heading,
|
|
45
|
+
content=documents,
|
|
46
|
+
content_rowid=id,
|
|
47
|
+
tokenize='porter unicode61'
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
-- Triggers to keep FTS in sync
|
|
51
|
+
CREATE TRIGGER IF NOT EXISTS docs_ai AFTER INSERT ON documents BEGIN
|
|
52
|
+
INSERT INTO documents_fts(rowid, title, content, heading)
|
|
53
|
+
VALUES (new.id, new.title, new.content, COALESCE(
|
|
54
|
+
(SELECT heading FROM chunks WHERE docid = new.docid AND seq = 0 LIMIT 1),
|
|
55
|
+
new.title
|
|
56
|
+
));
|
|
57
|
+
END;
|
|
58
|
+
|
|
59
|
+
CREATE TRIGGER IF NOT EXISTS docs_ad AFTER DELETE ON documents BEGIN
|
|
60
|
+
INSERT INTO documents_fts(documents_fts, rowid, title, content, heading)
|
|
61
|
+
VALUES ('delete', old.id, old.title, old.content, '');
|
|
62
|
+
END;
|
|
63
|
+
|
|
64
|
+
CREATE TRIGGER IF NOT EXISTS docs_au AFTER UPDATE ON documents BEGIN
|
|
65
|
+
INSERT INTO documents_fts(documents_fts, rowid, title, content, heading)
|
|
66
|
+
VALUES ('delete', old.id, old.title, old.content, '');
|
|
67
|
+
INSERT INTO documents_fts(rowid, title, content, heading)
|
|
68
|
+
VALUES (new.id, new.title, new.content, COALESCE(
|
|
69
|
+
(SELECT heading FROM chunks WHERE docid = new.docid AND seq = 0 LIMIT 1),
|
|
70
|
+
new.title
|
|
71
|
+
));
|
|
72
|
+
END;
|
|
73
|
+
|
|
74
|
+
-- Chunks: document splits for embedding
|
|
75
|
+
CREATE TABLE IF NOT EXISTS chunks (
|
|
76
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
77
|
+
docid TEXT NOT NULL,
|
|
78
|
+
seq INTEGER NOT NULL,
|
|
79
|
+
pos INTEGER NOT NULL DEFAULT 0,
|
|
80
|
+
content TEXT NOT NULL,
|
|
81
|
+
heading TEXT NOT NULL DEFAULT '',
|
|
82
|
+
checksum TEXT NOT NULL,
|
|
83
|
+
FOREIGN KEY (docid) REFERENCES documents(docid) ON DELETE CASCADE
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
CREATE INDEX IF NOT EXISTS idx_chunks_docid ON chunks(docid);
|
|
87
|
+
|
|
88
|
+
-- Context: hierarchical metadata tree
|
|
89
|
+
CREATE TABLE IF NOT EXISTS contexts (
|
|
90
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
91
|
+
collection TEXT,
|
|
92
|
+
path TEXT NOT NULL,
|
|
93
|
+
context TEXT NOT NULL,
|
|
94
|
+
UNIQUE(collection, path)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
-- Links: wikilink graph
|
|
98
|
+
CREATE TABLE IF NOT EXISTS links (
|
|
99
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
100
|
+
source_docid TEXT NOT NULL,
|
|
101
|
+
source_path TEXT NOT NULL,
|
|
102
|
+
target_docid TEXT,
|
|
103
|
+
target_path TEXT NOT NULL,
|
|
104
|
+
link_type TEXT NOT NULL DEFAULT 'wikilink',
|
|
105
|
+
FOREIGN KEY (source_docid) REFERENCES documents(docid) ON DELETE CASCADE
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
CREATE INDEX IF NOT EXISTS idx_links_source ON links(source_docid);
|
|
109
|
+
CREATE INDEX IF NOT EXISTS idx_links_target ON links(target_docid);
|
|
110
|
+
CREATE INDEX IF NOT EXISTS idx_links_target_path ON links(target_path);
|
|
111
|
+
|
|
112
|
+
-- Tags: manual + frontmatter
|
|
113
|
+
CREATE TABLE IF NOT EXISTS tags (
|
|
114
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
115
|
+
docid TEXT NOT NULL,
|
|
116
|
+
tag TEXT NOT NULL,
|
|
117
|
+
source TEXT NOT NULL DEFAULT 'manual',
|
|
118
|
+
UNIQUE(docid, tag, source),
|
|
119
|
+
FOREIGN KEY (docid) REFERENCES documents(docid) ON DELETE CASCADE
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
CREATE INDEX IF NOT EXISTS idx_tags_docid ON tags(docid);
|
|
123
|
+
CREATE INDEX IF NOT EXISTS idx_tags_tag ON tags(tag);
|
|
124
|
+
|
|
125
|
+
-- LLM cache
|
|
126
|
+
CREATE TABLE IF NOT EXISTS llm_cache (
|
|
127
|
+
key TEXT PRIMARY KEY,
|
|
128
|
+
value TEXT NOT NULL,
|
|
129
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
130
|
+
expires_at TEXT
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
-- Global settings
|
|
134
|
+
CREATE TABLE IF NOT EXISTS settings (
|
|
135
|
+
key TEXT PRIMARY KEY,
|
|
136
|
+
value TEXT NOT NULL
|
|
137
|
+
);
|
|
138
|
+
`;
|
|
139
|
+
export class MnemonicDB {
|
|
140
|
+
db;
|
|
141
|
+
dbPath;
|
|
142
|
+
constructor(dbPath) {
|
|
143
|
+
this.dbPath = dbPath;
|
|
144
|
+
this.db = new Database(dbPath);
|
|
145
|
+
this.db.pragma('journal_mode = WAL');
|
|
146
|
+
this.db.pragma('foreign_keys = ON');
|
|
147
|
+
}
|
|
148
|
+
/** Initialize schema */
|
|
149
|
+
init() {
|
|
150
|
+
this.db.exec(SCHEMA);
|
|
151
|
+
}
|
|
152
|
+
/** Load sqlite-vec extension */
|
|
153
|
+
async loadVectors() {
|
|
154
|
+
try {
|
|
155
|
+
const sqliteVec = await import('sqlite-vec');
|
|
156
|
+
sqliteVec.load(this.db);
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
// sqlite-vec not available, vector search disabled
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/** Check if vector index exists */
|
|
163
|
+
hasVectorIndex() {
|
|
164
|
+
try {
|
|
165
|
+
this.db.prepare("SELECT 1 FROM vectors_vec LIMIT 1").get();
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/** Create vector table with given dimension */
|
|
173
|
+
createVectorTable(dim) {
|
|
174
|
+
this.db.exec(`
|
|
175
|
+
CREATE TABLE IF NOT EXISTS vectors (
|
|
176
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
177
|
+
hash TEXT NOT NULL UNIQUE,
|
|
178
|
+
embedding BLOB NOT NULL
|
|
179
|
+
);
|
|
180
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS vectors_vec USING vec0(
|
|
181
|
+
hash TEXT PRIMARY KEY,
|
|
182
|
+
embedding float[${dim}]
|
|
183
|
+
);
|
|
184
|
+
`);
|
|
185
|
+
}
|
|
186
|
+
/** Close database */
|
|
187
|
+
close() {
|
|
188
|
+
this.db.close();
|
|
189
|
+
}
|
|
190
|
+
/** Get database file path */
|
|
191
|
+
getPath() {
|
|
192
|
+
return this.dbPath;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/** Load collection config from YAML or inline options */
|
|
196
|
+
export function loadConfig(options) {
|
|
197
|
+
if (options.config?.collections) {
|
|
198
|
+
return options.config.collections;
|
|
199
|
+
}
|
|
200
|
+
if (options.configPath && existsSync(options.configPath)) {
|
|
201
|
+
const content = readFileSync(options.configPath, 'utf-8');
|
|
202
|
+
const parsed = parseYaml(content);
|
|
203
|
+
if (parsed.collections && typeof parsed.collections === 'object') {
|
|
204
|
+
return parsed.collections;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return {};
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/store/database.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAG1C,4CAA4C;AAC5C,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqId,CAAC;AAEF,MAAM,OAAO,UAAU;IACd,EAAE,CAAoB;IACrB,MAAM,CAAS;IAEvB,YAAY,MAAc;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACrC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACtC,CAAC;IAED,wBAAwB;IACxB,IAAI;QACF,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED,gCAAgC;IAChC,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;YAC7C,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;QACrD,CAAC;IACH,CAAC;IAED,mCAAmC;IACnC,cAAc;QACZ,IAAI,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC,GAAG,EAAE,CAAC;YAC3D,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,iBAAiB,CAAC,GAAW;QAC3B,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;0BAQS,GAAG;;KAExB,CAAC,CAAC;IACL,CAAC;IAED,qBAAqB;IACrB,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;IAED,6BAA6B;IAC7B,OAAO;QACL,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF;AAED,yDAAyD;AACzD,MAAM,UAAU,UAAU,CAAC,OAAqB;IAC9C,IAAI,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC;IACpC,CAAC;IAED,IAAI,OAAO,CAAC,UAAU,IAAI,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACzD,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAA4B,CAAC;QAC7D,IAAI,MAAM,CAAC,WAAW,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YACjE,OAAO,MAAM,CAAC,WAA+C,CAAC;QAChE,CAAC;IACH,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { MnemonicDB } from './database.js';
|
|
2
|
+
import type { DocumentResult, DocumentNotFound, ContextEntry, LinkEntry } from '../types.js';
|
|
3
|
+
/** Generate 6-char docid from content hash */
|
|
4
|
+
export declare function docid(content: string): string;
|
|
5
|
+
/** Generate full content hash */
|
|
6
|
+
export declare function contentHash(content: string): string;
|
|
7
|
+
/** Extract title from content (first heading or filename) */
|
|
8
|
+
export declare function extractTitle(content: string, fallback: string): string;
|
|
9
|
+
/** Parse frontmatter from markdown content */
|
|
10
|
+
export declare function parseFrontmatter(content: string): {
|
|
11
|
+
frontmatter: Record<string, unknown> | null;
|
|
12
|
+
body: string;
|
|
13
|
+
};
|
|
14
|
+
/** Extract tags from frontmatter and inline #tags */
|
|
15
|
+
export declare function extractTags(frontmatter: Record<string, unknown> | null, content: string): string[];
|
|
16
|
+
export declare class DocumentStore {
|
|
17
|
+
private db;
|
|
18
|
+
constructor(db: MnemonicDB);
|
|
19
|
+
/** Add or update a document */
|
|
20
|
+
upsert(collection: string, relPath: string, fullPath: string, content: string): {
|
|
21
|
+
docid: string;
|
|
22
|
+
isNew: boolean;
|
|
23
|
+
needsEmbed: boolean;
|
|
24
|
+
};
|
|
25
|
+
/** Extract wikilinks and markdown links from content */
|
|
26
|
+
private storeLinks;
|
|
27
|
+
/** Remove a document and its related data */
|
|
28
|
+
remove(docid: string): void;
|
|
29
|
+
/** Remove all documents in a collection */
|
|
30
|
+
removeCollection(name: string): void;
|
|
31
|
+
/** Get a document by path or docid */
|
|
32
|
+
get(identifier: string): DocumentResult | DocumentNotFound;
|
|
33
|
+
/** Get document body with line range */
|
|
34
|
+
getBody(identifier: string, options?: {
|
|
35
|
+
fromLine?: number;
|
|
36
|
+
maxLines?: number;
|
|
37
|
+
}): {
|
|
38
|
+
content: string;
|
|
39
|
+
totalLines: number;
|
|
40
|
+
} | DocumentNotFound;
|
|
41
|
+
/** Add context entry */
|
|
42
|
+
addContext(collection: string | null, path: string, context: string): void;
|
|
43
|
+
/** List all contexts */
|
|
44
|
+
listContexts(): ContextEntry[];
|
|
45
|
+
/** Remove a context */
|
|
46
|
+
removeContext(collection: string | null, path: string): void;
|
|
47
|
+
/** Get context chain for a document (hierarchical) */
|
|
48
|
+
getContextChain(collection: string, relPath: string): string[];
|
|
49
|
+
/** Add a manual tag */
|
|
50
|
+
addTag(docid: string, tag: string): void;
|
|
51
|
+
/** Remove a manual tag */
|
|
52
|
+
removeTag(docid: string, tag: string): void;
|
|
53
|
+
/** Get all tags */
|
|
54
|
+
getAllTags(): Array<{
|
|
55
|
+
tag: string;
|
|
56
|
+
count: number;
|
|
57
|
+
}>;
|
|
58
|
+
/** Get backlinks to a document */
|
|
59
|
+
getBacklinks(docid: string): LinkEntry[];
|
|
60
|
+
/** Get outgoing links from a document */
|
|
61
|
+
getLinks(docid: string): LinkEntry[];
|
|
62
|
+
/** Find orphan documents (no incoming or outgoing links) */
|
|
63
|
+
getOrphans(): Array<{
|
|
64
|
+
docid: string;
|
|
65
|
+
path: string;
|
|
66
|
+
}>;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=documents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/store/documents.ts"],"names":[],"mappings":"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"}
|