gitpt 1.2.0 → 1.4.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 +22 -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
@@ -0,0 +1,60 @@
1
+ import chalk from "chalk";
2
+ import inquirer from "inquirer";
3
+ import { saveConfig } from "../../../config.js";
4
+ import { getAvailableModels } from "./getAvailableModels.js";
5
+ import { selectModel } from "./selectModel.js";
6
+ /**
7
+ * Set up a local LLM configuration
8
+ */
9
+ export const setupLocalLLM = async (existingConfig) => {
10
+ console.log(chalk.blue("Local LLM Setup"));
11
+ const endpointAnswer = await inquirer.prompt([
12
+ {
13
+ type: "input",
14
+ name: "localLLMEndpoint",
15
+ message: "Enter local LLM API endpoint (e.g., http://127.0.0.1:1234):",
16
+ default: existingConfig.customLLMEndpoint || "http://127.0.0.1:1234",
17
+ validate: (input) => {
18
+ if (!input)
19
+ return "API endpoint is required";
20
+ if (!input.startsWith("http://") && !input.startsWith("https://")) {
21
+ return "Must be a valid URL starting with http:// or https://";
22
+ }
23
+ return true;
24
+ },
25
+ },
26
+ ]);
27
+ console.log(chalk.gray("Trying to fetch available models from local LLM server..."));
28
+ const models = await getAvailableModels({
29
+ baseURLOverride: endpointAnswer.localLLMEndpoint,
30
+ });
31
+ let selectedModel;
32
+ if (models.length > 0) {
33
+ console.log(chalk.green(`✓ Found ${models.length} models available on your local LLM server`));
34
+ selectedModel = await selectModel(models, existingConfig.model);
35
+ }
36
+ else {
37
+ console.log(chalk.yellow("Could not fetch models from local LLM server, please enter model name manually"));
38
+ const modelAnswer = await inquirer.prompt([
39
+ {
40
+ type: "input",
41
+ name: "model",
42
+ message: "Enter model name to use with local endpoint:",
43
+ default: existingConfig.model,
44
+ validate: (input) => (input ? true : "Model name is required"),
45
+ },
46
+ ]);
47
+ selectedModel = modelAnswer.model;
48
+ }
49
+ const updatedConfig = {
50
+ ...existingConfig,
51
+ provider: "local",
52
+ model: selectedModel,
53
+ customLLMEndpoint: endpointAnswer.localLLMEndpoint,
54
+ };
55
+ // Save the config
56
+ saveConfig(updatedConfig);
57
+ console.log(chalk.green("✓ Local LLM configuration saved"));
58
+ console.log(chalk.gray("Testing connection to local LLM..."));
59
+ return updatedConfig;
60
+ };
@@ -0,0 +1,2 @@
1
+ import { GitPTConfig } from "../../../config.js";
2
+ export declare const setupOpenRouter: (existingConfig: GitPTConfig) => Promise<GitPTConfig>;
@@ -0,0 +1,66 @@
1
+ import chalk from "chalk";
2
+ import inquirer from "inquirer";
3
+ import { OPENROUTER_API_URL } from "../../../llm/index.js";
4
+ import { saveConfig } from "../../../config.js";
5
+ import { getAvailableModels } from "./getAvailableModels.js";
6
+ import { getOrUpdateApiKey } from "./getOrUpdateApiKey.js";
7
+ import { selectModel } from "./selectModel.js";
8
+ export const setupOpenRouter = async (existingConfig) => {
9
+ // Get API key - either the existing one or a new one
10
+ const apiKey = await getOrUpdateApiKey(existingConfig.apiKey);
11
+ if (!apiKey) {
12
+ console.error(chalk.red("API key is required for OpenRouter."));
13
+ process.exit(1);
14
+ }
15
+ // Update the config with the potentially new API key
16
+ const updatedConfig = { ...existingConfig, apiKey };
17
+ // Display current model if any
18
+ if (updatedConfig.model) {
19
+ console.log("Current model:", chalk.yellow(updatedConfig.model));
20
+ console.log("");
21
+ }
22
+ try {
23
+ console.log(chalk.gray("Fetching available models from OpenRouter..."));
24
+ const models = await getAvailableModels({
25
+ baseURLOverride: OPENROUTER_API_URL,
26
+ });
27
+ if (models.length > 0) {
28
+ console.log(chalk.green(`✓ Found ${models.length} models available with your API key`));
29
+ }
30
+ else {
31
+ console.log(chalk.yellow("No models found from OpenRouter. Please specify a model manually."));
32
+ }
33
+ const selectedModel = await selectModel(models, updatedConfig.model);
34
+ const finalConfig = {
35
+ ...updatedConfig,
36
+ model: selectedModel,
37
+ useLocalLLM: false,
38
+ };
39
+ // Save the config
40
+ saveConfig(finalConfig);
41
+ console.log(chalk.green(`✓ Model set to: ${chalk.yellow(selectedModel)}`));
42
+ return finalConfig;
43
+ }
44
+ catch (error) {
45
+ console.error(chalk.yellow(`Error fetching models: ${error}`));
46
+ // Fallback to manual input if API call fails
47
+ const modelAnswer = await inquirer.prompt([
48
+ {
49
+ type: "input",
50
+ name: "model",
51
+ message: "Enter model identifier:",
52
+ validate: (input) => input ? true : "Model identifier is required",
53
+ },
54
+ ]);
55
+ const selectedModel = modelAnswer.model;
56
+ const finalConfig = {
57
+ ...updatedConfig,
58
+ model: selectedModel,
59
+ useLocalLLM: false,
60
+ };
61
+ // Save the config
62
+ saveConfig(finalConfig);
63
+ console.log(chalk.green(`✓ Model set to: ${chalk.yellow(selectedModel)}`));
64
+ return finalConfig;
65
+ }
66
+ };
@@ -0,0 +1,13 @@
1
+ export interface Model {
2
+ id: string;
3
+ name?: string;
4
+ context_length?: number;
5
+ pricing?: {
6
+ prompt: number;
7
+ completion: number;
8
+ };
9
+ }
10
+ export interface ModelResponse {
11
+ data: Model[];
12
+ object?: string;
13
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1 +1 @@
1
- export declare function modelCommand(modelId?: string): Promise<void>;
1
+ export declare const modelCommand: () => Promise<void>;
@@ -1,114 +1,6 @@
1
- import inquirer from 'inquirer';
2
- import chalk from 'chalk';
3
- import fetch from 'node-fetch';
4
- import { getConfig, saveConfig } from '../utils/config.js';
5
- // List of popular models available on OpenRouter
6
- const POPULAR_MODELS = [
7
- { name: 'Claude 3 Opus - Anthropic', value: 'anthropic/claude-3-opus:beta' },
8
- { name: 'Claude 3 Sonnet - Anthropic', value: 'anthropic/claude-3-sonnet:beta' },
9
- { name: 'Claude 3 Haiku - Anthropic', value: 'anthropic/claude-3-haiku:beta' },
10
- { name: 'GPT-4o - OpenAI', value: 'openai/gpt-4o' },
11
- { name: 'GPT-4 Turbo - OpenAI', value: 'openai/gpt-4-turbo' },
12
- { name: 'GPT-3.5 Turbo - OpenAI', value: 'openai/gpt-3.5-turbo' },
13
- { name: 'Other (specify model identifier)', value: 'custom' }
14
- ];
15
- async function fetchAvailableModels(apiKey) {
16
- try {
17
- const response = await fetch('https://openrouter.ai/api/v1/models', {
18
- headers: {
19
- 'Authorization': `Bearer ${apiKey}`,
20
- 'HTTP-Referer': 'https://github.com/bartaxyz/GitPT',
21
- }
22
- });
23
- if (!response.ok) {
24
- throw new Error(`Failed to fetch models: ${response.status} ${response.statusText}`);
25
- }
26
- const data = await response.json();
27
- return data.data;
28
- }
29
- catch (error) {
30
- console.error(chalk.red('Error fetching models:'), error);
31
- return [];
32
- }
33
- }
34
- export async function modelCommand(modelId) {
35
- console.log(chalk.blue('GitPT Model Selection'));
36
- // Check if config exists
37
- const existingConfig = getConfig();
38
- if (!existingConfig) {
39
- console.error(chalk.red('GitPT is not configured. Please run "gitpt setup" first.'));
40
- process.exit(1);
41
- }
42
- let selectedModel;
43
- // If a model ID is provided directly, use it
44
- if (modelId) {
45
- selectedModel = modelId;
46
- // Update config with the new model while keeping the existing API key
47
- saveConfig({
48
- apiKey: existingConfig.apiKey,
49
- model: selectedModel
50
- });
51
- console.log(chalk.green(`✓ Model set to: ${chalk.yellow(selectedModel)}`));
52
- return;
53
- }
54
- // Otherwise, show interactive selection
55
- console.log('Current model:', chalk.yellow(existingConfig.model));
56
- console.log('');
57
- try {
58
- // Try to fetch available models from OpenRouter
59
- console.log(chalk.gray('Fetching available models from OpenRouter...'));
60
- const availableModels = await fetchAvailableModels(existingConfig.apiKey);
61
- let modelChoices;
62
- if (availableModels.length > 0) {
63
- // Convert available models to choices format
64
- modelChoices = availableModels.map(model => ({
65
- name: `${model.name} (Context: ${model.context_length})`,
66
- value: model.id
67
- }));
68
- // Add custom option at the end
69
- modelChoices.push({ name: 'Other (specify model identifier)', value: 'custom' });
70
- console.log(chalk.green(`✓ Found ${availableModels.length} models available with your API key`));
71
- }
72
- else {
73
- // Fallback to predefined list if API call fails
74
- console.log(chalk.yellow('Could not fetch models from OpenRouter, using predefined list'));
75
- modelChoices = POPULAR_MODELS;
76
- }
77
- const answers = await inquirer.prompt([
78
- {
79
- type: 'list',
80
- name: 'modelChoice',
81
- message: 'Select an AI model:',
82
- choices: modelChoices,
83
- default: () => {
84
- // Try to find current model in the list to set as default
85
- const currentIndex = modelChoices.findIndex(choice => choice.value === existingConfig.model);
86
- return currentIndex >= 0 ? currentIndex : 0;
87
- }
88
- },
89
- {
90
- type: 'input',
91
- name: 'customModel',
92
- message: 'Enter model identifier:',
93
- when: (answers) => answers.modelChoice === 'custom',
94
- validate: (input) => {
95
- if (!input)
96
- return 'Model identifier is required';
97
- return true;
98
- }
99
- }
100
- ]);
101
- // Get the selected model
102
- selectedModel = answers.modelChoice === 'custom' ? answers.customModel : answers.modelChoice;
103
- // Save the updated configuration
104
- saveConfig({
105
- apiKey: existingConfig.apiKey,
106
- model: selectedModel
107
- });
108
- console.log(chalk.green(`✓ Model updated to: ${chalk.yellow(selectedModel)}`));
109
- }
110
- catch (error) {
111
- console.error(chalk.red('Error updating model:'), error);
112
- process.exit(1);
113
- }
114
- }
1
+ import chalk from "chalk";
2
+ import { setupMiddleware } from "./middleware/setupMiddleware/index.js";
3
+ export const modelCommand = async () => {
4
+ console.log(chalk.blue("GitPT Model Selection"));
5
+ await setupMiddleware({ context: "model" });
6
+ };
@@ -0,0 +1 @@
1
+ export declare const systemPrompt = "\nYou are a helpful assistant that generates clear, informative GitHub pull request titles and descriptions.\n\nFor the title:\n- Keep it concise (under 80 characters)\n- Start with a verb in present tense (e.g., \"Add\", \"Fix\", \"Update\")\n- Clearly summarize the main purpose of the changes\n\nFor the description:\n- Start with a brief summary (1-2 sentences) of what the PR accomplishes\n- Include a more detailed explanation of changes if needed\n- List key changes as bullet points if there are multiple components\n- Include any relevant context that reviewers should know\n- End with any testing instructions if applicable\n\nFormat the description in Markdown with sections.\nDo not include \"PR\" or \"Pull Request\" in the title.\n";
@@ -0,0 +1,18 @@
1
+ export const systemPrompt = `
2
+ You are a helpful assistant that generates clear, informative GitHub pull request titles and descriptions.
3
+
4
+ For the title:
5
+ - Keep it concise (under 80 characters)
6
+ - Start with a verb in present tense (e.g., "Add", "Fix", "Update")
7
+ - Clearly summarize the main purpose of the changes
8
+
9
+ For the description:
10
+ - Start with a brief summary (1-2 sentences) of what the PR accomplishes
11
+ - Include a more detailed explanation of changes if needed
12
+ - List key changes as bullet points if there are multiple components
13
+ - Include any relevant context that reviewers should know
14
+ - End with any testing instructions if applicable
15
+
16
+ Format the description in Markdown with sections.
17
+ Do not include "PR" or "Pull Request" in the title.
18
+ `;
@@ -0,0 +1 @@
1
+ export declare const userPrompt: (context: string) => string;
@@ -0,0 +1,22 @@
1
+ export const userPrompt = (context) => `
2
+ Generate a pull request title and description for the following changes:
3
+
4
+ ${context}
5
+
6
+ Format your response exactly like this example:
7
+ Title: Add user authentication with JWT
8
+ Description:
9
+ ## Summary
10
+ This PR adds user authentication using JWT tokens.
11
+
12
+ ## Changes
13
+ - Implement login and registration endpoints
14
+ - Add JWT generation and validation
15
+ - Update user model with password hashing
16
+ - Add authorization middleware
17
+
18
+ ## How to test
19
+ 1. Register a new user with \`/api/register\`
20
+ 2. Login with the new user credentials
21
+ 3. Use the returned token to access protected endpoints
22
+ `;
@@ -0,0 +1,4 @@
1
+ export declare const generatePRDetails: () => Promise<{
2
+ title: string;
3
+ body: string;
4
+ }>;
@@ -0,0 +1,35 @@
1
+ import chalk from "chalk";
2
+ import { getConfig } from "../../config.js";
3
+ import { getLLMClient } from "../../llm/index.js";
4
+ import { systemPrompt } from "./context/systemPrompt.js";
5
+ import { userPrompt } from "./context/userPrompt.js";
6
+ import { getPRContext } from "./getPRContext.js";
7
+ export const generatePRDetails = async () => {
8
+ const { model } = getConfig();
9
+ const context = getPRContext().join("\n\n");
10
+ const userPromptWithContext = userPrompt(context);
11
+ const llmClient = getLLMClient();
12
+ try {
13
+ const response = await llmClient.chat.completions.create({
14
+ model: model,
15
+ messages: [
16
+ { role: "system", content: systemPrompt },
17
+ { role: "user", content: userPromptWithContext },
18
+ ],
19
+ max_completion_tokens: 1000,
20
+ });
21
+ const result = response.choices[0].message?.content?.trim();
22
+ if (!result) {
23
+ throw new Error("No response from LLM");
24
+ }
25
+ const titleMatch = result.match(/Title:\s*(.+?)(?:\n|$)/);
26
+ const descMatch = result.match(/Description:\s*\n([\s\S]+)$/);
27
+ const title = titleMatch ? titleMatch[1].trim() : "";
28
+ const body = descMatch ? descMatch[1].trim() : result;
29
+ return { title, body };
30
+ }
31
+ catch (error) {
32
+ console.error(chalk.red("Error generating PR details:"), error);
33
+ throw new Error("Failed to generate PR details");
34
+ }
35
+ };
@@ -0,0 +1 @@
1
+ export declare const getPRContext: () => string[];
@@ -0,0 +1,65 @@
1
+ import chalk from "chalk";
2
+ import { execSync } from "child_process";
3
+ import { git } from "../../services/git/index.js";
4
+ export const getPRContext = () => {
5
+ const currentBranch = git.getCurrentBranch();
6
+ const baseBranch = git.getDefaultBranch();
7
+ // Get context for PR
8
+ const commitMessages = git.getCommitsSinceBaseBranch(baseBranch);
9
+ const changedFiles = git.getChangedFiles(baseBranch);
10
+ // Check if we have any content to work with
11
+ if (commitMessages.length === 0 && changedFiles.length === 0) {
12
+ console.log(chalk.yellow("No commits or changed files detected."));
13
+ console.log(chalk.yellow("Will attempt to generate PR details using branch name and repository context."));
14
+ }
15
+ // Get additional context from repository
16
+ let repoName = "";
17
+ let repoDescription = "";
18
+ try {
19
+ // Try to get repo information from GitHub CLI
20
+ const repoInfo = JSON.parse(execSync("gh repo view --json name,description").toString().trim());
21
+ repoName = repoInfo.name || "";
22
+ repoDescription = repoInfo.description || "";
23
+ }
24
+ catch (error) {
25
+ // Continue without this info
26
+ }
27
+ console.log(chalk.blue("Generating PR title and description..."));
28
+ // Build a rich context for the AI
29
+ let contextSections = [
30
+ `Branch: ${currentBranch}`,
31
+ `Base branch: ${baseBranch}`,
32
+ ];
33
+ // Add repository info if available
34
+ if (repoName) {
35
+ contextSections.push(`Repository: ${repoName}`);
36
+ }
37
+ if (repoDescription) {
38
+ contextSections.push(`Repository description: ${repoDescription}`);
39
+ }
40
+ // Add commit messages if available
41
+ if (commitMessages.length > 0) {
42
+ contextSections.push("Commit messages in this branch:", commitMessages.map((msg) => `- ${msg}`).join("\n"));
43
+ }
44
+ else {
45
+ contextSections.push("No commit messages available.");
46
+ // Try to extract intent from branch name if no commits
47
+ if (currentBranch.includes("/")) {
48
+ const branchParts = currentBranch.split("/");
49
+ const branchType = branchParts[0]; // e.g., "feature", "fix", "chore"
50
+ const branchDescription = branchParts
51
+ .slice(1)
52
+ .join("/")
53
+ .replace(/-/g, " ");
54
+ contextSections.push("Branch name analysis:", `Type: ${branchType}`, `Description: ${branchDescription}`);
55
+ }
56
+ }
57
+ // Add changed files if available
58
+ if (changedFiles.length > 0) {
59
+ contextSections.push("Files changed in this branch:", changedFiles.map((file) => `- ${file}`).join("\n"));
60
+ }
61
+ else {
62
+ contextSections.push("No file changes detected.");
63
+ }
64
+ return contextSections;
65
+ };
@@ -6,5 +6,5 @@ interface PullRequestOptions {
6
6
  edit?: boolean;
7
7
  [key: string]: any;
8
8
  }
9
- export declare function prCreateCommand(options?: PullRequestOptions): Promise<void>;
9
+ export declare const prCreateCommand: (options?: PullRequestOptions) => Promise<void>;
10
10
  export {};
@@ -0,0 +1,66 @@
1
+ import chalk from "chalk";
2
+ import inquirer from "inquirer";
3
+ import { capabilitiesMiddleware } from "../middleware/capabilitiesMiddleware/index.js";
4
+ import { setupMiddleware } from "../middleware/setupMiddleware/index.js";
5
+ import { gh } from "../../services/gh/index.js";
6
+ import { git } from "../../services/git/index.js";
7
+ import { generatePRDetails } from "./generatePRDetails.js";
8
+ export const prCreateCommand = async (options = {}) => {
9
+ capabilitiesMiddleware(["git", "gh"]);
10
+ await setupMiddleware();
11
+ try {
12
+ const baseBranch = options.base || git.getDefaultBranch();
13
+ let title = options.title || "";
14
+ let body = options.body || "";
15
+ // Generate PR details if not provided
16
+ if (!title || !body) {
17
+ const generatedDetails = await generatePRDetails();
18
+ title = title || generatedDetails.title;
19
+ body = body || generatedDetails.body;
20
+ console.log(chalk.green("✓ PR details generated"));
21
+ console.log("");
22
+ console.log(chalk.cyan("Title:"));
23
+ console.log(title);
24
+ console.log("");
25
+ console.log(chalk.cyan("Description:"));
26
+ console.log(body);
27
+ console.log("");
28
+ }
29
+ // Allow editing PR details
30
+ if (options.edit !== false) {
31
+ const answers = await inquirer.prompt([
32
+ {
33
+ type: "input",
34
+ name: "title",
35
+ message: "Edit PR title:",
36
+ default: title,
37
+ },
38
+ {
39
+ type: "editor",
40
+ name: "body",
41
+ message: "Edit PR description:",
42
+ default: body,
43
+ },
44
+ {
45
+ type: "confirm",
46
+ name: "draft",
47
+ message: "Create as draft PR?",
48
+ default: options.draft || false,
49
+ },
50
+ ]);
51
+ title = answers.title;
52
+ body = answers.body;
53
+ const isDraft = answers.draft;
54
+ // Create the PR
55
+ gh.createPullRequest(title, body, baseBranch, isDraft);
56
+ }
57
+ else {
58
+ // Create the PR without editing
59
+ gh.createPullRequest(title, body, baseBranch, options.draft || false);
60
+ }
61
+ }
62
+ catch (error) {
63
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
64
+ process.exit(1);
65
+ }
66
+ };
@@ -1 +1,3 @@
1
- export declare function setupCommand(): Promise<void>;
1
+ export declare const setupCommand: (options?: {
2
+ clearConfig?: boolean;
3
+ }) => Promise<void>;
@@ -1,60 +1,15 @@
1
- import inquirer from 'inquirer';
2
- import chalk from 'chalk';
3
- import { saveConfig, clearConfig } from '../utils/config.js';
4
- // List of popular models available on OpenRouter
5
- const POPULAR_MODELS = [
6
- { name: 'Claude 3 Opus - Anthropic', value: 'anthropic/claude-3-opus:beta' },
7
- { name: 'Claude 3 Sonnet - Anthropic', value: 'anthropic/claude-3-sonnet:beta' },
8
- { name: 'Claude 3 Haiku - Anthropic', value: 'anthropic/claude-3-haiku:beta' },
9
- { name: 'GPT-4o - OpenAI', value: 'openai/gpt-4o' },
10
- { name: 'GPT-4 Turbo - OpenAI', value: 'openai/gpt-4-turbo' },
11
- { name: 'GPT-3.5 Turbo - OpenAI', value: 'openai/gpt-3.5-turbo' },
12
- { name: 'Other (specify model identifier)', value: 'custom' }
13
- ];
14
- export async function setupCommand() {
15
- console.log(chalk.blue('GitPT Setup'));
16
- console.log('This will configure GitPT to use OpenRouter for generating commit messages.');
17
- console.log('If you don\'t have an OpenRouter account yet, sign up at https://openrouter.ai');
18
- console.log('');
19
- const answers = await inquirer.prompt([
20
- {
21
- type: 'input',
22
- name: 'apiKey',
23
- message: 'Enter your OpenRouter API key:',
24
- validate: (input) => {
25
- if (!input)
26
- return 'API key is required';
27
- return true;
28
- }
29
- },
30
- {
31
- type: 'list',
32
- name: 'modelChoice',
33
- message: 'Select an AI model:',
34
- choices: POPULAR_MODELS
35
- },
36
- {
37
- type: 'input',
38
- name: 'customModel',
39
- message: 'Enter model identifier:',
40
- when: (answers) => answers.modelChoice === 'custom',
41
- validate: (input) => {
42
- if (!input)
43
- return 'Model identifier is required';
44
- return true;
45
- }
46
- }
47
- ]);
48
- // Clear existing config before saving new one
49
- clearConfig();
50
- // Save the new configuration
51
- const model = answers.modelChoice === 'custom' ? answers.customModel : answers.modelChoice;
52
- saveConfig({
53
- apiKey: answers.apiKey,
54
- model: model
55
- });
56
- console.log(chalk.green('✓ GitPT configuration saved successfully'));
57
- console.log(`Model set to: ${chalk.yellow(model)}`);
58
- console.log('');
59
- console.log(`Use ${chalk.cyan('gitpt commit')} to create commits with AI-generated messages.`);
60
- }
1
+ import chalk from "chalk";
2
+ import { clearConfig } from "../config.js";
3
+ import { setupMiddleware } from "./middleware/setupMiddleware/index.js";
4
+ export const setupCommand = async (options = {}) => {
5
+ console.log(chalk.blue("GitPT Setup"));
6
+ console.log("This will configure GitPT to use an LLM for generating commit messages.");
7
+ console.log("You can use either OpenRouter (remote service) or a local LLM.");
8
+ console.log("");
9
+ if (options.clearConfig) {
10
+ clearConfig();
11
+ }
12
+ await setupMiddleware({ context: "setup" });
13
+ console.log("");
14
+ console.log(`Use ${chalk.cyan("gitpt commit")} to create commits with AI-generated messages.`);
15
+ };
@@ -0,0 +1,18 @@
1
+ export interface GitPTConfig {
2
+ provider?: "openrouter" | "local";
3
+ customLLMEndpoint?: string;
4
+ model?: string;
5
+ apiKey?: string;
6
+ }
7
+ export declare const getConfig: () => GitPTConfig;
8
+ export declare const saveConfig: (newConfig: GitPTConfig) => void;
9
+ export declare enum ConfigErrors {
10
+ CustomLLMEndpointRequired = "Custom LLM endpoint is required for local LLM provider.",
11
+ APIKeyRequired = "API key is required for OpenRouter provider.",
12
+ ModelRequired = "Model is required."
13
+ }
14
+ export declare const validateConfig: () => {
15
+ isValid: boolean;
16
+ errors?: string[];
17
+ };
18
+ export declare const clearConfig: () => void;