@dongowu/git-ai-cli 1.0.1 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -0
- package/dist/cli.js +24 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/commit.d.ts +5 -1
- package/dist/commands/commit.d.ts.map +1 -1
- package/dist/commands/commit.js +91 -21
- package/dist/commands/commit.js.map +1 -1
- package/dist/commands/config.js +1 -1
- package/dist/commands/hook.d.ts +2 -0
- package/dist/commands/hook.d.ts.map +1 -0
- package/dist/commands/hook.js +147 -0
- package/dist/commands/hook.js.map +1 -0
- package/dist/utils/ai.d.ts +7 -1
- package/dist/utils/ai.d.ts.map +1 -1
- package/dist/utils/ai.js +21 -2
- package/dist/utils/ai.js.map +1 -1
- package/dist/utils/git.d.ts +2 -1
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +33 -11
- package/dist/utils/git.js.map +1 -1
- package/package.json +8 -2
- package/scripts/release.sh +34 -0
package/README.md
CHANGED
|
@@ -69,6 +69,9 @@ git-ai
|
|
|
69
69
|
| 🏠 **本地部署** | 支持 Ollama、LM Studio,数据不出本机 |
|
|
70
70
|
| 🔍 **智能 Diff** | 自动过滤 lock 文件,Token 优化截断 |
|
|
71
71
|
| 💬 **交互式** | 提交 / 编辑 / 重新生成 / 取消 |
|
|
72
|
+
| ⚡ **一键提交** | `-y` 参数跳过确认,CI/CD 友好 |
|
|
73
|
+
| 🎯 **多条候选** | `-n 3` 生成多条消息供选择 |
|
|
74
|
+
| 🪝 **Git Hook** | 自动集成到 git commit 流程 |
|
|
72
75
|
| 📝 **规范化** | 遵循 Conventional Commits 标准 |
|
|
73
76
|
| 🌍 **中英双语** | 支持中文和英文输出 |
|
|
74
77
|
|
|
@@ -124,6 +127,45 @@ git-ai config
|
|
|
124
127
|
|
|
125
128
|
## 🔧 高级功能
|
|
126
129
|
|
|
130
|
+
### 命令行选项
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# 一键提交(跳过确认,CI/CD 友好)
|
|
134
|
+
git-ai -y
|
|
135
|
+
git-ai --yes
|
|
136
|
+
|
|
137
|
+
# 生成多条候选消息
|
|
138
|
+
git-ai -n 3
|
|
139
|
+
git-ai --num 3
|
|
140
|
+
|
|
141
|
+
# 组合使用
|
|
142
|
+
git-ai -y -n 3 # 生成 3 条,自动选择第一条提交
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Git Hook 集成
|
|
146
|
+
|
|
147
|
+
自动集成到 `git commit` 流程,无需手动运行 `git-ai`:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# 安装 hook
|
|
151
|
+
git-ai hook install
|
|
152
|
+
|
|
153
|
+
# 查看状态
|
|
154
|
+
git-ai hook status
|
|
155
|
+
|
|
156
|
+
# 移除 hook
|
|
157
|
+
git-ai hook remove
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
安装后,直接运行 `git commit`(不带 `-m`)会自动生成 commit message:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
git add .
|
|
164
|
+
git commit # 自动调用 git-ai 生成消息
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
> 💡 跳过 hook: `git commit --no-verify`
|
|
168
|
+
|
|
127
169
|
### 自动忽略的文件
|
|
128
170
|
|
|
129
171
|
以下文件会自动从 Diff 分析中排除,避免浪费 Token:
|
|
@@ -166,8 +208,26 @@ git-ai
|
|
|
166
208
|
- **Local deployment**: Ollama, LM Studio - keep your data private
|
|
167
209
|
- **Smart diff**: Auto-filter lock files, token optimization
|
|
168
210
|
- **Interactive**: Commit / Edit / Regenerate / Cancel
|
|
211
|
+
- **One-click commit**: `-y` flag for CI/CD pipelines
|
|
212
|
+
- **Multiple choices**: `-n 3` to generate multiple options
|
|
213
|
+
- **Git Hook**: Auto-integrate with `git commit`
|
|
169
214
|
- **Conventional Commits**: Standard commit message format
|
|
170
215
|
|
|
216
|
+
### CLI Options
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# Auto commit (skip confirmation)
|
|
220
|
+
git-ai -y
|
|
221
|
+
|
|
222
|
+
# Generate multiple choices
|
|
223
|
+
git-ai -n 3
|
|
224
|
+
|
|
225
|
+
# Git Hook
|
|
226
|
+
git-ai hook install # Install hook
|
|
227
|
+
git-ai hook remove # Remove hook
|
|
228
|
+
git-ai hook status # Check status
|
|
229
|
+
```
|
|
230
|
+
|
|
171
231
|
### Workflow
|
|
172
232
|
|
|
173
233
|
```
|
package/dist/cli.js
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { cac } from 'cac';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
4
5
|
import { runConfig } from './commands/config.js';
|
|
5
6
|
import { runCommit } from './commands/commit.js';
|
|
7
|
+
import { runHook } from './commands/hook.js';
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const pkg = require('../package.json');
|
|
6
10
|
const cli = cac('git-ai');
|
|
7
11
|
cli
|
|
8
12
|
.command('', 'Generate AI-powered commit message')
|
|
9
|
-
.
|
|
13
|
+
.option('-y, --yes', 'Skip confirmation and commit directly')
|
|
14
|
+
.option('-n, --num <count>', 'Generate multiple commit messages to choose from', { default: 1 })
|
|
15
|
+
.action(async (options) => {
|
|
10
16
|
try {
|
|
11
|
-
await runCommit(
|
|
17
|
+
await runCommit({
|
|
18
|
+
autoCommit: options.yes ?? false,
|
|
19
|
+
numChoices: Math.min(Math.max(Number(options.num) || 1, 1), 5),
|
|
20
|
+
});
|
|
12
21
|
}
|
|
13
22
|
catch (error) {
|
|
14
23
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
@@ -28,7 +37,19 @@ cli
|
|
|
28
37
|
process.exit(1);
|
|
29
38
|
}
|
|
30
39
|
});
|
|
40
|
+
cli
|
|
41
|
+
.command('hook <action>', 'Manage Git hooks (install/remove)')
|
|
42
|
+
.action(async (action) => {
|
|
43
|
+
try {
|
|
44
|
+
await runHook(action);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
48
|
+
console.error(chalk.red(`\n❌ Error: ${message}\n`));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
31
52
|
cli.help();
|
|
32
|
-
cli.version('
|
|
53
|
+
cli.version(pkg.version || '0.0.0');
|
|
33
54
|
cli.parse();
|
|
34
55
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAyB,CAAC;AAE/D,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;AAE1B,GAAG;KACA,OAAO,CAAC,EAAE,EAAE,oCAAoC,CAAC;KACjD,MAAM,CAAC,WAAW,EAAE,uCAAuC,CAAC;KAC5D,MAAM,CAAC,mBAAmB,EAAE,kDAAkD,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;KAC/F,MAAM,CAAC,KAAK,EAAE,OAAwC,EAAE,EAAE;IACzD,IAAI,CAAC;QACH,MAAM,SAAS,CAAC;YACd,UAAU,EAAE,OAAO,CAAC,GAAG,IAAI,KAAK;YAChC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;SAC/D,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACzE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,OAAO,IAAI,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,GAAG;KACA,OAAO,CAAC,QAAQ,EAAE,gCAAgC,CAAC;KACnD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,IAAI,CAAC;QACH,MAAM,SAAS,EAAE,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACzE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,OAAO,IAAI,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,GAAG;KACA,OAAO,CAAC,eAAe,EAAE,mCAAmC,CAAC;KAC7D,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,EAAE;IAC/B,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACzE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,OAAO,IAAI,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,GAAG,CAAC,IAAI,EAAE,CAAC;AACX,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC;AAEpC,GAAG,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commit.d.ts","sourceRoot":"","sources":["../../src/commands/commit.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"commit.d.ts","sourceRoot":"","sources":["../../src/commands/commit.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAUD,wBAAsB,SAAS,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0H1E"}
|
package/dist/commands/commit.js
CHANGED
|
@@ -3,29 +3,31 @@ import chalk from 'chalk';
|
|
|
3
3
|
import ora from 'ora';
|
|
4
4
|
import { getConfig } from '../utils/config.js';
|
|
5
5
|
import { isGitInstalled, isInGitRepo, getStagedFiles, getFilteredDiff, commit, } from '../utils/git.js';
|
|
6
|
-
import { createAIClient, generateCommitMessage } from '../utils/ai.js';
|
|
7
|
-
|
|
6
|
+
import { createAIClient, generateCommitMessage, } from '../utils/ai.js';
|
|
7
|
+
function exitWithError(message, hint) {
|
|
8
|
+
console.error(chalk.red(`❌ ${message}`));
|
|
9
|
+
if (hint) {
|
|
10
|
+
console.log(chalk.gray(` ${hint}`));
|
|
11
|
+
}
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
export async function runCommit(options = {}) {
|
|
15
|
+
const { autoCommit = false, numChoices = 1 } = options;
|
|
8
16
|
// Environment checks
|
|
9
17
|
if (!(await isGitInstalled())) {
|
|
10
|
-
|
|
11
|
-
process.exit(1);
|
|
18
|
+
exitWithError('Git is not installed. Please install git first.');
|
|
12
19
|
}
|
|
13
20
|
if (!(await isInGitRepo())) {
|
|
14
|
-
|
|
15
|
-
process.exit(1);
|
|
21
|
+
exitWithError('Not in a git repository.');
|
|
16
22
|
}
|
|
17
23
|
const stagedFiles = await getStagedFiles();
|
|
18
24
|
if (stagedFiles.length === 0) {
|
|
19
|
-
|
|
20
|
-
console.log(chalk.gray(' Use `git add <files>` to stage your changes first.'));
|
|
21
|
-
process.exit(1);
|
|
25
|
+
exitWithError('No staged changes found.', 'Use `git add <files>` to stage your changes first.');
|
|
22
26
|
}
|
|
23
27
|
// Check config
|
|
24
28
|
const config = getConfig();
|
|
25
29
|
if (!config) {
|
|
26
|
-
|
|
27
|
-
console.log(chalk.gray(' Run `git ai config` to set up your AI provider.'));
|
|
28
|
-
process.exit(1);
|
|
30
|
+
exitWithError('Configuration not found.', 'Run `git-ai config` to set up your AI provider.');
|
|
29
31
|
}
|
|
30
32
|
// Show staged files
|
|
31
33
|
console.log(chalk.cyan('\n📁 Staged files:'));
|
|
@@ -33,13 +35,41 @@ export async function runCommit() {
|
|
|
33
35
|
console.log(chalk.gray(` ${file}`));
|
|
34
36
|
});
|
|
35
37
|
// Get filtered diff
|
|
36
|
-
const { diff, truncated } = await getFilteredDiff();
|
|
38
|
+
const { diff, truncated, ignoredFiles } = await getFilteredDiff(stagedFiles);
|
|
39
|
+
if (ignoredFiles.length > 0) {
|
|
40
|
+
const preview = ignoredFiles.slice(0, 8).join(', ');
|
|
41
|
+
const more = ignoredFiles.length > 8 ? ` (+${ignoredFiles.length - 8} more)` : '';
|
|
42
|
+
console.log(chalk.gray(`\n🧹 Ignored from diff (token optimization): ${preview}${more}`));
|
|
43
|
+
}
|
|
37
44
|
if (truncated) {
|
|
38
45
|
console.log(chalk.yellow('\n⚠️ Diff was truncated due to size limits.'));
|
|
39
46
|
}
|
|
40
47
|
// Create AI client
|
|
41
48
|
const client = createAIClient(config);
|
|
42
|
-
|
|
49
|
+
const input = { diff, stagedFiles, ignoredFiles, truncated };
|
|
50
|
+
// Generate commit message(s)
|
|
51
|
+
let commitMessage;
|
|
52
|
+
if (numChoices > 1) {
|
|
53
|
+
// Generate multiple choices
|
|
54
|
+
const messages = await generateMultipleWithSpinner(client, input, config, numChoices);
|
|
55
|
+
if (autoCommit) {
|
|
56
|
+
// Auto mode: use first message
|
|
57
|
+
commitMessage = messages[0];
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
commitMessage = await selectFromChoices(messages);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
commitMessage = await generateWithSpinner(client, input, config);
|
|
65
|
+
}
|
|
66
|
+
// Auto commit mode
|
|
67
|
+
if (autoCommit) {
|
|
68
|
+
console.log(chalk.green('\n✨ Generated commit message:\n'));
|
|
69
|
+
console.log(chalk.white.bold(` ${commitMessage.split('\n').join('\n ')}`));
|
|
70
|
+
await performCommit(commitMessage);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
43
73
|
// Interactive loop
|
|
44
74
|
while (true) {
|
|
45
75
|
console.log(chalk.green('\n✨ Generated commit message:\n'));
|
|
@@ -78,7 +108,13 @@ export async function runCommit() {
|
|
|
78
108
|
}
|
|
79
109
|
}
|
|
80
110
|
else if (action === 'regenerate') {
|
|
81
|
-
|
|
111
|
+
if (numChoices > 1) {
|
|
112
|
+
const messages = await generateMultipleWithSpinner(client, input, config, numChoices);
|
|
113
|
+
commitMessage = await selectFromChoices(messages);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
commitMessage = await generateWithSpinner(client, input, config);
|
|
117
|
+
}
|
|
82
118
|
}
|
|
83
119
|
else {
|
|
84
120
|
console.log(chalk.gray('\n👋 Commit cancelled.\n'));
|
|
@@ -86,21 +122,56 @@ export async function runCommit() {
|
|
|
86
122
|
}
|
|
87
123
|
}
|
|
88
124
|
}
|
|
89
|
-
async function
|
|
125
|
+
async function selectFromChoices(messages) {
|
|
126
|
+
if (messages.length === 1) {
|
|
127
|
+
return messages[0];
|
|
128
|
+
}
|
|
129
|
+
const { selected } = await inquirer.prompt([
|
|
130
|
+
{
|
|
131
|
+
type: 'list',
|
|
132
|
+
name: 'selected',
|
|
133
|
+
message: 'Select a commit message:',
|
|
134
|
+
choices: messages.map((msg, i) => ({
|
|
135
|
+
name: `${i + 1}. ${msg.split('\n')[0]}`,
|
|
136
|
+
value: msg,
|
|
137
|
+
})),
|
|
138
|
+
},
|
|
139
|
+
]);
|
|
140
|
+
return selected;
|
|
141
|
+
}
|
|
142
|
+
async function generateWithSpinner(client, input, config) {
|
|
90
143
|
const spinner = ora({
|
|
91
144
|
text: 'Generating commit message...',
|
|
92
145
|
color: 'cyan',
|
|
93
146
|
}).start();
|
|
94
147
|
try {
|
|
95
|
-
const message = await generateCommitMessage(client,
|
|
148
|
+
const message = await generateCommitMessage(client, input, config);
|
|
96
149
|
spinner.succeed('Commit message generated!');
|
|
97
150
|
return message;
|
|
98
151
|
}
|
|
99
152
|
catch (error) {
|
|
100
153
|
spinner.fail('Failed to generate commit message');
|
|
101
154
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
102
|
-
|
|
103
|
-
|
|
155
|
+
exitWithError(errorMessage);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async function generateMultipleWithSpinner(client, input, config, count) {
|
|
159
|
+
const spinner = ora({
|
|
160
|
+
text: `Generating ${count} commit messages...`,
|
|
161
|
+
color: 'cyan',
|
|
162
|
+
}).start();
|
|
163
|
+
try {
|
|
164
|
+
const promises = Array.from({ length: count }, () => generateCommitMessage(client, input, config));
|
|
165
|
+
const messages = await Promise.all(promises);
|
|
166
|
+
// Dedupe
|
|
167
|
+
const unique = [...new Set(messages)];
|
|
168
|
+
spinner.succeed(`Generated ${unique.length} commit message(s)!`);
|
|
169
|
+
return unique;
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
spinner.fail('Failed to generate commit messages');
|
|
173
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
174
|
+
exitWithError(errorMessage);
|
|
104
175
|
}
|
|
105
176
|
}
|
|
106
177
|
async function performCommit(message) {
|
|
@@ -116,8 +187,7 @@ async function performCommit(message) {
|
|
|
116
187
|
catch (error) {
|
|
117
188
|
spinner.fail('Failed to create commit');
|
|
118
189
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
119
|
-
|
|
120
|
-
process.exit(1);
|
|
190
|
+
exitWithError(errorMessage);
|
|
121
191
|
}
|
|
122
192
|
}
|
|
123
193
|
//# sourceMappingURL=commit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commit.js","sourceRoot":"","sources":["../../src/commands/commit.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EACL,cAAc,EACd,WAAW,EACX,cAAc,EACd,eAAe,EACf,MAAM,GACP,MAAM,iBAAiB,CAAC;AACzB,OAAO,
|
|
1
|
+
{"version":3,"file":"commit.js","sourceRoot":"","sources":["../../src/commands/commit.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/config.js
CHANGED
|
@@ -91,6 +91,6 @@ export async function runConfig() {
|
|
|
91
91
|
setConfig(config);
|
|
92
92
|
console.log(chalk.green('\n✅ Configuration saved successfully!'));
|
|
93
93
|
console.log(chalk.gray(` Config file: ${getConfigPath()}`));
|
|
94
|
-
console.log(chalk.cyan('\n💡 You can now use `git
|
|
94
|
+
console.log(chalk.cyan('\n💡 You can now use `git-ai` to generate commit messages.\n'));
|
|
95
95
|
}
|
|
96
96
|
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/commands/hook.ts"],"names":[],"mappings":"AA0DA,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB3D"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { execa } from 'execa';
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync, unlinkSync, chmodSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
const HOOK_NAME = 'prepare-commit-msg';
|
|
6
|
+
const HOOK_SCRIPT = `#!/bin/sh
|
|
7
|
+
# git-ai hook - auto-generate commit message
|
|
8
|
+
# To disable temporarily: git commit --no-verify
|
|
9
|
+
|
|
10
|
+
COMMIT_MSG_FILE=$1
|
|
11
|
+
COMMIT_SOURCE=$2
|
|
12
|
+
|
|
13
|
+
# Only run for regular commits (not merge, squash, etc.)
|
|
14
|
+
if [ -z "$COMMIT_SOURCE" ]; then
|
|
15
|
+
# Check if there's already a message (e.g., from -m flag)
|
|
16
|
+
if [ -s "$COMMIT_MSG_FILE" ]; then
|
|
17
|
+
EXISTING_MSG=$(cat "$COMMIT_MSG_FILE" | grep -v "^#" | tr -d '[:space:]')
|
|
18
|
+
if [ -n "$EXISTING_MSG" ]; then
|
|
19
|
+
exit 0
|
|
20
|
+
fi
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# Generate commit message using git-ai
|
|
24
|
+
if command -v git-ai >/dev/null 2>&1; then
|
|
25
|
+
echo "🤖 Generating commit message with git-ai..."
|
|
26
|
+
MSG=$(git-ai --yes 2>/dev/null | grep -A 100 "Generated commit message:" | tail -n +2 | head -n 1 | sed 's/^[[:space:]]*//')
|
|
27
|
+
if [ -n "$MSG" ]; then
|
|
28
|
+
echo "$MSG" > "$COMMIT_MSG_FILE"
|
|
29
|
+
fi
|
|
30
|
+
fi
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
exit 0
|
|
34
|
+
`;
|
|
35
|
+
async function getGitHooksPath() {
|
|
36
|
+
try {
|
|
37
|
+
// Check if custom hooks path is configured
|
|
38
|
+
const { stdout } = await execa('git', ['config', '--get', 'core.hooksPath']);
|
|
39
|
+
return stdout.trim();
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Default to .git/hooks
|
|
43
|
+
const { stdout } = await execa('git', ['rev-parse', '--git-dir']);
|
|
44
|
+
return join(stdout.trim(), 'hooks');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function isInGitRepo() {
|
|
48
|
+
try {
|
|
49
|
+
await execa('git', ['rev-parse', '--is-inside-work-tree']);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export async function runHook(action) {
|
|
57
|
+
if (!['install', 'remove', 'status'].includes(action)) {
|
|
58
|
+
console.error(chalk.red(`❌ Unknown action: ${action}`));
|
|
59
|
+
console.log(chalk.gray(' Available actions: install, remove, status'));
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
if (!(await isInGitRepo())) {
|
|
63
|
+
console.error(chalk.red('❌ Not in a git repository.'));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
const hooksPath = await getGitHooksPath();
|
|
67
|
+
const hookFile = join(hooksPath, HOOK_NAME);
|
|
68
|
+
if (action === 'status') {
|
|
69
|
+
await showStatus(hookFile);
|
|
70
|
+
}
|
|
71
|
+
else if (action === 'install') {
|
|
72
|
+
await installHook(hookFile, hooksPath);
|
|
73
|
+
}
|
|
74
|
+
else if (action === 'remove') {
|
|
75
|
+
await removeHook(hookFile);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async function showStatus(hookFile) {
|
|
79
|
+
if (existsSync(hookFile)) {
|
|
80
|
+
const content = readFileSync(hookFile, 'utf-8');
|
|
81
|
+
if (content.includes('git-ai')) {
|
|
82
|
+
console.log(chalk.green('✅ git-ai hook is installed'));
|
|
83
|
+
console.log(chalk.gray(` Location: ${hookFile}`));
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
console.log(chalk.yellow('⚠️ A prepare-commit-msg hook exists but is not from git-ai'));
|
|
87
|
+
console.log(chalk.gray(` Location: ${hookFile}`));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
console.log(chalk.gray('❌ git-ai hook is not installed'));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async function installHook(hookFile, hooksPath) {
|
|
95
|
+
// Check if hook already exists
|
|
96
|
+
if (existsSync(hookFile)) {
|
|
97
|
+
const content = readFileSync(hookFile, 'utf-8');
|
|
98
|
+
if (content.includes('git-ai')) {
|
|
99
|
+
console.log(chalk.yellow('⚠️ git-ai hook is already installed'));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// Backup existing hook
|
|
103
|
+
const backupFile = `${hookFile}.backup`;
|
|
104
|
+
writeFileSync(backupFile, content);
|
|
105
|
+
console.log(chalk.gray(` Existing hook backed up to: ${backupFile}`));
|
|
106
|
+
}
|
|
107
|
+
// Ensure hooks directory exists
|
|
108
|
+
if (!existsSync(hooksPath)) {
|
|
109
|
+
await execa('mkdir', ['-p', hooksPath]);
|
|
110
|
+
}
|
|
111
|
+
// Write hook script
|
|
112
|
+
writeFileSync(hookFile, HOOK_SCRIPT);
|
|
113
|
+
chmodSync(hookFile, 0o755);
|
|
114
|
+
console.log(chalk.green('✅ git-ai hook installed successfully!'));
|
|
115
|
+
console.log(chalk.gray(` Location: ${hookFile}`));
|
|
116
|
+
console.log('');
|
|
117
|
+
console.log(chalk.cyan('📝 How it works:'));
|
|
118
|
+
console.log(chalk.gray(' When you run `git commit` without -m flag,'));
|
|
119
|
+
console.log(chalk.gray(' git-ai will auto-generate a commit message.'));
|
|
120
|
+
console.log('');
|
|
121
|
+
console.log(chalk.cyan('💡 Tips:'));
|
|
122
|
+
console.log(chalk.gray(' • Skip hook: git commit --no-verify'));
|
|
123
|
+
console.log(chalk.gray(' • Remove hook: git-ai hook remove'));
|
|
124
|
+
}
|
|
125
|
+
async function removeHook(hookFile) {
|
|
126
|
+
if (!existsSync(hookFile)) {
|
|
127
|
+
console.log(chalk.gray('❌ No hook to remove'));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const content = readFileSync(hookFile, 'utf-8');
|
|
131
|
+
if (!content.includes('git-ai')) {
|
|
132
|
+
console.log(chalk.yellow('⚠️ The existing hook is not from git-ai, skipping removal'));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
unlinkSync(hookFile);
|
|
136
|
+
// Restore backup if exists
|
|
137
|
+
const backupFile = `${hookFile}.backup`;
|
|
138
|
+
if (existsSync(backupFile)) {
|
|
139
|
+
const backupContent = readFileSync(backupFile, 'utf-8');
|
|
140
|
+
writeFileSync(hookFile, backupContent);
|
|
141
|
+
chmodSync(hookFile, 0o755);
|
|
142
|
+
unlinkSync(backupFile);
|
|
143
|
+
console.log(chalk.gray(' Previous hook restored from backup'));
|
|
144
|
+
}
|
|
145
|
+
console.log(chalk.green('✅ git-ai hook removed successfully!'));
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/commands/hook.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/ai.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import OpenAI from 'openai';
|
|
2
2
|
import type { AIConfig } from '../types.js';
|
|
3
3
|
export declare function createAIClient(config: AIConfig): OpenAI;
|
|
4
|
-
export
|
|
4
|
+
export interface CommitMessageGenerationInput {
|
|
5
|
+
diff: string;
|
|
6
|
+
stagedFiles?: string[];
|
|
7
|
+
ignoredFiles?: string[];
|
|
8
|
+
truncated?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function generateCommitMessage(client: OpenAI, input: CommitMessageGenerationInput, config: AIConfig): Promise<string>;
|
|
5
11
|
//# sourceMappingURL=ai.d.ts.map
|
package/dist/utils/ai.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/utils/ai.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA8B5C,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAKvD;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/utils/ai.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA8B5C,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAKvD;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,4BAA4B,EACnC,MAAM,EAAE,QAAQ,GACf,OAAO,CAAC,MAAM,CAAC,CA+CjB"}
|
package/dist/utils/ai.js
CHANGED
|
@@ -31,14 +31,33 @@ export function createAIClient(config) {
|
|
|
31
31
|
baseURL: config.baseUrl,
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
|
-
export async function generateCommitMessage(client,
|
|
34
|
+
export async function generateCommitMessage(client, input, config) {
|
|
35
35
|
const systemPrompt = config.customPrompt ||
|
|
36
36
|
(config.locale === 'zh' ? DEFAULT_SYSTEM_PROMPT_ZH : DEFAULT_SYSTEM_PROMPT_EN);
|
|
37
|
+
const isZh = config.locale === 'zh';
|
|
38
|
+
const lines = [];
|
|
39
|
+
if (input.stagedFiles?.length) {
|
|
40
|
+
const header = isZh ? '已暂存文件:' : 'Staged files:';
|
|
41
|
+
lines.push(`${header}\n${input.stagedFiles.map((f) => `- ${f}`).join('\n')}`);
|
|
42
|
+
}
|
|
43
|
+
if (input.ignoredFiles?.length) {
|
|
44
|
+
const header = isZh
|
|
45
|
+
? '以下文件为节省 Token 已忽略 Diff:'
|
|
46
|
+
: 'Ignored files (diff omitted for token optimization):';
|
|
47
|
+
lines.push(`${header}\n${input.ignoredFiles.map((f) => `- ${f}`).join('\n')}`);
|
|
48
|
+
}
|
|
49
|
+
if (input.truncated) {
|
|
50
|
+
lines.push(isZh
|
|
51
|
+
? '注意:Diff 内容已因长度限制被截断。'
|
|
52
|
+
: 'Note: The diff was truncated due to size limits.');
|
|
53
|
+
}
|
|
54
|
+
const diffHeader = isZh ? 'Git Diff:' : 'Git diff:';
|
|
55
|
+
lines.push(`${diffHeader}\n\n${input.diff || '(empty)'}`);
|
|
37
56
|
const response = await client.chat.completions.create({
|
|
38
57
|
model: config.model,
|
|
39
58
|
messages: [
|
|
40
59
|
{ role: 'system', content: systemPrompt },
|
|
41
|
-
{ role: 'user', content:
|
|
60
|
+
{ role: 'user', content: lines.join('\n\n') },
|
|
42
61
|
],
|
|
43
62
|
temperature: 0.7,
|
|
44
63
|
max_tokens: 500,
|
package/dist/utils/ai.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.js","sourceRoot":"","sources":["../../src/utils/ai.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAG5B,MAAM,wBAAwB,GAAG;;;;;;;;;;;;8CAYa,CAAC;AAE/C,MAAM,wBAAwB,GAAG;;;;;;;;;;;;6BAYJ,CAAC;AAE9B,MAAM,UAAU,cAAc,CAAC,MAAgB;IAC7C,OAAO,IAAI,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,QAAQ;QACjC,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC,CAAC;AACL,CAAC;
|
|
1
|
+
{"version":3,"file":"ai.js","sourceRoot":"","sources":["../../src/utils/ai.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAG5B,MAAM,wBAAwB,GAAG;;;;;;;;;;;;8CAYa,CAAC;AAE/C,MAAM,wBAAwB,GAAG;;;;;;;;;;;;6BAYJ,CAAC;AAE9B,MAAM,UAAU,cAAc,CAAC,MAAgB;IAC7C,OAAO,IAAI,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,QAAQ;QACjC,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC,CAAC;AACL,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAc,EACd,KAAmC,EACnC,MAAgB;IAEhB,MAAM,YAAY,GAChB,MAAM,CAAC,YAAY;QACnB,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC;IAEjF,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC;IACpC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,KAAK,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,IAAI,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI;YACjB,CAAC,CAAC,yBAAyB;YAC3B,CAAC,CAAC,sDAAsD,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,KAAK,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CACR,IAAI;YACF,CAAC,CAAC,sBAAsB;YACxB,CAAC,CAAC,kDAAkD,CACvD,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC;IACpD,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,OAAO,KAAK,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC;IAE1D,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QACpD,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;YACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;SAC9C;QACD,WAAW,EAAE,GAAG;QAChB,UAAU,EAAE,GAAG;KAChB,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC9D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/utils/git.d.ts
CHANGED
|
@@ -3,9 +3,10 @@ export declare function isInGitRepo(): Promise<boolean>;
|
|
|
3
3
|
export declare function getStagedDiff(): Promise<string>;
|
|
4
4
|
export declare function getStagedFiles(): Promise<string[]>;
|
|
5
5
|
export declare function isBlacklisted(filename: string): boolean;
|
|
6
|
-
export declare function getFilteredDiff(): Promise<{
|
|
6
|
+
export declare function getFilteredDiff(files: string[]): Promise<{
|
|
7
7
|
diff: string;
|
|
8
8
|
truncated: boolean;
|
|
9
|
+
ignoredFiles: string[];
|
|
9
10
|
}>;
|
|
10
11
|
export declare function commit(message: string): Promise<void>;
|
|
11
12
|
//# sourceMappingURL=git.d.ts.map
|
package/dist/utils/git.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAGA,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAOvD;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAOpD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAGrD;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAGxD;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAWvD;
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAGA,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAOvD;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAOpD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAGrD;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAGxD;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAWvD;AAkCD,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA0BvE;AAED,wBAAsB,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3D"}
|
package/dist/utils/git.js
CHANGED
|
@@ -38,20 +38,42 @@ export function isBlacklisted(filename) {
|
|
|
38
38
|
return filename === pattern || filename.endsWith(`/${pattern}`);
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
function chunkArgsByLength(args, options) {
|
|
42
|
+
const batches = [];
|
|
43
|
+
let current = [];
|
|
44
|
+
let currentChars = 0;
|
|
45
|
+
for (const arg of args) {
|
|
46
|
+
const argLen = arg.length + 1;
|
|
47
|
+
const shouldStartNewBatch = current.length >= options.maxItems || currentChars + argLen > options.maxChars;
|
|
48
|
+
if (shouldStartNewBatch) {
|
|
49
|
+
if (current.length > 0) {
|
|
50
|
+
batches.push(current);
|
|
51
|
+
}
|
|
52
|
+
current = [];
|
|
53
|
+
currentChars = 0;
|
|
48
54
|
}
|
|
55
|
+
current.push(arg);
|
|
56
|
+
currentChars += argLen;
|
|
57
|
+
}
|
|
58
|
+
if (current.length > 0) {
|
|
59
|
+
batches.push(current);
|
|
60
|
+
}
|
|
61
|
+
return batches;
|
|
62
|
+
}
|
|
63
|
+
export async function getFilteredDiff(files) {
|
|
64
|
+
const ignoredFiles = files.filter(isBlacklisted);
|
|
65
|
+
const allowedFiles = files.filter((file) => !isBlacklisted(file));
|
|
66
|
+
const diffParts = [];
|
|
67
|
+
const fileBatches = chunkArgsByLength(allowedFiles, { maxItems: 50, maxChars: 6000 });
|
|
68
|
+
for (const batch of fileBatches) {
|
|
49
69
|
try {
|
|
50
|
-
const { stdout } = await execa('git', ['diff', '--cached', '--',
|
|
51
|
-
|
|
70
|
+
const { stdout } = await execa('git', ['diff', '--cached', '--', ...batch]);
|
|
71
|
+
if (stdout) {
|
|
72
|
+
diffParts.push(stdout);
|
|
73
|
+
}
|
|
52
74
|
}
|
|
53
75
|
catch {
|
|
54
|
-
diffParts.push(`[
|
|
76
|
+
diffParts.push(`[Diff unavailable for ${batch.length} file(s)]`);
|
|
55
77
|
}
|
|
56
78
|
}
|
|
57
79
|
let fullDiff = diffParts.join('\n');
|
|
@@ -60,7 +82,7 @@ export async function getFilteredDiff() {
|
|
|
60
82
|
fullDiff = fullDiff.slice(0, MAX_DIFF_LENGTH) + '\n\n...[Diff Truncated]';
|
|
61
83
|
truncated = true;
|
|
62
84
|
}
|
|
63
|
-
return { diff: fullDiff, truncated };
|
|
85
|
+
return { diff: fullDiff, truncated, ignoredFiles };
|
|
64
86
|
}
|
|
65
87
|
export async function commit(message) {
|
|
66
88
|
await execa('git', ['commit', '-m', message]);
|
package/dist/utils/git.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC;IAC3E,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;QACrC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC7B,OAAO,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,QAAQ,KAAK,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dongowu/git-ai-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Fast, privacy-first, bring-your-own-model Git commit message generator",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cli.js",
|
|
@@ -11,7 +11,13 @@
|
|
|
11
11
|
"build": "tsc",
|
|
12
12
|
"dev": "tsc --watch",
|
|
13
13
|
"start": "node dist/cli.js",
|
|
14
|
-
"prepublishOnly": "npm run build"
|
|
14
|
+
"prepublishOnly": "npm run build",
|
|
15
|
+
"release": "npm version patch && git push && git push --tags && npm publish --access=public",
|
|
16
|
+
"release:minor": "npm version minor && git push && git push --tags && npm publish --access=public",
|
|
17
|
+
"release:major": "npm version major && git push && git push --tags && npm publish --access=public",
|
|
18
|
+
"tag": "npm version patch && git push && git push --tags",
|
|
19
|
+
"tag:minor": "npm version minor && git push && git push --tags",
|
|
20
|
+
"tag:major": "npm version major && git push && git push --tags"
|
|
15
21
|
},
|
|
16
22
|
"keywords": [
|
|
17
23
|
"git",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# release.sh - 自动发布脚本
|
|
3
|
+
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
# 颜色
|
|
7
|
+
GREEN='\033[0;32m'
|
|
8
|
+
YELLOW='\033[1;33m'
|
|
9
|
+
NC='\033[0m'
|
|
10
|
+
|
|
11
|
+
# 获取版本类型
|
|
12
|
+
VERSION_TYPE=${1:-patch}
|
|
13
|
+
|
|
14
|
+
echo -e "${GREEN}🚀 Starting release...${NC}"
|
|
15
|
+
|
|
16
|
+
# 1. 构建
|
|
17
|
+
echo -e "${YELLOW}📦 Building...${NC}"
|
|
18
|
+
npm run build
|
|
19
|
+
|
|
20
|
+
# 2. 更新版本
|
|
21
|
+
echo -e "${YELLOW}📝 Bumping ${VERSION_TYPE} version...${NC}"
|
|
22
|
+
npm version $VERSION_TYPE
|
|
23
|
+
|
|
24
|
+
# 3. 推送到 GitHub
|
|
25
|
+
echo -e "${YELLOW}📤 Pushing to GitHub...${NC}"
|
|
26
|
+
git push
|
|
27
|
+
git push --tags
|
|
28
|
+
|
|
29
|
+
# 4. 发布到 npm
|
|
30
|
+
echo -e "${YELLOW}📦 Publishing to npm...${NC}"
|
|
31
|
+
read -p "Enter OTP code: " OTP
|
|
32
|
+
npm publish --access=public --otp=$OTP
|
|
33
|
+
|
|
34
|
+
echo -e "${GREEN}✅ Release complete!${NC}"
|