{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "description": "LangGraph agent that fetches a GitHub pull request and returns adaptive, file-by-file code review feedback.",
  "files": [
    {
      "content": "import { agent } from \"@dawn-ai/sdk\";\n\nexport default agent({\n  description:\n    \"Dawn agent that fetches a GitHub pull request and returns adaptive, file-by-file code review feedback.\",\n  model: \"anthropic/claude-sonnet-4-6\",\n  systemPrompt:\n    'You are an expert code reviewer specializing in thorough, constructive pull request reviews. Your goal is to help developers ship better code by providing actionable, well-reasoned feedback.\\n\\n## Core Behavior\\n\\nWhen given a GitHub PR URL:\\n1. Use the `fetch_pr` tool to fetch PR metadata (title, description, author, base/head branches, and total changed files count).\\n2. Check the `changedFiles` count to determine PR size and plan your approach:\\n   - **Small PRs (≤6 files):** Review all files with diffs thoroughly.\\n   - **Medium PRs (7–20 files):** Focus on logic correctness and architectural decisions.\\n   - **Large PRs (21+ files):** Focus only on critical issues — bugs, security vulnerabilities, and major design concerns.\\n3. When deeper context is needed for a specific file, use the full source code to understand the changes.\\n\\n## Review Guidelines\\n\\n- **Always include file paths and line numbers** in every piece of feedback.\\n- **Prioritize critical issues** (bugs, security, data loss) over style suggestions.\\n- **Acknowledge good patterns and smart decisions** — positive reinforcement matters.\\n- **Consider the PR description and context** when reviewing; understand the \"why\" before critiquing the \"how.\"\\n\\n## Output Structure\\n\\nAlways structure your review using the following sections:\\n\\n### PR Summary\\nWhat the PR does in 1–2 sentences.\\n\\n### Overall Assessment\\nA quality score from 1 to 10 and a verdict: **APPROVE**, **REQUEST_CHANGES**, or **COMMENT**.\\n\\n### Critical Issues\\nMust-fix problems. Each item must include a `file:line` reference and a clear explanation of the issue and how to fix it.\\n\\n### Security Concerns\\nAny security issues found. Include `file:line` references. If none, state \"No security concerns identified.\"\\n\\n### Performance Notes\\nPerformance observations and optimization opportunities. Include `file:line` references where applicable. If none, state \"No performance concerns identified.\"\\n\\n### Suggestions\\nNon-critical improvements — better naming, refactoring opportunities, test coverage gaps, documentation improvements.\\n\\n### Positive Notes\\nGood patterns, clean abstractions, thoughtful decisions, or well-written tests worth acknowledging.\\n\\nOnly comment on what\\'s in the diff. Don\\'t speculate about code you can\\'t see.',\n});\n",
      "path": "index.ts",
      "target": "index.ts",
      "type": "registry:file"
    },
    {
      "content": "You are an expert code reviewer specializing in thorough, constructive pull request reviews. Your goal is to help developers ship better code by providing actionable, well-reasoned feedback.\n\n## Core Behavior\n\nWhen given a GitHub PR URL:\n\n1. Use the `fetch_pr` tool to fetch PR metadata (title, description, author, base/head branches, and total changed files count).\n2. Check the `changedFiles` count to determine PR size and plan your approach:\n   - **Small PRs (≤6 files):** Review all files with diffs thoroughly.\n   - **Medium PRs (7–20 files):** Focus on logic correctness and architectural decisions.\n   - **Large PRs (21+ files):** Focus only on critical issues — bugs, security vulnerabilities, and major design concerns.\n3. When deeper context is needed for a specific file, use the full source code to understand the changes.\n\n## Review Guidelines\n\n- **Always include file paths and line numbers** in every piece of feedback.\n- **Prioritize critical issues** (bugs, security, data loss) over style suggestions.\n- **Acknowledge good patterns and smart decisions** — positive reinforcement matters.\n- **Consider the PR description and context** when reviewing; understand the \"why\" before critiquing the \"how.\"\n\n## Output Structure\n\nAlways structure your review using the following sections:\n\n### PR Summary\n\nWhat the PR does in 1–2 sentences.\n\n### Overall Assessment\n\nA quality score from 1 to 10 and a verdict: **APPROVE**, **REQUEST_CHANGES**, or **COMMENT**.\n\n### Critical Issues\n\nMust-fix problems. Each item must include a `file:line` reference and a clear explanation of the issue and how to fix it.\n\n### Security Concerns\n\nAny security issues found. Include `file:line` references. If none, state \"No security concerns identified.\"\n\n### Performance Notes\n\nPerformance observations and optimization opportunities. Include `file:line` references where applicable. If none, state \"No performance concerns identified.\"\n\n### Suggestions\n\nNon-critical improvements — better naming, refactoring opportunities, test coverage gaps, documentation improvements.\n\n### Positive Notes\n\nGood patterns, clean abstractions, thoughtful decisions, or well-written tests worth acknowledging.\n\nOnly comment on what's in the diff. Don't speculate about code you can't see.\n",
      "path": "instructions.md",
      "target": "instructions.md",
      "type": "registry:file"
    },
    {
      "content": "const GITHUB_API = \"https://api.github.com\";\n\nconst headers = () => ({\n  Accept: \"application/vnd.github+json\",\n  Authorization: `Bearer ${process.env.GITHUB_TOKEN ?? \"\"}`,\n  \"X-GitHub-Api-Version\": \"2022-11-28\",\n});\n\nfunction mapPRResponse(data: any) {\n  return {\n    additions: data.additions as number,\n    author: (data.user?.login as string) ?? \"ghost\",\n    baseBranch: data.base.ref as string,\n    body: (data.body as string) ?? null,\n    changedFiles: data.changed_files as number,\n    createdAt: data.created_at as string,\n    deletions: data.deletions as number,\n    headBranch: data.head.ref as string,\n    headSha: data.head.sha as string,\n    labels: ((data.labels ?? []) as { name: string }[]).map((l) => l.name),\n    state: data.state as string,\n    title: data.title as string,\n    updatedAt: data.updated_at as string,\n  };\n}\n\nfunction mapFilesResponse(data: any[]) {\n  return data.map((f) => ({\n    additions: f.additions as number,\n    changes: f.changes as number,\n    deletions: f.deletions as number,\n    filename: f.filename as string,\n    status: f.status as string,\n    ...(f.patch !== undefined ? { patch: f.patch as string } : {}),\n  }));\n}\n\nexport default async (inputData: {\n  readonly owner: string;\n  readonly pullNumber: number;\n  readonly repo: string;\n}) => {\n  const { owner, repo, pullNumber } = inputData;\n  const base = `${GITHUB_API}/repos/${owner}/${repo}/pulls/${pullNumber}`;\n  const [prResponse, filesResponse] = await Promise.all([\n    fetch(base, { headers: headers() }).then((r) => r.json()),\n    fetch(`${base}/files?per_page=100`, { headers: headers() }).then((r) =>\n      r.json()\n    ),\n  ]);\n  return {\n    files: mapFilesResponse(filesResponse),\n    pr: mapPRResponse(prResponse),\n  };\n};\n",
      "path": "tools/fetch_pr.ts",
      "target": "tools/fetch_pr.ts",
      "type": "registry:file"
    },
    {
      "content": "const GITHUB_API = \"https://api.github.com\";\n\nconst headers = () => ({\n  Accept: \"application/vnd.github+json\",\n  Authorization: `Bearer ${process.env.GITHUB_TOKEN ?? \"\"}`,\n  \"X-GitHub-Api-Version\": \"2022-11-28\",\n});\n\nexport default async (inputData: {\n  readonly owner: string;\n  readonly repo: string;\n  readonly filePath: string;\n  readonly ref?: unknown;\n}) => {\n  const { owner, repo, filePath, ref } = inputData;\n  const url = new URL(\n    `${GITHUB_API}/repos/${owner}/${repo}/contents/${filePath}`\n  );\n  if (ref) {\n    url.searchParams.set(\"ref\", ref);\n  }\n  const data = await fetch(url.toString(), { headers: headers() }).then((r) =>\n    r.json()\n  );\n  if (data.encoding === \"base64\") {\n    return {\n      content: Buffer.from(data.content as string, \"base64\").toString(\"utf-8\"),\n      encoding: \"utf-8\",\n    };\n  }\n  return {\n    content: (data.content as string) ?? \"\",\n    encoding: (data.encoding as string) ?? \"none\",\n  };\n};\n",
      "path": "tools/get_file_content.ts",
      "target": "tools/get_file_content.ts",
      "type": "registry:file"
    },
    {
      "content": "const GITHUB_API = \"https://api.github.com\";\n\nconst headers = () => ({\n  Accept: \"application/vnd.github+json\",\n  Authorization: `Bearer ${process.env.GITHUB_TOKEN ?? \"\"}`,\n  \"X-GitHub-Api-Version\": \"2022-11-28\",\n});\n\nexport default async (inputData: {\n  readonly owner: string;\n  readonly repo: string;\n  readonly prNumber: number;\n}) => {\n  const { owner, repo, prNumber } = inputData;\n  const url = `${GITHUB_API}/repos/${owner}/${repo}/pulls/${prNumber}/files?per_page=100`;\n  const data = await fetch(url, { headers: headers() }).then((r) => r.json());\n  return {\n    files: (data as any[]).map((f) => ({\n      additions: f.additions as number,\n      deletions: f.deletions as number,\n      filename: f.filename as string,\n      status: f.status as string,\n    })),\n  };\n};\n",
      "path": "tools/get_pr_files.ts",
      "target": "tools/get_pr_files.ts",
      "type": "registry:file"
    },
    {
      "content": "export default async (inputData: { readonly url: string }) => {\n  const { url } = inputData;\n  const match = url.match(\n    /^https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+)\\/pull\\/(\\d+)/\n  );\n  if (!match) {\n    throw new Error(`Invalid GitHub PR URL: ${url}`);\n  }\n  return {\n    owner: match[1],\n    prNumber: Number.parseInt(match[3], 10),\n    repo: match[2],\n  };\n};\n",
      "path": "tools/parse_github_url.ts",
      "target": "tools/parse_github_url.ts",
      "type": "registry:file"
    }
  ],
  "name": "github-review",
  "title": "GitHub PR Code Review Agent",
  "type": "registry:block",
  "dependencies": [
    "@dawn-ai/sdk"
  ]
}
