@snapcommit/cli 2.6.0 → 3.0.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.
- package/dist/commands/cursor-style.js +113 -98
- package/package.json +1 -1
|
@@ -57,25 +57,25 @@ async function executeCursorStyle(userInput) {
|
|
|
57
57
|
await handleAICommand(userInput);
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
|
-
* AI-powered command handler -
|
|
61
|
-
* Pure AI interpretation
|
|
60
|
+
* AI-powered command handler - CURSOR-STYLE!
|
|
61
|
+
* Pure AI interpretation, minimal output, instant feel
|
|
62
62
|
*/
|
|
63
63
|
async function handleAICommand(userInput) {
|
|
64
64
|
const token = (0, auth_1.getToken)();
|
|
65
65
|
if (!token) {
|
|
66
|
-
console.log(chalk_1.default.red('❌ Not authenticated\n'));
|
|
66
|
+
console.log(chalk_1.default.red('\n❌ Not authenticated\n'));
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
69
|
// Get AI interpretation for EVERYTHING
|
|
70
70
|
const intent = await getAIInterpretation(userInput, token);
|
|
71
71
|
if (!intent) {
|
|
72
|
-
console.log(chalk_1.default.red('❌ Could not understand
|
|
73
|
-
console.log(chalk_1.default.gray('
|
|
72
|
+
console.log(chalk_1.default.red('\n❌ Could not understand'));
|
|
73
|
+
console.log(chalk_1.default.gray(' Try: "commit and push" or "show changes"\n'));
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
|
-
// Debug
|
|
76
|
+
// Debug mode (if needed)
|
|
77
77
|
if (process.env.DEBUG) {
|
|
78
|
-
console.log(chalk_1.default.gray(`[DEBUG]
|
|
78
|
+
console.log(chalk_1.default.gray(`[DEBUG] ${JSON.stringify(intent, null, 2)}`));
|
|
79
79
|
}
|
|
80
80
|
// Execute based on type
|
|
81
81
|
if (intent.type === 'git') {
|
|
@@ -84,30 +84,26 @@ async function handleAICommand(userInput) {
|
|
|
84
84
|
await showStatus();
|
|
85
85
|
return;
|
|
86
86
|
}
|
|
87
|
-
//
|
|
87
|
+
// Commit/push flow
|
|
88
88
|
if (intent.action === 'commit' || intent.action === 'push' ||
|
|
89
89
|
(intent.gitCommands && intent.gitCommands.some((cmd) => cmd.includes('commit')))) {
|
|
90
90
|
await executeCommitWithAI(intent);
|
|
91
91
|
return;
|
|
92
92
|
}
|
|
93
|
-
// Other git commands
|
|
93
|
+
// Other git commands (branch, merge, etc.)
|
|
94
94
|
if (intent.gitCommands && intent.gitCommands.length > 0) {
|
|
95
95
|
await executeGitCommands(intent.gitCommands);
|
|
96
|
-
console.log(chalk_1.default.green('
|
|
96
|
+
console.log(chalk_1.default.green('✓\n'));
|
|
97
97
|
}
|
|
98
98
|
else {
|
|
99
|
-
|
|
100
|
-
console.log(chalk_1.default.yellow('⚠️ No commands to execute'));
|
|
101
|
-
console.log(chalk_1.default.gray(`Intent action: ${intent.action || 'none'}`));
|
|
102
|
-
console.log(chalk_1.default.gray(`Git commands: ${intent.gitCommands?.length || 0}\n`));
|
|
99
|
+
console.log(chalk_1.default.yellow('\n⚠️ No action taken\n'));
|
|
103
100
|
}
|
|
104
101
|
}
|
|
105
102
|
else if (intent.type === 'github') {
|
|
106
103
|
await executeGitHubCommand(intent);
|
|
107
|
-
console.log(chalk_1.default.green('✓ Done\n'));
|
|
108
104
|
}
|
|
109
105
|
else {
|
|
110
|
-
console.log(chalk_1.default.yellow(
|
|
106
|
+
console.log(chalk_1.default.yellow(`\n⚠️ Unknown action\n`));
|
|
111
107
|
}
|
|
112
108
|
}
|
|
113
109
|
/**
|
|
@@ -132,8 +128,8 @@ async function showStatus() {
|
|
|
132
128
|
console.log();
|
|
133
129
|
}
|
|
134
130
|
/**
|
|
135
|
-
* Execute commit
|
|
136
|
-
*
|
|
131
|
+
* Execute commit - EXACTLY like Cursor!
|
|
132
|
+
* Minimal friction, one prompt, instant feel
|
|
137
133
|
*/
|
|
138
134
|
async function executeCommitWithAI(intent) {
|
|
139
135
|
const status = (0, git_1.getGitStatus)();
|
|
@@ -142,11 +138,14 @@ async function executeCommitWithAI(intent) {
|
|
|
142
138
|
console.log(chalk_1.default.gray('\n✓ Branch clean\n'));
|
|
143
139
|
return;
|
|
144
140
|
}
|
|
145
|
-
//
|
|
146
|
-
|
|
141
|
+
// Count files
|
|
142
|
+
let fileCount = status.staged + status.unstaged + status.untracked;
|
|
143
|
+
// Show changed files (like Cursor sidebar)
|
|
144
|
+
console.log(chalk_1.default.blue(`\n📦 Changes (${fileCount} ${fileCount === 1 ? 'file' : 'files'}):`));
|
|
147
145
|
try {
|
|
148
146
|
const output = (0, child_process_1.execSync)('git status --short', { encoding: 'utf-8' });
|
|
149
|
-
output.split('\n').filter(line => line.trim()).
|
|
147
|
+
const lines = output.split('\n').filter(line => line.trim()).slice(0, 10); // Show max 10
|
|
148
|
+
lines.forEach(line => {
|
|
150
149
|
const status = line.substring(0, 2);
|
|
151
150
|
const file = line.substring(3);
|
|
152
151
|
if (status.includes('M')) {
|
|
@@ -159,6 +158,9 @@ async function executeCommitWithAI(intent) {
|
|
|
159
158
|
console.log(chalk_1.default.red(` - ${file}`));
|
|
160
159
|
}
|
|
161
160
|
});
|
|
161
|
+
if (fileCount > 10) {
|
|
162
|
+
console.log(chalk_1.default.gray(` ... and ${fileCount - 10} more`));
|
|
163
|
+
}
|
|
162
164
|
}
|
|
163
165
|
catch {
|
|
164
166
|
if (status.unstaged > 0)
|
|
@@ -167,79 +169,40 @@ async function executeCommitWithAI(intent) {
|
|
|
167
169
|
console.log(chalk_1.default.green(` • ${status.untracked} new`));
|
|
168
170
|
}
|
|
169
171
|
console.log();
|
|
170
|
-
//
|
|
171
|
-
const readline = await Promise.resolve().then(() => __importStar(require('readline')));
|
|
172
|
-
const rl = readline.createInterface({
|
|
173
|
-
input: process.stdin,
|
|
174
|
-
output: process.stdout,
|
|
175
|
-
});
|
|
176
|
-
const fileChoice = await new Promise((resolve) => {
|
|
177
|
-
rl.question(chalk_1.default.cyan('What do you want to do? ') + chalk_1.default.gray('(commit all / select files / cancel): '), (ans) => {
|
|
178
|
-
rl.close();
|
|
179
|
-
resolve(ans.toLowerCase().trim());
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
if (fileChoice.includes('cancel') || fileChoice === 'n' || fileChoice === 'no') {
|
|
183
|
-
console.log(chalk_1.default.gray('\n✗ Cancelled\n'));
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
if (fileChoice.includes('select')) {
|
|
187
|
-
console.log(chalk_1.default.yellow('\n💡 Use: ') + chalk_1.default.cyan('git add <files>') + chalk_1.default.yellow(' to stage specific files'));
|
|
188
|
-
console.log(chalk_1.default.gray(' Then run: ') + chalk_1.default.cyan('snap') + chalk_1.default.gray(' and try again\n'));
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
// Stage all (default for "commit all" or just pressing Enter)
|
|
172
|
+
// Stage all
|
|
192
173
|
try {
|
|
193
174
|
(0, git_1.stageAllChanges)();
|
|
194
175
|
}
|
|
195
176
|
catch (error) {
|
|
196
|
-
console.log(chalk_1.default.red(
|
|
177
|
+
console.log(chalk_1.default.red(`❌ ${error.message}\n`));
|
|
197
178
|
return;
|
|
198
179
|
}
|
|
199
|
-
// Generate AI commit message
|
|
200
|
-
console.log(chalk_1.default.blue('🤖 Generating commit message...\n'));
|
|
180
|
+
// Generate AI commit message (like Cursor does instantly)
|
|
201
181
|
const diff = (0, git_1.getGitDiff)(true);
|
|
202
182
|
let commitMessage = await generateCommitMessage(diff);
|
|
203
|
-
// Show message
|
|
204
|
-
console.log(chalk_1.default.cyan('
|
|
205
|
-
console.log(
|
|
206
|
-
|
|
183
|
+
// Show message like Cursor - clean and ready to use
|
|
184
|
+
console.log(chalk_1.default.cyan('🤖 ') + chalk_1.default.white.bold(commitMessage.split('\n')[0]));
|
|
185
|
+
console.log();
|
|
186
|
+
// ONE PROMPT - like Cursor's commit button
|
|
187
|
+
const readline = await Promise.resolve().then(() => __importStar(require('readline')));
|
|
188
|
+
const rl = readline.createInterface({
|
|
207
189
|
input: process.stdin,
|
|
208
190
|
output: process.stdout,
|
|
209
191
|
});
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
resolve(ans.
|
|
192
|
+
const response = await new Promise((resolve) => {
|
|
193
|
+
rl.question(chalk_1.default.gray('→ Press Enter to commit, or edit message: '), (ans) => {
|
|
194
|
+
rl.close();
|
|
195
|
+
resolve(ans.trim());
|
|
214
196
|
});
|
|
215
197
|
});
|
|
216
|
-
//
|
|
217
|
-
if (
|
|
218
|
-
|
|
219
|
-
return;
|
|
198
|
+
// If they typed something, use it. Otherwise use AI message.
|
|
199
|
+
if (response) {
|
|
200
|
+
commitMessage = response;
|
|
220
201
|
}
|
|
221
|
-
|
|
222
|
-
const rl3 = readline.createInterface({
|
|
223
|
-
input: process.stdin,
|
|
224
|
-
output: process.stdout,
|
|
225
|
-
});
|
|
226
|
-
commitMessage = await new Promise((resolve) => {
|
|
227
|
-
rl3.question(chalk_1.default.cyan('Your message: '), (ans) => {
|
|
228
|
-
rl3.close();
|
|
229
|
-
resolve(ans.trim() || commitMessage);
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
console.log(chalk_1.default.green('\n✓ Message updated\n'));
|
|
233
|
-
}
|
|
234
|
-
else if (messageAction && !messageAction.includes('good') && !messageAction.includes('yes') && !messageAction.includes('ok')) {
|
|
235
|
-
// They typed a custom message directly
|
|
236
|
-
commitMessage = messageAction;
|
|
237
|
-
console.log(chalk_1.default.green('\n✓ Using your message\n'));
|
|
238
|
-
}
|
|
239
|
-
// Commit
|
|
202
|
+
// Commit (like Cursor's instant commit)
|
|
240
203
|
try {
|
|
241
204
|
(0, child_process_1.execSync)(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
242
|
-
console.log(chalk_1.default.green(
|
|
205
|
+
console.log(chalk_1.default.green(`\n✓ Committed`));
|
|
243
206
|
}
|
|
244
207
|
catch (error) {
|
|
245
208
|
console.log(chalk_1.default.red(`\n❌ Commit failed: ${error.message}\n`));
|
|
@@ -266,69 +229,121 @@ async function executeCommitWithAI(intent) {
|
|
|
266
229
|
}
|
|
267
230
|
}
|
|
268
231
|
/**
|
|
269
|
-
* Execute Git commands
|
|
232
|
+
* Execute Git commands - Cursor-style (clean, fast, auto-fix)
|
|
270
233
|
*/
|
|
271
234
|
async function executeGitCommands(commands) {
|
|
272
235
|
for (const cmd of commands) {
|
|
273
236
|
try {
|
|
274
|
-
(0, child_process_1.execSync)(cmd, { encoding: 'utf-8', stdio: 'pipe' });
|
|
237
|
+
const output = (0, child_process_1.execSync)(cmd, { encoding: 'utf-8', stdio: 'pipe' });
|
|
238
|
+
// Show meaningful output for certain commands
|
|
239
|
+
if (cmd.includes('git branch') && !cmd.includes('-D')) {
|
|
240
|
+
if (output.trim()) {
|
|
241
|
+
console.log(chalk_1.default.cyan('\n' + output.trim() + '\n'));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
else if (cmd.includes('git log')) {
|
|
245
|
+
console.log(chalk_1.default.cyan('\n' + output.trim() + '\n'));
|
|
246
|
+
}
|
|
247
|
+
else if (cmd.includes('git diff') && !cmd.includes('--name-only')) {
|
|
248
|
+
if (output.trim()) {
|
|
249
|
+
console.log(chalk_1.default.gray('\n' + output.trim().substring(0, 500) + (output.length > 500 ? '...' : '') + '\n'));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
275
252
|
}
|
|
276
253
|
catch (error) {
|
|
277
254
|
// Try to auto-fix common errors
|
|
278
255
|
const fixed = await tryAutoFix(error, cmd);
|
|
279
256
|
if (!fixed) {
|
|
280
|
-
console.log(chalk_1.default.red(
|
|
257
|
+
console.log(chalk_1.default.red(`\n❌ ${error.message}\n`));
|
|
281
258
|
return;
|
|
282
259
|
}
|
|
283
260
|
}
|
|
284
261
|
}
|
|
285
262
|
}
|
|
286
263
|
/**
|
|
287
|
-
* Execute GitHub operations
|
|
264
|
+
* Execute GitHub operations - Cursor-style streamlined!
|
|
288
265
|
*/
|
|
289
266
|
async function executeGitHubCommand(intent) {
|
|
290
267
|
if (!(0, github_connect_1.isGitHubConnected)()) {
|
|
291
|
-
console.log(chalk_1.default.yellow('⚠️ GitHub not connected
|
|
268
|
+
console.log(chalk_1.default.yellow('\n⚠️ GitHub not connected'));
|
|
269
|
+
console.log(chalk_1.default.gray(' Run: ') + chalk_1.default.cyan('snap github connect\n'));
|
|
292
270
|
return;
|
|
293
271
|
}
|
|
294
272
|
try {
|
|
295
273
|
switch (intent.action) {
|
|
296
274
|
case 'pr_create':
|
|
297
|
-
console.log(chalk_1.default.blue('Creating PR...'));
|
|
275
|
+
console.log(chalk_1.default.blue('\n🔄 Creating PR...'));
|
|
298
276
|
const pr = await github.createPullRequest(intent.options || {});
|
|
299
|
-
console.log(chalk_1.default.green(`✓ PR
|
|
277
|
+
console.log(chalk_1.default.green(`✓ PR #${pr.number} created`));
|
|
278
|
+
console.log(chalk_1.default.cyan(` ${pr.html_url}\n`));
|
|
300
279
|
break;
|
|
301
280
|
case 'pr_list':
|
|
302
|
-
console.log(chalk_1.default.blue('Listing PRs...'));
|
|
303
281
|
const prs = await github.listPullRequests({ state: 'open', limit: 10 });
|
|
304
282
|
if (prs.length === 0) {
|
|
305
|
-
console.log(chalk_1.default.gray('No open PRs'));
|
|
283
|
+
console.log(chalk_1.default.gray('\n✓ No open PRs\n'));
|
|
306
284
|
}
|
|
307
285
|
else {
|
|
308
|
-
|
|
286
|
+
console.log(chalk_1.default.blue(`\n📋 Open PRs (${prs.length}):`));
|
|
287
|
+
prs.forEach((p) => {
|
|
288
|
+
console.log(chalk_1.default.cyan(` #${p.number} `) + chalk_1.default.white(p.title));
|
|
289
|
+
});
|
|
290
|
+
console.log();
|
|
291
|
+
}
|
|
292
|
+
break;
|
|
293
|
+
case 'pr_merge':
|
|
294
|
+
const prNumber = intent.target || intent.options?.number;
|
|
295
|
+
if (!prNumber) {
|
|
296
|
+
console.log(chalk_1.default.red('\n❌ PR number required\n'));
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
console.log(chalk_1.default.blue(`\n🔄 Merging PR #${prNumber}...`));
|
|
300
|
+
await github.mergePullRequest(prNumber);
|
|
301
|
+
console.log(chalk_1.default.green(`✓ PR #${prNumber} merged\n`));
|
|
302
|
+
break;
|
|
303
|
+
case 'ci_check':
|
|
304
|
+
console.log(chalk_1.default.blue('\n🔍 Checking CI status...'));
|
|
305
|
+
// TODO: Implement CI status check
|
|
306
|
+
console.log(chalk_1.default.gray(' CI checks (coming soon)\n'));
|
|
307
|
+
break;
|
|
308
|
+
case 'issue_create':
|
|
309
|
+
console.log(chalk_1.default.blue('\n🔄 Creating issue...'));
|
|
310
|
+
const issue = await github.createIssue(intent.options || {});
|
|
311
|
+
console.log(chalk_1.default.green(`✓ Issue #${issue.number} created`));
|
|
312
|
+
console.log(chalk_1.default.cyan(` ${issue.html_url}\n`));
|
|
313
|
+
break;
|
|
314
|
+
case 'issue_list':
|
|
315
|
+
const issues = await github.listIssues({ state: 'open', limit: 10 });
|
|
316
|
+
if (issues.length === 0) {
|
|
317
|
+
console.log(chalk_1.default.gray('\n✓ No open issues\n'));
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
console.log(chalk_1.default.blue(`\n🐛 Open Issues (${issues.length}):`));
|
|
321
|
+
issues.forEach((i) => {
|
|
322
|
+
console.log(chalk_1.default.cyan(` #${i.number} `) + chalk_1.default.white(i.title));
|
|
323
|
+
});
|
|
324
|
+
console.log();
|
|
309
325
|
}
|
|
310
326
|
break;
|
|
311
327
|
default:
|
|
312
|
-
console.log(chalk_1.default.yellow(
|
|
328
|
+
console.log(chalk_1.default.yellow(`\n⚠️ Action not supported: ${intent.action}\n`));
|
|
313
329
|
}
|
|
314
330
|
}
|
|
315
331
|
catch (error) {
|
|
316
|
-
console.log(chalk_1.default.red(
|
|
332
|
+
console.log(chalk_1.default.red(`\n❌ ${error.message}\n`));
|
|
317
333
|
}
|
|
318
334
|
}
|
|
319
335
|
/**
|
|
320
|
-
* Auto-fix common Git errors (like Cursor does)
|
|
336
|
+
* Auto-fix common Git errors (like Cursor does - silently when possible)
|
|
321
337
|
*/
|
|
322
338
|
async function tryAutoFix(error, command) {
|
|
323
339
|
const errorMsg = error.message?.toLowerCase() || '';
|
|
324
340
|
// Merge conflict
|
|
325
341
|
if (errorMsg.includes('conflict')) {
|
|
326
|
-
console.log(chalk_1.default.yellow('⚠️
|
|
342
|
+
console.log(chalk_1.default.yellow('\n⚠️ Conflict detected - auto-resolving...'));
|
|
327
343
|
try {
|
|
328
|
-
// Try to accept current changes
|
|
329
344
|
(0, child_process_1.execSync)('git add .', { encoding: 'utf-8', stdio: 'pipe' });
|
|
330
345
|
(0, child_process_1.execSync)('git commit --no-edit', { encoding: 'utf-8', stdio: 'pipe' });
|
|
331
|
-
console.log(chalk_1.default.green('✓
|
|
346
|
+
console.log(chalk_1.default.green('✓ Resolved\n'));
|
|
332
347
|
return true;
|
|
333
348
|
}
|
|
334
349
|
catch {
|
|
@@ -337,11 +352,11 @@ async function tryAutoFix(error, command) {
|
|
|
337
352
|
}
|
|
338
353
|
// Diverged branches
|
|
339
354
|
if (errorMsg.includes('diverged') || errorMsg.includes('non-fast-forward')) {
|
|
340
|
-
console.log(chalk_1.default.yellow('⚠️
|
|
355
|
+
console.log(chalk_1.default.yellow('\n⚠️ Syncing with remote...'));
|
|
341
356
|
try {
|
|
342
357
|
(0, child_process_1.execSync)('git pull --rebase', { encoding: 'utf-8', stdio: 'pipe' });
|
|
343
358
|
(0, child_process_1.execSync)(command, { encoding: 'utf-8', stdio: 'pipe' });
|
|
344
|
-
console.log(chalk_1.default.green('✓
|
|
359
|
+
console.log(chalk_1.default.green('✓ Synced\n'));
|
|
345
360
|
return true;
|
|
346
361
|
}
|
|
347
362
|
catch {
|
|
@@ -350,12 +365,12 @@ async function tryAutoFix(error, command) {
|
|
|
350
365
|
}
|
|
351
366
|
// Unstaged changes
|
|
352
367
|
if (errorMsg.includes('unstaged') || errorMsg.includes('uncommitted')) {
|
|
353
|
-
console.log(chalk_1.default.yellow('⚠️
|
|
368
|
+
console.log(chalk_1.default.yellow('\n⚠️ Stashing changes...'));
|
|
354
369
|
try {
|
|
355
370
|
(0, child_process_1.execSync)('git stash', { encoding: 'utf-8', stdio: 'pipe' });
|
|
356
371
|
(0, child_process_1.execSync)(command, { encoding: 'utf-8', stdio: 'pipe' });
|
|
357
372
|
(0, child_process_1.execSync)('git stash pop', { encoding: 'utf-8', stdio: 'pipe' });
|
|
358
|
-
console.log(chalk_1.default.green('✓
|
|
373
|
+
console.log(chalk_1.default.green('✓ Restored\n'));
|
|
359
374
|
return true;
|
|
360
375
|
}
|
|
361
376
|
catch {
|