ai-git-tools 2.0.73 → 2.0.75
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
CHANGED
|
@@ -2,6 +2,9 @@ import { CopilotClient, approveAll } from '@github/copilot-sdk';
|
|
|
2
2
|
import { CONSTANTS, PROJECT_SKILLS_CONTEXT } from '../utils/constants.js';
|
|
3
3
|
import { getSkillsSummaryForPrompt, log } from '../utils/helpers.js';
|
|
4
4
|
|
|
5
|
+
// 讓 CopilotClient 啟動的 Node 子程序繼承此設定,靜音 SQLite ExperimentalWarning
|
|
6
|
+
process.env.NODE_NO_WARNINGS = '1';
|
|
7
|
+
|
|
5
8
|
// CopilotClient 子程序啟動 + AI 模型回應可能共需 60-120s,設為 150s 保留足夠緩衝
|
|
6
9
|
const AI_TIMEOUT_MS = 150000;
|
|
7
10
|
|
|
@@ -35,6 +38,14 @@ export class AIAnalyzer {
|
|
|
35
38
|
});
|
|
36
39
|
}
|
|
37
40
|
|
|
41
|
+
/**
|
|
42
|
+
* 預熱 CopilotClient — 在 workflow 開始時盡早呼叫,
|
|
43
|
+
* 讓 subprocess 在 git 操作期間並行啟動,避免 session.idle timeout
|
|
44
|
+
*/
|
|
45
|
+
async warmup() {
|
|
46
|
+
await this._getOrCreateClient();
|
|
47
|
+
}
|
|
48
|
+
|
|
38
49
|
/**
|
|
39
50
|
* 釋放 CopilotClient 子程序資源
|
|
40
51
|
*/
|
|
@@ -51,28 +62,47 @@ export class AIAnalyzer {
|
|
|
51
62
|
}
|
|
52
63
|
|
|
53
64
|
/**
|
|
54
|
-
* 生成 PR
|
|
65
|
+
* 生成 PR 內容(失敗時自動重建 client 重試一次)
|
|
55
66
|
*/
|
|
56
67
|
async generatePRContent(commits, diff) {
|
|
57
68
|
const skillsSummary = getSkillsSummaryForPrompt(PROJECT_SKILLS_CONTEXT);
|
|
58
69
|
const prompt = this.buildPRPrompt(commits, diff, skillsSummary);
|
|
59
70
|
|
|
60
|
-
|
|
71
|
+
for (let attempt = 1; attempt <= 2; attempt++) {
|
|
72
|
+
try {
|
|
73
|
+
if (attempt === 2) {
|
|
74
|
+
log.info(' 重試 AI 請求(重建 session)...\n');
|
|
75
|
+
await this.close(); // 釋放舊 client,下一次 _createSession 會建新的
|
|
76
|
+
}
|
|
61
77
|
|
|
62
|
-
|
|
63
|
-
const responsePromise = session.sendAndWait({ prompt });
|
|
64
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
65
|
-
setTimeout(() => reject(new Error(`AI 請求超時 (${AI_TIMEOUT_MS / 1000} 秒)`)), AI_TIMEOUT_MS);
|
|
66
|
-
});
|
|
78
|
+
const session = await this._createSession();
|
|
67
79
|
|
|
68
|
-
|
|
69
|
-
|
|
80
|
+
const responsePromise = session.sendAndWait({ prompt });
|
|
81
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
82
|
+
setTimeout(() => reject(new Error(`AI 請求超時 (${AI_TIMEOUT_MS / 1000} 秒)`)), AI_TIMEOUT_MS);
|
|
83
|
+
});
|
|
70
84
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
85
|
+
const response = await Promise.race([responsePromise, timeoutPromise]);
|
|
86
|
+
const prContent = response?.data.content?.trim() || '';
|
|
87
|
+
|
|
88
|
+
if (!prContent) {
|
|
89
|
+
throw new Error('AI 未能生成 PR 內容');
|
|
90
|
+
}
|
|
74
91
|
|
|
75
|
-
|
|
92
|
+
return this.parsePRContent(prContent);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
// SDK 內部 session.idle timeout(hardcoded 60s)→ 重試一次
|
|
95
|
+
const isSessionIdleTimeout =
|
|
96
|
+
error.message?.includes('session.idle') || error.message?.includes('Timeout after');
|
|
97
|
+
if (attempt === 1 && isSessionIdleTimeout) {
|
|
98
|
+
log.warning(` AI session 超時,即將重試...\n`);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// unreachable,但保留讓 linter 滿意
|
|
105
|
+
throw new Error('AI 未能生成 PR 內容');
|
|
76
106
|
// 注意:不在此 stop() client,改由 close() 統一清理以便複用
|
|
77
107
|
}
|
|
78
108
|
|
|
@@ -143,25 +173,13 @@ ${skillsSummary}
|
|
|
143
173
|
> type 必須是以下之一:feat / fix / refactor / style / docs / test / chore / perf
|
|
144
174
|
> **重要**:如果有新增任何功能、新增檔案、新增 API、新增組件,優先使用 **feat**
|
|
145
175
|
|
|
146
|
-
##
|
|
147
|
-
[
|
|
148
|
-
|
|
149
|
-
---
|
|
150
|
-
|
|
151
|
-
## ✏️ 做了什麼 (What)
|
|
152
|
-
- [具體變更項目 1]
|
|
153
|
-
- [具體變更項目 2]
|
|
154
|
-
- [具體變更項目 3]
|
|
176
|
+
## 📝 變更摘要
|
|
177
|
+
[簡述這個 PR 的主要目的和影響範圍,2-3 句話]
|
|
155
178
|
|
|
156
|
-
##
|
|
157
|
-
- [
|
|
158
|
-
- [
|
|
159
|
-
|
|
160
|
-
## ⚙️ 怎麼做到的 (How)
|
|
161
|
-
- [技術實作重點說明 1]
|
|
162
|
-
- [技術實作重點說明 2]
|
|
163
|
-
|
|
164
|
-
---
|
|
179
|
+
## 🎯 主要變更
|
|
180
|
+
- [變更項目 1]
|
|
181
|
+
- [變更項目 2]
|
|
182
|
+
- [變更項目 3]
|
|
165
183
|
|
|
166
184
|
## 🔀 變更類型
|
|
167
185
|
- [ ] ✨ 新功能 (feat)
|
|
@@ -185,19 +203,19 @@ ${skillsSummary}
|
|
|
185
203
|
>
|
|
186
204
|
> **特別注意**: 如果 diff 中有「新增檔案」或「新增功能」,**務必勾選** ✨ 新功能 (feat)
|
|
187
205
|
|
|
188
|
-
##
|
|
189
|
-
|
|
190
|
-
|
|
206
|
+
## 🧪 測試方法
|
|
207
|
+
1. [具體的測試步驟 1]
|
|
208
|
+
2. [具體的測試步驟 2]
|
|
209
|
+
3. [具體的測試步驟 3]
|
|
191
210
|
|
|
192
|
-
|
|
211
|
+
## 💥 Breaking Changes
|
|
212
|
+
[如果有破壞性變更請詳細說明,沒有則填寫「無」]
|
|
193
213
|
|
|
194
|
-
##
|
|
195
|
-
|
|
196
|
-
- [ ] [測試項目 2]
|
|
197
|
-
- [ ] [測試項目 3]
|
|
214
|
+
## 📌 注意事項
|
|
215
|
+
[需要特別注意的事項]
|
|
198
216
|
|
|
199
|
-
## 📸
|
|
200
|
-
[
|
|
217
|
+
## 📸 截圖
|
|
218
|
+
[如果是 UI 變更,提醒需要截圖]
|
|
201
219
|
|
|
202
220
|
---
|
|
203
221
|
|
|
@@ -210,26 +228,23 @@ ${skillsSummary}
|
|
|
210
228
|
- [請 reviewer 特別關注的邏輯或設計決策 1]
|
|
211
229
|
- [請 reviewer 特別關注的邏輯或設計決策 2]
|
|
212
230
|
|
|
213
|
-
## 🔗 相關 Issue
|
|
214
|
-
- Closes #[issue 編號](沒有則填「無」)
|
|
215
|
-
|
|
216
231
|
---
|
|
217
232
|
|
|
218
233
|
**規則**:
|
|
219
234
|
1. PR 標題格式:type: 簡短描述(不超過 50 字)
|
|
220
235
|
2. type 必須符合 Conventional Commits
|
|
221
|
-
3.
|
|
222
|
-
4.
|
|
223
|
-
5.
|
|
224
|
-
6.
|
|
236
|
+
3. 變更摘要用 2-3 句話概括整體影響
|
|
237
|
+
4. 全部使用繁體中文(台灣正體)
|
|
238
|
+
5. 不要在開頭加引導語句
|
|
239
|
+
6. 直接開始輸出 # [type]: [標題]
|
|
225
240
|
7. **變更類型判斷必須準確**:
|
|
226
241
|
- 檢查 diff 中是否有 "new file mode" 或大量 "+++" 行(表示新增檔案)
|
|
227
242
|
- 檢查 commit 訊息是否包含「新增」、「add」、「feat」等關鍵字
|
|
243
|
+
- 檢查主要變更列表,如果提到「新增 xxx」就必須勾選 ✨ 新功能 (feat)
|
|
228
244
|
- 新增配置檔、新增組件、新增 API、新增功能都算 feat
|
|
229
245
|
- 一個 PR 可以同時是多種類型(如:feat + refactor + chore)
|
|
230
|
-
8. **Risk Level 判斷**:HIGH = 影響付款/登入/資料寫入核心流程;MEDIUM = 影響現有功能但有降級保護;LOW = 新增功能或純重構
|
|
246
|
+
8. **Risk Level 判斷**:HIGH = 影響付款/登入/資料寫入核心流程;MEDIUM = 影響現有功能但有降級保護;LOW = 新增功能或純重構
|
|
231
247
|
9. **Reviewer 重點**:列出最值得仔細看的 1-3 個地方(核心演算法、架構決策、潛在邊界條件)
|
|
232
|
-
10. **相關 Issue**:若 commit 訊息含 #issue 編號或 closes/fixes/resolves,自動帶入;否則填「無」
|
|
233
248
|
|
|
234
249
|
---
|
|
235
250
|
|