ai-git-tools 2.0.1 → 2.0.2
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/package.json +1 -1
- package/src/commands/init.js +1 -1
- package/src/commands/pr.js +40 -40
package/package.json
CHANGED
package/src/commands/init.js
CHANGED
package/src/commands/pr.js
CHANGED
|
@@ -16,7 +16,7 @@ import { handleError, getProjectTypePrompt } from '../utils/helpers.js';
|
|
|
16
16
|
*/
|
|
17
17
|
async function generatePRContent(baseBranch, headBranch, config) {
|
|
18
18
|
const logger = new Logger();
|
|
19
|
-
logger.step('AI
|
|
19
|
+
logger.step('AI 正在分析變更且生成 PR 内容...');
|
|
20
20
|
|
|
21
21
|
// 獲取 diff 和 commits
|
|
22
22
|
const diff = GitOperations.getDiff(baseBranch, headBranch);
|
|
@@ -27,7 +27,7 @@ async function generatePRContent(baseBranch, headBranch, config) {
|
|
|
27
27
|
|
|
28
28
|
const prompt = `${getProjectTypePrompt()}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
請根據以下資訊生成一個 Pull Request 的標題和描述。
|
|
31
31
|
|
|
32
32
|
**Commits 列表**:
|
|
33
33
|
${commits}
|
|
@@ -37,17 +37,17 @@ ${truncatedDiff}
|
|
|
37
37
|
|
|
38
38
|
**输出格式**(JSON):
|
|
39
39
|
{
|
|
40
|
-
"title": "PR
|
|
41
|
-
"description": "PR 描述(使用 Markdown
|
|
40
|
+
"title": "PR 標題(簡短、繁體中文,50 字內)",
|
|
41
|
+
"description": "PR 描述(使用 Markdown 格式,繁體中文)"
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
**PR 描述应包含**:
|
|
45
|
-
1. ## 📝
|
|
46
|
-
2. ## ✨
|
|
47
|
-
3. ## 🔧
|
|
48
|
-
4. ## ✅
|
|
45
|
+
1. ## 📝 變更摘要(簡述主要變更)
|
|
46
|
+
2. ## ✨ 主要功能(列出新增功能或修正項目)
|
|
47
|
+
3. ## 🔧 技術細節(選填,如有重要的技術變更)
|
|
48
|
+
4. ## ✅ 測試(如何測試這些變更)
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
請只輸出 JSON,不要其他文字。`;
|
|
51
51
|
|
|
52
52
|
const response = await AIClient.sendAndWait(prompt, config.ai.model);
|
|
53
53
|
|
|
@@ -56,20 +56,20 @@ ${truncatedDiff}
|
|
|
56
56
|
logger.success('PR 内容生成完成\n');
|
|
57
57
|
return prContent;
|
|
58
58
|
} catch (error) {
|
|
59
|
-
throw new Error(`無法解析 AI
|
|
59
|
+
throw new Error(`無法解析 AI 回應: ${error.message}`);
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
|
-
* 顯示 PR
|
|
64
|
+
* 顯示 PR 預覽
|
|
65
65
|
*/
|
|
66
66
|
function displayPreview(prContent, stats) {
|
|
67
67
|
console.log('\n' + '═'.repeat(60));
|
|
68
|
-
console.log('📋 PR
|
|
68
|
+
console.log('📋 PR 預覽');
|
|
69
69
|
console.log('═'.repeat(60));
|
|
70
|
-
console.log(`\n
|
|
71
|
-
console.log(
|
|
72
|
-
console.log(
|
|
70
|
+
console.log(`\n標題: ${prContent.title}\n`);
|
|
71
|
+
console.log(`統計: ${stats.stats}`);
|
|
72
|
+
console.log(`檔案數: ${stats.filesChanged} 個檔案\n`);
|
|
73
73
|
console.log('─'.repeat(60));
|
|
74
74
|
console.log('描述:\n');
|
|
75
75
|
console.log(prContent.description);
|
|
@@ -77,7 +77,7 @@ function displayPreview(prContent, stats) {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
|
-
* PR
|
|
80
|
+
* PR 命令主函數
|
|
81
81
|
*/
|
|
82
82
|
export async function prCommand() {
|
|
83
83
|
const logger = new Logger();
|
|
@@ -88,40 +88,40 @@ export async function prCommand() {
|
|
|
88
88
|
// 載入配置
|
|
89
89
|
const config = await loadPRConfig();
|
|
90
90
|
|
|
91
|
-
//
|
|
91
|
+
// 獲取當前分支
|
|
92
92
|
const currentBranch = GitOperations.getCurrentBranch();
|
|
93
93
|
let headBranch = config.headBranch || currentBranch;
|
|
94
94
|
let baseBranch = config.baseBranch;
|
|
95
95
|
|
|
96
|
-
//
|
|
96
|
+
// 自動偵測 base branch
|
|
97
97
|
if (!baseBranch) {
|
|
98
|
-
logger.step('
|
|
98
|
+
logger.step('正在偵測 release 分支...\n');
|
|
99
99
|
const latestRelease = GitOperations.findLatestReleaseBranch();
|
|
100
100
|
|
|
101
101
|
if (latestRelease) {
|
|
102
102
|
baseBranch = latestRelease;
|
|
103
|
-
logger.success(
|
|
103
|
+
logger.success(`自動選擇目標分支: ${baseBranch}\n`);
|
|
104
104
|
} else {
|
|
105
|
-
logger.error('
|
|
106
|
-
console.log('💡 使用 --base
|
|
105
|
+
logger.error('未偵測到任何 release 分支');
|
|
106
|
+
console.log('💡 使用 --base 參數指定目標分支');
|
|
107
107
|
process.exit(1);
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
// 檢查是否在 base branch
|
|
112
112
|
if (currentBranch === baseBranch) {
|
|
113
|
-
logger.error(`你目前在 ${baseBranch}
|
|
114
|
-
console.log('💡
|
|
113
|
+
logger.error(`你目前在 ${baseBranch} 分支,請切換到 feature 分支`);
|
|
114
|
+
console.log('💡 切換到 feature 分支: git checkout <feature-branch>');
|
|
115
115
|
process.exit(1);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
console.log('\n📌
|
|
118
|
+
console.log('\n📌 分支資訊:');
|
|
119
119
|
console.log(` Base: ${baseBranch}`);
|
|
120
120
|
console.log(` Head: ${headBranch}\n`);
|
|
121
121
|
|
|
122
|
-
//
|
|
122
|
+
// 推送到遠端(預覽模式跳過)
|
|
123
123
|
if (!config.preview) {
|
|
124
|
-
logger.step(
|
|
124
|
+
logger.step(`推送到遠端分支: origin/${headBranch}`);
|
|
125
125
|
GitOperations.push(headBranch);
|
|
126
126
|
logger.success('推送成功\n');
|
|
127
127
|
|
|
@@ -132,33 +132,33 @@ export async function prCommand() {
|
|
|
132
132
|
logger.success('同步完成\n');
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
//
|
|
135
|
+
// 獲取變更統計
|
|
136
136
|
const stats = GitOperations.getChangeStats(baseBranch, headBranch);
|
|
137
|
-
console.log(`📈
|
|
138
|
-
console.log(`📁
|
|
137
|
+
console.log(`📈 變更統計: ${stats.stats}`);
|
|
138
|
+
console.log(`📁 影響檔案: ${stats.filesChanged} 個\n`);
|
|
139
139
|
|
|
140
|
-
// 生成 PR
|
|
140
|
+
// 生成 PR 內容
|
|
141
141
|
const prContent = await generatePRContent(baseBranch, headBranch, config);
|
|
142
142
|
|
|
143
|
-
//
|
|
143
|
+
// 顯示預覽
|
|
144
144
|
displayPreview(prContent, stats);
|
|
145
145
|
|
|
146
|
-
//
|
|
146
|
+
// 預覽模式:僅顯示不創建
|
|
147
147
|
if (config.preview) {
|
|
148
|
-
logger.info('
|
|
148
|
+
logger.info('預覽模式:未創建 PR');
|
|
149
149
|
return;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
//
|
|
153
|
-
logger.step('
|
|
152
|
+
// 創建 PR(使用 GitHub CLI)
|
|
153
|
+
logger.step('創建 Pull Request...');
|
|
154
154
|
|
|
155
155
|
// 準備 PR body
|
|
156
156
|
const prBody = prContent.description;
|
|
157
157
|
|
|
158
|
-
//
|
|
158
|
+
// 構建 gh pr create 命令
|
|
159
159
|
let ghCommand = `gh pr create --base ${baseBranch} --head ${headBranch} --title "${prContent.title.replace(/"/g, '\\"')}"`;
|
|
160
160
|
|
|
161
|
-
//
|
|
161
|
+
// 將 body 寫入臨時檔案
|
|
162
162
|
const { writeFileSync, unlinkSync } = await import('fs');
|
|
163
163
|
const tmpFile = '/tmp/pr-body-temp.md';
|
|
164
164
|
writeFileSync(tmpFile, prBody, 'utf-8');
|
|
@@ -172,7 +172,7 @@ export async function prCommand() {
|
|
|
172
172
|
const result = execSync(ghCommand, { encoding: 'utf-8' });
|
|
173
173
|
unlinkSync(tmpFile);
|
|
174
174
|
|
|
175
|
-
logger.success('PR
|
|
175
|
+
logger.success('PR 創建成功!\n');
|
|
176
176
|
console.log(result);
|
|
177
177
|
} catch (error) {
|
|
178
178
|
try {
|
|
@@ -180,7 +180,7 @@ export async function prCommand() {
|
|
|
180
180
|
} catch (e) {
|
|
181
181
|
// 忽略
|
|
182
182
|
}
|
|
183
|
-
throw new Error(
|
|
183
|
+
throw new Error(`創建 PR 失敗: ${error.message}`);
|
|
184
184
|
}
|
|
185
185
|
} catch (error) {
|
|
186
186
|
handleError(error);
|