(repo: string, issueNumber: number)
| 37 | * input — the bridge test doesn't hinge on the model echoing the right target. |
| 38 | */ |
| 39 | export function createTriageTools(repo: string, issueNumber: number) { |
| 40 | // ── Normal bridged tool: host fetches the issue's comment thread ────────── |
| 41 | const fetchIssueComments = toolDefinition({ |
| 42 | name: 'fetchIssueComments', |
| 43 | description: |
| 44 | `Fetch the human discussion thread on issue #${issueNumber} of ${repo} ` + |
| 45 | 'from the host. Comments often hold reproduction steps, stack traces, and ' + |
| 46 | 'maintainer hints that are not in the issue body. Takes no arguments.', |
| 47 | inputSchema: z.object({}), |
| 48 | outputSchema: z.object({ |
| 49 | count: z.number(), |
| 50 | comments: z.array( |
| 51 | z.object({ |
| 52 | author: z.string(), |
| 53 | body: z.string(), |
| 54 | createdAt: z.string(), |
| 55 | }), |
| 56 | ), |
| 57 | }), |
| 58 | }).server(async () => { |
| 59 | const res = await fetch( |
| 60 | `https://api.github.com/repos/${repo}/issues/${issueNumber}/comments?per_page=20`, |
| 61 | { headers: githubHeaders() }, |
| 62 | ) |
| 63 | if (!res.ok) { |
| 64 | throw new Error( |
| 65 | `GitHub comments fetch failed: ${res.status} ${res.statusText}`, |
| 66 | ) |
| 67 | } |
| 68 | const data = (await res.json()) as Array<{ |
| 69 | user?: { login?: string } |
| 70 | body?: string |
| 71 | created_at?: string |
| 72 | }> |
| 73 | const comments = data.map((comment) => ({ |
| 74 | author: comment.user?.login ?? 'unknown', |
| 75 | body: comment.body ?? '', |
| 76 | createdAt: comment.created_at ?? '', |
| 77 | })) |
| 78 | return { count: comments.length, comments } |
| 79 | }) |
| 80 | |
| 81 | // ── Code-mode bound tool: host searches the repo for related issues ─────── |
| 82 | const searchRelatedIssues = toolDefinition({ |
| 83 | name: 'searchRelatedIssues', |
| 84 | description: |
| 85 | `Search ${repo} for issues matching a free-text query. Use it to find ` + |
| 86 | 'duplicates or related reports for the issue under triage.', |
| 87 | inputSchema: z.object({ |
| 88 | query: z.string().describe('Free-text search terms.'), |
| 89 | }), |
| 90 | outputSchema: z.object({ |
| 91 | issues: z.array( |
| 92 | z.object({ |
| 93 | number: z.number(), |
| 94 | title: z.string(), |
| 95 | state: z.string(), |
| 96 | url: z.string(), |
no test coverage detected