@snapcommit/cli 2.0.5 → 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 };
@@ -10,7 +10,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.executeCursorStyle = executeCursorStyle;
11
11
  const chalk_1 = __importDefault(require("chalk"));
12
12
  const child_process_1 = require("child_process");
13
- const readline_1 = __importDefault(require("readline"));
14
13
  const git_1 = require("../utils/git");
15
14
  const auth_1 = require("../lib/auth");
16
15
  async function executeCursorStyle(userInput) {
@@ -18,132 +17,62 @@ async function executeCursorStyle(userInput) {
18
17
  console.log(chalk_1.default.red('\n❌ Not a git repository\n'));
19
18
  return;
20
19
  }
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'));
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'));
26
25
  return;
27
26
  }
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
- });
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`));
33
35
  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 (natural language!)
40
- const needsConfirm = plan.actions.some(a => a.requiresConfirmation);
41
- if (needsConfirm) {
42
- const confirmPrompt = plan.commitMessage
43
- ? chalk_1.default.cyan('What next? ') + chalk_1.default.gray('(') + chalk_1.default.white('continue') + chalk_1.default.gray(' • ') + chalk_1.default.white('cancel') + chalk_1.default.gray(' • ') + chalk_1.default.white('edit message') + chalk_1.default.gray('): ')
44
- : chalk_1.default.cyan('What next? ') + chalk_1.default.gray('(') + chalk_1.default.white('continue') + chalk_1.default.gray(' • ') + chalk_1.default.white('cancel') + chalk_1.default.gray('): ');
45
- const answer = await askQuestion(confirmPrompt);
46
- const input = answer.toLowerCase().trim();
47
- // Cancel commands
48
- if (input === 'cancel' || input === 'no' || input === 'n' || input === 'stop' || input === 'abort') {
49
- console.log(chalk_1.default.gray('\n✗ Cancelled\n'));
50
- return;
51
- }
52
- // Edit commands
53
- if (plan.commitMessage && (input === 'edit' || input === 'e' || input === 'change' || input === 'edit message')) {
54
- plan.commitMessage = await editMessage(plan.commitMessage);
55
- }
56
- // Everything else (including "continue", "yes", "go ahead", "do it", "y", or just Enter) → proceed
36
+ // Stage everything
37
+ try {
38
+ (0, git_1.stageAllChanges)();
57
39
  }
58
- // Execute the plan
59
- console.log(chalk_1.default.blue('\n⚙️ Executing...\n'));
60
- for (const action of plan.actions) {
61
- try {
62
- await executeAction(action, plan.commitMessage);
63
- }
64
- catch (error) {
65
- // Try to auto-fix common errors
66
- const fixed = await tryAutoFix(error, action);
67
- if (!fixed) {
68
- console.log(chalk_1.default.red(`\n❌ Error: ${error.message}\n`));
69
- console.log(chalk_1.default.yellow('💡 Try: "undo last change" to revert\n'));
70
- return;
71
- }
72
- }
40
+ catch (error) {
41
+ console.log(chalk_1.default.red(`❌ Failed to stage changes: ${error.message}\n`));
42
+ return;
73
43
  }
74
- console.log(chalk_1.default.green('\n✅ All done!\n'));
75
- }
76
- async function interpretRequest(userInput) {
77
- // This will call the backend AI to interpret the request
78
- // For now, let's handle some common patterns
79
- const input = userInput.toLowerCase();
80
- const actions = [];
81
- let commitMessage;
82
- // "commit and push" pattern
83
- if (input.includes('commit') && input.includes('push')) {
84
- // Generate commit message
85
- const diff = await getChangeDiff();
86
- if (diff) {
87
- commitMessage = await generateCommitMessage(diff);
88
- }
89
- actions.push({
90
- type: 'stage',
91
- description: 'Stage all changes',
92
- requiresConfirmation: false,
93
- });
94
- actions.push({
95
- type: 'commit',
96
- description: `Commit with message: "${commitMessage || 'Update'}"`,
97
- requiresConfirmation: true,
98
- requiresCommitMessage: true,
99
- });
100
- actions.push({
101
- type: 'push',
102
- description: 'Push to origin',
103
- command: 'git push',
104
- requiresConfirmation: true,
105
- });
106
- return {
107
- actions,
108
- commitMessage,
109
- explanation: 'Stage all changes, commit with AI-generated message, and push to remote',
110
- };
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'));
111
53
  }
112
- // "commit" only
113
- if (input.includes('commit') && !input.includes('push')) {
114
- const diff = await getChangeDiff();
115
- if (diff) {
116
- commitMessage = await generateCommitMessage(diff);
117
- }
118
- actions.push({
119
- type: 'stage',
120
- description: 'Stage all changes',
121
- requiresConfirmation: false,
122
- });
123
- actions.push({
124
- type: 'commit',
125
- description: `Commit with message: "${commitMessage || 'Update'}"`,
126
- requiresConfirmation: true,
127
- requiresCommitMessage: true,
128
- });
129
- return {
130
- actions,
131
- commitMessage,
132
- explanation: 'Stage and commit changes with AI-generated message',
133
- };
54
+ catch (error) {
55
+ console.log(chalk_1.default.red(`❌ Commit failed: ${error.message}\n`));
56
+ return;
134
57
  }
135
- // Let the AI handle complex requests
136
- return await getAIInterpretation(userInput);
137
- }
138
- async function getChangeDiff() {
58
+ // Push
139
59
  try {
140
- (0, git_1.stageAllChanges)();
141
- 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'));
142
63
  }
143
- catch {
144
- 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
+ }
145
72
  }
73
+ console.log(chalk_1.default.green('✅ Done!\n'));
146
74
  }
75
+ // All removed - we're keeping it SUPER simple now!
147
76
  async function generateCommitMessage(diff) {
148
77
  const token = (0, auth_1.getToken)();
149
78
  if (!token) {
@@ -176,141 +105,4 @@ async function generateCommitMessage(diff) {
176
105
  return 'Update changes';
177
106
  }
178
107
  }
179
- async function getAIInterpretation(userInput) {
180
- const token = (0, auth_1.getToken)();
181
- if (!token)
182
- return null;
183
- try {
184
- const currentBranch = (0, git_1.getCurrentBranch)();
185
- const status = (0, git_1.getGitStatus)();
186
- const response = await fetch('https://snapcommit.dev/api/ai/interpret', {
187
- method: 'POST',
188
- headers: { 'Content-Type': 'application/json' },
189
- body: JSON.stringify({
190
- userInput,
191
- token,
192
- context: {
193
- currentBranch,
194
- hasUncommittedChanges: status.unstaged > 0 || status.untracked > 0,
195
- lastCommitHash: (0, child_process_1.execSync)('git log -1 --format=%H 2>/dev/null || echo ""', { encoding: 'utf-8' }).trim(),
196
- remoteBranch: (0, child_process_1.execSync)('git rev-parse --abbrev-ref @{upstream} 2>/dev/null || echo ""', { encoding: 'utf-8' }).trim(),
197
- },
198
- }),
199
- });
200
- const data = await response.json();
201
- // Convert AI intent to execution plan
202
- // This is a simplified version - in production, this would be more sophisticated
203
- return convertIntentToPlan(data.intent);
204
- }
205
- catch {
206
- return null;
207
- }
208
- }
209
- function convertIntentToPlan(intent) {
210
- // Convert the AI intent format to our execution plan format
211
- // This bridges the existing intent format with the new Cursor-style execution
212
- if (!intent || !intent.gitCommands)
213
- return null;
214
- const actions = intent.gitCommands.map((cmd, i) => ({
215
- type: inferActionType(cmd),
216
- description: intent.explanation || `Execute: ${cmd}`,
217
- command: cmd,
218
- requiresConfirmation: intent.needsConfirmation || intent.riskLevel !== 'safe',
219
- }));
220
- return {
221
- actions,
222
- explanation: intent.explanation,
223
- };
224
- }
225
- function inferActionType(command) {
226
- if (command.includes('git add'))
227
- return 'stage';
228
- if (command.includes('git commit'))
229
- return 'commit';
230
- if (command.includes('git push'))
231
- return 'push';
232
- if (command.includes('git checkout') || command.includes('git switch'))
233
- return 'checkout';
234
- if (command.includes('git merge'))
235
- return 'merge';
236
- if (command.includes('git reset'))
237
- return 'reset';
238
- if (command.includes('git branch'))
239
- return 'branch';
240
- if (command.includes('git pull'))
241
- return 'pull';
242
- if (command.includes('git rebase'))
243
- return 'rebase';
244
- if (command.includes('git cherry-pick'))
245
- return 'cherry-pick';
246
- return 'stage';
247
- }
248
- async function executeAction(action, commitMessage) {
249
- switch (action.type) {
250
- case 'stage':
251
- (0, git_1.stageAllChanges)();
252
- console.log(chalk_1.default.green(' ✓ Staged all changes'));
253
- break;
254
- case 'commit':
255
- if (commitMessage) {
256
- (0, child_process_1.execSync)(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, { encoding: 'utf-8' });
257
- console.log(chalk_1.default.green(` ✓ Committed`));
258
- }
259
- break;
260
- case 'push':
261
- (0, child_process_1.execSync)('git push', { encoding: 'utf-8', stdio: 'pipe' });
262
- console.log(chalk_1.default.green(' ✓ Pushed to remote'));
263
- break;
264
- default:
265
- if (action.command) {
266
- (0, child_process_1.execSync)(action.command, { encoding: 'utf-8', stdio: 'pipe' });
267
- console.log(chalk_1.default.green(` ✓ ${action.description}`));
268
- }
269
- break;
270
- }
271
- }
272
- async function tryAutoFix(error, action) {
273
- const errorMsg = error.message?.toLowerCase() || '';
274
- // Handle "no remote configured"
275
- if (errorMsg.includes('no configured push destination')) {
276
- console.log(chalk_1.default.yellow('\n⚠️ No remote repository configured'));
277
- console.log(chalk_1.default.gray(' You need to add a remote first\n'));
278
- return false;
279
- }
280
- // Handle merge conflicts
281
- if (errorMsg.includes('conflict')) {
282
- console.log(chalk_1.default.yellow('\n⚠️ Merge conflict detected'));
283
- console.log(chalk_1.default.gray(' Use: "resolve conflicts" to fix\n'));
284
- return false;
285
- }
286
- // Handle auth failures
287
- if (errorMsg.includes('authentication') || errorMsg.includes('permission denied')) {
288
- console.log(chalk_1.default.yellow('\n⚠️ Authentication failed'));
289
- console.log(chalk_1.default.gray(' Check your Git credentials\n'));
290
- return false;
291
- }
292
- return false;
293
- }
294
- function askQuestion(query) {
295
- const rl = readline_1.default.createInterface({
296
- input: process.stdin,
297
- output: process.stdout,
298
- terminal: false, // Don't process terminal escape sequences
299
- });
300
- return new Promise((resolve) => {
301
- // Write prompt manually
302
- process.stdout.write(query);
303
- // Listen for ONE line of input
304
- rl.once('line', (answer) => {
305
- rl.close();
306
- resolve(answer.trim());
307
- });
308
- });
309
- }
310
- async function editMessage(originalMessage) {
311
- console.log(chalk_1.default.cyan('\n✏️ Edit commit message:\n'));
312
- console.log(chalk_1.default.gray(' (Press Enter to keep, or type new message)\n'));
313
- console.log(chalk_1.default.white(` Current: ${chalk_1.default.cyan(originalMessage)}\n`));
314
- const newMessage = await askQuestion(chalk_1.default.yellow(' New message: '));
315
- return newMessage.trim() || originalMessage;
316
- }
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.5",
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": {