@noesis-brain/mcp-server 2.0.0 → 2.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 -5
- package/dist/agent/runner.d.ts +25 -0
- package/dist/agent/runner.d.ts.map +1 -0
- package/dist/agent/runner.js +218 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/api/NoesisClient.d.ts +119 -0
- package/dist/api/NoesisClient.d.ts.map +1 -1
- package/dist/api/NoesisClient.js +130 -6
- package/dist/api/NoesisClient.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +409 -35
- package/dist/cli/setup.js.map +1 -1
- package/dist/database/PostgresAdapter.js +216 -216
- package/dist/index.js +31 -1
- package/dist/index.js.map +1 -1
- package/dist/resolve/noteRef.d.ts +101 -0
- package/dist/resolve/noteRef.d.ts.map +1 -0
- package/dist/resolve/noteRef.js +186 -0
- package/dist/resolve/noteRef.js.map +1 -0
- package/dist/resolve/rootsFormat.d.ts +12 -0
- package/dist/resolve/rootsFormat.d.ts.map +1 -0
- package/dist/resolve/rootsFormat.js +63 -0
- package/dist/resolve/rootsFormat.js.map +1 -0
- package/dist/services/embedding.js +19 -19
- package/dist/tools/backlog.d.ts +4 -0
- package/dist/tools/backlog.d.ts.map +1 -0
- package/dist/tools/backlog.js +157 -0
- package/dist/tools/backlog.js.map +1 -0
- package/dist/tools/index.d.ts +52 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +438 -142
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/navis.d.ts.map +1 -1
- package/dist/tools/navis.js +4 -0
- package/dist/tools/navis.js.map +1 -1
- package/package.json +9 -4
- package/scripts/agent-e2e.mjs +69 -0
- package/scripts/noesis-capture-session-end.mjs +94 -0
- package/scripts/noesis-capture-watcher.mjs +907 -0
- package/scripts/noesis-sync.mjs +469 -469
- package/skill-templates/noesis-capture.md +166 -0
- package/skill-templates/noesis-create-study-note.md +149 -0
- package/skill-templates/noesis-find-related.md +89 -0
- package/skill-templates/noesis-investigate.md +90 -0
- package/skill-templates/noesis-manage-news.md +80 -0
- package/skill-templates/noesis-refine-note.md +92 -92
- package/skill-templates/noesis-skim-read.md +72 -0
- package/skill-templates/noesis-sync.md +110 -110
- package/templates/claude-md-block.md +26 -22
- package/templates/claude-md-restructure-on-sync.md +10 -0
|
@@ -44,21 +44,21 @@ export class PostgresAdapter {
|
|
|
44
44
|
}
|
|
45
45
|
// Use PostgreSQL full-text search with ts_rank
|
|
46
46
|
const userFilter = this.buildUserFilter(1);
|
|
47
|
-
let sql = `
|
|
48
|
-
SELECT
|
|
49
|
-
n.id,
|
|
50
|
-
n.title,
|
|
51
|
-
n.content,
|
|
52
|
-
n.file_path,
|
|
53
|
-
n.description,
|
|
54
|
-
n.points,
|
|
55
|
-
n.is_favorite,
|
|
56
|
-
n.modified_at,
|
|
57
|
-
ts_rank(n.fts_vector, plainto_tsquery('english', $${userFilter.nextParamIndex})) as relevance_score
|
|
58
|
-
FROM notes n
|
|
59
|
-
WHERE n.fts_vector @@ plainto_tsquery('english', $${userFilter.nextParamIndex})
|
|
60
|
-
AND COALESCE(n.is_trashed, FALSE) = FALSE
|
|
61
|
-
AND ${userFilter.condition}
|
|
47
|
+
let sql = `
|
|
48
|
+
SELECT
|
|
49
|
+
n.id,
|
|
50
|
+
n.title,
|
|
51
|
+
n.content,
|
|
52
|
+
n.file_path,
|
|
53
|
+
n.description,
|
|
54
|
+
n.points,
|
|
55
|
+
n.is_favorite,
|
|
56
|
+
n.modified_at,
|
|
57
|
+
ts_rank(n.fts_vector, plainto_tsquery('english', $${userFilter.nextParamIndex})) as relevance_score
|
|
58
|
+
FROM notes n
|
|
59
|
+
WHERE n.fts_vector @@ plainto_tsquery('english', $${userFilter.nextParamIndex})
|
|
60
|
+
AND COALESCE(n.is_trashed, FALSE) = FALSE
|
|
61
|
+
AND ${userFilter.condition}
|
|
62
62
|
`;
|
|
63
63
|
const params = [...userFilter.params, searchTerms];
|
|
64
64
|
let paramIndex = userFilter.nextParamIndex + 1;
|
|
@@ -92,20 +92,20 @@ export class PostgresAdapter {
|
|
|
92
92
|
const { limit = 10, root } = options;
|
|
93
93
|
const likePattern = `%${query}%`;
|
|
94
94
|
const userFilter = this.buildUserFilter(1);
|
|
95
|
-
let sql = `
|
|
96
|
-
SELECT
|
|
97
|
-
id,
|
|
98
|
-
title,
|
|
99
|
-
content,
|
|
100
|
-
file_path,
|
|
101
|
-
description,
|
|
102
|
-
points,
|
|
103
|
-
is_favorite,
|
|
104
|
-
modified_at
|
|
105
|
-
FROM notes
|
|
106
|
-
WHERE (title ILIKE $${userFilter.nextParamIndex} OR description ILIKE $${userFilter.nextParamIndex} OR content ILIKE $${userFilter.nextParamIndex})
|
|
107
|
-
AND COALESCE(is_trashed, FALSE) = FALSE
|
|
108
|
-
AND ${userFilter.condition}
|
|
95
|
+
let sql = `
|
|
96
|
+
SELECT
|
|
97
|
+
id,
|
|
98
|
+
title,
|
|
99
|
+
content,
|
|
100
|
+
file_path,
|
|
101
|
+
description,
|
|
102
|
+
points,
|
|
103
|
+
is_favorite,
|
|
104
|
+
modified_at
|
|
105
|
+
FROM notes
|
|
106
|
+
WHERE (title ILIKE $${userFilter.nextParamIndex} OR description ILIKE $${userFilter.nextParamIndex} OR content ILIKE $${userFilter.nextParamIndex})
|
|
107
|
+
AND COALESCE(is_trashed, FALSE) = FALSE
|
|
108
|
+
AND ${userFilter.condition}
|
|
109
109
|
`;
|
|
110
110
|
const params = [...userFilter.params, likePattern];
|
|
111
111
|
let paramIndex = userFilter.nextParamIndex + 1;
|
|
@@ -149,10 +149,10 @@ export class PostgresAdapter {
|
|
|
149
149
|
async listNotes(options = {}) {
|
|
150
150
|
const { limit = 50, offset = 0, root } = options;
|
|
151
151
|
const userFilter = this.buildUserFilter(1);
|
|
152
|
-
let sql = `
|
|
153
|
-
SELECT * FROM notes
|
|
154
|
-
WHERE COALESCE(is_trashed, FALSE) = FALSE
|
|
155
|
-
AND ${userFilter.condition}
|
|
152
|
+
let sql = `
|
|
153
|
+
SELECT * FROM notes
|
|
154
|
+
WHERE COALESCE(is_trashed, FALSE) = FALSE
|
|
155
|
+
AND ${userFilter.condition}
|
|
156
156
|
`;
|
|
157
157
|
const params = [...userFilter.params];
|
|
158
158
|
let paramIndex = userFilter.nextParamIndex;
|
|
@@ -173,13 +173,13 @@ export class PostgresAdapter {
|
|
|
173
173
|
const cutoffDate = new Date();
|
|
174
174
|
cutoffDate.setDate(cutoffDate.getDate() - days);
|
|
175
175
|
const userFilter = this.buildUserFilter(3);
|
|
176
|
-
const result = await this.pool.query(`
|
|
177
|
-
SELECT * FROM notes
|
|
178
|
-
WHERE modified_at >= $1
|
|
179
|
-
AND COALESCE(is_trashed, FALSE) = FALSE
|
|
180
|
-
AND ${userFilter.condition}
|
|
181
|
-
ORDER BY modified_at DESC
|
|
182
|
-
LIMIT $2
|
|
176
|
+
const result = await this.pool.query(`
|
|
177
|
+
SELECT * FROM notes
|
|
178
|
+
WHERE modified_at >= $1
|
|
179
|
+
AND COALESCE(is_trashed, FALSE) = FALSE
|
|
180
|
+
AND ${userFilter.condition}
|
|
181
|
+
ORDER BY modified_at DESC
|
|
182
|
+
LIMIT $2
|
|
183
183
|
`, [cutoffDate.toISOString(), limit, ...userFilter.params]);
|
|
184
184
|
return result.rows;
|
|
185
185
|
}
|
|
@@ -188,11 +188,11 @@ export class PostgresAdapter {
|
|
|
188
188
|
*/
|
|
189
189
|
async getRoots() {
|
|
190
190
|
const userFilter = this.buildUserFilter(1);
|
|
191
|
-
const result = await this.pool.query(`
|
|
192
|
-
SELECT id, path, name, COALESCE(is_visible, TRUE) as is_visible
|
|
193
|
-
FROM roots
|
|
194
|
-
WHERE COALESCE(is_visible, TRUE) = TRUE
|
|
195
|
-
AND ${userFilter.condition}
|
|
191
|
+
const result = await this.pool.query(`
|
|
192
|
+
SELECT id, path, name, COALESCE(is_visible, TRUE) as is_visible
|
|
193
|
+
FROM roots
|
|
194
|
+
WHERE COALESCE(is_visible, TRUE) = TRUE
|
|
195
|
+
AND ${userFilter.condition}
|
|
196
196
|
`, userFilter.params);
|
|
197
197
|
return result.rows;
|
|
198
198
|
}
|
|
@@ -283,19 +283,19 @@ export class PostgresAdapter {
|
|
|
283
283
|
*/
|
|
284
284
|
async getNotesForPull(options = {}) {
|
|
285
285
|
const { root, rootId } = options;
|
|
286
|
-
let sql = `
|
|
287
|
-
SELECT
|
|
288
|
-
n.id,
|
|
289
|
-
n.relative_path,
|
|
290
|
-
n.content,
|
|
291
|
-
n.title,
|
|
292
|
-
r.name as root_name,
|
|
293
|
-
r.path as root_path,
|
|
294
|
-
n.modified_at
|
|
295
|
-
FROM notes n
|
|
296
|
-
JOIN roots r ON n.root_id = r.id
|
|
297
|
-
WHERE COALESCE(n.is_trashed, FALSE) = FALSE
|
|
298
|
-
AND n.relative_path IS NOT NULL
|
|
286
|
+
let sql = `
|
|
287
|
+
SELECT
|
|
288
|
+
n.id,
|
|
289
|
+
n.relative_path,
|
|
290
|
+
n.content,
|
|
291
|
+
n.title,
|
|
292
|
+
r.name as root_name,
|
|
293
|
+
r.path as root_path,
|
|
294
|
+
n.modified_at
|
|
295
|
+
FROM notes n
|
|
296
|
+
JOIN roots r ON n.root_id = r.id
|
|
297
|
+
WHERE COALESCE(n.is_trashed, FALSE) = FALSE
|
|
298
|
+
AND n.relative_path IS NOT NULL
|
|
299
299
|
`;
|
|
300
300
|
const params = [];
|
|
301
301
|
let paramIndex = 1;
|
|
@@ -336,20 +336,20 @@ export class PostgresAdapter {
|
|
|
336
336
|
return 'skipped';
|
|
337
337
|
}
|
|
338
338
|
// Update existing note (also sets relative_path and project in case they were NULL)
|
|
339
|
-
await this.pool.query(`
|
|
340
|
-
UPDATE notes SET
|
|
341
|
-
content = $1,
|
|
342
|
-
hash = $2,
|
|
343
|
-
title = $3,
|
|
344
|
-
description = $4,
|
|
345
|
-
keywords = $5::jsonb,
|
|
346
|
-
file_path = $6,
|
|
347
|
-
relative_path = $7,
|
|
348
|
-
file_size = $8,
|
|
349
|
-
project = $9,
|
|
350
|
-
modified_at = NOW(),
|
|
351
|
-
indexed_at = NOW()
|
|
352
|
-
WHERE id = $10
|
|
339
|
+
await this.pool.query(`
|
|
340
|
+
UPDATE notes SET
|
|
341
|
+
content = $1,
|
|
342
|
+
hash = $2,
|
|
343
|
+
title = $3,
|
|
344
|
+
description = $4,
|
|
345
|
+
keywords = $5::jsonb,
|
|
346
|
+
file_path = $6,
|
|
347
|
+
relative_path = $7,
|
|
348
|
+
file_size = $8,
|
|
349
|
+
project = $9,
|
|
350
|
+
modified_at = NOW(),
|
|
351
|
+
indexed_at = NOW()
|
|
352
|
+
WHERE id = $10
|
|
353
353
|
`, [
|
|
354
354
|
file.content,
|
|
355
355
|
file.hash,
|
|
@@ -365,11 +365,11 @@ export class PostgresAdapter {
|
|
|
365
365
|
return 'updated';
|
|
366
366
|
}
|
|
367
367
|
// Insert new note (include user_id and project if configured)
|
|
368
|
-
await this.pool.query(`
|
|
369
|
-
INSERT INTO notes (
|
|
370
|
-
root_id, file_path, relative_path, content, hash,
|
|
371
|
-
title, description, keywords, file_size, project, modified_at, indexed_at, user_id
|
|
372
|
-
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9, $10, NOW(), NOW(), $11)
|
|
368
|
+
await this.pool.query(`
|
|
369
|
+
INSERT INTO notes (
|
|
370
|
+
root_id, file_path, relative_path, content, hash,
|
|
371
|
+
title, description, keywords, file_size, project, modified_at, indexed_at, user_id
|
|
372
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9, $10, NOW(), NOW(), $11)
|
|
373
373
|
`, [
|
|
374
374
|
file.rootId,
|
|
375
375
|
file.path,
|
|
@@ -390,11 +390,11 @@ export class PostgresAdapter {
|
|
|
390
390
|
*/
|
|
391
391
|
async getRootsForSync() {
|
|
392
392
|
const userFilter = this.buildUserFilter(1);
|
|
393
|
-
const result = await this.pool.query(`
|
|
394
|
-
SELECT id, name, path, last_scanned_at
|
|
395
|
-
FROM roots
|
|
396
|
-
WHERE COALESCE(is_visible, TRUE) = TRUE
|
|
397
|
-
AND ${userFilter.condition}
|
|
393
|
+
const result = await this.pool.query(`
|
|
394
|
+
SELECT id, name, path, last_scanned_at
|
|
395
|
+
FROM roots
|
|
396
|
+
WHERE COALESCE(is_visible, TRUE) = TRUE
|
|
397
|
+
AND ${userFilter.condition}
|
|
398
398
|
`, userFilter.params);
|
|
399
399
|
return result.rows.map(row => ({
|
|
400
400
|
id: row.id,
|
|
@@ -416,10 +416,10 @@ export class PostgresAdapter {
|
|
|
416
416
|
*/
|
|
417
417
|
async createRoot(options) {
|
|
418
418
|
const { name, path, type = 'folder' } = options;
|
|
419
|
-
const result = await this.pool.query(`
|
|
420
|
-
INSERT INTO roots (name, path, type, is_active, is_visible, user_id)
|
|
421
|
-
VALUES ($1, $2, $3, FALSE, TRUE, $4)
|
|
422
|
-
RETURNING id, name, path
|
|
419
|
+
const result = await this.pool.query(`
|
|
420
|
+
INSERT INTO roots (name, path, type, is_active, is_visible, user_id)
|
|
421
|
+
VALUES ($1, $2, $3, FALSE, TRUE, $4)
|
|
422
|
+
RETURNING id, name, path
|
|
423
423
|
`, [name, path, type, this.userId]);
|
|
424
424
|
return result.rows[0];
|
|
425
425
|
}
|
|
@@ -427,9 +427,9 @@ export class PostgresAdapter {
|
|
|
427
427
|
* Log a sync operation (for Dashboard sync activity display)
|
|
428
428
|
*/
|
|
429
429
|
async logSyncOperation(options) {
|
|
430
|
-
await this.pool.query(`
|
|
431
|
-
INSERT INTO sync_logs (root_id, files_scanned, files_added, files_updated, files_deleted, source, machine_name, notes)
|
|
432
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
430
|
+
await this.pool.query(`
|
|
431
|
+
INSERT INTO sync_logs (root_id, files_scanned, files_added, files_updated, files_deleted, source, machine_name, notes)
|
|
432
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
433
433
|
`, [
|
|
434
434
|
options.rootId,
|
|
435
435
|
options.filesScanned,
|
|
@@ -445,10 +445,10 @@ export class PostgresAdapter {
|
|
|
445
445
|
* Get recent sync logs for a root
|
|
446
446
|
*/
|
|
447
447
|
async getSyncLogs(rootId, limit = 10) {
|
|
448
|
-
let sql = `
|
|
449
|
-
SELECT id, root_id, synced_at, files_scanned, files_added,
|
|
450
|
-
files_updated, files_deleted, source, machine_name, notes
|
|
451
|
-
FROM sync_logs
|
|
448
|
+
let sql = `
|
|
449
|
+
SELECT id, root_id, synced_at, files_scanned, files_added,
|
|
450
|
+
files_updated, files_deleted, source, machine_name, notes
|
|
451
|
+
FROM sync_logs
|
|
452
452
|
`;
|
|
453
453
|
const params = [];
|
|
454
454
|
let paramIndex = 1;
|
|
@@ -490,9 +490,9 @@ export class PostgresAdapter {
|
|
|
490
490
|
* Set last sync time in settings
|
|
491
491
|
*/
|
|
492
492
|
async setLastSyncTime(timestamp) {
|
|
493
|
-
await this.pool.query(`
|
|
494
|
-
INSERT INTO settings (key, value) VALUES ('last_sync_time', $1)
|
|
495
|
-
ON CONFLICT (key) DO UPDATE SET value = $1
|
|
493
|
+
await this.pool.query(`
|
|
494
|
+
INSERT INTO settings (key, value) VALUES ('last_sync_time', $1)
|
|
495
|
+
ON CONFLICT (key) DO UPDATE SET value = $1
|
|
496
496
|
`, [timestamp]);
|
|
497
497
|
}
|
|
498
498
|
/**
|
|
@@ -500,12 +500,12 @@ export class PostgresAdapter {
|
|
|
500
500
|
*/
|
|
501
501
|
async getNoteCountByRoot() {
|
|
502
502
|
const userFilter = this.buildUserFilter(1);
|
|
503
|
-
const result = await this.pool.query(`
|
|
504
|
-
SELECT root_id, COUNT(*) as count
|
|
505
|
-
FROM notes
|
|
506
|
-
WHERE COALESCE(is_trashed, FALSE) = FALSE
|
|
507
|
-
AND ${userFilter.condition}
|
|
508
|
-
GROUP BY root_id
|
|
503
|
+
const result = await this.pool.query(`
|
|
504
|
+
SELECT root_id, COUNT(*) as count
|
|
505
|
+
FROM notes
|
|
506
|
+
WHERE COALESCE(is_trashed, FALSE) = FALSE
|
|
507
|
+
AND ${userFilter.condition}
|
|
508
|
+
GROUP BY root_id
|
|
509
509
|
`, userFilter.params);
|
|
510
510
|
const counts = new Map();
|
|
511
511
|
for (const row of result.rows) {
|
|
@@ -565,16 +565,16 @@ export class PostgresAdapter {
|
|
|
565
565
|
*/
|
|
566
566
|
async getNoteForEnhancement(id) {
|
|
567
567
|
const userFilter = this.buildUserFilter(2);
|
|
568
|
-
const result = await this.pool.query(`
|
|
569
|
-
SELECT
|
|
570
|
-
n.id, n.title, n.description, n.keywords,
|
|
571
|
-
COALESCE(n.aliases, '{}') as aliases,
|
|
572
|
-
n.content, n.file_path, n.ai_enhanced_at,
|
|
573
|
-
r.name as root_name
|
|
574
|
-
FROM notes n
|
|
575
|
-
LEFT JOIN roots r ON n.root_id = r.id
|
|
576
|
-
WHERE n.id = $1 AND COALESCE(n.is_trashed, FALSE) = FALSE
|
|
577
|
-
AND n.${userFilter.condition}
|
|
568
|
+
const result = await this.pool.query(`
|
|
569
|
+
SELECT
|
|
570
|
+
n.id, n.title, n.description, n.keywords,
|
|
571
|
+
COALESCE(n.aliases, '{}') as aliases,
|
|
572
|
+
n.content, n.file_path, n.ai_enhanced_at,
|
|
573
|
+
r.name as root_name
|
|
574
|
+
FROM notes n
|
|
575
|
+
LEFT JOIN roots r ON n.root_id = r.id
|
|
576
|
+
WHERE n.id = $1 AND COALESCE(n.is_trashed, FALSE) = FALSE
|
|
577
|
+
AND n.${userFilter.condition}
|
|
578
578
|
`, [id, ...userFilter.params]);
|
|
579
579
|
if (result.rows.length === 0)
|
|
580
580
|
return null;
|
|
@@ -597,19 +597,19 @@ export class PostgresAdapter {
|
|
|
597
597
|
async getNotesNeedingEnhancement(options = {}) {
|
|
598
598
|
const { root, limit = 50, important_only = false } = options;
|
|
599
599
|
const userFilter = this.buildUserFilter(1);
|
|
600
|
-
let sql = `
|
|
601
|
-
SELECT
|
|
602
|
-
id, title, file_path,
|
|
603
|
-
(description IS NOT NULL AND description != '') as has_description,
|
|
604
|
-
(keywords IS NOT NULL AND jsonb_array_length(keywords) > 0) as has_keywords,
|
|
605
|
-
COALESCE(is_favorite, FALSE) as is_favorite,
|
|
606
|
-
(content LIKE '%⭐%') as has_stars,
|
|
607
|
-
COALESCE(points, 0) as points,
|
|
608
|
-
ai_enhanced_at
|
|
609
|
-
FROM notes
|
|
610
|
-
WHERE COALESCE(is_trashed, FALSE) = FALSE
|
|
611
|
-
AND (description IS NULL OR description = '' OR keywords IS NULL OR jsonb_array_length(keywords) = 0)
|
|
612
|
-
AND ${userFilter.condition}
|
|
600
|
+
let sql = `
|
|
601
|
+
SELECT
|
|
602
|
+
id, title, file_path,
|
|
603
|
+
(description IS NOT NULL AND description != '') as has_description,
|
|
604
|
+
(keywords IS NOT NULL AND jsonb_array_length(keywords) > 0) as has_keywords,
|
|
605
|
+
COALESCE(is_favorite, FALSE) as is_favorite,
|
|
606
|
+
(content LIKE '%⭐%') as has_stars,
|
|
607
|
+
COALESCE(points, 0) as points,
|
|
608
|
+
ai_enhanced_at
|
|
609
|
+
FROM notes
|
|
610
|
+
WHERE COALESCE(is_trashed, FALSE) = FALSE
|
|
611
|
+
AND (description IS NULL OR description = '' OR keywords IS NULL OR jsonb_array_length(keywords) = 0)
|
|
612
|
+
AND ${userFilter.condition}
|
|
613
613
|
`;
|
|
614
614
|
const params = [...userFilter.params];
|
|
615
615
|
let paramIndex = userFilter.nextParamIndex;
|
|
@@ -674,16 +674,16 @@ export class PostgresAdapter {
|
|
|
674
674
|
*/
|
|
675
675
|
async getNoteForScoring(id) {
|
|
676
676
|
const userFilter = this.buildUserFilter(2);
|
|
677
|
-
const result = await this.pool.query(`
|
|
678
|
-
SELECT
|
|
679
|
-
id, title, description, keywords, content, file_path,
|
|
680
|
-
importance_score, quality_score,
|
|
681
|
-
COALESCE(relations, '[]'::jsonb) as relations,
|
|
682
|
-
COALESCE(is_favorite, FALSE) as is_favorite,
|
|
683
|
-
COALESCE(points, 0) as points
|
|
684
|
-
FROM notes
|
|
685
|
-
WHERE id = $1 AND COALESCE(is_trashed, FALSE) = FALSE
|
|
686
|
-
AND ${userFilter.condition}
|
|
677
|
+
const result = await this.pool.query(`
|
|
678
|
+
SELECT
|
|
679
|
+
id, title, description, keywords, content, file_path,
|
|
680
|
+
importance_score, quality_score,
|
|
681
|
+
COALESCE(relations, '[]'::jsonb) as relations,
|
|
682
|
+
COALESCE(is_favorite, FALSE) as is_favorite,
|
|
683
|
+
COALESCE(points, 0) as points
|
|
684
|
+
FROM notes
|
|
685
|
+
WHERE id = $1 AND COALESCE(is_trashed, FALSE) = FALSE
|
|
686
|
+
AND ${userFilter.condition}
|
|
687
687
|
`, [id, ...userFilter.params]);
|
|
688
688
|
if (result.rows.length === 0)
|
|
689
689
|
return null;
|
|
@@ -770,11 +770,11 @@ export class PostgresAdapter {
|
|
|
770
770
|
async getNotesForRelationAnalysis(excludeId, options = {}) {
|
|
771
771
|
const { root, limit = 50 } = options;
|
|
772
772
|
const userFilter = this.buildUserFilter(2);
|
|
773
|
-
let sql = `
|
|
774
|
-
SELECT id, title, description, keywords, file_path
|
|
775
|
-
FROM notes
|
|
776
|
-
WHERE id != $1 AND COALESCE(is_trashed, FALSE) = FALSE
|
|
777
|
-
AND ${userFilter.condition}
|
|
773
|
+
let sql = `
|
|
774
|
+
SELECT id, title, description, keywords, file_path
|
|
775
|
+
FROM notes
|
|
776
|
+
WHERE id != $1 AND COALESCE(is_trashed, FALSE) = FALSE
|
|
777
|
+
AND ${userFilter.condition}
|
|
778
778
|
`;
|
|
779
779
|
const params = [excludeId, ...userFilter.params];
|
|
780
780
|
let paramIndex = userFilter.nextParamIndex;
|
|
@@ -810,54 +810,54 @@ export class PostgresAdapter {
|
|
|
810
810
|
paramIndex++;
|
|
811
811
|
}
|
|
812
812
|
// Get aggregate stats
|
|
813
|
-
const statsResult = await this.pool.query(`
|
|
814
|
-
SELECT
|
|
815
|
-
COUNT(*) as total,
|
|
816
|
-
COUNT(importance_score) as with_importance,
|
|
817
|
-
COUNT(quality_score) as with_quality,
|
|
818
|
-
COUNT(*) FILTER (WHERE jsonb_array_length(COALESCE(relations, '[]'::jsonb)) > 0) as with_relations,
|
|
819
|
-
COUNT(*) FILTER (WHERE description IS NOT NULL AND description != '') as with_description,
|
|
820
|
-
COUNT(*) FILTER (WHERE keywords IS NOT NULL AND jsonb_array_length(keywords) > 0) as with_keywords
|
|
821
|
-
FROM notes
|
|
822
|
-
WHERE ${whereClause}
|
|
813
|
+
const statsResult = await this.pool.query(`
|
|
814
|
+
SELECT
|
|
815
|
+
COUNT(*) as total,
|
|
816
|
+
COUNT(importance_score) as with_importance,
|
|
817
|
+
COUNT(quality_score) as with_quality,
|
|
818
|
+
COUNT(*) FILTER (WHERE jsonb_array_length(COALESCE(relations, '[]'::jsonb)) > 0) as with_relations,
|
|
819
|
+
COUNT(*) FILTER (WHERE description IS NOT NULL AND description != '') as with_description,
|
|
820
|
+
COUNT(*) FILTER (WHERE keywords IS NOT NULL AND jsonb_array_length(keywords) > 0) as with_keywords
|
|
821
|
+
FROM notes
|
|
822
|
+
WHERE ${whereClause}
|
|
823
823
|
`, params);
|
|
824
824
|
const stats = statsResult.rows[0];
|
|
825
825
|
// Get low quality docs (score < 50 or NULL, prioritize NULL)
|
|
826
826
|
const lowQualityParams = [...params, limit];
|
|
827
|
-
const lowQualityResult = await this.pool.query(`
|
|
828
|
-
SELECT id, title, quality_score, file_path
|
|
829
|
-
FROM notes
|
|
830
|
-
WHERE ${whereClause} AND (quality_score IS NULL OR quality_score < 50)
|
|
831
|
-
ORDER BY quality_score NULLS FIRST, modified_at DESC
|
|
832
|
-
LIMIT $${paramIndex}
|
|
827
|
+
const lowQualityResult = await this.pool.query(`
|
|
828
|
+
SELECT id, title, quality_score, file_path
|
|
829
|
+
FROM notes
|
|
830
|
+
WHERE ${whereClause} AND (quality_score IS NULL OR quality_score < 50)
|
|
831
|
+
ORDER BY quality_score NULLS FIRST, modified_at DESC
|
|
832
|
+
LIMIT $${paramIndex}
|
|
833
833
|
`, lowQualityParams);
|
|
834
834
|
// Get low importance docs (score < 30 or NULL)
|
|
835
|
-
const lowImportanceResult = await this.pool.query(`
|
|
836
|
-
SELECT id, title, importance_score, file_path
|
|
837
|
-
FROM notes
|
|
838
|
-
WHERE ${whereClause} AND (importance_score IS NULL OR importance_score < 30)
|
|
839
|
-
ORDER BY importance_score NULLS FIRST, modified_at DESC
|
|
840
|
-
LIMIT $${paramIndex}
|
|
835
|
+
const lowImportanceResult = await this.pool.query(`
|
|
836
|
+
SELECT id, title, importance_score, file_path
|
|
837
|
+
FROM notes
|
|
838
|
+
WHERE ${whereClause} AND (importance_score IS NULL OR importance_score < 30)
|
|
839
|
+
ORDER BY importance_score NULLS FIRST, modified_at DESC
|
|
840
|
+
LIMIT $${paramIndex}
|
|
841
841
|
`, lowQualityParams);
|
|
842
842
|
// Get orphan docs (no relations)
|
|
843
|
-
const orphansResult = await this.pool.query(`
|
|
844
|
-
SELECT id, title, file_path
|
|
845
|
-
FROM notes
|
|
846
|
-
WHERE ${whereClause} AND (relations IS NULL OR jsonb_array_length(relations) = 0)
|
|
847
|
-
ORDER BY modified_at DESC
|
|
848
|
-
LIMIT $${paramIndex}
|
|
843
|
+
const orphansResult = await this.pool.query(`
|
|
844
|
+
SELECT id, title, file_path
|
|
845
|
+
FROM notes
|
|
846
|
+
WHERE ${whereClause} AND (relations IS NULL OR jsonb_array_length(relations) = 0)
|
|
847
|
+
ORDER BY modified_at DESC
|
|
848
|
+
LIMIT $${paramIndex}
|
|
849
849
|
`, lowQualityParams);
|
|
850
850
|
// Get docs missing metadata
|
|
851
|
-
const missingMetadataResult = await this.pool.query(`
|
|
852
|
-
SELECT
|
|
853
|
-
id, title, file_path,
|
|
854
|
-
(description IS NULL OR description = '') as missing_desc,
|
|
855
|
-
(keywords IS NULL OR jsonb_array_length(keywords) = 0) as missing_kw
|
|
856
|
-
FROM notes
|
|
857
|
-
WHERE ${whereClause}
|
|
858
|
-
AND ((description IS NULL OR description = '') OR (keywords IS NULL OR jsonb_array_length(keywords) = 0))
|
|
859
|
-
ORDER BY modified_at DESC
|
|
860
|
-
LIMIT $${paramIndex}
|
|
851
|
+
const missingMetadataResult = await this.pool.query(`
|
|
852
|
+
SELECT
|
|
853
|
+
id, title, file_path,
|
|
854
|
+
(description IS NULL OR description = '') as missing_desc,
|
|
855
|
+
(keywords IS NULL OR jsonb_array_length(keywords) = 0) as missing_kw
|
|
856
|
+
FROM notes
|
|
857
|
+
WHERE ${whereClause}
|
|
858
|
+
AND ((description IS NULL OR description = '') OR (keywords IS NULL OR jsonb_array_length(keywords) = 0))
|
|
859
|
+
ORDER BY modified_at DESC
|
|
860
|
+
LIMIT $${paramIndex}
|
|
861
861
|
`, lowQualityParams);
|
|
862
862
|
return {
|
|
863
863
|
total: parseInt(stats.total),
|
|
@@ -889,12 +889,12 @@ export class PostgresAdapter {
|
|
|
889
889
|
async getNotesWithoutEmbeddings(options = {}) {
|
|
890
890
|
const { limit = 50, root } = options;
|
|
891
891
|
const userFilter = this.buildUserFilter(1);
|
|
892
|
-
let sql = `
|
|
893
|
-
SELECT id, title, content, file_path
|
|
894
|
-
FROM notes
|
|
895
|
-
WHERE embedding IS NULL
|
|
896
|
-
AND COALESCE(is_trashed, FALSE) = FALSE
|
|
897
|
-
AND ${userFilter.condition}
|
|
892
|
+
let sql = `
|
|
893
|
+
SELECT id, title, content, file_path
|
|
894
|
+
FROM notes
|
|
895
|
+
WHERE embedding IS NULL
|
|
896
|
+
AND COALESCE(is_trashed, FALSE) = FALSE
|
|
897
|
+
AND ${userFilter.condition}
|
|
898
898
|
`;
|
|
899
899
|
const params = [...userFilter.params];
|
|
900
900
|
let paramIndex = userFilter.nextParamIndex;
|
|
@@ -925,14 +925,14 @@ export class PostgresAdapter {
|
|
|
925
925
|
const { limit = 10, root } = options;
|
|
926
926
|
const vectorString = `[${embedding.join(',')}]`;
|
|
927
927
|
const userFilter = this.buildUserFilter(2);
|
|
928
|
-
let sql = `
|
|
929
|
-
SELECT
|
|
930
|
-
id, title, description, file_path,
|
|
931
|
-
1 - (embedding <=> $1::vector) as similarity
|
|
932
|
-
FROM notes
|
|
933
|
-
WHERE embedding IS NOT NULL
|
|
934
|
-
AND COALESCE(is_trashed, FALSE) = FALSE
|
|
935
|
-
AND ${userFilter.condition}
|
|
928
|
+
let sql = `
|
|
929
|
+
SELECT
|
|
930
|
+
id, title, description, file_path,
|
|
931
|
+
1 - (embedding <=> $1::vector) as similarity
|
|
932
|
+
FROM notes
|
|
933
|
+
WHERE embedding IS NOT NULL
|
|
934
|
+
AND COALESCE(is_trashed, FALSE) = FALSE
|
|
935
|
+
AND ${userFilter.condition}
|
|
936
936
|
`;
|
|
937
937
|
const params = [vectorString, ...userFilter.params];
|
|
938
938
|
let paramIndex = userFilter.nextParamIndex;
|
|
@@ -957,11 +957,11 @@ export class PostgresAdapter {
|
|
|
957
957
|
*/
|
|
958
958
|
async getNoteEmbedding(id) {
|
|
959
959
|
const userFilter = this.buildUserFilter(2);
|
|
960
|
-
const result = await this.pool.query(`
|
|
961
|
-
SELECT id, title, embedding
|
|
962
|
-
FROM notes
|
|
963
|
-
WHERE id = $1 AND COALESCE(is_trashed, FALSE) = FALSE
|
|
964
|
-
AND ${userFilter.condition}
|
|
960
|
+
const result = await this.pool.query(`
|
|
961
|
+
SELECT id, title, embedding
|
|
962
|
+
FROM notes
|
|
963
|
+
WHERE id = $1 AND COALESCE(is_trashed, FALSE) = FALSE
|
|
964
|
+
AND ${userFilter.condition}
|
|
965
965
|
`, [id, ...userFilter.params]);
|
|
966
966
|
if (result.rows.length === 0)
|
|
967
967
|
return null;
|
|
@@ -992,17 +992,17 @@ export class PostgresAdapter {
|
|
|
992
992
|
}
|
|
993
993
|
// Find similar notes (excluding the source note)
|
|
994
994
|
const similarUserFilter = this.buildUserFilter(4);
|
|
995
|
-
const result = await this.pool.query(`
|
|
996
|
-
SELECT
|
|
997
|
-
id, title, description, file_path,
|
|
998
|
-
1 - (embedding <=> $1) as similarity
|
|
999
|
-
FROM notes
|
|
1000
|
-
WHERE id != $2
|
|
1001
|
-
AND embedding IS NOT NULL
|
|
1002
|
-
AND COALESCE(is_trashed, FALSE) = FALSE
|
|
1003
|
-
AND ${similarUserFilter.condition}
|
|
1004
|
-
ORDER BY embedding <=> $1
|
|
1005
|
-
LIMIT $3
|
|
995
|
+
const result = await this.pool.query(`
|
|
996
|
+
SELECT
|
|
997
|
+
id, title, description, file_path,
|
|
998
|
+
1 - (embedding <=> $1) as similarity
|
|
999
|
+
FROM notes
|
|
1000
|
+
WHERE id != $2
|
|
1001
|
+
AND embedding IS NOT NULL
|
|
1002
|
+
AND COALESCE(is_trashed, FALSE) = FALSE
|
|
1003
|
+
AND ${similarUserFilter.condition}
|
|
1004
|
+
ORDER BY embedding <=> $1
|
|
1005
|
+
LIMIT $3
|
|
1006
1006
|
`, [noteResult.rows[0].embedding, noteId, limit, ...similarUserFilter.params]);
|
|
1007
1007
|
return result.rows.map(row => ({
|
|
1008
1008
|
id: row.id,
|
|
@@ -1017,14 +1017,14 @@ export class PostgresAdapter {
|
|
|
1017
1017
|
*/
|
|
1018
1018
|
async getEmbeddingStats() {
|
|
1019
1019
|
const userFilter = this.buildUserFilter(1);
|
|
1020
|
-
const result = await this.pool.query(`
|
|
1021
|
-
SELECT
|
|
1022
|
-
COUNT(*) as total,
|
|
1023
|
-
COUNT(embedding) as with_embeddings,
|
|
1024
|
-
COUNT(*) - COUNT(embedding) as without_embeddings
|
|
1025
|
-
FROM notes
|
|
1026
|
-
WHERE COALESCE(is_trashed, FALSE) = FALSE
|
|
1027
|
-
AND ${userFilter.condition}
|
|
1020
|
+
const result = await this.pool.query(`
|
|
1021
|
+
SELECT
|
|
1022
|
+
COUNT(*) as total,
|
|
1023
|
+
COUNT(embedding) as with_embeddings,
|
|
1024
|
+
COUNT(*) - COUNT(embedding) as without_embeddings
|
|
1025
|
+
FROM notes
|
|
1026
|
+
WHERE COALESCE(is_trashed, FALSE) = FALSE
|
|
1027
|
+
AND ${userFilter.condition}
|
|
1028
1028
|
`, userFilter.params);
|
|
1029
1029
|
const row = result.rows[0];
|
|
1030
1030
|
return {
|
package/dist/index.js
CHANGED
|
@@ -79,7 +79,31 @@ async function main() {
|
|
|
79
79
|
const subcommand = process.argv[2];
|
|
80
80
|
if (subcommand === 'setup' || subcommand === 'upgrade') {
|
|
81
81
|
const { runSetup } = await import('./cli/setup.js');
|
|
82
|
-
|
|
82
|
+
try {
|
|
83
|
+
await runSetup(process.argv.slice(3));
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
console.error(`\nnoesis-mcp setup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// `noesis-mcp agent` runs the Local Agent daemon (ai_mode = claude-subscription):
|
|
92
|
+
// it polls the Noesis agent-job queue and runs jobs on your own Claude subscription.
|
|
93
|
+
if (subcommand === 'agent') {
|
|
94
|
+
const { runAgentDaemon, resolveAgentConfig } = await import('./agent/runner.js');
|
|
95
|
+
try {
|
|
96
|
+
const cfg = resolveAgentConfig();
|
|
97
|
+
const controller = new AbortController();
|
|
98
|
+
for (const sig of ['SIGINT', 'SIGTERM']) {
|
|
99
|
+
process.on(sig, () => { console.error(`\n[noesis-agent] ${sig} — shutting down`); controller.abort(); });
|
|
100
|
+
}
|
|
101
|
+
await runAgentDaemon(cfg, controller.signal);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
console.error(`\nnoesis-mcp agent failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
83
107
|
return;
|
|
84
108
|
}
|
|
85
109
|
// Get API configuration
|
|
@@ -96,6 +120,12 @@ async function main() {
|
|
|
96
120
|
}
|
|
97
121
|
// Initialize API client (replaces direct database access)
|
|
98
122
|
const client = new NoesisClient(apiBaseUrl, apiToken);
|
|
123
|
+
// Phase 50: fire-and-forget device-home report. Lets the web UI resolve
|
|
124
|
+
// stored `~/Noesis/...` paths to this machine's absolute form for display.
|
|
125
|
+
// Failures (offline, server down) just leave the cache as-is; next startup retries.
|
|
126
|
+
client.reportDeviceHomeDir().catch((err) => {
|
|
127
|
+
console.error(`[noesis-mcp] reportDeviceHomeDir failed (non-fatal): ${err?.message || err}`);
|
|
128
|
+
});
|
|
99
129
|
// Create MCP server
|
|
100
130
|
const server = new McpServer({
|
|
101
131
|
name: 'noesis',
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,oCAAoC;AACpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,yDAAyD;AACzD,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;AAC5D,0DAA0D;AAC1D,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC;AAE/D;;GAEG;AACH,SAAS,YAAY;IACnB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC9C,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAE9C,IAAI,CAAC,QAAQ,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,SAAS,eAAe;IACtB,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;AACpC,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,6FAA6F;IAC7F,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QACvD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACpD,MAAM,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|