@snapcommit/cli 3.11.6 → 3.11.7

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.
@@ -54,99 +54,64 @@ async function executeCursorStyle(userInput) {
54
54
  console.log(chalk_1.default.red('\n❌ Not a git repository\n'));
55
55
  return;
56
56
  }
57
- // Fast-path for common commands (pattern matching) - Cursor does this!
58
- const handled = await tryQuickCommands(userInput);
59
- if (handled) {
60
- return;
61
- }
62
- // Everything else goes through AI
57
+ // EVERYTHING goes through AI - that's the point of SnapCommit!
63
58
  await handleAICommand(userInput);
64
59
  }
65
60
  /**
66
- * Try to handle common commands with pattern matching (FAST PATH)
67
- * Returns true if handled, false if should go to AI
61
+ * Generate conversational feedback based on AI intent
68
62
  */
69
- async function tryQuickCommands(input) {
70
- const lower = input.toLowerCase().trim();
71
- // Status commands
72
- if (lower === 'status' || lower === 'show status' || lower === 'what changed' || lower === 'git status') {
73
- await showStatus();
74
- return true;
75
- }
76
- // Stage commands - MUST handle before AI!
77
- if (lower.startsWith('stage')) {
78
- const rest = input.replace(/^stage\s*/i, '').trim();
79
- const ALL_KEYWORDS = ['all', 'all changes', 'everything', 'everything please', 'it all', 'them all'];
80
- try {
81
- if (!rest || ALL_KEYWORDS.includes(rest.toLowerCase())) {
82
- (0, child_process_1.execSync)('git add -A', { stdio: 'ignore' });
83
- console.log(chalk_1.default.green('\n✓ Staged all changes\n'));
84
- }
85
- else {
86
- // Parse file list (handle "and", commas, etc.)
87
- const files = rest
88
- .replace(/\sand\s/gi, ',')
89
- .split(',')
90
- .map((segment) => segment
91
- .replace(/^(the|file|files)\s+/i, '')
92
- .replace(/\s+please$/i, '')
93
- .trim())
94
- .filter(Boolean);
95
- if (files.length === 0) {
96
- console.log(chalk_1.default.yellow('\n⚠️ No files specified to stage.\n'));
97
- return true;
98
- }
99
- files.forEach((file) => {
100
- const escaped = file.replace(/(["\\$`])/g, '\\$1');
101
- (0, child_process_1.execSync)(`git add -- "${escaped}"`, { stdio: 'ignore' });
102
- });
103
- console.log(chalk_1.default.green(`\n✓ Staged ${files.length} ${files.length === 1 ? 'file' : 'files'}: ${files.join(', ')}\n`));
104
- }
105
- }
106
- catch (error) {
107
- console.log(chalk_1.default.red(`\n❌ Failed to stage: ${error.message}\n`));
63
+ function getConversationalMessage(intent, userInput) {
64
+ const action = intent.action?.toLowerCase() || '';
65
+ const commands = intent.gitCommands || [];
66
+ // Extract file names from commands
67
+ const fileMatch = commands[0]?.match(/(?:diff|add|checkout|log)\s+(?:--\s+)?([^\s]+)/);
68
+ const fileName = fileMatch ? fileMatch[1] : '';
69
+ // Conversational messages based on action
70
+ if (action === 'status') {
71
+ return 'Got it! Let me check your repo status...';
72
+ }
73
+ if (action === 'diff') {
74
+ if (fileName) {
75
+ return `Perfect! Showing you what changed in ${chalk_1.default.cyan(fileName)}...`;
108
76
  }
109
- return true;
77
+ return 'Alright, showing you the changes...';
110
78
  }
111
- // Push commands
112
- if (lower === 'push' || lower === 'push it' || lower === 'git push') {
113
- try {
114
- console.log(chalk_1.default.gray('\n📤 Pushing to remote...\n'));
115
- (0, child_process_1.execSync)('git push', { stdio: 'inherit' });
116
- console.log(chalk_1.default.green('\n✅ Pushed!\n'));
117
- return true;
118
- }
119
- catch (error) {
120
- console.log(chalk_1.default.red('\n❌ Push failed\n'));
121
- return true;
122
- }
79
+ if (action === 'log') {
80
+ return 'Sure thing! Pulling up your recent commits...';
123
81
  }
124
- // Pull commands
125
- if (lower === 'pull' || lower === 'pull latest' || lower === 'git pull') {
126
- try {
127
- console.log(chalk_1.default.gray('\n📥 Pulling from remote...\n'));
128
- (0, child_process_1.execSync)('git pull', { stdio: 'inherit' });
129
- console.log(chalk_1.default.green('\n✅ Pulled!\n'));
130
- return true;
131
- }
132
- catch (error) {
133
- console.log(chalk_1.default.red('\n❌ Pull failed\n'));
134
- return true;
82
+ if (action === 'commit') {
83
+ if (intent.shouldPush) {
84
+ return 'Got it! I\'ll commit your changes and push them up...';
135
85
  }
86
+ return 'Okay! Let me commit those changes for you...';
136
87
  }
137
- // Diff commands
138
- if (lower === 'diff' || lower === 'show diff' || lower === 'what changed' || lower === 'changes') {
139
- try {
140
- (0, child_process_1.execSync)('git diff', { stdio: 'inherit' });
141
- return true;
142
- }
143
- catch (error) {
144
- console.log(chalk_1.default.red('\n❌ Failed to show diff\n'));
145
- return true;
88
+ if (action === 'push') {
89
+ return 'Pushing your changes to the remote now...';
90
+ }
91
+ if (action === 'branch') {
92
+ if (commands[0]?.includes('-b')) {
93
+ const branchName = commands[0].match(/checkout -b ([^\s]+)/)?.[1];
94
+ return `Creating and switching to branch ${chalk_1.default.cyan(branchName)}...`;
146
95
  }
96
+ return 'Switching branches...';
147
97
  }
148
- // Not handled - let AI process it
149
- return false;
98
+ if (action === 'merge') {
99
+ return 'Alright, merging that branch...';
100
+ }
101
+ if (action === 'stash') {
102
+ return 'Stashing your changes...';
103
+ }
104
+ if (action === 'pr_create') {
105
+ return 'Perfect! Creating a pull request for you...';
106
+ }
107
+ if (action === 'pr_list') {
108
+ return 'Let me grab your open pull requests...';
109
+ }
110
+ if (action === 'ci_check') {
111
+ return 'Checking CI status...';
112
+ }
113
+ // Default fallback
114
+ return 'On it!';
150
115
  }
151
116
  /**
152
117
  * AI-powered command handler - CURSOR-STYLE!
@@ -158,17 +123,18 @@ async function handleAICommand(userInput) {
158
123
  console.log(chalk_1.default.red('\n❌ Not authenticated\n'));
159
124
  return;
160
125
  }
126
+ // Show thinking indicator
127
+ console.log(chalk_1.default.gray('🤔 Understanding your command...\n'));
161
128
  // Get AI interpretation for EVERYTHING
162
129
  const intent = await getAIInterpretation(userInput, token);
163
130
  if (!intent) {
164
- console.log(chalk_1.default.red('\nCould not understand'));
165
- console.log(chalk_1.default.gray(' Try: "commit and push" or "show changes"\n'));
131
+ console.log(chalk_1.default.red('❌ Hmm, I couldn\'t quite understand that.'));
132
+ console.log(chalk_1.default.gray(' 💡 Try something like: "commit and push" or "show me what changed"\n'));
166
133
  return;
167
134
  }
168
- // Debug mode (if needed)
169
- if (process.env.DEBUG) {
170
- console.log(chalk_1.default.gray(`[DEBUG] ${JSON.stringify(intent, null, 2)}`));
171
- }
135
+ // Conversational feedback based on what we're doing
136
+ const actionMsg = getConversationalMessage(intent, userInput);
137
+ console.log(chalk_1.default.blue(`✨ ${actionMsg}\n`));
172
138
  // Execute based on type
173
139
  if (intent.type === 'git') {
174
140
  // Status check
@@ -176,6 +142,17 @@ async function handleAICommand(userInput) {
176
142
  await showStatus();
177
143
  return;
178
144
  }
145
+ // Diff check - show changes
146
+ if (intent.action === 'diff' || intent.action === 'log') {
147
+ if (intent.gitCommands && intent.gitCommands.length > 0) {
148
+ await executeGitCommands(intent.gitCommands);
149
+ }
150
+ else {
151
+ console.log(chalk_1.default.yellow('⚠️ I understood what you want, but couldn\'t generate the right git command.'));
152
+ console.log(chalk_1.default.gray(' 💡 Try: "show diff for test1.txt" or "what changed in this file?"\n'));
153
+ }
154
+ return;
155
+ }
179
156
  // Commit/push flow
180
157
  if (intent.action === 'commit' || intent.action === 'push' ||
181
158
  (intent.gitCommands && intent.gitCommands.some((cmd) => cmd.includes('commit')))) {
@@ -189,6 +166,7 @@ async function handleAICommand(userInput) {
189
166
  }
190
167
  else {
191
168
  console.log(chalk_1.default.yellow('\n⚠️ No action taken\n'));
169
+ console.log(chalk_1.default.gray(` Debug: action=${intent.action}, gitCommands=${JSON.stringify(intent.gitCommands)}\n`));
192
170
  }
193
171
  }
194
172
  else if (intent.type === 'github') {
@@ -624,8 +602,26 @@ async function executeGitCommands(commands) {
624
602
  console.log(chalk_1.default.cyan('\n' + output.trim() + '\n'));
625
603
  }
626
604
  else if (cmd.includes('git diff') && !cmd.includes('--name-only')) {
627
- if (output.trim()) {
628
- console.log(chalk_1.default.gray('\n' + output.trim().substring(0, 500) + (output.length > 500 ? '...' : '') + '\n'));
605
+ let diffOutput = output.trim();
606
+ // If no diff (possibly staged), try --cached
607
+ if (!diffOutput) {
608
+ const cachedCmd = cmd.replace('git diff', 'git diff --cached');
609
+ try {
610
+ const cachedOutput = (0, child_process_1.execSync)(cachedCmd, { encoding: 'utf-8', stdio: 'pipe' }).trim();
611
+ if (cachedOutput) {
612
+ diffOutput = cachedOutput;
613
+ console.log(chalk_1.default.gray('\nShowing staged changes (git diff --cached):\n'));
614
+ }
615
+ }
616
+ catch {
617
+ // ignore - we'll handle below
618
+ }
619
+ }
620
+ if (diffOutput) {
621
+ console.log('\n' + diffOutput + '\n');
622
+ }
623
+ else {
624
+ console.log(chalk_1.default.gray('\n(no changes in working tree or staging area)\n'));
629
625
  }
630
626
  }
631
627
  }
@@ -1680,8 +1676,6 @@ async function getAIInterpretation(userInput, token) {
1680
1676
  try {
1681
1677
  const currentBranch = (0, git_1.getCurrentBranch)();
1682
1678
  const status = (0, git_1.getGitStatus)();
1683
- // Show loading indicator for slow AI responses
1684
- console.log(chalk_1.default.blue('🤔 Understanding your command...'));
1685
1679
  const response = await fetch('https://www.snapcommit.dev/api/ai/interpret', {
1686
1680
  method: 'POST',
1687
1681
  headers: { 'Content-Type': 'application/json' },
@@ -1723,7 +1717,7 @@ async function getAIInterpretation(userInput, token) {
1723
1717
  return null;
1724
1718
  }
1725
1719
  // Debug: Show what AI returned
1726
- if (process.env.DEBUG === 'true') {
1720
+ if (process.env.DEBUG === 'true' || process.env.SNAP_DEBUG) {
1727
1721
  console.log(chalk_1.default.gray('[DEBUG] AI Response:'), JSON.stringify(data, null, 2));
1728
1722
  }
1729
1723
  if (!data || !data.intent) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snapcommit/cli",
3
- "version": "3.11.6",
3
+ "version": "3.11.7",
4
4
  "description": "Instant AI commits. Beautiful progress tracking. Never write commit messages again.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {