gitpt 1.1.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 +52 -32
  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 +25 -0
  85. package/dist/utils/commitlint.js +148 -0
  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 -6
  91. package/dist/commands/add.d.ts +0 -1
  92. package/dist/commands/add.js +0 -16
  93. package/dist/commands/commit.js +0 -74
  94. package/dist/commands/pr.js +0 -458
  95. package/dist/utils/api.d.ts +0 -1
  96. package/dist/utils/api.js +0 -58
  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,24 @@
1
+ import { executeGitAdd } from "./executeGitAdd.js";
2
+ import { executeGitCommit } from "./executeGitCommit.js";
3
+ import { getChangedFiles } from "./getChangedFiles.js";
4
+ import { getCommitsSinceBaseBranch } from "./getCommitsSinceBaseBranch.js";
5
+ import { getCurrentBranch } from "./getCurrentBranch.js";
6
+ import { getDefaultBranch } from "./getDefaultBranch.js";
7
+ import { getStagedChanges } from "./getStagedChanges.js";
8
+ import { getStagedFiles } from "./getStagedFiles.js";
9
+ import { hasStagedChanges } from "./hasStagedChanges.js";
10
+ import { isAvailable } from "./isAvailable.js";
11
+ import { isGitRepository } from "./isGitRepository.js";
12
+ export const git = {
13
+ add: executeGitAdd,
14
+ commit: executeGitCommit,
15
+ getChangedFiles,
16
+ getCommitsSinceBaseBranch,
17
+ getCurrentBranch,
18
+ getDefaultBranch,
19
+ hasStagedChanges,
20
+ getStagedChanges,
21
+ getStagedFiles,
22
+ isAvailable,
23
+ isGitRepository,
24
+ };
@@ -0,0 +1 @@
1
+ export declare const isAvailable: () => boolean;
@@ -0,0 +1,10 @@
1
+ import { execSync } from "child_process";
2
+ export const isAvailable = () => {
3
+ try {
4
+ execSync("git --version", { stdio: "ignore" });
5
+ return true;
6
+ }
7
+ catch (error) {
8
+ return false;
9
+ }
10
+ };
@@ -0,0 +1 @@
1
+ export declare const isGitRepository: () => boolean;
@@ -0,0 +1,10 @@
1
+ import { execSync } from "child_process";
2
+ export const isGitRepository = () => {
3
+ try {
4
+ execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" });
5
+ return true;
6
+ }
7
+ catch (error) {
8
+ return false;
9
+ }
10
+ };
@@ -0,0 +1,25 @@
1
+ export interface CommitlintConfig {
2
+ rules?: Record<string, any>;
3
+ extends?: string | string[];
4
+ }
5
+ /**
6
+ * Check if a commitlint configuration exists in the repository
7
+ */
8
+ export declare function hasCommitlintConfig(): boolean;
9
+ /**
10
+ * Read commitlint config file (using @commitlint/load) and print it out
11
+ */
12
+ export declare function readCommitlintConfig(): Promise<any>;
13
+ /**
14
+ * Get the commitlint configuration format rules as a string
15
+ */
16
+ export declare function getCommitlintRules(): string;
17
+ /**
18
+ * Validate a commit message against commitlint rules
19
+ * @param message The commit message to validate
20
+ * @returns An object with success status and error message if applicable
21
+ */
22
+ export declare function validateCommitMessage(message: string): Promise<{
23
+ valid: boolean;
24
+ errors?: string;
25
+ }>;
@@ -0,0 +1,148 @@
1
+ import loadConfig from "@commitlint/load";
2
+ import { execSync } from "child_process";
3
+ import fs from "fs";
4
+ /**
5
+ * Check if a commitlint configuration exists in the repository
6
+ */
7
+ export function hasCommitlintConfig() {
8
+ const possibleConfigFiles = [
9
+ ".commitlintrc",
10
+ ".commitlintrc.json",
11
+ ".commitlintrc.yaml",
12
+ ".commitlintrc.yml",
13
+ ".commitlintrc.js",
14
+ "commitlint.config.js",
15
+ "package.json",
16
+ ];
17
+ // Temporary
18
+ readCommitlintConfig();
19
+ // Check if any of the possible config files exist
20
+ return possibleConfigFiles.some((file) => {
21
+ try {
22
+ if (file === "package.json") {
23
+ const packageJson = JSON.parse(fs.readFileSync("package.json", "utf8"));
24
+ return packageJson.commitlint !== undefined;
25
+ }
26
+ return fs.existsSync(file);
27
+ }
28
+ catch (error) {
29
+ return false;
30
+ }
31
+ });
32
+ }
33
+ /**
34
+ * Read commitlint config file (using @commitlint/load) and print it out
35
+ */
36
+ export async function readCommitlintConfig() {
37
+ const config = await loadConfig();
38
+ // console.log(config);
39
+ return config.rules;
40
+ }
41
+ /**
42
+ * Get the commitlint configuration format rules as a string
43
+ */
44
+ export function getCommitlintRules() {
45
+ try {
46
+ // Try to get the rules using commitlint CLI if available
47
+ try {
48
+ const rulesOutput = execSync("npx commitlint --print-config", {
49
+ stdio: ["ignore", "pipe", "ignore"],
50
+ }).toString();
51
+ const config = JSON.parse(rulesOutput);
52
+ return formatCommitlintRules(config);
53
+ }
54
+ catch (error) {
55
+ // If CLI approach fails, try to find and parse config files manually
56
+ // This is a simplified approach - in a real implementation, you'd want to handle
57
+ // all possible config files and formats
58
+ if (fs.existsSync("commitlint.config.js")) {
59
+ // We can't directly require the JS file in ESM, so we'll return a generic message
60
+ return "Follow the conventional commit format (type(scope): message)";
61
+ }
62
+ if (fs.existsSync(".commitlintrc.json")) {
63
+ const config = JSON.parse(fs.readFileSync(".commitlintrc.json", "utf8"));
64
+ return formatCommitlintRules(config);
65
+ }
66
+ // Default to conventional commits format if we can't parse the config
67
+ return "Follow the conventional commit format (type(scope): message)";
68
+ }
69
+ }
70
+ catch (error) {
71
+ // If all else fails, return a generic message
72
+ return "Follow the conventional commit format (type(scope): message)";
73
+ }
74
+ }
75
+ /**
76
+ * Format commitlint rules into a human-readable string
77
+ */
78
+ function formatCommitlintRules(config) {
79
+ let rulesDescription = "Follow these commit message rules:\n";
80
+ if (!config.rules) {
81
+ return "Follow the conventional commit format (type(scope): message)";
82
+ }
83
+ // Extract type-enum rule if it exists
84
+ if (config.rules["type-enum"] &&
85
+ Array.isArray(config.rules["type-enum"][2])) {
86
+ const allowedTypes = config.rules["type-enum"][2];
87
+ rulesDescription += `- Commit type must be one of: ${allowedTypes.join(", ")}\n`;
88
+ }
89
+ // Extract other common rules
90
+ if (config.rules["scope-enum"] &&
91
+ Array.isArray(config.rules["scope-enum"][2])) {
92
+ const allowedScopes = config.rules["scope-enum"][2];
93
+ rulesDescription += `- Scope must be one of: ${allowedScopes.join(", ")}\n`;
94
+ }
95
+ if (config.rules["subject-case"]) {
96
+ rulesDescription += `- Subject must follow case rules\n`;
97
+ }
98
+ if (config.rules["subject-max-length"]) {
99
+ const maxLength = config.rules["subject-max-length"][2];
100
+ rulesDescription += `- Subject must be no longer than ${maxLength} characters\n`;
101
+ }
102
+ rulesDescription +=
103
+ "- Use a single commit message, not multiple messages separated by blank lines or markdown formatting";
104
+ return rulesDescription;
105
+ }
106
+ /**
107
+ * Validate a commit message against commitlint rules
108
+ * @param message The commit message to validate
109
+ * @returns An object with success status and error message if applicable
110
+ */
111
+ export async function validateCommitMessage(message) {
112
+ if (!hasCommitlintConfig()) {
113
+ // If no commitlint config exists, consider it valid
114
+ return { valid: true };
115
+ }
116
+ // Using CLI approach
117
+ try {
118
+ // Create a temporary file with the message
119
+ const tempFile = `/tmp/gitpt-commit-msg-${Date.now()}`;
120
+ fs.writeFileSync(tempFile, message);
121
+ try {
122
+ execSync(`npx commitlint < ${tempFile}`, { stdio: "ignore" });
123
+ fs.unlinkSync(tempFile);
124
+ return { valid: true };
125
+ }
126
+ catch (error) {
127
+ // It's likely a validation error, capture the output
128
+ try {
129
+ const errorOutput = execSync(`npx commitlint < ${tempFile} 2>&1 || true`).toString();
130
+ fs.unlinkSync(tempFile);
131
+ return {
132
+ valid: false,
133
+ errors: errorOutput,
134
+ };
135
+ }
136
+ catch (e) {
137
+ // If we still can't get error output, fall back to basic pattern check
138
+ fs.unlinkSync(tempFile);
139
+ return { valid: true };
140
+ }
141
+ }
142
+ }
143
+ catch (error) {
144
+ // If all else fails, just do a basic regex check
145
+ console.warn("Warning: Could not validate with commitlint, performing basic validation");
146
+ return { valid: true };
147
+ }
148
+ }
@@ -0,0 +1 @@
1
+ export declare const formatBaseURL: (baseURL: string) => string;
@@ -0,0 +1,7 @@
1
+ export const formatBaseURL = (baseURL) => {
2
+ // If it doesn't end with /v1, add it
3
+ if (!baseURL.endsWith("/v1")) {
4
+ return `${baseURL}/v1`;
5
+ }
6
+ return baseURL;
7
+ };
@@ -0,0 +1 @@
1
+ export declare const maskApiKey: (apiKey: string) => string;
@@ -0,0 +1,8 @@
1
+ export const maskApiKey = (apiKey) => {
2
+ if (apiKey.length <= 10) {
3
+ return "*".repeat(apiKey.length);
4
+ }
5
+ const firstFour = apiKey.substring(0, 4);
6
+ const lastFour = apiKey.substring(apiKey.length - 4);
7
+ return `${firstFour}...${lastFour}`;
8
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitpt",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "CLI tool that helps you write commit messages & pull request descriptions using AI",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -13,10 +13,9 @@
13
13
  "LICENSE"
14
14
  ],
15
15
  "scripts": {
16
+ "typecheck": "tsc --noEmit",
16
17
  "build": "tsc",
17
- "dev": "ts-node --esm src/index.ts",
18
- "start": "node dist/index.js",
19
- "test": "echo \"Error: no test specified\" && exit 1",
18
+ "test": "npm run typecheck",
20
19
  "prepublishOnly": "npm run build"
21
20
  },
22
21
  "repository": {
@@ -39,14 +38,18 @@
39
38
  "@types/inquirer": "^9.0.7",
40
39
  "@types/node": "^22.14.1",
41
40
  "@types/node-fetch": "^2.6.12",
42
- "ts-node": "^10.9.2",
41
+ "tsc-alias": "^1.8.16",
43
42
  "typescript": "^5.8.3"
44
43
  },
45
44
  "dependencies": {
45
+ "@commitlint/cli": "^19.8.1",
46
+ "@commitlint/config-conventional": "^19.8.1",
47
+ "@commitlint/load": "^19.8.1",
46
48
  "chalk": "^5.4.1",
47
49
  "commander": "^13.1.0",
48
50
  "configstore": "^7.0.0",
49
51
  "inquirer": "^12.5.2",
50
- "node-fetch": "^3.3.2"
52
+ "node-fetch": "^3.3.2",
53
+ "openai": "^4.100.0"
51
54
  }
52
55
  }
@@ -1 +0,0 @@
1
- export declare function addCommand(files: string[]): void;
@@ -1,16 +0,0 @@
1
- import chalk from 'chalk';
2
- import { isGitRepository, executeGitAdd } from '../utils/git.js';
3
- export function addCommand(files) {
4
- if (!isGitRepository()) {
5
- console.error(chalk.red('Error: Not a git repository'));
6
- process.exit(1);
7
- }
8
- try {
9
- executeGitAdd(files);
10
- console.log(chalk.green('Files added to staging area'));
11
- }
12
- catch (error) {
13
- console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
14
- process.exit(1);
15
- }
16
- }
@@ -1,74 +0,0 @@
1
- import inquirer from 'inquirer';
2
- import chalk from 'chalk';
3
- import { isGitRepository, hasStagedChanges, getStagedChanges, executeGitCommit } from '../utils/git.js';
4
- import { generateCommitMessage } from '../utils/api.js';
5
- import { getConfig } from '../utils/config.js';
6
- export async function commitCommand(options) {
7
- if (!isGitRepository()) {
8
- console.error(chalk.red('Error: Not a git repository'));
9
- process.exit(1);
10
- }
11
- // Check if config exists
12
- const config = getConfig();
13
- if (!config) {
14
- console.error(chalk.red('GitPT is not configured. Please run "gitpt setup" first.'));
15
- process.exit(1);
16
- }
17
- // Check if there are staged changes
18
- if (!hasStagedChanges()) {
19
- console.error(chalk.yellow('No staged changes. Use "git add" or "gitpt add" to stage changes first.'));
20
- process.exit(1);
21
- }
22
- let commitMessage;
23
- // If message is provided, use that
24
- if (options.message) {
25
- commitMessage = options.message;
26
- }
27
- else {
28
- try {
29
- // Get staged changes
30
- const diff = getStagedChanges();
31
- console.log(chalk.blue('Generating commit message...'));
32
- // Generate commit message
33
- commitMessage = await generateCommitMessage(diff);
34
- console.log(chalk.green('✓ Commit message generated'));
35
- console.log('');
36
- console.log(chalk.cyan('Generated message:'));
37
- console.log(commitMessage);
38
- console.log('');
39
- }
40
- catch (error) {
41
- console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
42
- process.exit(1);
43
- }
44
- }
45
- // If edit is true or not specified, prompt user to edit the message
46
- if (options.edit !== false) {
47
- const answer = await inquirer.prompt([
48
- {
49
- type: 'editor',
50
- name: 'message',
51
- message: 'Edit commit message:',
52
- default: commitMessage
53
- }
54
- ]);
55
- commitMessage = answer.message;
56
- }
57
- // Extract other git options to pass through
58
- const gitOptions = Object.keys(options)
59
- .filter(key => !['message', 'edit'].includes(key))
60
- .map(key => {
61
- if (typeof options[key] === 'boolean') {
62
- return options[key] ? `--${key}` : `--no-${key}`;
63
- }
64
- return `--${key}=${options[key]}`;
65
- });
66
- try {
67
- executeGitCommit(commitMessage, gitOptions);
68
- console.log(chalk.green('✓ Changes committed successfully'));
69
- }
70
- catch (error) {
71
- console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
72
- process.exit(1);
73
- }
74
- }