ai-git-tools 2.0.42 → 2.0.45

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-git-tools",
3
- "version": "2.0.42",
3
+ "version": "2.0.45",
4
4
  "description": "AI-powered Git automation tools for commit messages and PR generation",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -42,6 +42,15 @@ export async function autodevCommand(issueInput, cliOptions = {}) {
42
42
  commitOnly: cliOptions.commitOnly ?? false,
43
43
  };
44
44
 
45
+ // 永遠顯示啟動設定,方便確認
46
+ console.log('📋 autodev 啟動設定:');
47
+ console.log(` AI 模型 : ${config.aiModel}`);
48
+ console.log(` 重試次數 : ${config.maxRetries}`);
49
+ console.log(` 測試框架 : ${options.framework ?? '自動偵測'}`);
50
+ console.log(` Commit : ${options.skipAll || options.skipCommit ? '跳過' : '自動'}`);
51
+ console.log(` PR : ${options.skipAll || options.skipPr || options.commitOnly ? '跳過' : '自動'}`);
52
+ if (options.dryRun) console.log(' ⚠️ 乾運行模式(不實際執行)');
53
+
45
54
  const workflow = new AutodevWorkflow(config);
46
55
  await workflow.execute(issueInput, options);
47
56
  } catch (error) {
@@ -197,7 +197,7 @@ export async function loadAutodevConfig() {
197
197
  verbose: false,
198
198
  projectRoot: process.cwd(),
199
199
  // AI 設定(可被 autodev 子區塊或全域 ai 區塊覆蓋)
200
- aiModel: 'gpt-4.1',
200
+ aiModel: 'claude-sonnet-4.5',
201
201
  maxRetries: 3,
202
202
  };
203
203
 
@@ -28,23 +28,49 @@ export class CodeGenerator {
28
28
  async generateCodeFiles(issueData, projectRoot = process.cwd()) {
29
29
  const prompt = this._buildPrompt(issueData, projectRoot);
30
30
 
31
- console.log(' 🤖 調用 AI 生成代碼框架...');
31
+ const VALID_MODELS = ['gpt-4.1', 'gpt-4o', 'claude-haiku-4.5', 'claude-sonnet-4.5', 'o3', 'o4-mini'];
32
+ if (!VALID_MODELS.includes(this.model)) {
33
+ console.warn(` ⚠️ model「${this.model}」可能無效!支援的模型:${VALID_MODELS.join(', ')}`);
34
+ }
35
+ console.log(` 🤖 調用 AI 生成代碼框架(model: ${this.model},最多等待 3 分鐘)...`);
32
36
 
33
37
  let response;
34
38
  try {
39
+ // 代碼生成需要較長時間,使用 180 秒 timeout
35
40
  response = await AIClient.sendAndWait(
36
41
  prompt,
37
42
  this.model,
38
- this.config.maxRetries || 3
43
+ this.config.maxRetries || 3,
44
+ 180_000
39
45
  );
40
46
  } catch (error) {
47
+ // 顯示完整錯誤訊息方便除錯
41
48
  console.warn(` ⚠️ AI 調用失敗:${error.message}`);
49
+ if (error.cause) console.warn(` 原因:${error.cause}`);
50
+ return [];
51
+ }
52
+
53
+ if (!response) {
54
+ console.warn(' ⚠️ AI 回傳空回應');
42
55
  return [];
43
56
  }
44
57
 
45
58
  // 解析 AI 回應
46
59
  const files = this._parseResponse(response);
47
- console.log(` 生成 ${files.length} 個檔案`);
60
+ if (files.length === 0) {
61
+ console.warn(' ⚠️ AI 未回傳任何檔案(可能 JSON 格式有誤)');
62
+ if (process.env.AUTODEV_DEBUG) {
63
+ console.log(' --- AI 原始回應 ---');
64
+ console.log(response.slice(0, 500));
65
+ console.log(' (設定 AUTODEV_DEBUG=1 可看到完整回應)');
66
+ }
67
+ } else {
68
+ console.log(` ✅ AI 規劃生成 ${files.length} 個檔案:`);
69
+ files.forEach((f) => {
70
+ const icon = f.filePath.includes('.test.') || f.filePath.includes('__tests__') ? '🧪' : '📄';
71
+ console.log(` ${icon} ${f.filePath}`);
72
+ });
73
+ }
48
74
  return files;
49
75
  }
50
76
 
@@ -63,7 +89,8 @@ export class CodeGenerator {
63
89
 
64
90
  for (const file of files) {
65
91
  if (file.type === 'skip') {
66
- skipped.push(`${file.filePath} (${file.reason})`);
92
+ console.log(` ⏭️ 跳過 ${file.filePath}${file.reason ? ` (${file.reason})` : ''}`);
93
+ skipped.push(`${file.filePath}${file.reason ? ` (${file.reason})` : ''}`);
67
94
  continue;
68
95
  }
69
96
 
@@ -76,17 +103,21 @@ export class CodeGenerator {
76
103
  mkdirSync(dir, { recursive: true });
77
104
  }
78
105
  } catch (e) {
79
- console.warn(` ⚠️ 無法建立目錄 ${dir}`);
106
+ console.warn(` ⚠️ 無法建立目錄 ${dir}:${e.message}`);
80
107
  skipped.push(file.filePath);
81
108
  continue;
82
109
  }
83
110
 
84
- // 寫入檔案
111
+ // 寫入檔案(即時顯示)
85
112
  try {
113
+ const isTest = file.filePath.includes('.test.') || file.filePath.includes('__tests__');
114
+ const icon = isTest ? '🧪' : '📄';
115
+ const existed = existsSync(fullPath);
86
116
  writeFileSync(fullPath, file.content, 'utf-8');
87
117
  written.push(file.filePath);
118
+ console.log(` ${icon} ${existed ? '更新' : '新建'} ${file.filePath}`);
88
119
  } catch (e) {
89
- console.warn(` ⚠️ 無法寫入 ${file.filePath}`);
120
+ console.warn(` ⚠️ 無法寫入 ${file.filePath}:${e.message}`);
90
121
  skipped.push(file.filePath);
91
122
  }
92
123
  }
@@ -196,15 +196,28 @@ export class AutodevWorkflow {
196
196
  return [];
197
197
  }
198
198
 
199
- // 寫入檔案
199
+ // 寫入檔案(每個檔案會即時顯示名稱)
200
200
  const { written, skipped } = await this.codeGenerator.writeFiles(files, projectRoot);
201
- console.log(` ✅ 已寫入 ${written.length} 個檔案`);
201
+
202
202
  if (skipped.length > 0) {
203
203
  console.warn(` ⚠️ 跳過 ${skipped.length} 個檔案`);
204
204
  }
205
205
 
206
- if (options.verbose) {
207
- written.forEach((f) => console.log(` 新建: ${f}`));
206
+ // 顯示 git diff --stat 讓用戶看到實際變動
207
+ if (written.length > 0) {
208
+ console.log(`\n ✅ 共寫入 ${written.length} 個檔案,git 變動摘要:`);
209
+ try {
210
+ const { execSync } = await import('child_process');
211
+ const stat = execSync('git diff --stat HEAD 2>/dev/null || git status --short', {
212
+ cwd: projectRoot,
213
+ encoding: 'utf-8',
214
+ }).trim();
215
+ if (stat) {
216
+ stat.split('\n').forEach((line) => console.log(` ${line}`));
217
+ }
218
+ } catch (_) {
219
+ // git diff 失敗不影響流程
220
+ }
208
221
  }
209
222
 
210
223
  return written;