github-pr-search.ts 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. /// <reference path="../env.d.ts" />
  2. import { tool } from "@opencode-ai/plugin"
  3. import DESCRIPTION from "./github-pr-search.txt"
  4. async function githubFetch(endpoint: string, options: RequestInit = {}) {
  5. const response = await fetch(`https://api.github.com${endpoint}`, {
  6. ...options,
  7. headers: {
  8. Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
  9. Accept: "application/vnd.github+json",
  10. "Content-Type": "application/json",
  11. ...options.headers,
  12. },
  13. })
  14. if (!response.ok) {
  15. throw new Error(`GitHub API error: ${response.status} ${response.statusText}`)
  16. }
  17. return response.json()
  18. }
  19. interface PR {
  20. title: string
  21. html_url: string
  22. }
  23. export default tool({
  24. description: DESCRIPTION,
  25. args: {
  26. query: tool.schema.string().describe("Search query for PR titles and descriptions"),
  27. limit: tool.schema.number().describe("Maximum number of results to return").default(10),
  28. offset: tool.schema.number().describe("Number of results to skip for pagination").default(0),
  29. },
  30. async execute(args) {
  31. const owner = "anomalyco"
  32. const repo = "opencode"
  33. const page = Math.floor(args.offset / args.limit) + 1
  34. const searchQuery = encodeURIComponent(`${args.query} repo:${owner}/${repo} type:pr state:open`)
  35. const result = await githubFetch(
  36. `/search/issues?q=${searchQuery}&per_page=${args.limit}&page=${page}&sort=updated&order=desc`,
  37. )
  38. if (result.total_count === 0) {
  39. return `No PRs found matching "${args.query}"`
  40. }
  41. const prs = result.items as PR[]
  42. const formatted = prs.map((pr) => `${pr.title}\n${pr.html_url}`).join("\n\n")
  43. return `Found ${result.total_count} PRs (showing ${prs.length}):\n\n${formatted}`
  44. },
  45. })