@crowley/rag-mcp 1.0.5 → 1.0.6
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 +46 -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/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 +425 -512
- package/dist/types.d.ts +19 -2
- package/package.json +4 -2
package/dist/tools/ask.d.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Ask tools module - question answering, code explanation, feature finding,
|
|
3
3
|
* conversation analysis, and auto-remember.
|
|
4
4
|
*/
|
|
5
|
-
import type {
|
|
5
|
+
import type { ToolSpec } from "../types.js";
|
|
6
6
|
/**
|
|
7
7
|
* Create the ask tools module with project-specific descriptions.
|
|
8
8
|
*/
|
|
9
|
-
export declare function createAskTools(projectName: string):
|
|
9
|
+
export declare function createAskTools(projectName: string): ToolSpec[];
|
package/dist/tools/ask.js
CHANGED
|
@@ -3,254 +3,199 @@
|
|
|
3
3
|
* conversation analysis, and auto-remember.
|
|
4
4
|
*/
|
|
5
5
|
import { pct } from "../formatters.js";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { TOOL_ANNOTATIONS } from "../annotations.js";
|
|
6
8
|
/**
|
|
7
9
|
* Create the ask tools module with project-specific descriptions.
|
|
8
10
|
*/
|
|
9
11
|
export function createAskTools(projectName) {
|
|
10
|
-
|
|
12
|
+
return [
|
|
11
13
|
{
|
|
12
14
|
name: "ask_codebase",
|
|
13
15
|
description: `Ask a question about the ${projectName} codebase. Uses RAG + LLM to provide contextual answers.`,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
schema: z.object({
|
|
17
|
+
question: z.string().describe("Question about the codebase"),
|
|
18
|
+
}),
|
|
19
|
+
annotations: TOOL_ANNOTATIONS["ask_codebase"],
|
|
20
|
+
handler: async (args, ctx) => {
|
|
21
|
+
const { question } = args;
|
|
22
|
+
const response = await ctx.api.post("/api/ask", {
|
|
23
|
+
collection: `${ctx.collectionPrefix}codebase`,
|
|
24
|
+
question,
|
|
25
|
+
});
|
|
26
|
+
return response.data.answer || "No answer could be generated.";
|
|
23
27
|
},
|
|
24
28
|
},
|
|
25
29
|
{
|
|
26
30
|
name: "explain_code",
|
|
27
31
|
description: "Get a detailed explanation of a code snippet.",
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
32
|
+
schema: z.object({
|
|
33
|
+
code: z.string().describe("Code snippet to explain"),
|
|
34
|
+
filePath: z.string().optional().describe("Optional file path for context"),
|
|
35
|
+
}),
|
|
36
|
+
annotations: TOOL_ANNOTATIONS["explain_code"],
|
|
37
|
+
handler: async (args, ctx) => {
|
|
38
|
+
const { code, filePath } = args;
|
|
39
|
+
const response = await ctx.api.post("/api/explain", {
|
|
40
|
+
collection: `${ctx.collectionPrefix}codebase`,
|
|
41
|
+
code,
|
|
42
|
+
filePath,
|
|
43
|
+
});
|
|
44
|
+
const data = response.data;
|
|
45
|
+
let result = `## Summary\n${data.summary || "N/A"}\n\n`;
|
|
46
|
+
result += `## Purpose\n${data.purpose || "N/A"}\n\n`;
|
|
47
|
+
if (data.keyComponents && data.keyComponents.length > 0) {
|
|
48
|
+
result += `## Key Components\n`;
|
|
49
|
+
for (const comp of data.keyComponents) {
|
|
50
|
+
result += `- ${comp}\n`;
|
|
51
|
+
}
|
|
52
|
+
result += "\n";
|
|
53
|
+
}
|
|
54
|
+
if (data.dependencies && data.dependencies.length > 0) {
|
|
55
|
+
result += `## Dependencies\n`;
|
|
56
|
+
for (const dep of data.dependencies) {
|
|
57
|
+
result += `- ${dep}\n`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
41
61
|
},
|
|
42
62
|
},
|
|
43
63
|
{
|
|
44
64
|
name: "find_feature",
|
|
45
65
|
description: `Find where a specific feature is implemented in the ${projectName} codebase.`,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
66
|
+
schema: z.object({
|
|
67
|
+
description: z.string().describe("Description of the feature to find"),
|
|
68
|
+
}),
|
|
69
|
+
annotations: TOOL_ANNOTATIONS["find_feature"],
|
|
70
|
+
handler: async (args, ctx) => {
|
|
71
|
+
const { description } = args;
|
|
72
|
+
const response = await ctx.api.post("/api/find-feature", {
|
|
73
|
+
collection: `${ctx.collectionPrefix}codebase`,
|
|
74
|
+
description,
|
|
75
|
+
});
|
|
76
|
+
const data = response.data;
|
|
77
|
+
let result = `## Feature: ${data.name || description}\n\n`;
|
|
78
|
+
result += `${data.explanation || "No explanation available."}\n\n`;
|
|
79
|
+
if (data.mainFiles && data.mainFiles.length > 0) {
|
|
80
|
+
result += `### Main Files\n`;
|
|
81
|
+
for (const f of data.mainFiles) {
|
|
82
|
+
result += `- **${f.file}** (${pct(f.score)} match)\n`;
|
|
83
|
+
}
|
|
84
|
+
result += "\n";
|
|
85
|
+
}
|
|
86
|
+
if (data.relatedFiles && data.relatedFiles.length > 0) {
|
|
87
|
+
result += `### Related Files\n`;
|
|
88
|
+
for (const f of data.relatedFiles) {
|
|
89
|
+
result += `- ${f.file}\n`;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
55
93
|
},
|
|
56
94
|
},
|
|
57
95
|
{
|
|
58
96
|
name: "analyze_conversation",
|
|
59
97
|
description: `Analyze a conversation to extract learnings, decisions, and insights for ${projectName}.`,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
98
|
+
schema: z.object({
|
|
99
|
+
conversation: z.string().describe("The conversation text to analyze"),
|
|
100
|
+
context: z.string().optional().describe("Additional context about the conversation"),
|
|
101
|
+
autoSave: z.boolean().optional().describe("Automatically save extracted learnings (default: false)"),
|
|
102
|
+
minConfidence: z.number().optional().describe("Minimum confidence threshold for learnings (0-1, default: 0.7)"),
|
|
103
|
+
}),
|
|
104
|
+
annotations: TOOL_ANNOTATIONS["analyze_conversation"],
|
|
105
|
+
handler: async (args, ctx) => {
|
|
106
|
+
const { conversation, context, autoSave = false, minConfidence = 0.7 } = args;
|
|
107
|
+
const response = await ctx.api.post("/api/analyze-conversation", {
|
|
108
|
+
projectName: ctx.projectName,
|
|
109
|
+
conversation,
|
|
110
|
+
context,
|
|
111
|
+
autoSave,
|
|
112
|
+
minConfidence,
|
|
113
|
+
});
|
|
114
|
+
const data = response.data;
|
|
115
|
+
let result = `## Conversation Analysis\n\n`;
|
|
116
|
+
result += `**Summary:** ${data.summary || "N/A"}\n\n`;
|
|
117
|
+
if (data.learnings && data.learnings.length > 0) {
|
|
118
|
+
result += `### Extracted Learnings\n`;
|
|
119
|
+
for (const l of data.learnings) {
|
|
120
|
+
result += `- **[${l.type}]** (confidence: ${pct(l.confidence)}) ${l.content}\n`;
|
|
121
|
+
if (l.tags && l.tags.length > 0) {
|
|
122
|
+
result += ` Tags: ${l.tags.join(", ")}\n`;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
result += "\n";
|
|
126
|
+
}
|
|
127
|
+
if (data.entities) {
|
|
128
|
+
if (data.entities.files && data.entities.files.length > 0) {
|
|
129
|
+
result += `### Referenced Files\n`;
|
|
130
|
+
for (const f of data.entities.files) {
|
|
131
|
+
result += `- ${f}\n`;
|
|
132
|
+
}
|
|
133
|
+
result += "\n";
|
|
134
|
+
}
|
|
135
|
+
if (data.entities.functions && data.entities.functions.length > 0) {
|
|
136
|
+
result += `### Referenced Functions\n`;
|
|
137
|
+
for (const f of data.entities.functions) {
|
|
138
|
+
result += `- ${f}\n`;
|
|
139
|
+
}
|
|
140
|
+
result += "\n";
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (data.savedCount !== undefined) {
|
|
144
|
+
result += `**Saved:** ${data.savedCount} learnings\n`;
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
83
147
|
},
|
|
84
148
|
},
|
|
85
149
|
{
|
|
86
150
|
name: "auto_remember",
|
|
87
151
|
description: `Automatically classify and remember information for ${projectName}. Analyzes content to determine the best memory type.`,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
152
|
+
schema: z.object({
|
|
153
|
+
content: z.string().describe("Content to analyze and remember"),
|
|
154
|
+
context: z.string().optional().describe("Additional context"),
|
|
155
|
+
relatedTo: z.string().optional().describe("Related feature or topic"),
|
|
156
|
+
tags: z.array(z.string()).optional().describe("Tags for categorization"),
|
|
157
|
+
}),
|
|
158
|
+
annotations: TOOL_ANNOTATIONS["auto_remember"],
|
|
159
|
+
handler: async (args, ctx) => {
|
|
160
|
+
const { content, context, relatedTo, tags } = args;
|
|
161
|
+
// First, analyze the content to classify it
|
|
162
|
+
const analyzeResponse = await ctx.api.post("/api/analyze-conversation", {
|
|
163
|
+
projectName: ctx.projectName,
|
|
164
|
+
conversation: content,
|
|
165
|
+
context,
|
|
166
|
+
autoSave: false,
|
|
167
|
+
minConfidence: 0.5,
|
|
168
|
+
});
|
|
169
|
+
const analysis = analyzeResponse.data;
|
|
170
|
+
let memoryType = "note";
|
|
171
|
+
let confidence = 0;
|
|
172
|
+
if (analysis.learnings && analysis.learnings.length > 0) {
|
|
173
|
+
const best = analysis.learnings[0];
|
|
174
|
+
memoryType = best.type || "note";
|
|
175
|
+
confidence = best.confidence || 0;
|
|
176
|
+
}
|
|
177
|
+
// Save with the classified type
|
|
178
|
+
const rememberResponse = await ctx.api.post("/api/memory", {
|
|
179
|
+
projectName: ctx.projectName,
|
|
180
|
+
type: memoryType,
|
|
181
|
+
content,
|
|
182
|
+
relatedTo,
|
|
183
|
+
tags: tags || (analysis.learnings?.[0]?.tags),
|
|
184
|
+
metadata: {
|
|
185
|
+
source: 'auto_pattern',
|
|
186
|
+
confidence,
|
|
107
187
|
},
|
|
108
|
-
}
|
|
109
|
-
|
|
188
|
+
});
|
|
189
|
+
const saved = rememberResponse.data;
|
|
190
|
+
let result = `## Auto-Remembered\n\n`;
|
|
191
|
+
result += `- **Type:** ${memoryType}\n`;
|
|
192
|
+
result += `- **Confidence:** ${confidence > 0 ? pct(confidence) : "N/A (fallback to note)"}\n`;
|
|
193
|
+
result += `- **ID:** ${saved.id || "N/A"}\n`;
|
|
194
|
+
if (saved.tags && saved.tags.length > 0) {
|
|
195
|
+
result += `- **Tags:** ${saved.tags.join(", ")}\n`;
|
|
196
|
+
}
|
|
197
|
+
return result;
|
|
110
198
|
},
|
|
111
199
|
},
|
|
112
200
|
];
|
|
113
|
-
const handlers = {
|
|
114
|
-
ask_codebase: async (args, ctx) => {
|
|
115
|
-
const { question } = args;
|
|
116
|
-
const response = await ctx.api.post("/api/ask", {
|
|
117
|
-
collection: `${ctx.collectionPrefix}codebase`,
|
|
118
|
-
question,
|
|
119
|
-
});
|
|
120
|
-
return response.data.answer || "No answer could be generated.";
|
|
121
|
-
},
|
|
122
|
-
explain_code: async (args, ctx) => {
|
|
123
|
-
const { code, filePath } = args;
|
|
124
|
-
const response = await ctx.api.post("/api/explain", {
|
|
125
|
-
collection: `${ctx.collectionPrefix}codebase`,
|
|
126
|
-
code,
|
|
127
|
-
filePath,
|
|
128
|
-
});
|
|
129
|
-
const data = response.data;
|
|
130
|
-
let result = `## Summary\n${data.summary || "N/A"}\n\n`;
|
|
131
|
-
result += `## Purpose\n${data.purpose || "N/A"}\n\n`;
|
|
132
|
-
if (data.keyComponents && data.keyComponents.length > 0) {
|
|
133
|
-
result += `## Key Components\n`;
|
|
134
|
-
for (const comp of data.keyComponents) {
|
|
135
|
-
result += `- ${comp}\n`;
|
|
136
|
-
}
|
|
137
|
-
result += "\n";
|
|
138
|
-
}
|
|
139
|
-
if (data.dependencies && data.dependencies.length > 0) {
|
|
140
|
-
result += `## Dependencies\n`;
|
|
141
|
-
for (const dep of data.dependencies) {
|
|
142
|
-
result += `- ${dep}\n`;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return result;
|
|
146
|
-
},
|
|
147
|
-
find_feature: async (args, ctx) => {
|
|
148
|
-
const { description } = args;
|
|
149
|
-
const response = await ctx.api.post("/api/find-feature", {
|
|
150
|
-
collection: `${ctx.collectionPrefix}codebase`,
|
|
151
|
-
description,
|
|
152
|
-
});
|
|
153
|
-
const data = response.data;
|
|
154
|
-
let result = `## Feature: ${data.name || description}\n\n`;
|
|
155
|
-
result += `${data.explanation || "No explanation available."}\n\n`;
|
|
156
|
-
if (data.mainFiles && data.mainFiles.length > 0) {
|
|
157
|
-
result += `### Main Files\n`;
|
|
158
|
-
for (const f of data.mainFiles) {
|
|
159
|
-
result += `- **${f.file}** (${pct(f.score)} match)\n`;
|
|
160
|
-
}
|
|
161
|
-
result += "\n";
|
|
162
|
-
}
|
|
163
|
-
if (data.relatedFiles && data.relatedFiles.length > 0) {
|
|
164
|
-
result += `### Related Files\n`;
|
|
165
|
-
for (const f of data.relatedFiles) {
|
|
166
|
-
result += `- ${f.file}\n`;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return result;
|
|
170
|
-
},
|
|
171
|
-
analyze_conversation: async (args, ctx) => {
|
|
172
|
-
const { conversation, context, autoSave = false, minConfidence = 0.7 } = args;
|
|
173
|
-
const response = await ctx.api.post("/api/analyze-conversation", {
|
|
174
|
-
projectName: ctx.projectName,
|
|
175
|
-
conversation,
|
|
176
|
-
context,
|
|
177
|
-
autoSave,
|
|
178
|
-
minConfidence,
|
|
179
|
-
});
|
|
180
|
-
const data = response.data;
|
|
181
|
-
let result = `## Conversation Analysis\n\n`;
|
|
182
|
-
result += `**Summary:** ${data.summary || "N/A"}\n\n`;
|
|
183
|
-
if (data.learnings && data.learnings.length > 0) {
|
|
184
|
-
result += `### Extracted Learnings\n`;
|
|
185
|
-
for (const l of data.learnings) {
|
|
186
|
-
result += `- **[${l.type}]** (confidence: ${pct(l.confidence)}) ${l.content}\n`;
|
|
187
|
-
if (l.tags && l.tags.length > 0) {
|
|
188
|
-
result += ` Tags: ${l.tags.join(", ")}\n`;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
result += "\n";
|
|
192
|
-
}
|
|
193
|
-
if (data.entities) {
|
|
194
|
-
if (data.entities.files && data.entities.files.length > 0) {
|
|
195
|
-
result += `### Referenced Files\n`;
|
|
196
|
-
for (const f of data.entities.files) {
|
|
197
|
-
result += `- ${f}\n`;
|
|
198
|
-
}
|
|
199
|
-
result += "\n";
|
|
200
|
-
}
|
|
201
|
-
if (data.entities.functions && data.entities.functions.length > 0) {
|
|
202
|
-
result += `### Referenced Functions\n`;
|
|
203
|
-
for (const f of data.entities.functions) {
|
|
204
|
-
result += `- ${f}\n`;
|
|
205
|
-
}
|
|
206
|
-
result += "\n";
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
if (data.savedCount !== undefined) {
|
|
210
|
-
result += `**Saved:** ${data.savedCount} learnings\n`;
|
|
211
|
-
}
|
|
212
|
-
return result;
|
|
213
|
-
},
|
|
214
|
-
auto_remember: async (args, ctx) => {
|
|
215
|
-
const { content, context, relatedTo, tags } = args;
|
|
216
|
-
// First, analyze the content to classify it
|
|
217
|
-
const analyzeResponse = await ctx.api.post("/api/analyze-conversation", {
|
|
218
|
-
projectName: ctx.projectName,
|
|
219
|
-
conversation: content,
|
|
220
|
-
context,
|
|
221
|
-
autoSave: false,
|
|
222
|
-
minConfidence: 0.5,
|
|
223
|
-
});
|
|
224
|
-
const analysis = analyzeResponse.data;
|
|
225
|
-
let memoryType = "note";
|
|
226
|
-
let confidence = 0;
|
|
227
|
-
if (analysis.learnings && analysis.learnings.length > 0) {
|
|
228
|
-
const best = analysis.learnings[0];
|
|
229
|
-
memoryType = best.type || "note";
|
|
230
|
-
confidence = best.confidence || 0;
|
|
231
|
-
}
|
|
232
|
-
// Save with the classified type
|
|
233
|
-
const rememberResponse = await ctx.api.post("/api/memory", {
|
|
234
|
-
projectName: ctx.projectName,
|
|
235
|
-
type: memoryType,
|
|
236
|
-
content,
|
|
237
|
-
relatedTo,
|
|
238
|
-
tags: tags || (analysis.learnings?.[0]?.tags),
|
|
239
|
-
metadata: {
|
|
240
|
-
source: 'auto_pattern',
|
|
241
|
-
confidence,
|
|
242
|
-
},
|
|
243
|
-
});
|
|
244
|
-
const saved = rememberResponse.data;
|
|
245
|
-
let result = `## Auto-Remembered\n\n`;
|
|
246
|
-
result += `- **Type:** ${memoryType}\n`;
|
|
247
|
-
result += `- **Confidence:** ${confidence > 0 ? pct(confidence) : "N/A (fallback to note)"}\n`;
|
|
248
|
-
result += `- **ID:** ${saved.id || "N/A"}\n`;
|
|
249
|
-
if (saved.tags && saved.tags.length > 0) {
|
|
250
|
-
result += `- **Tags:** ${saved.tags.join(", ")}\n`;
|
|
251
|
-
}
|
|
252
|
-
return result;
|
|
253
|
-
},
|
|
254
|
-
};
|
|
255
|
-
return { tools, handlers };
|
|
256
201
|
}
|
package/dist/tools/cache.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cache Management Tools
|
|
3
3
|
*/
|
|
4
|
-
import type {
|
|
5
|
-
export declare function createCacheTools(projectName: string):
|
|
4
|
+
import type { ToolSpec } from "../types.js";
|
|
5
|
+
export declare function createCacheTools(projectName: string): ToolSpec[];
|
package/dist/tools/cache.js
CHANGED
|
@@ -1,98 +1,79 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cache Management Tools
|
|
3
3
|
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { TOOL_ANNOTATIONS } from "../annotations.js";
|
|
4
6
|
export function createCacheTools(projectName) {
|
|
5
|
-
|
|
7
|
+
return [
|
|
6
8
|
{
|
|
7
9
|
name: "get_cache_stats",
|
|
8
10
|
description: `Get cache statistics for ${projectName}. Shows hit rates, cache levels, and memory usage.`,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
schema: z.object({
|
|
12
|
+
sessionId: z.string().optional().describe("Optional session ID for session-specific stats"),
|
|
13
|
+
}),
|
|
14
|
+
annotations: TOOL_ANNOTATIONS["get_cache_stats"],
|
|
15
|
+
handler: async (args, ctx) => {
|
|
16
|
+
const { sessionId } = args;
|
|
17
|
+
if (sessionId) {
|
|
18
|
+
const response = await ctx.api.get(`/api/cache/session/${sessionId}`);
|
|
19
|
+
const stats = response.data;
|
|
20
|
+
let result = `# 📊 Cache Stats for Session\n\n`;
|
|
21
|
+
result += `**Session ID**: ${sessionId}\n\n`;
|
|
22
|
+
result += `## Hit Rates\n`;
|
|
23
|
+
result += `- **Total Hits**: ${stats.hits}\n`;
|
|
24
|
+
result += `- **Misses**: ${stats.misses}\n`;
|
|
25
|
+
result += `- **Hit Rate**: ${(stats.hitRate * 100).toFixed(1)}%\n\n`;
|
|
26
|
+
result += `## Cache Level Distribution\n`;
|
|
27
|
+
result += `- **L1 (Session)**: ${stats.l1Hits} hits\n`;
|
|
28
|
+
result += `- **L2 (Project)**: ${stats.l2Hits} hits\n`;
|
|
29
|
+
result += `- **L3 (Global)**: ${stats.l3Hits} hits\n`;
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
const response = await ctx.api.get("/api/cache/analytics");
|
|
33
|
+
const analytics = response.data;
|
|
34
|
+
let result = `# 📊 Global Cache Analytics\n\n`;
|
|
35
|
+
result += `**Status**: ${analytics.enabled ? (analytics.connected ? "🟢 Connected" : "🟡 Disconnected") : "🔴 Disabled"}\n\n`;
|
|
36
|
+
if (analytics.connected) {
|
|
37
|
+
result += `## Keys\n`;
|
|
38
|
+
result += `- **Total**: ${analytics.totalKeys?.toLocaleString() || "N/A"}\n`;
|
|
39
|
+
result += `- **Embeddings**: ${analytics.embeddingKeys?.toLocaleString() || "N/A"}\n`;
|
|
40
|
+
result += `- **Search**: ${analytics.searchKeys?.toLocaleString() || "N/A"}\n`;
|
|
41
|
+
result += `- **Sessions**: ${analytics.sessionKeys?.toLocaleString() || "N/A"}\n\n`;
|
|
42
|
+
result += `## Memory\n`;
|
|
43
|
+
result += `- **Used**: ${analytics.memoryUsage || "N/A"}\n`;
|
|
44
|
+
}
|
|
45
|
+
return result;
|
|
17
46
|
},
|
|
18
47
|
},
|
|
19
48
|
{
|
|
20
49
|
name: "warm_cache",
|
|
21
50
|
description: `Warm the embedding cache for ${projectName}. Pre-loads frequently used embeddings for faster responses.`,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
recentQueries
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
51
|
+
schema: z.object({
|
|
52
|
+
sessionId: z.string().describe("Session ID to warm cache for"),
|
|
53
|
+
previousSessionId: z.string().optional().describe("Previous session to copy cache from (for session resumption)"),
|
|
54
|
+
recentQueries: z.array(z.string()).optional().describe("Recent queries to pre-warm in cache"),
|
|
55
|
+
}),
|
|
56
|
+
annotations: TOOL_ANNOTATIONS["warm_cache"],
|
|
57
|
+
handler: async (args, ctx) => {
|
|
58
|
+
const { sessionId, previousSessionId, recentQueries } = args;
|
|
59
|
+
const response = await ctx.api.post("/api/cache/warm", {
|
|
60
|
+
sessionId,
|
|
61
|
+
previousSessionId,
|
|
62
|
+
recentQueries,
|
|
63
|
+
});
|
|
64
|
+
const { warmedCount } = response.data;
|
|
65
|
+
let result = `🔥 **Cache Warmed**\n\n`;
|
|
66
|
+
result += `- **Session ID**: ${sessionId}\n`;
|
|
67
|
+
result += `- **Pre-loaded**: ${warmedCount} embeddings\n`;
|
|
68
|
+
if (previousSessionId) {
|
|
69
|
+
result += `- **Resumed from**: ${previousSessionId}\n`;
|
|
70
|
+
}
|
|
71
|
+
if (recentQueries && recentQueries.length > 0) {
|
|
72
|
+
result += `- **Queries warmed**: ${recentQueries.length}\n`;
|
|
73
|
+
}
|
|
74
|
+
result += `\nThe session cache is now primed for faster responses!`;
|
|
75
|
+
return result;
|
|
40
76
|
},
|
|
41
77
|
},
|
|
42
78
|
];
|
|
43
|
-
const handlers = {
|
|
44
|
-
get_cache_stats: async (args, ctx) => {
|
|
45
|
-
const { sessionId } = args;
|
|
46
|
-
if (sessionId) {
|
|
47
|
-
const response = await ctx.api.get(`/api/cache/session/${sessionId}`);
|
|
48
|
-
const stats = response.data;
|
|
49
|
-
let result = `# 📊 Cache Stats for Session\n\n`;
|
|
50
|
-
result += `**Session ID**: ${sessionId}\n\n`;
|
|
51
|
-
result += `## Hit Rates\n`;
|
|
52
|
-
result += `- **Total Hits**: ${stats.hits}\n`;
|
|
53
|
-
result += `- **Misses**: ${stats.misses}\n`;
|
|
54
|
-
result += `- **Hit Rate**: ${(stats.hitRate * 100).toFixed(1)}%\n\n`;
|
|
55
|
-
result += `## Cache Level Distribution\n`;
|
|
56
|
-
result += `- **L1 (Session)**: ${stats.l1Hits} hits\n`;
|
|
57
|
-
result += `- **L2 (Project)**: ${stats.l2Hits} hits\n`;
|
|
58
|
-
result += `- **L3 (Global)**: ${stats.l3Hits} hits\n`;
|
|
59
|
-
return result;
|
|
60
|
-
}
|
|
61
|
-
const response = await ctx.api.get("/api/cache/analytics");
|
|
62
|
-
const analytics = response.data;
|
|
63
|
-
let result = `# 📊 Global Cache Analytics\n\n`;
|
|
64
|
-
result += `**Status**: ${analytics.enabled ? (analytics.connected ? "🟢 Connected" : "🟡 Disconnected") : "🔴 Disabled"}\n\n`;
|
|
65
|
-
if (analytics.connected) {
|
|
66
|
-
result += `## Keys\n`;
|
|
67
|
-
result += `- **Total**: ${analytics.totalKeys?.toLocaleString() || "N/A"}\n`;
|
|
68
|
-
result += `- **Embeddings**: ${analytics.embeddingKeys?.toLocaleString() || "N/A"}\n`;
|
|
69
|
-
result += `- **Search**: ${analytics.searchKeys?.toLocaleString() || "N/A"}\n`;
|
|
70
|
-
result += `- **Sessions**: ${analytics.sessionKeys?.toLocaleString() || "N/A"}\n\n`;
|
|
71
|
-
result += `## Memory\n`;
|
|
72
|
-
result += `- **Used**: ${analytics.memoryUsage || "N/A"}\n`;
|
|
73
|
-
}
|
|
74
|
-
return result;
|
|
75
|
-
},
|
|
76
|
-
warm_cache: async (args, ctx) => {
|
|
77
|
-
const { sessionId, previousSessionId, recentQueries } = args;
|
|
78
|
-
const response = await ctx.api.post("/api/cache/warm", {
|
|
79
|
-
sessionId,
|
|
80
|
-
previousSessionId,
|
|
81
|
-
recentQueries,
|
|
82
|
-
});
|
|
83
|
-
const { warmedCount } = response.data;
|
|
84
|
-
let result = `🔥 **Cache Warmed**\n\n`;
|
|
85
|
-
result += `- **Session ID**: ${sessionId}\n`;
|
|
86
|
-
result += `- **Pre-loaded**: ${warmedCount} embeddings\n`;
|
|
87
|
-
if (previousSessionId) {
|
|
88
|
-
result += `- **Resumed from**: ${previousSessionId}\n`;
|
|
89
|
-
}
|
|
90
|
-
if (recentQueries && recentQueries.length > 0) {
|
|
91
|
-
result += `- **Queries warmed**: ${recentQueries.length}\n`;
|
|
92
|
-
}
|
|
93
|
-
result += `\nThe session cache is now primed for faster responses!`;
|
|
94
|
-
return result;
|
|
95
|
-
},
|
|
96
|
-
};
|
|
97
|
-
return { tools, handlers };
|
|
98
79
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Clustering tools module - code clustering, duplicate detection,
|
|
3
3
|
* similarity recommendations, and learning extraction.
|
|
4
4
|
*/
|
|
5
|
-
import type {
|
|
5
|
+
import type { ToolSpec } from "../types.js";
|
|
6
6
|
/**
|
|
7
7
|
* Create the clustering tools module with project-specific descriptions.
|
|
8
8
|
*/
|
|
9
|
-
export declare function createClusteringTools(projectName: string):
|
|
9
|
+
export declare function createClusteringTools(projectName: string): ToolSpec[];
|