candy-debug 1.1.0 → 1.1.1
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 +9 -5
- package/dist/candy-debug.mjs +322 -174
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,14 +33,14 @@ candy-debug ./my-project > review.json
|
|
|
33
33
|
candy-debug ./my-project --scan-only
|
|
34
34
|
|
|
35
35
|
# Amazon Bedrock で動かす(モデルは環境変数 BEDROCK_MODEL_ID)
|
|
36
|
-
export AWS_REGION=ap-northeast-1 BEDROCK_MODEL_ID=
|
|
36
|
+
export AWS_REGION=ap-northeast-1 BEDROCK_MODEL_ID=zai.glm-5
|
|
37
37
|
cdbg ./my-project --provider bedrock -o review.json
|
|
38
38
|
|
|
39
39
|
# CI で使う: warning 以上の指摘があれば終了コード 3(JSON は書き終えてから返す)
|
|
40
40
|
cdbg . --provider bedrock --fail-on warning -o review.json
|
|
41
41
|
|
|
42
|
-
#
|
|
43
|
-
cdbg fix review.json --dir . --summary pr.md
|
|
42
|
+
# 指摘のあるファイルを AI に直させる(このときだけ対象フォルダへ書き込む)
|
|
43
|
+
cdbg fix review.json --dir . --provider bedrock --summary pr.md
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
Bedrock の認証は AWS SDK の標準の順序(環境変数・`~/.aws`・SSO・CodeBuild/ECS の実行ロールなど)で探します。
|
|
@@ -61,7 +61,11 @@ CodePipeline に組み込んだ例は、リポジトリの `examples/roxy-pipeli
|
|
|
61
61
|
| `--doctor [--json]` | AI を呼べるかの確認 |
|
|
62
62
|
|
|
63
63
|
`cdbg fix <review.json>` のオプション: `--dir <folder>`(既定 カレント)/ `--min-severity <sev>`(既定 `warning`)/
|
|
64
|
-
`--summary <file>`(プルリクエスト用の Markdown)/ `--dry-run`
|
|
64
|
+
`--summary <file>`(プルリクエスト用の Markdown)/ `--dry-run`。`--provider` / `--model` / `--region` もレビューと同じく使えます。
|
|
65
|
+
|
|
66
|
+
`cdbg fix` は、指摘のあるファイルごとにファイル全体と指摘を AI へ送り、直したファイル全体を返させます。
|
|
67
|
+
JavaScript / JSON は構文検査(`node --check`)を通ったものだけ書き込みます。AI が途中で切れた応答を返したとき・
|
|
68
|
+
対象フォルダの外を指す指摘・AI が「直した」と申告しなかった指摘は書き込みません。**動作は確かめないので、必ず差分を確認してください。**
|
|
65
69
|
|
|
66
70
|
| 環境変数 | 内容 |
|
|
67
71
|
| --------------------------- | --------------------------------------------- |
|
|
@@ -84,7 +88,7 @@ CodePipeline に組み込んだ例は、リポジトリの `examples/roxy-pipeli
|
|
|
84
88
|
{
|
|
85
89
|
"format": "candy-debug/review",
|
|
86
90
|
"schemaVersion": 1,
|
|
87
|
-
"generator": { "name": "candy-debug", "version": "1.1.
|
|
91
|
+
"generator": { "name": "candy-debug", "version": "1.1.1" },
|
|
88
92
|
"project": { "name": "my-project", "dir": "/path/to/my-project" },
|
|
89
93
|
"findings": [/* 指摘 */],
|
|
90
94
|
"scenario": { "beats": [/* 台詞・表情・コード片・赤枠の位置 */] },
|
package/dist/candy-debug.mjs
CHANGED
|
@@ -3900,7 +3900,7 @@ var init_getProfileName = __esm({
|
|
|
3900
3900
|
|
|
3901
3901
|
// node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getSSOTokenFilepath.js
|
|
3902
3902
|
import { createHash } from "node:crypto";
|
|
3903
|
-
import { join as
|
|
3903
|
+
import { join as join3 } from "node:path";
|
|
3904
3904
|
var getSSOTokenFilepath;
|
|
3905
3905
|
var init_getSSOTokenFilepath = __esm({
|
|
3906
3906
|
"node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getSSOTokenFilepath.js"() {
|
|
@@ -3908,7 +3908,7 @@ var init_getSSOTokenFilepath = __esm({
|
|
|
3908
3908
|
getSSOTokenFilepath = (id) => {
|
|
3909
3909
|
const hasher = createHash("sha1");
|
|
3910
3910
|
const cacheName = hasher.update(id).digest("hex");
|
|
3911
|
-
return
|
|
3911
|
+
return join3(getHomeDir(), ".aws", "sso", "cache", `${cacheName}.json`);
|
|
3912
3912
|
};
|
|
3913
3913
|
}
|
|
3914
3914
|
});
|
|
@@ -3963,24 +3963,24 @@ var init_getConfigData = __esm({
|
|
|
3963
3963
|
});
|
|
3964
3964
|
|
|
3965
3965
|
// node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getConfigFilepath.js
|
|
3966
|
-
import { join as
|
|
3966
|
+
import { join as join4 } from "node:path";
|
|
3967
3967
|
var ENV_CONFIG_PATH, getConfigFilepath;
|
|
3968
3968
|
var init_getConfigFilepath = __esm({
|
|
3969
3969
|
"node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getConfigFilepath.js"() {
|
|
3970
3970
|
init_getHomeDir();
|
|
3971
3971
|
ENV_CONFIG_PATH = "AWS_CONFIG_FILE";
|
|
3972
|
-
getConfigFilepath = () => process.env[ENV_CONFIG_PATH] ||
|
|
3972
|
+
getConfigFilepath = () => process.env[ENV_CONFIG_PATH] || join4(getHomeDir(), ".aws", "config");
|
|
3973
3973
|
}
|
|
3974
3974
|
});
|
|
3975
3975
|
|
|
3976
3976
|
// node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getCredentialsFilepath.js
|
|
3977
|
-
import { join as
|
|
3977
|
+
import { join as join5 } from "node:path";
|
|
3978
3978
|
var ENV_CREDENTIALS_PATH, getCredentialsFilepath;
|
|
3979
3979
|
var init_getCredentialsFilepath = __esm({
|
|
3980
3980
|
"node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getCredentialsFilepath.js"() {
|
|
3981
3981
|
init_getHomeDir();
|
|
3982
3982
|
ENV_CREDENTIALS_PATH = "AWS_SHARED_CREDENTIALS_FILE";
|
|
3983
|
-
getCredentialsFilepath = () => process.env[ENV_CREDENTIALS_PATH] ||
|
|
3983
|
+
getCredentialsFilepath = () => process.env[ENV_CREDENTIALS_PATH] || join5(getHomeDir(), ".aws", "credentials");
|
|
3984
3984
|
}
|
|
3985
3985
|
});
|
|
3986
3986
|
|
|
@@ -4060,7 +4060,7 @@ var init_readFile = __esm({
|
|
|
4060
4060
|
});
|
|
4061
4061
|
|
|
4062
4062
|
// node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/loadSharedConfigFiles.js
|
|
4063
|
-
import { join as
|
|
4063
|
+
import { join as join6 } from "node:path";
|
|
4064
4064
|
var swallowError, loadSharedConfigFiles;
|
|
4065
4065
|
var init_loadSharedConfigFiles = __esm({
|
|
4066
4066
|
"node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/loadSharedConfigFiles.js"() {
|
|
@@ -4078,11 +4078,11 @@ var init_loadSharedConfigFiles = __esm({
|
|
|
4078
4078
|
const relativeHomeDirPrefix = "~/";
|
|
4079
4079
|
let resolvedFilepath = filepath;
|
|
4080
4080
|
if (filepath.startsWith(relativeHomeDirPrefix)) {
|
|
4081
|
-
resolvedFilepath =
|
|
4081
|
+
resolvedFilepath = join6(homeDir, filepath.slice(2));
|
|
4082
4082
|
}
|
|
4083
4083
|
let resolvedConfigFilepath = configFilepath;
|
|
4084
4084
|
if (configFilepath.startsWith(relativeHomeDirPrefix)) {
|
|
4085
|
-
resolvedConfigFilepath =
|
|
4085
|
+
resolvedConfigFilepath = join6(homeDir, configFilepath.slice(2));
|
|
4086
4086
|
}
|
|
4087
4087
|
const parsedFiles = await Promise.all([
|
|
4088
4088
|
readFile2(resolvedConfigFilepath, {
|
|
@@ -27631,7 +27631,7 @@ var require_dist_cjs14 = __commonJS({
|
|
|
27631
27631
|
var { createHash: createHash5, createPrivateKey, createPublicKey, sign: sign2 } = __require("node:crypto");
|
|
27632
27632
|
var { promises } = __require("node:fs");
|
|
27633
27633
|
var { homedir: homedir2 } = __require("node:os");
|
|
27634
|
-
var { dirname: dirname2, join:
|
|
27634
|
+
var { dirname: dirname2, join: join7 } = __require("node:path");
|
|
27635
27635
|
var LoginCredentialsFetcher = class _LoginCredentialsFetcher {
|
|
27636
27636
|
profileData;
|
|
27637
27637
|
init;
|
|
@@ -27795,10 +27795,10 @@ var require_dist_cjs14 = __commonJS({
|
|
|
27795
27795
|
await promises.writeFile(tokenFilePath, JSON.stringify(token, null, 2), "utf8");
|
|
27796
27796
|
}
|
|
27797
27797
|
getTokenFilePath() {
|
|
27798
|
-
const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ??
|
|
27798
|
+
const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ?? join7(homedir2(), ".aws", "login", "cache");
|
|
27799
27799
|
const loginSessionBytes = Buffer.from(this.loginSession, "utf8");
|
|
27800
27800
|
const loginSessionSha256 = createHash5("sha256").update(loginSessionBytes).digest("hex");
|
|
27801
|
-
return
|
|
27801
|
+
return join7(directory, `${loginSessionSha256}.json`);
|
|
27802
27802
|
}
|
|
27803
27803
|
derToRawSignature(derSignature) {
|
|
27804
27804
|
let offset = 2;
|
|
@@ -32605,7 +32605,7 @@ import { parseArgs } from "node:util";
|
|
|
32605
32605
|
// package.json
|
|
32606
32606
|
var package_default = {
|
|
32607
32607
|
name: "candy-debug",
|
|
32608
|
-
version: "1.1.
|
|
32608
|
+
version: "1.1.1",
|
|
32609
32609
|
description: "\u30ED\u30AD\u30B7\u30FC\u304C\u30B3\u30FC\u30C9\u30EC\u30D3\u30E5\u30FC\u3092\u3057\u3066\u3001\u30CE\u30D9\u30EB\u30B2\u30FC\u30E0\u7528\u306E\u53F0\u672C\uFF08JSON\uFF09\u3092\u4F5C\u308B CLI",
|
|
32610
32610
|
type: "module",
|
|
32611
32611
|
bin: {
|
|
@@ -32970,8 +32970,10 @@ function parseReviewFile(raw) {
|
|
|
32970
32970
|
}
|
|
32971
32971
|
|
|
32972
32972
|
// src/fix/applyFixes.ts
|
|
32973
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
32973
32974
|
import { promises as fs2 } from "node:fs";
|
|
32974
|
-
import {
|
|
32975
|
+
import { tmpdir } from "node:os";
|
|
32976
|
+
import { extname, isAbsolute, join as join2, relative as relative2, resolve } from "node:path";
|
|
32975
32977
|
|
|
32976
32978
|
// src/review/scanner.ts
|
|
32977
32979
|
import { promises as fs } from "node:fs";
|
|
@@ -33219,17 +33221,156 @@ function prioritize(findings, max) {
|
|
|
33219
33221
|
return [...keepRest, ...keepPraise];
|
|
33220
33222
|
}
|
|
33221
33223
|
|
|
33224
|
+
// src/review/prompts.ts
|
|
33225
|
+
var REVIEW_SYSTEM = `\u3042\u306A\u305F\u306F\u7D4C\u9A13\u8C4A\u5BCC\u306A\u30B3\u30FC\u30C9\u30EC\u30D3\u30E5\u30A2\u30FC\u3067\u3059\u3002\u65E5\u672C\u8A9E\u3067\u56DE\u7B54\u3057\u307E\u3059\u3002
|
|
33226
|
+
|
|
33227
|
+
# \u51FA\u529B\u5F62\u5F0F
|
|
33228
|
+
JSON \u914D\u5217\u306E\u307F\u3092\u51FA\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u524D\u7F6E\u304D\u30FB\u5F8C\u66F8\u304D\u30FB\u30DE\u30FC\u30AF\u30C0\u30A6\u30F3\u306E\u30B3\u30FC\u30C9\u30D5\u30A7\u30F3\u30B9\u3092\u66F8\u3044\u3066\u306F\u3044\u3051\u307E\u305B\u3093\u3002
|
|
33229
|
+
|
|
33230
|
+
\u5404\u8981\u7D20\u306E\u5F62\u5F0F:
|
|
33231
|
+
{
|
|
33232
|
+
"severity": "critical" | "warning" | "info" | "praise",
|
|
33233
|
+
"category": "\u30D0\u30B0" | "\u5B89\u5168\u6027" | "\u53EF\u8AAD\u6027" | "\u8A2D\u8A08" | "\u6027\u80FD" | "\u898F\u7D04" \u306E\u3044\u305A\u308C\u304B,
|
|
33234
|
+
"title": "\u4E00\u884C\u8981\u7D04\uFF0840\u5B57\u4EE5\u5185\uFF09",
|
|
33235
|
+
"file": "\u5165\u529B\u3067\u4E0E\u3048\u3089\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u30D1\u30B9\u3068\u5B8C\u5168\u306B\u4E00\u81F4\u3059\u308B\u6587\u5B57\u5217",
|
|
33236
|
+
"startLine": \u6307\u6458\u5BFE\u8C61\u306E\u958B\u59CB\u884C\u756A\u53F7\uFF08\u5165\u529B\u306B\u4ED8\u3044\u3066\u3044\u308B\u884C\u756A\u53F7\u3092\u305D\u306E\u307E\u307E\u4F7F\u3046\uFF09,
|
|
33237
|
+
"endLine": \u6307\u6458\u5BFE\u8C61\u306E\u7D42\u4E86\u884C\u756A\u53F7,
|
|
33238
|
+
"highlightText": "\u305D\u306E\u884C\u306B\u5B9F\u5728\u3059\u308B\u90E8\u5206\u6587\u5B57\u5217\u3002\u67A0\u3067\u56F2\u3093\u3067\u793A\u3059\u306E\u306B\u4F7F\u3046",
|
|
33239
|
+
"problem": "\u4F55\u304C\u554F\u984C\u304B\u30022\u301C3\u6587",
|
|
33240
|
+
"suggestion": "\u3069\u3046\u76F4\u3059\u304B\u30022\u301C3\u6587",
|
|
33241
|
+
"improvedCode": "\u6539\u5584\u5F8C\u306E\u30B3\u30FC\u30C9\uFF08startLine\u301CendLine \u306E\u7BC4\u56F2\u3076\u3093\u3060\u3051\uFF09\u3002\u7121\u3051\u308C\u3070\u7701\u7565",
|
|
33242
|
+
"confidence": "high" | "medium" | "low"
|
|
33243
|
+
}
|
|
33244
|
+
|
|
33245
|
+
# \u5B88\u308B\u3053\u3068
|
|
33246
|
+
1. file \u306F\u5FC5\u305A\u5165\u529B\u3067\u4E0E\u3048\u305F\u30D5\u30A1\u30A4\u30EB\u30D1\u30B9\u306E\u3044\u305A\u308C\u304B\u3068\u5B8C\u5168\u4E00\u81F4\u3055\u305B\u308B\u3002\u63A8\u6E2C\u3067\u66F8\u304B\u306A\u3044\u3002
|
|
33247
|
+
2. startLine / endLine \u306F\u5165\u529B\u306B\u4ED8\u3044\u3066\u3044\u308B\u884C\u756A\u53F7\u3092\u305D\u306E\u307E\u307E\u4F7F\u3046\u3002\u6570\u3048\u76F4\u3055\u306A\u3044\u3002
|
|
33248
|
+
3. highlightText \u306F\u305D\u306E\u884C\u306B**\u5B9F\u5728\u3059\u308B\u6587\u5B57\u5217**\u306B\u3059\u308B\u3002\u5B58\u5728\u3057\u306A\u3044\u6587\u5B57\u5217\u3092\u66F8\u304B\u306A\u3044\u3002
|
|
33249
|
+
4. \u78BA\u4FE1\u304C\u6301\u3066\u306A\u3044\u3082\u306E\u306F confidence \u3092 "low" \u306B\u3059\u308B\u3002\u63A8\u6E2C\u3067\u65AD\u5B9A\u3057\u306A\u3044\u3002
|
|
33250
|
+
5. \u4E00\u822C\u8AD6\u3092\u66F8\u304B\u306A\u3044\u3002\u300C\u5909\u6570\u540D\u306F\u5206\u304B\u308A\u3084\u3059\u304F\u300D\u3067\u306F\u306A\u304F\u3001\u305D\u306E\u30B3\u30FC\u30C9\u306E\u5177\u4F53\u7684\u306A\u7B87\u6240\u3092\u6307\u3059\u3002
|
|
33251
|
+
6. **\u826F\u3044\u70B9\uFF08severity: "praise"\uFF09\u3092\u5FC5\u305A1\u4EF6\u4EE5\u4E0A\u542B\u3081\u308B\u3002**
|
|
33252
|
+
7. \u30AD\u30E3\u30E9\u30AF\u30BF\u30FC\u3092\u6F14\u3058\u306A\u3044\u3002\u3053\u3053\u3067\u306F\u4E8B\u5B9F\u3060\u3051\u3092\u3001\u7D20\u306E\u65E5\u672C\u8A9E\u3067\u66F8\u304F\u3002`;
|
|
33253
|
+
function reviewUserPrompt(formattedFiles, maxFindings) {
|
|
33254
|
+
return `\u6B21\u306E\u30B3\u30FC\u30C9\u3092\u30EC\u30D3\u30E5\u30FC\u3057\u3001\u6307\u6458\u3092\u6700\u5927 ${maxFindings} \u4EF6\u3001JSON \u914D\u5217\u3067\u51FA\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
33255
|
+
\u91CD\u8981\u306A\u3082\u306E\u3092\u512A\u5148\u3057\u3001\u4E9B\u7D30\u306A\u3082\u306E\u306F\u7701\u3044\u3066\u304F\u3060\u3055\u3044\u3002
|
|
33256
|
+
|
|
33257
|
+
${formattedFiles}`;
|
|
33258
|
+
}
|
|
33259
|
+
function scenarioSystem(c5) {
|
|
33260
|
+
return `\u3042\u306A\u305F\u306F\u300C${c5.nameJa}\u300D\u3068\u3044\u3046\u30AD\u30E3\u30E9\u30AF\u30BF\u30FC\u3068\u3057\u3066\u3001\u30B3\u30FC\u30C9\u30EC\u30D3\u30E5\u30FC\u306E\u5185\u5BB9\u3092\u8A9E\u308B\u53F0\u672C\u3092\u66F8\u304D\u307E\u3059\u3002
|
|
33261
|
+
|
|
33262
|
+
# \u30AD\u30E3\u30E9\u30AF\u30BF\u30FC
|
|
33263
|
+
- \u540D\u524D: ${c5.nameJa}
|
|
33264
|
+
- \u4EBA\u7269\u50CF: ${c5.persona}
|
|
33265
|
+
- \u53E3\u8ABF: ${c5.tone}
|
|
33266
|
+
- \u53E3\u8ABF\u306E\u4F8B:
|
|
33267
|
+
${c5.sampleLines.map((l3) => ` \u300C${l3}\u300D`).join("\n")}
|
|
33268
|
+
|
|
33269
|
+
# \u51FA\u529B\u5F62\u5F0F
|
|
33270
|
+
JSON \u914D\u5217\u306E\u307F\u3092\u51FA\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u524D\u7F6E\u304D\u30FB\u5F8C\u66F8\u304D\u30FB\u30B3\u30FC\u30C9\u30D5\u30A7\u30F3\u30B9\u3092\u66F8\u3044\u3066\u306F\u3044\u3051\u307E\u305B\u3093\u3002
|
|
33271
|
+
|
|
33272
|
+
\u5404\u8981\u7D20\u306E\u5F62\u5F0F:
|
|
33273
|
+
{
|
|
33274
|
+
"findingId": "\u5BFE\u8C61\u306E\u6307\u6458ID\uFF08\u30AA\u30FC\u30D7\u30CB\u30F3\u30B0\u3068\u30A8\u30F3\u30C7\u30A3\u30F3\u30B0\u306F\u7701\u7565\uFF09",
|
|
33275
|
+
"role": "opening" | "present" | "problem" | "improve" | "summary" | "ending",
|
|
33276
|
+
"text": "\u53F0\u8A5E",
|
|
33277
|
+
"emotion": ${EMOTIONS.map((e5) => `"${e5}"`).join(" | ")}
|
|
33278
|
+
}
|
|
33279
|
+
|
|
33280
|
+
# \u5B88\u308B\u3053\u3068
|
|
33281
|
+
1. **\u53F0\u8A5E\u306F\u5168\u89D2100\u6587\u5B57\u4EE5\u5185\u3002** 45\u301C80\u6587\u5B57\u304C\u6700\u3082\u8AAD\u307F\u3084\u3059\u3044\u3002\u6539\u884C\u306F \\n \u30671\u56DE\u307E\u3067\u3002
|
|
33282
|
+
2. \u4E0A\u8A18\u306E\u30AD\u30E3\u30E9\u30AF\u30BF\u30FC\u306E\u53E3\u8ABF\u3067\u66F8\u304F\u3002\u53E3\u8ABF\u306E\u4F8B\u306B\u5BC4\u305B\u308B\u3002
|
|
33283
|
+
3. **\u6280\u8853\u7684\u306A\u5185\u5BB9\u3092\u5909\u3048\u306A\u3044\u3002** \u6307\u6458\u306E\u610F\u5473\u306F\u5909\u3048\u305A\u3001\u8A00\u3044\u65B9\u3060\u3051\u3092\u30AD\u30E3\u30E9\u30AF\u30BF\u30FC\u306E\u3082\u306E\u306B\u3059\u308B\u3002
|
|
33284
|
+
4. emotion \u306F\u4E0A\u306B\u6319\u3052\u305F\u3082\u306E\u304B\u3089\u306E\u307F\u9078\u3076\u3002
|
|
33285
|
+
5. **\u53F0\u8A5E\u306B\u30D5\u30A1\u30A4\u30EB\u540D\u30FB\u884C\u756A\u53F7\u30FB\u8A18\u53F7\u3092\u66F8\u304B\u306A\u3044\u3002** \u97F3\u58F0\u3067\u8AAD\u307F\u4E0A\u3052\u308B\u305F\u3081\u3001
|
|
33286
|
+
\u300C4\u884C\u76EE\u306E db.query \u304C\u300D\u306E\u3088\u3046\u306A\u66F8\u304D\u65B9\u3092\u3059\u308B\u3068\u805E\u304D\u82E6\u3057\u304F\u306A\u308B\u3002\u4F4D\u7F6E\u306F\u753B\u9762\u304C\u793A\u3059\u3002
|
|
33287
|
+
6. confidence \u304C low \u306E\u6307\u6458\u306F\u3001\u65AD\u5B9A\u3092\u907F\u3051\u305F\u8A00\u3044\u56DE\u3057\u306B\u3059\u308B\u3002
|
|
33288
|
+
|
|
33289
|
+
# \u69CB\u6210
|
|
33290
|
+
- \u6700\u521D\u306B role="opening" \u30921\u3064\u3002\u5168\u4F53\u3067\u4F55\u4EF6\u898B\u3064\u304B\u3063\u305F\u304B\u3092\u4F1D\u3048\u308B\u3002
|
|
33291
|
+
- \u6307\u6458\u3054\u3068\u306B present \u2192 problem \u2192 improve \u2192 summary \u306E\u9806\u3067\u4E26\u3079\u308B\u3002
|
|
33292
|
+
- severity \u304C "praise" \u306E\u6307\u6458\u306F problem \u3092\u4F5C\u3089\u306A\u3044\u3002
|
|
33293
|
+
- improvedCode \u304C\u7121\u3044\u6307\u6458\u306F improve \u3092\u4F5C\u3089\u306A\u3044\u3002
|
|
33294
|
+
- \u6700\u5F8C\u306B role="ending" \u30921\u3064\u3002\u826F\u3044\u70B9\u306B\u89E6\u308C\u3066\u7D42\u3048\u308B\u3002
|
|
33295
|
+
|
|
33296
|
+
# \u8868\u60C5\u306E\u4F7F\u3044\u5206\u3051
|
|
33297
|
+
- normal: \u63D0\u793A\uFF08present\uFF09
|
|
33298
|
+
- serious: \u91CD\u5927\u306A\u6307\u6458\uFF08critical\uFF09
|
|
33299
|
+
- exasperated: \u96D1\u306A\u30B3\u30FC\u30C9\u3078\u306E\u6307\u6458
|
|
33300
|
+
- thinking: \u6539\u5584\u6848\u306E\u63D0\u793A\uFF08improve\uFF09
|
|
33301
|
+
- proud: \u307E\u3068\u3081\u30FB\u826F\u3044\u70B9\u30FB\u30A8\u30F3\u30C7\u30A3\u30F3\u30B0
|
|
33302
|
+
- flustered: \u7279\u306B\u91CD\u5927\u306A\u767A\u898B
|
|
33303
|
+
- sulking: \u4F7F\u7528\u983B\u5EA6\u306F\u4F4E\u3044`;
|
|
33304
|
+
}
|
|
33305
|
+
function scenarioUserPrompt(findings) {
|
|
33306
|
+
const counts = findings.reduce((acc, f5) => {
|
|
33307
|
+
acc[f5.severity] = (acc[f5.severity] ?? 0) + 1;
|
|
33308
|
+
return acc;
|
|
33309
|
+
}, {});
|
|
33310
|
+
const list2 = findings.map(
|
|
33311
|
+
(f5) => [
|
|
33312
|
+
`## ${f5.id}\uFF08${f5.severity} / ${f5.category} / \u78BA\u4FE1\u5EA6 ${f5.confidence}\uFF09`,
|
|
33313
|
+
`\u898B\u51FA\u3057: ${f5.title}`,
|
|
33314
|
+
`\u554F\u984C: ${f5.problem}`,
|
|
33315
|
+
f5.suggestion ? `\u6539\u5584: ${f5.suggestion}` : "",
|
|
33316
|
+
f5.improvedCode ? "\u6539\u5584\u5F8C\u306E\u30B3\u30FC\u30C9\u3042\u308A" : "\u6539\u5584\u5F8C\u306E\u30B3\u30FC\u30C9\u306A\u3057"
|
|
33317
|
+
].filter(Boolean).join("\n")
|
|
33318
|
+
).join("\n\n");
|
|
33319
|
+
return `\u6B21\u306E\u30EC\u30D3\u30E5\u30FC\u7D50\u679C\u3092\u53F0\u672C\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
33320
|
+
|
|
33321
|
+
\u5168\u4F53: ${findings.length}\u4EF6\uFF08${Object.entries(counts).map(([k5, v]) => `${k5} ${v}`).join(" / ")}\uFF09
|
|
33322
|
+
|
|
33323
|
+
${list2}`;
|
|
33324
|
+
}
|
|
33325
|
+
var FIX_SYSTEM = `\u3042\u306A\u305F\u306F\u7D4C\u9A13\u8C4A\u5BCC\u306A\u30BD\u30D5\u30C8\u30A6\u30A7\u30A2\u30A8\u30F3\u30B8\u30CB\u30A2\u3067\u3059\u3002
|
|
33326
|
+
\u4E0E\u3048\u3089\u308C\u305F 1 \u3064\u306E\u30D5\u30A1\u30A4\u30EB\u3068\u3001\u305D\u306E\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u30EC\u30D3\u30E5\u30FC\u6307\u6458\u3092\u53D7\u3051\u53D6\u308A\u3001\u6307\u6458\u3092\u76F4\u3057\u305F**\u30D5\u30A1\u30A4\u30EB\u5168\u4F53**\u3092\u8FD4\u3057\u307E\u3059\u3002
|
|
33327
|
+
|
|
33328
|
+
# \u51FA\u529B\u5F62\u5F0F
|
|
33329
|
+
1. \u6700\u521D\u306B\u3001\u76F4\u3057\u305F\u30D5\u30A1\u30A4\u30EB\u5168\u4F53\u3092 1 \u3064\u306E\u30B3\u30FC\u30C9\u30D6\u30ED\u30C3\u30AF\uFF08\`\`\` \u3067\u56F2\u3080\uFF09\u3067\u51FA\u529B\u3059\u308B\u3002\u7701\u7565\u30FB\u300C\u2026\u300D\u30FB\u300C\u4EE5\u4E0B\u540C\u3058\u300D\u306F\u7981\u6B62\u3002
|
|
33330
|
+
2. \u305D\u306E\u6B21\u306E\u884C\u306B\u3001\u76F4\u3057\u305F\u6307\u6458\u306E ID \u3092\u30AB\u30F3\u30DE\u533A\u5207\u308A\u3067\u300CFIXED: F-001,F-003\u300D\u306E\u5F62\u3067 1 \u884C\u3060\u3051\u66F8\u304F\u3002
|
|
33331
|
+
1 \u4EF6\u3082\u76F4\u305B\u306A\u3051\u308C\u3070\u300CFIXED: none\u300D\u3068\u66F8\u304F\u3002
|
|
33332
|
+
3. \u305D\u308C\u4EE5\u5916\u306E\u8AAC\u660E\u306F\u66F8\u304B\u306A\u3044\u3002
|
|
33333
|
+
|
|
33334
|
+
# \u5B88\u308B\u3053\u3068
|
|
33335
|
+
1. **\u6307\u6458\u306B\u95A2\u4FC2\u3059\u308B\u7B87\u6240\u3060\u3051\u3092\u76F4\u3059\u3002** \u95A2\u4FC2\u306E\u7121\u3044\u884C\u306E\u66F8\u304D\u65B9\u30FB\u30A4\u30F3\u30C7\u30F3\u30C8\u30FB\u30B3\u30E1\u30F3\u30C8\u30FB\u4E26\u3073\u9806\u3092\u5909\u3048\u306A\u3044\u3002
|
|
33336
|
+
2. \u5B58\u5728\u3057\u306A\u3044\u95A2\u6570\u30FB\u30E9\u30A4\u30D6\u30E9\u30EA\u3092\u4F7F\u308F\u306A\u3044\u3002\u65B0\u3057\u3044\u4F9D\u5B58\uFF08import / require\uFF09\u3092\u8DB3\u3055\u306A\u3044\u3002
|
|
33337
|
+
3. \u5909\u6570\u3092\u4E8C\u91CD\u306B\u5BA3\u8A00\u3057\u306A\u3044\u3002\u65E2\u306B\u3042\u308B\u5BA3\u8A00\u3092\u6D88\u3055\u306A\u3044\u3002
|
|
33338
|
+
4. \u76F4\u3059\u3068\u4ED6\u306E\u7B87\u6240\u304C\u58CA\u308C\u308B\u6307\u6458\u306F\u76F4\u3055\u305A\u3001FIXED \u306B\u542B\u3081\u306A\u3044\u3002
|
|
33339
|
+
5. \u5143\u306E\u30D5\u30A1\u30A4\u30EB\u306E\u30A4\u30F3\u30C7\u30F3\u30C8\uFF08\u30B9\u30DA\u30FC\u30B9\u304B\u30BF\u30D6\u304B\u30FB\u5E45\uFF09\u3068\u6539\u884C\u306E\u6D41\u5100\u306B\u5408\u308F\u305B\u308B\u3002`;
|
|
33340
|
+
function fixUserPrompt(file, findings) {
|
|
33341
|
+
const list2 = findings.map(
|
|
33342
|
+
(f5) => [
|
|
33343
|
+
`## ${f5.id}\uFF08${f5.severity}\uFF09${f5.startLine}\u301C${f5.endLine} \u884C\u76EE: ${f5.title}`,
|
|
33344
|
+
`\u554F\u984C: ${f5.problem}`,
|
|
33345
|
+
f5.suggestion ? `\u76F4\u3057\u65B9: ${f5.suggestion}` : "",
|
|
33346
|
+
// 参考として渡す。範囲ちょうどの差し替えとは限らない(CLI-07)
|
|
33347
|
+
f5.improvedCode ? `\u6539\u5584\u6848\uFF08\u53C2\u8003\uFF09:
|
|
33348
|
+
${f5.improvedCode}` : ""
|
|
33349
|
+
].filter(Boolean).join("\n")
|
|
33350
|
+
).join("\n\n");
|
|
33351
|
+
return `\u6B21\u306E\u30D5\u30A1\u30A4\u30EB\u306E\u6307\u6458\u3092\u76F4\u3057\u3001\u30D5\u30A1\u30A4\u30EB\u5168\u4F53\u3092\u8FD4\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
33352
|
+
|
|
33353
|
+
# \u30D5\u30A1\u30A4\u30EB: ${file.relPath}\uFF08${file.language}\uFF09
|
|
33354
|
+
\`\`\`
|
|
33355
|
+
${file.content}
|
|
33356
|
+
\`\`\`
|
|
33357
|
+
|
|
33358
|
+
# \u6307\u6458
|
|
33359
|
+
${list2}`;
|
|
33360
|
+
}
|
|
33361
|
+
|
|
33222
33362
|
// src/fix/applyFixes.ts
|
|
33223
33363
|
var RANK = { critical: 3, warning: 2, info: 1, praise: 0 };
|
|
33224
33364
|
function atLeast(sev, min) {
|
|
33225
33365
|
return RANK[sev] >= RANK[min] && sev !== "praise";
|
|
33226
33366
|
}
|
|
33367
|
+
var MAX_LINES = 1500;
|
|
33227
33368
|
var isInt = (v) => typeof v === "number" && Number.isInteger(v) && v >= 1;
|
|
33228
33369
|
function check(f5) {
|
|
33229
33370
|
if (typeof f5.file !== "string" || !f5.file) return "file \u304C\u7121\u3044";
|
|
33230
33371
|
if (!isInt(f5.startLine) || !isInt(f5.endLine) || f5.endLine < f5.startLine) return "\u884C\u756A\u53F7\u304C\u4E0D\u6B63";
|
|
33231
|
-
if (typeof f5.
|
|
33232
|
-
return "\
|
|
33372
|
+
if (typeof f5.title !== "string" || typeof f5.problem !== "string")
|
|
33373
|
+
return "\u898B\u51FA\u3057\u304B\u554F\u984C\u306E\u8AAC\u660E\u304C\u7121\u3044";
|
|
33233
33374
|
if (!SEVERITIES.includes(f5.severity)) return "\u91CD\u8981\u5EA6\u304C\u4E0D\u6B63";
|
|
33234
33375
|
return null;
|
|
33235
33376
|
}
|
|
@@ -33240,19 +33381,58 @@ function safeJoin(root5, rel) {
|
|
|
33240
33381
|
if (!r5 || r5.startsWith("..") || isAbsolute(r5)) return null;
|
|
33241
33382
|
return abs;
|
|
33242
33383
|
}
|
|
33243
|
-
|
|
33244
|
-
|
|
33245
|
-
|
|
33246
|
-
|
|
33247
|
-
|
|
33384
|
+
function parseFixResponse(text) {
|
|
33385
|
+
const m3 = text.match(/```[^\n]*\n([\s\S]*?)\n?```/);
|
|
33386
|
+
if (!m3 || !m3[1].trim()) return null;
|
|
33387
|
+
const line = text.slice(m3.index + m3[0].length).match(/FIXED:\s*([^\n]*)/i);
|
|
33388
|
+
if (!line) return { code: m3[1], fixed: [] };
|
|
33389
|
+
const v = line[1].trim();
|
|
33390
|
+
if (/^none$/i.test(v)) return { code: m3[1], fixed: [] };
|
|
33391
|
+
return { code: m3[1], fixed: v.split(/[\s,、]+/).filter(Boolean) };
|
|
33392
|
+
}
|
|
33393
|
+
async function syntaxCheck(path, code) {
|
|
33394
|
+
const ext = extname(path).toLowerCase();
|
|
33395
|
+
if (ext === ".json") {
|
|
33396
|
+
try {
|
|
33397
|
+
JSON.parse(code);
|
|
33398
|
+
return null;
|
|
33399
|
+
} catch (e5) {
|
|
33400
|
+
return `JSON \u3068\u3057\u3066\u8AAD\u3081\u306A\u3044\uFF08${e5 instanceof Error ? e5.message : String(e5)}\uFF09`;
|
|
33401
|
+
}
|
|
33402
|
+
}
|
|
33403
|
+
if (![".js", ".mjs", ".cjs"].includes(ext)) return "unchecked";
|
|
33404
|
+
const dir = await fs2.mkdtemp(join2(tmpdir(), "cdbg-fix-"));
|
|
33405
|
+
const tmp = join2(dir, `check${ext}`);
|
|
33406
|
+
try {
|
|
33407
|
+
await fs2.writeFile(tmp, code, "utf8");
|
|
33408
|
+
const err = await new Promise((done) => {
|
|
33409
|
+
const child = spawn2(process.execPath, ["--check", tmp], {
|
|
33410
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
33411
|
+
// Electron の Node で動いているときも、素の Node として振る舞わせる
|
|
33412
|
+
env: { ...process.env, ELECTRON_RUN_AS_NODE: "1" }
|
|
33413
|
+
});
|
|
33414
|
+
let stderr = "";
|
|
33415
|
+
child.stderr.on("data", (d5) => stderr += d5.toString());
|
|
33416
|
+
child.on("error", (e5) => done(e5.message));
|
|
33417
|
+
child.on("close", (c5) => done(c5 === 0 ? "" : stderr));
|
|
33418
|
+
});
|
|
33419
|
+
if (!err) return null;
|
|
33420
|
+
const first = err.split("\n").find((l3) => /Error/.test(l3)) ?? err.split("\n")[0];
|
|
33421
|
+
return `\u69CB\u6587\u30A8\u30E9\u30FC\uFF08${first.trim()}\uFF09`;
|
|
33422
|
+
} finally {
|
|
33423
|
+
await fs2.rm(dir, { recursive: true, force: true });
|
|
33248
33424
|
}
|
|
33249
|
-
return lines;
|
|
33250
33425
|
}
|
|
33251
|
-
async function applyFixes(root5, findings, opts
|
|
33426
|
+
async function applyFixes(root5, findings, opts) {
|
|
33252
33427
|
const min = opts.minSeverity ?? "warning";
|
|
33253
33428
|
const applied = [];
|
|
33254
33429
|
const skipped = [];
|
|
33255
|
-
const
|
|
33430
|
+
const unchecked = [];
|
|
33431
|
+
const skipAll = (list2, reason) => {
|
|
33432
|
+
for (const f5 of list2) {
|
|
33433
|
+
skipped.push({ findingId: String(f5.id ?? "?"), file: String(f5.file ?? "?"), reason });
|
|
33434
|
+
}
|
|
33435
|
+
};
|
|
33256
33436
|
const byFile = /* @__PURE__ */ new Map();
|
|
33257
33437
|
for (const f5 of findings) {
|
|
33258
33438
|
if (SEVERITIES.includes(f5.severity) && !atLeast(f5.severity, min)) {
|
|
@@ -33260,54 +33440,90 @@ async function applyFixes(root5, findings, opts = {}) {
|
|
|
33260
33440
|
}
|
|
33261
33441
|
const bad = check(f5);
|
|
33262
33442
|
if (bad) {
|
|
33263
|
-
|
|
33443
|
+
skipAll([f5], bad);
|
|
33264
33444
|
continue;
|
|
33265
33445
|
}
|
|
33266
33446
|
const ok = f5;
|
|
33267
|
-
|
|
33268
|
-
list2.push(ok);
|
|
33269
|
-
byFile.set(ok.file, list2);
|
|
33447
|
+
byFile.set(ok.file, [...byFile.get(ok.file) ?? [], ok]);
|
|
33270
33448
|
}
|
|
33271
33449
|
for (const [file, list2] of byFile) {
|
|
33272
33450
|
const abs = safeJoin(root5, file);
|
|
33273
33451
|
if (!abs) {
|
|
33274
|
-
|
|
33452
|
+
skipAll(list2, "\u5BFE\u8C61\u30D5\u30A9\u30EB\u30C0\u306E\u5916\u3092\u6307\u3057\u3066\u3044\u308B");
|
|
33275
33453
|
continue;
|
|
33276
33454
|
}
|
|
33277
33455
|
let text;
|
|
33278
33456
|
try {
|
|
33279
33457
|
text = await fs2.readFile(abs, "utf8");
|
|
33280
33458
|
} catch {
|
|
33281
|
-
|
|
33459
|
+
skipAll(list2, "\u30D5\u30A1\u30A4\u30EB\u3092\u8AAD\u3081\u306A\u3044");
|
|
33282
33460
|
continue;
|
|
33283
33461
|
}
|
|
33284
33462
|
const eol = text.includes("\r\n") ? "\r\n" : "\n";
|
|
33285
33463
|
const endsWithNewline = text.endsWith("\n");
|
|
33286
|
-
const
|
|
33287
|
-
const
|
|
33288
|
-
|
|
33289
|
-
(
|
|
33464
|
+
const original = text.replace(/\r\n/g, "\n");
|
|
33465
|
+
const lineCount = original.replace(/\n$/, "").split("\n").length;
|
|
33466
|
+
if (lineCount > MAX_LINES) {
|
|
33467
|
+
skipAll(list2, `\u30D5\u30A1\u30A4\u30EB\u304C\u9577\u3059\u304E\u308B\uFF08${lineCount} \u884C\u3002\u4E0A\u9650 ${MAX_LINES}\uFF09`);
|
|
33468
|
+
continue;
|
|
33469
|
+
}
|
|
33470
|
+
const outOfRange = list2.filter((f5) => f5.endLine > lineCount);
|
|
33471
|
+
if (outOfRange.length > 0)
|
|
33472
|
+
skipAll(outOfRange, `\u884C\u7BC4\u56F2\u304C\u30D5\u30A1\u30A4\u30EB\u306E\u5916\uFF08${lineCount} \u884C\u3057\u304B\u306A\u3044\uFF09`);
|
|
33473
|
+
const targets = list2.filter((f5) => f5.endLine <= lineCount);
|
|
33474
|
+
if (targets.length === 0) continue;
|
|
33475
|
+
let res;
|
|
33476
|
+
try {
|
|
33477
|
+
res = await opts.ai.complete(
|
|
33478
|
+
{
|
|
33479
|
+
purpose: "fix",
|
|
33480
|
+
system: FIX_SYSTEM,
|
|
33481
|
+
user: fixUserPrompt(
|
|
33482
|
+
{ relPath: file, language: languageOf(file), content: original },
|
|
33483
|
+
targets
|
|
33484
|
+
)
|
|
33485
|
+
},
|
|
33486
|
+
opts.signal
|
|
33487
|
+
);
|
|
33488
|
+
} catch (e5) {
|
|
33489
|
+
if (opts.signal?.aborted) throw e5;
|
|
33490
|
+
skipAll(targets, `AI \u306E\u547C\u3073\u51FA\u3057\u306B\u5931\u6557\u3057\u305F\uFF08${e5 instanceof Error ? e5.message : String(e5)}\uFF09`);
|
|
33491
|
+
continue;
|
|
33492
|
+
}
|
|
33493
|
+
const parsed = parseFixResponse(res.text);
|
|
33494
|
+
if (!parsed) {
|
|
33495
|
+
skipAll(targets, "AI \u306E\u5FDC\u7B54\u306B\u30B3\u30FC\u30C9\u304C\u7121\u304B\u3063\u305F");
|
|
33496
|
+
continue;
|
|
33497
|
+
}
|
|
33498
|
+
let code = parsed.code.replace(/\r\n/g, "\n").replace(/\n+$/, "");
|
|
33499
|
+
const newCount = code.split("\n").length;
|
|
33500
|
+
if (newCount < Math.max(1, Math.floor(lineCount * 0.5))) {
|
|
33501
|
+
skipAll(targets, `AI \u306E\u5FDC\u7B54\u304C\u5143\u3088\u308A\u6975\u7AEF\u306B\u77ED\u3044\uFF08${lineCount} \u884C \u2192 ${newCount} \u884C\uFF09`);
|
|
33502
|
+
continue;
|
|
33503
|
+
}
|
|
33504
|
+
if (code === original.replace(/\n+$/, "")) {
|
|
33505
|
+
skipAll(targets, "AI \u304C\u4F55\u3082\u5909\u3048\u306A\u304B\u3063\u305F");
|
|
33506
|
+
continue;
|
|
33507
|
+
}
|
|
33508
|
+
code = code.split("\n").join(eol) + (endsWithNewline ? eol : "");
|
|
33509
|
+
const syntax = await syntaxCheck(abs, code);
|
|
33510
|
+
if (syntax !== null && syntax !== "unchecked") {
|
|
33511
|
+
skipAll(targets, `\u76F4\u3057\u305F\u30B3\u30FC\u30C9\u304C${syntax}`);
|
|
33512
|
+
continue;
|
|
33513
|
+
}
|
|
33514
|
+
const fixedIds = new Set(parsed.fixed);
|
|
33515
|
+
const done = targets.filter((f5) => fixedIds.has(f5.id));
|
|
33516
|
+
if (done.length === 0) {
|
|
33517
|
+
skipAll(targets, "AI \u304C\u76F4\u3057\u305F\u6307\u6458\u3092\u7533\u544A\u3057\u306A\u304B\u3063\u305F\uFF08FIXED \u884C\u304C\u7121\u3044\u30FBnone\uFF09");
|
|
33518
|
+
continue;
|
|
33519
|
+
}
|
|
33520
|
+
skipAll(
|
|
33521
|
+
targets.filter((f5) => !fixedIds.has(f5.id)),
|
|
33522
|
+
"AI \u304C\u76F4\u3055\u306A\u304B\u3063\u305F\uFF08\u76F4\u3059\u3068\u4ED6\u304C\u58CA\u308C\u308B\u7B49\uFF09"
|
|
33290
33523
|
);
|
|
33291
|
-
|
|
33292
|
-
|
|
33293
|
-
|
|
33294
|
-
skip(f5, `\u884C\u7BC4\u56F2\u304C\u30D5\u30A1\u30A4\u30EB\u306E\u5916\uFF08${lines.length} \u884C\u3057\u304B\u306A\u3044\uFF09`);
|
|
33295
|
-
continue;
|
|
33296
|
-
}
|
|
33297
|
-
if (done.some((d5) => f5.startLine <= d5.end && d5.start <= f5.endLine)) {
|
|
33298
|
-
skip(f5, "\u4ED6\u306E\u4FEE\u6B63\u3068\u7BC4\u56F2\u304C\u91CD\u306A\u308B");
|
|
33299
|
-
continue;
|
|
33300
|
-
}
|
|
33301
|
-
const original = lines.slice(f5.startLine - 1, f5.endLine);
|
|
33302
|
-
if (f5.highlightText) {
|
|
33303
|
-
const squash = (s2) => s2.replace(/\s+/g, "");
|
|
33304
|
-
if (!squash(original.join("\n")).includes(squash(f5.highlightText))) {
|
|
33305
|
-
skip(f5, "\u30EC\u30D3\u30E5\u30FC\u5F8C\u306B\u30B3\u30FC\u30C9\u304C\u5909\u308F\u3063\u3066\u3044\u308B\uFF08\u6307\u6458\u7B87\u6240\u304C\u898B\u3064\u304B\u3089\u306A\u3044\uFF09");
|
|
33306
|
-
continue;
|
|
33307
|
-
}
|
|
33308
|
-
}
|
|
33309
|
-
lines.splice(f5.startLine - 1, original.length, ...replacementLines(original, f5.improvedCode));
|
|
33310
|
-
done.push({ start: f5.startLine, end: f5.endLine });
|
|
33524
|
+
if (!opts.dryRun) await fs2.writeFile(abs, code, "utf8");
|
|
33525
|
+
if (syntax === "unchecked") unchecked.push(file);
|
|
33526
|
+
for (const f5 of done) {
|
|
33311
33527
|
applied.push({
|
|
33312
33528
|
findingId: f5.id,
|
|
33313
33529
|
severity: f5.severity,
|
|
@@ -33316,13 +33532,9 @@ async function applyFixes(root5, findings, opts = {}) {
|
|
|
33316
33532
|
startLine: f5.startLine,
|
|
33317
33533
|
endLine: f5.endLine
|
|
33318
33534
|
});
|
|
33319
|
-
changed = true;
|
|
33320
|
-
}
|
|
33321
|
-
if (changed && !opts.dryRun) {
|
|
33322
|
-
await fs2.writeFile(abs, lines.join(eol) + (endsWithNewline ? eol : ""), "utf8");
|
|
33323
33535
|
}
|
|
33324
33536
|
}
|
|
33325
|
-
return { applied, skipped };
|
|
33537
|
+
return { applied, skipped, unchecked };
|
|
33326
33538
|
}
|
|
33327
33539
|
function pullRequestBody(result, findings, roxy = {}) {
|
|
33328
33540
|
const byId = new Map(findings.map((f5) => [f5.id, f5]));
|
|
@@ -33336,6 +33548,16 @@ function pullRequestBody(result, findings, roxy = {}) {
|
|
|
33336
33548
|
if (f5?.suggestion) out.push(`- \u76F4\u3057\u65B9: ${f5.suggestion}`);
|
|
33337
33549
|
out.push("");
|
|
33338
33550
|
}
|
|
33551
|
+
if (result.unchecked.length > 0) {
|
|
33552
|
+
out.push(
|
|
33553
|
+
"## \u26A0 \u69CB\u6587\u691C\u67FB\u3092\u3057\u3066\u3044\u306A\u3044\u30D5\u30A1\u30A4\u30EB",
|
|
33554
|
+
"",
|
|
33555
|
+
...result.unchecked.map(
|
|
33556
|
+
(f5) => `- \`${f5}\`\uFF08\u3053\u306E\u8A00\u8A9E\u306E\u691C\u67FB\u624B\u6BB5\u304C\u7121\u3044\u3002\u7279\u306B\u5FF5\u5165\u308A\u306B\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\uFF09`
|
|
33557
|
+
),
|
|
33558
|
+
""
|
|
33559
|
+
);
|
|
33560
|
+
}
|
|
33339
33561
|
if (result.skipped.length > 0) {
|
|
33340
33562
|
out.push(`## \u76F4\u305B\u306A\u304B\u3063\u305F\u6307\u6458\uFF08${result.skipped.length} \u4EF6\u30FB\u624B\u3067\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\uFF09`, "");
|
|
33341
33563
|
for (const s2 of result.skipped) {
|
|
@@ -33347,7 +33569,7 @@ function pullRequestBody(result, findings, roxy = {}) {
|
|
|
33347
33569
|
if (roxy.ending) out.push(`> \u30ED\u30AD\u30B7\u30FC\u300C${roxy.ending}\u300D`, "");
|
|
33348
33570
|
out.push(
|
|
33349
33571
|
"---",
|
|
33350
|
-
"*\u3053\u306E\u4FEE\u6B63\u306F candy-debug\uFF08\u30ED\u30AD\u30B7\u30FC\u30D1\u30A4\u30D7\u30E9\u30A4\u30F3\uFF09\u304C\
|
|
33572
|
+
"*\u3053\u306E\u4FEE\u6B63\u306F candy-debug\uFF08\u30ED\u30AD\u30B7\u30FC\u30D1\u30A4\u30D7\u30E9\u30A4\u30F3\uFF09\u304C AI \u306B\u66F8\u304D\u76F4\u3055\u305B\u305F\u3082\u306E\u3067\u3059\u3002\u69CB\u6587\u691C\u67FB\u306F\u901A\u3063\u3066\u3044\u307E\u3059\u304C\u3001\u52D5\u4F5C\u306F\u78BA\u304B\u3081\u3066\u3044\u307E\u305B\u3093\u3002\u5FC5\u305A\u4E2D\u8EAB\u3092\u78BA\u8A8D\u3057\u3066\u304B\u3089\u30DE\u30FC\u30B8\u3057\u3066\u304F\u3060\u3055\u3044\u3002*"
|
|
33351
33573
|
);
|
|
33352
33574
|
const body = out.join("\n");
|
|
33353
33575
|
return body.length > 1e4 ? body.slice(0, 9990) + "\n\u2026\uFF08\u7701\u7565\uFF09" : body;
|
|
@@ -33383,108 +33605,6 @@ function extractJson(text) {
|
|
|
33383
33605
|
return null;
|
|
33384
33606
|
}
|
|
33385
33607
|
|
|
33386
|
-
// src/review/prompts.ts
|
|
33387
|
-
var REVIEW_SYSTEM = `\u3042\u306A\u305F\u306F\u7D4C\u9A13\u8C4A\u5BCC\u306A\u30B3\u30FC\u30C9\u30EC\u30D3\u30E5\u30A2\u30FC\u3067\u3059\u3002\u65E5\u672C\u8A9E\u3067\u56DE\u7B54\u3057\u307E\u3059\u3002
|
|
33388
|
-
|
|
33389
|
-
# \u51FA\u529B\u5F62\u5F0F
|
|
33390
|
-
JSON \u914D\u5217\u306E\u307F\u3092\u51FA\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u524D\u7F6E\u304D\u30FB\u5F8C\u66F8\u304D\u30FB\u30DE\u30FC\u30AF\u30C0\u30A6\u30F3\u306E\u30B3\u30FC\u30C9\u30D5\u30A7\u30F3\u30B9\u3092\u66F8\u3044\u3066\u306F\u3044\u3051\u307E\u305B\u3093\u3002
|
|
33391
|
-
|
|
33392
|
-
\u5404\u8981\u7D20\u306E\u5F62\u5F0F:
|
|
33393
|
-
{
|
|
33394
|
-
"severity": "critical" | "warning" | "info" | "praise",
|
|
33395
|
-
"category": "\u30D0\u30B0" | "\u5B89\u5168\u6027" | "\u53EF\u8AAD\u6027" | "\u8A2D\u8A08" | "\u6027\u80FD" | "\u898F\u7D04" \u306E\u3044\u305A\u308C\u304B,
|
|
33396
|
-
"title": "\u4E00\u884C\u8981\u7D04\uFF0840\u5B57\u4EE5\u5185\uFF09",
|
|
33397
|
-
"file": "\u5165\u529B\u3067\u4E0E\u3048\u3089\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u30D1\u30B9\u3068\u5B8C\u5168\u306B\u4E00\u81F4\u3059\u308B\u6587\u5B57\u5217",
|
|
33398
|
-
"startLine": \u6307\u6458\u5BFE\u8C61\u306E\u958B\u59CB\u884C\u756A\u53F7\uFF08\u5165\u529B\u306B\u4ED8\u3044\u3066\u3044\u308B\u884C\u756A\u53F7\u3092\u305D\u306E\u307E\u307E\u4F7F\u3046\uFF09,
|
|
33399
|
-
"endLine": \u6307\u6458\u5BFE\u8C61\u306E\u7D42\u4E86\u884C\u756A\u53F7,
|
|
33400
|
-
"highlightText": "\u305D\u306E\u884C\u306B\u5B9F\u5728\u3059\u308B\u90E8\u5206\u6587\u5B57\u5217\u3002\u67A0\u3067\u56F2\u3093\u3067\u793A\u3059\u306E\u306B\u4F7F\u3046",
|
|
33401
|
-
"problem": "\u4F55\u304C\u554F\u984C\u304B\u30022\u301C3\u6587",
|
|
33402
|
-
"suggestion": "\u3069\u3046\u76F4\u3059\u304B\u30022\u301C3\u6587",
|
|
33403
|
-
"improvedCode": "\u6539\u5584\u5F8C\u306E\u30B3\u30FC\u30C9\uFF08startLine\u301CendLine \u306E\u7BC4\u56F2\u3076\u3093\u3060\u3051\uFF09\u3002\u7121\u3051\u308C\u3070\u7701\u7565",
|
|
33404
|
-
"confidence": "high" | "medium" | "low"
|
|
33405
|
-
}
|
|
33406
|
-
|
|
33407
|
-
# \u5B88\u308B\u3053\u3068
|
|
33408
|
-
1. file \u306F\u5FC5\u305A\u5165\u529B\u3067\u4E0E\u3048\u305F\u30D5\u30A1\u30A4\u30EB\u30D1\u30B9\u306E\u3044\u305A\u308C\u304B\u3068\u5B8C\u5168\u4E00\u81F4\u3055\u305B\u308B\u3002\u63A8\u6E2C\u3067\u66F8\u304B\u306A\u3044\u3002
|
|
33409
|
-
2. startLine / endLine \u306F\u5165\u529B\u306B\u4ED8\u3044\u3066\u3044\u308B\u884C\u756A\u53F7\u3092\u305D\u306E\u307E\u307E\u4F7F\u3046\u3002\u6570\u3048\u76F4\u3055\u306A\u3044\u3002
|
|
33410
|
-
3. highlightText \u306F\u305D\u306E\u884C\u306B**\u5B9F\u5728\u3059\u308B\u6587\u5B57\u5217**\u306B\u3059\u308B\u3002\u5B58\u5728\u3057\u306A\u3044\u6587\u5B57\u5217\u3092\u66F8\u304B\u306A\u3044\u3002
|
|
33411
|
-
4. \u78BA\u4FE1\u304C\u6301\u3066\u306A\u3044\u3082\u306E\u306F confidence \u3092 "low" \u306B\u3059\u308B\u3002\u63A8\u6E2C\u3067\u65AD\u5B9A\u3057\u306A\u3044\u3002
|
|
33412
|
-
5. \u4E00\u822C\u8AD6\u3092\u66F8\u304B\u306A\u3044\u3002\u300C\u5909\u6570\u540D\u306F\u5206\u304B\u308A\u3084\u3059\u304F\u300D\u3067\u306F\u306A\u304F\u3001\u305D\u306E\u30B3\u30FC\u30C9\u306E\u5177\u4F53\u7684\u306A\u7B87\u6240\u3092\u6307\u3059\u3002
|
|
33413
|
-
6. **\u826F\u3044\u70B9\uFF08severity: "praise"\uFF09\u3092\u5FC5\u305A1\u4EF6\u4EE5\u4E0A\u542B\u3081\u308B\u3002**
|
|
33414
|
-
7. \u30AD\u30E3\u30E9\u30AF\u30BF\u30FC\u3092\u6F14\u3058\u306A\u3044\u3002\u3053\u3053\u3067\u306F\u4E8B\u5B9F\u3060\u3051\u3092\u3001\u7D20\u306E\u65E5\u672C\u8A9E\u3067\u66F8\u304F\u3002`;
|
|
33415
|
-
function reviewUserPrompt(formattedFiles, maxFindings) {
|
|
33416
|
-
return `\u6B21\u306E\u30B3\u30FC\u30C9\u3092\u30EC\u30D3\u30E5\u30FC\u3057\u3001\u6307\u6458\u3092\u6700\u5927 ${maxFindings} \u4EF6\u3001JSON \u914D\u5217\u3067\u51FA\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
33417
|
-
\u91CD\u8981\u306A\u3082\u306E\u3092\u512A\u5148\u3057\u3001\u4E9B\u7D30\u306A\u3082\u306E\u306F\u7701\u3044\u3066\u304F\u3060\u3055\u3044\u3002
|
|
33418
|
-
|
|
33419
|
-
${formattedFiles}`;
|
|
33420
|
-
}
|
|
33421
|
-
function scenarioSystem(c5) {
|
|
33422
|
-
return `\u3042\u306A\u305F\u306F\u300C${c5.nameJa}\u300D\u3068\u3044\u3046\u30AD\u30E3\u30E9\u30AF\u30BF\u30FC\u3068\u3057\u3066\u3001\u30B3\u30FC\u30C9\u30EC\u30D3\u30E5\u30FC\u306E\u5185\u5BB9\u3092\u8A9E\u308B\u53F0\u672C\u3092\u66F8\u304D\u307E\u3059\u3002
|
|
33423
|
-
|
|
33424
|
-
# \u30AD\u30E3\u30E9\u30AF\u30BF\u30FC
|
|
33425
|
-
- \u540D\u524D: ${c5.nameJa}
|
|
33426
|
-
- \u4EBA\u7269\u50CF: ${c5.persona}
|
|
33427
|
-
- \u53E3\u8ABF: ${c5.tone}
|
|
33428
|
-
- \u53E3\u8ABF\u306E\u4F8B:
|
|
33429
|
-
${c5.sampleLines.map((l3) => ` \u300C${l3}\u300D`).join("\n")}
|
|
33430
|
-
|
|
33431
|
-
# \u51FA\u529B\u5F62\u5F0F
|
|
33432
|
-
JSON \u914D\u5217\u306E\u307F\u3092\u51FA\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u524D\u7F6E\u304D\u30FB\u5F8C\u66F8\u304D\u30FB\u30B3\u30FC\u30C9\u30D5\u30A7\u30F3\u30B9\u3092\u66F8\u3044\u3066\u306F\u3044\u3051\u307E\u305B\u3093\u3002
|
|
33433
|
-
|
|
33434
|
-
\u5404\u8981\u7D20\u306E\u5F62\u5F0F:
|
|
33435
|
-
{
|
|
33436
|
-
"findingId": "\u5BFE\u8C61\u306E\u6307\u6458ID\uFF08\u30AA\u30FC\u30D7\u30CB\u30F3\u30B0\u3068\u30A8\u30F3\u30C7\u30A3\u30F3\u30B0\u306F\u7701\u7565\uFF09",
|
|
33437
|
-
"role": "opening" | "present" | "problem" | "improve" | "summary" | "ending",
|
|
33438
|
-
"text": "\u53F0\u8A5E",
|
|
33439
|
-
"emotion": ${EMOTIONS.map((e5) => `"${e5}"`).join(" | ")}
|
|
33440
|
-
}
|
|
33441
|
-
|
|
33442
|
-
# \u5B88\u308B\u3053\u3068
|
|
33443
|
-
1. **\u53F0\u8A5E\u306F\u5168\u89D2100\u6587\u5B57\u4EE5\u5185\u3002** 45\u301C80\u6587\u5B57\u304C\u6700\u3082\u8AAD\u307F\u3084\u3059\u3044\u3002\u6539\u884C\u306F \\n \u30671\u56DE\u307E\u3067\u3002
|
|
33444
|
-
2. \u4E0A\u8A18\u306E\u30AD\u30E3\u30E9\u30AF\u30BF\u30FC\u306E\u53E3\u8ABF\u3067\u66F8\u304F\u3002\u53E3\u8ABF\u306E\u4F8B\u306B\u5BC4\u305B\u308B\u3002
|
|
33445
|
-
3. **\u6280\u8853\u7684\u306A\u5185\u5BB9\u3092\u5909\u3048\u306A\u3044\u3002** \u6307\u6458\u306E\u610F\u5473\u306F\u5909\u3048\u305A\u3001\u8A00\u3044\u65B9\u3060\u3051\u3092\u30AD\u30E3\u30E9\u30AF\u30BF\u30FC\u306E\u3082\u306E\u306B\u3059\u308B\u3002
|
|
33446
|
-
4. emotion \u306F\u4E0A\u306B\u6319\u3052\u305F\u3082\u306E\u304B\u3089\u306E\u307F\u9078\u3076\u3002
|
|
33447
|
-
5. **\u53F0\u8A5E\u306B\u30D5\u30A1\u30A4\u30EB\u540D\u30FB\u884C\u756A\u53F7\u30FB\u8A18\u53F7\u3092\u66F8\u304B\u306A\u3044\u3002** \u97F3\u58F0\u3067\u8AAD\u307F\u4E0A\u3052\u308B\u305F\u3081\u3001
|
|
33448
|
-
\u300C4\u884C\u76EE\u306E db.query \u304C\u300D\u306E\u3088\u3046\u306A\u66F8\u304D\u65B9\u3092\u3059\u308B\u3068\u805E\u304D\u82E6\u3057\u304F\u306A\u308B\u3002\u4F4D\u7F6E\u306F\u753B\u9762\u304C\u793A\u3059\u3002
|
|
33449
|
-
6. confidence \u304C low \u306E\u6307\u6458\u306F\u3001\u65AD\u5B9A\u3092\u907F\u3051\u305F\u8A00\u3044\u56DE\u3057\u306B\u3059\u308B\u3002
|
|
33450
|
-
|
|
33451
|
-
# \u69CB\u6210
|
|
33452
|
-
- \u6700\u521D\u306B role="opening" \u30921\u3064\u3002\u5168\u4F53\u3067\u4F55\u4EF6\u898B\u3064\u304B\u3063\u305F\u304B\u3092\u4F1D\u3048\u308B\u3002
|
|
33453
|
-
- \u6307\u6458\u3054\u3068\u306B present \u2192 problem \u2192 improve \u2192 summary \u306E\u9806\u3067\u4E26\u3079\u308B\u3002
|
|
33454
|
-
- severity \u304C "praise" \u306E\u6307\u6458\u306F problem \u3092\u4F5C\u3089\u306A\u3044\u3002
|
|
33455
|
-
- improvedCode \u304C\u7121\u3044\u6307\u6458\u306F improve \u3092\u4F5C\u3089\u306A\u3044\u3002
|
|
33456
|
-
- \u6700\u5F8C\u306B role="ending" \u30921\u3064\u3002\u826F\u3044\u70B9\u306B\u89E6\u308C\u3066\u7D42\u3048\u308B\u3002
|
|
33457
|
-
|
|
33458
|
-
# \u8868\u60C5\u306E\u4F7F\u3044\u5206\u3051
|
|
33459
|
-
- normal: \u63D0\u793A\uFF08present\uFF09
|
|
33460
|
-
- serious: \u91CD\u5927\u306A\u6307\u6458\uFF08critical\uFF09
|
|
33461
|
-
- exasperated: \u96D1\u306A\u30B3\u30FC\u30C9\u3078\u306E\u6307\u6458
|
|
33462
|
-
- thinking: \u6539\u5584\u6848\u306E\u63D0\u793A\uFF08improve\uFF09
|
|
33463
|
-
- proud: \u307E\u3068\u3081\u30FB\u826F\u3044\u70B9\u30FB\u30A8\u30F3\u30C7\u30A3\u30F3\u30B0
|
|
33464
|
-
- flustered: \u7279\u306B\u91CD\u5927\u306A\u767A\u898B
|
|
33465
|
-
- sulking: \u4F7F\u7528\u983B\u5EA6\u306F\u4F4E\u3044`;
|
|
33466
|
-
}
|
|
33467
|
-
function scenarioUserPrompt(findings) {
|
|
33468
|
-
const counts = findings.reduce((acc, f5) => {
|
|
33469
|
-
acc[f5.severity] = (acc[f5.severity] ?? 0) + 1;
|
|
33470
|
-
return acc;
|
|
33471
|
-
}, {});
|
|
33472
|
-
const list2 = findings.map(
|
|
33473
|
-
(f5) => [
|
|
33474
|
-
`## ${f5.id}\uFF08${f5.severity} / ${f5.category} / \u78BA\u4FE1\u5EA6 ${f5.confidence}\uFF09`,
|
|
33475
|
-
`\u898B\u51FA\u3057: ${f5.title}`,
|
|
33476
|
-
`\u554F\u984C: ${f5.problem}`,
|
|
33477
|
-
f5.suggestion ? `\u6539\u5584: ${f5.suggestion}` : "",
|
|
33478
|
-
f5.improvedCode ? "\u6539\u5584\u5F8C\u306E\u30B3\u30FC\u30C9\u3042\u308A" : "\u6539\u5584\u5F8C\u306E\u30B3\u30FC\u30C9\u306A\u3057"
|
|
33479
|
-
].filter(Boolean).join("\n")
|
|
33480
|
-
).join("\n\n");
|
|
33481
|
-
return `\u6B21\u306E\u30EC\u30D3\u30E5\u30FC\u7D50\u679C\u3092\u53F0\u672C\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
33482
|
-
|
|
33483
|
-
\u5168\u4F53: ${findings.length}\u4EF6\uFF08${Object.entries(counts).map(([k5, v]) => `${k5} ${v}`).join(" / ")}\uFF09
|
|
33484
|
-
|
|
33485
|
-
${list2}`;
|
|
33486
|
-
}
|
|
33487
|
-
|
|
33488
33608
|
// src/review/pipeline.ts
|
|
33489
33609
|
var SNIPPET_PAD = 2;
|
|
33490
33610
|
var SNIPPET_MAX_LINES = 12;
|
|
@@ -33709,7 +33829,7 @@ var HELP = `candy-debug ${package_default.version}
|
|
|
33709
33829
|
|
|
33710
33830
|
\u4F7F\u3044\u65B9:
|
|
33711
33831
|
candy-debug <\u5BFE\u8C61\u30D5\u30A9\u30EB\u30C0> [\u30AA\u30D7\u30B7\u30E7\u30F3] \u30EC\u30D3\u30E5\u30FC\u3057\u3066 JSON \u3092\u51FA\u3059
|
|
33712
|
-
candy-debug fix <review.json> [\u30AA\u30D7\u30B7\u30E7\u30F3]
|
|
33832
|
+
candy-debug fix <review.json> [\u30AA\u30D7\u30B7\u30E7\u30F3] \u6307\u6458\u3092 AI \u306B\u76F4\u3055\u305B\u3001\u5BFE\u8C61\u30D5\u30A9\u30EB\u30C0\u3078\u66F8\u304D\u8FBC\u3080
|
|
33713
33833
|
cdbg ... \u77ED\u7E2E\u540D\u3002\u4E2D\u8EAB\u306F\u540C\u3058
|
|
33714
33834
|
|
|
33715
33835
|
\u30EC\u30D3\u30E5\u30FC\u306E\u30AA\u30D7\u30B7\u30E7\u30F3:
|
|
@@ -33726,11 +33846,11 @@ var HELP = `candy-debug ${package_default.version}
|
|
|
33726
33846
|
--scan-only AI \u3092\u547C\u3070\u305A\u3001\u5BFE\u8C61\u30D5\u30A1\u30A4\u30EB\u306E\u4E00\u89A7\u3068\u7D71\u8A08\u3060\u3051\u3092 JSON \u3067\u51FA\u3059
|
|
33727
33847
|
--doctor AI \u3092\u547C\u3079\u308B\u304B\u3092\u78BA\u304B\u3081\u308B\uFF08--json \u3067\u7D50\u679C\u3092 JSON \u306B\uFF09
|
|
33728
33848
|
|
|
33729
|
-
fix \u306E\u30AA\u30D7\u30B7\u30E7\u30F3:
|
|
33730
|
-
--dir <folder> \
|
|
33849
|
+
fix \u306E\u30AA\u30D7\u30B7\u30E7\u30F3\uFF08--provider / --model / --region \u3082\u30EC\u30D3\u30E5\u30FC\u3068\u540C\u3058\u304F\u4F7F\u3048\u308B\uFF09:
|
|
33850
|
+
--dir <folder> \u76F4\u3059\u30D5\u30A9\u30EB\u30C0\uFF08\u65E2\u5B9A \u30AB\u30EC\u30F3\u30C8\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\uFF09
|
|
33731
33851
|
--min-severity <sev> \u3053\u306E\u91CD\u8981\u5EA6\u4EE5\u4E0A\u3060\u3051\u76F4\u3059\uFF08\u65E2\u5B9A warning\uFF09
|
|
33732
33852
|
--summary <file> \u30D7\u30EB\u30EA\u30AF\u30A8\u30B9\u30C8\u7528\u306E\u672C\u6587\uFF08Markdown\uFF09\u3092\u66F8\u304D\u51FA\u3059
|
|
33733
|
-
--dry-run \u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304D\u63DB\u3048\u305A\u3001\
|
|
33853
|
+
--dry-run \u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304D\u63DB\u3048\u305A\u3001\u76F4\u305B\u308B\u304B\u3060\u3051\u3092\u78BA\u304B\u3081\u308B\uFF08AI \u306F\u547C\u3076\uFF09
|
|
33734
33854
|
|
|
33735
33855
|
-v, --version \u7248\u6570\u3092\u8868\u793A
|
|
33736
33856
|
-h, --help \u3053\u306E\u8AAC\u660E\u3092\u8868\u793A
|
|
@@ -33871,8 +33991,9 @@ async function makeProvider(opts) {
|
|
|
33871
33991
|
};
|
|
33872
33992
|
}
|
|
33873
33993
|
async function runFix(opts) {
|
|
33874
|
-
if (!opts.target)
|
|
33994
|
+
if (!opts.target) {
|
|
33875
33995
|
throw new UsageError("\u30EC\u30D3\u30E5\u30FC\u7D50\u679C\u306E JSON \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF08cdbg fix review.json\uFF09");
|
|
33996
|
+
}
|
|
33876
33997
|
let raw;
|
|
33877
33998
|
try {
|
|
33878
33999
|
raw = JSON.parse(await readFile3(resolve2(opts.target), "utf8"));
|
|
@@ -33883,11 +34004,35 @@ async function runFix(opts) {
|
|
|
33883
34004
|
if (!parsed.ok) throw new Error(parsed.error);
|
|
33884
34005
|
const file = parsed.file;
|
|
33885
34006
|
const dir = resolve2(opts.dir ?? ".");
|
|
34007
|
+
const { ai, destination } = await makeProvider(opts);
|
|
34008
|
+
if (opts.progress === "text") {
|
|
34009
|
+
process.stderr.write(`\u5BFE\u8C61: ${dir}
|
|
34010
|
+
\u6307\u6458\u306E\u3042\u308B\u30D5\u30A1\u30A4\u30EB\u3092 ${destination} \u3078\u9001\u3063\u3066\u76F4\u3055\u305B\u307E\u3059\u3002
|
|
34011
|
+
`);
|
|
34012
|
+
}
|
|
34013
|
+
const controller = new AbortController();
|
|
34014
|
+
const onSignal = () => controller.abort();
|
|
34015
|
+
process.once("SIGINT", onSignal);
|
|
34016
|
+
process.once("SIGTERM", onSignal);
|
|
33886
34017
|
const findings = file.findings;
|
|
33887
|
-
|
|
33888
|
-
|
|
33889
|
-
|
|
33890
|
-
|
|
34018
|
+
let result;
|
|
34019
|
+
try {
|
|
34020
|
+
result = await applyFixes(dir, findings, {
|
|
34021
|
+
ai,
|
|
34022
|
+
minSeverity: opts.minSeverity,
|
|
34023
|
+
dryRun: opts.dryRun,
|
|
34024
|
+
signal: controller.signal
|
|
34025
|
+
});
|
|
34026
|
+
} catch (e5) {
|
|
34027
|
+
if (controller.signal.aborted) {
|
|
34028
|
+
emit(opts.progress, { type: "error", message: "\u4E2D\u65AD\u3057\u307E\u3057\u305F" });
|
|
34029
|
+
return 130;
|
|
34030
|
+
}
|
|
34031
|
+
throw e5;
|
|
34032
|
+
} finally {
|
|
34033
|
+
process.off("SIGINT", onSignal);
|
|
34034
|
+
process.off("SIGTERM", onSignal);
|
|
34035
|
+
}
|
|
33891
34036
|
if (opts.summary) {
|
|
33892
34037
|
const beats = file.scenario.beats;
|
|
33893
34038
|
await writeOutput(
|
|
@@ -33899,13 +34044,16 @@ async function runFix(opts) {
|
|
|
33899
34044
|
);
|
|
33900
34045
|
}
|
|
33901
34046
|
if (opts.progress === "text") {
|
|
33902
|
-
const verb = opts.dryRun ? "\
|
|
34047
|
+
const verb = opts.dryRun ? "\u76F4\u305B\u308B" : "\u76F4\u3057\u305F";
|
|
33903
34048
|
process.stderr.write(
|
|
33904
|
-
`${
|
|
34049
|
+
`${verb}\u6307\u6458: ${result.applied.length} \u4EF6 / \u898B\u9001\u308A ${result.skipped.length} \u4EF6
|
|
33905
34050
|
`
|
|
33906
34051
|
);
|
|
33907
|
-
for (const s2 of result.skipped)
|
|
34052
|
+
for (const s2 of result.skipped) {
|
|
33908
34053
|
process.stderr.write(` \u898B\u9001\u308A ${s2.findingId} ${s2.file}: ${s2.reason}
|
|
34054
|
+
`);
|
|
34055
|
+
}
|
|
34056
|
+
for (const u of result.unchecked) process.stderr.write(` \u69CB\u6587\u691C\u67FB\u306A\u3057: ${u}
|
|
33909
34057
|
`);
|
|
33910
34058
|
}
|
|
33911
34059
|
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|