@hiveforge/hivemind-mcp 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/LICENSE +21 -0
- package/README.md +148 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +175 -0
- package/dist/cli.js.map +1 -0
- package/dist/graph/builder.d.ts +47 -0
- package/dist/graph/builder.d.ts.map +1 -0
- package/dist/graph/builder.js +182 -0
- package/dist/graph/builder.js.map +1 -0
- package/dist/graph/database.d.ts +71 -0
- package/dist/graph/database.d.ts.map +1 -0
- package/dist/graph/database.js +255 -0
- package/dist/graph/database.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/markdown.d.ts +29 -0
- package/dist/parser/markdown.d.ts.map +1 -0
- package/dist/parser/markdown.js +122 -0
- package/dist/parser/markdown.js.map +1 -0
- package/dist/search/engine.d.ts +48 -0
- package/dist/search/engine.d.ts.map +1 -0
- package/dist/search/engine.js +88 -0
- package/dist/search/engine.js.map +1 -0
- package/dist/server.d.ts +23 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +504 -0
- package/dist/server.js.map +1 -0
- package/dist/types/index.d.ts +646 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +133 -0
- package/dist/types/index.js.map +1 -0
- package/dist/vault/reader.d.ts +56 -0
- package/dist/vault/reader.d.ts.map +1 -0
- package/dist/vault/reader.js +185 -0
- package/dist/vault/reader.js.map +1 -0
- package/dist/vault/watcher.d.ts +33 -0
- package/dist/vault/watcher.d.ts.map +1 -0
- package/dist/vault/watcher.js +92 -0
- package/dist/vault/watcher.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/graph/database.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAIzE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,EAAE,CAAoB;gBAElB,MAAM,EAAE,cAAc;IAelC;;OAEG;IACH,OAAO,CAAC,eAAe;IASvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAsExB;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IA2BjC;;OAEG;IACH,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAchH;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAqB1C;;OAEG;IACH,WAAW,IAAI,SAAS,EAAE;IAiB1B;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE;IAiBzC;;OAEG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE;IAkB7C;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAgB9E;;OAEG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAK5B;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,QAAQ;;;;;;;IAiBR;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { dirname } from 'path';
|
|
3
|
+
import { mkdirSync } from 'fs';
|
|
4
|
+
export class HivemindDatabase {
|
|
5
|
+
db;
|
|
6
|
+
constructor(config) {
|
|
7
|
+
// Ensure directory exists
|
|
8
|
+
this.ensureDirectory(config.path);
|
|
9
|
+
this.db = new Database(config.path, {
|
|
10
|
+
readonly: config.readonly || false,
|
|
11
|
+
fileMustExist: false,
|
|
12
|
+
});
|
|
13
|
+
// Enable WAL mode for better concurrency
|
|
14
|
+
this.db.pragma('journal_mode = WAL');
|
|
15
|
+
this.initializeSchema();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Ensure database directory exists
|
|
19
|
+
*/
|
|
20
|
+
ensureDirectory(dbPath) {
|
|
21
|
+
const dir = dirname(dbPath);
|
|
22
|
+
try {
|
|
23
|
+
mkdirSync(dir, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
// Directory might already exist
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Initialize database schema
|
|
31
|
+
*/
|
|
32
|
+
initializeSchema() {
|
|
33
|
+
// Nodes table (entities)
|
|
34
|
+
this.db.exec(`
|
|
35
|
+
CREATE TABLE IF NOT EXISTS nodes (
|
|
36
|
+
id TEXT PRIMARY KEY,
|
|
37
|
+
type TEXT NOT NULL,
|
|
38
|
+
status TEXT NOT NULL,
|
|
39
|
+
title TEXT NOT NULL,
|
|
40
|
+
content TEXT NOT NULL,
|
|
41
|
+
frontmatter TEXT NOT NULL,
|
|
42
|
+
file_path TEXT NOT NULL,
|
|
43
|
+
created_at INTEGER NOT NULL,
|
|
44
|
+
updated_at INTEGER NOT NULL
|
|
45
|
+
);
|
|
46
|
+
`);
|
|
47
|
+
// Relationships table (edges)
|
|
48
|
+
this.db.exec(`
|
|
49
|
+
CREATE TABLE IF NOT EXISTS relationships (
|
|
50
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
51
|
+
source_id TEXT NOT NULL,
|
|
52
|
+
target_id TEXT NOT NULL,
|
|
53
|
+
rel_type TEXT,
|
|
54
|
+
properties TEXT,
|
|
55
|
+
FOREIGN KEY (source_id) REFERENCES nodes(id) ON DELETE CASCADE,
|
|
56
|
+
FOREIGN KEY (target_id) REFERENCES nodes(id) ON DELETE CASCADE,
|
|
57
|
+
UNIQUE(source_id, target_id, rel_type)
|
|
58
|
+
);
|
|
59
|
+
`);
|
|
60
|
+
// Indexes for fast lookups
|
|
61
|
+
this.db.exec(`
|
|
62
|
+
CREATE INDEX IF NOT EXISTS idx_nodes_type ON nodes(type);
|
|
63
|
+
CREATE INDEX IF NOT EXISTS idx_nodes_status ON nodes(status);
|
|
64
|
+
CREATE INDEX IF NOT EXISTS idx_relationships_source ON relationships(source_id);
|
|
65
|
+
CREATE INDEX IF NOT EXISTS idx_relationships_target ON relationships(target_id);
|
|
66
|
+
`);
|
|
67
|
+
// Full-text search index using FTS5
|
|
68
|
+
this.db.exec(`
|
|
69
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS nodes_fts USING fts5(
|
|
70
|
+
id UNINDEXED,
|
|
71
|
+
title,
|
|
72
|
+
content,
|
|
73
|
+
content='nodes',
|
|
74
|
+
content_rowid='rowid'
|
|
75
|
+
);
|
|
76
|
+
`);
|
|
77
|
+
// Triggers to keep FTS index in sync
|
|
78
|
+
this.db.exec(`
|
|
79
|
+
CREATE TRIGGER IF NOT EXISTS nodes_ai AFTER INSERT ON nodes BEGIN
|
|
80
|
+
INSERT INTO nodes_fts(rowid, id, title, content)
|
|
81
|
+
VALUES (new.rowid, new.id, new.title, new.content);
|
|
82
|
+
END;
|
|
83
|
+
|
|
84
|
+
CREATE TRIGGER IF NOT EXISTS nodes_ad AFTER DELETE ON nodes BEGIN
|
|
85
|
+
DELETE FROM nodes_fts WHERE rowid = old.rowid;
|
|
86
|
+
END;
|
|
87
|
+
|
|
88
|
+
CREATE TRIGGER IF NOT EXISTS nodes_au AFTER UPDATE ON nodes BEGIN
|
|
89
|
+
UPDATE nodes_fts
|
|
90
|
+
SET title = new.title, content = new.content
|
|
91
|
+
WHERE rowid = new.rowid;
|
|
92
|
+
END;
|
|
93
|
+
`);
|
|
94
|
+
console.error('Database schema initialized');
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Insert or update a node
|
|
98
|
+
*/
|
|
99
|
+
upsertNode(note) {
|
|
100
|
+
const stmt = this.db.prepare(`
|
|
101
|
+
INSERT INTO nodes (id, type, status, title, content, frontmatter, file_path, created_at, updated_at)
|
|
102
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
103
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
104
|
+
type = excluded.type,
|
|
105
|
+
status = excluded.status,
|
|
106
|
+
title = excluded.title,
|
|
107
|
+
content = excluded.content,
|
|
108
|
+
frontmatter = excluded.frontmatter,
|
|
109
|
+
file_path = excluded.file_path,
|
|
110
|
+
updated_at = excluded.updated_at
|
|
111
|
+
`);
|
|
112
|
+
stmt.run(note.id, note.frontmatter.type, note.frontmatter.status, note.frontmatter.title || note.fileName, note.content, JSON.stringify(note.frontmatter), note.filePath, note.stats.created.getTime(), note.stats.modified.getTime());
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Insert a relationship
|
|
116
|
+
*/
|
|
117
|
+
insertRelationship(sourceId, targetId, relType, properties) {
|
|
118
|
+
const stmt = this.db.prepare(`
|
|
119
|
+
INSERT OR IGNORE INTO relationships (source_id, target_id, rel_type, properties)
|
|
120
|
+
VALUES (?, ?, ?, ?)
|
|
121
|
+
`);
|
|
122
|
+
stmt.run(sourceId, targetId, relType || 'related', properties ? JSON.stringify(properties) : null);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get a node by ID
|
|
126
|
+
*/
|
|
127
|
+
getNode(id) {
|
|
128
|
+
const stmt = this.db.prepare(`
|
|
129
|
+
SELECT * FROM nodes WHERE id = ?
|
|
130
|
+
`);
|
|
131
|
+
const row = stmt.get(id);
|
|
132
|
+
if (!row)
|
|
133
|
+
return undefined;
|
|
134
|
+
return {
|
|
135
|
+
id: row.id,
|
|
136
|
+
type: row.type,
|
|
137
|
+
status: row.status,
|
|
138
|
+
title: row.title,
|
|
139
|
+
content: row.content,
|
|
140
|
+
properties: JSON.parse(row.frontmatter),
|
|
141
|
+
filePath: row.file_path,
|
|
142
|
+
created: new Date(row.created_at),
|
|
143
|
+
updated: new Date(row.updated_at),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Get all nodes
|
|
148
|
+
*/
|
|
149
|
+
getAllNodes() {
|
|
150
|
+
const stmt = this.db.prepare('SELECT * FROM nodes ORDER BY updated_at DESC');
|
|
151
|
+
const rows = stmt.all();
|
|
152
|
+
return rows.map(row => ({
|
|
153
|
+
id: row.id,
|
|
154
|
+
type: row.type,
|
|
155
|
+
status: row.status,
|
|
156
|
+
title: row.title,
|
|
157
|
+
content: row.content,
|
|
158
|
+
properties: JSON.parse(row.frontmatter),
|
|
159
|
+
filePath: row.file_path,
|
|
160
|
+
created: new Date(row.created_at),
|
|
161
|
+
updated: new Date(row.updated_at),
|
|
162
|
+
}));
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get nodes by type
|
|
166
|
+
*/
|
|
167
|
+
getNodesByType(type) {
|
|
168
|
+
const stmt = this.db.prepare('SELECT * FROM nodes WHERE type = ? ORDER BY title');
|
|
169
|
+
const rows = stmt.all(type);
|
|
170
|
+
return rows.map(row => ({
|
|
171
|
+
id: row.id,
|
|
172
|
+
type: row.type,
|
|
173
|
+
status: row.status,
|
|
174
|
+
title: row.title,
|
|
175
|
+
content: row.content,
|
|
176
|
+
properties: JSON.parse(row.frontmatter),
|
|
177
|
+
filePath: row.file_path,
|
|
178
|
+
created: new Date(row.created_at),
|
|
179
|
+
updated: new Date(row.updated_at),
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get relationships for a node
|
|
184
|
+
*/
|
|
185
|
+
getRelationships(nodeId) {
|
|
186
|
+
const stmt = this.db.prepare(`
|
|
187
|
+
SELECT * FROM relationships
|
|
188
|
+
WHERE source_id = ? OR target_id = ?
|
|
189
|
+
`);
|
|
190
|
+
const rows = stmt.all(nodeId, nodeId);
|
|
191
|
+
return rows.map(row => ({
|
|
192
|
+
id: row.id.toString(),
|
|
193
|
+
sourceId: row.source_id,
|
|
194
|
+
targetId: row.target_id,
|
|
195
|
+
relationType: row.rel_type,
|
|
196
|
+
properties: row.properties ? JSON.parse(row.properties) : undefined,
|
|
197
|
+
bidirectional: false, // Will be determined by graph builder
|
|
198
|
+
}));
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Full-text search using FTS5
|
|
202
|
+
*/
|
|
203
|
+
search(query, limit = 10) {
|
|
204
|
+
const stmt = this.db.prepare(`
|
|
205
|
+
SELECT id, rank
|
|
206
|
+
FROM nodes_fts
|
|
207
|
+
WHERE nodes_fts MATCH ?
|
|
208
|
+
ORDER BY rank
|
|
209
|
+
LIMIT ?
|
|
210
|
+
`);
|
|
211
|
+
const rows = stmt.all(query, limit);
|
|
212
|
+
return rows.map(row => ({
|
|
213
|
+
id: row.id,
|
|
214
|
+
rank: row.rank,
|
|
215
|
+
}));
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Delete a node and its relationships
|
|
219
|
+
*/
|
|
220
|
+
deleteNode(id) {
|
|
221
|
+
const stmt = this.db.prepare('DELETE FROM nodes WHERE id = ?');
|
|
222
|
+
stmt.run(id);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Clear all data
|
|
226
|
+
*/
|
|
227
|
+
clear() {
|
|
228
|
+
this.db.exec('DELETE FROM nodes');
|
|
229
|
+
this.db.exec('DELETE FROM relationships');
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get database statistics
|
|
233
|
+
*/
|
|
234
|
+
getStats() {
|
|
235
|
+
const nodeCount = this.db.prepare('SELECT COUNT(*) as count FROM nodes').get();
|
|
236
|
+
const relCount = this.db.prepare('SELECT COUNT(*) as count FROM relationships').get();
|
|
237
|
+
const typeStats = this.db.prepare(`
|
|
238
|
+
SELECT type, COUNT(*) as count
|
|
239
|
+
FROM nodes
|
|
240
|
+
GROUP BY type
|
|
241
|
+
`).all();
|
|
242
|
+
return {
|
|
243
|
+
nodes: nodeCount.count,
|
|
244
|
+
relationships: relCount.count,
|
|
245
|
+
byType: Object.fromEntries(typeStats.map(s => [s.type, s.count])),
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Close database connection
|
|
250
|
+
*/
|
|
251
|
+
close() {
|
|
252
|
+
this.db.close();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/graph/database.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA2CA,wBAAsB,WAAW,kBAIhC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { HivemindServer } from './server.js';
|
|
3
|
+
import { readFileSync, existsSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
function loadConfig() {
|
|
6
|
+
// Try to load config from multiple locations
|
|
7
|
+
const configPaths = [
|
|
8
|
+
join(process.cwd(), 'config.json'),
|
|
9
|
+
join(process.cwd(), 'hivemind.config.json'),
|
|
10
|
+
process.env.HIVEMIND_CONFIG_PATH,
|
|
11
|
+
].filter((path) => !!path);
|
|
12
|
+
for (const configPath of configPaths) {
|
|
13
|
+
if (existsSync(configPath)) {
|
|
14
|
+
console.error(`Loading config from: ${configPath}`);
|
|
15
|
+
const configData = readFileSync(configPath, 'utf-8');
|
|
16
|
+
return JSON.parse(configData);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// Default configuration
|
|
20
|
+
console.error('No config file found, using defaults');
|
|
21
|
+
return {
|
|
22
|
+
vault: {
|
|
23
|
+
path: process.env.HIVEMIND_VAULT_PATH || join(process.cwd(), 'sample-vault'),
|
|
24
|
+
watchForChanges: true,
|
|
25
|
+
debounceMs: 100,
|
|
26
|
+
},
|
|
27
|
+
server: {
|
|
28
|
+
transport: 'stdio',
|
|
29
|
+
},
|
|
30
|
+
indexing: {
|
|
31
|
+
strategy: 'incremental',
|
|
32
|
+
batchSize: 100,
|
|
33
|
+
enableVectorSearch: false, // Disabled for MVP
|
|
34
|
+
enableFullTextSearch: true,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export async function startServer() {
|
|
39
|
+
const config = loadConfig();
|
|
40
|
+
const server = new HivemindServer(config);
|
|
41
|
+
await server.start();
|
|
42
|
+
}
|
|
43
|
+
async function main() {
|
|
44
|
+
try {
|
|
45
|
+
await startServer();
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error('Failed to start Hivemind server:', error);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
main();
|
|
53
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,SAAS,UAAU;IACjB,6CAA6C;IAC7C,MAAM,WAAW,GAAG;QAClB,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,CAAC;QAClC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,sBAAsB,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,oBAAoB;KACjC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAE3C,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;YACpD,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACrD,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAmB,CAAC;QAClD,CAAC;IACH,CAAC;IAED,wBAAwB;IACxB,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;IACtD,OAAO;QACL,KAAK,EAAE;YACL,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC;YAC5E,eAAe,EAAE,IAAI;YACrB,UAAU,EAAE,GAAG;SAChB;QACD,MAAM,EAAE;YACN,SAAS,EAAE,OAAO;SACnB;QACD,QAAQ,EAAE;YACR,QAAQ,EAAE,aAAa;YACvB,SAAS,EAAE,GAAG;YACd,kBAAkB,EAAE,KAAK,EAAE,mBAAmB;YAC9C,oBAAoB,EAAE,IAAI;SAC3B;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,WAAW,EAAE,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { VaultNote } from '../types/index.js';
|
|
2
|
+
export declare class MarkdownParser {
|
|
3
|
+
/**
|
|
4
|
+
* Parse a markdown file and extract frontmatter, content, and links
|
|
5
|
+
*/
|
|
6
|
+
parseFile(filePath: string): Promise<VaultNote>;
|
|
7
|
+
/**
|
|
8
|
+
* Parse markdown content string
|
|
9
|
+
*/
|
|
10
|
+
parseContent(content: string, filePath: string): VaultNote;
|
|
11
|
+
/**
|
|
12
|
+
* Parse and validate frontmatter
|
|
13
|
+
*/
|
|
14
|
+
private parseFrontmatter;
|
|
15
|
+
/**
|
|
16
|
+
* Extract headings from markdown AST
|
|
17
|
+
*/
|
|
18
|
+
private extractHeadings;
|
|
19
|
+
/**
|
|
20
|
+
* Extract text content from a node
|
|
21
|
+
*/
|
|
22
|
+
private extractTextFromNode;
|
|
23
|
+
/**
|
|
24
|
+
* Extract wikilinks from markdown content
|
|
25
|
+
* Matches [[Link]] and [[Link|Alias]] patterns
|
|
26
|
+
*/
|
|
27
|
+
private extractWikilinks;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/parser/markdown.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAA4B,MAAM,mBAAmB,CAAC;AAI7E,qBAAa,cAAc;IACzB;;OAEG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAKrD;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS;IAqC1D;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;OAEG;IACH,OAAO,CAAC,eAAe;IA+BvB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAY3B;;;OAGG;IACH,OAAO,CAAC,gBAAgB;CAczB"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import matter from 'gray-matter';
|
|
2
|
+
import { remark } from 'remark';
|
|
3
|
+
import { BaseFrontmatterSchema } from '../types/index.js';
|
|
4
|
+
import { promises as fs } from 'fs';
|
|
5
|
+
export class MarkdownParser {
|
|
6
|
+
/**
|
|
7
|
+
* Parse a markdown file and extract frontmatter, content, and links
|
|
8
|
+
*/
|
|
9
|
+
async parseFile(filePath) {
|
|
10
|
+
const fileContent = await fs.readFile(filePath, 'utf-8');
|
|
11
|
+
return this.parseContent(fileContent, filePath);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parse markdown content string
|
|
15
|
+
*/
|
|
16
|
+
parseContent(content, filePath) {
|
|
17
|
+
// Parse frontmatter with gray-matter
|
|
18
|
+
const { data: frontmatter, content: markdownContent } = matter(content);
|
|
19
|
+
// Validate and parse frontmatter
|
|
20
|
+
const parsedFrontmatter = this.parseFrontmatter(frontmatter);
|
|
21
|
+
// Parse markdown AST
|
|
22
|
+
const ast = remark().parse(markdownContent);
|
|
23
|
+
// Extract headings
|
|
24
|
+
const headings = this.extractHeadings(ast);
|
|
25
|
+
// Extract wikilinks
|
|
26
|
+
const links = this.extractWikilinks(markdownContent);
|
|
27
|
+
// Get file stats
|
|
28
|
+
const fileName = filePath.split(/[/\\]/).pop() || '';
|
|
29
|
+
const note = {
|
|
30
|
+
id: parsedFrontmatter.id,
|
|
31
|
+
filePath,
|
|
32
|
+
fileName,
|
|
33
|
+
frontmatter: parsedFrontmatter,
|
|
34
|
+
content: markdownContent,
|
|
35
|
+
links,
|
|
36
|
+
headings,
|
|
37
|
+
stats: {
|
|
38
|
+
size: content.length,
|
|
39
|
+
created: new Date(), // Will be updated by reader
|
|
40
|
+
modified: new Date(),
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
return note;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Parse and validate frontmatter
|
|
47
|
+
*/
|
|
48
|
+
parseFrontmatter(raw) {
|
|
49
|
+
try {
|
|
50
|
+
// Validate with Zod schema
|
|
51
|
+
return BaseFrontmatterSchema.parse(raw);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.error('Frontmatter validation error:', error);
|
|
55
|
+
// Return minimal valid frontmatter
|
|
56
|
+
return {
|
|
57
|
+
id: raw.id || 'unknown',
|
|
58
|
+
type: raw.type || 'lore',
|
|
59
|
+
status: raw.status || 'draft',
|
|
60
|
+
tags: raw.tags || [],
|
|
61
|
+
aliases: raw.aliases || [],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Extract headings from markdown AST
|
|
67
|
+
*/
|
|
68
|
+
extractHeadings(ast) {
|
|
69
|
+
const headings = [];
|
|
70
|
+
let position = 0;
|
|
71
|
+
const visit = (node, pos) => {
|
|
72
|
+
if (node.type === 'heading') {
|
|
73
|
+
const mdHeading = node;
|
|
74
|
+
const text = this.extractTextFromNode(mdHeading);
|
|
75
|
+
headings.push({
|
|
76
|
+
level: mdHeading.depth,
|
|
77
|
+
text,
|
|
78
|
+
position: pos,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// Recurse into children
|
|
82
|
+
if (node.children) {
|
|
83
|
+
for (const child of node.children) {
|
|
84
|
+
visit(child, pos++);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
for (const child of ast.children) {
|
|
89
|
+
visit(child, position++);
|
|
90
|
+
}
|
|
91
|
+
return headings;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Extract text content from a node
|
|
95
|
+
*/
|
|
96
|
+
extractTextFromNode(node) {
|
|
97
|
+
if (node.type === 'text') {
|
|
98
|
+
return node.value;
|
|
99
|
+
}
|
|
100
|
+
if (node.children) {
|
|
101
|
+
return node.children.map((child) => this.extractTextFromNode(child)).join('');
|
|
102
|
+
}
|
|
103
|
+
return '';
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Extract wikilinks from markdown content
|
|
107
|
+
* Matches [[Link]] and [[Link|Alias]] patterns
|
|
108
|
+
*/
|
|
109
|
+
extractWikilinks(content) {
|
|
110
|
+
const wikilinkRegex = /\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g;
|
|
111
|
+
const links = [];
|
|
112
|
+
let match;
|
|
113
|
+
while ((match = wikilinkRegex.exec(content)) !== null) {
|
|
114
|
+
const linkTarget = match[1].trim();
|
|
115
|
+
if (linkTarget && !links.includes(linkTarget)) {
|
|
116
|
+
links.push(linkTarget);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return links;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/parser/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { HivemindDatabase } from '../graph/database.js';
|
|
2
|
+
export interface QueryResult {
|
|
3
|
+
nodes: any[];
|
|
4
|
+
relationships?: any[];
|
|
5
|
+
metadata: {
|
|
6
|
+
source: 'fts' | 'graph' | 'hybrid';
|
|
7
|
+
executionTime: number;
|
|
8
|
+
totalResults: number;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare class SearchEngine {
|
|
12
|
+
private db;
|
|
13
|
+
constructor(db: HivemindDatabase);
|
|
14
|
+
/**
|
|
15
|
+
* Enhanced search combining FTS5 and graph traversal
|
|
16
|
+
*/
|
|
17
|
+
search(query: string, options?: {
|
|
18
|
+
limit?: number;
|
|
19
|
+
includeRelationships?: boolean;
|
|
20
|
+
filters?: {
|
|
21
|
+
type?: string[];
|
|
22
|
+
status?: string[];
|
|
23
|
+
};
|
|
24
|
+
}): Promise<QueryResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Get a node with its relationships
|
|
27
|
+
*/
|
|
28
|
+
getNodeWithRelationships(id: string): Promise<{
|
|
29
|
+
node: any;
|
|
30
|
+
relationships: any[];
|
|
31
|
+
relatedNodes: any[];
|
|
32
|
+
} | null>;
|
|
33
|
+
/**
|
|
34
|
+
* Find nodes by type
|
|
35
|
+
*/
|
|
36
|
+
getNodesByType(type: string): Promise<any[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Get graph statistics
|
|
39
|
+
*/
|
|
40
|
+
getStats(): {
|
|
41
|
+
nodes: number;
|
|
42
|
+
relationships: number;
|
|
43
|
+
byType: {
|
|
44
|
+
[k: string]: number;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/search/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,GAAG,EAAE,CAAC;IACb,aAAa,CAAC,EAAE,GAAG,EAAE,CAAC;IACtB,QAAQ,EAAE;QACR,MAAM,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;QACnC,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,EAAE,CAAmB;gBAEjB,EAAE,EAAE,gBAAgB;IAIhC;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QACpC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAC/B,OAAO,CAAC,EAAE;YACR,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;YAChB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;SACnB,CAAC;KACH,GAAG,OAAO,CAAC,WAAW,CAAC;IAgDxB;;OAEG;IACG,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAClD,IAAI,EAAE,GAAG,CAAC;QACV,aAAa,EAAE,GAAG,EAAE,CAAC;QACrB,YAAY,EAAE,GAAG,EAAE,CAAC;KACrB,GAAG,IAAI,CAAC;IAwBT;;OAEG;IACG,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAIlD;;OAEG;IACH,QAAQ;;;;;;;CAGT"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export class SearchEngine {
|
|
2
|
+
db;
|
|
3
|
+
constructor(db) {
|
|
4
|
+
this.db = db;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Enhanced search combining FTS5 and graph traversal
|
|
8
|
+
*/
|
|
9
|
+
async search(query, options) {
|
|
10
|
+
const startTime = Date.now();
|
|
11
|
+
const limit = options?.limit || 10;
|
|
12
|
+
// Use FTS5 for full-text search
|
|
13
|
+
const ftsResults = this.db.search(query, limit * 2); // Get more than needed for filtering
|
|
14
|
+
// Get full node details
|
|
15
|
+
let nodes = ftsResults
|
|
16
|
+
.map(result => this.db.getNode(result.id))
|
|
17
|
+
.filter(node => node !== undefined);
|
|
18
|
+
// Apply filters
|
|
19
|
+
if (options?.filters) {
|
|
20
|
+
nodes = nodes.filter(node => {
|
|
21
|
+
if (options.filters?.type && !options.filters.type.includes(node.type)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
if (options.filters?.status && !options.filters.status.includes(node.status)) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
// Limit results
|
|
31
|
+
nodes = nodes.slice(0, limit);
|
|
32
|
+
// Optionally include relationships
|
|
33
|
+
let relationships = [];
|
|
34
|
+
if (options?.includeRelationships) {
|
|
35
|
+
for (const node of nodes) {
|
|
36
|
+
const rels = this.db.getRelationships(node.id);
|
|
37
|
+
relationships.push(...rels);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
nodes,
|
|
42
|
+
relationships: options?.includeRelationships ? relationships : undefined,
|
|
43
|
+
metadata: {
|
|
44
|
+
source: 'fts',
|
|
45
|
+
executionTime: Date.now() - startTime,
|
|
46
|
+
totalResults: ftsResults.length,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get a node with its relationships
|
|
52
|
+
*/
|
|
53
|
+
async getNodeWithRelationships(id) {
|
|
54
|
+
const node = this.db.getNode(id);
|
|
55
|
+
if (!node)
|
|
56
|
+
return null;
|
|
57
|
+
const relationships = this.db.getRelationships(id);
|
|
58
|
+
// Get related nodes
|
|
59
|
+
const relatedIds = new Set();
|
|
60
|
+
for (const rel of relationships) {
|
|
61
|
+
if (rel.sourceId !== id)
|
|
62
|
+
relatedIds.add(rel.sourceId);
|
|
63
|
+
if (rel.targetId !== id)
|
|
64
|
+
relatedIds.add(rel.targetId);
|
|
65
|
+
}
|
|
66
|
+
const relatedNodes = Array.from(relatedIds)
|
|
67
|
+
.map(rid => this.db.getNode(rid))
|
|
68
|
+
.filter(n => n !== undefined);
|
|
69
|
+
return {
|
|
70
|
+
node,
|
|
71
|
+
relationships,
|
|
72
|
+
relatedNodes,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Find nodes by type
|
|
77
|
+
*/
|
|
78
|
+
async getNodesByType(type) {
|
|
79
|
+
return this.db.getNodesByType(type);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get graph statistics
|
|
83
|
+
*/
|
|
84
|
+
getStats() {
|
|
85
|
+
return this.db.getStats();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/search/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type HivemindConfig } from './types/index.js';
|
|
2
|
+
export declare class HivemindServer {
|
|
3
|
+
private server;
|
|
4
|
+
private config;
|
|
5
|
+
private vaultReader;
|
|
6
|
+
private vaultWatcher;
|
|
7
|
+
private database;
|
|
8
|
+
private graphBuilder;
|
|
9
|
+
private searchEngine;
|
|
10
|
+
private isIndexed;
|
|
11
|
+
constructor(config: HivemindConfig);
|
|
12
|
+
private setupHandlers;
|
|
13
|
+
private handleQueryCharacter;
|
|
14
|
+
private handleQueryLocation;
|
|
15
|
+
private handleSearchVault;
|
|
16
|
+
private setupVaultWatcher;
|
|
17
|
+
private ensureIndexed;
|
|
18
|
+
private formatCharacterWithRelationships;
|
|
19
|
+
private formatLocationWithRelationships;
|
|
20
|
+
private formatSearchResults;
|
|
21
|
+
start(): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=server.d.ts.map
|