gitpt 1.2.0 → 1.3.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.
Files changed (100) hide show
  1. package/README.md +20 -10
  2. package/dist/commands/commit/context/systemPrompt.d.ts +1 -0
  3. package/dist/commands/commit/context/systemPrompt.js +38 -0
  4. package/dist/commands/commit/context/userPrompt.d.ts +1 -0
  5. package/dist/commands/commit/context/userPrompt.js +5 -0
  6. package/dist/commands/commit/generateCommitMessage.d.ts +1 -0
  7. package/dist/commands/commit/generateCommitMessage.js +39 -0
  8. package/dist/commands/{commit.d.ts → commit/index.d.ts} +1 -1
  9. package/dist/commands/commit/index.js +183 -0
  10. package/dist/commands/config.d.ts +1 -0
  11. package/dist/commands/config.js +11 -0
  12. package/dist/commands/middleware/capabilitiesMiddleware/ghCapability.d.ts +1 -0
  13. package/dist/commands/middleware/capabilitiesMiddleware/ghCapability.js +23 -0
  14. package/dist/commands/middleware/capabilitiesMiddleware/gitCapability.d.ts +1 -0
  15. package/dist/commands/middleware/capabilitiesMiddleware/gitCapability.js +12 -0
  16. package/dist/commands/middleware/capabilitiesMiddleware/index.d.ts +3 -0
  17. package/dist/commands/middleware/capabilitiesMiddleware/index.js +15 -0
  18. package/dist/commands/middleware/hasStagedChangesMiddleware.d.ts +1 -0
  19. package/dist/commands/middleware/hasStagedChangesMiddleware.js +8 -0
  20. package/dist/commands/middleware/setupMiddleware/getAvailableModels.d.ts +4 -0
  21. package/dist/commands/middleware/setupMiddleware/getAvailableModels.js +11 -0
  22. package/dist/commands/middleware/setupMiddleware/getOrUpdateApiKey.d.ts +1 -0
  23. package/dist/commands/middleware/setupMiddleware/getOrUpdateApiKey.js +39 -0
  24. package/dist/commands/middleware/setupMiddleware/index.d.ts +4 -0
  25. package/dist/commands/middleware/setupMiddleware/index.js +40 -0
  26. package/dist/commands/middleware/setupMiddleware/selectModel.d.ts +5 -0
  27. package/dist/commands/middleware/setupMiddleware/selectModel.js +38 -0
  28. package/dist/commands/middleware/setupMiddleware/setupLocalLLM.d.ts +5 -0
  29. package/dist/commands/middleware/setupMiddleware/setupLocalLLM.js +60 -0
  30. package/dist/commands/middleware/setupMiddleware/setupOpenRouter.d.ts +2 -0
  31. package/dist/commands/middleware/setupMiddleware/setupOpenRouter.js +66 -0
  32. package/dist/commands/middleware/setupMiddleware/types.d.ts +13 -0
  33. package/dist/commands/middleware/setupMiddleware/types.js +1 -0
  34. package/dist/commands/model.d.ts +1 -1
  35. package/dist/commands/model.js +6 -114
  36. package/dist/commands/pr/context/systemPrompt.d.ts +1 -0
  37. package/dist/commands/pr/context/systemPrompt.js +18 -0
  38. package/dist/commands/pr/context/userPrompt.d.ts +1 -0
  39. package/dist/commands/pr/context/userPrompt.js +20 -0
  40. package/dist/commands/pr/generatePRDetails.d.ts +4 -0
  41. package/dist/commands/pr/generatePRDetails.js +35 -0
  42. package/dist/commands/pr/getPRContext.d.ts +1 -0
  43. package/dist/commands/pr/getPRContext.js +65 -0
  44. package/dist/commands/{pr.d.ts → pr/index.d.ts} +1 -1
  45. package/dist/commands/pr/index.js +66 -0
  46. package/dist/commands/setup.d.ts +3 -1
  47. package/dist/commands/setup.js +15 -60
  48. package/dist/config.d.ts +18 -0
  49. package/dist/config.js +58 -0
  50. package/dist/index.d.ts +1 -1
  51. package/dist/index.js +37 -49
  52. package/dist/llm/index.d.ts +5 -0
  53. package/dist/llm/index.js +14 -0
  54. package/dist/services/gh/createPullRequest.d.ts +1 -0
  55. package/dist/services/gh/createPullRequest.js +63 -0
  56. package/dist/services/gh/index.d.ts +4 -0
  57. package/dist/services/gh/index.js +6 -0
  58. package/dist/services/gh/isAvailable.d.ts +1 -0
  59. package/dist/services/gh/isAvailable.js +10 -0
  60. package/dist/services/git/executeGitAdd.d.ts +1 -0
  61. package/dist/services/git/executeGitAdd.js +15 -0
  62. package/dist/services/git/executeGitCommit.d.ts +1 -0
  63. package/dist/services/git/executeGitCommit.js +12 -0
  64. package/dist/services/git/getChangedFiles.d.ts +1 -0
  65. package/dist/services/git/getChangedFiles.js +64 -0
  66. package/dist/services/git/getCommitsSinceBaseBranch.d.ts +1 -0
  67. package/dist/services/git/getCommitsSinceBaseBranch.js +59 -0
  68. package/dist/services/git/getCurrentBranch.d.ts +1 -0
  69. package/dist/services/git/getCurrentBranch.js +11 -0
  70. package/dist/services/git/getDefaultBranch.d.ts +1 -0
  71. package/dist/services/git/getDefaultBranch.js +63 -0
  72. package/dist/services/git/getStagedChanges.d.ts +1 -0
  73. package/dist/services/git/getStagedChanges.js +11 -0
  74. package/dist/services/git/getStagedFiles.d.ts +1 -0
  75. package/dist/services/git/getStagedFiles.js +12 -0
  76. package/dist/services/git/hasStagedChanges.d.ts +1 -0
  77. package/dist/services/git/hasStagedChanges.js +10 -0
  78. package/dist/services/git/index.d.ts +13 -0
  79. package/dist/services/git/index.js +24 -0
  80. package/dist/services/git/isAvailable.d.ts +1 -0
  81. package/dist/services/git/isAvailable.js +10 -0
  82. package/dist/services/git/isGitRepository.d.ts +1 -0
  83. package/dist/services/git/isGitRepository.js +10 -0
  84. package/dist/utils/commitlint.d.ts +4 -3
  85. package/dist/utils/commitlint.js +62 -38
  86. package/dist/utils/formatBaseURL.d.ts +1 -0
  87. package/dist/utils/formatBaseURL.js +7 -0
  88. package/dist/utils/maskApiKey.d.ts +1 -0
  89. package/dist/utils/maskApiKey.js +8 -0
  90. package/package.json +9 -10
  91. package/dist/commands/add.d.ts +0 -1
  92. package/dist/commands/add.js +0 -16
  93. package/dist/commands/commit.js +0 -99
  94. package/dist/commands/pr.js +0 -458
  95. package/dist/utils/api.d.ts +0 -1
  96. package/dist/utils/api.js +0 -61
  97. package/dist/utils/config.d.ts +0 -7
  98. package/dist/utils/config.js +0 -24
  99. package/dist/utils/git.d.ts +0 -6
  100. package/dist/utils/git.js +0 -62
@@ -1,458 +0,0 @@
1
- import inquirer from 'inquirer';
2
- import chalk from 'chalk';
3
- import { execSync } from 'child_process';
4
- import { isGitRepository } from '../utils/git.js';
5
- import { getConfig } from '../utils/config.js';
6
- import fetch from 'node-fetch';
7
- function getCurrentBranch() {
8
- try {
9
- return execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
10
- }
11
- catch (error) {
12
- console.error(chalk.red('Error getting current branch:'), error);
13
- throw new Error('Failed to get current branch');
14
- }
15
- }
16
- function getDefaultBaseBranch() {
17
- try {
18
- // First check for a default branch set in git config
19
- try {
20
- const defaultBranch = execSync('git config init.defaultBranch').toString().trim();
21
- if (defaultBranch) {
22
- return defaultBranch;
23
- }
24
- }
25
- catch (error) {
26
- // Continue if git config doesn't have default branch
27
- }
28
- // Next, check if GitHub CLI can tell us the default branch
29
- try {
30
- const repoInfo = execSync('gh repo view --json defaultBranchRef --jq .defaultBranchRef.name').toString().trim();
31
- if (repoInfo) {
32
- return repoInfo;
33
- }
34
- }
35
- catch (error) {
36
- // Continue if gh command fails
37
- }
38
- // Try to find default branch in remote branches list
39
- const branches = execSync('git branch -r').toString().trim().split('\n');
40
- // Common default branch names, in order of likelihood
41
- const mainPatterns = [
42
- /origin\/main$/,
43
- /origin\/master$/,
44
- /origin\/develop$/,
45
- /origin\/dev$/,
46
- /origin\/trunk$/
47
- ];
48
- // Try each pattern in order
49
- for (const pattern of mainPatterns) {
50
- const defaultBranch = branches.find(b => pattern.test(b.trim()));
51
- if (defaultBranch) {
52
- return defaultBranch.trim().replace(/^origin\//, '');
53
- }
54
- }
55
- // Check for a branch that has 'HEAD -> origin/' in it, indicating the default branch
56
- const headBranch = branches.find(b => b.includes('HEAD -> origin/'));
57
- if (headBranch) {
58
- const match = headBranch.match(/HEAD -> origin\/([^,\s]+)/);
59
- if (match && match[1]) {
60
- return match[1];
61
- }
62
- }
63
- // Fallback to 'main' as most GitHub repos use this now
64
- console.log(chalk.yellow('Could not determine default branch, using "main"'));
65
- return 'main';
66
- }
67
- catch (error) {
68
- // If we can't determine, default to main
69
- console.log(chalk.yellow('Error detecting default branch, using "main"'));
70
- return 'main';
71
- }
72
- }
73
- function getCommitsSinceBaseBranch(baseBranch) {
74
- try {
75
- // Try first with origin/baseBranch
76
- try {
77
- const mergeBase = execSync(`git merge-base HEAD origin/${baseBranch}`).toString().trim();
78
- const commitMessages = execSync(`git log --pretty=format:"%s" ${mergeBase}..HEAD`).toString().trim();
79
- if (commitMessages) {
80
- return commitMessages.split('\n').filter(Boolean);
81
- }
82
- }
83
- catch (error) {
84
- // If origin/baseBranch doesn't exist, try with just baseBranch
85
- console.log(chalk.yellow(`No origin/${baseBranch} found, trying with local ${baseBranch} branch...`));
86
- }
87
- // Try with local branch
88
- try {
89
- const mergeBase = execSync(`git merge-base HEAD ${baseBranch}`).toString().trim();
90
- const commitMessages = execSync(`git log --pretty=format:"%s" ${mergeBase}..HEAD`).toString().trim();
91
- if (commitMessages) {
92
- return commitMessages.split('\n').filter(Boolean);
93
- }
94
- }
95
- catch (error) {
96
- // If that fails too, fallback to simple branch comparison
97
- console.log(chalk.yellow(`Merge base with ${baseBranch} not found, comparing branches directly...`));
98
- }
99
- // Direct branch comparison
100
- try {
101
- const commitMessages = execSync(`git log --pretty=format:"%s" ${baseBranch}..HEAD`).toString().trim();
102
- if (commitMessages) {
103
- return commitMessages.split('\n').filter(Boolean);
104
- }
105
- }
106
- catch (error) {
107
- console.log(chalk.yellow(`Could not compare with ${baseBranch}, using recent commits...`));
108
- }
109
- // Last resort: get most recent commits
110
- const commitMessages = execSync('git log --pretty=format:"%s" -n 10').toString().trim();
111
- return commitMessages.split('\n').filter(Boolean);
112
- }
113
- catch (error) {
114
- console.error(chalk.yellow('Could not get commits. Using empty list.'));
115
- return [];
116
- }
117
- }
118
- function getChangedFiles(baseBranch) {
119
- // Try several methods to get changed files
120
- // Method 1: Compare with origin/baseBranch using three dots
121
- try {
122
- const changedFiles = execSync(`git diff --name-only origin/${baseBranch}...HEAD`).toString().trim();
123
- if (changedFiles) {
124
- return changedFiles.split('\n').filter(Boolean);
125
- }
126
- }
127
- catch (error) {
128
- // Continue to next method
129
- }
130
- // Method 2: Compare with local baseBranch using three dots
131
- try {
132
- const changedFiles = execSync(`git diff --name-only ${baseBranch}...HEAD`).toString().trim();
133
- if (changedFiles) {
134
- return changedFiles.split('\n').filter(Boolean);
135
- }
136
- }
137
- catch (error) {
138
- // Continue to next method
139
- }
140
- // Method 3: Direct comparison with two dots
141
- try {
142
- const changedFiles = execSync(`git diff --name-only ${baseBranch}..HEAD`).toString().trim();
143
- if (changedFiles) {
144
- return changedFiles.split('\n').filter(Boolean);
145
- }
146
- }
147
- catch (error) {
148
- // Continue to next method
149
- }
150
- // Method 4: Get recently modified files
151
- try {
152
- console.log(chalk.yellow(`Could not determine changed files relative to ${baseBranch}, using recently modified files...`));
153
- const changedFiles = execSync('git ls-files --modified --others --exclude-standard').toString().trim();
154
- if (changedFiles) {
155
- return changedFiles.split('\n').filter(Boolean);
156
- }
157
- }
158
- catch (error) {
159
- // Last resort
160
- }
161
- // Method 5: List all files in the repo as a last resort
162
- try {
163
- console.log(chalk.yellow('Using all tracked files as fallback...'));
164
- const allFiles = execSync('git ls-files').toString().trim();
165
- return allFiles.split('\n').filter(Boolean).slice(0, 50); // Limit to first 50 files
166
- }
167
- catch (error) {
168
- console.error(chalk.red('Could not determine changed files.'));
169
- return [];
170
- }
171
- }
172
- async function generatePRDetails(baseBranch, currentBranch) {
173
- const config = getConfig();
174
- if (!config) {
175
- throw new Error('GitPT is not configured. Please run "gitpt setup" first.');
176
- }
177
- const { apiKey, model } = config;
178
- // Get context for PR
179
- const commitMessages = getCommitsSinceBaseBranch(baseBranch);
180
- const changedFiles = getChangedFiles(baseBranch);
181
- // Check if we have any content to work with
182
- if (commitMessages.length === 0 && changedFiles.length === 0) {
183
- console.log(chalk.yellow('No commits or changed files detected.'));
184
- console.log(chalk.yellow('Will attempt to generate PR details using branch name and repository context.'));
185
- }
186
- // Get additional context from repository
187
- let repoName = "";
188
- let repoDescription = "";
189
- try {
190
- // Try to get repo information from GitHub CLI
191
- const repoInfo = JSON.parse(execSync('gh repo view --json name,description').toString().trim());
192
- repoName = repoInfo.name || "";
193
- repoDescription = repoInfo.description || "";
194
- }
195
- catch (error) {
196
- // Continue without this info
197
- }
198
- console.log(chalk.blue('Generating PR title and description...'));
199
- // Build a rich context for the AI
200
- let contextSections = [
201
- `Branch: ${currentBranch}`,
202
- `Base branch: ${baseBranch}`
203
- ];
204
- // Add repository info if available
205
- if (repoName) {
206
- contextSections.push(`Repository: ${repoName}`);
207
- }
208
- if (repoDescription) {
209
- contextSections.push(`Repository description: ${repoDescription}`);
210
- }
211
- // Add commit messages if available
212
- if (commitMessages.length > 0) {
213
- contextSections.push('Commit messages in this branch:', commitMessages.map(msg => `- ${msg}`).join('\n'));
214
- }
215
- else {
216
- contextSections.push('No commit messages available.');
217
- // Try to extract intent from branch name if no commits
218
- if (currentBranch.includes('/')) {
219
- const branchParts = currentBranch.split('/');
220
- const branchType = branchParts[0]; // e.g., "feature", "fix", "chore"
221
- const branchDescription = branchParts.slice(1).join('/').replace(/-/g, ' ');
222
- contextSections.push('Branch name analysis:', `Type: ${branchType}`, `Description: ${branchDescription}`);
223
- }
224
- }
225
- // Add changed files if available
226
- if (changedFiles.length > 0) {
227
- contextSections.push('Files changed in this branch:', changedFiles.map(file => `- ${file}`).join('\n'));
228
- }
229
- else {
230
- contextSections.push('No file changes detected.');
231
- }
232
- // Create the final context
233
- const context = contextSections.join('\n\n');
234
- const systemPrompt = `You are a helpful assistant that generates clear, informative GitHub pull request titles and descriptions.
235
- For the title:
236
- - Keep it concise (under 80 characters)
237
- - Start with a verb in present tense (e.g., "Add", "Fix", "Update")
238
- - Clearly summarize the main purpose of the changes
239
-
240
- For the description:
241
- - Start with a brief summary (1-2 sentences) of what the PR accomplishes
242
- - Include a more detailed explanation of changes if needed
243
- - List key changes as bullet points if there are multiple components
244
- - Include any relevant context that reviewers should know
245
- - End with any testing instructions if applicable
246
-
247
- Format the description in Markdown with sections.
248
- Do not include "PR" or "Pull Request" in the title.`;
249
- const userPrompt = `Generate a pull request title and description for the following changes:
250
-
251
- ${context}
252
-
253
- Format your response exactly like this example:
254
- Title: Add user authentication with JWT
255
- Description:
256
- ## Summary
257
- This PR adds user authentication using JWT tokens.
258
-
259
- ## Changes
260
- - Implement login and registration endpoints
261
- - Add JWT generation and validation
262
- - Update user model with password hashing
263
- - Add authorization middleware
264
-
265
- ## How to test
266
- 1. Register a new user with \`/api/register\`
267
- 2. Login with the new user credentials
268
- 3. Use the returned token to access protected endpoints`;
269
- try {
270
- const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
271
- method: 'POST',
272
- headers: {
273
- 'Content-Type': 'application/json',
274
- 'Authorization': `Bearer ${apiKey}`,
275
- 'HTTP-Referer': 'https://github.com/bartaxyz/GitPT',
276
- },
277
- body: JSON.stringify({
278
- model: model,
279
- messages: [
280
- { role: 'system', content: systemPrompt },
281
- { role: 'user', content: userPrompt }
282
- ],
283
- max_tokens: 1000,
284
- }),
285
- });
286
- if (!response.ok) {
287
- const errorText = await response.text();
288
- throw new Error(`API request failed: ${response.status} ${response.statusText}\n${errorText}`);
289
- }
290
- const data = await response.json();
291
- const result = data.choices[0].message.content.trim();
292
- // Parse title and description from AI response
293
- const titleMatch = result.match(/Title:\s*(.+?)(?:\n|$)/);
294
- const descMatch = result.match(/Description:\s*\n([\s\S]+)$/);
295
- const title = titleMatch ? titleMatch[1].trim() : '';
296
- const body = descMatch ? descMatch[1].trim() : result; // Fallback to full response if parsing fails
297
- return { title, body };
298
- }
299
- catch (error) {
300
- console.error(chalk.red('Error generating PR details:'), error);
301
- throw new Error('Failed to generate PR details');
302
- }
303
- }
304
- function checkGitHubCLIAvailability() {
305
- try {
306
- execSync('gh --version', { stdio: 'ignore' });
307
- return true;
308
- }
309
- catch (error) {
310
- return false;
311
- }
312
- }
313
- function createPullRequest(title, body, baseBranch, draft) {
314
- const draftFlag = draft ? '--draft' : '';
315
- try {
316
- console.log(chalk.blue(`Creating pull request to ${baseBranch}...`));
317
- // Create a temporary file for the PR body to avoid issues with escaping
318
- const tempFilePath = `/tmp/gitpt-pr-body-${Date.now()}.md`;
319
- try {
320
- // Write the body to a temporary file
321
- execSync(`cat > "${tempFilePath}" << 'GITPT_EOF'
322
- ${body}
323
- GITPT_EOF`);
324
- // Try to get the remote repo URL if available
325
- let repoUrlArg = '';
326
- try {
327
- const repoUrl = execSync('git config --get remote.origin.url').toString().trim();
328
- if (repoUrl) {
329
- repoUrlArg = `--repo "${repoUrl}"`;
330
- }
331
- }
332
- catch (e) {
333
- // Proceed without repo URL
334
- }
335
- // Use the file for the body
336
- const command = `gh pr create --title "${title.replace(/"/g, '\\"')}" --body-file "${tempFilePath}" --base "${baseBranch}" ${draftFlag} ${repoUrlArg}`;
337
- // Set a timeout to avoid hanging indefinitely
338
- console.log(chalk.gray('Running GitHub PR creation command...'));
339
- console.log(chalk.gray(`Using base branch: ${baseBranch}`));
340
- // Add debugging output
341
- console.log(chalk.gray('Executing command with 60s timeout:'));
342
- // Execute the command with a timeout
343
- const result = execSync(command, {
344
- stdio: 'pipe',
345
- timeout: 60000 // 60-second timeout
346
- }).toString();
347
- console.log(result);
348
- console.log(chalk.green('✓ Pull request created successfully'));
349
- }
350
- finally {
351
- // Clean up temporary file
352
- try {
353
- execSync(`rm -f "${tempFilePath}"`);
354
- }
355
- catch (e) {
356
- // Ignore cleanup errors
357
- }
358
- }
359
- }
360
- catch (error) {
361
- if (error instanceof Error && error.message.includes('timeout')) {
362
- console.error(chalk.red('Error: GitHub CLI command timed out after 60 seconds.'));
363
- console.log(chalk.yellow('You may need to create the PR manually using:'));
364
- console.log(chalk.yellow(`gh pr create --title "${title}" --base "${baseBranch}" ${draftFlag}`));
365
- }
366
- else {
367
- console.error(chalk.red('Error creating pull request:'), error);
368
- }
369
- throw new Error('Failed to create pull request');
370
- }
371
- }
372
- export async function prCreateCommand(options = {}) {
373
- if (!isGitRepository()) {
374
- console.error(chalk.red('Error: Not a git repository'));
375
- process.exit(1);
376
- }
377
- // Check if GitHub CLI is available
378
- if (!checkGitHubCLIAvailability()) {
379
- console.error(chalk.red('Error: GitHub CLI (gh) is not installed or not available in PATH.'));
380
- console.log(chalk.yellow('Please install GitHub CLI from https://cli.github.com/'));
381
- process.exit(1);
382
- }
383
- // Check if user is authenticated with GitHub CLI
384
- try {
385
- const authStatus = execSync('gh auth status -h github.com 2>&1 || true').toString();
386
- if (authStatus.includes('not logged')) {
387
- console.error(chalk.red('Error: You are not authenticated with GitHub CLI.'));
388
- console.log(chalk.yellow('Please run `gh auth login` to authenticate.'));
389
- process.exit(1);
390
- }
391
- }
392
- catch (error) {
393
- console.log(chalk.yellow('Warning: Could not verify GitHub CLI authentication.'));
394
- console.log(chalk.yellow('If PR creation fails, please run `gh auth login` first.'));
395
- }
396
- // Get configuration
397
- const config = getConfig();
398
- if (!config) {
399
- console.error(chalk.red('GitPT is not configured. Please run "gitpt setup" first.'));
400
- process.exit(1);
401
- }
402
- try {
403
- const currentBranch = getCurrentBranch();
404
- const baseBranch = options.base || getDefaultBaseBranch();
405
- let title = options.title || '';
406
- let body = options.body || '';
407
- // Generate PR details if not provided
408
- if (!title || !body) {
409
- const generatedDetails = await generatePRDetails(baseBranch, currentBranch);
410
- title = title || generatedDetails.title;
411
- body = body || generatedDetails.body;
412
- console.log(chalk.green('✓ PR details generated'));
413
- console.log('');
414
- console.log(chalk.cyan('Generated title:'));
415
- console.log(title);
416
- console.log('');
417
- console.log(chalk.cyan('Generated description:'));
418
- console.log(body);
419
- console.log('');
420
- }
421
- // Allow editing PR details
422
- if (options.edit !== false) {
423
- const answers = await inquirer.prompt([
424
- {
425
- type: 'input',
426
- name: 'title',
427
- message: 'Edit PR title:',
428
- default: title
429
- },
430
- {
431
- type: 'editor',
432
- name: 'body',
433
- message: 'Edit PR description:',
434
- default: body
435
- },
436
- {
437
- type: 'confirm',
438
- name: 'draft',
439
- message: 'Create as draft PR?',
440
- default: options.draft || false
441
- }
442
- ]);
443
- title = answers.title;
444
- body = answers.body;
445
- const isDraft = answers.draft;
446
- // Create the PR
447
- createPullRequest(title, body, baseBranch, isDraft);
448
- }
449
- else {
450
- // Create the PR without editing
451
- createPullRequest(title, body, baseBranch, options.draft || false);
452
- }
453
- }
454
- catch (error) {
455
- console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
456
- process.exit(1);
457
- }
458
- }
@@ -1 +0,0 @@
1
- export declare function generateCommitMessage(diff: string, validationErrors?: string): Promise<string>;
package/dist/utils/api.js DELETED
@@ -1,61 +0,0 @@
1
- import fetch from "node-fetch";
2
- import { getConfig } from "./config.js";
3
- import { hasCommitlintConfig, getCommitlintRules } from "./commitlint.js";
4
- const OPENROUTER_API_URL = "https://openrouter.ai/api/v1/chat/completions";
5
- export async function generateCommitMessage(diff, validationErrors) {
6
- // Check if commitlint is configured
7
- const hasCommitlint = hasCommitlintConfig();
8
- const config = getConfig();
9
- if (!config) {
10
- throw new Error('GitPT is not configured. Please run "gitpt setup" first.');
11
- }
12
- const { apiKey, model } = config;
13
- const messages = [
14
- {
15
- role: "system",
16
- content: `You are a helpful assistant that generates concise, informative Git commit messages.
17
- Follow these strict rules:
18
- ${hasCommitlint ? getCommitlintRules() : `1. Use conventional commit format: type: description
19
- 2. Types are: feat, fix, docs, style, refactor, test, chore
20
- 3. NO scopes in parentheses - do not use feat(scope)
21
- 4. Keep the entire message under 100 characters
22
- 5. Use present tense (e.g., "add feature" not "added feature")
23
- 6. Be brief but descriptive about WHAT changed
24
- 7. Do not include detailed explanations
25
- 8. Examples:
26
- - feat: add user authentication
27
- - fix: resolve null pointer in login
28
- - chore: update dependencies
29
- - style: format css files`}${validationErrors ? `\n\nYOUR PREVIOUS MESSAGE FAILED VALIDATION WITH THESE ERRORS:\n${validationErrors}\n\nFIX THESE ISSUES IN YOUR NEW MESSAGE.` : ''}`,
30
- },
31
- {
32
- role: "user",
33
- content: `Generate a commit message for the following git diff:\n\n${diff}`,
34
- },
35
- ];
36
- try {
37
- const response = await fetch(OPENROUTER_API_URL, {
38
- method: "POST",
39
- headers: {
40
- "Content-Type": "application/json",
41
- Authorization: `Bearer ${apiKey}`,
42
- "HTTP-Referer": "https://github.com/bartaxyz/GitPT",
43
- },
44
- body: JSON.stringify({
45
- model: model,
46
- messages: messages,
47
- max_tokens: 300,
48
- }),
49
- });
50
- if (!response.ok) {
51
- const errorText = await response.text();
52
- throw new Error(`API request failed: ${response.status} ${response.statusText}\n${errorText}`);
53
- }
54
- const data = (await response.json());
55
- return data.choices[0].message.content.trim();
56
- }
57
- catch (error) {
58
- console.error("Error generating commit message:", error);
59
- throw new Error("Failed to generate commit message");
60
- }
61
- }
@@ -1,7 +0,0 @@
1
- export interface GitPTConfig {
2
- apiKey: string;
3
- model: string;
4
- }
5
- export declare function getConfig(): GitPTConfig | null;
6
- export declare function saveConfig(newConfig: GitPTConfig): void;
7
- export declare function clearConfig(): void;
@@ -1,24 +0,0 @@
1
- import Configstore from 'configstore';
2
- import chalk from 'chalk';
3
- const config = new Configstore('gitpt');
4
- export function getConfig() {
5
- try {
6
- const apiKey = config.get('apiKey');
7
- const model = config.get('model');
8
- if (!apiKey || !model) {
9
- return null;
10
- }
11
- return { apiKey, model };
12
- }
13
- catch (error) {
14
- console.error(chalk.red('Error reading configuration:'), error);
15
- return null;
16
- }
17
- }
18
- export function saveConfig(newConfig) {
19
- config.set('apiKey', newConfig.apiKey);
20
- config.set('model', newConfig.model);
21
- }
22
- export function clearConfig() {
23
- config.clear();
24
- }
@@ -1,6 +0,0 @@
1
- export declare function isGitRepository(): boolean;
2
- export declare function getStagedChanges(): string;
3
- export declare function getStagedFiles(): string[];
4
- export declare function hasStagedChanges(): boolean;
5
- export declare function executeGitAdd(files: string[]): void;
6
- export declare function executeGitCommit(message: string, additionalArgs?: string[]): void;
package/dist/utils/git.js DELETED
@@ -1,62 +0,0 @@
1
- import { execSync } from 'child_process';
2
- import chalk from 'chalk';
3
- export function isGitRepository() {
4
- try {
5
- execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
6
- return true;
7
- }
8
- catch (error) {
9
- return false;
10
- }
11
- }
12
- export function getStagedChanges() {
13
- try {
14
- return execSync('git diff --staged').toString();
15
- }
16
- catch (error) {
17
- console.error(chalk.red('Error getting staged changes:'), error);
18
- throw new Error('Failed to get staged changes');
19
- }
20
- }
21
- export function getStagedFiles() {
22
- try {
23
- const result = execSync('git diff --staged --name-only').toString();
24
- return result.split('\n').filter(Boolean);
25
- }
26
- catch (error) {
27
- console.error(chalk.red('Error getting staged files:'), error);
28
- throw new Error('Failed to get staged files');
29
- }
30
- }
31
- export function hasStagedChanges() {
32
- try {
33
- const output = execSync('git diff --staged --quiet || echo "has-changes"').toString();
34
- return output.includes('has-changes');
35
- }
36
- catch (error) {
37
- return true; // Assume there are changes if we can't check
38
- }
39
- }
40
- export function executeGitAdd(files) {
41
- try {
42
- if (files.length === 0) {
43
- throw new Error('No files specified');
44
- }
45
- const fileArgs = files.join(' ');
46
- execSync(`git add ${fileArgs}`, { stdio: 'inherit' });
47
- }
48
- catch (error) {
49
- console.error(chalk.red('Error adding files:'), error);
50
- throw new Error('Failed to add files to git');
51
- }
52
- }
53
- export function executeGitCommit(message, additionalArgs = []) {
54
- try {
55
- const args = additionalArgs.join(' ');
56
- execSync(`git commit -m "${message}" ${args}`, { stdio: 'inherit' });
57
- }
58
- catch (error) {
59
- console.error(chalk.red('Error committing changes:'), error);
60
- throw new Error('Failed to commit changes');
61
- }
62
- }