ai-git-tools 2.0.20 → 2.0.21
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 +2 -0
- package/bin/cli.js +2 -3
- package/package.json +1 -1
- package/src/commands/init.js +2 -2
- package/src/core/config-loader.js +4 -23
- package/src/pr-modules/ai/code-analyzer.js +1 -1
- package/src/pr-modules/core/config-loader.js +6 -1
- package/src/pr-modules/core/github-api.js +1 -9
- package/src/pr-modules/core/workflow.js +19 -11
package/README.md
CHANGED
|
@@ -163,6 +163,7 @@ npx ai-git-tools pr [選項]
|
|
|
163
163
|
--no-confirm 跳過確認直接創建
|
|
164
164
|
--interactive-reviewers 啟用互動式 reviewer 選擇 (預設啟用)
|
|
165
165
|
--auto-labels 自動添加 Labels (預設啟用)
|
|
166
|
+
--include-impact 在 PR 中包含影響範圍分析和注意事項 (預設關閉)
|
|
166
167
|
\`\`\`
|
|
167
168
|
|
|
168
169
|
**範例:**
|
|
@@ -213,6 +214,7 @@ export default {
|
|
|
213
214
|
github: {
|
|
214
215
|
defaultBase: 'release', // 預設目標分支:'release'=自動查找最新,或指定具體分支名
|
|
215
216
|
autoLabels: true, // 自動添加 Labels
|
|
217
|
+
includeImpactAnalysis: false, // 是否在 PR 中包含影響範圍分析和注意事項 (使用 --include-impact 啟用)
|
|
216
218
|
},
|
|
217
219
|
|
|
218
220
|
// Reviewer 設定
|
package/bin/cli.js
CHANGED
|
@@ -52,11 +52,10 @@ program
|
|
|
52
52
|
.description('AI 自動生成 PR 並創建 Pull Request')
|
|
53
53
|
.option('--base <branch>', '指定目標分支')
|
|
54
54
|
.option('--model <model>', '指定 AI 模型')
|
|
55
|
-
.option('--org <org-name>', '指定 GitHub 組織名稱')
|
|
56
55
|
.option('--preview', '僅預覽 PR 內容,不實際創建')
|
|
57
56
|
.option('--no-confirm', '跳過確認直接創建')
|
|
58
|
-
.option('--auto-labels', '自動添加 Labels')
|
|
59
|
-
.option('--
|
|
57
|
+
.option('--auto-labels', '自動添加 Labels (預設啟用)')
|
|
58
|
+
.option('--include-impact', '在 PR 中包含影響範圍分析和注意事項 (預設關閉)')
|
|
60
59
|
.action(prCommand);
|
|
61
60
|
|
|
62
61
|
program.parse();
|
package/package.json
CHANGED
package/src/commands/init.js
CHANGED
|
@@ -23,9 +23,9 @@ export default {
|
|
|
23
23
|
|
|
24
24
|
// GitHub 相關配置
|
|
25
25
|
github: {
|
|
26
|
-
|
|
27
|
-
defaultBase: 'release', // PR分支(使用 'release' 自動偵測最新 release 分支,如 release-2025-m11.1)
|
|
26
|
+
defaultBase: 'release', // PR 預設目標分支(使用 'release' 自動偵測最新 release 分支,如 release-2025-m11.1)
|
|
28
27
|
autoLabels: true, // 自動新增 Labels
|
|
28
|
+
includeImpactAnalysis: false, // 是否在 PR 中包含影響範圍分析和注意事項(使用 --include-impact 啟用)
|
|
29
29
|
},
|
|
30
30
|
|
|
31
31
|
// Reviewers 相關配置
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* 支援從任何目錄下的 .ai-git-config.mjs 載入配置
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { execSync } from 'child_process';
|
|
8
7
|
import { existsSync } from 'fs';
|
|
9
8
|
import { resolve } from 'path';
|
|
10
9
|
|
|
@@ -111,7 +110,6 @@ export function parsePRCliArgs() {
|
|
|
111
110
|
noConfirm: false,
|
|
112
111
|
autoReviewers: false,
|
|
113
112
|
autoLabels: null,
|
|
114
|
-
orgName: null,
|
|
115
113
|
};
|
|
116
114
|
|
|
117
115
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -122,9 +120,6 @@ export function parsePRCliArgs() {
|
|
|
122
120
|
case '--model':
|
|
123
121
|
config.model = args[++i];
|
|
124
122
|
break;
|
|
125
|
-
case '--org':
|
|
126
|
-
config.orgName = args[++i];
|
|
127
|
-
break;
|
|
128
123
|
case '--preview':
|
|
129
124
|
config.preview = true;
|
|
130
125
|
break;
|
|
@@ -134,9 +129,6 @@ export function parsePRCliArgs() {
|
|
|
134
129
|
case '--auto-labels':
|
|
135
130
|
config.autoLabels = true;
|
|
136
131
|
break;
|
|
137
|
-
case '--no-labels':
|
|
138
|
-
config.autoLabels = false;
|
|
139
|
-
break;
|
|
140
132
|
default:
|
|
141
133
|
break;
|
|
142
134
|
}
|
|
@@ -166,31 +158,20 @@ export async function loadPRConfig() {
|
|
|
166
158
|
if (!config) {
|
|
167
159
|
config = {
|
|
168
160
|
ai: { model: 'gpt-4.1', maxDiffLength: 8000, maxRetries: 3 },
|
|
169
|
-
github: {
|
|
161
|
+
github: { defaultBase: 'release', autoLabels: true },
|
|
170
162
|
reviewers: { autoSelect: true, maxSuggested: 5, gitHistoryDepth: 20, excludeAuthors: [] },
|
|
171
163
|
output: { verbose: false, saveHistory: false },
|
|
172
164
|
};
|
|
173
165
|
}
|
|
174
166
|
|
|
175
|
-
//
|
|
176
|
-
if (!config.github
|
|
177
|
-
|
|
178
|
-
const remoteUrl = execSync('git config --get remote.origin.url', { encoding: 'utf-8' }).trim();
|
|
179
|
-
const match = remoteUrl.match(/github\.com[:/]([^/]+)\//);
|
|
180
|
-
config.github.orgName = match ? match[1] : 'kingsinfo-project';
|
|
181
|
-
} catch (error) {
|
|
182
|
-
config.github.orgName = 'kingsinfo-project';
|
|
183
|
-
}
|
|
167
|
+
// 確保 github 物件存在
|
|
168
|
+
if (!config.github) {
|
|
169
|
+
config.github = {};
|
|
184
170
|
}
|
|
185
171
|
|
|
186
172
|
// 合併命令行參數
|
|
187
173
|
const cliConfig = parsePRCliArgs();
|
|
188
174
|
if (cliConfig.model) config.ai.model = cliConfig.model;
|
|
189
|
-
if (cliConfig.orgName) config.github.orgName = cliConfig.orgName;
|
|
190
|
-
if (cliConfig.autoReviewers) config.reviewers.autoSelect = cliConfig.autoReviewers;
|
|
191
|
-
if (cliConfig.autoLabels !== null) config.github.autoLabels = cliConfig.autoLabels;
|
|
192
|
-
|
|
193
|
-
config.baseBranch = cliConfig.baseBranch;
|
|
194
175
|
config.headBranch = cliConfig.headBranch;
|
|
195
176
|
config.draft = cliConfig.draft;
|
|
196
177
|
config.preview = cliConfig.preview;
|
|
@@ -14,6 +14,7 @@ export function parseCliArgs() {
|
|
|
14
14
|
noConfirm: false,
|
|
15
15
|
interactiveReviewers: undefined,
|
|
16
16
|
autoLabels: null,
|
|
17
|
+
includeImpactAnalysis: null,
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -39,6 +40,9 @@ export function parseCliArgs() {
|
|
|
39
40
|
case '--auto-labels':
|
|
40
41
|
config.autoLabels = true;
|
|
41
42
|
break;
|
|
43
|
+
case '--include-impact':
|
|
44
|
+
config.includeImpactAnalysis = true;
|
|
45
|
+
break;
|
|
42
46
|
case '--help':
|
|
43
47
|
showHelp();
|
|
44
48
|
process.exit(0);
|
|
@@ -67,7 +71,7 @@ export async function loadConfig() {
|
|
|
67
71
|
// 使用內建預設值
|
|
68
72
|
config = {
|
|
69
73
|
ai: { model: 'gpt-4.1', maxDiffLength: 8000, maxRetries: 3 },
|
|
70
|
-
github: { defaultBase: 'release', autoLabels: true },
|
|
74
|
+
github: { defaultBase: 'release', autoLabels: true, includeImpactAnalysis: false },
|
|
71
75
|
reviewers: { interactiveReviewers: true, maxSuggested: 5, gitHistoryDepth: 20, excludeAuthors: [] },
|
|
72
76
|
output: { verbose: false, saveHistory: false },
|
|
73
77
|
};
|
|
@@ -80,6 +84,7 @@ export async function loadConfig() {
|
|
|
80
84
|
if (cliConfig.model) config.ai.model = cliConfig.model;
|
|
81
85
|
if (cliConfig.interactiveReviewers !== undefined) config.reviewers.interactiveReviewers = cliConfig.interactiveReviewers;
|
|
82
86
|
if (cliConfig.autoLabels !== null) config.github.autoLabels = cliConfig.autoLabels;
|
|
87
|
+
if (cliConfig.includeImpactAnalysis !== null) config.github.includeImpactAnalysis = cliConfig.includeImpactAnalysis;
|
|
83
88
|
|
|
84
89
|
// 其他 CLI 參數直接加入 config
|
|
85
90
|
config.baseBranch = cliConfig.baseBranch;
|
|
@@ -113,13 +113,6 @@ export class GitHubAPI {
|
|
|
113
113
|
* 從 GitHub 抓取組織的團隊列表
|
|
114
114
|
*/
|
|
115
115
|
async fetchTeams(orgName = this.orgName) {
|
|
116
|
-
// 如果沒有 orgName,直接返回空結果
|
|
117
|
-
if (!orgName || orgName.trim() === '') {
|
|
118
|
-
log.warning('未設置 GitHub 組織名稱,且無法自動偵測');
|
|
119
|
-
log.info('請在 .ai-pr-config.js 中設置 github.orgName 或使用 --org 參數\n');
|
|
120
|
-
return { teams: {}, members: [] };
|
|
121
|
-
}
|
|
122
|
-
|
|
123
116
|
try {
|
|
124
117
|
// 先檢查認證狀態
|
|
125
118
|
const authStatus = this.checkAuth();
|
|
@@ -198,8 +191,7 @@ export class GitHubAPI {
|
|
|
198
191
|
console.log(' 1. 已安裝 GitHub CLI: brew install gh');
|
|
199
192
|
console.log(' 2. 已執行認證: gh auth login');
|
|
200
193
|
console.log(' 3. 選擇正確的認證範圍(需要 read:org 權限)');
|
|
201
|
-
console.log(` 4. 有權限存取 ${orgName}
|
|
202
|
-
console.log(' 5. 組織名稱正確(可用 --org 參數指定)\n');
|
|
194
|
+
console.log(` 4. 有權限存取 ${orgName} 組織\n`);
|
|
203
195
|
|
|
204
196
|
log.info('提示: 你仍可以手動輸入 reviewer 的 GitHub username\n');
|
|
205
197
|
|
|
@@ -286,19 +286,27 @@ export class PRWorkflow {
|
|
|
286
286
|
// 生成 PR 標題和描述
|
|
287
287
|
const { title, body } = await this.ai.generatePRContent(changeData.commits, changeData.diff);
|
|
288
288
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
289
|
+
let enhancedBody = body;
|
|
290
|
+
let blastRadius = null;
|
|
291
|
+
let warnings = [];
|
|
292
|
+
|
|
293
|
+
// 根據配置決定是否進行影響範圍分析
|
|
294
|
+
if (this.config.github.includeImpactAnalysis === true) {
|
|
295
|
+
log.step('正在使用 AI 深度分析影響範圍和潛在問題...\n');
|
|
296
|
+
const analysis = await this.ai.analyzeImpact(
|
|
297
|
+
changeData.changedFiles,
|
|
298
|
+
changeData.diff,
|
|
299
|
+
changeData.commits
|
|
300
|
+
);
|
|
301
|
+
blastRadius = analysis.blastRadius;
|
|
302
|
+
warnings = analysis.warnings;
|
|
296
303
|
|
|
297
|
-
|
|
298
|
-
|
|
304
|
+
// 顯示分析結果摘要
|
|
305
|
+
this.displayAnalysisSummary(blastRadius, warnings);
|
|
299
306
|
|
|
300
|
-
|
|
301
|
-
|
|
307
|
+
// 將分析結果附加到 body
|
|
308
|
+
enhancedBody = this.ai.appendAnalysisToBody(body, blastRadius, warnings);
|
|
309
|
+
}
|
|
302
310
|
|
|
303
311
|
return { title, body: enhancedBody, blastRadius, warnings };
|
|
304
312
|
}
|