wiggum-cli 0.2.6 → 0.3.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/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 +146 -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 +181 -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 +269 -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 +78 -36
- 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/dist/utils/json-repair.d.ts +14 -0
- package/dist/utils/json-repair.d.ts.map +1 -0
- package/dist/utils/json-repair.js +103 -0
- package/dist/utils/json-repair.js.map +1 -0
- package/dist/utils/tracing.d.ts +25 -0
- package/dist/utils/tracing.d.ts.map +1 -0
- package/dist/utils/tracing.js +64 -0
- package/dist/utils/tracing.js.map +1 -0
- package/package.json +5 -3
- package/src/ai/agents/codebase-analyst.ts +169 -0
- package/src/ai/agents/index.ts +147 -0
- package/src/ai/agents/orchestrator.ts +218 -0
- package/src/ai/agents/stack-researcher.ts +294 -0
- package/src/ai/agents/types.ts +132 -0
- package/src/ai/enhancer.ts +128 -38
- 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/utils/json-repair.ts +113 -0
- package/src/utils/tracing.ts +76 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Repair Utility
|
|
3
|
+
* Fixes common JSON syntax errors from AI responses
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Attempt to repair malformed JSON from AI responses
|
|
7
|
+
*/
|
|
8
|
+
export function repairJson(text) {
|
|
9
|
+
let json = text;
|
|
10
|
+
// Remove any leading/trailing whitespace
|
|
11
|
+
json = json.trim();
|
|
12
|
+
// Remove trailing commas before ] or }
|
|
13
|
+
json = json.replace(/,(\s*[\]}])/g, '$1');
|
|
14
|
+
// Fix missing commas between array elements or object properties
|
|
15
|
+
// Pattern: value followed by newline and another value without comma
|
|
16
|
+
json = json.replace(/("|\d|true|false|null|\]|\})(\s*\n\s*)("|\[|\{)/g, '$1,$2$3');
|
|
17
|
+
// Fix single quotes to double quotes (but not inside strings)
|
|
18
|
+
// This is a simplified approach - may not work for all cases
|
|
19
|
+
json = json.replace(/'/g, '"');
|
|
20
|
+
// Remove JavaScript-style comments
|
|
21
|
+
json = json.replace(/\/\/.*$/gm, '');
|
|
22
|
+
json = json.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
23
|
+
// Fix unquoted keys (simple cases)
|
|
24
|
+
json = json.replace(/(\{|\,)\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '$1"$2":');
|
|
25
|
+
// Remove any text before the first { or [
|
|
26
|
+
const firstBrace = json.indexOf('{');
|
|
27
|
+
const firstBracket = json.indexOf('[');
|
|
28
|
+
let startIndex = -1;
|
|
29
|
+
if (firstBrace !== -1 && firstBracket !== -1) {
|
|
30
|
+
startIndex = Math.min(firstBrace, firstBracket);
|
|
31
|
+
}
|
|
32
|
+
else if (firstBrace !== -1) {
|
|
33
|
+
startIndex = firstBrace;
|
|
34
|
+
}
|
|
35
|
+
else if (firstBracket !== -1) {
|
|
36
|
+
startIndex = firstBracket;
|
|
37
|
+
}
|
|
38
|
+
if (startIndex > 0) {
|
|
39
|
+
json = json.substring(startIndex);
|
|
40
|
+
}
|
|
41
|
+
// Remove any text after the last } or ]
|
|
42
|
+
const lastBrace = json.lastIndexOf('}');
|
|
43
|
+
const lastBracket = json.lastIndexOf(']');
|
|
44
|
+
let endIndex = -1;
|
|
45
|
+
if (lastBrace !== -1 && lastBracket !== -1) {
|
|
46
|
+
endIndex = Math.max(lastBrace, lastBracket);
|
|
47
|
+
}
|
|
48
|
+
else if (lastBrace !== -1) {
|
|
49
|
+
endIndex = lastBrace;
|
|
50
|
+
}
|
|
51
|
+
else if (lastBracket !== -1) {
|
|
52
|
+
endIndex = lastBracket;
|
|
53
|
+
}
|
|
54
|
+
if (endIndex !== -1 && endIndex < json.length - 1) {
|
|
55
|
+
json = json.substring(0, endIndex + 1);
|
|
56
|
+
}
|
|
57
|
+
return json;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Parse JSON with repair attempts
|
|
61
|
+
* Tries to fix common issues before parsing
|
|
62
|
+
*/
|
|
63
|
+
export function parseJsonSafe(text) {
|
|
64
|
+
// First try parsing as-is
|
|
65
|
+
try {
|
|
66
|
+
return JSON.parse(text);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// Try with repairs
|
|
70
|
+
}
|
|
71
|
+
// Try repairing the JSON
|
|
72
|
+
try {
|
|
73
|
+
const repaired = repairJson(text);
|
|
74
|
+
return JSON.parse(repaired);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Repair failed
|
|
78
|
+
}
|
|
79
|
+
// Last resort: try to extract JSON from markdown code blocks
|
|
80
|
+
const jsonMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
81
|
+
if (jsonMatch) {
|
|
82
|
+
try {
|
|
83
|
+
const repaired = repairJson(jsonMatch[1]);
|
|
84
|
+
return JSON.parse(repaired);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Still failed
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Try finding a JSON object
|
|
91
|
+
const objectMatch = text.match(/\{[\s\S]*\}/);
|
|
92
|
+
if (objectMatch) {
|
|
93
|
+
try {
|
|
94
|
+
const repaired = repairJson(objectMatch[0]);
|
|
95
|
+
return JSON.parse(repaired);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// Still failed
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=json-repair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-repair.js","sourceRoot":"","sources":["../../src/utils/json-repair.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Braintrust Tracing Utility
|
|
3
|
+
* Provides AI call tracing for debugging and analysis
|
|
4
|
+
*/
|
|
5
|
+
import * as ai from 'ai';
|
|
6
|
+
export { traced, currentSpan, wrapTraced } from 'braintrust';
|
|
7
|
+
export declare function initTracing(): void;
|
|
8
|
+
/**
|
|
9
|
+
* Check if tracing is enabled
|
|
10
|
+
*/
|
|
11
|
+
export declare function isTracingEnabled(): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Get wrapped AI SDK functions for automatic tracing
|
|
14
|
+
* Falls back to original functions if tracing not available
|
|
15
|
+
*/
|
|
16
|
+
export declare function getTracedAI(): typeof ai;
|
|
17
|
+
/**
|
|
18
|
+
* Wrap a function with tracing
|
|
19
|
+
* No-op if tracing is not enabled
|
|
20
|
+
*/
|
|
21
|
+
export declare function maybeTraced<T extends (...args: unknown[]) => unknown>(fn: T, options?: {
|
|
22
|
+
type?: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
}): T;
|
|
25
|
+
//# sourceMappingURL=tracing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../../src/utils/tracing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAGzB,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAO7D,wBAAgB,WAAW,IAAI,IAAI,CAkBlC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED;;;GAGG;AACH,wBAAgB,WAAW,cAS1B;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EACnE,EAAE,EAAE,CAAC,EACL,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7C,CAAC,CAUH"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Braintrust Tracing Utility
|
|
3
|
+
* Provides AI call tracing for debugging and analysis
|
|
4
|
+
*/
|
|
5
|
+
import { initLogger, wrapAISDK } from 'braintrust';
|
|
6
|
+
import * as ai from 'ai';
|
|
7
|
+
// Re-export traced utilities
|
|
8
|
+
export { traced, currentSpan, wrapTraced } from 'braintrust';
|
|
9
|
+
/**
|
|
10
|
+
* Initialize Braintrust logger if API key is available
|
|
11
|
+
*/
|
|
12
|
+
let loggerInitialized = false;
|
|
13
|
+
export function initTracing() {
|
|
14
|
+
if (loggerInitialized)
|
|
15
|
+
return;
|
|
16
|
+
const apiKey = process.env.BRAINTRUST_API_KEY;
|
|
17
|
+
if (!apiKey) {
|
|
18
|
+
// Silently skip tracing if no API key
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
initLogger({
|
|
23
|
+
apiKey,
|
|
24
|
+
projectName: process.env.BRAINTRUST_PROJECT_NAME || 'wiggum-cli',
|
|
25
|
+
});
|
|
26
|
+
loggerInitialized = true;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Silently fail if tracing can't be initialized
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Check if tracing is enabled
|
|
34
|
+
*/
|
|
35
|
+
export function isTracingEnabled() {
|
|
36
|
+
return !!process.env.BRAINTRUST_API_KEY;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get wrapped AI SDK functions for automatic tracing
|
|
40
|
+
* Falls back to original functions if tracing not available
|
|
41
|
+
*/
|
|
42
|
+
export function getTracedAI() {
|
|
43
|
+
initTracing();
|
|
44
|
+
if (isTracingEnabled()) {
|
|
45
|
+
return wrapAISDK(ai);
|
|
46
|
+
}
|
|
47
|
+
// Return original AI SDK functions if tracing not enabled
|
|
48
|
+
return ai;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Wrap a function with tracing
|
|
52
|
+
* No-op if tracing is not enabled
|
|
53
|
+
*/
|
|
54
|
+
export function maybeTraced(fn, options = {}) {
|
|
55
|
+
if (!isTracingEnabled()) {
|
|
56
|
+
return fn;
|
|
57
|
+
}
|
|
58
|
+
const { wrapTraced } = require('braintrust');
|
|
59
|
+
return wrapTraced(fn, {
|
|
60
|
+
type: options.type || 'function',
|
|
61
|
+
name: options.name || fn.name || 'anonymous',
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=tracing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.js","sourceRoot":"","sources":["../../src/utils/tracing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,6BAA6B;AAC7B,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7D;;GAEG;AACH,IAAI,iBAAiB,GAAG,KAAK,CAAC;AAE9B,MAAM,UAAU,WAAW;IACzB,IAAI,iBAAiB;QAAE,OAAO;IAE9B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,sCAAsC;QACtC,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,UAAU,CAAC;YACT,MAAM;YACN,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,YAAY;SACjE,CAAC,CAAC;QACH,iBAAiB,GAAG,IAAI,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,WAAW,EAAE,CAAC;IAEd,IAAI,gBAAgB,EAAE,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC;IAED,0DAA0D;IAC1D,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CACzB,EAAK,EACL,UAA4C,EAAE;IAE9C,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7C,OAAO,UAAU,CAAC,EAAE,EAAE;QACpB,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,UAAU;QAChC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,WAAW;KAC7C,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wiggum-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "AI-powered feature development loop CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"
|
|
8
|
+
"wiggum": "./bin/ralph.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "tsc && npm run copy-templates",
|
|
@@ -23,13 +23,15 @@
|
|
|
23
23
|
"code-generation",
|
|
24
24
|
"tech-stack-detection"
|
|
25
25
|
],
|
|
26
|
-
"author": "
|
|
26
|
+
"author": "Wiggum CLI Contributors",
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@ai-sdk/anthropic": "^3.0.15",
|
|
30
30
|
"@ai-sdk/openai": "^3.0.12",
|
|
31
|
+
"@braintrust/otel": "^0.2.0",
|
|
31
32
|
"@clack/prompts": "^0.7.0",
|
|
32
33
|
"ai": "^6.0.41",
|
|
34
|
+
"braintrust": "^2.0.2",
|
|
33
35
|
"cfonts": "^3.2.0",
|
|
34
36
|
"commander": "^12.1.0",
|
|
35
37
|
"picocolors": "^1.0.0",
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codebase Analyst Agent
|
|
3
|
+
* Explores the codebase to understand its structure and patterns
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { stepCountIs, type LanguageModel } from 'ai';
|
|
7
|
+
import type { CodebaseAnalysis, CodebaseAnalystInput } from './types.js';
|
|
8
|
+
import { createExplorationTools } from '../tools.js';
|
|
9
|
+
import { isReasoningModel } from '../providers.js';
|
|
10
|
+
import { logger } from '../../utils/logger.js';
|
|
11
|
+
import { parseJsonSafe } from '../../utils/json-repair.js';
|
|
12
|
+
import { getTracedAI } from '../../utils/tracing.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* System prompt for the Codebase Analyst agent
|
|
16
|
+
*/
|
|
17
|
+
const CODEBASE_ANALYST_SYSTEM_PROMPT = `You are a Codebase Analyst agent. Your job is to thoroughly explore a codebase and produce a structured analysis.
|
|
18
|
+
|
|
19
|
+
## Your Mission
|
|
20
|
+
Explore the codebase to understand:
|
|
21
|
+
1. Project structure and entry points
|
|
22
|
+
2. Key directories and their purposes
|
|
23
|
+
3. Naming conventions
|
|
24
|
+
4. Available commands (from package.json)
|
|
25
|
+
5. The primary project type
|
|
26
|
+
|
|
27
|
+
## Exploration Strategy
|
|
28
|
+
1. First, list the root directory to understand project structure
|
|
29
|
+
2. Read package.json to understand scripts and dependencies
|
|
30
|
+
3. Search for key patterns: entry points, routes, components
|
|
31
|
+
4. Identify the PROJECT TYPE:
|
|
32
|
+
- MCP Server: Has @modelcontextprotocol dependencies
|
|
33
|
+
- REST API: Express/Fastify/Hono with route handlers
|
|
34
|
+
- React SPA: React with components, no server-side rendering
|
|
35
|
+
- Next.js App: Next.js with app or pages directory
|
|
36
|
+
- CLI Tool: Has bin entry in package.json
|
|
37
|
+
- Library: Published package without app entry
|
|
38
|
+
|
|
39
|
+
## Tools Available
|
|
40
|
+
- searchCode: Search using ripgrep patterns
|
|
41
|
+
- readFile: Read file contents
|
|
42
|
+
- listDirectory: List directory structure
|
|
43
|
+
- getPackageInfo: Get package.json info
|
|
44
|
+
|
|
45
|
+
## Output Format
|
|
46
|
+
After exploration, output ONLY valid JSON with this exact structure:
|
|
47
|
+
{
|
|
48
|
+
"projectContext": {
|
|
49
|
+
"entryPoints": ["src/index.ts"],
|
|
50
|
+
"keyDirectories": {"src/routes": "API routes"},
|
|
51
|
+
"namingConventions": "camelCase files, PascalCase components",
|
|
52
|
+
"projectType": "MCP Server"
|
|
53
|
+
},
|
|
54
|
+
"commands": {
|
|
55
|
+
"test": "npm test",
|
|
56
|
+
"lint": "npm run lint",
|
|
57
|
+
"build": "npm run build",
|
|
58
|
+
"dev": "npm run dev"
|
|
59
|
+
},
|
|
60
|
+
"implementationGuidelines": [
|
|
61
|
+
"Run npm test after changes",
|
|
62
|
+
"Use Zod for validation"
|
|
63
|
+
],
|
|
64
|
+
"possibleMissedTechnologies": ["Redis"]
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
Keep each guideline to 5-10 words max. Max 7 guidelines.`;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Run the Codebase Analyst agent
|
|
71
|
+
*/
|
|
72
|
+
export async function runCodebaseAnalyst(
|
|
73
|
+
model: LanguageModel,
|
|
74
|
+
modelId: string,
|
|
75
|
+
input: CodebaseAnalystInput,
|
|
76
|
+
verbose: boolean = false
|
|
77
|
+
): Promise<CodebaseAnalysis | null> {
|
|
78
|
+
const tools = createExplorationTools(input.projectRoot);
|
|
79
|
+
|
|
80
|
+
const prompt = `Analyze this codebase and produce a structured analysis.
|
|
81
|
+
|
|
82
|
+
Project: ${input.projectRoot}
|
|
83
|
+
|
|
84
|
+
Start by exploring the directory structure and package.json, then produce your analysis as JSON.`;
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const { generateText } = getTracedAI();
|
|
88
|
+
|
|
89
|
+
const result = await generateText({
|
|
90
|
+
model,
|
|
91
|
+
system: CODEBASE_ANALYST_SYSTEM_PROMPT,
|
|
92
|
+
prompt,
|
|
93
|
+
tools,
|
|
94
|
+
stopWhen: stepCountIs(12),
|
|
95
|
+
maxOutputTokens: 3000,
|
|
96
|
+
...(isReasoningModel(modelId) ? {} : { temperature: 0.3 }),
|
|
97
|
+
experimental_telemetry: {
|
|
98
|
+
isEnabled: true,
|
|
99
|
+
metadata: { agent: 'codebase-analyst', projectRoot: input.projectRoot },
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Extract JSON from response
|
|
104
|
+
const analysis = parseCodebaseAnalysis(result.text, result.steps, verbose);
|
|
105
|
+
return analysis;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
if (verbose) {
|
|
108
|
+
logger.error(`Codebase Analyst error: ${error instanceof Error ? error.message : String(error)}`);
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Parse the codebase analysis from agent response
|
|
116
|
+
*/
|
|
117
|
+
function parseCodebaseAnalysis(
|
|
118
|
+
text: string,
|
|
119
|
+
steps: Array<{ text?: string }> | undefined,
|
|
120
|
+
verbose: boolean
|
|
121
|
+
): CodebaseAnalysis | null {
|
|
122
|
+
// Try to get text from the result or steps
|
|
123
|
+
let textToParse = text;
|
|
124
|
+
|
|
125
|
+
if (!textToParse || textToParse.trim() === '') {
|
|
126
|
+
// Look through steps for text content
|
|
127
|
+
const stepsList = steps || [];
|
|
128
|
+
for (let i = stepsList.length - 1; i >= 0; i--) {
|
|
129
|
+
const step = stepsList[i];
|
|
130
|
+
if (step.text && step.text.trim() !== '') {
|
|
131
|
+
textToParse = step.text;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!textToParse || textToParse.trim() === '') {
|
|
138
|
+
if (verbose) {
|
|
139
|
+
logger.warn('Codebase Analyst: No text output found');
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Use safe JSON parser with repair capabilities
|
|
145
|
+
const parsed = parseJsonSafe<CodebaseAnalysis>(textToParse);
|
|
146
|
+
|
|
147
|
+
if (!parsed) {
|
|
148
|
+
if (verbose) {
|
|
149
|
+
logger.warn('Codebase Analyst: Failed to parse JSON response');
|
|
150
|
+
logger.warn(`Response preview: ${textToParse.substring(0, 200)}...`);
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Validate required fields
|
|
156
|
+
if (!parsed.projectContext || !parsed.commands) {
|
|
157
|
+
if (verbose) {
|
|
158
|
+
logger.warn('Codebase Analyst: Missing required fields in response');
|
|
159
|
+
}
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Ensure projectType is set
|
|
164
|
+
if (!parsed.projectContext.projectType) {
|
|
165
|
+
parsed.projectContext.projectType = 'Unknown';
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return parsed;
|
|
169
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agents Index
|
|
3
|
+
* Exports all agent types and functions
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Types
|
|
7
|
+
export type {
|
|
8
|
+
CodebaseAnalysis,
|
|
9
|
+
StackResearch,
|
|
10
|
+
McpRecommendations,
|
|
11
|
+
MultiAgentAnalysis,
|
|
12
|
+
AgentCapabilities,
|
|
13
|
+
AgentOptions,
|
|
14
|
+
CodebaseAnalystInput,
|
|
15
|
+
StackResearcherInput,
|
|
16
|
+
OrchestratorInput,
|
|
17
|
+
} from './types.js';
|
|
18
|
+
|
|
19
|
+
// Agents
|
|
20
|
+
export { runCodebaseAnalyst } from './codebase-analyst.js';
|
|
21
|
+
export { runStackResearcher } from './stack-researcher.js';
|
|
22
|
+
export { runOrchestrator, mergeAgentResults } from './orchestrator.js';
|
|
23
|
+
|
|
24
|
+
// Re-export for convenience
|
|
25
|
+
import type { LanguageModel } from 'ai';
|
|
26
|
+
import type { ScanResult, DetectedStack } from '../../scanner/types.js';
|
|
27
|
+
import type {
|
|
28
|
+
MultiAgentAnalysis,
|
|
29
|
+
AgentCapabilities,
|
|
30
|
+
AgentOptions,
|
|
31
|
+
} from './types.js';
|
|
32
|
+
import { runCodebaseAnalyst } from './codebase-analyst.js';
|
|
33
|
+
import { runStackResearcher } from './stack-researcher.js';
|
|
34
|
+
import { runOrchestrator, mergeAgentResults } from './orchestrator.js';
|
|
35
|
+
import { logger } from '../../utils/logger.js';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Run the full multi-agent analysis pipeline
|
|
39
|
+
*/
|
|
40
|
+
export async function runMultiAgentAnalysis(
|
|
41
|
+
model: LanguageModel,
|
|
42
|
+
modelId: string,
|
|
43
|
+
scanResult: ScanResult,
|
|
44
|
+
options: AgentOptions = {}
|
|
45
|
+
): Promise<MultiAgentAnalysis | null> {
|
|
46
|
+
const { tavilyApiKey, context7ApiKey, verbose = false } = options;
|
|
47
|
+
|
|
48
|
+
// Determine capabilities
|
|
49
|
+
const capabilities: AgentCapabilities = {
|
|
50
|
+
hasTavily: !!tavilyApiKey,
|
|
51
|
+
hasContext7: !!context7ApiKey,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
if (verbose) {
|
|
55
|
+
logger.info('Starting multi-agent analysis...');
|
|
56
|
+
logger.info(`Capabilities: Tavily=${capabilities.hasTavily}, Context7=${capabilities.hasContext7}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Run Codebase Analyst
|
|
60
|
+
if (verbose) {
|
|
61
|
+
logger.info('Running Codebase Analyst...');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const codebaseAnalysis = await runCodebaseAnalyst(
|
|
65
|
+
model,
|
|
66
|
+
modelId,
|
|
67
|
+
{
|
|
68
|
+
scanResult,
|
|
69
|
+
projectRoot: scanResult.projectRoot,
|
|
70
|
+
},
|
|
71
|
+
verbose
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
if (!codebaseAnalysis) {
|
|
75
|
+
if (verbose) {
|
|
76
|
+
logger.warn('Codebase Analyst failed, using defaults');
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Run Stack Researcher
|
|
82
|
+
if (verbose) {
|
|
83
|
+
logger.info('Running Stack Researcher...');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const stackResearch = await runStackResearcher(
|
|
87
|
+
model,
|
|
88
|
+
modelId,
|
|
89
|
+
{
|
|
90
|
+
stack: scanResult.stack,
|
|
91
|
+
projectType: codebaseAnalysis.projectContext.projectType,
|
|
92
|
+
capabilities,
|
|
93
|
+
},
|
|
94
|
+
{ tavilyApiKey, context7ApiKey },
|
|
95
|
+
verbose
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
if (!stackResearch) {
|
|
99
|
+
if (verbose) {
|
|
100
|
+
logger.warn('Stack Researcher failed, using defaults');
|
|
101
|
+
}
|
|
102
|
+
// Continue with defaults - stack research is optional
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Run Orchestrator to merge results
|
|
106
|
+
if (verbose) {
|
|
107
|
+
logger.info('Running Orchestrator...');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const mcpServers = await runOrchestrator(
|
|
111
|
+
model,
|
|
112
|
+
modelId,
|
|
113
|
+
{
|
|
114
|
+
codebaseAnalysis,
|
|
115
|
+
stackResearch: stackResearch || getDefaultStackResearch(),
|
|
116
|
+
stack: scanResult.stack,
|
|
117
|
+
},
|
|
118
|
+
verbose
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
// Merge all results
|
|
122
|
+
const finalResult = mergeAgentResults(
|
|
123
|
+
codebaseAnalysis,
|
|
124
|
+
stackResearch || getDefaultStackResearch(),
|
|
125
|
+
mcpServers
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
if (verbose) {
|
|
129
|
+
logger.info('Multi-agent analysis complete');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return finalResult;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Get default stack research when agent fails
|
|
137
|
+
*/
|
|
138
|
+
function getDefaultStackResearch() {
|
|
139
|
+
return {
|
|
140
|
+
bestPractices: ['Follow project conventions'],
|
|
141
|
+
antiPatterns: ['Avoid skipping tests'],
|
|
142
|
+
testingTools: ['npm test'],
|
|
143
|
+
debuggingTools: ['console.log'],
|
|
144
|
+
documentationHints: ['Check official docs'],
|
|
145
|
+
researchMode: 'knowledge-only' as const,
|
|
146
|
+
};
|
|
147
|
+
}
|