@identikey/coding-mcp 2.0.1
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 +134 -0
- package/build/common/apiClient.d.ts +14 -0
- package/build/common/apiClient.d.ts.map +1 -0
- package/build/common/apiClient.js +68 -0
- package/build/common/personaClient.d.ts +48 -0
- package/build/common/personaClient.d.ts.map +1 -0
- package/build/common/personaClient.js +101 -0
- package/build/common/promptBuilder.d.ts +10 -0
- package/build/common/promptBuilder.d.ts.map +1 -0
- package/build/common/promptBuilder.js +14 -0
- package/build/common/providerConfig.d.ts +23 -0
- package/build/common/providerConfig.d.ts.map +1 -0
- package/build/common/providerConfig.js +43 -0
- package/build/common/tokenFormatter.d.ts +12 -0
- package/build/common/tokenFormatter.d.ts.map +1 -0
- package/build/common/tokenFormatter.js +24 -0
- package/build/core/CommandDispatcher.d.ts +81 -0
- package/build/core/CommandDispatcher.d.ts.map +1 -0
- package/build/core/CommandDispatcher.js +242 -0
- package/build/core/ToolCommand.d.ts +188 -0
- package/build/core/ToolCommand.d.ts.map +1 -0
- package/build/core/ToolCommand.js +63 -0
- package/build/core/ToolRegistry.d.ts +80 -0
- package/build/core/ToolRegistry.d.ts.map +1 -0
- package/build/core/ToolRegistry.js +279 -0
- package/build/index.d.ts +8 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +329 -0
- package/build/infra/eventBus.d.ts +120 -0
- package/build/infra/eventBus.d.ts.map +1 -0
- package/build/infra/eventBus.js +138 -0
- package/build/personas/ada/index.d.ts +15 -0
- package/build/personas/ada/index.d.ts.map +1 -0
- package/build/personas/ada/index.js +121 -0
- package/build/personas/atlas/index.d.ts +13 -0
- package/build/personas/atlas/index.d.ts.map +1 -0
- package/build/personas/atlas/index.js +65 -0
- package/build/personas/charles/index.d.ts +18 -0
- package/build/personas/charles/index.d.ts.map +1 -0
- package/build/personas/charles/index.js +190 -0
- package/build/personas/hermes/index.d.ts +13 -0
- package/build/personas/hermes/index.d.ts.map +1 -0
- package/build/personas/hermes/index.js +61 -0
- package/build/personas/iris/index.d.ts +13 -0
- package/build/personas/iris/index.d.ts.map +1 -0
- package/build/personas/iris/index.js +61 -0
- package/build/personas/router.d.ts +18 -0
- package/build/personas/router.d.ts.map +1 -0
- package/build/personas/router.js +302 -0
- package/build/personas/sentinel/index.d.ts +13 -0
- package/build/personas/sentinel/index.d.ts.map +1 -0
- package/build/personas/sentinel/index.js +62 -0
- package/build/personas/types.d.ts +91 -0
- package/build/personas/types.d.ts.map +1 -0
- package/build/personas/types.js +60 -0
- package/build/personas/xavier/index.d.ts +14 -0
- package/build/personas/xavier/index.d.ts.map +1 -0
- package/build/personas/xavier/index.js +80 -0
- package/build/prompts/architectPrompts.d.ts +5 -0
- package/build/prompts/architectPrompts.d.ts.map +1 -0
- package/build/prompts/architectPrompts.js +58 -0
- package/build/prompts/codeadvicePrompts.d.ts +5 -0
- package/build/prompts/codeadvicePrompts.d.ts.map +1 -0
- package/build/prompts/codeadvicePrompts.js +13 -0
- package/build/prompts/researcherPrompts.d.ts +2 -0
- package/build/prompts/researcherPrompts.d.ts.map +1 -0
- package/build/prompts/researcherPrompts.js +39 -0
- package/build/tools/architect.d.ts +32 -0
- package/build/tools/architect.d.ts.map +1 -0
- package/build/tools/architect.js +75 -0
- package/build/tools/ask.d.ts +39 -0
- package/build/tools/ask.d.ts.map +1 -0
- package/build/tools/ask.js +139 -0
- package/build/tools/codeReview.d.ts +22 -0
- package/build/tools/codeReview.d.ts.map +1 -0
- package/build/tools/codeReview.js +35 -0
- package/build/tools/codeadvice.d.ts +29 -0
- package/build/tools/codeadvice.d.ts.map +1 -0
- package/build/tools/codeadvice.js +56 -0
- package/build/tools/discover.d.ts +24 -0
- package/build/tools/discover.d.ts.map +1 -0
- package/build/tools/discover.js +220 -0
- package/build/tools/persona.d.ts +48 -0
- package/build/tools/persona.d.ts.map +1 -0
- package/build/tools/persona.js +108 -0
- package/build/tools/researcher.d.ts +61 -0
- package/build/tools/researcher.d.ts.map +1 -0
- package/build/tools/researcher.js +346 -0
- package/build/tools/screenshot.d.ts +28 -0
- package/build/tools/screenshot.d.ts.map +1 -0
- package/build/tools/screenshot.js +46 -0
- package/package.json +56 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { classifyQuery, explainRouting } from "../personas/router.js";
|
|
3
|
+
import { PersonaRegistry } from "../personas/types.js";
|
|
4
|
+
import { callAIWithPersona } from "../common/personaClient.js";
|
|
5
|
+
/**
|
|
6
|
+
* Ask tool - Smart routing to the best persona based on query analysis
|
|
7
|
+
* Primary UX for natural language interaction with personas
|
|
8
|
+
*/
|
|
9
|
+
export const askToolName = "ask";
|
|
10
|
+
export const askToolDescription = "Ask a question naturally and get routed to the best expert persona automatically. You can also address a persona directly, e.g., 'ask xavier: <your question>' or 'charles: <your question>' to force that persona.";
|
|
11
|
+
export const AskToolSchema = z.object({
|
|
12
|
+
persona_id: z
|
|
13
|
+
.union([z.literal("auto"), z.string()])
|
|
14
|
+
.optional()
|
|
15
|
+
.default("auto")
|
|
16
|
+
.describe("Persona to use: 'auto' (default) routes to best expert, or a specific id like 'charles', 'ada', 'xavier'"),
|
|
17
|
+
query: z
|
|
18
|
+
.string()
|
|
19
|
+
.min(1, "Query is required")
|
|
20
|
+
.describe("Your question or request"),
|
|
21
|
+
context: z
|
|
22
|
+
.string()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("Additional code or context for analysis"),
|
|
25
|
+
hint: z
|
|
26
|
+
.string()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe("Optional hint for routing (e.g., 'architecture', 'security')"),
|
|
29
|
+
explain_routing: z
|
|
30
|
+
.boolean()
|
|
31
|
+
.optional()
|
|
32
|
+
.default(false)
|
|
33
|
+
.describe("Show which persona was selected and why"),
|
|
34
|
+
reasoning_effort: z
|
|
35
|
+
.union([z.literal("low"), z.literal("medium"), z.literal("high")])
|
|
36
|
+
.optional()
|
|
37
|
+
.describe("How thoroughly to think about the answer"),
|
|
38
|
+
provider: z
|
|
39
|
+
.union([z.literal("xai"), z.literal("openai")])
|
|
40
|
+
.optional()
|
|
41
|
+
.describe("Optional provider override; defaults to persona preference or heuristic"),
|
|
42
|
+
});
|
|
43
|
+
export async function runAskTool(args) {
|
|
44
|
+
const { persona_id = "auto", query, context = "", hint, explain_routing, reasoning_effort, provider, } = args;
|
|
45
|
+
// Natural-language persona addressing (e.g., "ask xavier:", "xavier:")
|
|
46
|
+
let cleanedQuery = query;
|
|
47
|
+
let nlPersonaId;
|
|
48
|
+
const aliases = {
|
|
49
|
+
charles: ["charles", "charlie"],
|
|
50
|
+
ada: ["ada"],
|
|
51
|
+
xavier: ["xavier", "x"],
|
|
52
|
+
};
|
|
53
|
+
const lowered = query.trim().toLowerCase();
|
|
54
|
+
for (const [pid, names] of Object.entries(aliases)) {
|
|
55
|
+
for (const name of names) {
|
|
56
|
+
const patterns = [
|
|
57
|
+
new RegExp(`^ask\\s+${name}[:,-]\\s*`, "i"),
|
|
58
|
+
new RegExp(`^ask\\s+${name}\\s+for\\s+`, "i"),
|
|
59
|
+
new RegExp(`^${name}[:,-]\\s*`, "i"),
|
|
60
|
+
new RegExp(`^${name}\\s+for\\s+`, "i"),
|
|
61
|
+
];
|
|
62
|
+
if (patterns.some((p) => p.test(lowered))) {
|
|
63
|
+
nlPersonaId = pid;
|
|
64
|
+
cleanedQuery = query
|
|
65
|
+
.replace(patterns[0], "")
|
|
66
|
+
.replace(patterns[1], "")
|
|
67
|
+
.replace(patterns[2], "")
|
|
68
|
+
.replace(patterns[3], "")
|
|
69
|
+
.trim();
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (nlPersonaId)
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
// Determine persona: explicit override or classification
|
|
77
|
+
let selectedPersonaId = nlPersonaId || (persona_id === "auto" ? undefined : persona_id);
|
|
78
|
+
let classification;
|
|
79
|
+
if (!selectedPersonaId) {
|
|
80
|
+
classification = classifyQuery(cleanedQuery, hint);
|
|
81
|
+
selectedPersonaId = classification.primaryPersona;
|
|
82
|
+
}
|
|
83
|
+
// Get the selected persona
|
|
84
|
+
const persona = PersonaRegistry.get(selectedPersonaId);
|
|
85
|
+
if (!persona) {
|
|
86
|
+
// Shouldn't happen but handle gracefully
|
|
87
|
+
return {
|
|
88
|
+
content: [
|
|
89
|
+
{
|
|
90
|
+
type: "text",
|
|
91
|
+
text: "No suitable expert found. Please use the 'discover' tool to see available personas.",
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
// Build response with optional routing explanation
|
|
98
|
+
let response = "";
|
|
99
|
+
if (explain_routing) {
|
|
100
|
+
const explanation = classification
|
|
101
|
+
? explainRouting(classification)
|
|
102
|
+
: `Using your selected expert: ${persona.name}.`;
|
|
103
|
+
response += `*${explanation}*\n\n---\n\n`;
|
|
104
|
+
}
|
|
105
|
+
// Simple system prompt for natural conversation
|
|
106
|
+
const systemPrompt = `You are having a natural conversation with the user, providing expert guidance based on your knowledge and experience.
|
|
107
|
+
|
|
108
|
+
Answer their question directly and helpfully while maintaining your personality.`;
|
|
109
|
+
// Call the persona
|
|
110
|
+
const personaResponse = await callAIWithPersona({
|
|
111
|
+
systemPrompt,
|
|
112
|
+
task: cleanedQuery,
|
|
113
|
+
code: context,
|
|
114
|
+
analysisType: "advice", // Default to advice for ask tool
|
|
115
|
+
reasoningEffort: (reasoning_effort || "medium"),
|
|
116
|
+
personaId: persona.id,
|
|
117
|
+
providerOverride: provider,
|
|
118
|
+
});
|
|
119
|
+
response += personaResponse;
|
|
120
|
+
return {
|
|
121
|
+
content: [
|
|
122
|
+
{
|
|
123
|
+
type: "text",
|
|
124
|
+
text: response,
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
return {
|
|
131
|
+
content: [
|
|
132
|
+
{
|
|
133
|
+
type: "text",
|
|
134
|
+
text: `Error consulting ${persona.name}: ${error.message || error}`,
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* CodeReview tool
|
|
4
|
+
* - Takes in a file path and runs "git diff main -- <filePath>"
|
|
5
|
+
* - Returns the diff along with instructions to review and fix issues
|
|
6
|
+
*/
|
|
7
|
+
export declare const codeReviewToolName = "code-review";
|
|
8
|
+
export declare const codeReviewToolDescription = "Run a git diff against main on a specified file and provide instructions to review/fix issues.";
|
|
9
|
+
export declare const CodeReviewToolSchema: z.ZodObject<{
|
|
10
|
+
folderPath: z.ZodString;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
folderPath: string;
|
|
13
|
+
}, {
|
|
14
|
+
folderPath: string;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function runCodeReviewTool(args: z.infer<typeof CodeReviewToolSchema>): Promise<{
|
|
17
|
+
content: {
|
|
18
|
+
type: string;
|
|
19
|
+
text: string;
|
|
20
|
+
}[];
|
|
21
|
+
}>;
|
|
22
|
+
//# sourceMappingURL=codeReview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codeReview.d.ts","sourceRoot":"","sources":["../../src/tools/codeReview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;GAIG;AAEH,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAChD,eAAO,MAAM,yBAAyB,mGAC4D,CAAC;AAEnG,eAAO,MAAM,oBAAoB;;;;;;EAE/B,CAAC;AAEH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC;;;;;GA2B3C"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
/**
|
|
4
|
+
* CodeReview tool
|
|
5
|
+
* - Takes in a file path and runs "git diff main -- <filePath>"
|
|
6
|
+
* - Returns the diff along with instructions to review and fix issues
|
|
7
|
+
*/
|
|
8
|
+
export const codeReviewToolName = "code-review";
|
|
9
|
+
export const codeReviewToolDescription = "Run a git diff against main on a specified file and provide instructions to review/fix issues.";
|
|
10
|
+
export const CodeReviewToolSchema = z.object({
|
|
11
|
+
folderPath: z.string().min(1, "A folder path is required."),
|
|
12
|
+
});
|
|
13
|
+
export async function runCodeReviewTool(args) {
|
|
14
|
+
const { folderPath } = args;
|
|
15
|
+
let diffOutput = "";
|
|
16
|
+
try {
|
|
17
|
+
diffOutput = execSync(`git -C "${folderPath}" diff`, {
|
|
18
|
+
encoding: "utf-8",
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
// If there's an error (e.g., no git repo, or the file doesn't exist), include it in the response.
|
|
23
|
+
diffOutput = `Error running git diff: ${error}`;
|
|
24
|
+
}
|
|
25
|
+
const instructions = "Review this diff for any obvious issues. Fix them if found, then finalize the changes.";
|
|
26
|
+
const message = `Git Diff Output:\n${diffOutput}\n\nInstructions:\n${instructions}`;
|
|
27
|
+
return {
|
|
28
|
+
content: [
|
|
29
|
+
{
|
|
30
|
+
type: "text",
|
|
31
|
+
text: message,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* CodeAdvice tool
|
|
4
|
+
* - Calls an AI model (xAI Grok or OpenAI GPT-5) to provide quick, focused coding guidance
|
|
5
|
+
* - Input: 'task' (description of the problem), 'code' (relevant code snippet)
|
|
6
|
+
* - Provides immediate, actionable advice for specific coding problems
|
|
7
|
+
*/
|
|
8
|
+
export declare const codeAdviceToolName = "code-advice";
|
|
9
|
+
export declare const codeAdviceToolDescription = "Provides quick, focused coding guidance and immediate solutions for specific problems.";
|
|
10
|
+
export declare const CodeAdviceToolSchema: z.ZodObject<{
|
|
11
|
+
task: z.ZodString;
|
|
12
|
+
code: z.ZodString;
|
|
13
|
+
reasoning_effort: z.ZodOptional<z.ZodEnum<["low", "medium", "high"]>>;
|
|
14
|
+
}, "strip", z.ZodTypeAny, {
|
|
15
|
+
code: string;
|
|
16
|
+
task: string;
|
|
17
|
+
reasoning_effort?: "low" | "medium" | "high" | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
code: string;
|
|
20
|
+
task: string;
|
|
21
|
+
reasoning_effort?: "low" | "medium" | "high" | undefined;
|
|
22
|
+
}>;
|
|
23
|
+
export declare function runCodeAdviceTool(args: z.infer<typeof CodeAdviceToolSchema>): Promise<{
|
|
24
|
+
content: {
|
|
25
|
+
type: string;
|
|
26
|
+
text: string;
|
|
27
|
+
}[];
|
|
28
|
+
}>;
|
|
29
|
+
//# sourceMappingURL=codeadvice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codeadvice.d.ts","sourceRoot":"","sources":["../../src/tools/codeadvice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB;;;;;GAKG;AAEH,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAChD,eAAO,MAAM,yBAAyB,2FACoD,CAAC;AAE3F,eAAO,MAAM,oBAAoB;;;;;;;;;;;;EAS/B,CAAC;AAEH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC;;;;;GAsC3C"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { callAIProvider } from "../common/apiClient.js";
|
|
3
|
+
import { chooseProvider, } from "../common/providerConfig.js";
|
|
4
|
+
import { CODEADVICE_SYSTEM_PROMPT } from "../prompts/codeadvicePrompts.js";
|
|
5
|
+
/**
|
|
6
|
+
* CodeAdvice tool
|
|
7
|
+
* - Calls an AI model (xAI Grok or OpenAI GPT-5) to provide quick, focused coding guidance
|
|
8
|
+
* - Input: 'task' (description of the problem), 'code' (relevant code snippet)
|
|
9
|
+
* - Provides immediate, actionable advice for specific coding problems
|
|
10
|
+
*/
|
|
11
|
+
export const codeAdviceToolName = "code-advice";
|
|
12
|
+
export const codeAdviceToolDescription = "Provides quick, focused coding guidance and immediate solutions for specific problems.";
|
|
13
|
+
export const CodeAdviceToolSchema = z.object({
|
|
14
|
+
task: z.string().min(1, "Task description is required."),
|
|
15
|
+
code: z.string().min(1, "Code string is required."),
|
|
16
|
+
reasoning_effort: z
|
|
17
|
+
.enum(["low", "medium", "high"])
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("How hard the model should think (low/medium/high). Defaults to medium for quick advice."),
|
|
20
|
+
});
|
|
21
|
+
export async function runCodeAdviceTool(args) {
|
|
22
|
+
const { task, code, reasoning_effort = "medium" } = args;
|
|
23
|
+
try {
|
|
24
|
+
const selectedProvider = chooseProvider({
|
|
25
|
+
analysisType: "advice",
|
|
26
|
+
reasoningEffort: reasoning_effort,
|
|
27
|
+
textHint: task,
|
|
28
|
+
});
|
|
29
|
+
const result = await callAIProvider({
|
|
30
|
+
systemPrompt: CODEADVICE_SYSTEM_PROMPT,
|
|
31
|
+
task,
|
|
32
|
+
code,
|
|
33
|
+
analysisType: "advice",
|
|
34
|
+
reasoningEffort: reasoning_effort,
|
|
35
|
+
provider: selectedProvider,
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: result,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return {
|
|
48
|
+
content: [
|
|
49
|
+
{
|
|
50
|
+
type: "text",
|
|
51
|
+
text: `CodeAdvice Error: ${error.message || error}`,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Discover tool - List and explore available personas
|
|
4
|
+
* Helps users understand what personas are available and their specialties
|
|
5
|
+
*/
|
|
6
|
+
export declare const discoverToolName = "discover";
|
|
7
|
+
export declare const discoverToolDescription = "Discover available expert personas and their specialties";
|
|
8
|
+
export declare const DiscoverToolSchema: z.ZodObject<{
|
|
9
|
+
category: z.ZodDefault<z.ZodOptional<z.ZodEnum<["architecture", "algorithms", "security", "frontend", "backend", "data", "all"]>>>;
|
|
10
|
+
verbose: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
category: "data" | "architecture" | "algorithms" | "frontend" | "backend" | "security" | "all";
|
|
13
|
+
verbose: boolean;
|
|
14
|
+
}, {
|
|
15
|
+
category?: "data" | "architecture" | "algorithms" | "frontend" | "backend" | "security" | "all" | undefined;
|
|
16
|
+
verbose?: boolean | undefined;
|
|
17
|
+
}>;
|
|
18
|
+
export declare function runDiscoverTool(args: z.infer<typeof DiscoverToolSchema>): Promise<{
|
|
19
|
+
content: {
|
|
20
|
+
type: string;
|
|
21
|
+
text: string;
|
|
22
|
+
}[];
|
|
23
|
+
}>;
|
|
24
|
+
//# sourceMappingURL=discover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/tools/discover.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;GAGG;AAEH,eAAO,MAAM,gBAAgB,aAAa,CAAC;AAC3C,eAAO,MAAM,uBAAuB,6DACwB,CAAC;AAE7D,eAAO,MAAM,kBAAkB;;;;;;;;;EAoB7B,CAAC;AAuIH,wBAAsB,eAAe,CACnC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC;;;;;GAsGzC"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { PersonaRegistry } from "../personas/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Discover tool - List and explore available personas
|
|
5
|
+
* Helps users understand what personas are available and their specialties
|
|
6
|
+
*/
|
|
7
|
+
export const discoverToolName = "discover";
|
|
8
|
+
export const discoverToolDescription = "Discover available expert personas and their specialties";
|
|
9
|
+
export const DiscoverToolSchema = z.object({
|
|
10
|
+
category: z
|
|
11
|
+
.enum([
|
|
12
|
+
"architecture",
|
|
13
|
+
"algorithms",
|
|
14
|
+
"security",
|
|
15
|
+
"frontend",
|
|
16
|
+
"backend",
|
|
17
|
+
"data",
|
|
18
|
+
"all",
|
|
19
|
+
])
|
|
20
|
+
.optional()
|
|
21
|
+
.default("all")
|
|
22
|
+
.describe("Filter personas by category"),
|
|
23
|
+
verbose: z
|
|
24
|
+
.boolean()
|
|
25
|
+
.optional()
|
|
26
|
+
.default(false)
|
|
27
|
+
.describe("Show detailed information including example queries"),
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Get example queries for each persona
|
|
31
|
+
*/
|
|
32
|
+
function getExampleQueries(personaId) {
|
|
33
|
+
const examples = {
|
|
34
|
+
charles: [
|
|
35
|
+
"How should I structure my microservices architecture?",
|
|
36
|
+
"What's the best pattern for this use case?",
|
|
37
|
+
"Review my system design for scalability",
|
|
38
|
+
"How do I reduce coupling between these modules?",
|
|
39
|
+
"What's causing this technical debt?",
|
|
40
|
+
],
|
|
41
|
+
ada: [
|
|
42
|
+
"How can I optimize this algorithm?",
|
|
43
|
+
"What's the time complexity of this function?",
|
|
44
|
+
"Which data structure should I use here?",
|
|
45
|
+
"How do I implement dynamic programming for this?",
|
|
46
|
+
"Profile this code for performance bottlenecks",
|
|
47
|
+
],
|
|
48
|
+
atlas: [
|
|
49
|
+
"Sketch an OpenAPI for this service and a zero-downtime migration plan",
|
|
50
|
+
"Design pagination and idempotency for this endpoint",
|
|
51
|
+
"Model these entities and relationships for scalability",
|
|
52
|
+
"Propose a contract test suite for backward compatibility",
|
|
53
|
+
"Eliminate N+1 and add caching without breaking consistency",
|
|
54
|
+
],
|
|
55
|
+
hermes: [
|
|
56
|
+
"Draft a GitHub Actions pipeline with build/test/deploy and canary",
|
|
57
|
+
"Add OpenTelemetry and SLOs for this service",
|
|
58
|
+
"Create Terraform for a minimal prod-ready stack",
|
|
59
|
+
"Propose a rollback plan and health gates for deploys",
|
|
60
|
+
"Harden the supply chain with SBOM and signing",
|
|
61
|
+
],
|
|
62
|
+
sentinel: [
|
|
63
|
+
"Threat model this API and propose cheapest effective controls",
|
|
64
|
+
"Design OAuth/OIDC login with short-lived tokens and rotation",
|
|
65
|
+
"Lock down secrets and encrypt data at rest and in transit",
|
|
66
|
+
"Add rate limits and CSP to prevent abuse",
|
|
67
|
+
"Write policy-as-code tests for authZ rules",
|
|
68
|
+
],
|
|
69
|
+
iris: [
|
|
70
|
+
"Design a minimal component API for this flow using a design system",
|
|
71
|
+
"Make this page meet WCAG 2.2 AA; list fixes",
|
|
72
|
+
"Improve Core Web Vitals with code-splitting and image optimization",
|
|
73
|
+
"Add Playwright and axe checks for this form",
|
|
74
|
+
"Propose DS tokens and a Storybook for reuse",
|
|
75
|
+
],
|
|
76
|
+
"security-expert": [
|
|
77
|
+
"Is this authentication flow secure?",
|
|
78
|
+
"How do I prevent SQL injection here?",
|
|
79
|
+
"Review this code for OWASP vulnerabilities",
|
|
80
|
+
"What's the best way to store sensitive data?",
|
|
81
|
+
"How should I implement rate limiting?",
|
|
82
|
+
],
|
|
83
|
+
"frontend-expert": [
|
|
84
|
+
"How do I structure this React component?",
|
|
85
|
+
"What's the best state management approach?",
|
|
86
|
+
"How do I make this UI more accessible?",
|
|
87
|
+
"Optimize this for mobile performance",
|
|
88
|
+
"Should I use CSS modules or styled-components?",
|
|
89
|
+
],
|
|
90
|
+
"backend-expert": [
|
|
91
|
+
"How should I design this REST API?",
|
|
92
|
+
"What's the best database schema for this?",
|
|
93
|
+
"How do I handle this at scale?",
|
|
94
|
+
"Should I use a message queue here?",
|
|
95
|
+
"How do I implement caching effectively?",
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
return (examples[personaId] || [
|
|
99
|
+
"Help me understand this code",
|
|
100
|
+
"What's the best approach for this problem?",
|
|
101
|
+
"Review this implementation",
|
|
102
|
+
]);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get category for a persona based on their expertise
|
|
106
|
+
*/
|
|
107
|
+
function getPersonaCategory(persona) {
|
|
108
|
+
const expertiseStr = persona.traits?.expertise?.join(" ").toLowerCase() || "";
|
|
109
|
+
if (expertiseStr.includes("architecture") ||
|
|
110
|
+
expertiseStr.includes("system design")) {
|
|
111
|
+
return "architecture";
|
|
112
|
+
}
|
|
113
|
+
if (expertiseStr.includes("algorithm") ||
|
|
114
|
+
expertiseStr.includes("optimization")) {
|
|
115
|
+
return "algorithms";
|
|
116
|
+
}
|
|
117
|
+
if (expertiseStr.includes("security") ||
|
|
118
|
+
expertiseStr.includes("authentication")) {
|
|
119
|
+
return "security";
|
|
120
|
+
}
|
|
121
|
+
if (expertiseStr.includes("frontend") ||
|
|
122
|
+
expertiseStr.includes("react") ||
|
|
123
|
+
expertiseStr.includes("ui")) {
|
|
124
|
+
return "frontend";
|
|
125
|
+
}
|
|
126
|
+
if (expertiseStr.includes("backend") ||
|
|
127
|
+
expertiseStr.includes("api") ||
|
|
128
|
+
expertiseStr.includes("database")) {
|
|
129
|
+
return "backend";
|
|
130
|
+
}
|
|
131
|
+
if (expertiseStr.includes("data") || expertiseStr.includes("analytics")) {
|
|
132
|
+
return "data";
|
|
133
|
+
}
|
|
134
|
+
return "general";
|
|
135
|
+
}
|
|
136
|
+
export async function runDiscoverTool(args) {
|
|
137
|
+
const { category, verbose } = args;
|
|
138
|
+
// Get all registered personas
|
|
139
|
+
const allPersonas = PersonaRegistry.list();
|
|
140
|
+
// Filter by category if specified
|
|
141
|
+
const personas = category === "all"
|
|
142
|
+
? allPersonas
|
|
143
|
+
: allPersonas.filter((p) => getPersonaCategory(p) === category);
|
|
144
|
+
if (personas.length === 0) {
|
|
145
|
+
return {
|
|
146
|
+
content: [
|
|
147
|
+
{
|
|
148
|
+
type: "text",
|
|
149
|
+
text: category === "all"
|
|
150
|
+
? "No personas are currently registered. Please check your configuration."
|
|
151
|
+
: `No personas found in category: ${category}`,
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// Build the response
|
|
157
|
+
let response = `# Available Expert Personas\n\n`;
|
|
158
|
+
if (category !== "all") {
|
|
159
|
+
response += `*Filtered by category: ${category}*\n\n`;
|
|
160
|
+
}
|
|
161
|
+
for (const persona of personas) {
|
|
162
|
+
const info = {
|
|
163
|
+
id: persona.id,
|
|
164
|
+
name: persona.name,
|
|
165
|
+
description: persona.description,
|
|
166
|
+
expertise: persona.traits.expertise || [],
|
|
167
|
+
};
|
|
168
|
+
response += `## ${info.name} (\`${info.id}\`)\n`;
|
|
169
|
+
response += `${info.description}\n\n`;
|
|
170
|
+
if (info.expertise.length > 0) {
|
|
171
|
+
response += `**Expertise:**\n`;
|
|
172
|
+
info.expertise.forEach((skill) => {
|
|
173
|
+
response += `- ${skill}\n`;
|
|
174
|
+
});
|
|
175
|
+
response += `\n`;
|
|
176
|
+
}
|
|
177
|
+
if (verbose) {
|
|
178
|
+
// Add personality info
|
|
179
|
+
if (persona.traits.personality) {
|
|
180
|
+
response += `**Personality:** ${persona.traits.personality}\n\n`;
|
|
181
|
+
}
|
|
182
|
+
// Add example queries
|
|
183
|
+
const examples = getExampleQueries(persona.id);
|
|
184
|
+
response += `**Example Queries:**\n`;
|
|
185
|
+
examples.forEach((example) => {
|
|
186
|
+
response += `- "${example}"\n`;
|
|
187
|
+
});
|
|
188
|
+
response += `\n`;
|
|
189
|
+
// Add communication style
|
|
190
|
+
const style = persona.traits.communicationStyle;
|
|
191
|
+
if (style) {
|
|
192
|
+
response += `**Communication Style:**\n`;
|
|
193
|
+
response += `- Formality: ${style.formality}\n`;
|
|
194
|
+
response += `- Humor: ${style.humor}\n`;
|
|
195
|
+
response += `- Tone: ${style.tone?.join(", ") || "balanced"}\n`;
|
|
196
|
+
response += `\n`;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
response += `---\n\n`;
|
|
200
|
+
}
|
|
201
|
+
// Add usage instructions
|
|
202
|
+
response += `## How to Use\n\n`;
|
|
203
|
+
response += `1. **Natural Language** (Recommended):\n`;
|
|
204
|
+
response += ` Use the \`ask\` tool and your question will be automatically routed to the best expert.\n`;
|
|
205
|
+
response += ` Example: \`ask "How should I structure my React app?"\`\n\n`;
|
|
206
|
+
response += `2. **Direct Access**:\n`;
|
|
207
|
+
response += ` Use the \`persona\` tool with a specific persona ID for precise control.\n`;
|
|
208
|
+
response += ` Example: \`persona "charles" "Review this architecture"\`\n\n`;
|
|
209
|
+
if (!verbose) {
|
|
210
|
+
response += `*Tip: Use \`verbose: true\` to see example queries and detailed persona information.*\n`;
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
content: [
|
|
214
|
+
{
|
|
215
|
+
type: "text",
|
|
216
|
+
text: response,
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
};
|
|
220
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Persona tool - Direct interaction with registered personas
|
|
4
|
+
* Allows calling any registered persona for advice, analysis, or conversation
|
|
5
|
+
*/
|
|
6
|
+
export declare const personaToolName = "persona";
|
|
7
|
+
export declare const personaToolDescription = "Chat with a specific persona for specialized advice and analysis with personality";
|
|
8
|
+
export declare const PersonaToolSchema: z.ZodObject<{
|
|
9
|
+
persona_id: z.ZodString;
|
|
10
|
+
query: z.ZodString;
|
|
11
|
+
context: z.ZodOptional<z.ZodString>;
|
|
12
|
+
analysis_type: z.ZodDefault<z.ZodOptional<z.ZodEnum<["comprehensive", "advice", "research", "review"]>>>;
|
|
13
|
+
reasoning_effort: z.ZodDefault<z.ZodOptional<z.ZodEnum<["low", "medium", "high"]>>>;
|
|
14
|
+
tone_style: z.ZodOptional<z.ZodEnum<["concise", "detailed", "humorous", "straight"]>>;
|
|
15
|
+
output_format: z.ZodOptional<z.ZodEnum<["tldr", "detailed", "dual"]>>;
|
|
16
|
+
audience_level: z.ZodOptional<z.ZodEnum<["beginner", "intermediate", "expert", "auto"]>>;
|
|
17
|
+
include_diagrams: z.ZodOptional<z.ZodBoolean>;
|
|
18
|
+
user_constraints: z.ZodOptional<z.ZodString>;
|
|
19
|
+
}, "strip", z.ZodTypeAny, {
|
|
20
|
+
reasoning_effort: "low" | "medium" | "high";
|
|
21
|
+
query: string;
|
|
22
|
+
persona_id: string;
|
|
23
|
+
analysis_type: "comprehensive" | "advice" | "research" | "review";
|
|
24
|
+
context?: string | undefined;
|
|
25
|
+
tone_style?: "concise" | "detailed" | "humorous" | "straight" | undefined;
|
|
26
|
+
output_format?: "detailed" | "tldr" | "dual" | undefined;
|
|
27
|
+
audience_level?: "beginner" | "intermediate" | "expert" | "auto" | undefined;
|
|
28
|
+
include_diagrams?: boolean | undefined;
|
|
29
|
+
user_constraints?: string | undefined;
|
|
30
|
+
}, {
|
|
31
|
+
query: string;
|
|
32
|
+
persona_id: string;
|
|
33
|
+
context?: string | undefined;
|
|
34
|
+
reasoning_effort?: "low" | "medium" | "high" | undefined;
|
|
35
|
+
analysis_type?: "comprehensive" | "advice" | "research" | "review" | undefined;
|
|
36
|
+
tone_style?: "concise" | "detailed" | "humorous" | "straight" | undefined;
|
|
37
|
+
output_format?: "detailed" | "tldr" | "dual" | undefined;
|
|
38
|
+
audience_level?: "beginner" | "intermediate" | "expert" | "auto" | undefined;
|
|
39
|
+
include_diagrams?: boolean | undefined;
|
|
40
|
+
user_constraints?: string | undefined;
|
|
41
|
+
}>;
|
|
42
|
+
export declare function runPersonaTool(args: z.infer<typeof PersonaToolSchema>): Promise<{
|
|
43
|
+
content: {
|
|
44
|
+
type: string;
|
|
45
|
+
text: string;
|
|
46
|
+
}[];
|
|
47
|
+
}>;
|
|
48
|
+
//# sourceMappingURL=persona.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persona.d.ts","sourceRoot":"","sources":["../../src/tools/persona.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;GAGG;AAEH,eAAO,MAAM,eAAe,YAAY,CAAC;AACzC,eAAO,MAAM,sBAAsB,sFACkD,CAAC;AAEtF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyD5B,CAAC;AAEH,wBAAsB,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC;;;;;GAuE3E"}
|