@nclamvn/vibecode-cli 2.0.0 → 2.2.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/.vibecode/learning/fixes.json +1 -0
- package/.vibecode/learning/preferences.json +1 -0
- package/README.md +310 -49
- package/SESSION_NOTES.md +154 -0
- package/bin/vibecode.js +235 -2
- package/package.json +5 -2
- package/src/agent/decomposition.js +476 -0
- package/src/agent/index.js +391 -0
- package/src/agent/memory.js +542 -0
- package/src/agent/orchestrator.js +917 -0
- package/src/agent/self-healing.js +516 -0
- package/src/commands/agent.js +349 -0
- package/src/commands/ask.js +230 -0
- package/src/commands/assist.js +413 -0
- package/src/commands/build.js +345 -4
- package/src/commands/debug.js +565 -0
- package/src/commands/docs.js +167 -0
- package/src/commands/git.js +1024 -0
- package/src/commands/go.js +635 -0
- package/src/commands/learn.js +294 -0
- package/src/commands/migrate.js +341 -0
- package/src/commands/plan.js +8 -2
- package/src/commands/refactor.js +205 -0
- package/src/commands/review.js +126 -1
- package/src/commands/security.js +229 -0
- package/src/commands/shell.js +486 -0
- package/src/commands/templates.js +397 -0
- package/src/commands/test.js +194 -0
- package/src/commands/undo.js +281 -0
- package/src/commands/watch.js +556 -0
- package/src/commands/wizard.js +322 -0
- package/src/config/constants.js +5 -1
- package/src/config/templates.js +146 -15
- package/src/core/backup.js +325 -0
- package/src/core/error-analyzer.js +237 -0
- package/src/core/fix-generator.js +195 -0
- package/src/core/iteration.js +226 -0
- package/src/core/learning.js +295 -0
- package/src/core/session.js +18 -2
- package/src/core/test-runner.js +281 -0
- package/src/debug/analyzer.js +329 -0
- package/src/debug/evidence.js +228 -0
- package/src/debug/fixer.js +348 -0
- package/src/debug/image-analyzer.js +304 -0
- package/src/debug/index.js +378 -0
- package/src/debug/verifier.js +346 -0
- package/src/index.js +102 -0
- package/src/providers/claude-code.js +12 -7
- package/src/templates/index.js +724 -0
- package/src/ui/__tests__/error-translator.test.js +390 -0
- package/src/ui/dashboard.js +364 -0
- package/src/ui/error-translator.js +775 -0
- package/src/utils/image.js +222 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
2
|
+
// VIBECODE DEBUG - Fix Verifier
|
|
3
|
+
// Verifies that fixes resolve the original error
|
|
4
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
5
|
+
|
|
6
|
+
import { exec } from 'child_process';
|
|
7
|
+
import { promisify } from 'util';
|
|
8
|
+
import fs from 'fs-extra';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
|
|
11
|
+
const execAsync = promisify(exec);
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Fix Verifier Class
|
|
15
|
+
* Re-runs failing commands/tests to verify fixes
|
|
16
|
+
*/
|
|
17
|
+
export class FixVerifier {
|
|
18
|
+
constructor(projectPath) {
|
|
19
|
+
this.projectPath = projectPath;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Verify a fix by re-running the original failing command
|
|
24
|
+
*/
|
|
25
|
+
async verify(originalError, fixAttempt) {
|
|
26
|
+
const verification = {
|
|
27
|
+
fixId: fixAttempt.id,
|
|
28
|
+
timestamp: new Date().toISOString(),
|
|
29
|
+
originalError: {
|
|
30
|
+
type: originalError.type,
|
|
31
|
+
category: originalError.category,
|
|
32
|
+
message: originalError.message
|
|
33
|
+
},
|
|
34
|
+
checks: [],
|
|
35
|
+
passed: false,
|
|
36
|
+
summary: ''
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Determine which checks to run based on category
|
|
40
|
+
const checksToRun = this.getChecksForCategory(originalError.category);
|
|
41
|
+
|
|
42
|
+
for (const check of checksToRun) {
|
|
43
|
+
const result = await this.runCheck(check);
|
|
44
|
+
verification.checks.push(result);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Analyze results
|
|
48
|
+
verification.passed = this.analyzeResults(verification.checks, originalError);
|
|
49
|
+
verification.summary = this.generateSummary(verification);
|
|
50
|
+
|
|
51
|
+
return verification;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Get appropriate checks for error category
|
|
56
|
+
*/
|
|
57
|
+
getChecksForCategory(category) {
|
|
58
|
+
const categoryChecks = {
|
|
59
|
+
SYNTAX: ['tsc', 'build'],
|
|
60
|
+
TYPE: ['tsc', 'build'],
|
|
61
|
+
REFERENCE: ['tsc', 'build'],
|
|
62
|
+
IMPORT: ['tsc', 'build'],
|
|
63
|
+
LINT: ['lint'],
|
|
64
|
+
TEST: ['test'],
|
|
65
|
+
NEXTJS: ['build'],
|
|
66
|
+
DATABASE: ['prisma', 'build'],
|
|
67
|
+
FILE: ['build'],
|
|
68
|
+
RUNTIME: ['build', 'test']
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return categoryChecks[category] || ['build'];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Run a specific verification check
|
|
76
|
+
*/
|
|
77
|
+
async runCheck(checkName) {
|
|
78
|
+
const result = {
|
|
79
|
+
name: checkName,
|
|
80
|
+
command: '',
|
|
81
|
+
passed: false,
|
|
82
|
+
output: '',
|
|
83
|
+
error: null,
|
|
84
|
+
duration: 0
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const commands = {
|
|
88
|
+
tsc: 'npx tsc --noEmit',
|
|
89
|
+
build: 'npm run build',
|
|
90
|
+
lint: 'npm run lint',
|
|
91
|
+
test: 'npm test',
|
|
92
|
+
prisma: 'npx prisma generate'
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
result.command = commands[checkName] || checkName;
|
|
96
|
+
|
|
97
|
+
// Check if command is available
|
|
98
|
+
if (checkName === 'lint' || checkName === 'test' || checkName === 'build') {
|
|
99
|
+
const pkgPath = path.join(this.projectPath, 'package.json');
|
|
100
|
+
if (await fs.pathExists(pkgPath)) {
|
|
101
|
+
const pkg = await fs.readJson(pkgPath);
|
|
102
|
+
const scriptName = checkName === 'build' ? 'build' : checkName;
|
|
103
|
+
if (!pkg.scripts?.[scriptName]) {
|
|
104
|
+
result.passed = true;
|
|
105
|
+
result.output = `Script "${scriptName}" not found, skipping`;
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const startTime = Date.now();
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const { stdout, stderr } = await execAsync(result.command, {
|
|
115
|
+
cwd: this.projectPath,
|
|
116
|
+
timeout: 120000,
|
|
117
|
+
maxBuffer: 10 * 1024 * 1024
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
result.passed = true;
|
|
121
|
+
result.output = stdout || stderr || 'Success';
|
|
122
|
+
result.duration = Date.now() - startTime;
|
|
123
|
+
} catch (error) {
|
|
124
|
+
result.passed = false;
|
|
125
|
+
result.error = error.message;
|
|
126
|
+
result.output = error.stderr || error.stdout || error.message;
|
|
127
|
+
result.duration = Date.now() - startTime;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Compare before and after outputs
|
|
135
|
+
*/
|
|
136
|
+
compareOutput(before, after) {
|
|
137
|
+
const comparison = {
|
|
138
|
+
errorResolved: false,
|
|
139
|
+
newErrors: [],
|
|
140
|
+
improvements: [],
|
|
141
|
+
regressions: []
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// Check if original error message is gone
|
|
145
|
+
const originalMessage = (before.message || '').toLowerCase();
|
|
146
|
+
const afterOutput = (after.output || '').toLowerCase();
|
|
147
|
+
|
|
148
|
+
if (originalMessage && !afterOutput.includes(originalMessage)) {
|
|
149
|
+
comparison.errorResolved = true;
|
|
150
|
+
comparison.improvements.push('Original error no longer appears');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Check for new errors
|
|
154
|
+
const errorPatterns = [
|
|
155
|
+
/error:/gi,
|
|
156
|
+
/failed/gi,
|
|
157
|
+
/exception/gi,
|
|
158
|
+
/cannot find/gi,
|
|
159
|
+
/undefined/gi
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
const beforeMatches = this.countPatternMatches(before.output || '', errorPatterns);
|
|
163
|
+
const afterMatches = this.countPatternMatches(after.output || '', errorPatterns);
|
|
164
|
+
|
|
165
|
+
if (afterMatches > beforeMatches) {
|
|
166
|
+
comparison.regressions.push(`Potential new errors detected (${afterMatches - beforeMatches} more error patterns)`);
|
|
167
|
+
} else if (afterMatches < beforeMatches) {
|
|
168
|
+
comparison.improvements.push(`Fewer error patterns (${beforeMatches - afterMatches} less)`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return comparison;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Count pattern matches in text
|
|
176
|
+
*/
|
|
177
|
+
countPatternMatches(text, patterns) {
|
|
178
|
+
let count = 0;
|
|
179
|
+
for (const pattern of patterns) {
|
|
180
|
+
const matches = text.match(pattern);
|
|
181
|
+
if (matches) count += matches.length;
|
|
182
|
+
}
|
|
183
|
+
return count;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Analyze check results to determine if fix was successful
|
|
188
|
+
*/
|
|
189
|
+
analyzeResults(checks, originalError) {
|
|
190
|
+
// All checks must pass
|
|
191
|
+
const allPassed = checks.every(c => c.passed);
|
|
192
|
+
|
|
193
|
+
if (!allPassed) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// For specific categories, verify the error type is resolved
|
|
198
|
+
const relevantCheck = checks.find(c => {
|
|
199
|
+
switch (originalError.category) {
|
|
200
|
+
case 'SYNTAX':
|
|
201
|
+
case 'TYPE':
|
|
202
|
+
case 'REFERENCE':
|
|
203
|
+
case 'IMPORT':
|
|
204
|
+
return c.name === 'tsc' || c.name === 'build';
|
|
205
|
+
case 'LINT':
|
|
206
|
+
return c.name === 'lint';
|
|
207
|
+
case 'TEST':
|
|
208
|
+
return c.name === 'test';
|
|
209
|
+
default:
|
|
210
|
+
return c.name === 'build';
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
if (relevantCheck && !relevantCheck.passed) {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Generate verification summary
|
|
223
|
+
*/
|
|
224
|
+
generateSummary(verification) {
|
|
225
|
+
const passed = verification.checks.filter(c => c.passed);
|
|
226
|
+
const failed = verification.checks.filter(c => !c.passed);
|
|
227
|
+
|
|
228
|
+
if (verification.passed) {
|
|
229
|
+
return `✅ Fix verified! All ${passed.length} checks passed.`;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const failedNames = failed.map(c => c.name).join(', ');
|
|
233
|
+
return `❌ Fix verification failed. Failed checks: ${failedNames}`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Generate a detailed verification report
|
|
238
|
+
*/
|
|
239
|
+
generateReport(verification) {
|
|
240
|
+
const lines = [
|
|
241
|
+
'# Fix Verification Report',
|
|
242
|
+
'',
|
|
243
|
+
`**Fix ID**: ${verification.fixId}`,
|
|
244
|
+
`**Timestamp**: ${verification.timestamp}`,
|
|
245
|
+
`**Status**: ${verification.passed ? '✅ PASSED' : '❌ FAILED'}`,
|
|
246
|
+
'',
|
|
247
|
+
'## Original Error',
|
|
248
|
+
`- Type: ${verification.originalError.type}`,
|
|
249
|
+
`- Category: ${verification.originalError.category}`,
|
|
250
|
+
`- Message: ${verification.originalError.message || 'N/A'}`,
|
|
251
|
+
'',
|
|
252
|
+
'## Verification Checks',
|
|
253
|
+
''
|
|
254
|
+
];
|
|
255
|
+
|
|
256
|
+
for (const check of verification.checks) {
|
|
257
|
+
lines.push(`### ${check.name}`);
|
|
258
|
+
lines.push(`- Command: \`${check.command}\``);
|
|
259
|
+
lines.push(`- Status: ${check.passed ? '✅ Passed' : '❌ Failed'}`);
|
|
260
|
+
lines.push(`- Duration: ${check.duration}ms`);
|
|
261
|
+
|
|
262
|
+
if (check.error) {
|
|
263
|
+
lines.push(`- Error: ${check.error.substring(0, 200)}`);
|
|
264
|
+
}
|
|
265
|
+
lines.push('');
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
lines.push('## Summary');
|
|
269
|
+
lines.push(verification.summary);
|
|
270
|
+
|
|
271
|
+
return lines.join('\n');
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Quick check if a specific command passes
|
|
276
|
+
*/
|
|
277
|
+
async quickCheck(command) {
|
|
278
|
+
try {
|
|
279
|
+
await execAsync(command, {
|
|
280
|
+
cwd: this.projectPath,
|
|
281
|
+
timeout: 60000,
|
|
282
|
+
maxBuffer: 5 * 1024 * 1024
|
|
283
|
+
});
|
|
284
|
+
return { passed: true, output: 'Success' };
|
|
285
|
+
} catch (error) {
|
|
286
|
+
return {
|
|
287
|
+
passed: false,
|
|
288
|
+
output: error.stderr || error.stdout || error.message
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Verify that the build succeeds
|
|
295
|
+
*/
|
|
296
|
+
async verifyBuild() {
|
|
297
|
+
return this.runCheck('build');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Verify that TypeScript compiles
|
|
302
|
+
*/
|
|
303
|
+
async verifyTypeScript() {
|
|
304
|
+
return this.runCheck('tsc');
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Verify that tests pass
|
|
309
|
+
*/
|
|
310
|
+
async verifyTests() {
|
|
311
|
+
return this.runCheck('test');
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Verify that lint passes
|
|
316
|
+
*/
|
|
317
|
+
async verifyLint() {
|
|
318
|
+
return this.runCheck('lint');
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Run all standard verification checks
|
|
323
|
+
*/
|
|
324
|
+
async runAllChecks() {
|
|
325
|
+
const checks = ['tsc', 'lint', 'build', 'test'];
|
|
326
|
+
const results = [];
|
|
327
|
+
|
|
328
|
+
for (const check of checks) {
|
|
329
|
+
const result = await this.runCheck(check);
|
|
330
|
+
results.push(result);
|
|
331
|
+
|
|
332
|
+
// Stop on first failure for efficiency (optional)
|
|
333
|
+
// if (!result.passed) break;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return {
|
|
337
|
+
checks: results,
|
|
338
|
+
allPassed: results.every(r => r.passed),
|
|
339
|
+
summary: results.map(r => `${r.name}: ${r.passed ? '✅' : '❌'}`).join(', ')
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export function createFixVerifier(projectPath) {
|
|
345
|
+
return new FixVerifier(projectPath);
|
|
346
|
+
}
|
package/src/index.js
CHANGED
|
@@ -19,6 +19,108 @@ export { snapshotCommand } from './commands/snapshot.js';
|
|
|
19
19
|
// Phase C Commands
|
|
20
20
|
export { configCommand } from './commands/config.js';
|
|
21
21
|
|
|
22
|
+
// Phase E Commands - Magic Mode
|
|
23
|
+
export { goCommand } from './commands/go.js';
|
|
24
|
+
|
|
25
|
+
// Phase F Commands - Agent Mode
|
|
26
|
+
export { agentCommand } from './commands/agent.js';
|
|
27
|
+
|
|
28
|
+
// Phase G Commands - Debug Mode
|
|
29
|
+
export { debugCommand } from './commands/debug.js';
|
|
30
|
+
export { assistCommand } from './commands/assist.js';
|
|
31
|
+
|
|
32
|
+
// Phase H Commands - Smart Defaults
|
|
33
|
+
export { wizardCommand } from './commands/wizard.js';
|
|
34
|
+
|
|
35
|
+
// Phase H4 Commands - Undo/Rollback
|
|
36
|
+
export { undoCommand } from './commands/undo.js';
|
|
37
|
+
export { BackupManager, withBackup, createBackupManager } from './core/backup.js';
|
|
38
|
+
|
|
39
|
+
// Phase H5 Commands - Learning Mode
|
|
40
|
+
export { learnCommand } from './commands/learn.js';
|
|
41
|
+
export { askFeedback, showLearningSuggestion } from './commands/learn.js';
|
|
42
|
+
export { LearningEngine, getLearningEngine, createLearningEngine } from './core/learning.js';
|
|
43
|
+
|
|
44
|
+
// Phase I Commands - Git Integration
|
|
45
|
+
export { gitCommand, autoCommit } from './commands/git.js';
|
|
46
|
+
|
|
47
|
+
// Phase I2 Commands - File Watcher
|
|
48
|
+
export { watchCommand } from './commands/watch.js';
|
|
49
|
+
|
|
50
|
+
// Phase I3 Commands - Shell Mode
|
|
51
|
+
export { shellCommand } from './commands/shell.js';
|
|
52
|
+
|
|
53
|
+
// Phase K Commands - Maximize Claude Code
|
|
54
|
+
export { testCommand } from './commands/test.js';
|
|
55
|
+
export { docsCommand } from './commands/docs.js';
|
|
56
|
+
export { refactorCommand } from './commands/refactor.js';
|
|
57
|
+
export { securityCommand } from './commands/security.js';
|
|
58
|
+
export { askCommand } from './commands/ask.js';
|
|
59
|
+
export { migrateCommand } from './commands/migrate.js';
|
|
60
|
+
|
|
61
|
+
// Phase M Commands - Templates
|
|
62
|
+
export { templatesCommand } from './commands/templates.js';
|
|
63
|
+
export {
|
|
64
|
+
TEMPLATES,
|
|
65
|
+
getTemplate,
|
|
66
|
+
getTemplatesByCategory,
|
|
67
|
+
getCategories,
|
|
68
|
+
searchTemplates,
|
|
69
|
+
getCategoryIcon,
|
|
70
|
+
getTemplateIds,
|
|
71
|
+
isValidTemplate
|
|
72
|
+
} from './templates/index.js';
|
|
73
|
+
|
|
74
|
+
// UI exports (Phase H2: Dashboard)
|
|
75
|
+
export {
|
|
76
|
+
ProgressDashboard,
|
|
77
|
+
StepProgress,
|
|
78
|
+
renderInlineProgress,
|
|
79
|
+
updateProgress,
|
|
80
|
+
completeProgress
|
|
81
|
+
} from './ui/dashboard.js';
|
|
82
|
+
|
|
83
|
+
// UI exports (Phase H3: Error Translator)
|
|
84
|
+
export {
|
|
85
|
+
translateError,
|
|
86
|
+
formatTranslatedError,
|
|
87
|
+
showError,
|
|
88
|
+
inlineError,
|
|
89
|
+
getErrorCategory,
|
|
90
|
+
isErrorCategory
|
|
91
|
+
} from './ui/error-translator.js';
|
|
92
|
+
|
|
93
|
+
// Debug exports
|
|
94
|
+
export {
|
|
95
|
+
DebugEngine,
|
|
96
|
+
createDebugEngine,
|
|
97
|
+
EvidenceCollector,
|
|
98
|
+
RootCauseAnalyzer,
|
|
99
|
+
FixGenerator,
|
|
100
|
+
FixVerifier
|
|
101
|
+
} from './debug/index.js';
|
|
102
|
+
|
|
103
|
+
// Image Analysis exports (Phase I4)
|
|
104
|
+
export { ImageAnalyzer, analyzeScreenshot } from './debug/image-analyzer.js';
|
|
105
|
+
export {
|
|
106
|
+
saveClipboardImage,
|
|
107
|
+
imageToBase64,
|
|
108
|
+
getImageInfo,
|
|
109
|
+
isValidImage,
|
|
110
|
+
cleanupTempImages
|
|
111
|
+
} from './utils/image.js';
|
|
112
|
+
|
|
113
|
+
// Agent exports
|
|
114
|
+
export {
|
|
115
|
+
VibecodeAgent,
|
|
116
|
+
createAgent,
|
|
117
|
+
agentBuild,
|
|
118
|
+
DecompositionEngine,
|
|
119
|
+
MemoryEngine,
|
|
120
|
+
SelfHealingEngine,
|
|
121
|
+
Orchestrator
|
|
122
|
+
} from './agent/index.js';
|
|
123
|
+
|
|
22
124
|
// Constants
|
|
23
125
|
export { VERSION, SPEC_HASH, STATES } from './config/constants.js';
|
|
24
126
|
|
|
@@ -15,6 +15,7 @@ export const CLAUDE_CODE_CONFIG = {
|
|
|
15
15
|
command: 'claude',
|
|
16
16
|
flags: [
|
|
17
17
|
'--dangerously-skip-permissions', // Trust the AI - Contract đã locked
|
|
18
|
+
'--print', // Non-interactive mode (no TTY required)
|
|
18
19
|
],
|
|
19
20
|
timeout: 30 * 60 * 1000, // 30 minutes max
|
|
20
21
|
};
|
|
@@ -61,18 +62,22 @@ export async function spawnClaudeCode(prompt, options = {}) {
|
|
|
61
62
|
await fs.default.writeFile(promptFile, prompt, 'utf-8');
|
|
62
63
|
|
|
63
64
|
return new Promise((resolve, reject) => {
|
|
64
|
-
//
|
|
65
|
-
const
|
|
65
|
+
// Build command with --print mode and -p for prompt file
|
|
66
|
+
const args = [
|
|
67
|
+
...CLAUDE_CODE_CONFIG.flags,
|
|
68
|
+
'-p', promptFile
|
|
69
|
+
];
|
|
70
|
+
const command = `claude ${args.map(a => `"${a}"`).join(' ')}`;
|
|
66
71
|
|
|
67
72
|
// Log the command being run
|
|
68
73
|
if (logPath) {
|
|
69
|
-
appendToFile(logPath, `\n[${new Date().toISOString()}] Running: claude
|
|
74
|
+
appendToFile(logPath, `\n[${new Date().toISOString()}] Running: claude --print -p ${promptFile}\n`);
|
|
70
75
|
}
|
|
71
76
|
|
|
72
|
-
const proc = spawn(
|
|
77
|
+
const proc = spawn('claude', args, {
|
|
73
78
|
cwd: cwd || process.cwd(),
|
|
74
79
|
stdio: 'inherit', // Stream directly to terminal
|
|
75
|
-
shell:
|
|
80
|
+
shell: false, // No shell needed, safer
|
|
76
81
|
});
|
|
77
82
|
|
|
78
83
|
let timeoutId = setTimeout(() => {
|
|
@@ -153,7 +158,7 @@ export function getProviderInfo() {
|
|
|
153
158
|
return {
|
|
154
159
|
name: 'Claude Code',
|
|
155
160
|
command: CLAUDE_CODE_CONFIG.command,
|
|
156
|
-
mode: '--dangerously-skip-permissions',
|
|
157
|
-
description: 'AI coding
|
|
161
|
+
mode: '--dangerously-skip-permissions --print',
|
|
162
|
+
description: 'AI coding in non-interactive mode (contract-approved)'
|
|
158
163
|
};
|
|
159
164
|
}
|