@snapcommit/cli 3.11.5 → 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,10 +54,65 @@ async function executeCursorStyle(userInput) {
54
54
  console.log(chalk_1.default.red('\n❌ Not a git repository\n'));
55
55
  return;
56
56
  }
57
- // EVERYTHING goes through AI (like Cursor!)
58
- // No shortcuts, no special cases - pure AI interpretation
57
+ // EVERYTHING goes through AI - that's the point of SnapCommit!
59
58
  await handleAICommand(userInput);
60
59
  }
60
+ /**
61
+ * Generate conversational feedback based on AI intent
62
+ */
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)}...`;
76
+ }
77
+ return 'Alright, showing you the changes...';
78
+ }
79
+ if (action === 'log') {
80
+ return 'Sure thing! Pulling up your recent commits...';
81
+ }
82
+ if (action === 'commit') {
83
+ if (intent.shouldPush) {
84
+ return 'Got it! I\'ll commit your changes and push them up...';
85
+ }
86
+ return 'Okay! Let me commit those changes for you...';
87
+ }
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)}...`;
95
+ }
96
+ return 'Switching branches...';
97
+ }
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!';
115
+ }
61
116
  /**
62
117
  * AI-powered command handler - CURSOR-STYLE!
63
118
  * Pure AI interpretation, minimal output, instant feel
@@ -68,17 +123,18 @@ async function handleAICommand(userInput) {
68
123
  console.log(chalk_1.default.red('\n❌ Not authenticated\n'));
69
124
  return;
70
125
  }
126
+ // Show thinking indicator
127
+ console.log(chalk_1.default.gray('🤔 Understanding your command...\n'));
71
128
  // Get AI interpretation for EVERYTHING
72
129
  const intent = await getAIInterpretation(userInput, token);
73
130
  if (!intent) {
74
- console.log(chalk_1.default.red('\nCould not understand'));
75
- 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'));
76
133
  return;
77
134
  }
78
- // Debug mode (if needed)
79
- if (process.env.DEBUG) {
80
- console.log(chalk_1.default.gray(`[DEBUG] ${JSON.stringify(intent, null, 2)}`));
81
- }
135
+ // Conversational feedback based on what we're doing
136
+ const actionMsg = getConversationalMessage(intent, userInput);
137
+ console.log(chalk_1.default.blue(`✨ ${actionMsg}\n`));
82
138
  // Execute based on type
83
139
  if (intent.type === 'git') {
84
140
  // Status check
@@ -86,6 +142,17 @@ async function handleAICommand(userInput) {
86
142
  await showStatus();
87
143
  return;
88
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
+ }
89
156
  // Commit/push flow
90
157
  if (intent.action === 'commit' || intent.action === 'push' ||
91
158
  (intent.gitCommands && intent.gitCommands.some((cmd) => cmd.includes('commit')))) {
@@ -99,6 +166,7 @@ async function handleAICommand(userInput) {
99
166
  }
100
167
  else {
101
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`));
102
170
  }
103
171
  }
104
172
  else if (intent.type === 'github') {
@@ -534,8 +602,26 @@ async function executeGitCommands(commands) {
534
602
  console.log(chalk_1.default.cyan('\n' + output.trim() + '\n'));
535
603
  }
536
604
  else if (cmd.includes('git diff') && !cmd.includes('--name-only')) {
537
- if (output.trim()) {
538
- 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'));
539
625
  }
540
626
  }
541
627
  }
@@ -1590,8 +1676,6 @@ async function getAIInterpretation(userInput, token) {
1590
1676
  try {
1591
1677
  const currentBranch = (0, git_1.getCurrentBranch)();
1592
1678
  const status = (0, git_1.getGitStatus)();
1593
- // Show loading indicator for slow AI responses
1594
- console.log(chalk_1.default.blue('🤔 Understanding your command...'));
1595
1679
  const response = await fetch('https://www.snapcommit.dev/api/ai/interpret', {
1596
1680
  method: 'POST',
1597
1681
  headers: { 'Content-Type': 'application/json' },
@@ -1633,7 +1717,7 @@ async function getAIInterpretation(userInput, token) {
1633
1717
  return null;
1634
1718
  }
1635
1719
  // Debug: Show what AI returned
1636
- if (process.env.DEBUG === 'true') {
1720
+ if (process.env.DEBUG === 'true' || process.env.SNAP_DEBUG) {
1637
1721
  console.log(chalk_1.default.gray('[DEBUG] AI Response:'), JSON.stringify(data, null, 2));
1638
1722
  }
1639
1723
  if (!data || !data.intent) {
package/dist/index.js CHANGED
File without changes
@@ -160,6 +160,9 @@ async function startREPL() {
160
160
  }
161
161
  // Natural language processing
162
162
  try {
163
+ if (process.env.SNAP_DEBUG) {
164
+ console.log(chalk_1.default.gray(`[DEBUG] raw input: ${JSON.stringify(trimmed)}`));
165
+ }
163
166
  await (0, interpreter_1.executeNaturalLanguageCommand)(trimmed, context);
164
167
  }
165
168
  catch (error) {
@@ -51,9 +51,15 @@ const gitAdvanced = __importStar(require("../commands/git-advanced"));
51
51
  async function executeNaturalLanguageCommand(input, context) {
52
52
  // Normalize input (handle references like "that", "it", etc.)
53
53
  const normalizedInput = normalizeInput(input, context);
54
+ if (process.env.SNAP_DEBUG) {
55
+ console.log(chalk_1.default.gray(`[DEBUG] normalized input: ${JSON.stringify(normalizedInput)}`));
56
+ }
54
57
  // Pattern matching for common commands (fast path) - MUST run before AI
55
58
  const handled = await tryQuickCommands(normalizedInput, context);
56
59
  if (handled) {
60
+ if (process.env.SNAP_DEBUG) {
61
+ console.log(chalk_1.default.gray('[DEBUG] handled via quick command'));
62
+ }
57
63
  return;
58
64
  }
59
65
  // Check for clarification needs
@@ -212,6 +218,9 @@ async function tryQuickCommands(input, context) {
212
218
  const rest = input.replace(/^stage\s*/i, '').trim();
213
219
  const ALL_KEYWORDS = ['all', 'all changes', 'everything', 'everything please', 'it all', 'them all'];
214
220
  try {
221
+ if (process.env.SNAP_DEBUG) {
222
+ console.log(chalk_1.default.gray(`[DEBUG] staging rest: ${JSON.stringify(rest)} cwd=${process.cwd()}`));
223
+ }
215
224
  if (!rest || ALL_KEYWORDS.includes(rest.toLowerCase())) {
216
225
  (0, child_process_1.execSync)('git add -A', { stdio: 'ignore' });
217
226
  console.log(chalk_1.default.green('\n✓ Staged all changes\n'));
@@ -229,6 +238,9 @@ async function tryQuickCommands(input, context) {
229
238
  console.log(chalk_1.default.yellow('\n⚠️ No files specified to stage.\n'));
230
239
  return true;
231
240
  }
241
+ if (process.env.SNAP_DEBUG) {
242
+ console.log(chalk_1.default.gray(`[DEBUG] staging files: ${JSON.stringify(files)} cwd=${process.cwd()}`));
243
+ }
232
244
  files.forEach((file) => {
233
245
  const escaped = file.replace(/(["\\$`])/g, '\\$1');
234
246
  (0, child_process_1.execSync)(`git add -- "${escaped}"`, { stdio: 'ignore' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snapcommit/cli",
3
- "version": "3.11.5",
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": {