import { Agent, Box } from "@upstash/box"import { writeFile } from "node:fs/promises"import { z } from "zod"const responseSchema = z.object({ verdict: z.enum(["approved", "changes_requested"]), summary: z.string(), findings: z.array( z.object({ severity: z.enum(["high", "medium", "low"]), file: z.string(), line: z.number().nullable(), issue: z.string(), suggestion: z.string(), }), ),})type ReviewResult = z.infer<typeof responseSchema>const getRepoDir = (repo: string) => repo .split("/") .at(-1)! .replace(/\.git$/, "")type PullRequestInput = { repo: string base: string head: string}export async function reviewPullRequest(input: PullRequestInput): Promise<ReviewResult> { const box = await Box.create({ runtime: "node", agent: { harness: Agent.ClaudeCode, model: "anthropic/claude-opus-4-5", apiKey: process.env.ANTHROPIC_API_KEY, }, git: { token: process.env.GITHUB_TOKEN }, }) try { await box.git.clone({ repo: input.repo }) const repoDir = getRepoDir(input.repo) const reviewRun = await box.agent.run({ responseSchema, prompt: `Repository path: /work/${repoDir}Base branch: ${input.base}Head branch: ${input.head}Fetch both branches from origin, check out the head branch, and review only the codechanged in origin/${input.base}...HEAD.Focus on:- correctness bugs- security issues- performance regressions- missing edge-case testsRules:- Ignore style-only feedback.- Report only issues caused by changed code.- Keep each finding concrete and actionable.- Set verdict to "changes_requested" if there is at least one high severity issue.- If there are no meaningful issues, return verdict "approved" with empty findings. `.trim(), }) return reviewRun.result } finally { await box.delete() }}const result = await reviewPullRequest({ repo: "github.com/your-org/your-repo", base: "main", head: "feature/my-change",})await writeFile("./review-result.json", JSON.stringify(result, null, 2))console.log(`Verdict: ${result.verdict}`)console.log(result.summary)for (const finding of result.findings) { const line = finding.line === null ? "-" : String(finding.line) console.log(`[${finding.severity}] ${finding.file}:${line}`) console.log(`Issue: ${finding.issue}`) console.log(`Suggestion: ${finding.suggestion}`)}