edsger 0.2.4 â 0.2.5
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.
|
@@ -5,9 +5,9 @@ export const runRefactor = async (options) => {
|
|
|
5
5
|
// Load and validate configuration
|
|
6
6
|
const config = validateConfiguration(options);
|
|
7
7
|
if (options.verbose) {
|
|
8
|
-
logInfo('Starting code refactoring for current directory...');
|
|
8
|
+
logInfo('Starting automatic code refactoring for current directory...');
|
|
9
9
|
}
|
|
10
|
-
logInfo('Analyzing
|
|
10
|
+
logInfo('Analyzing and refactoring code...');
|
|
11
11
|
try {
|
|
12
12
|
const refactorPrompt = createRefactorPrompt(config);
|
|
13
13
|
const systemPrompt = createSystemPrompt();
|
|
@@ -17,6 +17,7 @@ export const runRefactor = async (options) => {
|
|
|
17
17
|
options: {
|
|
18
18
|
appendSystemPrompt: systemPrompt,
|
|
19
19
|
model: config.claude.model || 'sonnet',
|
|
20
|
+
permissionMode: 'bypassPermissions',
|
|
20
21
|
},
|
|
21
22
|
})) {
|
|
22
23
|
// Stream the refactoring process
|
|
@@ -33,7 +34,7 @@ export const runRefactor = async (options) => {
|
|
|
33
34
|
if (message.type === 'result') {
|
|
34
35
|
hasCompleted = true;
|
|
35
36
|
if (message.subtype === 'success') {
|
|
36
|
-
logSuccess('
|
|
37
|
+
logSuccess('Code refactoring completed successfully');
|
|
37
38
|
process.exit(0);
|
|
38
39
|
}
|
|
39
40
|
else {
|
|
@@ -56,52 +57,67 @@ export const runRefactor = async (options) => {
|
|
|
56
57
|
}
|
|
57
58
|
};
|
|
58
59
|
const createSystemPrompt = () => {
|
|
59
|
-
return `You are an expert code refactoring assistant using Claude Code. Your task is to analyze code in the current directory
|
|
60
|
+
return `You are an expert code refactoring assistant using Claude Code. Your task is to analyze and AUTOMATICALLY REFACTOR code in the current directory to improve quality and maintainability.
|
|
60
61
|
|
|
61
62
|
IMPORTANT INSTRUCTIONS:
|
|
62
63
|
1. Use the Bash tool to explore the project structure (ls, find, etc.)
|
|
63
64
|
2. Use the Read tool to examine file contents
|
|
64
65
|
3. Use the Grep tool to search for patterns, code smells, or duplications
|
|
65
|
-
4. Use the Edit tool to apply refactoring changes
|
|
66
|
-
5.
|
|
66
|
+
4. Use the Edit tool to DIRECTLY apply refactoring changes
|
|
67
|
+
5. You have FULL PERMISSION to make refactoring changes without asking for confirmation
|
|
67
68
|
|
|
68
|
-
REFACTORING FOCUS AREAS:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
69
|
+
REFACTORING FOCUS AREAS (prioritized):
|
|
70
|
+
1. Code duplication and DRY violations (HIGHEST PRIORITY)
|
|
71
|
+
2. Complex functions that need simplification
|
|
72
|
+
3. Poor naming conventions
|
|
73
|
+
4. Missing type annotations (TypeScript)
|
|
74
|
+
5. Inefficient algorithms or data structures
|
|
75
|
+
6. Code organization and structure
|
|
76
|
+
7. Missing or inadequate error handling
|
|
77
|
+
8. Opportunities for better abstraction
|
|
78
|
+
9. Performance improvements
|
|
78
79
|
|
|
79
80
|
WORKFLOW:
|
|
80
81
|
1. First, explore the project structure to understand the codebase
|
|
81
82
|
2. Identify files that would benefit from refactoring
|
|
82
|
-
3. Analyze specific issues and patterns
|
|
83
|
-
4.
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
3. Analyze specific issues and patterns (focus on high-impact issues first)
|
|
84
|
+
4. For each issue found:
|
|
85
|
+
- Explain what you're refactoring and why
|
|
86
|
+
- Apply the refactoring using the Edit tool
|
|
87
|
+
- Verify the change is correct
|
|
88
|
+
5. Continue until all high-priority refactorings are complete or you run out of turns
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
SAFETY GUIDELINES:
|
|
91
|
+
- Start with safest refactorings (extract utilities, remove duplication)
|
|
92
|
+
- Preserve existing functionality - only improve structure/quality
|
|
93
|
+
- Focus on non-breaking changes
|
|
94
|
+
- Make atomic commits for each logical refactoring
|
|
95
|
+
|
|
96
|
+
IMPORTANT: You should DIRECTLY perform refactorings without asking for permission. The user has granted you full bypass authority to improve the code.`;
|
|
88
97
|
};
|
|
89
98
|
const createRefactorPrompt = (config) => {
|
|
90
|
-
return `Please analyze the code in the current directory
|
|
99
|
+
return `Please analyze and REFACTOR the code in the current directory. You have full permission to make improvements directly.
|
|
100
|
+
|
|
101
|
+
TASK: Automatically identify and fix code quality issues
|
|
91
102
|
|
|
92
103
|
Steps to follow:
|
|
93
104
|
1. Start by running "ls -la" to see the project structure
|
|
94
105
|
2. Identify key source files (focus on patterns: ${config.patterns.join(', ')})
|
|
95
106
|
3. Read and analyze relevant source files
|
|
96
|
-
4. Look for:
|
|
97
|
-
- Code duplication
|
|
107
|
+
4. Look for HIGH-PRIORITY issues:
|
|
108
|
+
- Code duplication (MOST IMPORTANT - fix first)
|
|
98
109
|
- Complex or long functions
|
|
99
110
|
- Poor naming
|
|
100
111
|
- Missing types or documentation
|
|
101
112
|
- Error handling issues
|
|
102
113
|
- Performance bottlenecks
|
|
103
|
-
5.
|
|
104
|
-
|
|
114
|
+
5. For EACH issue found, IMMEDIATELY apply the fix:
|
|
115
|
+
- Use the Edit tool to make the change
|
|
116
|
+
- Explain what you changed and why
|
|
117
|
+
- Move to the next issue
|
|
118
|
+
6. Continue refactoring until all high-priority issues are addressed
|
|
119
|
+
|
|
120
|
+
IMPORTANT: Do NOT ask for permission. You have full bypass authority to improve the code directly. Start refactoring immediately after analysis.
|
|
105
121
|
|
|
106
|
-
Start by exploring the current directory structure.`;
|
|
122
|
+
Start by exploring the current directory structure and begin refactoring.`;
|
|
107
123
|
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface FormatterSection {
|
|
2
|
+
title: string;
|
|
3
|
+
content?: string;
|
|
4
|
+
items?: Array<{
|
|
5
|
+
label: string;
|
|
6
|
+
value?: string | number;
|
|
7
|
+
type?: 'success' | 'error' | 'info';
|
|
8
|
+
}>;
|
|
9
|
+
list?: Array<{
|
|
10
|
+
text: string;
|
|
11
|
+
isHighlight?: boolean;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export interface FormatterOptions {
|
|
15
|
+
title: string;
|
|
16
|
+
icon: string;
|
|
17
|
+
sections: FormatterSection[];
|
|
18
|
+
verbose?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare const formatResults: (options: FormatterOptions) => void;
|
|
21
|
+
export declare const createStatusSection: (featureId: string, status: string) => FormatterSection;
|
|
22
|
+
export declare const createSummarySection: (summary?: string) => FormatterSection | null;
|
|
23
|
+
export declare const createContentPreview: (content: string, title: string, maxLines?: number) => FormatterSection;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export const formatResults = (options) => {
|
|
2
|
+
const { title, icon, sections } = options;
|
|
3
|
+
console.log('\n' + '='.repeat(60));
|
|
4
|
+
console.log(`${icon} ${title}`);
|
|
5
|
+
console.log('='.repeat(60));
|
|
6
|
+
sections.forEach((section) => {
|
|
7
|
+
if (section.title) {
|
|
8
|
+
console.log(`\n${section.title}`);
|
|
9
|
+
}
|
|
10
|
+
if (section.content) {
|
|
11
|
+
console.log(section.content);
|
|
12
|
+
}
|
|
13
|
+
if (section.items) {
|
|
14
|
+
section.items.forEach((item) => {
|
|
15
|
+
const statusIcon = getStatusIcon(item.type);
|
|
16
|
+
const value = item.value !== undefined ? `: ${item.value}` : '';
|
|
17
|
+
console.log(`${statusIcon} ${item.label}${value}`);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
if (section.list) {
|
|
21
|
+
section.list.forEach((listItem, index) => {
|
|
22
|
+
const prefix = listItem.isHighlight ? ' â' : ' ';
|
|
23
|
+
console.log(`${prefix}${index + 1}. ${listItem.text}`);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
console.log('\n' + '='.repeat(60));
|
|
28
|
+
};
|
|
29
|
+
export const createStatusSection = (featureId, status) => ({
|
|
30
|
+
title: '',
|
|
31
|
+
items: [
|
|
32
|
+
{ label: 'đ Feature ID', value: featureId },
|
|
33
|
+
{
|
|
34
|
+
label: 'đ Status',
|
|
35
|
+
value: status === 'success' || status === 'testing_passed' ? 'â
Success' : 'â Failed',
|
|
36
|
+
type: status === 'success' || status === 'testing_passed' ? 'success' : 'error'
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
});
|
|
40
|
+
export const createSummarySection = (summary) => {
|
|
41
|
+
if (!summary)
|
|
42
|
+
return null;
|
|
43
|
+
return {
|
|
44
|
+
title: 'đ Summary:',
|
|
45
|
+
content: summary
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export const createContentPreview = (content, title, maxLines = 10) => {
|
|
49
|
+
const lines = content.split('\n');
|
|
50
|
+
const previewLines = lines.slice(0, maxLines);
|
|
51
|
+
let displayContent = previewLines.join('\n');
|
|
52
|
+
if (lines.length > maxLines) {
|
|
53
|
+
displayContent += `\n... (${lines.length - maxLines} more lines)`;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
title: `${title}:`,
|
|
57
|
+
content: 'â'.repeat(40) + '\n' + displayContent + '\n' + 'â'.repeat(40)
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
function getStatusIcon(type) {
|
|
61
|
+
switch (type) {
|
|
62
|
+
case 'success': return 'â
';
|
|
63
|
+
case 'error': return 'â';
|
|
64
|
+
case 'info': return 'âšī¸';
|
|
65
|
+
default: return 'đ';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CliOptions } from '../../types/index.js';
|
|
2
|
+
export interface CommandOptions {
|
|
3
|
+
featureId: string;
|
|
4
|
+
mcpServerUrl: string;
|
|
5
|
+
mcpToken: string;
|
|
6
|
+
verbose?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface CommandResult {
|
|
9
|
+
status: 'success' | 'error' | 'testing_passed' | 'testing_failed' | 'pending';
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
}
|
|
12
|
+
export interface CommandConfig<TResult extends CommandResult> {
|
|
13
|
+
name: string;
|
|
14
|
+
getFeatureId: (options: CliOptions) => string | undefined;
|
|
15
|
+
checkRequirements: () => Promise<boolean>;
|
|
16
|
+
requirementsError: string;
|
|
17
|
+
startMessage: string;
|
|
18
|
+
successMessage: string;
|
|
19
|
+
errorMessage: string;
|
|
20
|
+
analyzer: (commandOptions: CommandOptions, config: any, ...args: any[]) => Promise<TResult>;
|
|
21
|
+
formatter: (result: TResult, verbose?: boolean) => void;
|
|
22
|
+
}
|
|
23
|
+
export declare function executeCommand<TResult extends CommandResult>(options: CliOptions, config: CommandConfig<TResult>): Promise<void>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { logInfo, logError, logSuccess } from '../../utils/logger.js';
|
|
2
|
+
import { validateCommandEnvironment, validateRequirements, } from './validation.js';
|
|
3
|
+
export async function executeCommand(options, config) {
|
|
4
|
+
await validateRequirements(config.checkRequirements, config.requirementsError);
|
|
5
|
+
const { config: edsgerConfig, mcpServerUrl, mcpToken } = validateCommandEnvironment(options);
|
|
6
|
+
const featureId = config.getFeatureId(options);
|
|
7
|
+
if (!featureId) {
|
|
8
|
+
throw new Error(`Feature ID is required for ${config.name}`);
|
|
9
|
+
}
|
|
10
|
+
if (options.verbose) {
|
|
11
|
+
logInfo(`${config.startMessage}: ${featureId}`);
|
|
12
|
+
}
|
|
13
|
+
logInfo(`Starting ${config.name}...`);
|
|
14
|
+
try {
|
|
15
|
+
const result = await config.analyzer({
|
|
16
|
+
featureId,
|
|
17
|
+
mcpServerUrl,
|
|
18
|
+
mcpToken,
|
|
19
|
+
verbose: options.verbose,
|
|
20
|
+
}, edsgerConfig);
|
|
21
|
+
config.formatter(result, options.verbose);
|
|
22
|
+
if (result.status === 'success' || result.status === 'testing_passed') {
|
|
23
|
+
logSuccess(config.successMessage);
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}
|
|
26
|
+
else if (result.status === 'error' || result.status === 'testing_failed') {
|
|
27
|
+
logError(config.errorMessage);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
logError(`${config.errorMessage}: ${result.status}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
logError(`${config.errorMessage}: ${error instanceof Error ? error.message : String(error)}`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|