@snapcommit/cli 1.2.1 → 2.0.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/dist/commands/cursor-style.js +297 -0
- package/dist/commands/natural.js +8 -404
- package/dist/repl.js +31 -75
- package/package.json +1 -1
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cursor-style natural language Git assistant
|
|
4
|
+
* Shows preview, asks confirmation, handles errors automatically
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.executeCursorStyle = executeCursorStyle;
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
+
const child_process_1 = require("child_process");
|
|
13
|
+
const readline_1 = __importDefault(require("readline"));
|
|
14
|
+
const git_1 = require("../utils/git");
|
|
15
|
+
const auth_1 = require("../lib/auth");
|
|
16
|
+
async function executeCursorStyle(userInput) {
|
|
17
|
+
if (!(0, git_1.isGitRepo)()) {
|
|
18
|
+
console.log(chalk_1.default.red('\n❌ Not a git repository\n'));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
// Get AI interpretation of the request
|
|
22
|
+
console.log(chalk_1.default.blue('\n✨ Understanding your request...\n'));
|
|
23
|
+
const plan = await interpretRequest(userInput);
|
|
24
|
+
if (!plan) {
|
|
25
|
+
console.log(chalk_1.default.red('❌ Could not understand the request\n'));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// Show the execution plan
|
|
29
|
+
console.log(chalk_1.default.bold('📋 Here\'s what I\'ll do:\n'));
|
|
30
|
+
plan.actions.forEach((action, i) => {
|
|
31
|
+
console.log(chalk_1.default.gray(` ${i + 1}. `) + chalk_1.default.white(action.description));
|
|
32
|
+
});
|
|
33
|
+
console.log();
|
|
34
|
+
// If commit is involved, show the AI-generated message
|
|
35
|
+
if (plan.commitMessage) {
|
|
36
|
+
console.log(chalk_1.default.gray('📝 Commit message: ') + chalk_1.default.cyan(`"${plan.commitMessage}"`));
|
|
37
|
+
console.log();
|
|
38
|
+
}
|
|
39
|
+
// Ask for confirmation
|
|
40
|
+
const needsConfirm = plan.actions.some(a => a.requiresConfirmation);
|
|
41
|
+
if (needsConfirm) {
|
|
42
|
+
const confirmOptions = plan.commitMessage
|
|
43
|
+
? chalk_1.default.yellow('Continue? (Y/n/e to edit message): ')
|
|
44
|
+
: chalk_1.default.yellow('Continue? (Y/n): ');
|
|
45
|
+
const answer = await askQuestion(confirmOptions);
|
|
46
|
+
if (answer.toLowerCase() === 'n') {
|
|
47
|
+
console.log(chalk_1.default.gray('\n✗ Cancelled\n'));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (answer.toLowerCase() === 'e' && plan.commitMessage) {
|
|
51
|
+
plan.commitMessage = await editMessage(plan.commitMessage);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Execute the plan
|
|
55
|
+
console.log(chalk_1.default.blue('\n⚙️ Executing...\n'));
|
|
56
|
+
for (const action of plan.actions) {
|
|
57
|
+
try {
|
|
58
|
+
await executeAction(action, plan.commitMessage);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
// Try to auto-fix common errors
|
|
62
|
+
const fixed = await tryAutoFix(error, action);
|
|
63
|
+
if (!fixed) {
|
|
64
|
+
console.log(chalk_1.default.red(`\n❌ Error: ${error.message}\n`));
|
|
65
|
+
console.log(chalk_1.default.yellow('💡 Try: "undo last change" to revert\n'));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
console.log(chalk_1.default.green('\n✅ All done!\n'));
|
|
71
|
+
}
|
|
72
|
+
async function interpretRequest(userInput) {
|
|
73
|
+
// This will call the backend AI to interpret the request
|
|
74
|
+
// For now, let's handle some common patterns
|
|
75
|
+
const input = userInput.toLowerCase();
|
|
76
|
+
const actions = [];
|
|
77
|
+
let commitMessage;
|
|
78
|
+
// "commit and push" pattern
|
|
79
|
+
if (input.includes('commit') && input.includes('push')) {
|
|
80
|
+
// Generate commit message
|
|
81
|
+
const diff = await getChangeDiff();
|
|
82
|
+
if (diff) {
|
|
83
|
+
commitMessage = await generateCommitMessage(diff);
|
|
84
|
+
}
|
|
85
|
+
actions.push({
|
|
86
|
+
type: 'stage',
|
|
87
|
+
description: 'Stage all changes',
|
|
88
|
+
requiresConfirmation: false,
|
|
89
|
+
});
|
|
90
|
+
actions.push({
|
|
91
|
+
type: 'commit',
|
|
92
|
+
description: `Commit with message: "${commitMessage || 'Update'}"`,
|
|
93
|
+
requiresConfirmation: true,
|
|
94
|
+
requiresCommitMessage: true,
|
|
95
|
+
});
|
|
96
|
+
actions.push({
|
|
97
|
+
type: 'push',
|
|
98
|
+
description: 'Push to origin',
|
|
99
|
+
command: 'git push',
|
|
100
|
+
requiresConfirmation: true,
|
|
101
|
+
});
|
|
102
|
+
return {
|
|
103
|
+
actions,
|
|
104
|
+
commitMessage,
|
|
105
|
+
explanation: 'Stage all changes, commit with AI-generated message, and push to remote',
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// "commit" only
|
|
109
|
+
if (input.includes('commit') && !input.includes('push')) {
|
|
110
|
+
const diff = await getChangeDiff();
|
|
111
|
+
if (diff) {
|
|
112
|
+
commitMessage = await generateCommitMessage(diff);
|
|
113
|
+
}
|
|
114
|
+
actions.push({
|
|
115
|
+
type: 'stage',
|
|
116
|
+
description: 'Stage all changes',
|
|
117
|
+
requiresConfirmation: false,
|
|
118
|
+
});
|
|
119
|
+
actions.push({
|
|
120
|
+
type: 'commit',
|
|
121
|
+
description: `Commit with message: "${commitMessage || 'Update'}"`,
|
|
122
|
+
requiresConfirmation: true,
|
|
123
|
+
requiresCommitMessage: true,
|
|
124
|
+
});
|
|
125
|
+
return {
|
|
126
|
+
actions,
|
|
127
|
+
commitMessage,
|
|
128
|
+
explanation: 'Stage and commit changes with AI-generated message',
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
// Let the AI handle complex requests
|
|
132
|
+
return await getAIInterpretation(userInput);
|
|
133
|
+
}
|
|
134
|
+
async function getChangeDiff() {
|
|
135
|
+
try {
|
|
136
|
+
(0, git_1.stageAllChanges)();
|
|
137
|
+
return (0, git_1.getGitDiff)(true);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async function generateCommitMessage(diff) {
|
|
144
|
+
const token = (0, auth_1.getToken)();
|
|
145
|
+
if (!token)
|
|
146
|
+
return 'Update changes';
|
|
147
|
+
try {
|
|
148
|
+
// Truncate large diffs
|
|
149
|
+
if (diff.length > 40000) {
|
|
150
|
+
diff = diff.substring(0, 40000);
|
|
151
|
+
}
|
|
152
|
+
const response = await fetch('https://snapcommit.dev/api/ai/commit', {
|
|
153
|
+
method: 'POST',
|
|
154
|
+
headers: { 'Content-Type': 'application/json' },
|
|
155
|
+
body: JSON.stringify({ diff, token }),
|
|
156
|
+
});
|
|
157
|
+
const data = await response.json();
|
|
158
|
+
return data.message || 'Update changes';
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
return 'Update changes';
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
async function getAIInterpretation(userInput) {
|
|
165
|
+
const token = (0, auth_1.getToken)();
|
|
166
|
+
if (!token)
|
|
167
|
+
return null;
|
|
168
|
+
try {
|
|
169
|
+
const currentBranch = (0, git_1.getCurrentBranch)();
|
|
170
|
+
const status = (0, git_1.getGitStatus)();
|
|
171
|
+
const response = await fetch('https://snapcommit.dev/api/ai/interpret', {
|
|
172
|
+
method: 'POST',
|
|
173
|
+
headers: { 'Content-Type': 'application/json' },
|
|
174
|
+
body: JSON.stringify({
|
|
175
|
+
userInput,
|
|
176
|
+
token,
|
|
177
|
+
context: {
|
|
178
|
+
currentBranch,
|
|
179
|
+
hasUncommittedChanges: status.unstaged > 0 || status.untracked > 0,
|
|
180
|
+
lastCommitHash: (0, child_process_1.execSync)('git log -1 --format=%H 2>/dev/null || echo ""', { encoding: 'utf-8' }).trim(),
|
|
181
|
+
remoteBranch: (0, child_process_1.execSync)('git rev-parse --abbrev-ref @{upstream} 2>/dev/null || echo ""', { encoding: 'utf-8' }).trim(),
|
|
182
|
+
},
|
|
183
|
+
}),
|
|
184
|
+
});
|
|
185
|
+
const data = await response.json();
|
|
186
|
+
// Convert AI intent to execution plan
|
|
187
|
+
// This is a simplified version - in production, this would be more sophisticated
|
|
188
|
+
return convertIntentToPlan(data.intent);
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function convertIntentToPlan(intent) {
|
|
195
|
+
// Convert the AI intent format to our execution plan format
|
|
196
|
+
// This bridges the existing intent format with the new Cursor-style execution
|
|
197
|
+
if (!intent || !intent.gitCommands)
|
|
198
|
+
return null;
|
|
199
|
+
const actions = intent.gitCommands.map((cmd, i) => ({
|
|
200
|
+
type: inferActionType(cmd),
|
|
201
|
+
description: intent.explanation || `Execute: ${cmd}`,
|
|
202
|
+
command: cmd,
|
|
203
|
+
requiresConfirmation: intent.needsConfirmation || intent.riskLevel !== 'safe',
|
|
204
|
+
}));
|
|
205
|
+
return {
|
|
206
|
+
actions,
|
|
207
|
+
explanation: intent.explanation,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function inferActionType(command) {
|
|
211
|
+
if (command.includes('git add'))
|
|
212
|
+
return 'stage';
|
|
213
|
+
if (command.includes('git commit'))
|
|
214
|
+
return 'commit';
|
|
215
|
+
if (command.includes('git push'))
|
|
216
|
+
return 'push';
|
|
217
|
+
if (command.includes('git checkout') || command.includes('git switch'))
|
|
218
|
+
return 'checkout';
|
|
219
|
+
if (command.includes('git merge'))
|
|
220
|
+
return 'merge';
|
|
221
|
+
if (command.includes('git reset'))
|
|
222
|
+
return 'reset';
|
|
223
|
+
if (command.includes('git branch'))
|
|
224
|
+
return 'branch';
|
|
225
|
+
if (command.includes('git pull'))
|
|
226
|
+
return 'pull';
|
|
227
|
+
if (command.includes('git rebase'))
|
|
228
|
+
return 'rebase';
|
|
229
|
+
if (command.includes('git cherry-pick'))
|
|
230
|
+
return 'cherry-pick';
|
|
231
|
+
return 'stage';
|
|
232
|
+
}
|
|
233
|
+
async function executeAction(action, commitMessage) {
|
|
234
|
+
switch (action.type) {
|
|
235
|
+
case 'stage':
|
|
236
|
+
(0, git_1.stageAllChanges)();
|
|
237
|
+
console.log(chalk_1.default.green(' ✓ Staged all changes'));
|
|
238
|
+
break;
|
|
239
|
+
case 'commit':
|
|
240
|
+
if (commitMessage) {
|
|
241
|
+
(0, child_process_1.execSync)(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, { encoding: 'utf-8' });
|
|
242
|
+
console.log(chalk_1.default.green(` ✓ Committed`));
|
|
243
|
+
}
|
|
244
|
+
break;
|
|
245
|
+
case 'push':
|
|
246
|
+
(0, child_process_1.execSync)('git push', { encoding: 'utf-8', stdio: 'pipe' });
|
|
247
|
+
console.log(chalk_1.default.green(' ✓ Pushed to remote'));
|
|
248
|
+
break;
|
|
249
|
+
default:
|
|
250
|
+
if (action.command) {
|
|
251
|
+
(0, child_process_1.execSync)(action.command, { encoding: 'utf-8', stdio: 'pipe' });
|
|
252
|
+
console.log(chalk_1.default.green(` ✓ ${action.description}`));
|
|
253
|
+
}
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
async function tryAutoFix(error, action) {
|
|
258
|
+
const errorMsg = error.message?.toLowerCase() || '';
|
|
259
|
+
// Handle "no remote configured"
|
|
260
|
+
if (errorMsg.includes('no configured push destination')) {
|
|
261
|
+
console.log(chalk_1.default.yellow('\n⚠️ No remote repository configured'));
|
|
262
|
+
console.log(chalk_1.default.gray(' You need to add a remote first\n'));
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
// Handle merge conflicts
|
|
266
|
+
if (errorMsg.includes('conflict')) {
|
|
267
|
+
console.log(chalk_1.default.yellow('\n⚠️ Merge conflict detected'));
|
|
268
|
+
console.log(chalk_1.default.gray(' Use: "resolve conflicts" to fix\n'));
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
// Handle auth failures
|
|
272
|
+
if (errorMsg.includes('authentication') || errorMsg.includes('permission denied')) {
|
|
273
|
+
console.log(chalk_1.default.yellow('\n⚠️ Authentication failed'));
|
|
274
|
+
console.log(chalk_1.default.gray(' Check your Git credentials\n'));
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
function askQuestion(query) {
|
|
280
|
+
const rl = readline_1.default.createInterface({
|
|
281
|
+
input: process.stdin,
|
|
282
|
+
output: process.stdout,
|
|
283
|
+
});
|
|
284
|
+
return new Promise((resolve) => {
|
|
285
|
+
rl.question(query, (answer) => {
|
|
286
|
+
rl.close();
|
|
287
|
+
resolve(answer);
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
async function editMessage(originalMessage) {
|
|
292
|
+
console.log(chalk_1.default.cyan('\n✏️ Edit commit message:\n'));
|
|
293
|
+
console.log(chalk_1.default.gray(' (Press Enter to keep, or type new message)\n'));
|
|
294
|
+
console.log(chalk_1.default.white(` Current: ${chalk_1.default.cyan(originalMessage)}\n`));
|
|
295
|
+
const newMessage = await askQuestion(chalk_1.default.yellow(' New message: '));
|
|
296
|
+
return newMessage.trim() || originalMessage;
|
|
297
|
+
}
|
package/dist/commands/natural.js
CHANGED
|
@@ -1,97 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Natural language Git command handler
|
|
4
|
-
*
|
|
3
|
+
* Natural language Git command handler - Cursor-style!
|
|
4
|
+
* Just talk, we'll handle everything
|
|
5
5
|
*/
|
|
6
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
-
if (k2 === undefined) k2 = k;
|
|
8
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
-
}
|
|
12
|
-
Object.defineProperty(o, k2, desc);
|
|
13
|
-
}) : (function(o, m, k, k2) {
|
|
14
|
-
if (k2 === undefined) k2 = k;
|
|
15
|
-
o[k2] = m[k];
|
|
16
|
-
}));
|
|
17
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
-
}) : function(o, v) {
|
|
20
|
-
o["default"] = v;
|
|
21
|
-
});
|
|
22
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
-
var ownKeys = function(o) {
|
|
24
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
-
var ar = [];
|
|
26
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
-
return ar;
|
|
28
|
-
};
|
|
29
|
-
return ownKeys(o);
|
|
30
|
-
};
|
|
31
|
-
return function (mod) {
|
|
32
|
-
if (mod && mod.__esModule) return mod;
|
|
33
|
-
var result = {};
|
|
34
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
-
__setModuleDefault(result, mod);
|
|
36
|
-
return result;
|
|
37
|
-
};
|
|
38
|
-
})();
|
|
39
6
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
40
7
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
41
8
|
};
|
|
42
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
10
|
exports.naturalCommand = naturalCommand;
|
|
44
11
|
const chalk_1 = __importDefault(require("chalk"));
|
|
45
|
-
const
|
|
46
|
-
const readline_1 = __importDefault(require("readline"));
|
|
47
|
-
const git_interpreter_1 = require("../ai/git-interpreter");
|
|
48
|
-
const git_1 = require("../utils/git");
|
|
49
|
-
const anthropic_client_1 = require("../ai/anthropic-client");
|
|
50
|
-
const git_2 = require("../utils/git");
|
|
51
|
-
const database_1 = require("../db/database");
|
|
52
|
-
const analytics_1 = require("../utils/analytics");
|
|
53
|
-
const manager_1 = require("../license/manager");
|
|
54
|
-
const smart_solver_1 = require("../ai/smart-solver");
|
|
12
|
+
const cursor_style_1 = require("./cursor-style");
|
|
55
13
|
const auth_1 = require("../lib/auth");
|
|
56
|
-
|
|
57
|
-
const rl = readline_1.default.createInterface({
|
|
58
|
-
input: process.stdin,
|
|
59
|
-
output: process.stdout,
|
|
60
|
-
});
|
|
61
|
-
return new Promise(resolve => rl.question(query, ans => {
|
|
62
|
-
rl.close();
|
|
63
|
-
resolve(ans);
|
|
64
|
-
}));
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Execute git commands with visual feedback
|
|
68
|
-
*/
|
|
69
|
-
function executeGitCommands(commands, showCommands = true) {
|
|
70
|
-
const results = [];
|
|
71
|
-
for (const cmd of commands) {
|
|
72
|
-
if (showCommands) {
|
|
73
|
-
console.log(chalk_1.default.gray(` $ ${cmd}`));
|
|
74
|
-
}
|
|
75
|
-
try {
|
|
76
|
-
const output = (0, child_process_1.execSync)(cmd, { encoding: 'utf-8', stdio: 'pipe' });
|
|
77
|
-
if (output.trim()) {
|
|
78
|
-
if (showCommands) {
|
|
79
|
-
console.log(chalk_1.default.gray(` ${output.trim().split('\n').join('\n ')}`));
|
|
80
|
-
}
|
|
81
|
-
results.push(output.trim());
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
if (showCommands) {
|
|
86
|
-
console.log(chalk_1.default.red(` Error: ${error.message}`));
|
|
87
|
-
}
|
|
88
|
-
return { success: false, output: results.join('\n'), error: error.message };
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return { success: true, output: results.join('\n') };
|
|
92
|
-
}
|
|
14
|
+
const git_1 = require("../utils/git");
|
|
93
15
|
/**
|
|
94
|
-
* Main natural language command handler
|
|
16
|
+
* Main natural language command handler - Cursor-style!
|
|
17
|
+
* Now everything works like Cursor - just say what you want!
|
|
95
18
|
*/
|
|
96
19
|
async function naturalCommand(userInput) {
|
|
97
20
|
// Ensure authentication first
|
|
@@ -106,325 +29,6 @@ async function naturalCommand(userInput) {
|
|
|
106
29
|
console.log(chalk_1.default.gray(' Navigate to a git repository first\n'));
|
|
107
30
|
return;
|
|
108
31
|
}
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
const status = (0, git_1.getGitStatus)();
|
|
112
|
-
const hasUncommittedChanges = status.staged > 0 || status.unstaged > 0;
|
|
113
|
-
let lastCommitHash;
|
|
114
|
-
try {
|
|
115
|
-
lastCommitHash = (0, child_process_1.execSync)('git log -1 --format=%H', { encoding: 'utf-8' }).trim();
|
|
116
|
-
}
|
|
117
|
-
catch {
|
|
118
|
-
lastCommitHash = undefined;
|
|
119
|
-
}
|
|
120
|
-
// Check if we need clarification
|
|
121
|
-
const clarification = await (0, smart_solver_1.needsClarification)(userInput);
|
|
122
|
-
if (clarification.needsClarification && clarification.options) {
|
|
123
|
-
console.log(chalk_1.default.yellow('\n🤔 I need more information:\n'));
|
|
124
|
-
clarification.options.forEach((option, i) => {
|
|
125
|
-
console.log(chalk_1.default.white(` ${i + 1}. ${option.label}`));
|
|
126
|
-
});
|
|
127
|
-
console.log();
|
|
128
|
-
const answer = await askQuestion(chalk_1.default.yellow(`Which one? (1-${clarification.options.length}): `));
|
|
129
|
-
const choice = parseInt(answer) - 1;
|
|
130
|
-
if (choice >= 0 && choice < clarification.options.length) {
|
|
131
|
-
const selectedOption = clarification.options[choice];
|
|
132
|
-
userInput = selectedOption.value; // Use the clarified intent
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
console.log(chalk_1.default.gray('\nInvalid choice. Cancelled.\n'));
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
console.log(chalk_1.default.blue('\n✨ Understanding your request...\n'));
|
|
140
|
-
// Show spinner
|
|
141
|
-
const spinner = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
142
|
-
let i = 0;
|
|
143
|
-
const interval = setInterval(() => {
|
|
144
|
-
process.stdout.write(chalk_1.default.blue(`\r${spinner[i++ % spinner.length]} Thinking...`));
|
|
145
|
-
}, 100);
|
|
146
|
-
// Interpret user input
|
|
147
|
-
let intent;
|
|
148
|
-
try {
|
|
149
|
-
intent = await (0, git_interpreter_1.interpretGitCommand)(userInput, {
|
|
150
|
-
currentBranch,
|
|
151
|
-
hasUncommittedChanges,
|
|
152
|
-
lastCommitHash,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
catch (error) {
|
|
156
|
-
clearInterval(interval);
|
|
157
|
-
process.stdout.write('\r' + ' '.repeat(20) + '\r');
|
|
158
|
-
// Try smart solver as ultimate fallback
|
|
159
|
-
console.log(chalk_1.default.yellow('🧠 Using advanced problem solver...\n'));
|
|
160
|
-
const gitStatusOutput = (0, child_process_1.execSync)('git status', { encoding: 'utf-8' });
|
|
161
|
-
const result = await (0, smart_solver_1.solveGitProblem)(userInput, {
|
|
162
|
-
currentBranch,
|
|
163
|
-
gitStatus: gitStatusOutput,
|
|
164
|
-
recentError: error.message,
|
|
165
|
-
});
|
|
166
|
-
if (result.success) {
|
|
167
|
-
await showDopamineStats();
|
|
168
|
-
(0, analytics_1.trackEvent)({ event: analytics_1.EVENTS.NATURAL_COMMAND_SUCCESS });
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
(0, analytics_1.trackEvent)({ event: analytics_1.EVENTS.NATURAL_COMMAND_ERROR });
|
|
172
|
-
}
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
clearInterval(interval);
|
|
176
|
-
process.stdout.write('\r' + ' '.repeat(20) + '\r');
|
|
177
|
-
// Check if this is a GitHub operation
|
|
178
|
-
const intentType = intent.type || 'git';
|
|
179
|
-
if (intentType === 'github') {
|
|
180
|
-
// Handle GitHub operations
|
|
181
|
-
await handleGitHubOperation(intent);
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
// Show intent (for Git operations) - simplified
|
|
185
|
-
console.log(chalk_1.default.cyan(`✨ ${intent.explanation}`));
|
|
186
|
-
// Risk warning
|
|
187
|
-
if (intent.riskLevel === 'high') {
|
|
188
|
-
console.log(chalk_1.default.red('⚠️ Destructive operation!'));
|
|
189
|
-
}
|
|
190
|
-
// Confirmation
|
|
191
|
-
if (intent.needsConfirmation) {
|
|
192
|
-
const answer = await askQuestion(chalk_1.default.yellow('Continue? (Y/n): '));
|
|
193
|
-
if (answer.toLowerCase() === 'n') {
|
|
194
|
-
console.log(chalk_1.default.gray('\nCancelled.\n'));
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
// Special handling for commit (needs AI message generation)
|
|
199
|
-
if (intent.action === 'commit') {
|
|
200
|
-
await handleCommitWithAI();
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
// Execute git commands
|
|
204
|
-
const result = executeGitCommands(intent.gitCommands, false);
|
|
205
|
-
if (result.success) {
|
|
206
|
-
console.log(chalk_1.default.green(`✅ Done!\n`));
|
|
207
|
-
(0, analytics_1.trackEvent)({ event: analytics_1.EVENTS.NATURAL_COMMAND_SUCCESS });
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
// First approach failed - try smart solver
|
|
211
|
-
console.log(chalk_1.default.yellow(`\n⚠️ Standard approach failed. Trying advanced solver...\n`));
|
|
212
|
-
const gitStatusOutput = (0, child_process_1.execSync)('git status', { encoding: 'utf-8' });
|
|
213
|
-
const smartResult = await (0, smart_solver_1.solveGitProblem)(userInput, {
|
|
214
|
-
currentBranch,
|
|
215
|
-
gitStatus: gitStatusOutput,
|
|
216
|
-
recentError: result.error,
|
|
217
|
-
});
|
|
218
|
-
if (smartResult.success) {
|
|
219
|
-
await showDopamineStats();
|
|
220
|
-
(0, analytics_1.trackEvent)({ event: analytics_1.EVENTS.NATURAL_COMMAND_SUCCESS });
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
console.log(chalk_1.default.red(`❌ Could not solve the problem: ${smartResult.error}\n`));
|
|
224
|
-
(0, analytics_1.trackEvent)({ event: analytics_1.EVENTS.NATURAL_COMMAND_ERROR });
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* Handle commit with AI message generation
|
|
230
|
-
*/
|
|
231
|
-
async function handleCommitWithAI() {
|
|
232
|
-
const { getGitDiff, stageAllChanges } = await Promise.resolve().then(() => __importStar(require('../utils/git')));
|
|
233
|
-
console.log(chalk_1.default.blue('📟 Running Git commands:\n'));
|
|
234
|
-
// Stage all changes
|
|
235
|
-
console.log(chalk_1.default.gray(' $ git add -A'));
|
|
236
|
-
stageAllChanges();
|
|
237
|
-
console.log(chalk_1.default.gray(' ✓ Staged all changes\n'));
|
|
238
|
-
// Get diff
|
|
239
|
-
let diff;
|
|
240
|
-
try {
|
|
241
|
-
diff = getGitDiff();
|
|
242
|
-
if (diff.length > 40000) {
|
|
243
|
-
diff = diff.substring(0, 40000);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
catch (error) {
|
|
247
|
-
console.log(chalk_1.default.red(' ❌ Could not get diff\n'));
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
// Generate AI commit message
|
|
251
|
-
console.log(chalk_1.default.gray(' ✨ Generating commit message with AI...'));
|
|
252
|
-
let message;
|
|
253
|
-
try {
|
|
254
|
-
message = await (0, anthropic_client_1.generateCommitMessage)(diff);
|
|
255
|
-
console.log(chalk_1.default.gray(` ✓ Generated: "${message.split('\n')[0]}"\n`));
|
|
256
|
-
}
|
|
257
|
-
catch (error) {
|
|
258
|
-
console.log(chalk_1.default.red(' ❌ AI failed\n'));
|
|
259
|
-
(0, analytics_1.trackEvent)({ event: 'commit_error' });
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
// Commit
|
|
263
|
-
console.log(chalk_1.default.gray(` $ git commit -m "${message.split('\n')[0]}"`));
|
|
264
|
-
try {
|
|
265
|
-
const hash = (0, git_2.commitWithMessage)(message);
|
|
266
|
-
const stats = (0, git_2.getCommitStats)(hash);
|
|
267
|
-
console.log(chalk_1.default.gray(` ✓ Committed ${hash.substring(0, 7)}\n`));
|
|
268
|
-
console.log(chalk_1.default.green.bold('✅ Success! Committed your changes\n'));
|
|
269
|
-
console.log(chalk_1.default.gray(` Message: ${message.split('\n')[0]}`));
|
|
270
|
-
console.log(chalk_1.default.gray(` Files: ${stats.files} | +${stats.insertions} -${stats.deletions}\n`));
|
|
271
|
-
// Track
|
|
272
|
-
(0, manager_1.trackCommit)();
|
|
273
|
-
(0, analytics_1.trackEvent)({ event: analytics_1.EVENTS.COMMIT_SUCCESS });
|
|
274
|
-
// Log to database
|
|
275
|
-
(0, database_1.logCommit)({
|
|
276
|
-
message,
|
|
277
|
-
hash,
|
|
278
|
-
files_changed: stats.files,
|
|
279
|
-
insertions: stats.insertions,
|
|
280
|
-
deletions: stats.deletions,
|
|
281
|
-
timestamp: Date.now(),
|
|
282
|
-
});
|
|
283
|
-
// Dopamine
|
|
284
|
-
await showDopamineStats();
|
|
285
|
-
}
|
|
286
|
-
catch (error) {
|
|
287
|
-
console.log(chalk_1.default.red(` ❌ Commit failed: ${error.message}\n`));
|
|
288
|
-
(0, analytics_1.trackEvent)({ event: analytics_1.EVENTS.COMMIT_ERROR });
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* Show dopamine-inducing stats
|
|
293
|
-
*/
|
|
294
|
-
async function showDopamineStats() {
|
|
295
|
-
const { displayQuickDopamine } = await Promise.resolve().then(() => __importStar(require('../utils/dopamine')));
|
|
296
|
-
displayQuickDopamine();
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* Handle GitHub operations (PRs, CI checks, issues)
|
|
300
|
-
*/
|
|
301
|
-
async function handleGitHubOperation(intent) {
|
|
302
|
-
// Import GitHub connection utilities
|
|
303
|
-
const { getGitHubToken, isGitHubConnected } = await Promise.resolve().then(() => __importStar(require('./github-connect')));
|
|
304
|
-
const { Octokit } = await Promise.resolve().then(() => __importStar(require('@octokit/rest')));
|
|
305
|
-
// Check if GitHub is connected
|
|
306
|
-
if (!isGitHubConnected()) {
|
|
307
|
-
console.log(chalk_1.default.red('❌ GitHub not connected!\n'));
|
|
308
|
-
console.log(chalk_1.default.yellow('To connect GitHub:'));
|
|
309
|
-
console.log(chalk_1.default.cyan(' Run: ') + chalk_1.default.white('snap github connect'));
|
|
310
|
-
console.log(chalk_1.default.gray('\nYou\'ll need a GitHub Personal Access Token'));
|
|
311
|
-
console.log(chalk_1.default.gray('Get one at: https://github.com/settings/tokens\n'));
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
const githubToken = getGitHubToken();
|
|
315
|
-
if (!githubToken) {
|
|
316
|
-
console.log(chalk_1.default.red('❌ GitHub token not found\n'));
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
const octokit = new Octokit({ auth: githubToken });
|
|
320
|
-
console.log(chalk_1.default.green(`✨ ${intent.explanation}\n`));
|
|
321
|
-
// Show confirmation if needed
|
|
322
|
-
if (intent.needsConfirmation) {
|
|
323
|
-
const answer = await askQuestion(chalk_1.default.yellow('Continue? (Y/n): '));
|
|
324
|
-
if (answer.toLowerCase() === 'n') {
|
|
325
|
-
console.log(chalk_1.default.gray('\nCancelled.\n'));
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
// Get repo info from git remote
|
|
330
|
-
let owner, repo;
|
|
331
|
-
try {
|
|
332
|
-
const remote = (0, child_process_1.execSync)('git remote get-url origin', { encoding: 'utf-8' }).trim();
|
|
333
|
-
const match = remote.match(/github\.com[/:]([\w-]+)\/([\w-]+?)(\.git)?$/);
|
|
334
|
-
if (!match) {
|
|
335
|
-
console.log(chalk_1.default.red('❌ Not a GitHub repository\n'));
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
owner = match[1];
|
|
339
|
-
repo = match[2];
|
|
340
|
-
}
|
|
341
|
-
catch {
|
|
342
|
-
console.log(chalk_1.default.red('❌ Not a GitHub repository\n'));
|
|
343
|
-
return;
|
|
344
|
-
}
|
|
345
|
-
console.log(chalk_1.default.blue('🔄 Executing GitHub operation...\n'));
|
|
346
|
-
try {
|
|
347
|
-
if (intent.action === 'pr_create') {
|
|
348
|
-
// Create PR using Octokit
|
|
349
|
-
const currentBranch = (0, child_process_1.execSync)('git branch --show-current', { encoding: 'utf-8' }).trim();
|
|
350
|
-
const { data: pr } = await octokit.pulls.create({
|
|
351
|
-
owner,
|
|
352
|
-
repo,
|
|
353
|
-
title: intent.options?.title || `PR from ${currentBranch}`,
|
|
354
|
-
body: intent.options?.body || '',
|
|
355
|
-
head: intent.options?.head || currentBranch,
|
|
356
|
-
base: intent.options?.base || 'main',
|
|
357
|
-
});
|
|
358
|
-
console.log(chalk_1.default.green.bold('✅ Pull Request Created!\n'));
|
|
359
|
-
console.log(chalk_1.default.white(` Title: ${pr.title}`));
|
|
360
|
-
console.log(chalk_1.default.white(` Number: #${pr.number}`));
|
|
361
|
-
console.log(chalk_1.default.white(` URL: ${chalk_1.default.cyan(pr.html_url)}\n`));
|
|
362
|
-
}
|
|
363
|
-
else if (intent.action === 'pr_list') {
|
|
364
|
-
// List PRs using Octokit
|
|
365
|
-
const state = intent.options?.state || 'open';
|
|
366
|
-
const { data: prs } = await octokit.pulls.list({
|
|
367
|
-
owner,
|
|
368
|
-
repo,
|
|
369
|
-
state: state,
|
|
370
|
-
per_page: 20,
|
|
371
|
-
});
|
|
372
|
-
if (prs.length === 0) {
|
|
373
|
-
console.log(chalk_1.default.yellow(`No ${state} pull requests found.\n`));
|
|
374
|
-
return;
|
|
375
|
-
}
|
|
376
|
-
console.log(chalk_1.default.green.bold(`📋 ${state.toUpperCase()} Pull Requests:\n`));
|
|
377
|
-
prs.forEach((pr) => {
|
|
378
|
-
console.log(chalk_1.default.white(` #${pr.number} - ${pr.title}`));
|
|
379
|
-
console.log(chalk_1.default.gray(` ${pr.head.ref} → ${pr.base.ref} by @${pr.user?.login}`));
|
|
380
|
-
console.log(chalk_1.default.cyan(` ${pr.html_url}\n`));
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
else if (intent.action === 'ci_check') {
|
|
384
|
-
// Check CI status using Octokit
|
|
385
|
-
const ref = intent.options?.ref || (0, child_process_1.execSync)('git branch --show-current', { encoding: 'utf-8' }).trim();
|
|
386
|
-
// Get commit status checks
|
|
387
|
-
const { data: statusData } = await octokit.repos.getCombinedStatusForRef({
|
|
388
|
-
owner,
|
|
389
|
-
repo,
|
|
390
|
-
ref,
|
|
391
|
-
});
|
|
392
|
-
// Get workflow runs
|
|
393
|
-
const { data: workflowRuns } = await octokit.actions.listWorkflowRunsForRepo({
|
|
394
|
-
owner,
|
|
395
|
-
repo,
|
|
396
|
-
per_page: 10,
|
|
397
|
-
});
|
|
398
|
-
// Filter workflow runs for this ref
|
|
399
|
-
const relevantRuns = workflowRuns.workflow_runs.filter(run => run.head_branch === ref || run.head_sha === ref);
|
|
400
|
-
const stateColor = statusData.state === 'success' ? chalk_1.default.green :
|
|
401
|
-
statusData.state === 'pending' ? chalk_1.default.yellow : chalk_1.default.red;
|
|
402
|
-
console.log(stateColor.bold(`CI Status: ${statusData.state.toUpperCase()}\n`));
|
|
403
|
-
if (statusData.statuses.length > 0) {
|
|
404
|
-
console.log(chalk_1.default.white('Status Checks:'));
|
|
405
|
-
statusData.statuses.forEach((status) => {
|
|
406
|
-
const icon = status.state === 'success' ? '✅' : status.state === 'pending' ? '⏳' : '❌';
|
|
407
|
-
console.log(chalk_1.default.gray(` ${icon} ${status.context}: ${status.description}`));
|
|
408
|
-
});
|
|
409
|
-
console.log();
|
|
410
|
-
}
|
|
411
|
-
if (relevantRuns.length > 0) {
|
|
412
|
-
console.log(chalk_1.default.white('Workflows:'));
|
|
413
|
-
relevantRuns.forEach((workflow) => {
|
|
414
|
-
const icon = workflow.conclusion === 'success' ? '✅' :
|
|
415
|
-
workflow.status === 'in_progress' ? '⏳' : '❌';
|
|
416
|
-
console.log(chalk_1.default.gray(` ${icon} ${workflow.name}: ${workflow.conclusion || workflow.status}`));
|
|
417
|
-
});
|
|
418
|
-
console.log();
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
else {
|
|
422
|
-
console.log(chalk_1.default.yellow(`⚠️ GitHub operation "${intent.action}" not yet implemented\n`));
|
|
423
|
-
}
|
|
424
|
-
(0, analytics_1.trackEvent)({ event: analytics_1.EVENTS.NATURAL_COMMAND_SUCCESS });
|
|
425
|
-
}
|
|
426
|
-
catch (error) {
|
|
427
|
-
console.log(chalk_1.default.red(`❌ ${error.message}\n`));
|
|
428
|
-
(0, analytics_1.trackEvent)({ event: analytics_1.EVENTS.NATURAL_COMMAND_ERROR });
|
|
429
|
-
}
|
|
32
|
+
// Use the new Cursor-style execution!
|
|
33
|
+
await (0, cursor_style_1.executeCursorStyle)(userInput);
|
|
430
34
|
}
|
package/dist/repl.js
CHANGED
|
@@ -41,10 +41,7 @@ const readline_1 = __importDefault(require("readline"));
|
|
|
41
41
|
const chalk_1 = __importDefault(require("chalk"));
|
|
42
42
|
const auth_1 = require("./lib/auth");
|
|
43
43
|
const natural_1 = require("./commands/natural");
|
|
44
|
-
const quick_1 = require("./commands/quick");
|
|
45
|
-
const stats_1 = require("./commands/stats");
|
|
46
44
|
const github_connect_1 = require("./commands/github-connect");
|
|
47
|
-
const repo_manager_1 = require("./utils/repo-manager");
|
|
48
45
|
const version_1 = require("./utils/version");
|
|
49
46
|
/**
|
|
50
47
|
* Start SnapCommit REPL (Read-Eval-Print-Loop)
|
|
@@ -70,8 +67,9 @@ async function startREPL() {
|
|
|
70
67
|
console.log(chalk_1.default.yellow.bold('║ 🚀 UPDATE AVAILABLE! ║'));
|
|
71
68
|
console.log(chalk_1.default.yellow.bold('╚════════════════════════════════════════╝'));
|
|
72
69
|
console.log(chalk_1.default.white(` Current: ${chalk_1.default.red(updateInfo.currentVersion)} → Latest: ${chalk_1.default.green(updateInfo.latestVersion)}\n`));
|
|
73
|
-
console.log(chalk_1.default.cyan.bold('
|
|
74
|
-
console.log(chalk_1.default.gray(' (Faster AI,
|
|
70
|
+
console.log(chalk_1.default.cyan.bold(' To update: ') + chalk_1.default.white('Just type ') + chalk_1.default.cyan.bold('update') + chalk_1.default.white(' in the CLI below'));
|
|
71
|
+
console.log(chalk_1.default.gray(' (Faster AI, Cursor-style UX, better experience!)\n'));
|
|
72
|
+
console.log(chalk_1.default.white(' Example: ') + chalk_1.default.cyan('snap> update\n'));
|
|
75
73
|
}
|
|
76
74
|
}).catch((err) => {
|
|
77
75
|
// Silent fail - don't interrupt user experience
|
|
@@ -83,15 +81,15 @@ async function startREPL() {
|
|
|
83
81
|
console.log(chalk_1.default.green(`✅ GitHub connected as ${chalk_1.default.bold('@' + githubConfig?.username)}\n`));
|
|
84
82
|
}
|
|
85
83
|
console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
|
|
86
|
-
console.log(chalk_1.default.bold('💡
|
|
87
|
-
console.log(chalk_1.default.gray('
|
|
88
|
-
console.log(chalk_1.default.gray('
|
|
89
|
-
console.log(chalk_1.default.gray('
|
|
90
|
-
console.log(chalk_1.default.gray(' • ') + chalk_1.default.white('Switch repos: ') + chalk_1.default.cyan('cd /path/to/repo') + chalk_1.default.gray(' or ') + chalk_1.default.cyan('repos'));
|
|
84
|
+
console.log(chalk_1.default.bold('💡 Just talk to me! I understand natural language:\n'));
|
|
85
|
+
console.log(chalk_1.default.gray(' Git: ') + chalk_1.default.cyan('"commit and push changes"'));
|
|
86
|
+
console.log(chalk_1.default.gray(' ') + chalk_1.default.cyan('"switch to main and merge feature-x"'));
|
|
87
|
+
console.log(chalk_1.default.gray(' ') + chalk_1.default.cyan('"undo my last commit"'));
|
|
91
88
|
if (githubConnected) {
|
|
92
|
-
console.log(chalk_1.default.gray('
|
|
89
|
+
console.log(chalk_1.default.gray(' GitHub: ') + chalk_1.default.cyan('"create a PR to main"'));
|
|
90
|
+
console.log(chalk_1.default.gray(' ') + chalk_1.default.cyan('"check CI status"'));
|
|
93
91
|
}
|
|
94
|
-
console.log(chalk_1.default.gray('
|
|
92
|
+
console.log(chalk_1.default.gray(' Other: ') + chalk_1.default.cyan('exit') + chalk_1.default.gray(' • ') + chalk_1.default.cyan('help') + chalk_1.default.gray(' • ') + chalk_1.default.cyan('update\n'));
|
|
95
93
|
// Show GitHub setup reminder if not connected
|
|
96
94
|
if (!githubConnected) {
|
|
97
95
|
console.log(chalk_1.default.yellow.bold('┌─────────────────────────────────────────┐'));
|
|
@@ -125,60 +123,7 @@ async function startREPL() {
|
|
|
125
123
|
rl.close();
|
|
126
124
|
process.exit(0);
|
|
127
125
|
}
|
|
128
|
-
//
|
|
129
|
-
if (line === 'quick' || line === 'q') {
|
|
130
|
-
await (0, quick_1.quickCommand)();
|
|
131
|
-
rl.prompt();
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
if (line === 'commit' || line === 'c') {
|
|
135
|
-
const { commitCommand } = await Promise.resolve().then(() => __importStar(require('./commands/commit')));
|
|
136
|
-
rl.pause(); // Pause REPL readline to avoid conflicts
|
|
137
|
-
await commitCommand();
|
|
138
|
-
rl.resume(); // Resume REPL readline
|
|
139
|
-
rl.prompt();
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
if (line === 'stats' || line === 's') {
|
|
143
|
-
(0, stats_1.statsCommand)();
|
|
144
|
-
rl.prompt();
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
// cd command - navigate to different repo
|
|
148
|
-
if (line.startsWith('cd ')) {
|
|
149
|
-
const targetPath = line.substring(3).trim();
|
|
150
|
-
const result = (0, repo_manager_1.changeToRepo)(targetPath);
|
|
151
|
-
if (result.success) {
|
|
152
|
-
console.log(chalk_1.default.green(`\n✅ Switched to: ${chalk_1.default.bold(result.repoName)}`));
|
|
153
|
-
console.log(chalk_1.default.gray(` Path: ${result.repoPath}\n`));
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
console.log(chalk_1.default.red(`\n❌ ${result.error}`));
|
|
157
|
-
console.log(chalk_1.default.gray(' Navigate to a valid git repository\n'));
|
|
158
|
-
}
|
|
159
|
-
rl.prompt();
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
// repos command - show recent repos
|
|
163
|
-
if (line === 'repos' || line === 'repo') {
|
|
164
|
-
const repos = (0, repo_manager_1.getRecentRepos)();
|
|
165
|
-
if (repos.length === 0) {
|
|
166
|
-
console.log(chalk_1.default.yellow('\n📁 No recent repositories\n'));
|
|
167
|
-
console.log(chalk_1.default.gray(' Use ') + chalk_1.default.cyan('cd /path/to/repo') + chalk_1.default.gray(' to navigate to a repo\n'));
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
console.log(chalk_1.default.bold('\n📁 Recent Repositories:\n'));
|
|
171
|
-
repos.slice(0, 10).forEach((repo, index) => {
|
|
172
|
-
const isCurrent = repo.path === process.cwd();
|
|
173
|
-
const prefix = isCurrent ? chalk_1.default.green('→ ') : ' ';
|
|
174
|
-
console.log(prefix + chalk_1.default.cyan(`${index + 1}. ${repo.name}`) + chalk_1.default.gray(` (${repo.useCount} uses)`));
|
|
175
|
-
console.log(' ' + chalk_1.default.gray(repo.path));
|
|
176
|
-
});
|
|
177
|
-
console.log(chalk_1.default.gray('\n Use ') + chalk_1.default.cyan('cd <path>') + chalk_1.default.gray(' to switch repos\n'));
|
|
178
|
-
}
|
|
179
|
-
rl.prompt();
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
126
|
+
// All commands are now natural language - removed special commands!
|
|
182
127
|
// Update command - update SnapCommit to latest version
|
|
183
128
|
if (line === 'update' || line === 'upgrade') {
|
|
184
129
|
console.log(chalk_1.default.cyan('\n⚡ Updating SnapCommit to latest version...\n'));
|
|
@@ -212,15 +157,26 @@ async function startREPL() {
|
|
|
212
157
|
return;
|
|
213
158
|
}
|
|
214
159
|
if (line === 'help' || line === 'h') {
|
|
215
|
-
console.log(chalk_1.default.bold('\n
|
|
216
|
-
console.log(chalk_1.default.
|
|
217
|
-
console.log(chalk_1.default.
|
|
218
|
-
console.log(chalk_1.default.
|
|
219
|
-
console.log(chalk_1.default.
|
|
220
|
-
console.log(chalk_1.default.
|
|
221
|
-
console.log(chalk_1.default.
|
|
222
|
-
console.log(chalk_1.default.
|
|
223
|
-
console.log(chalk_1.default.
|
|
160
|
+
console.log(chalk_1.default.bold.cyan('\n╔════════════════════════════════════════╗'));
|
|
161
|
+
console.log(chalk_1.default.bold.cyan('║ SnapCommit - Your AI Git Assistant ║'));
|
|
162
|
+
console.log(chalk_1.default.bold.cyan('╚════════════════════════════════════════╝\n'));
|
|
163
|
+
console.log(chalk_1.default.bold('🎯 Just talk to me in plain English!\n'));
|
|
164
|
+
console.log(chalk_1.default.white.bold('Git Operations:\n'));
|
|
165
|
+
console.log(chalk_1.default.cyan(' "commit and push my changes"'));
|
|
166
|
+
console.log(chalk_1.default.cyan(' "switch to main branch"'));
|
|
167
|
+
console.log(chalk_1.default.cyan(' "create a new branch called feature-x"'));
|
|
168
|
+
console.log(chalk_1.default.cyan(' "undo my last commit"'));
|
|
169
|
+
console.log(chalk_1.default.cyan(' "merge feature-x into main"'));
|
|
170
|
+
console.log(chalk_1.default.cyan(' "show me what changed"\n'));
|
|
171
|
+
console.log(chalk_1.default.white.bold('GitHub Operations:\n'));
|
|
172
|
+
console.log(chalk_1.default.cyan(' "create a PR to main"'));
|
|
173
|
+
console.log(chalk_1.default.cyan(' "check CI status"'));
|
|
174
|
+
console.log(chalk_1.default.cyan(' "list my pull requests"'));
|
|
175
|
+
console.log(chalk_1.default.cyan(' "merge PR #123"\n'));
|
|
176
|
+
console.log(chalk_1.default.white.bold('System Commands:\n'));
|
|
177
|
+
console.log(chalk_1.default.gray(' • ') + chalk_1.default.cyan('update') + chalk_1.default.gray(' - Update to latest version'));
|
|
178
|
+
console.log(chalk_1.default.gray(' • ') + chalk_1.default.cyan('exit/quit') + chalk_1.default.gray(' - Exit SnapCommit\n'));
|
|
179
|
+
console.log(chalk_1.default.gray('💡 I\'ll show you what I\'ll do before executing anything!\n'));
|
|
224
180
|
rl.prompt();
|
|
225
181
|
return;
|
|
226
182
|
}
|