@crowley/rag-mcp 1.0.5 → 1.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/dist/annotations.d.ts +16 -0
- package/dist/annotations.js +158 -0
- package/dist/context-enrichment.js +7 -0
- package/dist/formatters.d.ts +2 -0
- package/dist/formatters.js +12 -0
- package/dist/index.js +99 -47
- package/dist/schemas.d.ts +97 -0
- package/dist/schemas.js +128 -0
- package/dist/tool-middleware.d.ts +40 -0
- package/dist/tool-middleware.js +216 -0
- package/dist/tool-registry.js +2 -1
- package/dist/tools/advanced.d.ts +2 -2
- package/dist/tools/advanced.js +200 -275
- package/dist/tools/agents.d.ts +2 -2
- package/dist/tools/agents.js +59 -78
- package/dist/tools/analytics.d.ts +2 -2
- package/dist/tools/analytics.js +170 -210
- package/dist/tools/architecture.d.ts +2 -2
- package/dist/tools/architecture.js +506 -669
- package/dist/tools/ask.d.ts +2 -2
- package/dist/tools/ask.js +164 -219
- package/dist/tools/cache.d.ts +2 -2
- package/dist/tools/cache.js +63 -82
- package/dist/tools/clustering.d.ts +2 -2
- package/dist/tools/clustering.js +154 -215
- package/dist/tools/confluence.d.ts +2 -2
- package/dist/tools/confluence.js +80 -116
- package/dist/tools/database.d.ts +2 -2
- package/dist/tools/database.js +303 -380
- package/dist/tools/feedback.d.ts +2 -2
- package/dist/tools/feedback.js +143 -184
- package/dist/tools/guidelines.d.ts +2 -2
- package/dist/tools/guidelines.js +123 -135
- package/dist/tools/indexing.d.ts +2 -2
- package/dist/tools/indexing.js +100 -108
- package/dist/tools/memory.d.ts +2 -2
- package/dist/tools/memory.js +299 -485
- package/dist/tools/pm.d.ts +2 -2
- package/dist/tools/pm.js +367 -615
- package/dist/tools/quality.d.ts +8 -0
- package/dist/tools/quality.js +60 -0
- package/dist/tools/review.d.ts +2 -2
- package/dist/tools/review.js +142 -189
- package/dist/tools/search.d.ts +2 -2
- package/dist/tools/search.js +230 -305
- package/dist/tools/session.d.ts +2 -2
- package/dist/tools/session.js +288 -345
- package/dist/tools/suggestions.d.ts +2 -2
- package/dist/tools/suggestions.js +517 -512
- package/dist/types.d.ts +19 -2
- package/package.json +4 -2
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quality tools module - LLM quality monitoring and reporting.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { TOOL_ANNOTATIONS } from "../annotations.js";
|
|
6
|
+
/**
|
|
7
|
+
* Create the quality tools module.
|
|
8
|
+
*/
|
|
9
|
+
export function createQualityTools(projectName) {
|
|
10
|
+
return [
|
|
11
|
+
{
|
|
12
|
+
name: "get_quality_report",
|
|
13
|
+
description: `Get LLM quality metrics for ${projectName}. Shows JSON parse rates, latency percentiles, thinking trace rates, and alerts.`,
|
|
14
|
+
schema: z.object({
|
|
15
|
+
endpoint: z.string().optional().describe("Filter by specific endpoint (e.g., '/api/ask')"),
|
|
16
|
+
}),
|
|
17
|
+
annotations: TOOL_ANNOTATIONS["get_quality_report"] || {
|
|
18
|
+
title: "Get Quality Report",
|
|
19
|
+
readOnlyHint: true,
|
|
20
|
+
openWorldHint: false,
|
|
21
|
+
},
|
|
22
|
+
handler: async (args, ctx) => {
|
|
23
|
+
const params = args.endpoint ? `?endpoint=${encodeURIComponent(args.endpoint)}` : '';
|
|
24
|
+
const response = await ctx.api.get(`/api/quality/report${params}`);
|
|
25
|
+
const data = response.data;
|
|
26
|
+
let result = `## Quality Report\n\n`;
|
|
27
|
+
result += `**Total Metrics:** ${data.total}\n\n`;
|
|
28
|
+
if (data.total === 0) {
|
|
29
|
+
result += `No quality metrics recorded yet.\n`;
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
const m = data.metrics;
|
|
33
|
+
result += `### Aggregate Metrics\n`;
|
|
34
|
+
result += `- **Avg Latency:** ${m.avgLatencyMs}ms\n`;
|
|
35
|
+
result += `- **P95 Latency:** ${m.p95LatencyMs}ms\n`;
|
|
36
|
+
result += `- **JSON Parse Rate:** ${(m.jsonParseRate * 100).toFixed(1)}%\n`;
|
|
37
|
+
result += `- **Thinking Rate:** ${(m.thinkingRate * 100).toFixed(1)}%\n`;
|
|
38
|
+
result += `- **Avg Output Length:** ${m.avgOutputLength} chars\n`;
|
|
39
|
+
result += `- **Avg Thinking Length:** ${m.avgThinkingLength} chars\n`;
|
|
40
|
+
result += `- **Avg Tokens:** ${m.avgTokens}\n\n`;
|
|
41
|
+
if (data.alerts.length > 0) {
|
|
42
|
+
result += `### ⚠ Alerts\n`;
|
|
43
|
+
for (const alert of data.alerts) {
|
|
44
|
+
result += `- ${alert}\n`;
|
|
45
|
+
}
|
|
46
|
+
result += `\n`;
|
|
47
|
+
}
|
|
48
|
+
if (Object.keys(data.byEndpoint).length > 0) {
|
|
49
|
+
result += `### By Endpoint\n`;
|
|
50
|
+
for (const [ep, stats] of Object.entries(data.byEndpoint)) {
|
|
51
|
+
result += `- **${ep}**: ${stats.count} calls, ${stats.avgLatencyMs}ms avg, `;
|
|
52
|
+
result += `JSON: ${(stats.jsonParseRate * 100).toFixed(0)}%, `;
|
|
53
|
+
result += `Thinking: ${(stats.thinkingRate * 100).toFixed(0)}%\n`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
}
|
package/dist/tools/review.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Review & testing tools module - code review, test generation, and test analysis.
|
|
3
3
|
*/
|
|
4
|
-
import type {
|
|
4
|
+
import type { ToolSpec } from "../types.js";
|
|
5
5
|
/**
|
|
6
6
|
* Create the review & testing tools module with project-specific descriptions.
|
|
7
7
|
*/
|
|
8
|
-
export declare function createReviewTools(projectName: string):
|
|
8
|
+
export declare function createReviewTools(projectName: string): ToolSpec[];
|
package/dist/tools/review.js
CHANGED
|
@@ -1,213 +1,166 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Review & testing tools module - code review, test generation, and test analysis.
|
|
3
3
|
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { TOOL_ANNOTATIONS } from "../annotations.js";
|
|
4
6
|
/**
|
|
5
7
|
* Create the review & testing tools module with project-specific descriptions.
|
|
6
8
|
*/
|
|
7
9
|
export function createReviewTools(projectName) {
|
|
8
|
-
|
|
10
|
+
return [
|
|
9
11
|
{
|
|
10
12
|
name: "review_code",
|
|
11
13
|
description: "Review code for issues, pattern violations, and improvements. Uses project patterns and ADRs for context.",
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
14
|
+
schema: z.object({
|
|
15
|
+
code: z.string().describe("Code to review"),
|
|
16
|
+
filePath: z.string().optional().describe("File path for context"),
|
|
17
|
+
reviewType: z.enum(["security", "performance", "patterns", "style", "general"]).optional().describe("Type of review focus (default: general)"),
|
|
18
|
+
diff: z.string().optional().describe("Git diff to review instead of full code"),
|
|
19
|
+
}),
|
|
20
|
+
annotations: TOOL_ANNOTATIONS["review_code"],
|
|
21
|
+
handler: async (args, ctx) => {
|
|
22
|
+
const { code, filePath, reviewType = "general", diff } = args;
|
|
23
|
+
const response = await ctx.api.post("/api/review", {
|
|
24
|
+
code: code || diff,
|
|
25
|
+
filePath,
|
|
26
|
+
reviewType,
|
|
27
|
+
diff,
|
|
28
|
+
});
|
|
29
|
+
const { review, context } = response.data;
|
|
30
|
+
let result = `# Code Review\n\n`;
|
|
31
|
+
if (review.score) {
|
|
32
|
+
result += `**Score**: ${review.score}/10\n\n`;
|
|
33
|
+
}
|
|
34
|
+
if (review.summary) {
|
|
35
|
+
result += `## Summary\n${review.summary}\n\n`;
|
|
36
|
+
}
|
|
37
|
+
if (review.issues && review.issues.length > 0) {
|
|
38
|
+
result += `## Issues Found\n`;
|
|
39
|
+
review.issues.forEach((issue, i) => {
|
|
40
|
+
const icon = issue.severity === "critical"
|
|
41
|
+
? "\u{1F6A8}"
|
|
42
|
+
: issue.severity === "high"
|
|
43
|
+
? "\u26A0\uFE0F"
|
|
44
|
+
: issue.severity === "medium"
|
|
45
|
+
? "\u{1F4CB}"
|
|
46
|
+
: "\u2139\uFE0F";
|
|
47
|
+
result += `\n### ${icon} ${i + 1}. ${issue.type} (${issue.severity})\n`;
|
|
48
|
+
result += `${issue.description}\n`;
|
|
49
|
+
if (issue.line)
|
|
50
|
+
result += `- Line: ${issue.line}\n`;
|
|
51
|
+
if (issue.suggestion)
|
|
52
|
+
result += `- Fix: ${issue.suggestion}\n`;
|
|
53
|
+
});
|
|
54
|
+
result += "\n";
|
|
55
|
+
}
|
|
56
|
+
if (review.positives && review.positives.length > 0) {
|
|
57
|
+
result += `## Positives\n`;
|
|
58
|
+
review.positives.forEach((p) => {
|
|
59
|
+
result += `- ${p}\n`;
|
|
60
|
+
});
|
|
61
|
+
result += "\n";
|
|
62
|
+
}
|
|
63
|
+
if (review.suggestions && review.suggestions.length > 0) {
|
|
64
|
+
result += `## Suggestions\n`;
|
|
65
|
+
review.suggestions.forEach((s) => {
|
|
66
|
+
result += `- ${s}\n`;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
result += `\n---\n_Context: ${context.patternsUsed} patterns, ${context.adrsUsed} ADRs, ${context.similarFilesFound} similar files_`;
|
|
70
|
+
return result;
|
|
34
71
|
},
|
|
35
72
|
},
|
|
36
73
|
{
|
|
37
74
|
name: "generate_tests",
|
|
38
75
|
description: "Generate unit/integration tests based on code and existing test patterns in the project.",
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
76
|
+
schema: z.object({
|
|
77
|
+
code: z.string().describe("Code to generate tests for"),
|
|
78
|
+
filePath: z.string().optional().describe("File path for context"),
|
|
79
|
+
framework: z.enum(["jest", "vitest", "pytest", "mocha"]).optional().describe("Test framework to use (default: jest)"),
|
|
80
|
+
testType: z.enum(["unit", "integration", "e2e"]).optional().describe("Type of tests to generate (default: unit)"),
|
|
81
|
+
coverage: z.enum(["minimal", "standard", "comprehensive"]).optional().describe("Coverage level (default: comprehensive)"),
|
|
82
|
+
}),
|
|
83
|
+
annotations: TOOL_ANNOTATIONS["generate_tests"],
|
|
84
|
+
handler: async (args, ctx) => {
|
|
85
|
+
const { code, filePath, framework = "jest", testType = "unit", coverage = "comprehensive", } = args;
|
|
86
|
+
const response = await ctx.api.post("/api/generate-tests", {
|
|
87
|
+
code,
|
|
88
|
+
filePath,
|
|
89
|
+
framework,
|
|
90
|
+
testType,
|
|
91
|
+
coverage,
|
|
92
|
+
});
|
|
93
|
+
const { tests, analysis, existingPatternsFound } = response.data;
|
|
94
|
+
let result = `# Generated Tests\n\n`;
|
|
95
|
+
result += `**Framework**: ${framework}\n`;
|
|
96
|
+
result += `**Type**: ${testType}\n`;
|
|
97
|
+
result += `**Coverage**: ${coverage}\n`;
|
|
98
|
+
result += `**Existing patterns found**: ${existingPatternsFound}\n\n`;
|
|
99
|
+
if (analysis) {
|
|
100
|
+
result += `## Code Analysis\n`;
|
|
101
|
+
result += `- Functions: ${analysis.functions?.join(", ") || "none"}\n`;
|
|
102
|
+
result += `- Classes: ${analysis.classes?.join(", ") || "none"}\n`;
|
|
103
|
+
result += `- Complexity: ${analysis.estimatedComplexity}\n\n`;
|
|
104
|
+
}
|
|
105
|
+
result += `## Generated Test Code\n\n`;
|
|
106
|
+
result +=
|
|
107
|
+
"```" + (framework === "pytest" ? "python" : "typescript") + "\n";
|
|
108
|
+
result += tests;
|
|
109
|
+
result += "\n```\n";
|
|
110
|
+
return result;
|
|
67
111
|
},
|
|
68
112
|
},
|
|
69
113
|
{
|
|
70
114
|
name: "analyze_tests",
|
|
71
115
|
description: "Analyze existing tests for coverage and quality.",
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
116
|
+
schema: z.object({
|
|
117
|
+
testCode: z.string().describe("Test code to analyze"),
|
|
118
|
+
sourceCode: z.string().optional().describe("Optional source code being tested"),
|
|
119
|
+
}),
|
|
120
|
+
annotations: TOOL_ANNOTATIONS["analyze_tests"],
|
|
121
|
+
handler: async (args, ctx) => {
|
|
122
|
+
const { testCode, sourceCode } = args;
|
|
123
|
+
const response = await ctx.api.post("/api/analyze-tests", {
|
|
124
|
+
testCode,
|
|
125
|
+
sourceCode,
|
|
126
|
+
});
|
|
127
|
+
const { analysis } = response.data;
|
|
128
|
+
let result = `# Test Analysis\n\n`;
|
|
129
|
+
if (analysis.quality) {
|
|
130
|
+
result += `**Quality**: ${analysis.quality}`;
|
|
131
|
+
if (analysis.score)
|
|
132
|
+
result += ` (${analysis.score}/10)`;
|
|
133
|
+
result += "\n\n";
|
|
134
|
+
}
|
|
135
|
+
if (analysis.coverage) {
|
|
136
|
+
result += `## Coverage Estimates\n`;
|
|
137
|
+
Object.entries(analysis.coverage).forEach(([key, value]) => {
|
|
138
|
+
result += `- ${key}: ${value}\n`;
|
|
139
|
+
});
|
|
140
|
+
result += "\n";
|
|
141
|
+
}
|
|
142
|
+
if (analysis.strengths && analysis.strengths.length > 0) {
|
|
143
|
+
result += `## Strengths\n`;
|
|
144
|
+
analysis.strengths.forEach((s) => {
|
|
145
|
+
result += `- ${s}\n`;
|
|
146
|
+
});
|
|
147
|
+
result += "\n";
|
|
148
|
+
}
|
|
149
|
+
if (analysis.weaknesses && analysis.weaknesses.length > 0) {
|
|
150
|
+
result += `## Weaknesses\n`;
|
|
151
|
+
analysis.weaknesses.forEach((w) => {
|
|
152
|
+
result += `- ${w}\n`;
|
|
153
|
+
});
|
|
154
|
+
result += "\n";
|
|
155
|
+
}
|
|
156
|
+
if (analysis.missingTests && analysis.missingTests.length > 0) {
|
|
157
|
+
result += `## Missing Tests\n`;
|
|
158
|
+
analysis.missingTests.forEach((t) => {
|
|
159
|
+
result += `- ${t}\n`;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
85
163
|
},
|
|
86
164
|
},
|
|
87
165
|
];
|
|
88
|
-
const handlers = {
|
|
89
|
-
review_code: async (args, ctx) => {
|
|
90
|
-
const { code, filePath, reviewType = "general", diff } = args;
|
|
91
|
-
const response = await ctx.api.post("/api/review", {
|
|
92
|
-
code: code || diff,
|
|
93
|
-
filePath,
|
|
94
|
-
reviewType,
|
|
95
|
-
diff,
|
|
96
|
-
});
|
|
97
|
-
const { review, context } = response.data;
|
|
98
|
-
let result = `# Code Review\n\n`;
|
|
99
|
-
if (review.score) {
|
|
100
|
-
result += `**Score**: ${review.score}/10\n\n`;
|
|
101
|
-
}
|
|
102
|
-
if (review.summary) {
|
|
103
|
-
result += `## Summary\n${review.summary}\n\n`;
|
|
104
|
-
}
|
|
105
|
-
if (review.issues && review.issues.length > 0) {
|
|
106
|
-
result += `## Issues Found\n`;
|
|
107
|
-
review.issues.forEach((issue, i) => {
|
|
108
|
-
const icon = issue.severity === "critical"
|
|
109
|
-
? "\u{1F6A8}"
|
|
110
|
-
: issue.severity === "high"
|
|
111
|
-
? "\u26A0\uFE0F"
|
|
112
|
-
: issue.severity === "medium"
|
|
113
|
-
? "\u{1F4CB}"
|
|
114
|
-
: "\u2139\uFE0F";
|
|
115
|
-
result += `\n### ${icon} ${i + 1}. ${issue.type} (${issue.severity})\n`;
|
|
116
|
-
result += `${issue.description}\n`;
|
|
117
|
-
if (issue.line)
|
|
118
|
-
result += `- Line: ${issue.line}\n`;
|
|
119
|
-
if (issue.suggestion)
|
|
120
|
-
result += `- Fix: ${issue.suggestion}\n`;
|
|
121
|
-
});
|
|
122
|
-
result += "\n";
|
|
123
|
-
}
|
|
124
|
-
if (review.positives && review.positives.length > 0) {
|
|
125
|
-
result += `## Positives\n`;
|
|
126
|
-
review.positives.forEach((p) => {
|
|
127
|
-
result += `- ${p}\n`;
|
|
128
|
-
});
|
|
129
|
-
result += "\n";
|
|
130
|
-
}
|
|
131
|
-
if (review.suggestions && review.suggestions.length > 0) {
|
|
132
|
-
result += `## Suggestions\n`;
|
|
133
|
-
review.suggestions.forEach((s) => {
|
|
134
|
-
result += `- ${s}\n`;
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
result += `\n---\n_Context: ${context.patternsUsed} patterns, ${context.adrsUsed} ADRs, ${context.similarFilesFound} similar files_`;
|
|
138
|
-
return result;
|
|
139
|
-
},
|
|
140
|
-
generate_tests: async (args, ctx) => {
|
|
141
|
-
const { code, filePath, framework = "jest", testType = "unit", coverage = "comprehensive", } = args;
|
|
142
|
-
const response = await ctx.api.post("/api/generate-tests", {
|
|
143
|
-
code,
|
|
144
|
-
filePath,
|
|
145
|
-
framework,
|
|
146
|
-
testType,
|
|
147
|
-
coverage,
|
|
148
|
-
});
|
|
149
|
-
const { tests, analysis, existingPatternsFound } = response.data;
|
|
150
|
-
let result = `# Generated Tests\n\n`;
|
|
151
|
-
result += `**Framework**: ${framework}\n`;
|
|
152
|
-
result += `**Type**: ${testType}\n`;
|
|
153
|
-
result += `**Coverage**: ${coverage}\n`;
|
|
154
|
-
result += `**Existing patterns found**: ${existingPatternsFound}\n\n`;
|
|
155
|
-
if (analysis) {
|
|
156
|
-
result += `## Code Analysis\n`;
|
|
157
|
-
result += `- Functions: ${analysis.functions?.join(", ") || "none"}\n`;
|
|
158
|
-
result += `- Classes: ${analysis.classes?.join(", ") || "none"}\n`;
|
|
159
|
-
result += `- Complexity: ${analysis.estimatedComplexity}\n\n`;
|
|
160
|
-
}
|
|
161
|
-
result += `## Generated Test Code\n\n`;
|
|
162
|
-
result +=
|
|
163
|
-
"```" + (framework === "pytest" ? "python" : "typescript") + "\n";
|
|
164
|
-
result += tests;
|
|
165
|
-
result += "\n```\n";
|
|
166
|
-
return result;
|
|
167
|
-
},
|
|
168
|
-
analyze_tests: async (args, ctx) => {
|
|
169
|
-
const { testCode, sourceCode } = args;
|
|
170
|
-
const response = await ctx.api.post("/api/analyze-tests", {
|
|
171
|
-
testCode,
|
|
172
|
-
sourceCode,
|
|
173
|
-
});
|
|
174
|
-
const { analysis } = response.data;
|
|
175
|
-
let result = `# Test Analysis\n\n`;
|
|
176
|
-
if (analysis.quality) {
|
|
177
|
-
result += `**Quality**: ${analysis.quality}`;
|
|
178
|
-
if (analysis.score)
|
|
179
|
-
result += ` (${analysis.score}/10)`;
|
|
180
|
-
result += "\n\n";
|
|
181
|
-
}
|
|
182
|
-
if (analysis.coverage) {
|
|
183
|
-
result += `## Coverage Estimates\n`;
|
|
184
|
-
Object.entries(analysis.coverage).forEach(([key, value]) => {
|
|
185
|
-
result += `- ${key}: ${value}\n`;
|
|
186
|
-
});
|
|
187
|
-
result += "\n";
|
|
188
|
-
}
|
|
189
|
-
if (analysis.strengths && analysis.strengths.length > 0) {
|
|
190
|
-
result += `## Strengths\n`;
|
|
191
|
-
analysis.strengths.forEach((s) => {
|
|
192
|
-
result += `- ${s}\n`;
|
|
193
|
-
});
|
|
194
|
-
result += "\n";
|
|
195
|
-
}
|
|
196
|
-
if (analysis.weaknesses && analysis.weaknesses.length > 0) {
|
|
197
|
-
result += `## Weaknesses\n`;
|
|
198
|
-
analysis.weaknesses.forEach((w) => {
|
|
199
|
-
result += `- ${w}\n`;
|
|
200
|
-
});
|
|
201
|
-
result += "\n";
|
|
202
|
-
}
|
|
203
|
-
if (analysis.missingTests && analysis.missingTests.length > 0) {
|
|
204
|
-
result += `## Missing Tests\n`;
|
|
205
|
-
analysis.missingTests.forEach((t) => {
|
|
206
|
-
result += `- ${t}\n`;
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
return result;
|
|
210
|
-
},
|
|
211
|
-
};
|
|
212
|
-
return { tools, handlers };
|
|
213
166
|
}
|
package/dist/tools/search.d.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Search tools module - codebase search, similarity search, grouped/hybrid search,
|
|
3
3
|
* documentation search, and project statistics.
|
|
4
4
|
*/
|
|
5
|
-
import type {
|
|
5
|
+
import type { ToolSpec } from "../types.js";
|
|
6
6
|
/**
|
|
7
7
|
* Create the search tools module with project-specific descriptions.
|
|
8
8
|
*/
|
|
9
|
-
export declare function createSearchTools(projectName: string):
|
|
9
|
+
export declare function createSearchTools(projectName: string): ToolSpec[];
|