wiggum-cli 0.2.6 → 0.3.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 +73 -60
- package/dist/ai/agents/codebase-analyst.d.ts +11 -0
- package/dist/ai/agents/codebase-analyst.d.ts.map +1 -0
- package/dist/ai/agents/codebase-analyst.js +150 -0
- package/dist/ai/agents/codebase-analyst.js.map +1 -0
- package/dist/ai/agents/index.d.ts +16 -0
- package/dist/ai/agents/index.d.ts.map +1 -0
- package/dist/ai/agents/index.js +85 -0
- package/dist/ai/agents/index.js.map +1 -0
- package/dist/ai/agents/orchestrator.d.ts +15 -0
- package/dist/ai/agents/orchestrator.d.ts.map +1 -0
- package/dist/ai/agents/orchestrator.js +187 -0
- package/dist/ai/agents/orchestrator.js.map +1 -0
- package/dist/ai/agents/stack-researcher.d.ts +15 -0
- package/dist/ai/agents/stack-researcher.d.ts.map +1 -0
- package/dist/ai/agents/stack-researcher.js +274 -0
- package/dist/ai/agents/stack-researcher.js.map +1 -0
- package/dist/ai/agents/types.d.ts +123 -0
- package/dist/ai/agents/types.d.ts.map +1 -0
- package/dist/ai/agents/types.js +6 -0
- package/dist/ai/agents/types.js.map +1 -0
- package/dist/ai/enhancer.d.ts +39 -1
- package/dist/ai/enhancer.d.ts.map +1 -1
- package/dist/ai/enhancer.js +54 -4
- package/dist/ai/enhancer.js.map +1 -1
- package/dist/ai/index.d.ts +4 -2
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +5 -1
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/prompts.d.ts +2 -2
- package/dist/ai/prompts.d.ts.map +1 -1
- package/dist/ai/prompts.js +66 -4
- package/dist/ai/prompts.js.map +1 -1
- package/dist/ai/providers.d.ts +28 -0
- package/dist/ai/providers.d.ts.map +1 -1
- package/dist/ai/providers.js +40 -0
- package/dist/ai/providers.js.map +1 -1
- package/dist/ai/tools/context7.d.ts +34 -0
- package/dist/ai/tools/context7.d.ts.map +1 -0
- package/dist/ai/tools/context7.js +135 -0
- package/dist/ai/tools/context7.js.map +1 -0
- package/dist/ai/tools/index.d.ts +7 -0
- package/dist/ai/tools/index.d.ts.map +1 -0
- package/dist/ai/tools/index.js +7 -0
- package/dist/ai/tools/index.js.map +1 -0
- package/dist/ai/tools/tavily.d.ts +27 -0
- package/dist/ai/tools/tavily.d.ts.map +1 -0
- package/dist/ai/tools/tavily.js +75 -0
- package/dist/ai/tools/tavily.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +14 -12
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts +2 -5
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +233 -154
- package/dist/commands/init.js.map +1 -1
- package/dist/utils/colors.d.ts.map +1 -1
- package/dist/utils/colors.js +10 -3
- package/dist/utils/colors.js.map +1 -1
- package/dist/utils/header.d.ts +1 -1
- package/dist/utils/header.js +3 -3
- package/dist/utils/header.js.map +1 -1
- package/package.json +3 -3
- package/src/ai/agents/codebase-analyst.ts +172 -0
- package/src/ai/agents/index.ts +147 -0
- package/src/ai/agents/orchestrator.ts +222 -0
- package/src/ai/agents/stack-researcher.ts +298 -0
- package/src/ai/agents/types.ts +132 -0
- package/src/ai/enhancer.ts +102 -4
- package/src/ai/index.ts +31 -1
- package/src/ai/prompts.ts +67 -4
- package/src/ai/providers.ts +48 -0
- package/src/ai/tools/context7.ts +167 -0
- package/src/ai/tools/index.ts +17 -0
- package/src/ai/tools/tavily.ts +101 -0
- package/src/cli.ts +14 -12
- package/src/commands/init.ts +278 -173
- package/src/utils/colors.ts +11 -3
- package/src/utils/header.ts +3 -3
package/src/ai/prompts.ts
CHANGED
|
@@ -100,6 +100,8 @@ Your goal is to thoroughly understand the codebase structure and produce actiona
|
|
|
100
100
|
3. Search for key patterns: entry points, routes, components, tests
|
|
101
101
|
4. Identify naming conventions by examining existing files
|
|
102
102
|
5. Look for existing documentation (.md files, README)
|
|
103
|
+
6. Determine the PROJECT TYPE (e.g., MCP server, REST API, React SPA, CLI tool, library)
|
|
104
|
+
7. Based on project type, include TECHNOLOGY-SPECIFIC testing/debugging tools
|
|
103
105
|
|
|
104
106
|
## Tools Available
|
|
105
107
|
You have these tools to explore the codebase:
|
|
@@ -110,6 +112,30 @@ You have these tools to explore the codebase:
|
|
|
110
112
|
|
|
111
113
|
${RIPGREP_SKILL}
|
|
112
114
|
|
|
115
|
+
## Technology-Specific Guidance
|
|
116
|
+
|
|
117
|
+
When you detect specific project types, include their specialized tools:
|
|
118
|
+
|
|
119
|
+
**MCP Server Projects** (detected by @modelcontextprotocol dependencies):
|
|
120
|
+
- Testing: "npx @anthropic-ai/mcp-inspector" for interactive debugging
|
|
121
|
+
- Practices: Follow MCP protocol spec, validate tool schemas, handle resources properly
|
|
122
|
+
|
|
123
|
+
**REST APIs** (Express, Fastify, Hono, etc.):
|
|
124
|
+
- Testing: API testing tools (supertest, httpie, curl examples)
|
|
125
|
+
- Debugging: Request logging, OpenAPI validation
|
|
126
|
+
|
|
127
|
+
**React/Next.js Projects**:
|
|
128
|
+
- Testing: React Testing Library patterns, Storybook for components
|
|
129
|
+
- Debugging: React DevTools, component isolation
|
|
130
|
+
|
|
131
|
+
**CLI Tools**:
|
|
132
|
+
- Testing: Integration tests with actual CLI invocation
|
|
133
|
+
- Debugging: --verbose flags, debug logging patterns
|
|
134
|
+
|
|
135
|
+
**Libraries/Packages**:
|
|
136
|
+
- Testing: Unit tests with high coverage, type checking
|
|
137
|
+
- Practices: Semantic versioning, changelog maintenance
|
|
138
|
+
|
|
113
139
|
## Output Requirements
|
|
114
140
|
After exploration, output valid JSON with:
|
|
115
141
|
- projectContext: entry points, key directories, naming conventions
|
|
@@ -117,8 +143,11 @@ After exploration, output valid JSON with:
|
|
|
117
143
|
- implementationGuidelines: short actionable rules (5-10 words each, max 7)
|
|
118
144
|
- mcpServers: essential and recommended servers
|
|
119
145
|
- possibleMissedTechnologies: technologies that might be in use
|
|
146
|
+
- technologyTools: testing, debugging, and validation tools specific to this project type
|
|
147
|
+
- technologyPractices: projectType, practices, antiPatterns, documentationHints
|
|
120
148
|
|
|
121
|
-
Be concise. Focus on WHAT TO DO, not what exists
|
|
149
|
+
Be concise. Focus on WHAT TO DO, not what exists.
|
|
150
|
+
Include SPECIFIC testing/debugging commands for the detected project type.`;
|
|
122
151
|
|
|
123
152
|
/**
|
|
124
153
|
* System prompt for codebase analysis (simple mode - no tools)
|
|
@@ -133,7 +162,16 @@ Rules:
|
|
|
133
162
|
- Focus on WHAT TO DO, not what exists
|
|
134
163
|
- Include specific file paths and commands
|
|
135
164
|
- Max 5-7 items per array
|
|
136
|
-
- No explanations, just actionable rules
|
|
165
|
+
- No explanations, just actionable rules
|
|
166
|
+
- CRITICAL: Include technology-specific testing and debugging tools
|
|
167
|
+
- Identify the PROJECT TYPE and provide stack-specific practices
|
|
168
|
+
|
|
169
|
+
Technology-specific tools to consider:
|
|
170
|
+
- MCP servers: "npx @anthropic-ai/mcp-inspector" for testing
|
|
171
|
+
- REST APIs: supertest, curl examples, OpenAPI validation
|
|
172
|
+
- React apps: React Testing Library, Storybook, DevTools
|
|
173
|
+
- CLI tools: integration tests, --verbose flags
|
|
174
|
+
- Libraries: high coverage unit tests, semantic versioning`;
|
|
137
175
|
|
|
138
176
|
/**
|
|
139
177
|
* Create the codebase analysis prompt
|
|
@@ -175,16 +213,41 @@ Respond with this JSON structure (keep values SHORT - 5-10 words max per item):
|
|
|
175
213
|
"essential": ["filesystem", "git"],
|
|
176
214
|
"recommended": ["docker", "postgres"]
|
|
177
215
|
},
|
|
178
|
-
"possibleMissedTechnologies": ["Redis", "WebSockets"]
|
|
216
|
+
"possibleMissedTechnologies": ["Redis", "WebSockets"],
|
|
217
|
+
"technologyTools": {
|
|
218
|
+
"testing": ["npx @anthropic-ai/mcp-inspector", "node test/test-*.js"],
|
|
219
|
+
"debugging": ["--verbose flag", "DEBUG=* env var"],
|
|
220
|
+
"validation": ["npx tsc --noEmit", "npm run lint"]
|
|
221
|
+
},
|
|
222
|
+
"technologyPractices": {
|
|
223
|
+
"projectType": "MCP Server",
|
|
224
|
+
"practices": [
|
|
225
|
+
"Validate tool input schemas with Zod",
|
|
226
|
+
"Return structured JSON from tools",
|
|
227
|
+
"Handle errors with proper MCP error codes"
|
|
228
|
+
],
|
|
229
|
+
"antiPatterns": [
|
|
230
|
+
"Don't expose internal errors to clients",
|
|
231
|
+
"Avoid blocking operations in tool handlers"
|
|
232
|
+
],
|
|
233
|
+
"documentationHints": [
|
|
234
|
+
"MCP spec: modelcontextprotocol.io/docs",
|
|
235
|
+
"Inspector: modelcontextprotocol.io/docs/tools/inspector"
|
|
236
|
+
]
|
|
237
|
+
}
|
|
179
238
|
}
|
|
180
239
|
|
|
181
|
-
|
|
240
|
+
CRITICAL:
|
|
241
|
+
- Identify the PROJECT TYPE first (MCP Server, REST API, React SPA, CLI, Library, etc.)
|
|
242
|
+
- Include technology-specific testing tools (e.g., MCP Inspector for MCP projects)
|
|
243
|
+
- Include technology-specific debugging approaches
|
|
182
244
|
- implementationGuidelines should be short rules (not analysis prompts)
|
|
183
245
|
- Include actual file paths from this project
|
|
184
246
|
- Infer commands from package.json patterns
|
|
185
247
|
- Max 5-7 items per array`;
|
|
186
248
|
}
|
|
187
249
|
|
|
250
|
+
|
|
188
251
|
/**
|
|
189
252
|
* Prompt for validating and improving scanner results
|
|
190
253
|
*/
|
package/src/ai/providers.ts
CHANGED
|
@@ -30,6 +30,16 @@ const API_KEY_ENV_VARS: Record<AIProvider, string> = {
|
|
|
30
30
|
openrouter: 'OPENROUTER_API_KEY',
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Environment variable names for optional services
|
|
35
|
+
*/
|
|
36
|
+
export const OPTIONAL_SERVICE_ENV_VARS = {
|
|
37
|
+
tavily: 'TAVILY_API_KEY',
|
|
38
|
+
context7: 'CONTEXT7_API_KEY',
|
|
39
|
+
} as const;
|
|
40
|
+
|
|
41
|
+
export type OptionalService = keyof typeof OPTIONAL_SERVICE_ENV_VARS;
|
|
42
|
+
|
|
33
43
|
/**
|
|
34
44
|
* Model option with label and value
|
|
35
45
|
*/
|
|
@@ -184,3 +194,41 @@ const REASONING_MODELS = [
|
|
|
184
194
|
export function isReasoningModel(modelId: string): boolean {
|
|
185
195
|
return REASONING_MODELS.some(m => modelId.startsWith(m));
|
|
186
196
|
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Check if Tavily API key is available
|
|
200
|
+
*/
|
|
201
|
+
export function hasTavilyKey(): boolean {
|
|
202
|
+
return !!process.env[OPTIONAL_SERVICE_ENV_VARS.tavily];
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Get the Tavily API key
|
|
207
|
+
*/
|
|
208
|
+
export function getTavilyKey(): string | undefined {
|
|
209
|
+
return process.env[OPTIONAL_SERVICE_ENV_VARS.tavily];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Check if Context7 API key is available
|
|
214
|
+
*/
|
|
215
|
+
export function hasContext7Key(): boolean {
|
|
216
|
+
return !!process.env[OPTIONAL_SERVICE_ENV_VARS.context7];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Get the Context7 API key
|
|
221
|
+
*/
|
|
222
|
+
export function getContext7Key(): string | undefined {
|
|
223
|
+
return process.env[OPTIONAL_SERVICE_ENV_VARS.context7];
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Get the status of all optional services
|
|
228
|
+
*/
|
|
229
|
+
export function getOptionalServicesStatus(): Record<OptionalService, boolean> {
|
|
230
|
+
return {
|
|
231
|
+
tavily: hasTavilyKey(),
|
|
232
|
+
context7: hasContext7Key(),
|
|
233
|
+
};
|
|
234
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context7 Documentation Lookup Tool
|
|
3
|
+
* Enables documentation lookup for libraries and frameworks
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { tool, zodSchema } from 'ai';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Context7 library info
|
|
11
|
+
*/
|
|
12
|
+
export interface Context7Library {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
codeSnippetCount?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Context7 documentation result
|
|
21
|
+
*/
|
|
22
|
+
export interface Context7DocResult {
|
|
23
|
+
title: string;
|
|
24
|
+
content: string;
|
|
25
|
+
codeExamples?: string[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Create a Context7 documentation lookup tool
|
|
30
|
+
* @param apiKey - Context7 API key
|
|
31
|
+
*/
|
|
32
|
+
export function createContext7Tool(apiKey: string) {
|
|
33
|
+
return tool({
|
|
34
|
+
description: `Look up documentation for libraries and frameworks.
|
|
35
|
+
Use this to find:
|
|
36
|
+
- API documentation for specific functions
|
|
37
|
+
- Usage examples and patterns
|
|
38
|
+
- Configuration options
|
|
39
|
+
- Best practices from official docs`,
|
|
40
|
+
inputSchema: zodSchema(z.object({
|
|
41
|
+
library: z.string().describe('Library name (e.g., "react", "express", "prisma")'),
|
|
42
|
+
query: z.string().describe('What you want to find in the documentation'),
|
|
43
|
+
})),
|
|
44
|
+
execute: async ({ library, query }) => {
|
|
45
|
+
try {
|
|
46
|
+
// First, resolve the library ID
|
|
47
|
+
const resolveResponse = await fetch('https://api.context7.com/v1/resolve-library-id', {
|
|
48
|
+
method: 'POST',
|
|
49
|
+
headers: {
|
|
50
|
+
'Content-Type': 'application/json',
|
|
51
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
52
|
+
},
|
|
53
|
+
body: JSON.stringify({
|
|
54
|
+
libraryName: library,
|
|
55
|
+
query: query,
|
|
56
|
+
}),
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (!resolveResponse.ok) {
|
|
60
|
+
// Try alternative endpoint structure
|
|
61
|
+
return await fallbackDocLookup(apiKey, library, query);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const resolveData = await resolveResponse.json() as { libraryId?: string; libraries?: Context7Library[] };
|
|
65
|
+
const libraryId = resolveData.libraryId || resolveData.libraries?.[0]?.id;
|
|
66
|
+
|
|
67
|
+
if (!libraryId) {
|
|
68
|
+
return `No documentation found for "${library}". Try a different library name.`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Query the documentation
|
|
72
|
+
const queryResponse = await fetch('https://api.context7.com/v1/query-docs', {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
headers: {
|
|
75
|
+
'Content-Type': 'application/json',
|
|
76
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
77
|
+
},
|
|
78
|
+
body: JSON.stringify({
|
|
79
|
+
libraryId,
|
|
80
|
+
query,
|
|
81
|
+
}),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
if (!queryResponse.ok) {
|
|
85
|
+
const errorText = await queryResponse.text();
|
|
86
|
+
return `Documentation lookup failed: ${queryResponse.status} - ${errorText}`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const docsData = await queryResponse.json() as { results?: Context7DocResult[] };
|
|
90
|
+
|
|
91
|
+
// Format results
|
|
92
|
+
const results: string[] = [];
|
|
93
|
+
results.push(`Documentation for ${library}:`);
|
|
94
|
+
results.push('');
|
|
95
|
+
|
|
96
|
+
if (docsData.results && docsData.results.length > 0) {
|
|
97
|
+
for (const doc of docsData.results.slice(0, 3)) {
|
|
98
|
+
results.push(`## ${doc.title}`);
|
|
99
|
+
results.push(doc.content.substring(0, 500));
|
|
100
|
+
if (doc.codeExamples && doc.codeExamples.length > 0) {
|
|
101
|
+
results.push('');
|
|
102
|
+
results.push('Example:');
|
|
103
|
+
results.push('```');
|
|
104
|
+
results.push(doc.codeExamples[0].substring(0, 300));
|
|
105
|
+
results.push('```');
|
|
106
|
+
}
|
|
107
|
+
results.push('');
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
results.push(`No specific documentation found for query: "${query}"`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return results.join('\n');
|
|
114
|
+
} catch (error) {
|
|
115
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
116
|
+
return `Documentation lookup error: ${errMsg}`;
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Fallback documentation lookup using alternative approach
|
|
124
|
+
*/
|
|
125
|
+
async function fallbackDocLookup(apiKey: string, library: string, query: string): Promise<string> {
|
|
126
|
+
try {
|
|
127
|
+
// Try a simpler query format
|
|
128
|
+
const response = await fetch(`https://api.context7.com/v1/search`, {
|
|
129
|
+
method: 'POST',
|
|
130
|
+
headers: {
|
|
131
|
+
'Content-Type': 'application/json',
|
|
132
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
133
|
+
},
|
|
134
|
+
body: JSON.stringify({
|
|
135
|
+
query: `${library} ${query}`,
|
|
136
|
+
limit: 5,
|
|
137
|
+
}),
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
if (!response.ok) {
|
|
141
|
+
return `Unable to find documentation for "${library}". The Context7 API may not support this library or the request format has changed.`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const data = await response.json() as { results?: Array<{ title: string; content: string }> };
|
|
145
|
+
|
|
146
|
+
if (data.results && data.results.length > 0) {
|
|
147
|
+
const results: string[] = [`Documentation for ${library}:`, ''];
|
|
148
|
+
for (const item of data.results.slice(0, 3)) {
|
|
149
|
+
results.push(`## ${item.title}`);
|
|
150
|
+
results.push(item.content.substring(0, 400));
|
|
151
|
+
results.push('');
|
|
152
|
+
}
|
|
153
|
+
return results.join('\n');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return `No documentation found for "${library}" with query "${query}"`;
|
|
157
|
+
} catch {
|
|
158
|
+
return `Documentation lookup for "${library}" failed. Please check your Context7 API key.`;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Check if Context7 can be used
|
|
164
|
+
*/
|
|
165
|
+
export function canUseContext7(apiKey?: string): boolean {
|
|
166
|
+
return !!apiKey && apiKey.length > 0;
|
|
167
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Tools Index
|
|
3
|
+
* Exports all tools for agent use
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
createTavilySearchTool,
|
|
8
|
+
canUseTavily,
|
|
9
|
+
type TavilySearchResult,
|
|
10
|
+
} from './tavily.js';
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
createContext7Tool,
|
|
14
|
+
canUseContext7,
|
|
15
|
+
type Context7Library,
|
|
16
|
+
type Context7DocResult,
|
|
17
|
+
} from './context7.js';
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tavily Web Search Tool
|
|
3
|
+
* Enables web search for current best practices and documentation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { tool, zodSchema } from 'ai';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Tavily search result
|
|
11
|
+
*/
|
|
12
|
+
export interface TavilySearchResult {
|
|
13
|
+
title: string;
|
|
14
|
+
url: string;
|
|
15
|
+
content: string;
|
|
16
|
+
score: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Tavily API response
|
|
21
|
+
*/
|
|
22
|
+
interface TavilyApiResponse {
|
|
23
|
+
results: TavilySearchResult[];
|
|
24
|
+
query: string;
|
|
25
|
+
answer?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Create a Tavily web search tool
|
|
30
|
+
* @param apiKey - Tavily API key
|
|
31
|
+
*/
|
|
32
|
+
export function createTavilySearchTool(apiKey: string) {
|
|
33
|
+
return tool({
|
|
34
|
+
description: `Search the web for current best practices, documentation, and recent information.
|
|
35
|
+
Use this to find:
|
|
36
|
+
- Current best practices for technologies
|
|
37
|
+
- Testing patterns and tools
|
|
38
|
+
- Library documentation and examples
|
|
39
|
+
- Recent updates and changes`,
|
|
40
|
+
inputSchema: zodSchema(z.object({
|
|
41
|
+
query: z.string().describe('Search query - be specific about what you want to find'),
|
|
42
|
+
searchDepth: z.enum(['basic', 'advanced']).optional()
|
|
43
|
+
.describe('Search depth - use "advanced" for comprehensive results'),
|
|
44
|
+
maxResults: z.number().min(1).max(10).optional()
|
|
45
|
+
.describe('Maximum number of results (default 5)'),
|
|
46
|
+
})),
|
|
47
|
+
execute: async ({ query, searchDepth, maxResults }) => {
|
|
48
|
+
try {
|
|
49
|
+
const response = await fetch('https://api.tavily.com/search', {
|
|
50
|
+
method: 'POST',
|
|
51
|
+
headers: {
|
|
52
|
+
'Content-Type': 'application/json',
|
|
53
|
+
},
|
|
54
|
+
body: JSON.stringify({
|
|
55
|
+
api_key: apiKey,
|
|
56
|
+
query,
|
|
57
|
+
search_depth: searchDepth || 'basic',
|
|
58
|
+
max_results: maxResults || 5,
|
|
59
|
+
include_answer: true,
|
|
60
|
+
include_raw_content: false,
|
|
61
|
+
}),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (!response.ok) {
|
|
65
|
+
const errorText = await response.text();
|
|
66
|
+
return `Search failed: ${response.status} - ${errorText}`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const data = await response.json() as TavilyApiResponse;
|
|
70
|
+
|
|
71
|
+
// Format results for the AI
|
|
72
|
+
const results: string[] = [];
|
|
73
|
+
|
|
74
|
+
if (data.answer) {
|
|
75
|
+
results.push(`Summary: ${data.answer}`);
|
|
76
|
+
results.push('');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
results.push('Sources:');
|
|
80
|
+
for (const result of data.results) {
|
|
81
|
+
results.push(`- ${result.title}`);
|
|
82
|
+
results.push(` URL: ${result.url}`);
|
|
83
|
+
results.push(` ${result.content.substring(0, 300)}...`);
|
|
84
|
+
results.push('');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return results.join('\n');
|
|
88
|
+
} catch (error) {
|
|
89
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
90
|
+
return `Search error: ${errMsg}`;
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Create a function that checks if Tavily search can be performed
|
|
98
|
+
*/
|
|
99
|
+
export function canUseTavily(apiKey?: string): boolean {
|
|
100
|
+
return !!apiKey && apiKey.length > 0;
|
|
101
|
+
}
|
package/src/cli.ts
CHANGED
|
@@ -27,8 +27,7 @@ export function createCli(): Command {
|
|
|
27
27
|
'after',
|
|
28
28
|
`
|
|
29
29
|
Examples:
|
|
30
|
-
$ ralph init Initialize Ralph
|
|
31
|
-
$ ralph init --ai Initialize with AI-enhanced analysis
|
|
30
|
+
$ ralph init Initialize Ralph with AI analysis
|
|
32
31
|
$ ralph new my-feature Create a new feature specification
|
|
33
32
|
$ ralph run my-feature Run the feature development loop
|
|
34
33
|
$ ralph monitor my-feature Monitor progress in real-time
|
|
@@ -43,10 +42,9 @@ Documentation:
|
|
|
43
42
|
.command('init')
|
|
44
43
|
.description(
|
|
45
44
|
'Initialize Ralph in the current project.\n\n' +
|
|
46
|
-
'
|
|
47
|
-
'
|
|
45
|
+
'Uses AI to analyze your codebase, detect the tech stack, and generate\n' +
|
|
46
|
+
'intelligent configuration files in .ralph/'
|
|
48
47
|
)
|
|
49
|
-
.option('--ai', 'Enable AI-enhanced analysis for deeper project insights')
|
|
50
48
|
.option(
|
|
51
49
|
'--provider <name>',
|
|
52
50
|
'AI provider to use (anthropic, openai, openrouter)',
|
|
@@ -57,15 +55,19 @@ Documentation:
|
|
|
57
55
|
'after',
|
|
58
56
|
`
|
|
59
57
|
Examples:
|
|
60
|
-
$ ralph init
|
|
61
|
-
$ ralph init --
|
|
62
|
-
$ ralph init --ai --provider openai With OpenAI provider
|
|
58
|
+
$ ralph init Initialize with AI analysis
|
|
59
|
+
$ ralph init --provider openai Use OpenAI provider
|
|
63
60
|
$ ralph init --yes Non-interactive mode
|
|
64
61
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
API Keys (BYOK - Bring Your Own Keys):
|
|
63
|
+
Required (one of):
|
|
64
|
+
ANTHROPIC_API_KEY For Anthropic (Claude) provider
|
|
65
|
+
OPENAI_API_KEY For OpenAI provider
|
|
66
|
+
OPENROUTER_API_KEY For OpenRouter provider
|
|
67
|
+
|
|
68
|
+
Optional (for enhanced research):
|
|
69
|
+
TAVILY_API_KEY Enable web search for best practices
|
|
70
|
+
CONTEXT7_API_KEY Enable documentation lookup
|
|
69
71
|
`
|
|
70
72
|
)
|
|
71
73
|
.action(async (options) => {
|