@ksw8954/git-ai-commit 1.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.
Files changed (77) hide show
  1. package/AGENTS.md +38 -0
  2. package/CRUSH.md +28 -0
  3. package/Makefile +32 -0
  4. package/README.md +145 -0
  5. package/dist/commands/ai.d.ts +35 -0
  6. package/dist/commands/ai.d.ts.map +1 -0
  7. package/dist/commands/ai.js +206 -0
  8. package/dist/commands/ai.js.map +1 -0
  9. package/dist/commands/commit.d.ts +17 -0
  10. package/dist/commands/commit.d.ts.map +1 -0
  11. package/dist/commands/commit.js +126 -0
  12. package/dist/commands/commit.js.map +1 -0
  13. package/dist/commands/config.d.ts +33 -0
  14. package/dist/commands/config.d.ts.map +1 -0
  15. package/dist/commands/config.js +141 -0
  16. package/dist/commands/config.js.map +1 -0
  17. package/dist/commands/configCommand.d.ts +20 -0
  18. package/dist/commands/configCommand.d.ts.map +1 -0
  19. package/dist/commands/configCommand.js +108 -0
  20. package/dist/commands/configCommand.js.map +1 -0
  21. package/dist/commands/git.d.ts +26 -0
  22. package/dist/commands/git.d.ts.map +1 -0
  23. package/dist/commands/git.js +150 -0
  24. package/dist/commands/git.js.map +1 -0
  25. package/dist/commands/loadEnv.d.ts +2 -0
  26. package/dist/commands/loadEnv.d.ts.map +1 -0
  27. package/dist/commands/loadEnv.js +11 -0
  28. package/dist/commands/loadEnv.js.map +1 -0
  29. package/dist/commands/prCommand.d.ts +16 -0
  30. package/dist/commands/prCommand.d.ts.map +1 -0
  31. package/dist/commands/prCommand.js +61 -0
  32. package/dist/commands/prCommand.js.map +1 -0
  33. package/dist/commands/tag.d.ts +17 -0
  34. package/dist/commands/tag.d.ts.map +1 -0
  35. package/dist/commands/tag.js +127 -0
  36. package/dist/commands/tag.js.map +1 -0
  37. package/dist/index.d.ts +3 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +23 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/prompts/commit.d.ts +3 -0
  42. package/dist/prompts/commit.d.ts.map +1 -0
  43. package/dist/prompts/commit.js +101 -0
  44. package/dist/prompts/commit.js.map +1 -0
  45. package/dist/prompts/pr.d.ts +3 -0
  46. package/dist/prompts/pr.d.ts.map +1 -0
  47. package/dist/prompts/pr.js +58 -0
  48. package/dist/prompts/pr.js.map +1 -0
  49. package/dist/prompts/tag.d.ts +3 -0
  50. package/dist/prompts/tag.d.ts.map +1 -0
  51. package/dist/prompts/tag.js +42 -0
  52. package/dist/prompts/tag.js.map +1 -0
  53. package/eslint.config.js +35 -0
  54. package/jest.config.js +16 -0
  55. package/package.json +51 -0
  56. package/src/__tests__/ai.test.ts +185 -0
  57. package/src/__tests__/commitCommand.test.ts +155 -0
  58. package/src/__tests__/config.test.ts +238 -0
  59. package/src/__tests__/git.test.ts +88 -0
  60. package/src/__tests__/integration.test.ts +138 -0
  61. package/src/__tests__/prCommand.test.ts +121 -0
  62. package/src/__tests__/tagCommand.test.ts +197 -0
  63. package/src/commands/ai.ts +266 -0
  64. package/src/commands/commit.ts +215 -0
  65. package/src/commands/config.ts +182 -0
  66. package/src/commands/configCommand.ts +139 -0
  67. package/src/commands/git.ts +174 -0
  68. package/src/commands/history.ts +82 -0
  69. package/src/commands/loadEnv.ts +5 -0
  70. package/src/commands/log.ts +71 -0
  71. package/src/commands/prCommand.ts +108 -0
  72. package/src/commands/tag.ts +230 -0
  73. package/src/index.ts +29 -0
  74. package/src/prompts/commit.ts +105 -0
  75. package/src/prompts/pr.ts +64 -0
  76. package/src/prompts/tag.ts +48 -0
  77. package/tsconfig.json +19 -0
@@ -0,0 +1,33 @@
1
+ export type SupportedLanguage = 'ko' | 'en';
2
+ export interface EnvironmentConfig {
3
+ apiKey?: string;
4
+ baseURL?: string;
5
+ model?: string;
6
+ mode: 'custom' | 'openai';
7
+ language: SupportedLanguage;
8
+ autoPush: boolean;
9
+ }
10
+ interface StoredConfig {
11
+ apiKey?: string;
12
+ baseURL?: string;
13
+ model?: string;
14
+ mode?: 'custom' | 'openai';
15
+ language?: SupportedLanguage | string;
16
+ autoPush?: boolean;
17
+ }
18
+ export declare class ConfigService {
19
+ private static getConfigFilePath;
20
+ private static loadFileConfig;
21
+ private static normalizeLanguage;
22
+ private static normalizeMode;
23
+ private static resolveEnvConfig;
24
+ static getConfig(): EnvironmentConfig;
25
+ static getEnvConfig(): EnvironmentConfig;
26
+ static updateConfig(updates: StoredConfig): Promise<void>;
27
+ static validateConfig(config: {
28
+ apiKey?: string;
29
+ language?: string;
30
+ }): void;
31
+ }
32
+ export {};
33
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAAC;AAE5C,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,YAAY;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC3B,QAAQ,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAOD,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAShC,OAAO,CAAC,MAAM,CAAC,cAAc;IAqB7B,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAShC,OAAO,CAAC,MAAM,CAAC,aAAa;IAS5B,OAAO,CAAC,MAAM,CAAC,gBAAgB;IA0B/B,MAAM,CAAC,SAAS,IAAI,iBAAiB;IAqBrC,MAAM,CAAC,YAAY,IAAI,iBAAiB;WAI3B,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA0C/D,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;CAS5E"}
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ConfigService = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const fs_2 = require("fs");
9
+ const os_1 = __importDefault(require("os"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const DEFAULT_MODEL = 'zai-org/GLM-4.5-FP8';
12
+ const DEFAULT_MODE = 'custom';
13
+ const DEFAULT_LANGUAGE = 'ko';
14
+ const DEFAULT_AUTO_PUSH = false;
15
+ class ConfigService {
16
+ static getConfigFilePath() {
17
+ const overridePath = process.env.GIT_AI_COMMIT_CONFIG_PATH;
18
+ if (overridePath) {
19
+ return path_1.default.resolve(overridePath);
20
+ }
21
+ return path_1.default.join(os_1.default.homedir(), '.git-ai-commit', 'config.json');
22
+ }
23
+ static loadFileConfig() {
24
+ const filePath = this.getConfigFilePath();
25
+ try {
26
+ if (!fs_1.default.existsSync(filePath)) {
27
+ return {};
28
+ }
29
+ const raw = fs_1.default.readFileSync(filePath, 'utf-8');
30
+ if (!raw.trim()) {
31
+ return {};
32
+ }
33
+ const parsed = JSON.parse(raw);
34
+ return typeof parsed === 'object' && parsed !== null ? parsed : {};
35
+ }
36
+ catch (error) {
37
+ console.warn('Warning: Failed to read configuration file. Falling back to environment variables.');
38
+ return {};
39
+ }
40
+ }
41
+ static normalizeLanguage(language) {
42
+ if (!language) {
43
+ return DEFAULT_LANGUAGE;
44
+ }
45
+ const normalized = language.toLowerCase();
46
+ return normalized === 'en' ? 'en' : 'ko';
47
+ }
48
+ static normalizeMode(mode) {
49
+ if (!mode) {
50
+ return DEFAULT_MODE;
51
+ }
52
+ const normalized = mode.toLowerCase();
53
+ return normalized === 'openai' ? 'openai' : 'custom';
54
+ }
55
+ static resolveEnvConfig(modeOverride) {
56
+ const resolvedMode = this.normalizeMode(modeOverride || process.env.AI_MODE);
57
+ const isOpenAI = resolvedMode === 'openai';
58
+ const apiKey = isOpenAI
59
+ ? process.env.OPENAI_API_KEY || process.env.AI_API_KEY || process.env.CHUTES_API_TOKEN
60
+ : process.env.AI_API_KEY || process.env.OPENAI_API_KEY || process.env.CHUTES_API_TOKEN;
61
+ const baseURL = isOpenAI
62
+ ? process.env.OPENAI_BASE_URL || process.env.AI_BASE_URL
63
+ : process.env.AI_BASE_URL || process.env.OPENAI_BASE_URL;
64
+ const model = isOpenAI
65
+ ? process.env.OPENAI_MODEL || process.env.AI_MODEL || DEFAULT_MODEL
66
+ : process.env.AI_MODEL || process.env.OPENAI_MODEL || DEFAULT_MODEL;
67
+ return {
68
+ apiKey: apiKey || undefined,
69
+ baseURL: baseURL || undefined,
70
+ model: model || DEFAULT_MODEL,
71
+ mode: resolvedMode,
72
+ language: DEFAULT_LANGUAGE,
73
+ autoPush: DEFAULT_AUTO_PUSH
74
+ };
75
+ }
76
+ static getConfig() {
77
+ const fileConfig = this.loadFileConfig();
78
+ const envConfig = this.resolveEnvConfig(fileConfig.mode);
79
+ const mode = this.normalizeMode(fileConfig.mode || envConfig.mode);
80
+ const apiKey = fileConfig.apiKey ?? envConfig.apiKey;
81
+ const baseURL = fileConfig.baseURL ?? envConfig.baseURL;
82
+ const model = fileConfig.model ?? envConfig.model ?? DEFAULT_MODEL;
83
+ const language = this.normalizeLanguage(fileConfig.language ?? envConfig.language);
84
+ const autoPush = typeof fileConfig.autoPush === 'boolean' ? fileConfig.autoPush : envConfig.autoPush;
85
+ return {
86
+ apiKey,
87
+ baseURL,
88
+ model,
89
+ mode,
90
+ language,
91
+ autoPush
92
+ };
93
+ }
94
+ static getEnvConfig() {
95
+ return this.getConfig();
96
+ }
97
+ static async updateConfig(updates) {
98
+ const filePath = this.getConfigFilePath();
99
+ const current = this.loadFileConfig();
100
+ const next = {
101
+ ...current,
102
+ ...updates
103
+ };
104
+ if (updates.language !== undefined) {
105
+ next.language = this.normalizeLanguage(updates.language);
106
+ }
107
+ if (updates.autoPush !== undefined) {
108
+ next.autoPush = Boolean(updates.autoPush);
109
+ }
110
+ if (updates.mode !== undefined) {
111
+ next.mode = this.normalizeMode(updates.mode);
112
+ }
113
+ if (next.model === DEFAULT_MODEL) {
114
+ delete next.model;
115
+ }
116
+ if (next.mode === DEFAULT_MODE) {
117
+ delete next.mode;
118
+ }
119
+ const sanitized = Object.entries(next).reduce((acc, [key, value]) => {
120
+ if (value !== undefined) {
121
+ acc[key] = value;
122
+ }
123
+ else {
124
+ delete acc[key];
125
+ }
126
+ return acc;
127
+ }, {});
128
+ await fs_2.promises.mkdir(path_1.default.dirname(filePath), { recursive: true });
129
+ await fs_2.promises.writeFile(filePath, JSON.stringify(sanitized, null, 2), 'utf-8');
130
+ }
131
+ static validateConfig(config) {
132
+ if (!config.apiKey) {
133
+ throw new Error('API key is required');
134
+ }
135
+ if (config.language && !['ko', 'en'].includes(config.language)) {
136
+ throw new Error('Unsupported language. Use "ko" or "en".');
137
+ }
138
+ }
139
+ }
140
+ exports.ConfigService = ConfigService;
141
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { Command } from 'commander';
2
+ export interface ConfigOptions {
3
+ show?: boolean;
4
+ language?: string;
5
+ autoPush?: boolean;
6
+ apiKey?: string;
7
+ baseUrl?: string;
8
+ model?: string;
9
+ mode?: 'custom' | 'openai';
10
+ }
11
+ export declare class ConfigCommand {
12
+ private program;
13
+ constructor();
14
+ private validateLanguage;
15
+ private validateMode;
16
+ private sanitizeStringValue;
17
+ private handleConfig;
18
+ getCommand(): Command;
19
+ }
20
+ //# sourceMappingURL=configCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configCommand.d.ts","sourceRoot":"","sources":["../../src/commands/configCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC5B;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAU;;IAgBzB,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,mBAAmB;YASb,YAAY;IA4E1B,UAAU,IAAI,OAAO;CAGtB"}
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfigCommand = void 0;
4
+ const commander_1 = require("commander");
5
+ const config_1 = require("./config");
6
+ class ConfigCommand {
7
+ constructor() {
8
+ this.program = new commander_1.Command('config')
9
+ .description('Manage git-ai-commit configuration')
10
+ .option('-s, --show', 'Show current configuration values')
11
+ .option('-l, --language <language>', 'Set default language for AI output (ko | en)')
12
+ .option('--auto-push', 'Enable automatic git push after successful commits created with --commit')
13
+ .option('--no-auto-push', 'Disable automatic git push after successful commits created with --commit')
14
+ .option('-k, --api-key <key>', 'Persist API key for AI requests (overrides environment variables)')
15
+ .option('-b, --base-url <url>', 'Persist API base URL (overrides environment variables)')
16
+ .option('-m, --model <model>', 'Persist default AI model')
17
+ .option('--mode <mode>', 'Persist AI mode (custom | openai)')
18
+ .action(this.handleConfig.bind(this));
19
+ }
20
+ validateLanguage(language) {
21
+ const normalized = language?.toLowerCase();
22
+ if (normalized !== 'ko' && normalized !== 'en') {
23
+ console.error('Language must be either "ko" or "en".');
24
+ process.exit(1);
25
+ }
26
+ return normalized;
27
+ }
28
+ validateMode(mode) {
29
+ const normalized = mode?.toLowerCase();
30
+ if (normalized !== 'custom' && normalized !== 'openai') {
31
+ console.error('Mode must be either "custom" or "openai".');
32
+ process.exit(1);
33
+ }
34
+ return normalized;
35
+ }
36
+ sanitizeStringValue(value) {
37
+ if (value === undefined) {
38
+ return undefined;
39
+ }
40
+ const trimmed = value.trim();
41
+ return trimmed.length > 0 ? trimmed : undefined;
42
+ }
43
+ async handleConfig(options) {
44
+ const updates = {};
45
+ if (options.language) {
46
+ updates.language = this.validateLanguage(options.language);
47
+ }
48
+ if (typeof options.autoPush === 'boolean') {
49
+ updates.autoPush = options.autoPush;
50
+ }
51
+ if (options.apiKey !== undefined) {
52
+ updates.apiKey = this.sanitizeStringValue(options.apiKey);
53
+ }
54
+ if (options.baseUrl !== undefined) {
55
+ updates.baseURL = this.sanitizeStringValue(options.baseUrl);
56
+ }
57
+ if (options.model !== undefined) {
58
+ updates.model = this.sanitizeStringValue(options.model);
59
+ }
60
+ if (options.mode) {
61
+ updates.mode = this.validateMode(options.mode);
62
+ }
63
+ const hasUpdates = Object.keys(updates).length > 0;
64
+ if (!options.show && !hasUpdates) {
65
+ console.log('Usage examples:');
66
+ console.log(' git-ai-commit config --show # Display merged configuration');
67
+ console.log(' git-ai-commit config --language en # Use English prompts and output');
68
+ console.log(' git-ai-commit config --auto-push # Push after commits created with --commit');
69
+ console.log(' git-ai-commit config -k sk-xxx # Persist API key securely on disk');
70
+ console.log(' git-ai-commit config -b https://api.test # Persist custom API base URL');
71
+ console.log(' git-ai-commit config --mode openai # Use OpenAI-compatible environment defaults');
72
+ console.log(' git-ai-commit config --model gpt-4o-mini # Persist preferred AI model');
73
+ return;
74
+ }
75
+ if (hasUpdates) {
76
+ try {
77
+ await config_1.ConfigService.updateConfig(updates);
78
+ console.log('Configuration updated successfully.');
79
+ }
80
+ catch (error) {
81
+ console.error('Error updating configuration:', error instanceof Error ? error.message : error);
82
+ process.exit(1);
83
+ return;
84
+ }
85
+ }
86
+ if (options.show) {
87
+ try {
88
+ const config = config_1.ConfigService.getConfig();
89
+ console.log('Current configuration:');
90
+ console.log(`Language: ${config.language}`);
91
+ console.log(`Auto push: ${config.autoPush ? 'enabled' : 'disabled'}`);
92
+ console.log(`API Key: ${config.apiKey ? '***' + config.apiKey.slice(-4) : 'Not set'}`);
93
+ console.log(`Base URL: ${config.baseURL || 'Not set (using provider default)'}`);
94
+ console.log(`Model: ${config.model || 'zai-org/GLM-4.5-FP8 (default)'}`);
95
+ console.log(`Mode: ${config.mode || 'custom (default)'}`);
96
+ }
97
+ catch (error) {
98
+ console.error('Error reading configuration:', error instanceof Error ? error.message : error);
99
+ process.exit(1);
100
+ }
101
+ }
102
+ }
103
+ getCommand() {
104
+ return this.program;
105
+ }
106
+ }
107
+ exports.ConfigCommand = ConfigCommand;
108
+ //# sourceMappingURL=configCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configCommand.js","sourceRoot":"","sources":["../../src/commands/configCommand.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export interface GitDiffResult {
2
+ success: boolean;
3
+ diff?: string;
4
+ error?: string;
5
+ }
6
+ export interface GitTagResult {
7
+ success: boolean;
8
+ tag?: string;
9
+ error?: string;
10
+ }
11
+ export interface GitLogResult {
12
+ success: boolean;
13
+ log?: string;
14
+ error?: string;
15
+ }
16
+ export declare class GitService {
17
+ static getStagedDiff(): Promise<GitDiffResult>;
18
+ static getBranchDiff(base: string, compare: string): Promise<GitDiffResult>;
19
+ static createCommit(message: string): Promise<boolean>;
20
+ static push(): Promise<boolean>;
21
+ static pushTag(tagName: string): Promise<boolean>;
22
+ static getLatestTag(): Promise<GitTagResult>;
23
+ static getCommitSummariesSince(tag?: string): Promise<GitLogResult>;
24
+ static createAnnotatedTag(tagName: string, message: string): Promise<boolean>;
25
+ }
26
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/commands/git.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,UAAU;WACR,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC;WAuBvC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;WA2BpE,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WAU/C,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;WAUxB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WAU1C,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC;WAwBrC,uBAAuB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;WAmC5D,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CASpF"}
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GitService = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const util_1 = require("util");
6
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
7
+ const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
8
+ class GitService {
9
+ static async getStagedDiff() {
10
+ try {
11
+ const { stdout } = await execAsync('git diff --staged');
12
+ if (!stdout.trim()) {
13
+ return {
14
+ success: false,
15
+ error: 'No staged changes found. Please stage your changes first.'
16
+ };
17
+ }
18
+ return {
19
+ success: true,
20
+ diff: stdout
21
+ };
22
+ }
23
+ catch (error) {
24
+ return {
25
+ success: false,
26
+ error: error instanceof Error ? error.message : 'Failed to get git diff'
27
+ };
28
+ }
29
+ }
30
+ static async getBranchDiff(base, compare) {
31
+ try {
32
+ const command = `git diff ${base}...${compare}`;
33
+ const { stdout } = await execAsync(command);
34
+ if (!stdout.trim()) {
35
+ return {
36
+ success: false,
37
+ error: `No differences found between ${base} and ${compare}.`
38
+ };
39
+ }
40
+ return {
41
+ success: true,
42
+ diff: stdout
43
+ };
44
+ }
45
+ catch (error) {
46
+ const message = error instanceof Error ? error.message : 'Failed to get branch diff';
47
+ return {
48
+ success: false,
49
+ error: message.includes('unknown revision')
50
+ ? `Unable to resolve one of the branches: ${base} or ${compare}.`
51
+ : message
52
+ };
53
+ }
54
+ }
55
+ static async createCommit(message) {
56
+ try {
57
+ await execFileAsync('git', ['commit', '-m', message]);
58
+ return true;
59
+ }
60
+ catch (error) {
61
+ console.error('Failed to create commit:', error instanceof Error ? error.message : error);
62
+ return false;
63
+ }
64
+ }
65
+ static async push() {
66
+ try {
67
+ await execFileAsync('git', ['push']);
68
+ return true;
69
+ }
70
+ catch (error) {
71
+ console.error('Failed to push to remote:', error instanceof Error ? error.message : error);
72
+ return false;
73
+ }
74
+ }
75
+ static async pushTag(tagName) {
76
+ try {
77
+ await execFileAsync('git', ['push', 'origin', tagName]);
78
+ return true;
79
+ }
80
+ catch (error) {
81
+ console.error('Failed to push tag to remote:', error instanceof Error ? error.message : error);
82
+ return false;
83
+ }
84
+ }
85
+ static async getLatestTag() {
86
+ try {
87
+ const { stdout } = await execAsync('git describe --tags --abbrev=0');
88
+ const tag = stdout.trim();
89
+ if (!tag) {
90
+ return {
91
+ success: false,
92
+ error: 'No tags found in the repository.'
93
+ };
94
+ }
95
+ return {
96
+ success: true,
97
+ tag
98
+ };
99
+ }
100
+ catch (error) {
101
+ return {
102
+ success: false,
103
+ error: 'Failed to determine the latest tag. Provide a base tag explicitly using --base-tag.'
104
+ };
105
+ }
106
+ }
107
+ static async getCommitSummariesSince(tag) {
108
+ try {
109
+ const logCommand = tag
110
+ ? `git log ${tag}..HEAD --pretty=format:%s`
111
+ : 'git log --pretty=format:%s';
112
+ const { stdout } = await execAsync(logCommand);
113
+ const trimmed = stdout
114
+ .split('\n')
115
+ .map(line => line.trim())
116
+ .filter(line => line.length > 0);
117
+ if (trimmed.length === 0) {
118
+ return {
119
+ success: false,
120
+ error: tag
121
+ ? `No commits found since tag ${tag}.`
122
+ : 'No commits found in the repository.'
123
+ };
124
+ }
125
+ const formattedLog = trimmed.map(entry => `- ${entry}`).join('\n');
126
+ return {
127
+ success: true,
128
+ log: formattedLog
129
+ };
130
+ }
131
+ catch (error) {
132
+ return {
133
+ success: false,
134
+ error: error instanceof Error ? error.message : 'Failed to read commit history.'
135
+ };
136
+ }
137
+ }
138
+ static async createAnnotatedTag(tagName, message) {
139
+ try {
140
+ await execFileAsync('git', ['tag', '-a', tagName, '-m', message]);
141
+ return true;
142
+ }
143
+ catch (error) {
144
+ console.error('Failed to create tag:', error instanceof Error ? error.message : error);
145
+ return false;
146
+ }
147
+ }
148
+ }
149
+ exports.GitService = GitService;
150
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/commands/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function loadEnv(): void;
2
+ //# sourceMappingURL=loadEnv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadEnv.d.ts","sourceRoot":"","sources":["../../src/commands/loadEnv.ts"],"names":[],"mappings":"AAEA,wBAAgB,OAAO,SAEtB"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.loadEnv = loadEnv;
7
+ const dotenv_1 = __importDefault(require("dotenv"));
8
+ function loadEnv() {
9
+ dotenv_1.default.config();
10
+ }
11
+ //# sourceMappingURL=loadEnv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadEnv.js","sourceRoot":"","sources":["../../src/commands/loadEnv.ts"],"names":[],"mappings":";;;;;AAEA,0BAEC;AAJD,oDAA4B;AAE5B,SAAgB,OAAO;IACrB,gBAAM,CAAC,MAAM,EAAE,CAAC;AAClB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { Command } from 'commander';
2
+ export interface PullRequestOptions {
3
+ base: string;
4
+ compare: string;
5
+ apiKey?: string;
6
+ baseURL?: string;
7
+ baseUrl?: string;
8
+ model?: string;
9
+ }
10
+ export declare class PullRequestCommand {
11
+ private program;
12
+ constructor();
13
+ private handlePullRequest;
14
+ getCommand(): Command;
15
+ }
16
+ //# sourceMappingURL=prCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prCommand.d.ts","sourceRoot":"","sources":["../../src/commands/prCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,OAAO,CAAU;;YAaX,iBAAiB;IAiD/B,UAAU,IAAI,OAAO;CAGtB"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PullRequestCommand = void 0;
4
+ const commander_1 = require("commander");
5
+ const git_1 = require("./git");
6
+ const ai_1 = require("./ai");
7
+ const config_1 = require("./config");
8
+ class PullRequestCommand {
9
+ constructor() {
10
+ this.program = new commander_1.Command('pr')
11
+ .description('Generate a pull request title and summary from branch differences')
12
+ .requiredOption('--base <branch>', 'Base branch to diff against (e.g. main)')
13
+ .requiredOption('--compare <branch>', 'Compare branch to describe (e.g. feature/my-change)')
14
+ .option('-k, --api-key <key>', 'Override API key for this run')
15
+ .option('-b, --base-url <url>', 'Override API base URL')
16
+ .option('--model <model>', 'Override AI model for this run')
17
+ .action(this.handlePullRequest.bind(this));
18
+ }
19
+ async handlePullRequest(options) {
20
+ try {
21
+ const existingConfig = config_1.ConfigService.getConfig();
22
+ const mergedApiKey = options.apiKey || existingConfig.apiKey;
23
+ const baseURLOverride = options.baseURL ?? options.baseUrl;
24
+ const mergedBaseURL = baseURLOverride || existingConfig.baseURL;
25
+ const mergedModel = options.model || existingConfig.model;
26
+ config_1.ConfigService.validateConfig({
27
+ apiKey: mergedApiKey,
28
+ language: existingConfig.language
29
+ });
30
+ const diffResult = await git_1.GitService.getBranchDiff(options.base, options.compare);
31
+ if (!diffResult.success || !diffResult.diff) {
32
+ console.error('Error:', diffResult.error || 'Unable to determine differences between branches.');
33
+ process.exit(1);
34
+ return;
35
+ }
36
+ const aiService = new ai_1.AIService({
37
+ apiKey: mergedApiKey,
38
+ baseURL: mergedBaseURL,
39
+ model: mergedModel,
40
+ language: existingConfig.language,
41
+ verbose: false
42
+ });
43
+ const aiResult = await aiService.generatePullRequestMessage(options.base, options.compare, diffResult.diff);
44
+ if (!aiResult.success || !aiResult.message) {
45
+ console.error('Error:', aiResult.error || 'Failed to generate pull request message.');
46
+ process.exit(1);
47
+ return;
48
+ }
49
+ console.log(aiResult.message);
50
+ }
51
+ catch (error) {
52
+ console.error('Error:', error instanceof Error ? error.message : error);
53
+ process.exit(1);
54
+ }
55
+ }
56
+ getCommand() {
57
+ return this.program;
58
+ }
59
+ }
60
+ exports.PullRequestCommand = PullRequestCommand;
61
+ //# sourceMappingURL=prCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prCommand.js","sourceRoot":"","sources":["../../src/commands/prCommand.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AACpC,+BAAmC;AACnC,6BAAiC;AACjC,qCAAyC;AAWzC,MAAa,kBAAkB;IAG7B;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,mBAAO,CAAC,IAAI,CAAC;aAC7B,WAAW,CAAC,mEAAmE,CAAC;aAChF,cAAc,CAAC,iBAAiB,EAAE,yCAAyC,CAAC;aAC5E,cAAc,CAAC,oBAAoB,EAAE,qDAAqD,CAAC;aAC3F,MAAM,CAAC,qBAAqB,EAAE,+BAA+B,CAAC;aAC9D,MAAM,CAAC,sBAAsB,EAAE,uBAAuB,CAAC;aACvD,MAAM,CAAC,iBAAiB,EAAE,gCAAgC,CAAC;aAC3D,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/C,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,OAA2B;QACzD,IAAI,CAAC;YACH,MAAM,cAAc,GAAG,sBAAa,CAAC,SAAS,EAAE,CAAC;YAEjD,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,MAAM,CAAC;YAC7D,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;YAC3D,MAAM,aAAa,GAAG,eAAe,IAAI,cAAc,CAAC,OAAO,CAAC;YAChE,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,IAAI,cAAc,CAAC,KAAK,CAAC;YAE1D,sBAAa,CAAC,cAAc,CAAC;gBAC3B,MAAM,EAAE,YAAY;gBACpB,QAAQ,EAAE,cAAc,CAAC,QAAQ;aAClC,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,MAAM,gBAAU,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAEjF,IAAI,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;gBAC5C,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,KAAK,IAAI,mDAAmD,CAAC,CAAC;gBACjG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAChB,OAAO;YACT,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,cAAS,CAAC;gBAC9B,MAAM,EAAE,YAAa;gBACrB,OAAO,EAAE,aAAa;gBACtB,KAAK,EAAE,WAAW;gBAClB,QAAQ,EAAE,cAAc,CAAC,QAAQ;gBACjC,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,0BAA0B,CACzD,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,OAAO,EACf,UAAU,CAAC,IAAI,CAChB,CAAC;YAEF,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;gBAC3C,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,IAAI,0CAA0C,CAAC,CAAC;gBACtF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAChB,OAAO;YACT,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF;AAlED,gDAkEC"}
@@ -0,0 +1,17 @@
1
+ import { Command } from 'commander';
2
+ export interface TagOptions {
3
+ apiKey?: string;
4
+ baseUrl?: string;
5
+ model?: string;
6
+ message?: string;
7
+ baseTag?: string;
8
+ }
9
+ export declare class TagCommand {
10
+ private program;
11
+ constructor();
12
+ private resolveAIConfig;
13
+ private handleTag;
14
+ private confirmTagPush;
15
+ getCommand(): Command;
16
+ }
17
+ //# sourceMappingURL=tag.d.ts.map