@snapcommit/cli 2.0.4 → 2.1.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.
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  /**
3
3
  * Cursor-style natural language Git assistant
4
- * Shows preview, asks confirmation, handles errors automatically
4
+ * DEAD SIMPLE: Check status Show changes → Commit → Push → Done!
5
5
  */
6
6
  var __importDefault = (this && this.__importDefault) || function (mod) {
7
7
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -17,128 +17,62 @@ async function executeCursorStyle(userInput) {
17
17
  console.log(chalk_1.default.red('\n❌ Not a git repository\n'));
18
18
  return;
19
19
  }
20
- // Get AI interpretation of the request
21
- console.log(chalk_1.default.blue('\n✨ Understanding your request...\n'));
22
- const plan = await interpretRequest(userInput);
23
- if (!plan) {
24
- console.log(chalk_1.default.red(' Could not understand the request\n'));
20
+ // Check if there are any changes first
21
+ const status = (0, git_1.getGitStatus)();
22
+ const hasChanges = status.staged > 0 || status.unstaged > 0 || status.untracked > 0;
23
+ if (!hasChanges) {
24
+ console.log(chalk_1.default.gray('\n✓ Branch clean - no changes to commit\n'));
25
25
  return;
26
26
  }
27
- // Show the execution plan
28
- console.log(chalk_1.default.bold('📋 Here\'s what I\'ll do:\n'));
29
- plan.actions.forEach((action, i) => {
30
- console.log(chalk_1.default.gray(` ${i + 1}. `) + chalk_1.default.white(action.description));
31
- });
27
+ // Show what changed
28
+ console.log(chalk_1.default.blue('\n📦 Changes detected:\n'));
29
+ if (status.unstaged > 0)
30
+ console.log(chalk_1.default.yellow(` ${status.unstaged} modified`));
31
+ if (status.untracked > 0)
32
+ console.log(chalk_1.default.yellow(` • ${status.untracked} new`));
33
+ if (status.staged > 0)
34
+ console.log(chalk_1.default.green(` • ${status.staged} staged`));
32
35
  console.log();
33
- // If commit is involved, show the AI-generated message
34
- if (plan.commitMessage) {
35
- console.log(chalk_1.default.gray('📝 Commit message: ') + chalk_1.default.cyan(`"${plan.commitMessage}"`));
36
- console.log();
37
- }
38
- // Ask for confirmation
39
- const needsConfirm = plan.actions.some(a => a.requiresConfirmation);
40
- if (needsConfirm) {
41
- const confirmOptions = plan.commitMessage
42
- ? chalk_1.default.yellow('Continue? (Y/n/e to edit message): ')
43
- : chalk_1.default.yellow('Continue? (Y/n): ');
44
- const answer = await askQuestion(confirmOptions);
45
- if (answer.toLowerCase() === 'n') {
46
- console.log(chalk_1.default.gray('\n✗ Cancelled\n'));
47
- return;
48
- }
49
- if (answer.toLowerCase() === 'e' && plan.commitMessage) {
50
- plan.commitMessage = await editMessage(plan.commitMessage);
51
- }
36
+ // Stage everything
37
+ try {
38
+ (0, git_1.stageAllChanges)();
52
39
  }
53
- // Execute the plan
54
- console.log(chalk_1.default.blue('\n⚙️ Executing...\n'));
55
- for (const action of plan.actions) {
56
- try {
57
- await executeAction(action, plan.commitMessage);
58
- }
59
- catch (error) {
60
- // Try to auto-fix common errors
61
- const fixed = await tryAutoFix(error, action);
62
- if (!fixed) {
63
- console.log(chalk_1.default.red(`\n❌ Error: ${error.message}\n`));
64
- console.log(chalk_1.default.yellow('💡 Try: "undo last change" to revert\n'));
65
- return;
66
- }
67
- }
40
+ catch (error) {
41
+ console.log(chalk_1.default.red(`❌ Failed to stage changes: ${error.message}\n`));
42
+ return;
68
43
  }
69
- console.log(chalk_1.default.green('\n✅ All done!\n'));
70
- }
71
- async function interpretRequest(userInput) {
72
- // This will call the backend AI to interpret the request
73
- // For now, let's handle some common patterns
74
- const input = userInput.toLowerCase();
75
- const actions = [];
76
- let commitMessage;
77
- // "commit and push" pattern
78
- if (input.includes('commit') && input.includes('push')) {
79
- // Generate commit message
80
- const diff = await getChangeDiff();
81
- if (diff) {
82
- commitMessage = await generateCommitMessage(diff);
83
- }
84
- actions.push({
85
- type: 'stage',
86
- description: 'Stage all changes',
87
- requiresConfirmation: false,
88
- });
89
- actions.push({
90
- type: 'commit',
91
- description: `Commit with message: "${commitMessage || 'Update'}"`,
92
- requiresConfirmation: true,
93
- requiresCommitMessage: true,
94
- });
95
- actions.push({
96
- type: 'push',
97
- description: 'Push to origin',
98
- command: 'git push',
99
- requiresConfirmation: true,
100
- });
101
- return {
102
- actions,
103
- commitMessage,
104
- explanation: 'Stage all changes, commit with AI-generated message, and push to remote',
105
- };
44
+ // Generate commit message
45
+ console.log(chalk_1.default.blue('🤖 Generating commit message...'));
46
+ const diff = (0, git_1.getGitDiff)(true);
47
+ const commitMessage = await generateCommitMessage(diff);
48
+ console.log(chalk_1.default.green(`\n📝 ${commitMessage.split('\n')[0]}\n`));
49
+ // Commit
50
+ try {
51
+ (0, child_process_1.execSync)(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, { encoding: 'utf-8', stdio: 'pipe' });
52
+ console.log(chalk_1.default.green('✓ Committed'));
106
53
  }
107
- // "commit" only
108
- if (input.includes('commit') && !input.includes('push')) {
109
- const diff = await getChangeDiff();
110
- if (diff) {
111
- commitMessage = await generateCommitMessage(diff);
112
- }
113
- actions.push({
114
- type: 'stage',
115
- description: 'Stage all changes',
116
- requiresConfirmation: false,
117
- });
118
- actions.push({
119
- type: 'commit',
120
- description: `Commit with message: "${commitMessage || 'Update'}"`,
121
- requiresConfirmation: true,
122
- requiresCommitMessage: true,
123
- });
124
- return {
125
- actions,
126
- commitMessage,
127
- explanation: 'Stage and commit changes with AI-generated message',
128
- };
54
+ catch (error) {
55
+ console.log(chalk_1.default.red(`❌ Commit failed: ${error.message}\n`));
56
+ return;
129
57
  }
130
- // Let the AI handle complex requests
131
- return await getAIInterpretation(userInput);
132
- }
133
- async function getChangeDiff() {
58
+ // Push
134
59
  try {
135
- (0, git_1.stageAllChanges)();
136
- return (0, git_1.getGitDiff)(true);
60
+ console.log(chalk_1.default.blue('⬆️ Pushing to remote...'));
61
+ (0, child_process_1.execSync)('git push', { encoding: 'utf-8', stdio: 'pipe' });
62
+ console.log(chalk_1.default.green('✓ Pushed\n'));
137
63
  }
138
- catch {
139
- return null;
64
+ catch (error) {
65
+ // If push fails (e.g., no remote), that's okay
66
+ if (error.message.includes('no configured push destination')) {
67
+ console.log(chalk_1.default.yellow('⚠️ No remote configured - changes committed locally\n'));
68
+ }
69
+ else {
70
+ console.log(chalk_1.default.yellow(`⚠️ Push failed: ${error.message}\n`));
71
+ }
140
72
  }
73
+ console.log(chalk_1.default.green('✅ Done!\n'));
141
74
  }
75
+ // All removed - we're keeping it SUPER simple now!
142
76
  async function generateCommitMessage(diff) {
143
77
  const token = (0, auth_1.getToken)();
144
78
  if (!token) {
@@ -171,139 +105,4 @@ async function generateCommitMessage(diff) {
171
105
  return 'Update changes';
172
106
  }
173
107
  }
174
- async function getAIInterpretation(userInput) {
175
- const token = (0, auth_1.getToken)();
176
- if (!token)
177
- return null;
178
- try {
179
- const currentBranch = (0, git_1.getCurrentBranch)();
180
- const status = (0, git_1.getGitStatus)();
181
- const response = await fetch('https://snapcommit.dev/api/ai/interpret', {
182
- method: 'POST',
183
- headers: { 'Content-Type': 'application/json' },
184
- body: JSON.stringify({
185
- userInput,
186
- token,
187
- context: {
188
- currentBranch,
189
- hasUncommittedChanges: status.unstaged > 0 || status.untracked > 0,
190
- lastCommitHash: (0, child_process_1.execSync)('git log -1 --format=%H 2>/dev/null || echo ""', { encoding: 'utf-8' }).trim(),
191
- remoteBranch: (0, child_process_1.execSync)('git rev-parse --abbrev-ref @{upstream} 2>/dev/null || echo ""', { encoding: 'utf-8' }).trim(),
192
- },
193
- }),
194
- });
195
- const data = await response.json();
196
- // Convert AI intent to execution plan
197
- // This is a simplified version - in production, this would be more sophisticated
198
- return convertIntentToPlan(data.intent);
199
- }
200
- catch {
201
- return null;
202
- }
203
- }
204
- function convertIntentToPlan(intent) {
205
- // Convert the AI intent format to our execution plan format
206
- // This bridges the existing intent format with the new Cursor-style execution
207
- if (!intent || !intent.gitCommands)
208
- return null;
209
- const actions = intent.gitCommands.map((cmd, i) => ({
210
- type: inferActionType(cmd),
211
- description: intent.explanation || `Execute: ${cmd}`,
212
- command: cmd,
213
- requiresConfirmation: intent.needsConfirmation || intent.riskLevel !== 'safe',
214
- }));
215
- return {
216
- actions,
217
- explanation: intent.explanation,
218
- };
219
- }
220
- function inferActionType(command) {
221
- if (command.includes('git add'))
222
- return 'stage';
223
- if (command.includes('git commit'))
224
- return 'commit';
225
- if (command.includes('git push'))
226
- return 'push';
227
- if (command.includes('git checkout') || command.includes('git switch'))
228
- return 'checkout';
229
- if (command.includes('git merge'))
230
- return 'merge';
231
- if (command.includes('git reset'))
232
- return 'reset';
233
- if (command.includes('git branch'))
234
- return 'branch';
235
- if (command.includes('git pull'))
236
- return 'pull';
237
- if (command.includes('git rebase'))
238
- return 'rebase';
239
- if (command.includes('git cherry-pick'))
240
- return 'cherry-pick';
241
- return 'stage';
242
- }
243
- async function executeAction(action, commitMessage) {
244
- switch (action.type) {
245
- case 'stage':
246
- (0, git_1.stageAllChanges)();
247
- console.log(chalk_1.default.green(' ✓ Staged all changes'));
248
- break;
249
- case 'commit':
250
- if (commitMessage) {
251
- (0, child_process_1.execSync)(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, { encoding: 'utf-8' });
252
- console.log(chalk_1.default.green(` ✓ Committed`));
253
- }
254
- break;
255
- case 'push':
256
- (0, child_process_1.execSync)('git push', { encoding: 'utf-8', stdio: 'pipe' });
257
- console.log(chalk_1.default.green(' ✓ Pushed to remote'));
258
- break;
259
- default:
260
- if (action.command) {
261
- (0, child_process_1.execSync)(action.command, { encoding: 'utf-8', stdio: 'pipe' });
262
- console.log(chalk_1.default.green(` ✓ ${action.description}`));
263
- }
264
- break;
265
- }
266
- }
267
- async function tryAutoFix(error, action) {
268
- const errorMsg = error.message?.toLowerCase() || '';
269
- // Handle "no remote configured"
270
- if (errorMsg.includes('no configured push destination')) {
271
- console.log(chalk_1.default.yellow('\n⚠️ No remote repository configured'));
272
- console.log(chalk_1.default.gray(' You need to add a remote first\n'));
273
- return false;
274
- }
275
- // Handle merge conflicts
276
- if (errorMsg.includes('conflict')) {
277
- console.log(chalk_1.default.yellow('\n⚠️ Merge conflict detected'));
278
- console.log(chalk_1.default.gray(' Use: "resolve conflicts" to fix\n'));
279
- return false;
280
- }
281
- // Handle auth failures
282
- if (errorMsg.includes('authentication') || errorMsg.includes('permission denied')) {
283
- console.log(chalk_1.default.yellow('\n⚠️ Authentication failed'));
284
- console.log(chalk_1.default.gray(' Check your Git credentials\n'));
285
- return false;
286
- }
287
- return false;
288
- }
289
- function askQuestion(query) {
290
- return new Promise((resolve) => {
291
- process.stdout.write(query);
292
- process.stdin.setRawMode(false);
293
- process.stdin.resume();
294
- process.stdin.setEncoding('utf8');
295
- const onData = (data) => {
296
- process.stdin.removeListener('data', onData);
297
- process.stdin.pause();
298
- resolve(data.toString().trim());
299
- };
300
- process.stdin.once('data', onData);
301
- });
302
- }
303
- async function editMessage(originalMessage) {
304
- console.log(chalk_1.default.cyan('\n✏️ Edit commit message:\n'));
305
- console.log(chalk_1.default.gray(' (Press Enter to keep, or type new message)\n'));
306
- console.log(chalk_1.default.white(` Current: ${chalk_1.default.cyan(originalMessage)}\n`));
307
- const newMessage = await askQuestion(chalk_1.default.yellow(' New message: '));
308
- return newMessage.trim() || originalMessage;
309
- }
108
+ // All complex logic removed - keeping it DEAD SIMPLE!
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snapcommit/cli",
3
- "version": "2.0.4",
3
+ "version": "2.1.0",
4
4
  "description": "Instant AI commits. Beautiful progress tracking. Never write commit messages again.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {