fix: resolve AI review duplication and GenAI config issues
swadhinbiswas committed 3 months ago
0b857d5
1 parent 35ec7c5
commit 0b857d5
3 files changed
+109 -27
Showing 3 changed files+109-27
▼bun.lock
+20-1
| @@ -16,6 +16,7 @@ | ||
16 | 16 | "@dnd-kit/core": "^6.3.1", |
17 | 17 | "@dnd-kit/sortable": "^10.0.0", |
18 | 18 | "@dnd-kit/utilities": "^3.2.2", |
19 | + "@google/genai": "^2.11.0", | |
19 | 20 | "@libsql/client": "^0.15.15", |
20 | 21 | "@mistralai/mistralai": "^2.4.1", |
21 | 22 | "@monaco-editor/react": "^4.6.0", |
| @@ -470,6 +471,8 @@ | ||
470 | 471 | |
471 | 472 | "@floating-ui/utils": ["@floating-ui/[email protected]", "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.11.tgz", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="], |
472 | 473 | |
474 | + "@google/genai": ["@google/[email protected]", "https://registry.npmmirror.com/@google/genai/-/genai-2.11.0.tgz", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-d2Csf29vS0GfHc52H0MG25ccY4FKvvbDgqDlEovLrPLF8sPegWr/GGO+LMOy85/1SnX0iV0zDAW7R8SsvWg8Vg=="], | |
475 | + | |
473 | 476 | "@graphql-tools/executor": ["@graphql-tools/[email protected]", "https://registry.npmmirror.com/@graphql-tools/executor/-/executor-1.5.3.tgz", { "dependencies": { "@graphql-tools/utils": "^11.1.0", "@graphql-typed-document-node/core": "^3.2.0", "@repeaterjs/repeater": "^3.0.4", "@whatwg-node/disposablestack": "^0.0.6", "@whatwg-node/promise-helpers": "^1.0.0", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-mgBFC0bsrZPZLu9EnydpMnAuQ8Iiq0CEbUcsmvXsm2/iYektGHDN/+bmb7hicA6dWZtdPfklYJmr21WD0GnOfA=="], |
474 | 477 | |
475 | 478 | "@graphql-tools/merge": ["@graphql-tools/[email protected]", "https://registry.npmmirror.com/@graphql-tools/merge/-/merge-9.1.9.tgz", { "dependencies": { "@graphql-tools/utils": "^11.1.0", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-iHUWNjRHeQRYdgIMIuChThOwoKzA9vrzYeslgfBo5eUYEyHGZCoDPjAavssoYXLwstYt1dZj2J22jSzc2DrN0Q=="], |
| @@ -1170,6 +1173,8 @@ | ||
1170 | 1173 | |
1171 | 1174 | "@types/react-dom": ["@types/[email protected]", "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.3.7.tgz", { "peerDependencies": { "@types/react": "^18.0.0" } }, "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ=="], |
1172 | 1175 | |
1176 | + "@types/retry": ["@types/[email protected]", "https://registry.npmmirror.com/@types/retry/-/retry-0.12.0.tgz", {}, "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA=="], | |
1177 | + | |
1173 | 1178 | "@types/ssh2": ["@types/[email protected]", "https://registry.npmmirror.com/@types/ssh2/-/ssh2-1.15.5.tgz", { "dependencies": { "@types/node": "^18.11.18" } }, "sha512-N1ASjp/nXH3ovBHddRJpli4ozpk6UdDYIX4RJWFa9L1YKnzdhTlVmiGHm4DZnj/jLbqZpes4aeR30EFGQtvhQQ=="], |
1174 | 1179 | |
1175 | 1180 | "@types/stats.js": ["@types/[email protected]", "https://registry.npmmirror.com/@types/stats.js/-/stats.js-0.17.4.tgz", {}, "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA=="], |
| @@ -1372,6 +1377,8 @@ | ||
1372 | 1377 | |
1373 | 1378 | "buffer": ["[email protected]", "https://registry.npmmirror.com/buffer/-/buffer-5.6.0.tgz", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4" } }, "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw=="], |
1374 | 1379 | |
1380 | + "buffer-equal-constant-time": ["[email protected]", "https://registry.npmmirror.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], | |
1381 | + | |
1375 | 1382 | "buffer-from": ["[email protected]", "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], |
1376 | 1383 | |
1377 | 1384 | "buildcheck": ["[email protected]", "https://registry.npmmirror.com/buildcheck/-/buildcheck-0.0.7.tgz", {}, "sha512-lHblz4ahamxpTmnsk+MNTRWsjYKv965MwOrSJyeD588rR3Jcu7swE+0wN5F+PbL5cjgu/9ObkhfzEPuofEMwLA=="], |
| @@ -1608,6 +1615,8 @@ | ||
1608 | 1615 | |
1609 | 1616 | "eastasianwidth": ["[email protected]", "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], |
1610 | 1617 | |
1618 | + "ecdsa-sig-formatter": ["[email protected]", "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], | |
1619 | + | |
1611 | 1620 | "ee-first": ["[email protected]", "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], |
1612 | 1621 | |
1613 | 1622 | "electron-to-chromium": ["[email protected]", "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.366.tgz", {}, "sha512-OlRuhb688YTCzzU3gXPLn6nGyd+F+53INE1qaKKlu6kETErE8FYsyDh0XqXEU+uBRn0MpCzz2vfNwORhkap8qg=="], |
| @@ -1776,6 +1785,8 @@ | ||
1776 | 1785 | |
1777 | 1786 | "globe.gl": ["[email protected]", "https://registry.npmmirror.com/globe.gl/-/globe.gl-2.46.1.tgz", { "dependencies": { "@tweenjs/tween.js": "18 - 25", "accessor-fn": "1", "kapsule": "^1.16", "three": ">=0.179 <1", "three-globe": "^2.45", "three-render-objects": "^1.41" } }, "sha512-h+OvX52EBIPLtM0/2JkM+JZ9gPAhPJ4y3+hxUwD5Ey/O0Zk2ockuTiJ71bZbnNBGmNiIZzA5Vr3TMT0b3d35IQ=="], |
1778 | 1787 | |
1788 | + "google-auth-library": ["[email protected]", "https://registry.npmmirror.com/google-auth-library/-/google-auth-library-10.9.0.tgz", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", "gcp-metadata": "8.1.2", "google-logging-utils": "1.1.3", "jws": "^4.0.0" } }, "sha512-xtvUqvINPhTaBm7nXqlYPcrMHJPm1lCNdSovxnKKhTm+4JsvQ+KGVYJViLoH9Yxu8w+T0Qv5HubzYT9BLrppJg=="], | |
1789 | + | |
1779 | 1790 | "google-logging-utils": ["[email protected]", "https://registry.npmmirror.com/google-logging-utils/-/google-logging-utils-1.1.3.tgz", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], |
1780 | 1791 | |
1781 | 1792 | "gopd": ["[email protected]", "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], |
| @@ -1958,6 +1969,10 @@ | ||
1958 | 1969 | |
1959 | 1970 | "jsonfile": ["[email protected]", "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], |
1960 | 1971 | |
1972 | + "jwa": ["[email protected]", "https://registry.npmmirror.com/jwa/-/jwa-2.0.1.tgz", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="], | |
1973 | + | |
1974 | + "jws": ["[email protected]", "https://registry.npmmirror.com/jws/-/jws-4.0.1.tgz", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="], | |
1975 | + | |
1961 | 1976 | "kapsule": ["[email protected]", "https://registry.npmmirror.com/kapsule/-/kapsule-1.16.3.tgz", { "dependencies": { "lodash-es": "4" } }, "sha512-4+5mNNf4vZDSwPhKprKwz3330iisPrb08JyMgbsdFrimBCKNHecua/WBwvVg3n7vwx0C1ARjfhwIpbrbd9n5wg=="], |
1962 | 1977 | |
1963 | 1978 | "keyv": ["[email protected]", "https://registry.npmmirror.com/keyv/-/keyv-5.6.0.tgz", { "dependencies": { "@keyv/serialize": "^1.1.1" } }, "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw=="], |
| @@ -2266,6 +2281,8 @@ | ||
2266 | 2281 | |
2267 | 2282 | "p-queue": ["[email protected]", "https://registry.npmmirror.com/p-queue/-/p-queue-8.1.1.tgz", { "dependencies": { "eventemitter3": "^5.0.1", "p-timeout": "^6.1.2" } }, "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ=="], |
2268 | 2283 | |
2284 | + "p-retry": ["[email protected]", "https://registry.npmmirror.com/p-retry/-/p-retry-4.6.2.tgz", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="], | |
2285 | + | |
2269 | 2286 | "p-timeout": ["[email protected]", "https://registry.npmmirror.com/p-timeout/-/p-timeout-6.1.4.tgz", {}, "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg=="], |
2270 | 2287 | |
2271 | 2288 | "p-try": ["[email protected]", "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], |
| @@ -2510,7 +2527,7 @@ | ||
2510 | 2527 | |
2511 | 2528 | "retext-stringify": ["[email protected]", "https://registry.npmmirror.com/retext-stringify/-/retext-stringify-4.0.0.tgz", { "dependencies": { "@types/nlcst": "^2.0.0", "nlcst-to-string": "^4.0.0", "unified": "^11.0.0" } }, "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA=="], |
2512 | 2529 | |
2513 | - "retry": ["[email protected]", "https://registry.npmmirror.com/retry/-/retry-0.12.0.tgz", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], | |
2530 | + "retry": ["[email protected]", "https://registry.npmmirror.com/retry/-/retry-0.13.1.tgz", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], | |
2514 | 2531 | |
2515 | 2532 | "reusify": ["[email protected]", "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], |
2516 | 2533 | |
| @@ -3120,6 +3137,8 @@ | ||
3120 | 3137 | |
3121 | 3138 | "prebuild-install/detect-libc": ["[email protected]", "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], |
3122 | 3139 | |
3140 | + "promise-retry/retry": ["[email protected]", "https://registry.npmmirror.com/retry/-/retry-0.12.0.tgz", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], | |
3141 | + | |
3123 | 3142 | "prompts/kleur": ["[email protected]", "https://registry.npmmirror.com/kleur/-/kleur-3.0.3.tgz", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], |
3124 | 3143 | |
3125 | 3144 | "qrcode/yargs": ["[email protected]", "https://registry.npmmirror.com/yargs/-/yargs-15.4.1.tgz", { "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.2" } }, "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A=="], |
3126 | 3145 | |
▼package.json
+1-0
| @@ -55,6 +55,7 @@ | ||
55 | 55 | "@dnd-kit/core": "^6.3.1", |
56 | 56 | "@dnd-kit/sortable": "^10.0.0", |
57 | 57 | "@dnd-kit/utilities": "^3.2.2", |
58 | + "@google/genai": "^2.11.0", | |
58 | 59 | "@libsql/client": "^0.15.15", |
59 | 60 | "@mistralai/mistralai": "^2.4.1", |
60 | 61 | "@monaco-editor/react": "^4.6.0", |
61 | 62 | |
▼scripts/ai-review.ts
+88-26
| @@ -1,9 +1,12 @@ | ||
1 | 1 | import { execSync } from 'child_process'; |
2 | 2 | import { Mistral } from '@mistralai/mistralai'; |
3 | +import { GoogleGenAI } from '@google/genai'; | |
4 | +import type { Interactions } from '@google/genai'; | |
3 | 5 | import dotenv from 'dotenv'; |
4 | 6 | |
5 | 7 | dotenv.config(); |
6 | 8 | |
9 | +const GEMINI_API_KEY = process.env.GEMINI_KEY || process.env.GEMINI_API_KEY; | |
7 | 10 | const AGENT_API_KEY = process.env.AGENT_API_KEY; |
8 | 11 | const GITHUB_TOKEN = process.env.GITHUB_TOKEN; |
9 | 12 | const PR_NUMBER = process.env.PR_NUMBER; |
| @@ -11,8 +14,8 @@ const REPO = process.env.REPO; | ||
11 | 14 | const BASE_SHA = process.env.BASE_SHA; |
12 | 15 | const HEAD_SHA = process.env.HEAD_SHA; |
13 | 16 | |
14 | -if (!AGENT_API_KEY) { | |
15 | - console.log("AGENT_API_KEY is not set. Skipping AI review."); | |
17 | +if (!GEMINI_API_KEY && !AGENT_API_KEY) { | |
18 | + console.log("No AI provider API key found (GEMINI_KEY or AGENT_API_KEY). Skipping AI review."); | |
16 | 19 | process.exit(0); |
17 | 20 | } |
18 | 21 | |
| @@ -21,10 +24,6 @@ if (!GITHUB_TOKEN) { | ||
21 | 24 | process.exit(0); |
22 | 25 | } |
23 | 26 | |
24 | -const client = new Mistral({ | |
25 | - apiKey: AGENT_API_KEY, | |
26 | -}); | |
27 | - | |
28 | 27 | async function run() { |
29 | 28 | try { |
30 | 29 | // 1. Get the diff |
| @@ -41,8 +40,6 @@ async function run() { | ||
41 | 40 | return; |
42 | 41 | } |
43 | 42 | |
44 | - // 2. Call Mistral API | |
45 | - console.log("Requesting review from Mistral Agent..."); | |
46 | 43 | const prompt = `You are a senior software engineer conducting a code review on a pull request. |
47 | 44 | Review the following git diff and provide constructive, human-like, and professional feedback. |
48 | 45 | Focus on identifying logic errors, security issues, performance bottlenecks, and best practice violations. |
| @@ -59,28 +56,93 @@ ${diff} | ||
59 | 56 | \`\`\` |
60 | 57 | `; |
61 | 58 | |
62 | - const messages = [ | |
63 | - {"role":"user","content": prompt} | |
64 | - ]; | |
59 | + let reviewComment = ""; | |
60 | + | |
61 | + if (AGENT_API_KEY) { | |
62 | + console.log("Requesting review from Mistral Agent..."); | |
63 | + const client = new Mistral({ apiKey: AGENT_API_KEY }); | |
64 | + const messages = [{ "role": "user", "content": prompt }]; | |
65 | + | |
66 | + const response = await client.beta.conversations.start({ | |
67 | + agentId: 'ag_019f4ae0eb2e764aaa3f1dec318fc748', | |
68 | + agentVersion: 0, | |
69 | + inputs: messages, | |
70 | + }); | |
71 | + | |
72 | + reviewComment = response?.choices?.[0]?.message?.content || response?.message?.content || ""; | |
73 | + | |
74 | + if (!reviewComment) { | |
75 | + console.log("Could not find standard content in response. Fallback to full response."); | |
76 | + process.exit(1); | |
77 | + } | |
78 | + reviewComment += "\n\n— *AI Code Review (Powered by Mistral Agent)*"; | |
79 | + | |
80 | + } else if (GEMINI_API_KEY) { | |
81 | + console.log("Requesting review from Gemini 3.5 Flash..."); | |
82 | + const ai = new GoogleGenAI({ apiKey: GEMINI_API_KEY }); | |
83 | + const tools: Interactions.Tool[] = [{ type: 'google_search' }]; | |
84 | + | |
85 | + // Fixed config: Using camelCase and nested thinkingConfig | |
86 | + const generationConfig = { | |
87 | + maxOutputTokens: 65536, | |
88 | + thinkingConfig: { thinkingBudget: 8192 }, | |
89 | + }; | |
90 | + | |
91 | + const interaction = await ai.interactions.create({ | |
92 | + model: 'models/gemini-3.5-flash', | |
93 | + input: prompt, | |
94 | + tools: tools, | |
95 | + generation_config: generationConfig, // the sdk still expects the property to be named generation_config | |
96 | + }); | |
97 | + | |
98 | + const step = interaction.steps?.at(-1); | |
99 | + reviewComment = step?.text || step?.parts?.[0]?.text || ""; | |
100 | + | |
101 | + if (!reviewComment) { | |
102 | + console.error("No content received from Gemini."); | |
103 | + process.exit(1); | |
104 | + } | |
105 | + reviewComment += "\n\n— *AI Code Review (Powered by Gemini)*"; | |
106 | + } | |
65 | 107 | |
66 | - const response = await client.beta.conversations.start({ | |
67 | - agentId: 'ag_019f4ae0eb2e764aaa3f1dec318fc748', | |
68 | - agentVersion: 0, | |
69 | - inputs: messages, | |
108 | + // 3. Post to GitHub (and handle deduplication) | |
109 | + console.log("Fetching existing reviews..."); | |
110 | + const reviewsResponse = await fetch(`https://api.github.com/repos/${REPO}/pulls/${PR_NUMBER}/reviews`, { | |
111 | + headers: { | |
112 | + 'Authorization': `Bearer ${GITHUB_TOKEN}`, | |
113 | + 'Accept': 'application/vnd.github.v3+json', | |
114 | + 'X-GitHub-Api-Version': '2022-11-28' | |
115 | + } | |
70 | 116 | }); |
71 | 117 | |
72 | - let reviewComment = response?.choices?.[0]?.message?.content || response?.message?.content; | |
73 | - | |
74 | - if (!reviewComment) { | |
75 | - console.log("Could not find standard content in response. Fallback to full response:", JSON.stringify(response)); | |
76 | - process.exit(1); | |
118 | + if (reviewsResponse.ok) { | |
119 | + const reviews = await reviewsResponse.json(); | |
120 | + // Look for a previous review made by our bot | |
121 | + const previousReview = reviews.find((r: any) => r.body && r.body.includes('AI Code Review (Powered by')); | |
122 | + | |
123 | + if (previousReview) { | |
124 | + console.log(`Updating existing review #${previousReview.id}...`); | |
125 | + const updateResponse = await fetch(`https://api.github.com/repos/${REPO}/pulls/${PR_NUMBER}/reviews/${previousReview.id}`, { | |
126 | + method: 'PUT', | |
127 | + headers: { | |
128 | + 'Authorization': `Bearer ${GITHUB_TOKEN}`, | |
129 | + 'Accept': 'application/vnd.github.v3+json', | |
130 | + 'X-GitHub-Api-Version': '2022-11-28' | |
131 | + }, | |
132 | + body: JSON.stringify({ body: reviewComment }) | |
133 | + }); | |
134 | + | |
135 | + if (!updateResponse.ok) { | |
136 | + const ghError = await updateResponse.text(); | |
137 | + console.error(`GitHub API Error on update: ${updateResponse.status} - ${ghError}`); | |
138 | + process.exit(1); | |
139 | + } | |
140 | + console.log("Review successfully updated!"); | |
141 | + return; | |
142 | + } | |
77 | 143 | } |
78 | - | |
79 | - // Add a signature | |
80 | - reviewComment += "\n\n— *AI Code Review (Powered by Mistral Agent)*"; | |
81 | 144 | |
82 | - // 3. Post to GitHub | |
83 | - console.log("Posting review to GitHub PR..."); | |
145 | + console.log("Posting new review to GitHub PR..."); | |
84 | 146 | const ghResponse = await fetch(`https://api.github.com/repos/${REPO}/pulls/${PR_NUMBER}/reviews`, { |
85 | 147 | method: 'POST', |
86 | 148 | headers: { |
| @@ -96,7 +158,7 @@ ${diff} | ||
96 | 158 | |
97 | 159 | if (!ghResponse.ok) { |
98 | 160 | const ghError = await ghResponse.text(); |
99 | - console.error(`GitHub API Error: ${ghResponse.status} - ${ghError}`); | |
161 | + console.error(`GitHub API Error on post: ${ghResponse.status} - ${ghError}`); | |
100 | 162 | process.exit(1); |
101 | 163 | } |
102 | 164 | |
103 | 165 | |