ai-git-tool 1.2.0 → 1.4.0

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.
@@ -0,0 +1,479 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkGHCLI = checkGHCLI;
4
+ exports.checkGHAuth = checkGHAuth;
5
+ exports.detectBaseBranch = detectBaseBranch;
6
+ exports.getBranchDiff = getBranchDiff;
7
+ exports.parseGitHubRepoPath = parseGitHubRepoPath;
8
+ exports.getPullRequestURL = getPullRequestURL;
9
+ exports.createPR = createPR;
10
+ exports.pushBranchForPR = pushBranchForPR;
11
+ exports.checkConflicts = checkConflicts;
12
+ exports.syncWithBaseBranch = syncWithBaseBranch;
13
+ const child_process_1 = require("child_process");
14
+ const errors_js_1 = require("../utils/errors.js");
15
+ const ui_js_1 = require("../utils/ui.js");
16
+ /**
17
+ * GitHub CLI がインストールされているかチェック
18
+ */
19
+ function checkGHCLI(language) {
20
+ try {
21
+ (0, child_process_1.execSync)("gh --version", { encoding: "utf-8", stdio: "pipe" });
22
+ }
23
+ catch {
24
+ if (language === "ja") {
25
+ (0, errors_js_1.showFriendlyError)("GitHub CLI (gh) がインストールされていません", "PR を作成するには GitHub CLI が必要です", [
26
+ "GitHub CLI をインストール: https://cli.github.com/",
27
+ "macOS: brew install gh",
28
+ "Windows: winget install GitHub.cli",
29
+ "Linux: 上記サイトから手順を確認",
30
+ ], [
31
+ "インストール後に ai-git pr を実行",
32
+ "または、手動で GitHub のウェブサイトから PR を作成",
33
+ ]);
34
+ }
35
+ else {
36
+ (0, errors_js_1.showFriendlyError)("GitHub CLI (gh) is not installed", "GitHub CLI is required to create pull requests", [
37
+ "Install GitHub CLI: https://cli.github.com/",
38
+ "macOS: brew install gh",
39
+ "Windows: winget install GitHub.cli",
40
+ "Linux: see the website above for instructions",
41
+ ], [
42
+ "Run ai-git pr after installation",
43
+ "Or create PR manually on GitHub website",
44
+ ]);
45
+ }
46
+ process.exit(1);
47
+ }
48
+ }
49
+ /**
50
+ * GitHub CLI の認証状態をチェック
51
+ */
52
+ function checkGHAuth(language) {
53
+ if (process.env.GH_TOKEN) {
54
+ return;
55
+ }
56
+ try {
57
+ (0, child_process_1.execSync)("gh auth status", { encoding: "utf-8", stdio: "pipe" });
58
+ }
59
+ catch {
60
+ if (language === "ja") {
61
+ (0, errors_js_1.showFriendlyError)("GitHub CLI の認証が必要です", "GitHub にログインしていないため、PR を作成できません", [
62
+ "対話式でログイン: gh auth login",
63
+ "ブラウザが開くので、指示に従ってログインしてください",
64
+ "または、Personal Access Token を使用: export GH_TOKEN=<your_token>",
65
+ "Token 作成: https://github.com/settings/tokens",
66
+ ], [
67
+ "ログイン後に ai-git pr を実行",
68
+ "ai-git commit でまずローカルにコミット(PR は後で作成)",
69
+ ]);
70
+ }
71
+ else {
72
+ (0, errors_js_1.showFriendlyError)("GitHub CLI authentication is required", "You need to log in to GitHub to create pull requests", [
73
+ "Interactive login: gh auth login",
74
+ "Follow the browser instructions to log in",
75
+ "Or use Personal Access Token: export GH_TOKEN=<your_token>",
76
+ "Create token: https://github.com/settings/tokens",
77
+ ], [
78
+ "Run ai-git pr after logging in",
79
+ "Use ai-git commit to commit locally first (create PR later)",
80
+ ]);
81
+ }
82
+ process.exit(1);
83
+ }
84
+ }
85
+ /**
86
+ * ベースブランチを検出
87
+ */
88
+ function detectBaseBranch(language) {
89
+ try {
90
+ const result = (0, child_process_1.execSync)("git symbolic-ref refs/remotes/origin/HEAD", {
91
+ encoding: "utf-8",
92
+ stdio: "pipe",
93
+ }).trim();
94
+ return result.replace("refs/remotes/origin/", "");
95
+ }
96
+ catch {
97
+ // Fallback
98
+ }
99
+ for (const branch of ["main", "master", "develop"]) {
100
+ try {
101
+ (0, child_process_1.execSync)(`git rev-parse --verify ${branch}`, { stdio: "pipe" });
102
+ return branch;
103
+ }
104
+ catch {
105
+ continue;
106
+ }
107
+ }
108
+ if (language === "ja") {
109
+ (0, errors_js_1.showFriendlyError)("ベースブランチを検出できませんでした", "main, master, develop のいずれも存在しません", [
110
+ "リポジトリのデフォルトブランチを確認: git branch -a",
111
+ "ベースブランチを作成: git checkout -b main",
112
+ "リモートからブランチを取得: git fetch origin",
113
+ "リモートのデフォルトブランチを設定: git remote set-head origin --auto",
114
+ ], [
115
+ "ベースブランチ作成後に ai-git pr を実行",
116
+ "ai-git commit で現在のブランチにコミット",
117
+ ]);
118
+ }
119
+ else {
120
+ (0, errors_js_1.showFriendlyError)("Could not detect base branch", "None of main, master, develop exist", [
121
+ "Check repository branches: git branch -a",
122
+ "Create base branch: git checkout -b main",
123
+ "Fetch branches from remote: git fetch origin",
124
+ "Set remote default branch: git remote set-head origin --auto",
125
+ ], [
126
+ "Run ai-git pr after creating base branch",
127
+ "Use ai-git commit to commit to current branch",
128
+ ]);
129
+ }
130
+ process.exit(1);
131
+ }
132
+ /**
133
+ * ブランチの差分を取得
134
+ */
135
+ function getBranchDiff(baseBranch, language) {
136
+ try {
137
+ const commits = (0, child_process_1.execSync)(`git log ${baseBranch}..HEAD --format="%h %s%n%b%n---"`, { encoding: "utf-8" });
138
+ const diff = (0, child_process_1.execSync)(`git diff ${baseBranch}...HEAD`, {
139
+ encoding: "utf-8",
140
+ });
141
+ return { commits, diff };
142
+ }
143
+ catch {
144
+ if (language === "ja") {
145
+ (0, errors_js_1.showFriendlyError)("ブランチの差分取得に失敗しました", `${baseBranch} ブランチとの差分を取得できませんでした`, [
146
+ "ブランチの状態を確認: git log --oneline",
147
+ `ベースブランチ (${baseBranch}) が存在するか確認: git branch -a`,
148
+ "リモートから最新を取得: git fetch origin",
149
+ "コミットがあるか確認: git log",
150
+ ], [
151
+ "コミットがない場合は ai-git commit でまずコミット",
152
+ "ブランチが存在しない場合は ai-git checkout で作成",
153
+ ]);
154
+ }
155
+ else {
156
+ (0, errors_js_1.showFriendlyError)("Failed to get branch diff", `Could not get diff with ${baseBranch} branch`, [
157
+ "Check branch status: git log --oneline",
158
+ `Check if base branch (${baseBranch}) exists: git branch -a`,
159
+ "Fetch latest from remote: git fetch origin",
160
+ "Check if there are commits: git log",
161
+ ], [
162
+ "Use ai-git commit to create commits first",
163
+ "Use ai-git checkout to create a new branch",
164
+ ]);
165
+ }
166
+ process.exit(1);
167
+ }
168
+ }
169
+ /**
170
+ * GitHub リポジトリのパスをパース
171
+ */
172
+ function parseGitHubRepoPath(remoteUrl) {
173
+ const normalized = remoteUrl.replace(/\.git$/, "");
174
+ const sshMatch = normalized.match(/^git@github\.com:(.+\/.+)$/);
175
+ if (sshMatch) {
176
+ return sshMatch[1];
177
+ }
178
+ const httpsMatch = normalized.match(/^https:\/\/github\.com\/(.+\/.+)$/);
179
+ if (httpsMatch) {
180
+ return httpsMatch[1];
181
+ }
182
+ return null;
183
+ }
184
+ /**
185
+ * Pull Request の URL を取得
186
+ */
187
+ function getPullRequestURL(branch) {
188
+ try {
189
+ const remoteUrl = (0, child_process_1.execSync)("git remote get-url origin", {
190
+ encoding: "utf-8",
191
+ stdio: "pipe",
192
+ }).trim();
193
+ const repoPath = parseGitHubRepoPath(remoteUrl);
194
+ if (!repoPath) {
195
+ return null;
196
+ }
197
+ return `https://github.com/${repoPath}/pull/new/${branch}`;
198
+ }
199
+ catch {
200
+ return null;
201
+ }
202
+ }
203
+ /**
204
+ * PR を作成
205
+ */
206
+ function createPR(description, baseBranch, fallbackURL, language, extractPRTitle, stripTitleLine) {
207
+ const titleLine = extractPRTitle(description);
208
+ const body = stripTitleLine(description);
209
+ const result = (0, child_process_1.spawnSync)("gh", [
210
+ "pr",
211
+ "create",
212
+ "--base",
213
+ baseBranch,
214
+ "--title",
215
+ titleLine.trim(),
216
+ "--body",
217
+ body,
218
+ ], { encoding: "utf-8", stdio: "pipe" });
219
+ if (result.stdout) {
220
+ process.stdout.write(result.stdout);
221
+ }
222
+ if (result.stderr) {
223
+ process.stderr.write(result.stderr);
224
+ }
225
+ if (result.status !== 0) {
226
+ if (language === "ja") {
227
+ const solutions = [
228
+ "ブランチがプッシュされているか確認: git log origin/$(git branch --show-current)",
229
+ "GitHub への接続を確認してください",
230
+ "gh auth status で認証状態を確認",
231
+ "同名の PR が既に存在しないか GitHub で確認",
232
+ ];
233
+ if (fallbackURL) {
234
+ solutions.push(`手動で作成: ${fallbackURL}`);
235
+ }
236
+ (0, errors_js_1.showFriendlyError)("PR の作成に失敗しました", "GitHub CLI で PR を作成できませんでした", solutions, [
237
+ "エラーを確認・修正後に ai-git pr を再実行",
238
+ "ai-git push でブランチをプッシュ(未プッシュの場合)",
239
+ ]);
240
+ }
241
+ else {
242
+ const solutions = [
243
+ "Check if branch is pushed: git log origin/$(git branch --show-current)",
244
+ "Verify GitHub connection",
245
+ "Check auth status: gh auth status",
246
+ "Check if PR with same name already exists on GitHub",
247
+ ];
248
+ if (fallbackURL) {
249
+ solutions.push(`Create manually: ${fallbackURL}`);
250
+ }
251
+ (0, errors_js_1.showFriendlyError)("Failed to create PR", "Could not create pull request via GitHub CLI", solutions, [
252
+ "Fix the error and run ai-git pr again",
253
+ "Use ai-git push to push branch (if not pushed)",
254
+ ]);
255
+ }
256
+ process.exit(1);
257
+ }
258
+ }
259
+ /**
260
+ * ブランチを push(PR 作成前)
261
+ */
262
+ function pushBranchForPR(currentBranch, language) {
263
+ try {
264
+ (0, child_process_1.execSync)(`git rev-parse --abbrev-ref ${currentBranch}@{upstream}`, {
265
+ encoding: "utf-8",
266
+ stdio: "pipe",
267
+ });
268
+ const localCommit = (0, child_process_1.execSync)(`git rev-parse ${currentBranch}`, {
269
+ encoding: "utf-8",
270
+ stdio: "pipe",
271
+ }).trim();
272
+ const remoteCommit = (0, child_process_1.execSync)(`git rev-parse ${currentBranch}@{upstream}`, {
273
+ encoding: "utf-8",
274
+ stdio: "pipe",
275
+ }).trim();
276
+ if (localCommit !== remoteCommit) {
277
+ console.log(`📤 ブランチを push 中... (origin ${currentBranch})`);
278
+ const pushResult = (0, child_process_1.spawnSync)("git", ["push"], { stdio: "inherit" });
279
+ if (pushResult.status !== 0) {
280
+ if (language === "ja") {
281
+ (0, errors_js_1.showFriendlyError)("ブランチの push に失敗しました (PR作成前)", "PR を作成する前にブランチをリモートにプッシュできませんでした", [
282
+ "リモートリポジトリの設定を確認: git remote -v",
283
+ "プッシュ権限を確認してください",
284
+ "リモートブランチとの競合確認: git pull --rebase",
285
+ "ネットワーク接続を確認してください",
286
+ ], [
287
+ "競合解決後に ai-git pr を再実行",
288
+ "手動でプッシュ: git push",
289
+ ]);
290
+ }
291
+ else {
292
+ (0, errors_js_1.showFriendlyError)("Failed to push branch (before PR creation)", "Could not push branch to remote before creating PR", [
293
+ "Check remote repository: git remote -v",
294
+ "Verify push permissions",
295
+ "Check for conflicts: git pull --rebase",
296
+ "Verify network connection",
297
+ ], [
298
+ "Run ai-git pr again after fixing",
299
+ "Push manually: git push",
300
+ ]);
301
+ }
302
+ process.exit(1);
303
+ }
304
+ }
305
+ }
306
+ catch {
307
+ console.log(`📤 ブランチを push 中... (origin ${currentBranch} を新規作成)`);
308
+ const pushResult = (0, child_process_1.spawnSync)("git", ["push", "-u", "origin", currentBranch], { stdio: "inherit" });
309
+ if (pushResult.status !== 0) {
310
+ if (language === "ja") {
311
+ (0, errors_js_1.showFriendlyError)("新しいブランチの push に失敗しました (PR作成前)", "PR を作成する前に新しいブランチをリモートに作成できませんでした", [
312
+ "リモートリポジトリの URL を確認: git remote -v",
313
+ "リモートリポジトリへのプッシュ権限を確認",
314
+ "SSH キーまたは認証情報が正しく設定されているか確認",
315
+ "ネットワーク接続を確認してください",
316
+ ], [
317
+ "認証・権限を確認後に ai-git pr を再実行",
318
+ "手動でプッシュ: git push -u origin " + currentBranch,
319
+ ]);
320
+ }
321
+ else {
322
+ (0, errors_js_1.showFriendlyError)("Failed to push new branch (before PR creation)", "Could not create new branch on remote before creating PR", [
323
+ "Check remote repository URL: git remote -v",
324
+ "Verify push permissions to remote",
325
+ "Check SSH keys or credentials are set up correctly",
326
+ "Verify network connection",
327
+ ], [
328
+ "Run ai-git pr again after fixing auth/permissions",
329
+ "Push manually: git push -u origin " + currentBranch,
330
+ ]);
331
+ }
332
+ process.exit(1);
333
+ }
334
+ }
335
+ }
336
+ /**
337
+ * コンフリクトがあるかを非破壊的に検知
338
+ */
339
+ function checkConflicts(baseBranch) {
340
+ try {
341
+ const mergeBase = (0, child_process_1.execSync)(`git merge-base HEAD origin/${baseBranch}`, {
342
+ encoding: "utf-8",
343
+ stdio: "pipe",
344
+ }).trim();
345
+ const mergeTreeOutput = (0, child_process_1.execSync)(`git merge-tree ${mergeBase} origin/${baseBranch} HEAD`, {
346
+ encoding: "utf-8",
347
+ stdio: "pipe",
348
+ });
349
+ return mergeTreeOutput.includes("<<<<<<<");
350
+ }
351
+ catch {
352
+ return false;
353
+ }
354
+ }
355
+ /**
356
+ * ベースブランチとの同期処理(PR作成前)
357
+ */
358
+ async function syncWithBaseBranch(baseBranch, currentBranch, language) {
359
+ console.log(language === "ja"
360
+ ? `🔄 ${baseBranch} との同期を確認中...`
361
+ : `🔄 Checking sync with ${baseBranch}...`);
362
+ // 最新を取得
363
+ try {
364
+ (0, child_process_1.execSync)(`git fetch origin ${baseBranch}`, { stdio: "pipe" });
365
+ }
366
+ catch {
367
+ if (language === "ja") {
368
+ (0, errors_js_1.showFriendlyError)("リモートブランチの取得に失敗しました", `origin/${baseBranch} を取得できませんでした`, [
369
+ "ネットワーク接続を確認してください",
370
+ "リモートリポジトリの設定を確認: git remote -v",
371
+ `リモートに ${baseBranch} ブランチが存在するか確認`,
372
+ ], ["接続を確認後に ai-git pr を再実行"]);
373
+ }
374
+ else {
375
+ (0, errors_js_1.showFriendlyError)("Failed to fetch remote branch", `Could not fetch origin/${baseBranch}`, [
376
+ "Check network connection",
377
+ "Check remote repository: git remote -v",
378
+ `Check if ${baseBranch} branch exists on remote`,
379
+ ], ["Run ai-git pr again after fixing connection"]);
380
+ }
381
+ process.exit(1);
382
+ }
383
+ // コンフリクトチェック
384
+ const hasConflicts = checkConflicts(baseBranch);
385
+ if (!hasConflicts) {
386
+ // コンフリクトなし → 自動的にマージ
387
+ console.log(language === "ja"
388
+ ? `✅ コンフリクトなし - origin/${baseBranch} をマージ中...`
389
+ : `✅ No conflicts - merging origin/${baseBranch}...`);
390
+ const mergeResult = (0, child_process_1.spawnSync)("git", ["merge", `origin/${baseBranch}`], {
391
+ stdio: "inherit",
392
+ });
393
+ if (mergeResult.status !== 0) {
394
+ if (language === "ja") {
395
+ (0, errors_js_1.showFriendlyError)("マージに失敗しました", `origin/${baseBranch} のマージ中にエラーが発生しました`, [
396
+ "Git の状態を確認: git status",
397
+ "マージを中止する場合: git merge --abort",
398
+ ], ["問題を解決後に ai-git pr を再実行"]);
399
+ }
400
+ else {
401
+ (0, errors_js_1.showFriendlyError)("Merge failed", `Error occurred while merging origin/${baseBranch}`, ["Check git status: git status", "Abort merge: git merge --abort"], ["Run ai-git pr again after fixing"]);
402
+ }
403
+ process.exit(1);
404
+ }
405
+ console.log(language === "ja"
406
+ ? `✅ origin/${baseBranch} をマージしました`
407
+ : `✅ Merged origin/${baseBranch}`);
408
+ return;
409
+ }
410
+ // コンフリクトあり → 選択肢を提示
411
+ console.log(language === "ja"
412
+ ? `⚠️ origin/${baseBranch} とのコンフリクトを検知しました`
413
+ : `⚠️ Conflicts detected with origin/${baseBranch}`);
414
+ const choices = language === "ja"
415
+ ? `次の操作を選択してください:
416
+ [m] merge origin/${baseBranch} してコンフリクトを解消してからPR作成
417
+ [r] rebase onto origin/${baseBranch} してコンフリクトを解消してからPR作成
418
+ [s] スキップ(そのままPR作成)
419
+ [a] 中止
420
+ 選択 [m/r/s/a]: `
421
+ : `Choose an action:
422
+ [m] merge origin/${baseBranch} and resolve conflicts before creating PR
423
+ [r] rebase onto origin/${baseBranch} and resolve conflicts before creating PR
424
+ [s] skip (create PR anyway)
425
+ [a] abort
426
+ Choice [m/r/s/a]: `;
427
+ const choice = await (0, ui_js_1.askUser)(choices);
428
+ if (choice === "m" || choice === "merge") {
429
+ console.log(language === "ja"
430
+ ? `🔀 origin/${baseBranch} をマージ中...`
431
+ : `🔀 Merging origin/${baseBranch}...`);
432
+ const result = (0, child_process_1.spawnSync)("git", ["merge", `origin/${baseBranch}`], {
433
+ stdio: "inherit",
434
+ });
435
+ if (result.status !== 0) {
436
+ if (language === "ja") {
437
+ console.log(`\n⚠️ コンフリクトを解消してください。解消後、以下を実行:`);
438
+ console.log(` git add .`);
439
+ console.log(` git commit`);
440
+ console.log(` ai-git pr\n`);
441
+ }
442
+ else {
443
+ console.log(`\n⚠️ Please resolve conflicts. After resolving, run:`);
444
+ console.log(` git add .`);
445
+ console.log(` git commit`);
446
+ console.log(` ai-git pr\n`);
447
+ }
448
+ process.exit(1);
449
+ }
450
+ }
451
+ else if (choice === "r" || choice === "rebase") {
452
+ console.log(language === "ja"
453
+ ? `🔀 origin/${baseBranch} へ rebase 中...`
454
+ : `🔀 Rebasing onto origin/${baseBranch}...`);
455
+ const result = (0, child_process_1.spawnSync)("git", ["rebase", `origin/${baseBranch}`], {
456
+ stdio: "inherit",
457
+ });
458
+ if (result.status !== 0) {
459
+ if (language === "ja") {
460
+ console.log(`\n⚠️ コンフリクトを解消してください。解消後、以下を実行:`);
461
+ console.log(` git add .`);
462
+ console.log(` git rebase --continue`);
463
+ console.log(` ai-git pr\n`);
464
+ }
465
+ else {
466
+ console.log(`\n⚠️ Please resolve conflicts. After resolving, run:`);
467
+ console.log(` git add .`);
468
+ console.log(` git rebase --continue`);
469
+ console.log(` ai-git pr\n`);
470
+ }
471
+ process.exit(1);
472
+ }
473
+ }
474
+ else if (choice === "a" || choice === "abort") {
475
+ console.log(language === "ja" ? "中止しました。" : "Aborted.");
476
+ process.exit(0);
477
+ }
478
+ // 's' または 'skip' の場合はそのまま続行
479
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseLanguage = parseLanguage;
37
+ exports.loadConfig = loadConfig;
38
+ exports.saveConfig = saveConfig;
39
+ exports.resolveLanguage = resolveLanguage;
40
+ const fs = __importStar(require("fs"));
41
+ const os = __importStar(require("os"));
42
+ const path = __importStar(require("path"));
43
+ const CONFIG_DIR = path.join(os.homedir(), ".ai-commit");
44
+ const CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
45
+ /**
46
+ * 言語文字列をパース
47
+ */
48
+ function parseLanguage(value) {
49
+ if (!value) {
50
+ return null;
51
+ }
52
+ if (value === "ja" || value === "en") {
53
+ return value;
54
+ }
55
+ return null;
56
+ }
57
+ /**
58
+ * 設定ファイルから言語設定を読み込む
59
+ */
60
+ function loadConfig() {
61
+ try {
62
+ if (!fs.existsSync(CONFIG_PATH)) {
63
+ return null;
64
+ }
65
+ const raw = fs.readFileSync(CONFIG_PATH, "utf-8");
66
+ const parsed = JSON.parse(raw);
67
+ const lang = parseLanguage(parsed.language);
68
+ if (!lang) {
69
+ return null;
70
+ }
71
+ return { language: lang };
72
+ }
73
+ catch {
74
+ return null;
75
+ }
76
+ }
77
+ /**
78
+ * 設定ファイルに言語設定を保存
79
+ */
80
+ function saveConfig(config) {
81
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
82
+ fs.writeFileSync(CONFIG_PATH, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
83
+ }
84
+ /**
85
+ * 言語設定を解決(フラグ → 設定ファイル → デフォルト)
86
+ */
87
+ function resolveLanguage(langValue) {
88
+ const fromFlag = parseLanguage(langValue);
89
+ if (langValue && !fromFlag) {
90
+ console.error("Error: --lang は ja または en を指定してください。");
91
+ process.exit(1);
92
+ }
93
+ if (fromFlag) {
94
+ return fromFlag;
95
+ }
96
+ const config = loadConfig();
97
+ return config?.language ?? "ja";
98
+ }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkIfGitRepository = checkIfGitRepository;
4
+ exports.showFriendlyError = showFriendlyError;
5
+ exports.handleGroqError = handleGroqError;
6
+ exports.isRequestTooLargeError = isRequestTooLargeError;
7
+ const child_process_1 = require("child_process");
8
+ /**
9
+ * Git リポジトリかどうかを確認
10
+ */
11
+ function checkIfGitRepository() {
12
+ try {
13
+ (0, child_process_1.execSync)("git rev-parse --git-dir", { stdio: "pipe" });
14
+ }
15
+ catch {
16
+ console.error("❌ これは Git リポジトリではありません。");
17
+ console.error("");
18
+ console.error("💡 次の手順を試してください:");
19
+ console.error(" 1. Git リポジトリを初期化する:");
20
+ console.error(" git init");
21
+ console.error(" 2. または、既存のリポジトリに移動する:");
22
+ console.error(" cd /path/to/your/repository");
23
+ process.exit(1);
24
+ }
25
+ }
26
+ /**
27
+ * 親切なエラーメッセージを表示
28
+ */
29
+ function showFriendlyError(title, reason, solutions, nextSteps) {
30
+ console.error(`❌ ${title}`);
31
+ console.error("");
32
+ console.error(`📋 原因: ${reason}`);
33
+ console.error("");
34
+ console.error("💡 解決方法:");
35
+ solutions.forEach((solution, idx) => {
36
+ console.error(` ${idx + 1}. ${solution}`);
37
+ });
38
+ if (nextSteps && nextSteps.length > 0) {
39
+ console.error("");
40
+ console.error("🚀 その後、以下のコマンドが使えます:");
41
+ nextSteps.forEach((step) => {
42
+ console.error(` - ${step}`);
43
+ });
44
+ }
45
+ }
46
+ /**
47
+ * Groq API エラーのハンドリング
48
+ */
49
+ function handleGroqError(error) {
50
+ const message = error instanceof Error ? error.message : String(error);
51
+ const lower = message.toLowerCase();
52
+ if (lower.includes("429") ||
53
+ lower.includes("quota") ||
54
+ lower.includes("rate")) {
55
+ console.error("❌ Groq API の利用上限に達しました(429: quota/rate limit)。");
56
+ console.error(" - 少し待って再実行してください");
57
+ console.error(" - https://console.groq.com で利用枠を確認してください");
58
+ console.error(" - 必要なら別プロジェクトの API キーを利用してください");
59
+ return;
60
+ }
61
+ if (lower.includes("401") ||
62
+ lower.includes("403") ||
63
+ lower.includes("api key")) {
64
+ console.error("❌ Groq API 認証エラーです。GROQ_API_KEY を確認してください。");
65
+ console.error(" 取得先: https://console.groq.com/keys");
66
+ return;
67
+ }
68
+ console.error("❌ Groq API 呼び出しに失敗しました。");
69
+ console.error(` 詳細: ${message}`);
70
+ }
71
+ /**
72
+ * リクエストが大きすぎるエラーかどうかを判定
73
+ */
74
+ function isRequestTooLargeError(error) {
75
+ const message = error instanceof Error ? error.message : String(error);
76
+ const lower = message.toLowerCase();
77
+ return (lower.includes("413") ||
78
+ lower.includes("request too large") ||
79
+ lower.includes("tokens per minute") ||
80
+ lower.includes("tpm"));
81
+ }