@snapcommit/cli 2.1.0 → 2.2.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 +210 -25
- package/package.json +1 -1
|
@@ -1,8 +1,41 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* Cursor-style natural language Git assistant
|
|
4
|
-
*
|
|
4
|
+
* Fast, simple, auto-fixes errors, handles ALL Git + GitHub operations
|
|
5
5
|
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
6
39
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
40
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
41
|
};
|
|
@@ -12,67 +45,219 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
12
45
|
const child_process_1 = require("child_process");
|
|
13
46
|
const git_1 = require("../utils/git");
|
|
14
47
|
const auth_1 = require("../lib/auth");
|
|
48
|
+
const github_connect_1 = require("./github-connect");
|
|
49
|
+
const github = __importStar(require("../lib/github"));
|
|
15
50
|
async function executeCursorStyle(userInput) {
|
|
16
51
|
if (!(0, git_1.isGitRepo)()) {
|
|
17
52
|
console.log(chalk_1.default.red('\n❌ Not a git repository\n'));
|
|
18
53
|
return;
|
|
19
54
|
}
|
|
20
|
-
|
|
55
|
+
const input = userInput.toLowerCase().trim();
|
|
56
|
+
// FAST PATH: Simple commit/push (no AI needed)
|
|
57
|
+
if (input.includes('commit') || input.includes('push') || input.includes('save')) {
|
|
58
|
+
await handleCommitAndPush();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// COMPLEX PATH: Use AI for everything else (branch, merge, rebase, undo, GitHub, etc.)
|
|
62
|
+
await handleComplexCommand(userInput);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Fast path: Commit and push (no AI interpretation needed)
|
|
66
|
+
*/
|
|
67
|
+
async function handleCommitAndPush() {
|
|
21
68
|
const status = (0, git_1.getGitStatus)();
|
|
22
69
|
const hasChanges = status.staged > 0 || status.unstaged > 0 || status.untracked > 0;
|
|
23
70
|
if (!hasChanges) {
|
|
24
|
-
console.log(chalk_1.default.gray('\n✓ Branch clean
|
|
71
|
+
console.log(chalk_1.default.gray('\n✓ Branch clean\n'));
|
|
25
72
|
return;
|
|
26
73
|
}
|
|
27
|
-
//
|
|
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`));
|
|
35
|
-
console.log();
|
|
36
|
-
// Stage everything
|
|
74
|
+
// Stage all
|
|
37
75
|
try {
|
|
38
76
|
(0, git_1.stageAllChanges)();
|
|
39
77
|
}
|
|
40
78
|
catch (error) {
|
|
41
|
-
console.log(chalk_1.default.red(`❌
|
|
79
|
+
console.log(chalk_1.default.red(`❌ ${error.message}\n`));
|
|
42
80
|
return;
|
|
43
81
|
}
|
|
44
|
-
// Generate commit message
|
|
45
|
-
console.log(chalk_1.default.blue('🤖 Generating commit message...'));
|
|
82
|
+
// Generate AI commit message
|
|
46
83
|
const diff = (0, git_1.getGitDiff)(true);
|
|
47
84
|
const commitMessage = await generateCommitMessage(diff);
|
|
48
|
-
console.log(chalk_1.default.green(`\n📝 ${commitMessage.split('\n')[0]}\n`));
|
|
49
85
|
// Commit
|
|
50
86
|
try {
|
|
51
87
|
(0, child_process_1.execSync)(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, { encoding: 'utf-8', stdio: 'pipe' });
|
|
52
|
-
console.log(chalk_1.default.green(
|
|
88
|
+
console.log(chalk_1.default.green(`✓ ${commitMessage.split('\n')[0]}`));
|
|
53
89
|
}
|
|
54
90
|
catch (error) {
|
|
55
|
-
console.log(chalk_1.default.red(`❌ Commit failed
|
|
91
|
+
console.log(chalk_1.default.red(`❌ Commit failed\n`));
|
|
56
92
|
return;
|
|
57
93
|
}
|
|
58
94
|
// Push
|
|
59
95
|
try {
|
|
60
|
-
console.log(chalk_1.default.blue('⬆️ Pushing to remote...'));
|
|
61
96
|
(0, child_process_1.execSync)('git push', { encoding: 'utf-8', stdio: 'pipe' });
|
|
62
97
|
console.log(chalk_1.default.green('✓ Pushed\n'));
|
|
63
98
|
}
|
|
64
99
|
catch (error) {
|
|
65
|
-
// If push fails (e.g., no remote), that's okay
|
|
66
100
|
if (error.message.includes('no configured push destination')) {
|
|
67
|
-
console.log(chalk_1.default.
|
|
101
|
+
console.log(chalk_1.default.gray('✓ Committed locally (no remote)\n'));
|
|
68
102
|
}
|
|
69
103
|
else {
|
|
70
|
-
console.log(chalk_1.default.yellow(`⚠️
|
|
104
|
+
console.log(chalk_1.default.yellow(`⚠️ ${error.message}\n`));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Complex path: Use AI to interpret and execute any Git/GitHub command
|
|
110
|
+
*/
|
|
111
|
+
async function handleComplexCommand(userInput) {
|
|
112
|
+
const token = (0, auth_1.getToken)();
|
|
113
|
+
if (!token) {
|
|
114
|
+
console.log(chalk_1.default.red('❌ Not authenticated\n'));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
// Get AI interpretation
|
|
118
|
+
const intent = await getAIInterpretation(userInput, token);
|
|
119
|
+
if (!intent) {
|
|
120
|
+
console.log(chalk_1.default.red('❌ Could not understand command\n'));
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
// Execute based on type
|
|
124
|
+
if (intent.type === 'git') {
|
|
125
|
+
await executeGitCommands(intent.gitCommands || []);
|
|
126
|
+
}
|
|
127
|
+
else if (intent.type === 'github') {
|
|
128
|
+
await executeGitHubCommand(intent);
|
|
129
|
+
}
|
|
130
|
+
console.log(chalk_1.default.green('✓ Done\n'));
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Execute Git commands with auto-retry on errors
|
|
134
|
+
*/
|
|
135
|
+
async function executeGitCommands(commands) {
|
|
136
|
+
for (const cmd of commands) {
|
|
137
|
+
try {
|
|
138
|
+
(0, child_process_1.execSync)(cmd, { encoding: 'utf-8', stdio: 'pipe' });
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
// Try to auto-fix common errors
|
|
142
|
+
const fixed = await tryAutoFix(error, cmd);
|
|
143
|
+
if (!fixed) {
|
|
144
|
+
console.log(chalk_1.default.red(`❌ ${error.message}\n`));
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
71
147
|
}
|
|
72
148
|
}
|
|
73
|
-
console.log(chalk_1.default.green('✅ Done!\n'));
|
|
74
149
|
}
|
|
75
|
-
|
|
150
|
+
/**
|
|
151
|
+
* Execute GitHub operations (PRs, CI, issues)
|
|
152
|
+
*/
|
|
153
|
+
async function executeGitHubCommand(intent) {
|
|
154
|
+
if (!(0, github_connect_1.isGitHubConnected)()) {
|
|
155
|
+
console.log(chalk_1.default.yellow('⚠️ GitHub not connected. Run: snap github connect\n'));
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
switch (intent.action) {
|
|
160
|
+
case 'pr_create':
|
|
161
|
+
console.log(chalk_1.default.blue('Creating PR...'));
|
|
162
|
+
const pr = await github.createPullRequest(intent.options || {});
|
|
163
|
+
console.log(chalk_1.default.green(`✓ PR created: ${pr.html_url}`));
|
|
164
|
+
break;
|
|
165
|
+
case 'pr_list':
|
|
166
|
+
console.log(chalk_1.default.blue('Listing PRs...'));
|
|
167
|
+
const prs = await github.listPullRequests({ state: 'open', limit: 10 });
|
|
168
|
+
if (prs.length === 0) {
|
|
169
|
+
console.log(chalk_1.default.gray('No open PRs'));
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
prs.forEach((p) => console.log(chalk_1.default.cyan(` #${p.number}: ${p.title}`)));
|
|
173
|
+
}
|
|
174
|
+
break;
|
|
175
|
+
default:
|
|
176
|
+
console.log(chalk_1.default.yellow(`⚠️ GitHub action not implemented: ${intent.action}\n`));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
console.log(chalk_1.default.red(`❌ ${error.message}\n`));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Auto-fix common Git errors (like Cursor does)
|
|
185
|
+
*/
|
|
186
|
+
async function tryAutoFix(error, command) {
|
|
187
|
+
const errorMsg = error.message?.toLowerCase() || '';
|
|
188
|
+
// Merge conflict
|
|
189
|
+
if (errorMsg.includes('conflict')) {
|
|
190
|
+
console.log(chalk_1.default.yellow('⚠️ Merge conflict - attempting auto-resolve...'));
|
|
191
|
+
try {
|
|
192
|
+
// Try to accept current changes
|
|
193
|
+
(0, child_process_1.execSync)('git add .', { encoding: 'utf-8', stdio: 'pipe' });
|
|
194
|
+
(0, child_process_1.execSync)('git commit --no-edit', { encoding: 'utf-8', stdio: 'pipe' });
|
|
195
|
+
console.log(chalk_1.default.green('✓ Auto-resolved'));
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Diverged branches
|
|
203
|
+
if (errorMsg.includes('diverged') || errorMsg.includes('non-fast-forward')) {
|
|
204
|
+
console.log(chalk_1.default.yellow('⚠️ Branches diverged - pulling and retrying...'));
|
|
205
|
+
try {
|
|
206
|
+
(0, child_process_1.execSync)('git pull --rebase', { encoding: 'utf-8', stdio: 'pipe' });
|
|
207
|
+
(0, child_process_1.execSync)(command, { encoding: 'utf-8', stdio: 'pipe' });
|
|
208
|
+
console.log(chalk_1.default.green('✓ Fixed'));
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// Unstaged changes
|
|
216
|
+
if (errorMsg.includes('unstaged') || errorMsg.includes('uncommitted')) {
|
|
217
|
+
console.log(chalk_1.default.yellow('⚠️ Unstaged changes - stashing and retrying...'));
|
|
218
|
+
try {
|
|
219
|
+
(0, child_process_1.execSync)('git stash', { encoding: 'utf-8', stdio: 'pipe' });
|
|
220
|
+
(0, child_process_1.execSync)(command, { encoding: 'utf-8', stdio: 'pipe' });
|
|
221
|
+
(0, child_process_1.execSync)('git stash pop', { encoding: 'utf-8', stdio: 'pipe' });
|
|
222
|
+
console.log(chalk_1.default.green('✓ Fixed'));
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get AI interpretation for complex commands
|
|
233
|
+
*/
|
|
234
|
+
async function getAIInterpretation(userInput, token) {
|
|
235
|
+
try {
|
|
236
|
+
const currentBranch = (0, git_1.getCurrentBranch)();
|
|
237
|
+
const status = (0, git_1.getGitStatus)();
|
|
238
|
+
const response = await fetch('https://snapcommit.dev/api/ai/interpret', {
|
|
239
|
+
method: 'POST',
|
|
240
|
+
headers: { 'Content-Type': 'application/json' },
|
|
241
|
+
body: JSON.stringify({
|
|
242
|
+
userInput,
|
|
243
|
+
token,
|
|
244
|
+
context: {
|
|
245
|
+
currentBranch,
|
|
246
|
+
hasUncommittedChanges: status.unstaged > 0 || status.untracked > 0,
|
|
247
|
+
lastCommitHash: (0, child_process_1.execSync)('git log -1 --format=%H 2>/dev/null || echo ""', { encoding: 'utf-8' }).trim(),
|
|
248
|
+
remoteBranch: (0, child_process_1.execSync)('git rev-parse --abbrev-ref @{upstream} 2>/dev/null || echo ""', { encoding: 'utf-8' }).trim(),
|
|
249
|
+
},
|
|
250
|
+
}),
|
|
251
|
+
});
|
|
252
|
+
if (!response.ok)
|
|
253
|
+
return null;
|
|
254
|
+
const data = await response.json();
|
|
255
|
+
return data.intent;
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
76
261
|
async function generateCommitMessage(diff) {
|
|
77
262
|
const token = (0, auth_1.getToken)();
|
|
78
263
|
if (!token) {
|