@jafreck/lore 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 +405 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +345 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/call-graph.d.ts +39 -0
- package/dist/indexer/call-graph.d.ts.map +1 -0
- package/dist/indexer/call-graph.js +193 -0
- package/dist/indexer/call-graph.js.map +1 -0
- package/dist/indexer/complexity.d.ts +9 -0
- package/dist/indexer/complexity.d.ts.map +1 -0
- package/dist/indexer/complexity.js +66 -0
- package/dist/indexer/complexity.js.map +1 -0
- package/dist/indexer/config-parser.d.ts +16 -0
- package/dist/indexer/config-parser.d.ts.map +1 -0
- package/dist/indexer/config-parser.js +261 -0
- package/dist/indexer/config-parser.js.map +1 -0
- package/dist/indexer/coverage.d.ts +13 -0
- package/dist/indexer/coverage.d.ts.map +1 -0
- package/dist/indexer/coverage.js +84 -0
- package/dist/indexer/coverage.js.map +1 -0
- package/dist/indexer/db.d.ts +38 -0
- package/dist/indexer/db.d.ts.map +1 -0
- package/dist/indexer/db.js +275 -0
- package/dist/indexer/db.js.map +1 -0
- package/dist/indexer/embedder.d.ts +70 -0
- package/dist/indexer/embedder.d.ts.map +1 -0
- package/dist/indexer/embedder.js +186 -0
- package/dist/indexer/embedder.js.map +1 -0
- package/dist/indexer/ensure-python-deps.d.ts +22 -0
- package/dist/indexer/ensure-python-deps.d.ts.map +1 -0
- package/dist/indexer/ensure-python-deps.js +47 -0
- package/dist/indexer/ensure-python-deps.js.map +1 -0
- package/dist/indexer/extractors/bash.d.ts +12 -0
- package/dist/indexer/extractors/bash.d.ts.map +1 -0
- package/dist/indexer/extractors/bash.js +57 -0
- package/dist/indexer/extractors/bash.js.map +1 -0
- package/dist/indexer/extractors/c.d.ts +12 -0
- package/dist/indexer/extractors/c.d.ts.map +1 -0
- package/dist/indexer/extractors/c.js +106 -0
- package/dist/indexer/extractors/c.js.map +1 -0
- package/dist/indexer/extractors/cpp.d.ts +12 -0
- package/dist/indexer/extractors/cpp.d.ts.map +1 -0
- package/dist/indexer/extractors/cpp.js +84 -0
- package/dist/indexer/extractors/cpp.js.map +1 -0
- package/dist/indexer/extractors/csharp.d.ts +12 -0
- package/dist/indexer/extractors/csharp.d.ts.map +1 -0
- package/dist/indexer/extractors/csharp.js +79 -0
- package/dist/indexer/extractors/csharp.js.map +1 -0
- package/dist/indexer/extractors/dart.d.ts +12 -0
- package/dist/indexer/extractors/dart.d.ts.map +1 -0
- package/dist/indexer/extractors/dart.js +80 -0
- package/dist/indexer/extractors/dart.js.map +1 -0
- package/dist/indexer/extractors/elixir.d.ts +12 -0
- package/dist/indexer/extractors/elixir.d.ts.map +1 -0
- package/dist/indexer/extractors/elixir.js +87 -0
- package/dist/indexer/extractors/elixir.js.map +1 -0
- package/dist/indexer/extractors/elm.d.ts +12 -0
- package/dist/indexer/extractors/elm.d.ts.map +1 -0
- package/dist/indexer/extractors/elm.js +87 -0
- package/dist/indexer/extractors/elm.js.map +1 -0
- package/dist/indexer/extractors/go.d.ts +12 -0
- package/dist/indexer/extractors/go.d.ts.map +1 -0
- package/dist/indexer/extractors/go.js +158 -0
- package/dist/indexer/extractors/go.js.map +1 -0
- package/dist/indexer/extractors/haskell.d.ts +12 -0
- package/dist/indexer/extractors/haskell.d.ts.map +1 -0
- package/dist/indexer/extractors/haskell.js +104 -0
- package/dist/indexer/extractors/haskell.js.map +1 -0
- package/dist/indexer/extractors/java.d.ts +12 -0
- package/dist/indexer/extractors/java.d.ts.map +1 -0
- package/dist/indexer/extractors/java.js +68 -0
- package/dist/indexer/extractors/java.js.map +1 -0
- package/dist/indexer/extractors/javascript.d.ts +13 -0
- package/dist/indexer/extractors/javascript.d.ts.map +1 -0
- package/dist/indexer/extractors/javascript.js +180 -0
- package/dist/indexer/extractors/javascript.js.map +1 -0
- package/dist/indexer/extractors/julia.d.ts +12 -0
- package/dist/indexer/extractors/julia.d.ts.map +1 -0
- package/dist/indexer/extractors/julia.js +94 -0
- package/dist/indexer/extractors/julia.js.map +1 -0
- package/dist/indexer/extractors/kotlin.d.ts +12 -0
- package/dist/indexer/extractors/kotlin.d.ts.map +1 -0
- package/dist/indexer/extractors/kotlin.js +71 -0
- package/dist/indexer/extractors/kotlin.js.map +1 -0
- package/dist/indexer/extractors/lua.d.ts +12 -0
- package/dist/indexer/extractors/lua.d.ts.map +1 -0
- package/dist/indexer/extractors/lua.js +68 -0
- package/dist/indexer/extractors/lua.js.map +1 -0
- package/dist/indexer/extractors/objc.d.ts +12 -0
- package/dist/indexer/extractors/objc.d.ts.map +1 -0
- package/dist/indexer/extractors/objc.js +129 -0
- package/dist/indexer/extractors/objc.js.map +1 -0
- package/dist/indexer/extractors/ocaml.d.ts +12 -0
- package/dist/indexer/extractors/ocaml.d.ts.map +1 -0
- package/dist/indexer/extractors/ocaml.js +92 -0
- package/dist/indexer/extractors/ocaml.js.map +1 -0
- package/dist/indexer/extractors/php.d.ts +12 -0
- package/dist/indexer/extractors/php.d.ts.map +1 -0
- package/dist/indexer/extractors/php.js +99 -0
- package/dist/indexer/extractors/php.js.map +1 -0
- package/dist/indexer/extractors/python.d.ts +12 -0
- package/dist/indexer/extractors/python.d.ts.map +1 -0
- package/dist/indexer/extractors/python.js +129 -0
- package/dist/indexer/extractors/python.js.map +1 -0
- package/dist/indexer/extractors/ruby.d.ts +12 -0
- package/dist/indexer/extractors/ruby.d.ts.map +1 -0
- package/dist/indexer/extractors/ruby.js +100 -0
- package/dist/indexer/extractors/ruby.js.map +1 -0
- package/dist/indexer/extractors/rust.d.ts +12 -0
- package/dist/indexer/extractors/rust.d.ts.map +1 -0
- package/dist/indexer/extractors/rust.js +82 -0
- package/dist/indexer/extractors/rust.js.map +1 -0
- package/dist/indexer/extractors/scala.d.ts +12 -0
- package/dist/indexer/extractors/scala.d.ts.map +1 -0
- package/dist/indexer/extractors/scala.js +91 -0
- package/dist/indexer/extractors/scala.js.map +1 -0
- package/dist/indexer/extractors/swift.d.ts +12 -0
- package/dist/indexer/extractors/swift.d.ts.map +1 -0
- package/dist/indexer/extractors/swift.js +90 -0
- package/dist/indexer/extractors/swift.js.map +1 -0
- package/dist/indexer/extractors/types.d.ts +118 -0
- package/dist/indexer/extractors/types.d.ts.map +1 -0
- package/dist/indexer/extractors/types.js +43 -0
- package/dist/indexer/extractors/types.js.map +1 -0
- package/dist/indexer/extractors/typescript.d.ts +14 -0
- package/dist/indexer/extractors/typescript.d.ts.map +1 -0
- package/dist/indexer/extractors/typescript.js +172 -0
- package/dist/indexer/extractors/typescript.js.map +1 -0
- package/dist/indexer/extractors/zig.d.ts +12 -0
- package/dist/indexer/extractors/zig.d.ts.map +1 -0
- package/dist/indexer/extractors/zig.js +95 -0
- package/dist/indexer/extractors/zig.js.map +1 -0
- package/dist/indexer/git-history.d.ts +23 -0
- package/dist/indexer/git-history.d.ts.map +1 -0
- package/dist/indexer/git-history.js +144 -0
- package/dist/indexer/git-history.js.map +1 -0
- package/dist/indexer/git-hooks.d.ts +19 -0
- package/dist/indexer/git-hooks.d.ts.map +1 -0
- package/dist/indexer/git-hooks.js +74 -0
- package/dist/indexer/git-hooks.js.map +1 -0
- package/dist/indexer/index.d.ts +83 -0
- package/dist/indexer/index.d.ts.map +1 -0
- package/dist/indexer/index.js +431 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/indexer/parser.d.ts +30 -0
- package/dist/indexer/parser.d.ts.map +1 -0
- package/dist/indexer/parser.js +114 -0
- package/dist/indexer/parser.js.map +1 -0
- package/dist/indexer/poller.d.ts +50 -0
- package/dist/indexer/poller.d.ts.map +1 -0
- package/dist/indexer/poller.js +140 -0
- package/dist/indexer/poller.js.map +1 -0
- package/dist/indexer/resolver.d.ts +52 -0
- package/dist/indexer/resolver.d.ts.map +1 -0
- package/dist/indexer/resolver.js +271 -0
- package/dist/indexer/resolver.js.map +1 -0
- package/dist/indexer/test-mapper.d.ts +6 -0
- package/dist/indexer/test-mapper.d.ts.map +1 -0
- package/dist/indexer/test-mapper.js +48 -0
- package/dist/indexer/test-mapper.js.map +1 -0
- package/dist/indexer/walker.d.ts +51 -0
- package/dist/indexer/walker.d.ts.map +1 -0
- package/dist/indexer/walker.js +100 -0
- package/dist/indexer/walker.js.map +1 -0
- package/dist/indexer/watcher.d.ts +51 -0
- package/dist/indexer/watcher.d.ts.map +1 -0
- package/dist/indexer/watcher.js +107 -0
- package/dist/indexer/watcher.js.map +1 -0
- package/dist/kb-server/db.d.ts +241 -0
- package/dist/kb-server/db.d.ts.map +1 -0
- package/dist/kb-server/db.js +659 -0
- package/dist/kb-server/db.js.map +1 -0
- package/dist/kb-server/server.d.ts +35 -0
- package/dist/kb-server/server.d.ts.map +1 -0
- package/dist/kb-server/server.js +240 -0
- package/dist/kb-server/server.js.map +1 -0
- package/dist/kb-server/tools/annotations.d.ts +40 -0
- package/dist/kb-server/tools/annotations.d.ts.map +1 -0
- package/dist/kb-server/tools/annotations.js +35 -0
- package/dist/kb-server/tools/annotations.js.map +1 -0
- package/dist/kb-server/tools/architecture.d.ts +60 -0
- package/dist/kb-server/tools/architecture.d.ts.map +1 -0
- package/dist/kb-server/tools/architecture.js +174 -0
- package/dist/kb-server/tools/architecture.js.map +1 -0
- package/dist/kb-server/tools/blame.d.ts +67 -0
- package/dist/kb-server/tools/blame.d.ts.map +1 -0
- package/dist/kb-server/tools/blame.js +162 -0
- package/dist/kb-server/tools/blame.js.map +1 -0
- package/dist/kb-server/tools/coverage.d.ts +67 -0
- package/dist/kb-server/tools/coverage.d.ts.map +1 -0
- package/dist/kb-server/tools/coverage.js +74 -0
- package/dist/kb-server/tools/coverage.js.map +1 -0
- package/dist/kb-server/tools/graph.d.ts +56 -0
- package/dist/kb-server/tools/graph.d.ts.map +1 -0
- package/dist/kb-server/tools/graph.js +188 -0
- package/dist/kb-server/tools/graph.js.map +1 -0
- package/dist/kb-server/tools/history.d.ts +47 -0
- package/dist/kb-server/tools/history.d.ts.map +1 -0
- package/dist/kb-server/tools/history.js +91 -0
- package/dist/kb-server/tools/history.js.map +1 -0
- package/dist/kb-server/tools/lookup.d.ts +36 -0
- package/dist/kb-server/tools/lookup.d.ts.map +1 -0
- package/dist/kb-server/tools/lookup.js +45 -0
- package/dist/kb-server/tools/lookup.js.map +1 -0
- package/dist/kb-server/tools/metrics.d.ts +73 -0
- package/dist/kb-server/tools/metrics.d.ts.map +1 -0
- package/dist/kb-server/tools/metrics.js +79 -0
- package/dist/kb-server/tools/metrics.js.map +1 -0
- package/dist/kb-server/tools/notes.d.ts +165 -0
- package/dist/kb-server/tools/notes.d.ts.map +1 -0
- package/dist/kb-server/tools/notes.js +175 -0
- package/dist/kb-server/tools/notes.js.map +1 -0
- package/dist/kb-server/tools/routes.d.ts +38 -0
- package/dist/kb-server/tools/routes.d.ts.map +1 -0
- package/dist/kb-server/tools/routes.js +38 -0
- package/dist/kb-server/tools/routes.js.map +1 -0
- package/dist/kb-server/tools/search.d.ts +60 -0
- package/dist/kb-server/tools/search.d.ts.map +1 -0
- package/dist/kb-server/tools/search.js +170 -0
- package/dist/kb-server/tools/search.js.map +1 -0
- package/dist/kb-server/tools/snippet.d.ts +44 -0
- package/dist/kb-server/tools/snippet.d.ts.map +1 -0
- package/dist/kb-server/tools/snippet.js +49 -0
- package/dist/kb-server/tools/snippet.js.map +1 -0
- package/dist/kb-server/tools/test-map.d.ts +38 -0
- package/dist/kb-server/tools/test-map.d.ts.map +1 -0
- package/dist/kb-server/tools/test-map.js +32 -0
- package/dist/kb-server/tools/test-map.js.map +1 -0
- package/dist/kb-server/tools/writeback.d.ts +49 -0
- package/dist/kb-server/tools/writeback.d.ts.map +1 -0
- package/dist/kb-server/tools/writeback.js +68 -0
- package/dist/kb-server/tools/writeback.js.map +1 -0
- package/package.json +92 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module kb-server/tools/notes
|
|
3
|
+
*
|
|
4
|
+
* MCP tools:
|
|
5
|
+
* - kb_notes_write: upsert notes by (key, scope)
|
|
6
|
+
* - kb_notes_read: retrieve notes with staleness/recency metadata
|
|
7
|
+
*/
|
|
8
|
+
import Database from 'better-sqlite3';
|
|
9
|
+
const DEFAULT_SCOPE = 'global';
|
|
10
|
+
const DEFAULT_LIMIT = 20;
|
|
11
|
+
const MAX_LIMIT = 200;
|
|
12
|
+
export const kbNotesWriteToolDef = {
|
|
13
|
+
name: 'kb_notes_write',
|
|
14
|
+
description: 'Upsert an LLM-authored note in the knowledge base by key and scope. ' +
|
|
15
|
+
'Defaults scope to "global" and updates updated_at on existing notes.',
|
|
16
|
+
inputSchema: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
key: { type: 'string', description: 'Topic identifier, e.g. "architecture/overview".' },
|
|
20
|
+
scope: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
description: 'Optional scope (default "global"), e.g. file:<path>, module:<name>.',
|
|
23
|
+
},
|
|
24
|
+
content: { type: 'string', description: 'The note text.' },
|
|
25
|
+
model: { type: 'string', description: 'Model identifier that authored the note.' },
|
|
26
|
+
source_hash: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'Optional source hash used for staleness detection.',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
required: ['key', 'content'],
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
export const kbNotesReadToolDef = {
|
|
35
|
+
name: 'kb_notes_read',
|
|
36
|
+
description: 'Read notes by exact key and/or key prefix, optionally filtered by scope. ' +
|
|
37
|
+
'Returns staleness metadata for file-scoped notes and recency metadata for global notes.',
|
|
38
|
+
inputSchema: {
|
|
39
|
+
type: 'object',
|
|
40
|
+
properties: {
|
|
41
|
+
key: { type: 'string', description: 'Exact key match.' },
|
|
42
|
+
key_prefix: { type: 'string', description: 'Prefix match (e.g. "architecture/").' },
|
|
43
|
+
scope: { type: 'string', description: 'Optional scope filter.' },
|
|
44
|
+
limit: { type: 'number', description: 'Max notes to return (default 20, max 200).' },
|
|
45
|
+
},
|
|
46
|
+
required: [],
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
function normalizeScope(scope) {
|
|
50
|
+
const normalized = scope?.trim();
|
|
51
|
+
return normalized ? normalized : DEFAULT_SCOPE;
|
|
52
|
+
}
|
|
53
|
+
function clampLimit(limit) {
|
|
54
|
+
if (limit == null)
|
|
55
|
+
return DEFAULT_LIMIT;
|
|
56
|
+
return Math.min(Math.max(1, Math.floor(limit)), MAX_LIMIT);
|
|
57
|
+
}
|
|
58
|
+
export function kbNotesWriteHandler(dbPath, args) {
|
|
59
|
+
const db = new Database(dbPath);
|
|
60
|
+
try {
|
|
61
|
+
db.pragma('foreign_keys = ON');
|
|
62
|
+
const scope = normalizeScope(args.scope);
|
|
63
|
+
const model = args.model ?? '';
|
|
64
|
+
const sourceHash = args.source_hash ?? null;
|
|
65
|
+
db.prepare(`INSERT INTO notes (key, scope, content, model, source_hash, created_at, updated_at)
|
|
66
|
+
VALUES (?, ?, ?, ?, ?, unixepoch(), unixepoch())
|
|
67
|
+
ON CONFLICT(key, scope) DO UPDATE SET
|
|
68
|
+
content = excluded.content,
|
|
69
|
+
model = excluded.model,
|
|
70
|
+
source_hash = excluded.source_hash,
|
|
71
|
+
updated_at = unixepoch()`).run(args.key, scope, args.content, model, sourceHash);
|
|
72
|
+
const row = db
|
|
73
|
+
.prepare('SELECT updated_at FROM notes WHERE key = ? AND scope = ?')
|
|
74
|
+
.get(args.key, scope);
|
|
75
|
+
return {
|
|
76
|
+
ok: true,
|
|
77
|
+
key: args.key,
|
|
78
|
+
scope,
|
|
79
|
+
updated_at: row.updated_at,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
db.close();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export function kbNotesReadHandler(db, args) {
|
|
87
|
+
const limit = clampLimit(args.limit);
|
|
88
|
+
const where = [];
|
|
89
|
+
const params = [];
|
|
90
|
+
const key = args.key?.trim();
|
|
91
|
+
if (key) {
|
|
92
|
+
where.push('key = ?');
|
|
93
|
+
params.push(key);
|
|
94
|
+
}
|
|
95
|
+
const keyPrefix = args.key_prefix?.trim();
|
|
96
|
+
if (keyPrefix) {
|
|
97
|
+
where.push('key LIKE ?');
|
|
98
|
+
params.push(`${keyPrefix}%`);
|
|
99
|
+
}
|
|
100
|
+
const scope = args.scope?.trim();
|
|
101
|
+
if (scope) {
|
|
102
|
+
where.push('scope = ?');
|
|
103
|
+
params.push(scope);
|
|
104
|
+
}
|
|
105
|
+
const whereSql = where.length ? `WHERE ${where.join(' AND ')}` : '';
|
|
106
|
+
const rows = db
|
|
107
|
+
.prepare(`SELECT key, scope, content, model, source_hash, created_at, updated_at
|
|
108
|
+
FROM notes
|
|
109
|
+
${whereSql}
|
|
110
|
+
ORDER BY updated_at DESC, id DESC
|
|
111
|
+
LIMIT ?`)
|
|
112
|
+
.all(...params, limit);
|
|
113
|
+
const kbIndexedAtRow = db
|
|
114
|
+
.prepare('SELECT MAX(indexed_at) AS indexed_at FROM files')
|
|
115
|
+
.get();
|
|
116
|
+
const kbIndexedAt = kbIndexedAtRow.indexed_at;
|
|
117
|
+
const getFileRecency = db.prepare(`SELECT last_hash, indexed_at
|
|
118
|
+
FROM files
|
|
119
|
+
WHERE path = ?
|
|
120
|
+
ORDER BY indexed_at DESC
|
|
121
|
+
LIMIT 1`);
|
|
122
|
+
const notes = rows.map((row) => {
|
|
123
|
+
if (row.scope.startsWith('file:')) {
|
|
124
|
+
const filePath = row.scope.slice('file:'.length);
|
|
125
|
+
const fileRow = getFileRecency.get(filePath);
|
|
126
|
+
let stale = false;
|
|
127
|
+
let staleReason = null;
|
|
128
|
+
if (!fileRow) {
|
|
129
|
+
stale = true;
|
|
130
|
+
staleReason = 'file_missing';
|
|
131
|
+
}
|
|
132
|
+
else if (row.source_hash && fileRow.last_hash && row.source_hash !== fileRow.last_hash) {
|
|
133
|
+
stale = true;
|
|
134
|
+
staleReason = 'source_hash_mismatch';
|
|
135
|
+
}
|
|
136
|
+
else if (fileRow.indexed_at > row.updated_at) {
|
|
137
|
+
stale = true;
|
|
138
|
+
staleReason = 'indexed_after_note';
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
...row,
|
|
142
|
+
stale,
|
|
143
|
+
stale_reason: staleReason,
|
|
144
|
+
file_last_hash: fileRow?.last_hash ?? null,
|
|
145
|
+
file_indexed_at: fileRow?.indexed_at ?? null,
|
|
146
|
+
kb_indexed_at: null,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
if (row.scope === DEFAULT_SCOPE) {
|
|
150
|
+
const stale = kbIndexedAt != null ? row.updated_at < kbIndexedAt : false;
|
|
151
|
+
return {
|
|
152
|
+
...row,
|
|
153
|
+
stale,
|
|
154
|
+
stale_reason: stale ? 'kb_reindexed_since_note' : null,
|
|
155
|
+
file_last_hash: null,
|
|
156
|
+
file_indexed_at: null,
|
|
157
|
+
kb_indexed_at: kbIndexedAt,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
...row,
|
|
162
|
+
stale: false,
|
|
163
|
+
stale_reason: null,
|
|
164
|
+
file_last_hash: null,
|
|
165
|
+
file_indexed_at: null,
|
|
166
|
+
kb_indexed_at: null,
|
|
167
|
+
};
|
|
168
|
+
});
|
|
169
|
+
return { notes, count: notes.length };
|
|
170
|
+
}
|
|
171
|
+
export const writeToolDef = kbNotesWriteToolDef;
|
|
172
|
+
export const readToolDef = kbNotesReadToolDef;
|
|
173
|
+
export const writeHandler = kbNotesWriteHandler;
|
|
174
|
+
export const readHandler = kbNotesReadHandler;
|
|
175
|
+
//# sourceMappingURL=notes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notes.js","sourceRoot":"","sources":["../../../src/kb-server/tools/notes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module kb-server/tools/routes
|
|
3
|
+
*
|
|
4
|
+
* MCP tool: query extracted API routes/endpoints.
|
|
5
|
+
*/
|
|
6
|
+
import type { Database } from '../db.js';
|
|
7
|
+
import { type ApiRouteRow } from '../db.js';
|
|
8
|
+
export declare const toolDef: {
|
|
9
|
+
readonly name: "kb_routes";
|
|
10
|
+
readonly description: string;
|
|
11
|
+
readonly inputSchema: {
|
|
12
|
+
readonly type: "object";
|
|
13
|
+
readonly properties: {
|
|
14
|
+
readonly method: {
|
|
15
|
+
readonly type: "string";
|
|
16
|
+
readonly description: "Optional HTTP method filter (for example GET, POST).";
|
|
17
|
+
};
|
|
18
|
+
readonly path_prefix: {
|
|
19
|
+
readonly type: "string";
|
|
20
|
+
readonly description: "Optional route path prefix filter.";
|
|
21
|
+
};
|
|
22
|
+
readonly framework: {
|
|
23
|
+
readonly type: "string";
|
|
24
|
+
readonly description: "Optional framework filter (for example express, fastapi, gin).";
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export interface RoutesArgs {
|
|
30
|
+
method?: string;
|
|
31
|
+
path_prefix?: string;
|
|
32
|
+
framework?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface RoutesResult {
|
|
35
|
+
results: ApiRouteRow[];
|
|
36
|
+
}
|
|
37
|
+
export declare function handler(db: Database.Database, args: RoutesArgs): RoutesResult;
|
|
38
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/kb-server/tools/routes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAE3D,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;CAsBV,CAAC;AAEX,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,YAAY,CAQ7E"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module kb-server/tools/routes
|
|
3
|
+
*
|
|
4
|
+
* MCP tool: query extracted API routes/endpoints.
|
|
5
|
+
*/
|
|
6
|
+
import { listApiRoutes } from '../db.js';
|
|
7
|
+
export const toolDef = {
|
|
8
|
+
name: 'kb_routes',
|
|
9
|
+
description: 'Query extracted API routes/endpoints from the knowledge-base index. ' +
|
|
10
|
+
'Optional filters: `method`, `path_prefix`, and `framework`.',
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
method: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'Optional HTTP method filter (for example GET, POST).',
|
|
17
|
+
},
|
|
18
|
+
path_prefix: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: 'Optional route path prefix filter.',
|
|
21
|
+
},
|
|
22
|
+
framework: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: 'Optional framework filter (for example express, fastapi, gin).',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
export function handler(db, args) {
|
|
30
|
+
return {
|
|
31
|
+
results: listApiRoutes(db, {
|
|
32
|
+
method: args.method,
|
|
33
|
+
pathPrefix: args.path_prefix,
|
|
34
|
+
framework: args.framework,
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/kb-server/tools/routes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAoB,MAAM,UAAU,CAAC;AAE3D,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,IAAI,EAAE,WAAW;IACjB,WAAW,EACT,sEAAsE;QACtE,6DAA6D;IAC/D,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,sDAAsD;aACpE;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,oCAAoC;aAClD;YACD,SAAS,EAAE;gBACT,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,gEAAgE;aAC9E;SACF;KACF;CACO,CAAC;AAYX,MAAM,UAAU,OAAO,CAAC,EAAqB,EAAE,IAAgB;IAC7D,OAAO;QACL,OAAO,EAAE,aAAa,CAAC,EAAE,EAAE;YACzB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,UAAU,EAAE,IAAI,CAAC,WAAW;YAC5B,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC;KACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module kb-server/tools/search
|
|
3
|
+
*
|
|
4
|
+
* MCP tool: multi-modal knowledge-base search.
|
|
5
|
+
*
|
|
6
|
+
* Modes:
|
|
7
|
+
* - "structural" — BM25 full-text search via FTS5 (symbols_fts).
|
|
8
|
+
* - "semantic" — cosine similarity via sqlite-vec vec0 tables (requires embeddings).
|
|
9
|
+
* - "fused" — Reciprocal Rank Fusion (k=60) combining structural + semantic.
|
|
10
|
+
*
|
|
11
|
+
* Semantic and fused modes fall back to structural-only when no EmbeddingProvider
|
|
12
|
+
* is supplied, clearly indicating the degradation in `mode_used`.
|
|
13
|
+
*/
|
|
14
|
+
import type { Database } from '../db.js';
|
|
15
|
+
import type { EmbeddingProvider } from '../../indexer/embedder.js';
|
|
16
|
+
export declare const toolDef: {
|
|
17
|
+
readonly name: "kb_search";
|
|
18
|
+
readonly description: string;
|
|
19
|
+
readonly inputSchema: {
|
|
20
|
+
readonly type: "object";
|
|
21
|
+
readonly properties: {
|
|
22
|
+
readonly query: {
|
|
23
|
+
readonly type: "string";
|
|
24
|
+
readonly description: "Search query string.";
|
|
25
|
+
};
|
|
26
|
+
readonly mode: {
|
|
27
|
+
readonly type: "string";
|
|
28
|
+
readonly enum: readonly ["structural", "semantic", "fused"];
|
|
29
|
+
readonly description: "Search mode (default: \"structural\").";
|
|
30
|
+
};
|
|
31
|
+
readonly limit: {
|
|
32
|
+
readonly type: "number";
|
|
33
|
+
readonly description: "Maximum number of results to return (default 20).";
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
readonly required: readonly ["query"];
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
export interface SearchArgs {
|
|
40
|
+
query: string;
|
|
41
|
+
mode?: 'structural' | 'semantic' | 'fused';
|
|
42
|
+
limit?: number;
|
|
43
|
+
branch?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface SearchResult {
|
|
46
|
+
results: Array<{
|
|
47
|
+
symbol_id: number;
|
|
48
|
+
name: string;
|
|
49
|
+
kind: string;
|
|
50
|
+
file_path: string;
|
|
51
|
+
start_line: number;
|
|
52
|
+
end_line: number;
|
|
53
|
+
score: number;
|
|
54
|
+
branch: string;
|
|
55
|
+
}>;
|
|
56
|
+
mode_used: string;
|
|
57
|
+
}
|
|
58
|
+
/** Execute a knowledge-base search in the requested mode. */
|
|
59
|
+
export declare function handler(db: Database.Database, args: SearchArgs, embedder?: EmbeddingProvider): Promise<SearchResult>;
|
|
60
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/kb-server/tools/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAInE,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;CA0BV,CAAC;AAIX,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,GAAG,UAAU,GAAG,OAAO,CAAC;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,KAAK,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AA8HD,6DAA6D;AAC7D,wBAAsB,OAAO,CAC3B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,IAAI,EAAE,UAAU,EAChB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,YAAY,CAAC,CA4BvB"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module kb-server/tools/search
|
|
3
|
+
*
|
|
4
|
+
* MCP tool: multi-modal knowledge-base search.
|
|
5
|
+
*
|
|
6
|
+
* Modes:
|
|
7
|
+
* - "structural" — BM25 full-text search via FTS5 (symbols_fts).
|
|
8
|
+
* - "semantic" — cosine similarity via sqlite-vec vec0 tables (requires embeddings).
|
|
9
|
+
* - "fused" — Reciprocal Rank Fusion (k=60) combining structural + semantic.
|
|
10
|
+
*
|
|
11
|
+
* Semantic and fused modes fall back to structural-only when no EmbeddingProvider
|
|
12
|
+
* is supplied, clearly indicating the degradation in `mode_used`.
|
|
13
|
+
*/
|
|
14
|
+
// ─── Tool definition ──────────────────────────────────────────────────────────
|
|
15
|
+
export const toolDef = {
|
|
16
|
+
name: 'kb_search',
|
|
17
|
+
description: 'Search the knowledge-base index for symbols matching a natural-language or code query. ' +
|
|
18
|
+
'mode="structural" uses BM25 FTS5 (fast, exact-ish). ' +
|
|
19
|
+
'mode="semantic" uses cosine similarity over embedding vectors (requires indexed embeddings). ' +
|
|
20
|
+
'mode="fused" combines both with Reciprocal Rank Fusion (RRF k=60).',
|
|
21
|
+
inputSchema: {
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
query: {
|
|
25
|
+
type: 'string',
|
|
26
|
+
description: 'Search query string.',
|
|
27
|
+
},
|
|
28
|
+
mode: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
enum: ['structural', 'semantic', 'fused'],
|
|
31
|
+
description: 'Search mode (default: "structural").',
|
|
32
|
+
},
|
|
33
|
+
limit: {
|
|
34
|
+
type: 'number',
|
|
35
|
+
description: 'Maximum number of results to return (default 20).',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
required: ['query'],
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Sanitise a user-provided query string for FTS5 MATCH.
|
|
43
|
+
*
|
|
44
|
+
* FTS5 has its own query grammar where characters like `*`, `OR`, `NOT`, `-`,
|
|
45
|
+
* `^`, `"`, `(`, `)` carry special meaning. Wrapping the query in escaped
|
|
46
|
+
* double-quotes forces FTS5 to treat it as a literal phrase, preventing
|
|
47
|
+
* syntax errors and injection from symbol names like `operator+` or `T*`.
|
|
48
|
+
*/
|
|
49
|
+
function sanitizeFts5Query(query) {
|
|
50
|
+
// Escape interior double-quotes, then wrap in double-quotes for a phrase query.
|
|
51
|
+
return `"${query.replace(/"/g, '""')}"`;
|
|
52
|
+
}
|
|
53
|
+
/** Run a structural BM25 FTS5 search and return ranked rows. */
|
|
54
|
+
function structuralSearch(db, query, limit, branch) {
|
|
55
|
+
const safeQuery = sanitizeFts5Query(query);
|
|
56
|
+
const branchClause = branch !== undefined ? ' AND f.branch = ?' : '';
|
|
57
|
+
try {
|
|
58
|
+
const sql = `SELECT s.id AS symbol_id, s.name, s.kind, f.path AS file_path,
|
|
59
|
+
s.start_line, s.end_line,
|
|
60
|
+
bm25(symbols_fts) AS score,
|
|
61
|
+
f.branch AS branch
|
|
62
|
+
FROM symbols_fts
|
|
63
|
+
JOIN symbols s ON s.rowid = symbols_fts.rowid
|
|
64
|
+
JOIN files f ON f.id = s.file_id
|
|
65
|
+
WHERE symbols_fts MATCH ?${branchClause}
|
|
66
|
+
ORDER BY score
|
|
67
|
+
LIMIT ?`;
|
|
68
|
+
const params = branch !== undefined ? [safeQuery, branch, limit] : [safeQuery, limit];
|
|
69
|
+
const rows = db.prepare(sql).all(...params);
|
|
70
|
+
return rows;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// FTS5 parse error — fall back to LIKE-based search.
|
|
74
|
+
const likeQuery = `%${query}%`;
|
|
75
|
+
const sql = `SELECT s.id AS symbol_id, s.name, s.kind, f.path AS file_path,
|
|
76
|
+
s.start_line, s.end_line,
|
|
77
|
+
0.0 AS score,
|
|
78
|
+
f.branch AS branch
|
|
79
|
+
FROM symbols s
|
|
80
|
+
JOIN files f ON f.id = s.file_id
|
|
81
|
+
WHERE s.name LIKE ?${branchClause}
|
|
82
|
+
LIMIT ?`;
|
|
83
|
+
const params = branch !== undefined ? [likeQuery, branch, limit] : [likeQuery, limit];
|
|
84
|
+
return db.prepare(sql).all(...params);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Attempt a semantic (cosine) search via the vec0 virtual table.
|
|
89
|
+
* Returns `null` when no embedder is available or the table has no rows.
|
|
90
|
+
*/
|
|
91
|
+
async function semanticSearch(db, query, limit, embedder, branch) {
|
|
92
|
+
try {
|
|
93
|
+
const [queryVec] = await embedder.embed([query]);
|
|
94
|
+
if (!queryVec)
|
|
95
|
+
return null;
|
|
96
|
+
const branchClause = branch !== undefined ? ' AND f.branch = ?' : '';
|
|
97
|
+
const sql = `SELECT s.id AS symbol_id, s.name, s.kind, f.path AS file_path,
|
|
98
|
+
s.start_line, s.end_line,
|
|
99
|
+
distance AS score,
|
|
100
|
+
f.branch AS branch
|
|
101
|
+
FROM symbol_embeddings
|
|
102
|
+
JOIN symbols s ON s.rowid = symbol_embeddings.rowid
|
|
103
|
+
JOIN files f ON f.id = s.file_id
|
|
104
|
+
WHERE embedding MATCH ?${branchClause}
|
|
105
|
+
ORDER BY distance
|
|
106
|
+
LIMIT ?`;
|
|
107
|
+
const params = branch !== undefined
|
|
108
|
+
? [JSON.stringify(queryVec), branch, limit]
|
|
109
|
+
: [JSON.stringify(queryVec), limit];
|
|
110
|
+
const rows = db.prepare(sql).all(...params);
|
|
111
|
+
return rows.length > 0 ? rows : null;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Reciprocal Rank Fusion (k=60) over structural and semantic result lists.
|
|
119
|
+
*
|
|
120
|
+
* RRF score = Σ 1/(k + rank_i) for each list i where the item appears.
|
|
121
|
+
* Higher score → better rank.
|
|
122
|
+
*/
|
|
123
|
+
function rrfFuse(structural, semantic, limit) {
|
|
124
|
+
const k = 60;
|
|
125
|
+
const scores = new Map();
|
|
126
|
+
const addList = (list) => {
|
|
127
|
+
list.forEach((item, idx) => {
|
|
128
|
+
const existing = scores.get(item.symbol_id);
|
|
129
|
+
const contrib = 1 / (k + idx + 1);
|
|
130
|
+
if (existing) {
|
|
131
|
+
existing.score += contrib;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
scores.set(item.symbol_id, { item, score: contrib });
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
addList(structural);
|
|
139
|
+
if (semantic)
|
|
140
|
+
addList(semantic);
|
|
141
|
+
return Array.from(scores.values())
|
|
142
|
+
.sort((a, b) => b.score - a.score)
|
|
143
|
+
.slice(0, limit)
|
|
144
|
+
.map(({ item, score }) => ({ ...item, score }));
|
|
145
|
+
}
|
|
146
|
+
/** Execute a knowledge-base search in the requested mode. */
|
|
147
|
+
export async function handler(db, args, embedder) {
|
|
148
|
+
const limit = args.limit ?? 20;
|
|
149
|
+
const mode = args.mode ?? 'structural';
|
|
150
|
+
const structural = structuralSearch(db, args.query, limit, args.branch);
|
|
151
|
+
if (mode === 'structural') {
|
|
152
|
+
return { results: structural, mode_used: 'structural' };
|
|
153
|
+
}
|
|
154
|
+
if (!embedder) {
|
|
155
|
+
// No query-time embedder available — callers can detect this degradation.
|
|
156
|
+
return { results: structural, mode_used: 'structural (no query-time embedder)' };
|
|
157
|
+
}
|
|
158
|
+
const semantic = await semanticSearch(db, args.query, limit, embedder, args.branch);
|
|
159
|
+
if (mode === 'semantic') {
|
|
160
|
+
if (semantic) {
|
|
161
|
+
return { results: semantic, mode_used: 'semantic' };
|
|
162
|
+
}
|
|
163
|
+
return { results: structural, mode_used: 'structural (fallback: no embeddings)' };
|
|
164
|
+
}
|
|
165
|
+
// mode === 'fused'
|
|
166
|
+
const fused = rrfFuse(structural, semantic, limit);
|
|
167
|
+
const modeUsed = semantic ? 'fused' : 'structural (fallback: no embeddings)';
|
|
168
|
+
return { results: fused, mode_used: modeUsed };
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/kb-server/tools/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module kb-server/tools/snippet
|
|
3
|
+
*
|
|
4
|
+
* MCP tool: extract source-code snippets for a given file path and
|
|
5
|
+
* optional line range directly from the filesystem.
|
|
6
|
+
*/
|
|
7
|
+
import type { Database } from '../db.js';
|
|
8
|
+
export declare const toolDef: {
|
|
9
|
+
readonly name: "kb_snippet";
|
|
10
|
+
readonly description: string;
|
|
11
|
+
readonly inputSchema: {
|
|
12
|
+
readonly type: "object";
|
|
13
|
+
readonly properties: {
|
|
14
|
+
readonly path: {
|
|
15
|
+
readonly type: "string";
|
|
16
|
+
readonly description: "Absolute file path as stored in the knowledge-base index.";
|
|
17
|
+
};
|
|
18
|
+
readonly start_line: {
|
|
19
|
+
readonly type: "number";
|
|
20
|
+
readonly description: "First line to include (1-based, inclusive). Defaults to 1.";
|
|
21
|
+
};
|
|
22
|
+
readonly end_line: {
|
|
23
|
+
readonly type: "number";
|
|
24
|
+
readonly description: "Last line to include (1-based, inclusive). Defaults to end-of-file.";
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
readonly required: readonly ["path"];
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export interface SnippetArgs {
|
|
31
|
+
path: string;
|
|
32
|
+
start_line?: number;
|
|
33
|
+
end_line?: number;
|
|
34
|
+
branch?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface SnippetResult {
|
|
37
|
+
path: string;
|
|
38
|
+
start_line: number;
|
|
39
|
+
end_line: number;
|
|
40
|
+
text: string;
|
|
41
|
+
}
|
|
42
|
+
/** Read source lines from the filesystem for the given indexed file path. */
|
|
43
|
+
export declare function handler(db: Database.Database, args: SnippetArgs): SnippetResult;
|
|
44
|
+
//# sourceMappingURL=snippet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippet.d.ts","sourceRoot":"","sources":["../../../src/kb-server/tools/snippet.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAKzC,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;CAwBV,CAAC;AAIX,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,GAAG,aAAa,CAiB/E"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module kb-server/tools/snippet
|
|
3
|
+
*
|
|
4
|
+
* MCP tool: extract source-code snippets for a given file path and
|
|
5
|
+
* optional line range directly from the filesystem.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from 'node:fs';
|
|
8
|
+
import { getFileByPath } from '../db.js';
|
|
9
|
+
// ─── Tool definition ──────────────────────────────────────────────────────────
|
|
10
|
+
export const toolDef = {
|
|
11
|
+
name: 'kb_snippet',
|
|
12
|
+
description: 'Return the source lines for a given file path (as recorded in the index). ' +
|
|
13
|
+
'Optionally restrict the output to a line range using `start_line` and `end_line` ' +
|
|
14
|
+
'(1-based, inclusive). Returns the raw source text.',
|
|
15
|
+
inputSchema: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
path: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: 'Absolute file path as stored in the knowledge-base index.',
|
|
21
|
+
},
|
|
22
|
+
start_line: {
|
|
23
|
+
type: 'number',
|
|
24
|
+
description: 'First line to include (1-based, inclusive). Defaults to 1.',
|
|
25
|
+
},
|
|
26
|
+
end_line: {
|
|
27
|
+
type: 'number',
|
|
28
|
+
description: 'Last line to include (1-based, inclusive). Defaults to end-of-file.',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
required: ['path'],
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
/** Read source lines from the filesystem for the given indexed file path. */
|
|
35
|
+
export function handler(db, args) {
|
|
36
|
+
// Confirm the path is known to the index; use branch to disambiguate if provided.
|
|
37
|
+
const fileRow = getFileByPath(db, args.path, args.branch);
|
|
38
|
+
if (!fileRow) {
|
|
39
|
+
throw new Error(`File not found in index: ${args.path}`);
|
|
40
|
+
}
|
|
41
|
+
const raw = readFileSync(args.path, 'utf8');
|
|
42
|
+
const lines = raw.split('\n');
|
|
43
|
+
const startLine = Math.max(1, args.start_line ?? 1);
|
|
44
|
+
const endLine = Math.min(lines.length, args.end_line ?? lines.length);
|
|
45
|
+
// slice is 0-based; lines are 1-based
|
|
46
|
+
const text = lines.slice(startLine - 1, endLine).join('\n');
|
|
47
|
+
return { path: args.path, start_line: startLine, end_line: endLine, text };
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=snippet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippet.js","sourceRoot":"","sources":["../../../src/kb-server/tools/snippet.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,iFAAiF;AAEjF,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,4EAA4E;QAC5E,mFAAmF;QACnF,qDAAqD;IACvD,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,2DAA2D;aACzE;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,6DAA6D;aAC3E;YACD,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,sEAAsE;aACpF;SACF;QACD,QAAQ,EAAE,CAAC,MAAM,CAAC;KACnB;CACO,CAAC;AAkBX,6EAA6E;AAC7E,MAAM,UAAU,OAAO,CAAC,EAAqB,EAAE,IAAiB;IAC9D,kFAAkF;IAClF,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,4BAA4B,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE9B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;IAEtE,sCAAsC;IACtC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE5D,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC7E,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module kb-server/tools/test-map
|
|
3
|
+
*
|
|
4
|
+
* MCP tool: query mapped tests for a source file.
|
|
5
|
+
*/
|
|
6
|
+
import type { Database } from '../db.js';
|
|
7
|
+
export declare const toolDef: {
|
|
8
|
+
readonly name: "kb_test_map";
|
|
9
|
+
readonly description: "Return mapped test files (with confidence values) for a given source file path.";
|
|
10
|
+
readonly inputSchema: {
|
|
11
|
+
readonly type: "object";
|
|
12
|
+
readonly properties: {
|
|
13
|
+
readonly source_path: {
|
|
14
|
+
readonly type: "string";
|
|
15
|
+
readonly description: "Source file path to resolve mapped test files for.";
|
|
16
|
+
};
|
|
17
|
+
readonly branch: {
|
|
18
|
+
readonly type: "string";
|
|
19
|
+
readonly description: "Optional branch to constrain mappings.";
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
readonly required: readonly ["source_path"];
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export interface TestMapArgs {
|
|
26
|
+
source_path: string;
|
|
27
|
+
branch?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface TestMapResult {
|
|
30
|
+
source_path: string;
|
|
31
|
+
branch: string | null;
|
|
32
|
+
mappings: Array<{
|
|
33
|
+
test_path: string;
|
|
34
|
+
confidence: string;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
export declare function handler(db: Database.Database, args: TestMapArgs): TestMapResult;
|
|
38
|
+
//# sourceMappingURL=test-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-map.d.ts","sourceRoot":"","sources":["../../../src/kb-server/tools/test-map.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAGzC,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;CAkBV,CAAC;AAEX,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5D;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,GAAG,aAAa,CAM/E"}
|