lynkr 9.9.1 → 9.10.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 +50 -9
- package/bin/cli.js +2 -0
- package/bin/lynkr-init.js +4 -12
- package/bin/lynkr-reset.js +71 -0
- package/config/model-tiers.json +199 -52
- package/package.json +2 -2
- package/scripts/validate-difficulty-classifier.js +27 -6
- package/src/api/providers-handler.js +0 -1
- package/src/api/router.js +275 -160
- package/src/clients/databricks.js +95 -6
- package/src/config/index.js +3 -43
- package/src/orchestrator/index.js +117 -1235
- package/src/orchestrator/passthrough-stream.js +382 -0
- package/src/orchestrator/sse-transformer.js +408 -0
- package/src/routing/affinity-store.js +17 -3
- package/src/routing/difficulty-classifier.js +52 -10
- package/src/routing/index.js +35 -3
- package/src/routing/intent-score.js +20 -2
- package/src/routing/session-affinity.js +8 -1
- package/src/routing/side-channel-detector.js +103 -0
- package/src/server.js +0 -46
- package/src/agents/context-manager.js +0 -236
- package/src/agents/decomposition/dispatcher.js +0 -185
- package/src/agents/decomposition/gate.js +0 -136
- package/src/agents/decomposition/index.js +0 -183
- package/src/agents/decomposition/model-call.js +0 -75
- package/src/agents/decomposition/planner.js +0 -223
- package/src/agents/decomposition/synthesizer.js +0 -89
- package/src/agents/decomposition/telemetry.js +0 -55
- package/src/agents/definitions/loader.js +0 -653
- package/src/agents/executor.js +0 -457
- package/src/agents/index.js +0 -165
- package/src/agents/parallel-coordinator.js +0 -68
- package/src/agents/reflector.js +0 -331
- package/src/agents/skillbook.js +0 -331
- package/src/agents/store.js +0 -259
- package/src/edits/index.js +0 -171
- package/src/indexer/babel-parser.js +0 -213
- package/src/indexer/index.js +0 -1629
- package/src/indexer/navigation/index.js +0 -32
- package/src/indexer/navigation/providers/treeSitter.js +0 -36
- package/src/indexer/parser.js +0 -443
- package/src/tasks/store.js +0 -349
- package/src/tests/coverage.js +0 -173
- package/src/tests/index.js +0 -171
- package/src/tests/store.js +0 -213
- package/src/tools/agent-task.js +0 -145
- package/src/tools/code-mode.js +0 -304
- package/src/tools/decompose.js +0 -91
- package/src/tools/edits.js +0 -94
- package/src/tools/execution.js +0 -171
- package/src/tools/git.js +0 -1346
- package/src/tools/index.js +0 -306
- package/src/tools/indexer.js +0 -360
- package/src/tools/lazy-loader.js +0 -366
- package/src/tools/mcp-remote.js +0 -88
- package/src/tools/mcp.js +0 -116
- package/src/tools/process.js +0 -167
- package/src/tools/smart-selection.js +0 -180
- package/src/tools/stubs.js +0 -55
- package/src/tools/tasks.js +0 -260
- package/src/tools/tests.js +0 -132
- package/src/tools/tinyfish.js +0 -358
- package/src/tools/truncate.js +0 -106
- package/src/tools/web-client.js +0 -71
- package/src/tools/web.js +0 -415
- package/src/tools/workspace.js +0 -204
package/src/tools/index.js
DELETED
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
const logger = require("../logger");
|
|
2
|
-
const { truncateToolOutput } = require("./truncate");
|
|
3
|
-
|
|
4
|
-
const registry = new Map();
|
|
5
|
-
const registryLowercase = new Map();
|
|
6
|
-
|
|
7
|
-
// Lazy loader reference (set after module load to avoid circular deps)
|
|
8
|
-
let lazyLoader = null;
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Set the lazy loader module (called from server.js)
|
|
12
|
-
* @param {Object} loader - The lazy-loader module
|
|
13
|
-
*/
|
|
14
|
-
function setLazyLoader(loader) {
|
|
15
|
-
lazyLoader = loader;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const TOOL_ALIASES = {
|
|
19
|
-
bash: "shell",
|
|
20
|
-
shell: "shell",
|
|
21
|
-
sh: "shell",
|
|
22
|
-
terminal: "shell",
|
|
23
|
-
grep: "workspace_search",
|
|
24
|
-
search: "workspace_search",
|
|
25
|
-
find: "workspace_search",
|
|
26
|
-
websearch: "web_search",
|
|
27
|
-
web_search: "web_search",
|
|
28
|
-
"Web Search": "web_search",
|
|
29
|
-
WebSearch: "web_search",
|
|
30
|
-
web_fetch: "web_fetch",
|
|
31
|
-
webfetch: "web_fetch",
|
|
32
|
-
web_agent: "web_agent",
|
|
33
|
-
webagent: "web_agent",
|
|
34
|
-
WebAgent: "web_agent",
|
|
35
|
-
tinyfish: "web_agent",
|
|
36
|
-
task: "Task",
|
|
37
|
-
write: "fs_write",
|
|
38
|
-
filewrite: "fs_write",
|
|
39
|
-
read: "fs_read",
|
|
40
|
-
fileread: "fs_read",
|
|
41
|
-
patch: "edit_patch",
|
|
42
|
-
edit: "edit_patch",
|
|
43
|
-
list: "workspace_list",
|
|
44
|
-
ls: "workspace_list",
|
|
45
|
-
dir: "workspace_list",
|
|
46
|
-
summary: "project_summary",
|
|
47
|
-
projectsummary: "project_summary",
|
|
48
|
-
overview: "project_summary",
|
|
49
|
-
reindex: "workspace_index_rebuild",
|
|
50
|
-
index: "workspace_index_rebuild",
|
|
51
|
-
scan: "workspace_index_rebuild",
|
|
52
|
-
history: "workspace_edit_history",
|
|
53
|
-
edits: "workspace_edit_history",
|
|
54
|
-
undo: "workspace_edit_revert",
|
|
55
|
-
revert: "workspace_edit_revert",
|
|
56
|
-
diff: "workspace_diff",
|
|
57
|
-
diffsummary: "workspace_diff_summary",
|
|
58
|
-
summarizediff: "workspace_diff_summary",
|
|
59
|
-
diffsum: "workspace_diff_summary",
|
|
60
|
-
symbol: "workspace_symbol_search",
|
|
61
|
-
symbols: "workspace_symbol_search",
|
|
62
|
-
findsymbol: "workspace_symbol_search",
|
|
63
|
-
symbolsearch: "workspace_symbol_search",
|
|
64
|
-
references: "workspace_symbol_references",
|
|
65
|
-
ref: "workspace_symbol_references",
|
|
66
|
-
findreferences: "workspace_symbol_references",
|
|
67
|
-
usages: "workspace_symbol_references",
|
|
68
|
-
status: "workspace_git_status",
|
|
69
|
-
stage: "workspace_git_stage",
|
|
70
|
-
unstage: "workspace_git_unstage",
|
|
71
|
-
commit: "workspace_git_commit",
|
|
72
|
-
push: "workspace_git_push",
|
|
73
|
-
pull: "workspace_git_pull",
|
|
74
|
-
branches: "workspace_git_branches",
|
|
75
|
-
checkout: "workspace_git_checkout",
|
|
76
|
-
branch: "workspace_git_checkout",
|
|
77
|
-
stash: "workspace_git_stash",
|
|
78
|
-
review: "workspace_diff_review",
|
|
79
|
-
releasenotes: "workspace_release_notes",
|
|
80
|
-
diffstat: "workspace_diff_by_commit",
|
|
81
|
-
merge: "workspace_git_merge",
|
|
82
|
-
rebase: "workspace_git_rebase",
|
|
83
|
-
conflicts: "workspace_git_conflicts",
|
|
84
|
-
patchplan: "workspace_git_patch_plan",
|
|
85
|
-
changelog: "workspace_changelog_generate",
|
|
86
|
-
prtemplate: "workspace_pr_template_generate",
|
|
87
|
-
sandbox: "workspace_sandbox_sessions",
|
|
88
|
-
mcpsessions: "workspace_sandbox_sessions",
|
|
89
|
-
mcpservers: "workspace_mcp_servers",
|
|
90
|
-
tests: "workspace_test_summary",
|
|
91
|
-
testrun: "workspace_test_run",
|
|
92
|
-
runtests: "workspace_test_run",
|
|
93
|
-
testsummary: "workspace_test_summary",
|
|
94
|
-
testhistory: "workspace_test_history",
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
function coerceString(value) {
|
|
98
|
-
if (value === undefined || value === null) return "";
|
|
99
|
-
if (typeof value === "string") return value;
|
|
100
|
-
try {
|
|
101
|
-
return JSON.stringify(value, null, 2);
|
|
102
|
-
} catch {
|
|
103
|
-
return String(value);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function normalizeHandlerResult(result) {
|
|
108
|
-
if (typeof result === "string") {
|
|
109
|
-
return {
|
|
110
|
-
ok: true,
|
|
111
|
-
status: 200,
|
|
112
|
-
content: result,
|
|
113
|
-
metadata: {},
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
if (result === undefined || result === null) {
|
|
117
|
-
return {
|
|
118
|
-
ok: true,
|
|
119
|
-
status: 200,
|
|
120
|
-
content: "",
|
|
121
|
-
metadata: {},
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
const ok = result.ok ?? true;
|
|
125
|
-
const status = result.status ?? (ok ? 200 : 500);
|
|
126
|
-
const content = coerceString(result.content ?? result.output ?? result.data ?? "");
|
|
127
|
-
const metadata = result.metadata ?? {};
|
|
128
|
-
return { ok, status, content, metadata };
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function parseArguments(call) {
|
|
132
|
-
const raw = call?.function?.arguments;
|
|
133
|
-
if (typeof raw !== "string" || raw.trim().length === 0) return {};
|
|
134
|
-
try {
|
|
135
|
-
return JSON.parse(raw);
|
|
136
|
-
} catch (err) {
|
|
137
|
-
logger.warn({ err }, "Failed to parse tool arguments");
|
|
138
|
-
return {};
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function normaliseToolCall(call) {
|
|
143
|
-
const name = call?.function?.name ?? call?.name;
|
|
144
|
-
const id = call?.id ?? `${name ?? "tool"}_${Date.now()}`;
|
|
145
|
-
return {
|
|
146
|
-
id,
|
|
147
|
-
name,
|
|
148
|
-
arguments: parseArguments(call),
|
|
149
|
-
raw: call,
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function registerTool(name, handler, options = {}) {
|
|
154
|
-
if (!name || typeof name !== "string") {
|
|
155
|
-
throw new Error("Tool name must be a non-empty string.");
|
|
156
|
-
}
|
|
157
|
-
if (typeof handler !== "function") {
|
|
158
|
-
throw new Error(`Tool "${name}" must be registered with a function handler.`);
|
|
159
|
-
}
|
|
160
|
-
registry.set(name, { handler, options });
|
|
161
|
-
registryLowercase.set(name.toLowerCase(), { handler, options, original: name });
|
|
162
|
-
logger.debug({ tool: name }, "Tool registered");
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
function hasTool(name) {
|
|
166
|
-
return registry.has(name);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function getTool(name) {
|
|
170
|
-
logger.debug({ tool: name }, "Getting tool");
|
|
171
|
-
if (!name) return undefined;
|
|
172
|
-
const direct = registry.get(name);
|
|
173
|
-
if (direct) return direct;
|
|
174
|
-
const lower = registryLowercase.get(name.toLowerCase());
|
|
175
|
-
if (lower) return registry.get(lower.original);
|
|
176
|
-
const aliasTarget = TOOL_ALIASES[name.toLowerCase()];
|
|
177
|
-
if (aliasTarget) {
|
|
178
|
-
const aliasEntry = registry.get(aliasTarget);
|
|
179
|
-
if (aliasEntry) return aliasEntry;
|
|
180
|
-
}
|
|
181
|
-
return undefined;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function listTools() {
|
|
185
|
-
return Array.from(registry.keys());
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
async function executeToolCall(call, context = {}) {
|
|
189
|
-
const normalisedCall = normaliseToolCall(call);
|
|
190
|
-
let registered = registry.get(normalisedCall.name);
|
|
191
|
-
if (!registered) {
|
|
192
|
-
const aliasTarget = TOOL_ALIASES[normalisedCall.name.toLowerCase()];
|
|
193
|
-
if (aliasTarget) {
|
|
194
|
-
registered = registry.get(aliasTarget);
|
|
195
|
-
if (registered) {
|
|
196
|
-
normalisedCall.name = aliasTarget;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
if (!registered) {
|
|
201
|
-
const lowerEntry = registryLowercase.get(normalisedCall.name.toLowerCase());
|
|
202
|
-
if (lowerEntry) {
|
|
203
|
-
registered = registry.get(lowerEntry.original);
|
|
204
|
-
normalisedCall.name = lowerEntry.original;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Lazy loading: If tool not found, try to load its category
|
|
209
|
-
if (!registered && lazyLoader) {
|
|
210
|
-
const loaded = lazyLoader.loadCategoryForTool(normalisedCall.name);
|
|
211
|
-
if (loaded) {
|
|
212
|
-
// Retry lookup after loading
|
|
213
|
-
registered = registry.get(normalisedCall.name);
|
|
214
|
-
if (!registered) {
|
|
215
|
-
const aliasTarget = TOOL_ALIASES[normalisedCall.name.toLowerCase()];
|
|
216
|
-
if (aliasTarget) {
|
|
217
|
-
registered = registry.get(aliasTarget);
|
|
218
|
-
if (registered) normalisedCall.name = aliasTarget;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
if (!registered) {
|
|
222
|
-
const lowerEntry = registryLowercase.get(normalisedCall.name.toLowerCase());
|
|
223
|
-
if (lowerEntry) {
|
|
224
|
-
registered = registry.get(lowerEntry.original);
|
|
225
|
-
normalisedCall.name = lowerEntry.original;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
if (!registered) {
|
|
232
|
-
const content = coerceString({
|
|
233
|
-
error: "tool_not_registered",
|
|
234
|
-
tool: normalisedCall.name,
|
|
235
|
-
input: normalisedCall.arguments,
|
|
236
|
-
});
|
|
237
|
-
return {
|
|
238
|
-
id: normalisedCall.id,
|
|
239
|
-
name: normalisedCall.name,
|
|
240
|
-
arguments: normalisedCall.arguments,
|
|
241
|
-
ok: false,
|
|
242
|
-
status: 404,
|
|
243
|
-
content,
|
|
244
|
-
metadata: { registered: false },
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
try {
|
|
249
|
-
const result = await registered.handler(
|
|
250
|
-
{
|
|
251
|
-
id: normalisedCall.id,
|
|
252
|
-
name: normalisedCall.name,
|
|
253
|
-
args: normalisedCall.arguments,
|
|
254
|
-
raw: normalisedCall.raw,
|
|
255
|
-
},
|
|
256
|
-
context,
|
|
257
|
-
);
|
|
258
|
-
const formatted = normalizeHandlerResult(result);
|
|
259
|
-
|
|
260
|
-
const truncatedContent = truncateToolOutput(normalisedCall.name, formatted.content);
|
|
261
|
-
|
|
262
|
-
return {
|
|
263
|
-
id: normalisedCall.id,
|
|
264
|
-
name: normalisedCall.name,
|
|
265
|
-
arguments: normalisedCall.arguments,
|
|
266
|
-
...formatted,
|
|
267
|
-
content: truncatedContent,
|
|
268
|
-
metadata: {
|
|
269
|
-
...(formatted.metadata ?? {}),
|
|
270
|
-
registered: true,
|
|
271
|
-
truncated: truncatedContent !== formatted.content,
|
|
272
|
-
originalLength: formatted.content?.length,
|
|
273
|
-
truncatedLength: truncatedContent?.length,
|
|
274
|
-
},
|
|
275
|
-
};
|
|
276
|
-
} catch (err) {
|
|
277
|
-
logger.error({ err, tool: normalisedCall.name }, "Tool execution failed");
|
|
278
|
-
return {
|
|
279
|
-
id: normalisedCall.id,
|
|
280
|
-
name: normalisedCall.name,
|
|
281
|
-
arguments: normalisedCall.arguments,
|
|
282
|
-
ok: false,
|
|
283
|
-
status: 500,
|
|
284
|
-
content: coerceString({
|
|
285
|
-
error: "tool_execution_failed",
|
|
286
|
-
tool: normalisedCall.name,
|
|
287
|
-
message: err.message,
|
|
288
|
-
}),
|
|
289
|
-
metadata: {
|
|
290
|
-
registered: true,
|
|
291
|
-
error: true,
|
|
292
|
-
},
|
|
293
|
-
error: err,
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
module.exports = {
|
|
299
|
-
registerTool,
|
|
300
|
-
hasTool,
|
|
301
|
-
getTool,
|
|
302
|
-
listTools,
|
|
303
|
-
executeToolCall,
|
|
304
|
-
setLazyLoader,
|
|
305
|
-
TOOL_ALIASES,
|
|
306
|
-
};
|
package/src/tools/indexer.js
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
const {
|
|
2
|
-
listWorkspaceFiles,
|
|
3
|
-
searchWorkspace,
|
|
4
|
-
rebuildWorkspaceIndex,
|
|
5
|
-
getProjectSummary,
|
|
6
|
-
searchSymbols,
|
|
7
|
-
searchSymbolReferences,
|
|
8
|
-
findDefinitionNearLocation,
|
|
9
|
-
listDefinitionsBySymbol,
|
|
10
|
-
} = require("../indexer");
|
|
11
|
-
const { registerTool } = require(".");
|
|
12
|
-
const { getTaskSummary } = require("../tasks/store");
|
|
13
|
-
const { getTestSummary } = require("../tests");
|
|
14
|
-
|
|
15
|
-
function registerWorkspaceListTool() {
|
|
16
|
-
registerTool(
|
|
17
|
-
"workspace_list",
|
|
18
|
-
async ({ args = {} }) => {
|
|
19
|
-
const patterns =
|
|
20
|
-
typeof args.patterns === "string"
|
|
21
|
-
? [args.patterns]
|
|
22
|
-
: Array.isArray(args.patterns)
|
|
23
|
-
? args.patterns
|
|
24
|
-
: undefined;
|
|
25
|
-
const ignore =
|
|
26
|
-
typeof args.ignore === "string"
|
|
27
|
-
? [args.ignore]
|
|
28
|
-
: Array.isArray(args.ignore)
|
|
29
|
-
? args.ignore
|
|
30
|
-
: undefined;
|
|
31
|
-
const limit = Number.isInteger(args.limit) ? args.limit : undefined;
|
|
32
|
-
const withStats = args.with_stats === true || args.include_stats === true;
|
|
33
|
-
const includeDirectories = args.include_directories === true;
|
|
34
|
-
|
|
35
|
-
const entries = await listWorkspaceFiles({
|
|
36
|
-
patterns,
|
|
37
|
-
ignore,
|
|
38
|
-
limit,
|
|
39
|
-
withStats,
|
|
40
|
-
includeDirectories,
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
ok: true,
|
|
45
|
-
status: 200,
|
|
46
|
-
content: JSON.stringify({ entries }, null, 2),
|
|
47
|
-
metadata: {
|
|
48
|
-
total: entries.length,
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
},
|
|
52
|
-
{ category: "indexing" },
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function registerWorkspaceSearchTool() {
|
|
57
|
-
registerTool(
|
|
58
|
-
"workspace_search",
|
|
59
|
-
async ({ args = {} }) => {
|
|
60
|
-
const query = args.query ?? args.term ?? args.pattern;
|
|
61
|
-
const regex = args.regex === true || args.is_regex === true;
|
|
62
|
-
const limit = Number.isInteger(args.limit) ? args.limit : undefined;
|
|
63
|
-
const ignore =
|
|
64
|
-
typeof args.ignore === "string"
|
|
65
|
-
? [args.ignore]
|
|
66
|
-
: Array.isArray(args.ignore)
|
|
67
|
-
? args.ignore
|
|
68
|
-
: undefined;
|
|
69
|
-
|
|
70
|
-
const result = await searchWorkspace({
|
|
71
|
-
query,
|
|
72
|
-
regex,
|
|
73
|
-
limit,
|
|
74
|
-
ignore,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
ok: true,
|
|
79
|
-
status: 200,
|
|
80
|
-
content: JSON.stringify(result, null, 2),
|
|
81
|
-
metadata: {
|
|
82
|
-
total: result.matches.length,
|
|
83
|
-
engine: result.engine,
|
|
84
|
-
},
|
|
85
|
-
};
|
|
86
|
-
},
|
|
87
|
-
{ category: "indexing" },
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function registerWorkspaceRebuildTool() {
|
|
92
|
-
registerTool(
|
|
93
|
-
"workspace_index_rebuild",
|
|
94
|
-
async ({ args = {} }) => {
|
|
95
|
-
const patterns =
|
|
96
|
-
typeof args.patterns === "string"
|
|
97
|
-
? [args.patterns]
|
|
98
|
-
: Array.isArray(args.patterns)
|
|
99
|
-
? args.patterns
|
|
100
|
-
: undefined;
|
|
101
|
-
const ignore =
|
|
102
|
-
typeof args.ignore === "string"
|
|
103
|
-
? [args.ignore]
|
|
104
|
-
: Array.isArray(args.ignore)
|
|
105
|
-
? args.ignore
|
|
106
|
-
: undefined;
|
|
107
|
-
|
|
108
|
-
const summary = await rebuildWorkspaceIndex({
|
|
109
|
-
patterns,
|
|
110
|
-
ignore,
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
ok: true,
|
|
115
|
-
status: 200,
|
|
116
|
-
content: JSON.stringify(summary, null, 2),
|
|
117
|
-
metadata: {
|
|
118
|
-
fileCount: summary.fileCount,
|
|
119
|
-
languages: summary.languages,
|
|
120
|
-
frameworks: summary.frameworks,
|
|
121
|
-
},
|
|
122
|
-
};
|
|
123
|
-
},
|
|
124
|
-
{ category: "indexing" },
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function registerProjectSummaryTool() {
|
|
129
|
-
registerTool(
|
|
130
|
-
"project_summary",
|
|
131
|
-
async ({ args = {} }) => {
|
|
132
|
-
let summary = getProjectSummary();
|
|
133
|
-
if (args.rebuild === true || args.refresh === true) {
|
|
134
|
-
summary = await rebuildWorkspaceIndex({});
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const tasksLimitRaw =
|
|
138
|
-
args.tasks_limit ?? args.tasksLimit ?? args.tasks_sample ?? args.tasksSample;
|
|
139
|
-
const tasks = getTaskSummary({
|
|
140
|
-
limit:
|
|
141
|
-
tasksLimitRaw === undefined || tasksLimitRaw === null
|
|
142
|
-
? undefined
|
|
143
|
-
: Number.isFinite(Number(tasksLimitRaw))
|
|
144
|
-
? Number(tasksLimitRaw)
|
|
145
|
-
: undefined,
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
const tests = getTestSummary({
|
|
149
|
-
includeRecent: args.tests_recent === true || args.testsRecent === true,
|
|
150
|
-
recentLimit:
|
|
151
|
-
args.tests_recent_limit ?? args.testsRecentLimit ?? args.tests_recent_sample ?? args.testsRecentSample,
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
const payload = {
|
|
155
|
-
...summary,
|
|
156
|
-
tasks,
|
|
157
|
-
tests,
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
return {
|
|
161
|
-
ok: true,
|
|
162
|
-
status: 200,
|
|
163
|
-
content: JSON.stringify(payload, null, 2),
|
|
164
|
-
metadata: {
|
|
165
|
-
fileCount: summary.fileCount,
|
|
166
|
-
languages: summary.languages,
|
|
167
|
-
frameworks: summary.frameworks,
|
|
168
|
-
tasks: tasks.total,
|
|
169
|
-
tests: tests.totalRuns ?? 0,
|
|
170
|
-
},
|
|
171
|
-
};
|
|
172
|
-
},
|
|
173
|
-
{ category: "indexing" },
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function registerSymbolSearchTool() {
|
|
178
|
-
registerTool(
|
|
179
|
-
"workspace_symbol_search",
|
|
180
|
-
async ({ args = {} }) => {
|
|
181
|
-
const query = args.query ?? args.name ?? args.symbol;
|
|
182
|
-
const limit =
|
|
183
|
-
typeof args.limit === "number" && args.limit > 0 ? Math.min(args.limit, 100) : 50;
|
|
184
|
-
const language =
|
|
185
|
-
typeof args.language === "string" ? args.language.toLowerCase() : undefined;
|
|
186
|
-
const file =
|
|
187
|
-
typeof args.path === "string"
|
|
188
|
-
? args.path
|
|
189
|
-
: typeof args.file === "string"
|
|
190
|
-
? args.file
|
|
191
|
-
: undefined;
|
|
192
|
-
|
|
193
|
-
const results = searchSymbols({
|
|
194
|
-
query,
|
|
195
|
-
language,
|
|
196
|
-
limit,
|
|
197
|
-
filePath: file,
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
return {
|
|
201
|
-
ok: true,
|
|
202
|
-
status: 200,
|
|
203
|
-
content: JSON.stringify(
|
|
204
|
-
{
|
|
205
|
-
query,
|
|
206
|
-
language,
|
|
207
|
-
file,
|
|
208
|
-
results,
|
|
209
|
-
},
|
|
210
|
-
null,
|
|
211
|
-
2,
|
|
212
|
-
),
|
|
213
|
-
metadata: {
|
|
214
|
-
total: results.length,
|
|
215
|
-
},
|
|
216
|
-
};
|
|
217
|
-
},
|
|
218
|
-
{ category: "indexing" },
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
function registerSymbolReferencesTool() {
|
|
223
|
-
registerTool(
|
|
224
|
-
"workspace_symbol_references",
|
|
225
|
-
async ({ args = {} }) => {
|
|
226
|
-
const symbol = args.symbol ?? args.name ?? args.query;
|
|
227
|
-
const limit =
|
|
228
|
-
typeof args.limit === "number" && args.limit > 0 ? Math.min(args.limit, 100) : 50;
|
|
229
|
-
const file =
|
|
230
|
-
typeof args.path === "string"
|
|
231
|
-
? args.path
|
|
232
|
-
: typeof args.file === "string"
|
|
233
|
-
? args.file
|
|
234
|
-
: undefined;
|
|
235
|
-
|
|
236
|
-
const results = searchSymbolReferences({
|
|
237
|
-
symbol,
|
|
238
|
-
filePath: file,
|
|
239
|
-
limit,
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
return {
|
|
243
|
-
ok: true,
|
|
244
|
-
status: 200,
|
|
245
|
-
content: JSON.stringify(
|
|
246
|
-
{
|
|
247
|
-
symbol,
|
|
248
|
-
file,
|
|
249
|
-
results,
|
|
250
|
-
},
|
|
251
|
-
null,
|
|
252
|
-
2,
|
|
253
|
-
),
|
|
254
|
-
metadata: {
|
|
255
|
-
total: results.length,
|
|
256
|
-
},
|
|
257
|
-
};
|
|
258
|
-
},
|
|
259
|
-
{ category: "indexing" },
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
function registerGotoDefinitionTool() {
|
|
264
|
-
registerTool(
|
|
265
|
-
"workspace_goto_definition",
|
|
266
|
-
async ({ args = {} }) => {
|
|
267
|
-
const filePath =
|
|
268
|
-
typeof args.file === "string"
|
|
269
|
-
? args.file
|
|
270
|
-
: typeof args.path === "string"
|
|
271
|
-
? args.path
|
|
272
|
-
: null;
|
|
273
|
-
const line =
|
|
274
|
-
typeof args.line === "number"
|
|
275
|
-
? args.line
|
|
276
|
-
: typeof args.row === "number"
|
|
277
|
-
? args.row
|
|
278
|
-
: null;
|
|
279
|
-
const column =
|
|
280
|
-
typeof args.column === "number"
|
|
281
|
-
? args.column
|
|
282
|
-
: typeof args.col === "number"
|
|
283
|
-
? args.col
|
|
284
|
-
: null;
|
|
285
|
-
const symbolName =
|
|
286
|
-
typeof args.symbol === "string"
|
|
287
|
-
? args.symbol
|
|
288
|
-
: typeof args.name === "string"
|
|
289
|
-
? args.name
|
|
290
|
-
: null;
|
|
291
|
-
|
|
292
|
-
if (filePath && line) {
|
|
293
|
-
const rows = findDefinitionNearLocation({ filePath, line, column });
|
|
294
|
-
return {
|
|
295
|
-
ok: true,
|
|
296
|
-
status: 200,
|
|
297
|
-
content: JSON.stringify(
|
|
298
|
-
{
|
|
299
|
-
filePath,
|
|
300
|
-
line,
|
|
301
|
-
column: column ?? null,
|
|
302
|
-
results: rows.map((row) => ({
|
|
303
|
-
symbol: row.name,
|
|
304
|
-
kind: row.kind,
|
|
305
|
-
definition: {
|
|
306
|
-
filePath: row.definition_path,
|
|
307
|
-
line: row.definition_line,
|
|
308
|
-
column: row.definition_column,
|
|
309
|
-
},
|
|
310
|
-
reference: {
|
|
311
|
-
filePath: row.reference_path,
|
|
312
|
-
line: row.reference_line,
|
|
313
|
-
column: row.reference_column,
|
|
314
|
-
snippet: row.snippet ?? null,
|
|
315
|
-
},
|
|
316
|
-
})),
|
|
317
|
-
},
|
|
318
|
-
null,
|
|
319
|
-
2,
|
|
320
|
-
),
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
if (symbolName) {
|
|
325
|
-
const rows = listDefinitionsBySymbol({ name: symbolName });
|
|
326
|
-
return {
|
|
327
|
-
ok: true,
|
|
328
|
-
status: 200,
|
|
329
|
-
content: JSON.stringify(
|
|
330
|
-
{
|
|
331
|
-
symbol: symbolName,
|
|
332
|
-
definitions: rows,
|
|
333
|
-
},
|
|
334
|
-
null,
|
|
335
|
-
2,
|
|
336
|
-
),
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
throw new Error(
|
|
341
|
-
"workspace_goto_definition requires either (file,line[,column]) or symbol name.",
|
|
342
|
-
);
|
|
343
|
-
},
|
|
344
|
-
{ category: "indexing" },
|
|
345
|
-
);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
function registerIndexerTools() {
|
|
349
|
-
registerWorkspaceListTool();
|
|
350
|
-
registerWorkspaceSearchTool();
|
|
351
|
-
registerWorkspaceRebuildTool();
|
|
352
|
-
registerProjectSummaryTool();
|
|
353
|
-
registerSymbolSearchTool();
|
|
354
|
-
registerSymbolReferencesTool();
|
|
355
|
-
registerGotoDefinitionTool();
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
module.exports = {
|
|
359
|
-
registerIndexerTools,
|
|
360
|
-
};
|