wiggum-cli 0.2.1 → 0.2.3
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/ai/enhancer.d.ts +44 -35
- package/dist/ai/enhancer.d.ts.map +1 -1
- package/dist/ai/enhancer.js +135 -90
- package/dist/ai/enhancer.js.map +1 -1
- package/dist/ai/index.d.ts +3 -2
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +3 -1
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/prompts.d.ts +6 -2
- package/dist/ai/prompts.d.ts.map +1 -1
- package/dist/ai/prompts.js +74 -43
- package/dist/ai/prompts.js.map +1 -1
- package/dist/ai/tools.d.ts +47 -0
- package/dist/ai/tools.d.ts.map +1 -0
- package/dist/ai/tools.js +253 -0
- package/dist/ai/tools.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +20 -5
- package/dist/commands/init.js.map +1 -1
- package/dist/utils/colors.d.ts +48 -0
- package/dist/utils/colors.d.ts.map +1 -0
- package/dist/utils/colors.js +85 -0
- package/dist/utils/colors.js.map +1 -0
- package/dist/utils/header.d.ts +5 -1
- package/dist/utils/header.d.ts.map +1 -1
- package/dist/utils/header.js +19 -4
- package/dist/utils/header.js.map +1 -1
- package/package.json +3 -2
- package/src/ai/enhancer.ts +186 -138
- package/src/ai/index.ts +10 -5
- package/src/ai/prompts.ts +75 -43
- package/src/ai/tools.ts +278 -0
- package/src/commands/init.ts +25 -4
- package/src/utils/colors.ts +95 -0
- package/src/utils/header.ts +21 -4
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simpson Color Palette
|
|
3
|
+
* Custom ANSI color utilities for the CLI
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Simpson color palette hex values
|
|
7
|
+
*/
|
|
8
|
+
export declare const SIMPSON_COLORS: {
|
|
9
|
+
readonly blue: "#2f64d6";
|
|
10
|
+
readonly yellow: "#f8db27";
|
|
11
|
+
readonly brown: "#9c5b01";
|
|
12
|
+
readonly white: "#ffffff";
|
|
13
|
+
readonly pink: "#ff81c1";
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Simpson color functions for terminal output
|
|
17
|
+
*/
|
|
18
|
+
export declare const simpson: {
|
|
19
|
+
yellow: (text: string) => string;
|
|
20
|
+
blue: (text: string) => string;
|
|
21
|
+
brown: (text: string) => string;
|
|
22
|
+
white: (text: string) => string;
|
|
23
|
+
pink: (text: string) => string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Box drawing characters
|
|
27
|
+
*/
|
|
28
|
+
export declare const box: {
|
|
29
|
+
topLeft: string;
|
|
30
|
+
topRight: string;
|
|
31
|
+
bottomLeft: string;
|
|
32
|
+
bottomRight: string;
|
|
33
|
+
horizontal: string;
|
|
34
|
+
vertical: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Draw a horizontal line
|
|
38
|
+
*/
|
|
39
|
+
export declare function drawLine(width?: number): string;
|
|
40
|
+
/**
|
|
41
|
+
* Draw a box around text
|
|
42
|
+
*/
|
|
43
|
+
export declare function drawBox(text: string, padding?: number): string;
|
|
44
|
+
/**
|
|
45
|
+
* Section header with horizontal lines
|
|
46
|
+
*/
|
|
47
|
+
export declare function sectionHeader(title: string): string;
|
|
48
|
+
//# sourceMappingURL=colors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/utils/colors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc;;;;;;CAMjB,CAAC;AA8BX;;GAEG;AACH,eAAO,MAAM,OAAO;mBACH,MAAM,KAAG,MAAM;iBACjB,MAAM,KAAG,MAAM;kBACd,MAAM,KAAG,MAAM;kBACf,MAAM,KAAG,MAAM;iBAChB,MAAM,KAAG,MAAM;CAC7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,GAAG;;;;;;;CAOf,CAAC;AAEF;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,GAAE,MAAW,GAAG,MAAM,CAEnD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,MAAU,GAAG,MAAM,CASjE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGnD"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simpson Color Palette
|
|
3
|
+
* Custom ANSI color utilities for the CLI
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Simpson color palette hex values
|
|
7
|
+
*/
|
|
8
|
+
export const SIMPSON_COLORS = {
|
|
9
|
+
blue: '#2f64d6',
|
|
10
|
+
yellow: '#f8db27',
|
|
11
|
+
brown: '#9c5b01',
|
|
12
|
+
white: '#ffffff',
|
|
13
|
+
pink: '#ff81c1',
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Convert hex to RGB
|
|
17
|
+
*/
|
|
18
|
+
function hexToRgb(hex) {
|
|
19
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
20
|
+
if (!result) {
|
|
21
|
+
return { r: 255, g: 255, b: 255 };
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
r: parseInt(result[1], 16),
|
|
25
|
+
g: parseInt(result[2], 16),
|
|
26
|
+
b: parseInt(result[3], 16),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create ANSI escape code for foreground color from hex
|
|
31
|
+
*/
|
|
32
|
+
function fgHex(hex) {
|
|
33
|
+
const { r, g, b } = hexToRgb(hex);
|
|
34
|
+
return `\x1b[38;2;${r};${g};${b}m`;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Reset ANSI escape code
|
|
38
|
+
*/
|
|
39
|
+
const reset = '\x1b[0m';
|
|
40
|
+
/**
|
|
41
|
+
* Simpson color functions for terminal output
|
|
42
|
+
*/
|
|
43
|
+
export const simpson = {
|
|
44
|
+
yellow: (text) => `${fgHex(SIMPSON_COLORS.yellow)}${text}${reset}`,
|
|
45
|
+
blue: (text) => `${fgHex(SIMPSON_COLORS.blue)}${text}${reset}`,
|
|
46
|
+
brown: (text) => `${fgHex(SIMPSON_COLORS.brown)}${text}${reset}`,
|
|
47
|
+
white: (text) => `${fgHex(SIMPSON_COLORS.white)}${text}${reset}`,
|
|
48
|
+
pink: (text) => `${fgHex(SIMPSON_COLORS.pink)}${text}${reset}`,
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Box drawing characters
|
|
52
|
+
*/
|
|
53
|
+
export const box = {
|
|
54
|
+
topLeft: '┌',
|
|
55
|
+
topRight: '┐',
|
|
56
|
+
bottomLeft: '└',
|
|
57
|
+
bottomRight: '┘',
|
|
58
|
+
horizontal: '─',
|
|
59
|
+
vertical: '│',
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Draw a horizontal line
|
|
63
|
+
*/
|
|
64
|
+
export function drawLine(width = 50) {
|
|
65
|
+
return simpson.brown(box.horizontal.repeat(width));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Draw a box around text
|
|
69
|
+
*/
|
|
70
|
+
export function drawBox(text, padding = 1) {
|
|
71
|
+
const paddedText = ' '.repeat(padding) + text + ' '.repeat(padding);
|
|
72
|
+
const width = paddedText.length;
|
|
73
|
+
const top = simpson.brown(box.topLeft + box.horizontal.repeat(width) + box.topRight);
|
|
74
|
+
const middle = simpson.brown(box.vertical) + paddedText + simpson.brown(box.vertical);
|
|
75
|
+
const bottom = simpson.brown(box.bottomLeft + box.horizontal.repeat(width) + box.bottomRight);
|
|
76
|
+
return `${top}\n${middle}\n${bottom}`;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Section header with horizontal lines
|
|
80
|
+
*/
|
|
81
|
+
export function sectionHeader(title) {
|
|
82
|
+
const line = drawLine(50);
|
|
83
|
+
return `\n${line}\n${simpson.yellow(title)}\n${line}`;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=colors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/utils/colors.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/header.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Display the RALPH ASCII header
|
|
2
|
+
* Display the RALPH ASCII header with welcome box
|
|
3
3
|
*/
|
|
4
4
|
export declare function displayHeader(): void;
|
|
5
|
+
/**
|
|
6
|
+
* Display a minimal header (for subcommands)
|
|
7
|
+
*/
|
|
8
|
+
export declare function displayMinimalHeader(): void;
|
|
5
9
|
//# sourceMappingURL=header.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../src/utils/header.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../src/utils/header.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAgBpC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAI3C"}
|
package/dist/utils/header.js
CHANGED
|
@@ -1,15 +1,30 @@
|
|
|
1
1
|
import cfonts from 'cfonts';
|
|
2
|
+
import { simpson, drawBox, SIMPSON_COLORS } from './colors.js';
|
|
2
3
|
/**
|
|
3
|
-
* Display the RALPH ASCII header
|
|
4
|
+
* Display the RALPH ASCII header with welcome box
|
|
4
5
|
*/
|
|
5
6
|
export function displayHeader() {
|
|
6
|
-
|
|
7
|
+
// Welcome box like Claude Code
|
|
8
|
+
const welcomeText = simpson.pink('*') + ' Welcome to ' + simpson.yellow('Ralph') + '🍩';
|
|
9
|
+
console.log('');
|
|
10
|
+
console.log(drawBox(welcomeText, 2));
|
|
11
|
+
console.log('');
|
|
12
|
+
// ASCII art logo in Simpson yellow
|
|
13
|
+
cfonts.say('WIGGUM CLI', {
|
|
7
14
|
font: 'block',
|
|
8
|
-
colors: [
|
|
15
|
+
colors: [SIMPSON_COLORS.yellow],
|
|
9
16
|
letterSpacing: 1,
|
|
10
17
|
lineHeight: 1,
|
|
11
|
-
space:
|
|
18
|
+
space: false,
|
|
12
19
|
maxLength: 0,
|
|
13
20
|
});
|
|
14
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Display a minimal header (for subcommands)
|
|
24
|
+
*/
|
|
25
|
+
export function displayMinimalHeader() {
|
|
26
|
+
console.log('');
|
|
27
|
+
console.log(simpson.yellow('Ralph') + simpson.brown(' │ ') + 'AI-powered loop development');
|
|
28
|
+
console.log('');
|
|
29
|
+
}
|
|
15
30
|
//# sourceMappingURL=header.js.map
|
package/dist/utils/header.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"header.js","sourceRoot":"","sources":["../../src/utils/header.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"header.js","sourceRoot":"","sources":["../../src/utils/header.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE/D;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,+BAA+B;IAC/B,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IACxF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,mCAAmC;IACnC,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE;QACvB,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC;QAC/B,aAAa,EAAE,CAAC;QAChB,UAAU,EAAE,CAAC;QACb,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,CAAC;KACb,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,6BAA6B,CAAC,CAAC;IAC5F,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wiggum-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "AI-powered feature development loop CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"ai": "^6.0.41",
|
|
33
33
|
"cfonts": "^3.2.0",
|
|
34
34
|
"commander": "^12.1.0",
|
|
35
|
-
"picocolors": "^1.0.0"
|
|
35
|
+
"picocolors": "^1.0.0",
|
|
36
|
+
"zod": "^4.3.5"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@types/node": "^20.10.0",
|
package/src/ai/enhancer.ts
CHANGED
|
@@ -3,64 +3,61 @@
|
|
|
3
3
|
* Uses AI to analyze the codebase for deeper insights
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { generateText } from 'ai';
|
|
6
|
+
import { generateText, stepCountIs } from 'ai';
|
|
7
7
|
import type { ScanResult, DetectedStack, DetectionResult } from '../scanner/types.js';
|
|
8
8
|
import { getModel, type AIProvider, hasApiKey, getApiKeyEnvVar } from './providers.js';
|
|
9
|
-
import { SYSTEM_PROMPT, createAnalysisPrompt } from './prompts.js';
|
|
9
|
+
import { SYSTEM_PROMPT, SYSTEM_PROMPT_AGENTIC, createAnalysisPrompt } from './prompts.js';
|
|
10
|
+
import { createExplorationTools } from './tools.js';
|
|
10
11
|
import { logger } from '../utils/logger.js';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
*
|
|
14
|
+
* Project context from AI analysis - key structure information
|
|
14
15
|
*/
|
|
15
|
-
export interface
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
export interface ProjectContext {
|
|
17
|
+
/** Key entry point files */
|
|
18
|
+
entryPoints?: string[];
|
|
19
|
+
/** Important directories and their purposes */
|
|
20
|
+
keyDirectories?: Record<string, string>;
|
|
21
|
+
/** Naming conventions used in the project */
|
|
22
|
+
namingConventions?: string;
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
|
-
*
|
|
26
|
+
* Detected commands from package.json scripts or common patterns
|
|
23
27
|
*/
|
|
24
|
-
export interface
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
export interface DetectedCommands {
|
|
29
|
+
test?: string;
|
|
30
|
+
lint?: string;
|
|
31
|
+
typecheck?: string;
|
|
32
|
+
build?: string;
|
|
33
|
+
dev?: string;
|
|
34
|
+
format?: string;
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
/**
|
|
31
|
-
*
|
|
38
|
+
* MCP server recommendations (categorized)
|
|
32
39
|
*/
|
|
33
|
-
export interface
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
export interface McpRecommendations {
|
|
41
|
+
/** Essential MCP servers for this stack */
|
|
42
|
+
essential?: string[];
|
|
43
|
+
/** Recommended but optional MCP servers */
|
|
44
|
+
recommended?: string[];
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
/**
|
|
39
|
-
*
|
|
40
|
-
*/
|
|
41
|
-
export interface McpRecommendation {
|
|
42
|
-
name: string;
|
|
43
|
-
reason: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Additional detection suggestions
|
|
48
|
-
*/
|
|
49
|
-
export interface AdditionalDetections {
|
|
50
|
-
possibleMissed?: string[];
|
|
51
|
-
refinements?: string[];
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* AI analysis result
|
|
48
|
+
* AI analysis result - focused on actionable outputs
|
|
56
49
|
*/
|
|
57
50
|
export interface AIAnalysisResult {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
51
|
+
/** Project structure and context */
|
|
52
|
+
projectContext?: ProjectContext;
|
|
53
|
+
/** Detected commands from package.json */
|
|
54
|
+
commands?: DetectedCommands;
|
|
55
|
+
/** Short, actionable implementation guidelines */
|
|
56
|
+
implementationGuidelines?: string[];
|
|
57
|
+
/** MCP server recommendations */
|
|
58
|
+
mcpServers?: McpRecommendations;
|
|
59
|
+
/** Additional technologies that may have been missed */
|
|
60
|
+
possibleMissedTechnologies?: string[];
|
|
64
61
|
}
|
|
65
62
|
|
|
66
63
|
/**
|
|
@@ -80,6 +77,8 @@ export interface EnhancerOptions {
|
|
|
80
77
|
provider?: AIProvider;
|
|
81
78
|
model?: string;
|
|
82
79
|
verbose?: boolean;
|
|
80
|
+
/** Use agentic mode with tools for deeper codebase exploration */
|
|
81
|
+
agentic?: boolean;
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
/**
|
|
@@ -119,37 +118,24 @@ function applyEnhancements(
|
|
|
119
118
|
): DetectedStack {
|
|
120
119
|
const enhanced = { ...stack };
|
|
121
120
|
|
|
122
|
-
// Enhance
|
|
123
|
-
if (analysis.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
analysis.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
...enhanced.
|
|
134
|
-
|
|
121
|
+
// Enhance MCP recommendations from AI analysis
|
|
122
|
+
if (analysis.mcpServers) {
|
|
123
|
+
const aiRecommended = [
|
|
124
|
+
...(analysis.mcpServers.essential || []),
|
|
125
|
+
...(analysis.mcpServers.recommended || []),
|
|
126
|
+
];
|
|
127
|
+
|
|
128
|
+
if (aiRecommended.length > 0) {
|
|
129
|
+
enhanced.mcp = {
|
|
130
|
+
...enhanced.mcp,
|
|
131
|
+
recommended: [
|
|
132
|
+
...(enhanced.mcp?.recommended || []),
|
|
133
|
+
...aiRecommended.filter(r => !enhanced.mcp?.recommended?.includes(r)),
|
|
135
134
|
],
|
|
136
135
|
};
|
|
137
136
|
}
|
|
138
137
|
}
|
|
139
138
|
|
|
140
|
-
// Enhance MCP recommendations
|
|
141
|
-
if (analysis.recommendedMcpServers && analysis.recommendedMcpServers.length > 0) {
|
|
142
|
-
const aiRecommended = analysis.recommendedMcpServers.map(r => r.name);
|
|
143
|
-
|
|
144
|
-
enhanced.mcp = {
|
|
145
|
-
...enhanced.mcp,
|
|
146
|
-
recommended: [
|
|
147
|
-
...(enhanced.mcp?.recommended || []),
|
|
148
|
-
...aiRecommended.filter(r => !enhanced.mcp?.recommended?.includes(r)),
|
|
149
|
-
],
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
|
|
153
139
|
return enhanced;
|
|
154
140
|
}
|
|
155
141
|
|
|
@@ -161,11 +147,13 @@ export class AIEnhancer {
|
|
|
161
147
|
private provider: AIProvider;
|
|
162
148
|
private model?: string;
|
|
163
149
|
private verbose: boolean;
|
|
150
|
+
private agentic: boolean;
|
|
164
151
|
|
|
165
152
|
constructor(options: EnhancerOptions = {}) {
|
|
166
153
|
this.provider = options.provider || 'anthropic';
|
|
167
154
|
this.model = options.model;
|
|
168
155
|
this.verbose = options.verbose || false;
|
|
156
|
+
this.agentic = options.agentic || false;
|
|
169
157
|
}
|
|
170
158
|
|
|
171
159
|
/**
|
|
@@ -202,22 +190,20 @@ export class AIEnhancer {
|
|
|
202
190
|
|
|
203
191
|
if (this.verbose) {
|
|
204
192
|
logger.info(`Using AI provider: ${provider} (${modelId})`);
|
|
193
|
+
if (this.agentic) {
|
|
194
|
+
logger.info('Agentic mode enabled - AI will explore the codebase with tools');
|
|
195
|
+
}
|
|
205
196
|
}
|
|
206
197
|
|
|
207
|
-
|
|
208
|
-
const prompt = createAnalysisPrompt(scanResult);
|
|
209
|
-
|
|
210
|
-
// Call the AI model
|
|
211
|
-
const { text } = await generateText({
|
|
212
|
-
model,
|
|
213
|
-
system: SYSTEM_PROMPT,
|
|
214
|
-
prompt,
|
|
215
|
-
maxOutputTokens: 2000,
|
|
216
|
-
temperature: 0.3, // Lower temperature for more consistent output
|
|
217
|
-
});
|
|
198
|
+
let analysis: AIAnalysisResult | null;
|
|
218
199
|
|
|
219
|
-
|
|
220
|
-
|
|
200
|
+
if (this.agentic) {
|
|
201
|
+
// Agentic mode: use tools to explore codebase
|
|
202
|
+
analysis = await this.enhanceAgentic(model, scanResult);
|
|
203
|
+
} else {
|
|
204
|
+
// Simple mode: just analyze detected stack
|
|
205
|
+
analysis = await this.enhanceSimple(model, scanResult);
|
|
206
|
+
}
|
|
221
207
|
|
|
222
208
|
if (!analysis) {
|
|
223
209
|
return {
|
|
@@ -250,6 +236,80 @@ export class AIEnhancer {
|
|
|
250
236
|
};
|
|
251
237
|
}
|
|
252
238
|
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Simple enhancement mode - analyze detected stack without tools
|
|
242
|
+
*/
|
|
243
|
+
private async enhanceSimple(
|
|
244
|
+
model: ReturnType<typeof getModel>['model'],
|
|
245
|
+
scanResult: ScanResult
|
|
246
|
+
): Promise<AIAnalysisResult | null> {
|
|
247
|
+
const prompt = createAnalysisPrompt(scanResult);
|
|
248
|
+
|
|
249
|
+
const { text } = await generateText({
|
|
250
|
+
model,
|
|
251
|
+
system: SYSTEM_PROMPT,
|
|
252
|
+
prompt,
|
|
253
|
+
maxOutputTokens: 2000,
|
|
254
|
+
temperature: 0.3,
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
return parseAIResponse(text);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Agentic enhancement mode - use tools to explore codebase
|
|
262
|
+
*/
|
|
263
|
+
private async enhanceAgentic(
|
|
264
|
+
model: ReturnType<typeof getModel>['model'],
|
|
265
|
+
scanResult: ScanResult
|
|
266
|
+
): Promise<AIAnalysisResult | null> {
|
|
267
|
+
const tools = createExplorationTools(scanResult.projectRoot);
|
|
268
|
+
|
|
269
|
+
const prompt = `Analyze this codebase and produce configuration for AI-assisted development.
|
|
270
|
+
|
|
271
|
+
Project: ${scanResult.projectRoot}
|
|
272
|
+
|
|
273
|
+
Start by exploring the codebase structure, then produce your analysis.
|
|
274
|
+
When done exploring, output your final analysis as valid JSON matching this structure:
|
|
275
|
+
|
|
276
|
+
{
|
|
277
|
+
"projectContext": {
|
|
278
|
+
"entryPoints": ["src/index.ts"],
|
|
279
|
+
"keyDirectories": {"src/routes": "API routes"},
|
|
280
|
+
"namingConventions": "camelCase files, PascalCase components"
|
|
281
|
+
},
|
|
282
|
+
"commands": {
|
|
283
|
+
"test": "npm test",
|
|
284
|
+
"lint": "npm run lint",
|
|
285
|
+
"build": "npm run build",
|
|
286
|
+
"dev": "npm run dev"
|
|
287
|
+
},
|
|
288
|
+
"implementationGuidelines": [
|
|
289
|
+
"Run npm test after changes",
|
|
290
|
+
"Use Zod for validation"
|
|
291
|
+
],
|
|
292
|
+
"mcpServers": {
|
|
293
|
+
"essential": ["filesystem", "git"],
|
|
294
|
+
"recommended": ["docker"]
|
|
295
|
+
},
|
|
296
|
+
"possibleMissedTechnologies": ["Redis"]
|
|
297
|
+
}`;
|
|
298
|
+
|
|
299
|
+
// Use agentic loop - AI will call tools until it has enough info
|
|
300
|
+
// stopWhen: stepCountIs(10) allows up to 10 tool-calling steps
|
|
301
|
+
const { text } = await generateText({
|
|
302
|
+
model,
|
|
303
|
+
system: SYSTEM_PROMPT_AGENTIC,
|
|
304
|
+
prompt,
|
|
305
|
+
tools,
|
|
306
|
+
stopWhen: stepCountIs(10),
|
|
307
|
+
maxOutputTokens: 4000,
|
|
308
|
+
temperature: 0.3,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
return parseAIResponse(text);
|
|
312
|
+
}
|
|
253
313
|
}
|
|
254
314
|
|
|
255
315
|
/**
|
|
@@ -269,85 +329,73 @@ export async function enhanceWithAI(
|
|
|
269
329
|
export function formatAIAnalysis(analysis: AIAnalysisResult): string {
|
|
270
330
|
const lines: string[] = [];
|
|
271
331
|
|
|
272
|
-
|
|
273
|
-
|
|
332
|
+
// Project context
|
|
333
|
+
if (analysis.projectContext) {
|
|
334
|
+
const ctx = analysis.projectContext;
|
|
274
335
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
lines.push(` Confidence: ${analysis.frameworkInsights.confidence}`);
|
|
282
|
-
if (analysis.frameworkInsights.notes) {
|
|
283
|
-
lines.push(` Notes: ${analysis.frameworkInsights.notes}`);
|
|
336
|
+
if (ctx.entryPoints && ctx.entryPoints.length > 0) {
|
|
337
|
+
lines.push('Entry Points:');
|
|
338
|
+
for (const entry of ctx.entryPoints) {
|
|
339
|
+
lines.push(` ${entry}`);
|
|
340
|
+
}
|
|
341
|
+
lines.push('');
|
|
284
342
|
}
|
|
285
|
-
lines.push('');
|
|
286
|
-
}
|
|
287
343
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
lines.push(
|
|
344
|
+
if (ctx.keyDirectories && Object.keys(ctx.keyDirectories).length > 0) {
|
|
345
|
+
lines.push('Key Directories:');
|
|
346
|
+
for (const [dir, purpose] of Object.entries(ctx.keyDirectories)) {
|
|
347
|
+
lines.push(` ${dir} → ${purpose}`);
|
|
348
|
+
}
|
|
349
|
+
lines.push('');
|
|
294
350
|
}
|
|
295
|
-
lines.push('');
|
|
296
|
-
}
|
|
297
351
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
for (const convention of analysis.codingConventions) {
|
|
302
|
-
lines.push(` - ${convention.convention}`);
|
|
303
|
-
lines.push(` Suggestion: ${convention.suggestion}`);
|
|
352
|
+
if (ctx.namingConventions) {
|
|
353
|
+
lines.push(`Naming: ${ctx.namingConventions}`);
|
|
354
|
+
lines.push('');
|
|
304
355
|
}
|
|
305
|
-
lines.push('');
|
|
306
356
|
}
|
|
307
357
|
|
|
308
|
-
//
|
|
309
|
-
if (analysis.
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
358
|
+
// Detected commands
|
|
359
|
+
if (analysis.commands) {
|
|
360
|
+
const cmds = analysis.commands;
|
|
361
|
+
const cmdList = Object.entries(cmds).filter(([_, v]) => v);
|
|
362
|
+
|
|
363
|
+
if (cmdList.length > 0) {
|
|
364
|
+
lines.push('Commands:');
|
|
365
|
+
for (const [name, cmd] of cmdList) {
|
|
366
|
+
lines.push(` ${name}: ${cmd}`);
|
|
367
|
+
}
|
|
368
|
+
lines.push('');
|
|
314
369
|
}
|
|
315
|
-
lines.push('');
|
|
316
370
|
}
|
|
317
371
|
|
|
318
|
-
//
|
|
319
|
-
if (analysis.
|
|
320
|
-
lines.push('
|
|
321
|
-
for (const
|
|
322
|
-
lines.push(`
|
|
372
|
+
// Implementation guidelines (the most important part)
|
|
373
|
+
if (analysis.implementationGuidelines && analysis.implementationGuidelines.length > 0) {
|
|
374
|
+
lines.push('Implementation Guidelines:');
|
|
375
|
+
for (const guideline of analysis.implementationGuidelines) {
|
|
376
|
+
lines.push(` • ${guideline}`);
|
|
323
377
|
}
|
|
324
378
|
lines.push('');
|
|
325
379
|
}
|
|
326
380
|
|
|
327
|
-
//
|
|
328
|
-
if (analysis.
|
|
329
|
-
if (
|
|
330
|
-
analysis.
|
|
331
|
-
analysis.additionalDetections.possibleMissed.length > 0
|
|
332
|
-
) {
|
|
333
|
-
lines.push('Possibly Missed Technologies:');
|
|
334
|
-
for (const tech of analysis.additionalDetections.possibleMissed) {
|
|
335
|
-
lines.push(` - ${tech}`);
|
|
336
|
-
}
|
|
337
|
-
lines.push('');
|
|
381
|
+
// MCP servers
|
|
382
|
+
if (analysis.mcpServers) {
|
|
383
|
+
if (analysis.mcpServers.essential && analysis.mcpServers.essential.length > 0) {
|
|
384
|
+
lines.push(`MCP (essential): ${analysis.mcpServers.essential.join(', ')}`);
|
|
338
385
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
) {
|
|
344
|
-
lines.push('Detection Refinements:');
|
|
345
|
-
for (const refinement of analysis.additionalDetections.refinements) {
|
|
346
|
-
lines.push(` - ${refinement}`);
|
|
347
|
-
}
|
|
386
|
+
if (analysis.mcpServers.recommended && analysis.mcpServers.recommended.length > 0) {
|
|
387
|
+
lines.push(`MCP (optional): ${analysis.mcpServers.recommended.join(', ')}`);
|
|
388
|
+
}
|
|
389
|
+
if (analysis.mcpServers.essential?.length || analysis.mcpServers.recommended?.length) {
|
|
348
390
|
lines.push('');
|
|
349
391
|
}
|
|
350
392
|
}
|
|
351
393
|
|
|
394
|
+
// Possibly missed technologies (brief)
|
|
395
|
+
if (analysis.possibleMissedTechnologies && analysis.possibleMissedTechnologies.length > 0) {
|
|
396
|
+
lines.push(`May also use: ${analysis.possibleMissedTechnologies.join(', ')}`);
|
|
397
|
+
lines.push('');
|
|
398
|
+
}
|
|
399
|
+
|
|
352
400
|
return lines.join('\n');
|
|
353
401
|
}
|
package/src/ai/index.ts
CHANGED
|
@@ -17,18 +17,23 @@ export {
|
|
|
17
17
|
export {
|
|
18
18
|
formatStackForPrompt,
|
|
19
19
|
SYSTEM_PROMPT,
|
|
20
|
+
SYSTEM_PROMPT_AGENTIC,
|
|
20
21
|
createAnalysisPrompt,
|
|
21
22
|
createValidationPrompt,
|
|
22
23
|
createRecommendationsPrompt,
|
|
23
24
|
} from './prompts.js';
|
|
24
25
|
|
|
26
|
+
// Tools for agentic exploration
|
|
27
|
+
export {
|
|
28
|
+
createExplorationTools,
|
|
29
|
+
RIPGREP_SKILL,
|
|
30
|
+
} from './tools.js';
|
|
31
|
+
|
|
25
32
|
// AI enhancer
|
|
26
33
|
export {
|
|
27
|
-
type
|
|
28
|
-
type
|
|
29
|
-
type
|
|
30
|
-
type McpRecommendation,
|
|
31
|
-
type AdditionalDetections,
|
|
34
|
+
type ProjectContext,
|
|
35
|
+
type DetectedCommands,
|
|
36
|
+
type McpRecommendations,
|
|
32
37
|
type AIAnalysisResult,
|
|
33
38
|
type EnhancedScanResult,
|
|
34
39
|
type EnhancerOptions,
|