@snapcommit/cli 3.4.0 ā 3.5.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/dist/commands/cursor-style.js +129 -23
- package/package.json +1 -1
|
@@ -384,47 +384,153 @@ async function executeCommitWithAI(intent) {
|
|
|
384
384
|
}
|
|
385
385
|
}
|
|
386
386
|
/**
|
|
387
|
-
*
|
|
387
|
+
* AI-POWERED conflict resolution - intelligently resolves merge conflicts!
|
|
388
388
|
*/
|
|
389
389
|
async function tryAdvancedConflictResolution() {
|
|
390
390
|
try {
|
|
391
|
-
//
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
return
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
|
|
391
|
+
// Get conflicted files
|
|
392
|
+
const conflictedFiles = (0, child_process_1.execSync)('git diff --name-only --diff-filter=U', { encoding: 'utf-8' })
|
|
393
|
+
.split('\n')
|
|
394
|
+
.filter(f => f.trim());
|
|
395
|
+
if (conflictedFiles.length === 0)
|
|
396
|
+
return false;
|
|
397
|
+
console.log(chalk_1.default.white(`\nš Analyzing ${conflictedFiles.length} conflicted file(s)...\n`));
|
|
398
|
+
// For each conflicted file, use AI to resolve
|
|
399
|
+
for (const file of conflictedFiles) {
|
|
400
|
+
try {
|
|
401
|
+
// Read the conflicted file
|
|
402
|
+
const conflictContent = (0, child_process_1.execSync)(`git show :1:${file}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
403
|
+
const oursContent = (0, child_process_1.execSync)(`git show :2:${file}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
404
|
+
const theirsContent = (0, child_process_1.execSync)(`git show :3:${file}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
405
|
+
// Ask AI to resolve the conflict
|
|
406
|
+
console.log(chalk_1.default.blue(`š¤ AI analyzing: ${file}...`));
|
|
407
|
+
const resolution = await resolveConflictWithAI(file, conflictContent, oursContent, theirsContent);
|
|
408
|
+
if (resolution) {
|
|
409
|
+
console.log(chalk_1.default.green(`ā AI resolved: ${file}`));
|
|
410
|
+
// Write the resolved content
|
|
411
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
412
|
+
fs.writeFileSync(file, resolution);
|
|
413
|
+
(0, child_process_1.execSync)(`git add ${file}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
// Fallback: ask user which version to keep
|
|
417
|
+
console.log(chalk_1.default.yellow(`\nā ļø ${file} - Choose resolution:`));
|
|
418
|
+
console.log(chalk_1.default.gray(' 1. Keep your changes (ours)'));
|
|
419
|
+
console.log(chalk_1.default.gray(' 2. Keep their changes (theirs)'));
|
|
420
|
+
console.log(chalk_1.default.gray(' 3. Skip (resolve manually later)\n'));
|
|
421
|
+
const rlConflict = await Promise.resolve().then(() => __importStar(require('readline')));
|
|
422
|
+
const rlChoice = rlConflict.createInterface({
|
|
423
|
+
input: process.stdin,
|
|
424
|
+
output: process.stdout,
|
|
425
|
+
});
|
|
426
|
+
const choice = await new Promise((resolve) => {
|
|
427
|
+
rlChoice.question(chalk_1.default.cyan('Choice (1/2/3): '), (ans) => {
|
|
428
|
+
setImmediate(() => rlChoice.close());
|
|
429
|
+
resolve(ans.trim());
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
if (choice === '1') {
|
|
433
|
+
(0, child_process_1.execSync)(`git checkout --ours ${file}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
434
|
+
(0, child_process_1.execSync)(`git add ${file}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
435
|
+
console.log(chalk_1.default.green(`ā Kept your changes: ${file}`));
|
|
436
|
+
}
|
|
437
|
+
else if (choice === '2') {
|
|
438
|
+
(0, child_process_1.execSync)(`git checkout --theirs ${file}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
439
|
+
(0, child_process_1.execSync)(`git add ${file}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
440
|
+
console.log(chalk_1.default.green(`ā Kept their changes: ${file}`));
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
console.log(chalk_1.default.gray(`ā Skipped: ${file}`));
|
|
444
|
+
return false; // User wants to resolve manually
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
catch (fileError) {
|
|
449
|
+
console.log(chalk_1.default.yellow(`ā ļø Couldn't auto-resolve ${file}`));
|
|
450
|
+
// Fallback: ask user
|
|
451
|
+
const rlFallback = await Promise.resolve().then(() => __importStar(require('readline')));
|
|
452
|
+
const rlFallbackChoice = rlFallback.createInterface({
|
|
453
|
+
input: process.stdin,
|
|
454
|
+
output: process.stdout,
|
|
455
|
+
});
|
|
456
|
+
const fallbackChoice = await new Promise((resolve) => {
|
|
457
|
+
rlFallbackChoice.question(chalk_1.default.cyan(`Keep (1) yours or (2) theirs? [1/2]: `), (ans) => {
|
|
458
|
+
setImmediate(() => rlFallbackChoice.close());
|
|
459
|
+
resolve(ans.trim());
|
|
460
|
+
});
|
|
461
|
+
});
|
|
462
|
+
if (fallbackChoice === '1') {
|
|
463
|
+
(0, child_process_1.execSync)(`git checkout --ours ${file}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
464
|
+
(0, child_process_1.execSync)(`git add ${file}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
465
|
+
}
|
|
466
|
+
else if (fallbackChoice === '2') {
|
|
467
|
+
(0, child_process_1.execSync)(`git checkout --theirs ${file}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
468
|
+
(0, child_process_1.execSync)(`git add ${file}`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
400
474
|
}
|
|
401
|
-
//
|
|
475
|
+
// Continue the rebase
|
|
402
476
|
try {
|
|
403
|
-
(0, child_process_1.execSync)('git rebase --abort', { encoding: 'utf-8', stdio: 'pipe' });
|
|
404
|
-
(0, child_process_1.execSync)('git pull --rebase', { encoding: 'utf-8', stdio: 'pipe' });
|
|
405
|
-
(0, child_process_1.execSync)('git checkout --theirs .', { encoding: 'utf-8', stdio: 'pipe' });
|
|
406
|
-
(0, child_process_1.execSync)('git add .', { encoding: 'utf-8', stdio: 'pipe' });
|
|
407
477
|
(0, child_process_1.execSync)('git rebase --continue', { encoding: 'utf-8', stdio: 'pipe' });
|
|
408
478
|
return true;
|
|
409
479
|
}
|
|
410
|
-
catch {
|
|
411
|
-
//
|
|
480
|
+
catch (continueError) {
|
|
481
|
+
// If rebase fails, might need to commit first
|
|
482
|
+
try {
|
|
483
|
+
(0, child_process_1.execSync)('git commit --no-edit', { encoding: 'utf-8', stdio: 'pipe' });
|
|
484
|
+
(0, child_process_1.execSync)('git rebase --continue', { encoding: 'utf-8', stdio: 'pipe' });
|
|
485
|
+
return true;
|
|
486
|
+
}
|
|
487
|
+
catch {
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
412
490
|
}
|
|
413
|
-
|
|
491
|
+
}
|
|
492
|
+
catch (error) {
|
|
493
|
+
console.log(chalk_1.default.red(`ā Conflict resolution failed: ${error.message}`));
|
|
414
494
|
try {
|
|
415
495
|
(0, child_process_1.execSync)('git rebase --abort', { encoding: 'utf-8', stdio: 'pipe' });
|
|
416
496
|
}
|
|
417
|
-
catch {
|
|
418
|
-
// Already aborted
|
|
419
|
-
}
|
|
497
|
+
catch { }
|
|
420
498
|
return false;
|
|
421
499
|
}
|
|
422
|
-
|
|
423
|
-
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Use AI to intelligently resolve merge conflicts
|
|
503
|
+
*/
|
|
504
|
+
async function resolveConflictWithAI(filename, base, ours, theirs) {
|
|
505
|
+
try {
|
|
506
|
+
const axios = (await Promise.resolve().then(() => __importStar(require('axios')))).default;
|
|
507
|
+
// Get the backend URL from env or default
|
|
508
|
+
const backendUrl = process.env.SNAPCOMMIT_BACKEND_URL || 'https://snapcommit.dev';
|
|
509
|
+
const response = await axios.post(`${backendUrl}/api/ai/resolve-conflict`, {
|
|
510
|
+
filename,
|
|
511
|
+
base,
|
|
512
|
+
ours,
|
|
513
|
+
theirs,
|
|
514
|
+
}, {
|
|
515
|
+
headers: {
|
|
516
|
+
'Content-Type': 'application/json',
|
|
517
|
+
},
|
|
518
|
+
timeout: 30000, // 30 second timeout
|
|
519
|
+
});
|
|
520
|
+
if (response.data?.resolution) {
|
|
521
|
+
return response.data.resolution;
|
|
522
|
+
}
|
|
523
|
+
return null;
|
|
524
|
+
}
|
|
525
|
+
catch (error) {
|
|
526
|
+
// AI resolution failed - fall back to manual choice
|
|
527
|
+
return null;
|
|
424
528
|
}
|
|
425
529
|
}
|
|
426
530
|
/**
|
|
427
531
|
* Execute Git commands - Cursor-style (clean, fast, auto-fix)
|
|
532
|
+
* NOW SUPPORTS: commits, pushes, pulls, merges, rebases, cherry-picks, stash,
|
|
533
|
+
* resets, reverts, blame, bisect, tags, reflog, and MORE!
|
|
428
534
|
*/
|
|
429
535
|
async function executeGitCommands(commands) {
|
|
430
536
|
for (const cmd of commands) {
|