@shipfox/api-integration-github 12.3.0 → 12.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,44 @@
1
1
  import { Octokit } from 'octokit';
2
+ import { mapGithubError } from '#api/client.js';
2
3
  import { createGithubInstallationTokenProvider } from '#api/installation-token-provider.js';
3
4
  import { normalizedGithubApiBaseUrl } from '#config.js';
4
5
  import { GithubIntegrationProviderError } from './errors.js';
5
6
  import { githubAgentToolCatalog, githubAgentToolSelectionCatalog } from './github-agent-tool-catalog.js';
6
7
  export { buildGithubAgentToolSelectionCatalog, DEFAULT_JOB_LOG_TAIL_LINES, githubAgentToolCatalog, githubAgentToolSelectionCatalog } from './github-agent-tool-catalog.js';
8
+ const GITHUB_GRAPHQL_ROUTE = 'POST /graphql';
9
+ const GITHUB_ARTIFACT_ARCHIVE_FORMAT = 'zip';
10
+ const GITHUB_ARTIFACT_DOWNLOAD_ROUTE = `GET /repos/{owner}/{repo}/actions/artifacts/{resource_id}/${GITHUB_ARTIFACT_ARCHIVE_FORMAT}`;
11
+ const GITHUB_ARTIFACT_DOWNLOAD_TIMEOUT_MS = 30_000;
12
+ const NO_PENDING_REVIEW_MESSAGE = 'No pending pull request review found for the authenticated GitHub user.';
13
+ const LATEST_PENDING_REVIEW_QUERY = `
14
+ query LatestPendingPullRequestReview($owner: String!, $repo: String!, $pullNumber: Int!) {
15
+ viewer {
16
+ login
17
+ }
18
+ repository(owner: $owner, name: $repo) {
19
+ pullRequest(number: $pullNumber) {
20
+ reviews(last: 100, states: [PENDING]) {
21
+ nodes {
22
+ id
23
+ author {
24
+ login
25
+ }
26
+ createdAt
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ `;
33
+ const ADD_PENDING_REVIEW_COMMENT_MUTATION = `
34
+ mutation AddCommentToPendingReview($input: AddPullRequestReviewThreadInput!) {
35
+ addPullRequestReviewThread(input: $input) {
36
+ thread {
37
+ id
38
+ }
39
+ }
40
+ }
41
+ `;
7
42
  export class GithubAgentToolsProvider {
8
43
  constructor(options = {}){
9
44
  this.options = options;
@@ -39,13 +74,17 @@ export class GithubAgentToolsProvider {
39
74
  return githubToolError('GitHub installation token is missing permission for this operation');
40
75
  }
41
76
  const client = (this.options.createClient ?? createOctokitClient)(token.token);
42
- try {
43
- const response = await client.request(operation.route, operation.parameters);
44
- return githubToolResult(tool.id, response.data);
45
- } catch (error) {
46
- if (error instanceof GithubIntegrationProviderError) return githubToolError(error.message);
47
- throw error;
77
+ const method = typeof call.arguments.method === 'string' ? call.arguments.method : undefined;
78
+ if (operation.kind === 'graphql') {
79
+ const data = await mapGithubError(()=>addCommentToPendingReview(client, operation.parameters));
80
+ return data === undefined ? githubToolError(NO_PENDING_REVIEW_MESSAGE) : githubToolResult(tool.id, data);
81
+ }
82
+ const operationParameters = await mapGithubError(()=>resolvePendingReviewParameters(client, operation.parameters, tool.id, method));
83
+ if (operationParameters === undefined) {
84
+ return githubToolError(NO_PENDING_REVIEW_MESSAGE);
48
85
  }
86
+ const response = await mapGithubError(()=>client.request(operation.route, operationParameters));
87
+ return githubToolResult(tool.id, response.data, response, operationParameters, operation.route);
49
88
  }
50
89
  };
51
90
  }
@@ -59,7 +98,26 @@ function createOctokitClient(token) {
59
98
  }
60
99
  });
61
100
  return {
62
- request: async (route, parameters)=>await octokit.request(route, parameters)
101
+ request: async (route, parameters)=>{
102
+ if (route !== GITHUB_ARTIFACT_DOWNLOAD_ROUTE) {
103
+ return await octokit.request(route, parameters);
104
+ }
105
+ const abortController = new AbortController();
106
+ const timeout = setTimeout(()=>abortController.abort(), GITHUB_ARTIFACT_DOWNLOAD_TIMEOUT_MS);
107
+ try {
108
+ return await octokit.request(route, {
109
+ ...parameters,
110
+ request: {
111
+ redirect: 'manual',
112
+ parseSuccessResponseBody: false,
113
+ signal: abortController.signal
114
+ }
115
+ });
116
+ } finally{
117
+ clearTimeout(timeout);
118
+ }
119
+ },
120
+ graphql: async (query, variables)=>await octokit.graphql(query, variables)
63
121
  };
64
122
  }
65
123
  function resolveGithubOperation(tool, call) {
@@ -74,10 +132,11 @@ function resolveGithubOperation(tool, call) {
74
132
  const route = githubOperationRoute(toolId, method, params);
75
133
  return route === undefined ? undefined : {
76
134
  route,
77
- parameters: projectGithubOperationParameters(toolId, method, params)
135
+ parameters: projectGithubOperationParameters(toolId, method, params),
136
+ kind: route === GITHUB_GRAPHQL_ROUTE ? 'graphql' : 'rest'
78
137
  };
79
138
  }
80
- function githubOperationRoute(toolId, method, args) {
139
+ export function githubOperationRoute(toolId, method, args) {
81
140
  const owner = '{owner}';
82
141
  const repo = '{repo}';
83
142
  const issue = '{issue_number}';
@@ -114,7 +173,7 @@ function githubOperationRoute(toolId, method, args) {
114
173
  case 'sub_issue_write.remove':
115
174
  return `DELETE ${repoPath}/issues/${issue}/sub_issues/{sub_issue_id}`;
116
175
  case 'sub_issue_write.reprioritize':
117
- return `PATCH ${repoPath}/issues/${issue}/sub_issues/{sub_issue_id}`;
176
+ return `PATCH ${repoPath}/issues/${issue}/sub_issues/priority`;
118
177
  case 'pull_request_read.get':
119
178
  return `GET ${repoPath}/pulls/${pull}`;
120
179
  case 'pull_request_read.get_diff':
@@ -142,7 +201,7 @@ function githubOperationRoute(toolId, method, args) {
142
201
  case 'update_pull_request.':
143
202
  return `PATCH ${repoPath}/pulls/${pull}`;
144
203
  case 'add_reply_to_pull_request_comment.':
145
- return `POST ${repoPath}/pulls/{comment_id}/replies`;
204
+ return args.reaction !== undefined && args.body === undefined ? `POST ${repoPath}/pulls/comments/{comment_id}/reactions` : `POST ${repoPath}/pulls/${pull}/comments/{comment_id}/replies`;
146
205
  case 'merge_pull_request.':
147
206
  return `PUT ${repoPath}/pulls/${pull}/merge`;
148
207
  case 'update_pull_request_branch.':
@@ -154,7 +213,7 @@ function githubOperationRoute(toolId, method, args) {
154
213
  case 'pull_request_review_write.delete_pending':
155
214
  return `DELETE ${repoPath}/pulls/${pull}/reviews/{review_id}`;
156
215
  case 'add_comment_to_pending_review.':
157
- return `POST ${repoPath}/pulls/${pull}/comments`;
216
+ return GITHUB_GRAPHQL_ROUTE;
158
217
  case 'actions_list.list_workflows':
159
218
  return `GET ${repoPath}/actions/workflows`;
160
219
  case 'actions_list.list_workflow_runs':
@@ -170,7 +229,7 @@ function githubOperationRoute(toolId, method, args) {
170
229
  case 'actions_get.get_workflow_job':
171
230
  return `GET ${repoPath}/actions/jobs/${resource}`;
172
231
  case 'actions_get.download_workflow_run_artifact':
173
- return `GET ${repoPath}/actions/artifacts/${resource}/{archive_format}`;
232
+ return GITHUB_ARTIFACT_DOWNLOAD_ROUTE;
174
233
  case 'actions_get.get_workflow_run_usage':
175
234
  return `GET ${repoPath}/actions/runs/${resource}/timing`;
176
235
  case 'actions_get.get_workflow_run_logs_url':
@@ -191,7 +250,54 @@ function githubOperationRoute(toolId, method, args) {
191
250
  return undefined;
192
251
  }
193
252
  }
194
- function projectGithubOperationParameters(toolId, method, args) {
253
+ async function addCommentToPendingReview(client, args) {
254
+ if (client.graphql === undefined) {
255
+ throw new GithubIntegrationProviderError('malformed-provider-response', 'GitHub client does not support GraphQL operations');
256
+ }
257
+ const reviewLookup = await client.graphql(LATEST_PENDING_REVIEW_QUERY, {
258
+ owner: args.owner,
259
+ repo: args.repo,
260
+ pullNumber: args.pull_number
261
+ });
262
+ const reviewId = latestPendingReviewNodeId(reviewLookup);
263
+ if (reviewId === undefined) return undefined;
264
+ const input = {
265
+ pullRequestReviewId: reviewId,
266
+ path: args.path,
267
+ body: args.body,
268
+ subjectType: args.subject_type
269
+ };
270
+ if (args.line !== undefined) input.line = args.line;
271
+ if (args.side !== undefined) input.side = args.side;
272
+ if (args.start_line !== undefined) input.startLine = args.start_line;
273
+ if (args.start_side !== undefined) input.startSide = args.start_side;
274
+ return await client.graphql(ADD_PENDING_REVIEW_COMMENT_MUTATION, {
275
+ input
276
+ });
277
+ }
278
+ function latestPendingReviewNodeId(data) {
279
+ if (!isRecord(data)) return undefined;
280
+ const viewer = isRecord(data.viewer) ? data.viewer.login : undefined;
281
+ if (typeof viewer !== 'string') return undefined;
282
+ const repository = isRecord(data.repository) ? data.repository : undefined;
283
+ const pullRequest = repository && isRecord(repository.pullRequest) ? repository.pullRequest : undefined;
284
+ const reviews = pullRequest && isRecord(pullRequest.reviews) ? pullRequest.reviews : undefined;
285
+ const nodes = reviews && Array.isArray(reviews.nodes) ? reviews.nodes : [];
286
+ let latest;
287
+ for (const node of nodes){
288
+ if (!isRecord(node)) continue;
289
+ const author = isRecord(node.author) ? node.author.login : undefined;
290
+ const id = node.id;
291
+ const createdAt = node.createdAt;
292
+ if (author !== viewer || typeof id !== 'string' || typeof createdAt !== 'string') continue;
293
+ if (latest === undefined || createdAt > latest.createdAt) latest = {
294
+ createdAt,
295
+ id
296
+ };
297
+ }
298
+ return latest?.id;
299
+ }
300
+ export function projectGithubOperationParameters(toolId, method, args) {
195
301
  const parameters = {
196
302
  ...args
197
303
  };
@@ -207,8 +313,48 @@ function projectGithubOperationParameters(toolId, method, args) {
207
313
  }
208
314
  return parameters;
209
315
  }
210
- function githubToolResult(toolId, data) {
211
- const structuredContent = projectGithubToolOutput(toolId, data);
316
+ async function resolvePendingReviewParameters(client, parameters, toolId, method) {
317
+ if (!isPendingReviewOperation(toolId, method)) return parameters;
318
+ const reviewId = await latestPendingReviewId(client, parameters);
319
+ return reviewId === undefined ? undefined : {
320
+ ...parameters,
321
+ review_id: reviewId
322
+ };
323
+ }
324
+ function isPendingReviewOperation(toolId, method) {
325
+ return toolId === 'pull_request_review_write' && (method === 'submit_pending' || method === 'delete_pending');
326
+ }
327
+ async function latestPendingReviewId(client, parameters) {
328
+ const perPage = 100;
329
+ let page = 1;
330
+ let reviewId;
331
+ while(true){
332
+ const response = await client.request('GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews', {
333
+ owner: parameters.owner,
334
+ repo: parameters.repo,
335
+ pull_number: parameters.pull_number,
336
+ per_page: perPage,
337
+ page
338
+ });
339
+ if (!Array.isArray(response.data)) return undefined;
340
+ reviewId = latestPendingReviewIdOnPage(response.data) ?? reviewId;
341
+ if (response.data.length < perPage) return reviewId;
342
+ page += 1;
343
+ }
344
+ }
345
+ function latestPendingReviewIdOnPage(data) {
346
+ for(let index = data.length - 1; index >= 0; index -= 1){
347
+ const review = data[index];
348
+ if (!isRecord(review) || review.state !== 'PENDING') continue;
349
+ if (typeof review.id === 'number' && Number.isSafeInteger(review.id)) return review.id;
350
+ }
351
+ return undefined;
352
+ }
353
+ function githubToolResult(toolId, data, response, parameters, route) {
354
+ const structuredContent = projectGithubToolOutput(toolId, data, response, parameters, route);
355
+ if (structuredContent === undefined) {
356
+ return githubToolError('GitHub artifact download did not return a download URL');
357
+ }
212
358
  return {
213
359
  content: [
214
360
  {
@@ -219,7 +365,10 @@ function githubToolResult(toolId, data) {
219
365
  structuredContent
220
366
  };
221
367
  }
222
- function projectGithubToolOutput(toolId, data) {
368
+ function projectGithubToolOutput(toolId, data, response, parameters, route) {
369
+ if (route === GITHUB_ARTIFACT_DOWNLOAD_ROUTE) {
370
+ return projectGithubArtifactDownloadOutput(response, parameters);
371
+ }
223
372
  switch(toolId){
224
373
  case 'list_issue_types':
225
374
  return {
@@ -256,6 +405,22 @@ function projectGithubToolOutput(toolId, data) {
256
405
  };
257
406
  }
258
407
  }
408
+ function projectGithubArtifactDownloadOutput(response, parameters) {
409
+ if (response === undefined) return undefined;
410
+ const downloadUrl = response.headers?.location;
411
+ if (typeof downloadUrl !== 'string' || downloadUrl.length === 0) return undefined;
412
+ const output = {
413
+ archive_format: GITHUB_ARTIFACT_ARCHIVE_FORMAT,
414
+ download_url: downloadUrl
415
+ };
416
+ if (typeof parameters?.resource_id === 'string') output.artifact_id = parameters.resource_id;
417
+ const contentType = response.headers?.['content-type'];
418
+ if (typeof contentType === 'string') output.content_type = contentType;
419
+ const contentLength = response.headers?.['content-length'];
420
+ const sizeBytes = typeof contentLength === 'number' ? contentLength : Number(contentLength);
421
+ if (Number.isSafeInteger(sizeBytes) && sizeBytes >= 0) output.size_bytes = sizeBytes;
422
+ return output;
423
+ }
259
424
  function githubSearchItems(data) {
260
425
  return isRecord(data) ? data.items : data;
261
426
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/agent-tools.ts"],"sourcesContent":["import type {\n AgentToolCallInput,\n AgentToolCatalogEntry,\n AgentToolSelectionCatalog,\n AgentToolSession,\n AgentToolsProvider,\n IntegrationConnection,\n OpenAgentToolsSessionInput,\n} from '@shipfox/api-integration-spi';\nimport {Octokit} from 'octokit';\nimport {\n createGithubInstallationTokenProvider,\n type GithubInstallationTokenProvider,\n} from '#api/installation-token-provider.js';\nimport {normalizedGithubApiBaseUrl} from '#config.js';\nimport type {GithubInstallation} from '#db/installations.js';\nimport {GithubIntegrationProviderError} from './errors.js';\nimport {\n type GithubAgentToolCatalogEntry,\n type GithubAgentToolId,\n type GithubAgentToolRequiredScope,\n githubAgentToolCatalog,\n githubAgentToolSelectionCatalog,\n} from './github-agent-tool-catalog.js';\n\nexport type {\n GithubAgentToolCatalogEntry,\n GithubAgentToolCategory,\n GithubAgentToolId,\n GithubAgentToolPermission,\n GithubAgentToolPermissionAccess,\n GithubAgentToolRequiredPermission,\n GithubAgentToolRequiredScope,\n GithubAgentToolSensitivity,\n} from './github-agent-tool-catalog.js';\nexport {\n buildGithubAgentToolSelectionCatalog,\n DEFAULT_JOB_LOG_TAIL_LINES,\n githubAgentToolCatalog,\n githubAgentToolSelectionCatalog,\n} from './github-agent-tool-catalog.js';\n\ntype GithubIntegrationConnection = IntegrationConnection<'github'>;\n\ntype GithubToolCallResult = {\n isError?: boolean | undefined;\n content: readonly {type: 'text'; text: string}[];\n structuredContent?: Record<string, unknown> | undefined;\n};\n\nexport class GithubAgentToolsProvider\n implements\n AgentToolsProvider<\n GithubIntegrationConnection,\n GithubAgentToolRequiredScope,\n unknown,\n GithubToolCallResult\n >\n{\n private readonly tokenProvider: GithubInstallationTokenProvider;\n\n constructor(private readonly options: GithubAgentToolsProviderOptions = {}) {\n this.tokenProvider = options.tokenProvider ?? createGithubInstallationTokenProvider();\n }\n\n catalog(): readonly GithubAgentToolCatalogEntry[] {\n return githubAgentToolCatalog;\n }\n\n selectionCatalog(): AgentToolSelectionCatalog {\n return githubAgentToolSelectionCatalog;\n }\n\n async openSession(\n input: OpenAgentToolsSessionInput<GithubIntegrationConnection, GithubAgentToolRequiredScope>,\n ): Promise<AgentToolSession<GithubToolCallResult>> {\n const installation = await this.options.getInstallationByConnectionId?.(input.connection.id);\n if (!installation) {\n throw new GithubIntegrationProviderError(\n 'installation-not-found',\n 'GitHub installation is not connected to this integration',\n );\n }\n const installationId = Number(installation.installationId);\n if (!Number.isSafeInteger(installationId) || installationId < 1) {\n throw new GithubIntegrationProviderError(\n 'malformed-provider-response',\n 'GitHub installation has an invalid installation ID',\n );\n }\n let tokenPromise:\n | ReturnType<GithubInstallationTokenProvider['getInstallationAccessToken']>\n | undefined;\n\n return {\n call: async (call) => {\n const tool = input.tools.find((candidate) => candidate.id === call.toolId);\n if (!tool) return githubToolError(`Unknown GitHub tool: ${call.toolId}`);\n const operation = resolveGithubOperation(tool, call);\n if (operation === undefined) return githubToolError('Unknown GitHub tool operation');\n const validationError = validateGithubToolArguments(tool, call.arguments);\n if (validationError) return githubToolError(validationError);\n tokenPromise ??= this.tokenProvider.getInstallationAccessToken(installationId);\n const token = await tokenPromise;\n if (!hasGrantedPermissions(token.permissions ?? {}, tool, call)) {\n return githubToolError(\n 'GitHub installation token is missing permission for this operation',\n );\n }\n const client = (this.options.createClient ?? createOctokitClient)(token.token);\n\n try {\n const response = await client.request(operation.route, operation.parameters);\n return githubToolResult(tool.id as GithubAgentToolId, response.data);\n } catch (error) {\n if (error instanceof GithubIntegrationProviderError)\n return githubToolError(error.message);\n throw error;\n }\n },\n };\n }\n}\n\nexport interface GithubAgentToolsProviderOptions {\n getInstallationByConnectionId?:\n | ((connectionId: string) => Promise<GithubInstallation | undefined>)\n | undefined;\n tokenProvider?: GithubInstallationTokenProvider | undefined;\n createClient?: GithubToolClientFactory | undefined;\n}\n\nexport interface GithubToolClient {\n request(route: string, parameters: Record<string, unknown>): Promise<{data: unknown}>;\n}\n\nexport type GithubToolClientFactory = (token: string) => GithubToolClient;\n\ninterface GithubToolOperation {\n route: string;\n parameters: Record<string, unknown>;\n}\n\nfunction createOctokitClient(token: string): GithubToolClient {\n const octokit = new Octokit({\n auth: token,\n baseUrl: normalizedGithubApiBaseUrl(),\n retry: {enabled: false},\n });\n return {\n request: async (route, parameters) => await octokit.request(route, parameters),\n };\n}\n\nfunction resolveGithubOperation(\n tool: AgentToolCatalogEntry<GithubAgentToolRequiredScope>,\n call: AgentToolCallInput,\n): GithubToolOperation | undefined {\n const args = call.arguments;\n const method = typeof args.method === 'string' ? args.method : undefined;\n const params = {...args};\n delete params.method;\n\n if (tool.methods && !tool.methods.some((candidate) => candidate.id === method)) return undefined;\n\n const toolId = tool.id as GithubAgentToolId;\n const route = githubOperationRoute(toolId, method, params);\n return route === undefined\n ? undefined\n : {route, parameters: projectGithubOperationParameters(toolId, method, params)};\n}\n\nfunction githubOperationRoute(\n toolId: GithubAgentToolId,\n method: string | undefined,\n args: Record<string, unknown>,\n): string | undefined {\n const owner = '{owner}';\n const repo = '{repo}';\n const issue = '{issue_number}';\n const pull = '{pull_number}';\n const run = '{run_id}';\n const resource = '{resource_id}';\n const repoPath = `/repos/${owner}/${repo}`;\n\n switch (`${toolId}.${method ?? ''}`) {\n case 'issue_read.get':\n return `GET ${repoPath}/issues/${issue}`;\n case 'issue_read.get_comments':\n return `GET ${repoPath}/issues/${issue}/comments`;\n case 'issue_read.get_sub_issues':\n return `GET ${repoPath}/issues/${issue}/sub_issues`;\n case 'issue_read.get_parent':\n return `GET ${repoPath}/issues/${issue}/parent`;\n case 'issue_read.get_labels':\n return `GET ${repoPath}/issues/${issue}/labels`;\n case 'list_issue_types.':\n return args.repo === undefined\n ? 'GET /orgs/{owner}/issue-types'\n : `GET ${repoPath}/issue-types`;\n case 'list_issues.':\n return `GET ${repoPath}/issues`;\n case 'search_issues.':\n return 'GET /search/issues';\n case 'add_issue_comment.':\n if (args.comment_id !== undefined)\n return `POST ${repoPath}/issues/comments/{comment_id}/reactions`;\n return args.reaction !== undefined && args.body === undefined\n ? `POST ${repoPath}/issues/${issue}/reactions`\n : `POST ${repoPath}/issues/${issue}/comments`;\n case 'issue_write.create':\n return `POST ${repoPath}/issues`;\n case 'issue_write.update':\n return `PATCH ${repoPath}/issues/${issue}`;\n case 'sub_issue_write.add':\n return `POST ${repoPath}/issues/${issue}/sub_issues`;\n case 'sub_issue_write.remove':\n return `DELETE ${repoPath}/issues/${issue}/sub_issues/{sub_issue_id}`;\n case 'sub_issue_write.reprioritize':\n return `PATCH ${repoPath}/issues/${issue}/sub_issues/{sub_issue_id}`;\n case 'pull_request_read.get':\n return `GET ${repoPath}/pulls/${pull}`;\n case 'pull_request_read.get_diff':\n return `GET ${repoPath}/pulls/${pull}`;\n case 'pull_request_read.get_status':\n return `GET ${repoPath}/commits/{ref}/status`;\n case 'pull_request_read.get_files':\n return `GET ${repoPath}/pulls/${pull}/files`;\n case 'pull_request_read.get_commits':\n return `GET ${repoPath}/pulls/${pull}/commits`;\n case 'pull_request_read.get_review_comments':\n return `GET ${repoPath}/pulls/${pull}/comments`;\n case 'pull_request_read.get_reviews':\n return `GET ${repoPath}/pulls/${pull}/reviews`;\n case 'pull_request_read.get_comments':\n return `GET ${repoPath}/issues/${pull}/comments`;\n case 'pull_request_read.get_check_runs':\n return `GET ${repoPath}/commits/{ref}/check-runs`;\n case 'list_pull_requests.':\n return `GET ${repoPath}/pulls`;\n case 'search_pull_requests.':\n return 'GET /search/issues';\n case 'create_pull_request.':\n return `POST ${repoPath}/pulls`;\n case 'update_pull_request.':\n return `PATCH ${repoPath}/pulls/${pull}`;\n case 'add_reply_to_pull_request_comment.':\n return `POST ${repoPath}/pulls/{comment_id}/replies`;\n case 'merge_pull_request.':\n return `PUT ${repoPath}/pulls/${pull}/merge`;\n case 'update_pull_request_branch.':\n return `PUT ${repoPath}/pulls/${pull}/update-branch`;\n case 'pull_request_review_write.create':\n return `POST ${repoPath}/pulls/${pull}/reviews`;\n case 'pull_request_review_write.submit_pending':\n return `POST ${repoPath}/pulls/${pull}/reviews/{review_id}/events`;\n case 'pull_request_review_write.delete_pending':\n return `DELETE ${repoPath}/pulls/${pull}/reviews/{review_id}`;\n case 'add_comment_to_pending_review.':\n return `POST ${repoPath}/pulls/${pull}/comments`;\n case 'actions_list.list_workflows':\n return `GET ${repoPath}/actions/workflows`;\n case 'actions_list.list_workflow_runs':\n return `GET ${repoPath}/actions/workflows/${resource}/runs`;\n case 'actions_list.list_workflow_jobs':\n return `GET ${repoPath}/actions/runs/${resource}/jobs`;\n case 'actions_list.list_workflow_run_artifacts':\n return `GET ${repoPath}/actions/runs/${resource}/artifacts`;\n case 'actions_get.get_workflow':\n return `GET ${repoPath}/actions/workflows/${resource}`;\n case 'actions_get.get_workflow_run':\n return `GET ${repoPath}/actions/runs/${resource}`;\n case 'actions_get.get_workflow_job':\n return `GET ${repoPath}/actions/jobs/${resource}`;\n case 'actions_get.download_workflow_run_artifact':\n return `GET ${repoPath}/actions/artifacts/${resource}/{archive_format}`;\n case 'actions_get.get_workflow_run_usage':\n return `GET ${repoPath}/actions/runs/${resource}/timing`;\n case 'actions_get.get_workflow_run_logs_url':\n return `GET ${repoPath}/actions/runs/${resource}/logs`;\n case 'actions_run_trigger.run_workflow':\n return `POST ${repoPath}/actions/workflows/{workflow_id}/dispatches`;\n case 'actions_run_trigger.rerun_workflow_run':\n return `POST ${repoPath}/actions/runs/${run}/rerun`;\n case 'actions_run_trigger.rerun_failed_jobs':\n return `POST ${repoPath}/actions/runs/${run}/rerun-failed-jobs`;\n case 'actions_run_trigger.cancel_workflow_run':\n return `POST ${repoPath}/actions/runs/${run}/cancel`;\n case 'actions_run_trigger.delete_workflow_run_logs':\n return `DELETE ${repoPath}/actions/runs/${run}/logs`;\n case 'get_job_logs.':\n return `GET ${repoPath}/actions/jobs/{job_id}/logs`;\n default:\n return undefined;\n }\n}\n\nfunction projectGithubOperationParameters(\n toolId: GithubAgentToolId,\n method: string | undefined,\n args: Record<string, unknown>,\n): Record<string, unknown> {\n const parameters = {...args};\n if (toolId === 'add_issue_comment' && parameters.reaction !== undefined) {\n parameters.content = parameters.reaction;\n delete parameters.reaction;\n if (parameters.body === undefined) delete parameters.body;\n }\n if (toolId === 'pull_request_read' && method === 'get_diff') {\n parameters.headers = {accept: 'application/vnd.github.diff'};\n }\n return parameters;\n}\n\nfunction githubToolResult(toolId: GithubAgentToolId, data: unknown): GithubToolCallResult {\n const structuredContent = projectGithubToolOutput(toolId, data);\n return {\n content: [{type: 'text', text: JSON.stringify(structuredContent)}],\n structuredContent,\n };\n}\n\nfunction projectGithubToolOutput(\n toolId: GithubAgentToolId,\n data: unknown,\n): Record<string, unknown> {\n switch (toolId) {\n case 'list_issue_types':\n return {issue_types: data};\n case 'list_issues':\n return {issues: data};\n case 'search_issues':\n return {issues: githubSearchItems(data)};\n case 'list_pull_requests':\n return {pull_requests: data};\n case 'search_pull_requests':\n return {pull_requests: githubSearchItems(data)};\n case 'create_pull_request':\n case 'update_pull_request':\n return {pull_request: data};\n case 'merge_pull_request':\n return {merge: data};\n default:\n return isRecord(data) ? data : {result: data};\n }\n}\n\nfunction githubSearchItems(data: unknown): unknown {\n return isRecord(data) ? data.items : data;\n}\n\nfunction githubToolError(message: string): GithubToolCallResult {\n return {isError: true, content: [{type: 'text', text: message}]};\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction validateGithubToolArguments(\n tool: AgentToolCatalogEntry<GithubAgentToolRequiredScope>,\n arguments_: Record<string, unknown>,\n): string | undefined {\n const required = Array.isArray(tool.inputSchema.required) ? tool.inputSchema.required : [];\n for (const name of required) {\n if (typeof name === 'string' && arguments_[name] === undefined) {\n return `Missing required parameter: ${name}`;\n }\n }\n\n const methodRequired = methodRequiredParameters(tool.inputSchema, arguments_);\n for (const name of methodRequired) {\n if (arguments_[name] === undefined) return `Missing required parameter: ${name}`;\n }\n\n const properties = tool.inputSchema.properties;\n if (typeof properties !== 'object' || properties === null || Array.isArray(properties)) {\n return undefined;\n }\n const propertySchemas = properties as Record<string, unknown>;\n for (const [name, value] of Object.entries(arguments_)) {\n const schema = propertySchemas[name];\n if (typeof schema !== 'object' || schema === null || Array.isArray(schema)) continue;\n const type = (schema as {type?: unknown}).type;\n if (type === 'integer' && (!Number.isInteger(value) || typeof value !== 'number')) {\n return `Parameter ${name} must be an integer`;\n }\n if (type === 'array' && !Array.isArray(value)) return `Parameter ${name} must be an array`;\n }\n return undefined;\n}\n\nfunction methodRequiredParameters(\n inputSchema: AgentToolCatalogEntry<GithubAgentToolRequiredScope>['inputSchema'],\n arguments_: Record<string, unknown>,\n): string[] {\n const method = arguments_.method;\n if (typeof method !== 'string' || !Array.isArray(inputSchema.oneOf)) return [];\n\n for (const candidate of inputSchema.oneOf) {\n if (!isRecord(candidate) || !isRecord(candidate.properties)) continue;\n const methodSchema = candidate.properties.method;\n if (!isRecord(methodSchema) || methodSchema.const !== method) continue;\n return Array.isArray(candidate.required)\n ? candidate.required.filter((name): name is string => typeof name === 'string')\n : [];\n }\n\n return [];\n}\n\nfunction hasGrantedPermissions(\n granted: Record<string, 'read' | 'write' | 'admin'>,\n tool: AgentToolCatalogEntry<GithubAgentToolRequiredScope>,\n call: AgentToolCallInput,\n): boolean {\n const method = typeof call.arguments.method === 'string' ? call.arguments.method : undefined;\n const required =\n tool.methods?.find((candidate) => candidate.id === method)?.requiredScope ?? tool.requiredScope;\n return required.every(({permission, access}) => {\n const actual = granted[permission];\n return actual === 'write' || actual === 'admin' || actual === access;\n });\n}\n"],"names":["Octokit","createGithubInstallationTokenProvider","normalizedGithubApiBaseUrl","GithubIntegrationProviderError","githubAgentToolCatalog","githubAgentToolSelectionCatalog","buildGithubAgentToolSelectionCatalog","DEFAULT_JOB_LOG_TAIL_LINES","GithubAgentToolsProvider","options","tokenProvider","catalog","selectionCatalog","openSession","input","installation","getInstallationByConnectionId","connection","id","installationId","Number","isSafeInteger","tokenPromise","call","tool","tools","find","candidate","toolId","githubToolError","operation","resolveGithubOperation","undefined","validationError","validateGithubToolArguments","arguments","getInstallationAccessToken","token","hasGrantedPermissions","permissions","client","createClient","createOctokitClient","response","request","route","parameters","githubToolResult","data","error","message","octokit","auth","baseUrl","retry","enabled","args","method","params","methods","some","githubOperationRoute","projectGithubOperationParameters","owner","repo","issue","pull","run","resource","repoPath","comment_id","reaction","body","content","headers","accept","structuredContent","projectGithubToolOutput","type","text","JSON","stringify","issue_types","issues","githubSearchItems","pull_requests","pull_request","merge","isRecord","result","items","isError","value","Array","isArray","arguments_","required","inputSchema","name","methodRequired","methodRequiredParameters","properties","propertySchemas","Object","entries","schema","isInteger","oneOf","methodSchema","const","filter","granted","requiredScope","every","permission","access","actual"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/agent-tools.ts"],"sourcesContent":["import type {\n AgentToolCallInput,\n AgentToolCatalogEntry,\n AgentToolSelectionCatalog,\n AgentToolSession,\n AgentToolsProvider,\n IntegrationConnection,\n OpenAgentToolsSessionInput,\n} from '@shipfox/api-integration-spi';\nimport {Octokit} from 'octokit';\nimport {mapGithubError} from '#api/client.js';\nimport {\n createGithubInstallationTokenProvider,\n type GithubInstallationTokenProvider,\n} from '#api/installation-token-provider.js';\nimport {normalizedGithubApiBaseUrl} from '#config.js';\nimport type {GithubInstallation} from '#db/installations.js';\nimport {GithubIntegrationProviderError} from './errors.js';\nimport {\n type GithubAgentToolCatalogEntry,\n type GithubAgentToolId,\n type GithubAgentToolRequiredScope,\n githubAgentToolCatalog,\n githubAgentToolSelectionCatalog,\n} from './github-agent-tool-catalog.js';\n\nexport type {\n GithubAgentToolCatalogEntry,\n GithubAgentToolCategory,\n GithubAgentToolId,\n GithubAgentToolPermission,\n GithubAgentToolPermissionAccess,\n GithubAgentToolRequiredPermission,\n GithubAgentToolRequiredScope,\n GithubAgentToolSensitivity,\n} from './github-agent-tool-catalog.js';\nexport {\n buildGithubAgentToolSelectionCatalog,\n DEFAULT_JOB_LOG_TAIL_LINES,\n githubAgentToolCatalog,\n githubAgentToolSelectionCatalog,\n} from './github-agent-tool-catalog.js';\n\ntype GithubIntegrationConnection = IntegrationConnection<'github'>;\n\ntype GithubToolCallResult = {\n isError?: boolean | undefined;\n content: readonly {type: 'text'; text: string}[];\n structuredContent?: Record<string, unknown> | undefined;\n};\n\nconst GITHUB_GRAPHQL_ROUTE = 'POST /graphql';\nconst GITHUB_ARTIFACT_ARCHIVE_FORMAT = 'zip';\nconst GITHUB_ARTIFACT_DOWNLOAD_ROUTE = `GET /repos/{owner}/{repo}/actions/artifacts/{resource_id}/${GITHUB_ARTIFACT_ARCHIVE_FORMAT}`;\nconst GITHUB_ARTIFACT_DOWNLOAD_TIMEOUT_MS = 30_000;\nconst NO_PENDING_REVIEW_MESSAGE =\n 'No pending pull request review found for the authenticated GitHub user.';\n\nconst LATEST_PENDING_REVIEW_QUERY = `\n query LatestPendingPullRequestReview($owner: String!, $repo: String!, $pullNumber: Int!) {\n viewer {\n login\n }\n repository(owner: $owner, name: $repo) {\n pullRequest(number: $pullNumber) {\n reviews(last: 100, states: [PENDING]) {\n nodes {\n id\n author {\n login\n }\n createdAt\n }\n }\n }\n }\n }\n`;\n\nconst ADD_PENDING_REVIEW_COMMENT_MUTATION = `\n mutation AddCommentToPendingReview($input: AddPullRequestReviewThreadInput!) {\n addPullRequestReviewThread(input: $input) {\n thread {\n id\n }\n }\n }\n`;\n\nexport class GithubAgentToolsProvider\n implements\n AgentToolsProvider<\n GithubIntegrationConnection,\n GithubAgentToolRequiredScope,\n unknown,\n GithubToolCallResult\n >\n{\n private readonly tokenProvider: GithubInstallationTokenProvider;\n\n constructor(private readonly options: GithubAgentToolsProviderOptions = {}) {\n this.tokenProvider = options.tokenProvider ?? createGithubInstallationTokenProvider();\n }\n\n catalog(): readonly GithubAgentToolCatalogEntry[] {\n return githubAgentToolCatalog;\n }\n\n selectionCatalog(): AgentToolSelectionCatalog {\n return githubAgentToolSelectionCatalog;\n }\n\n async openSession(\n input: OpenAgentToolsSessionInput<GithubIntegrationConnection, GithubAgentToolRequiredScope>,\n ): Promise<AgentToolSession<GithubToolCallResult>> {\n const installation = await this.options.getInstallationByConnectionId?.(input.connection.id);\n if (!installation) {\n throw new GithubIntegrationProviderError(\n 'installation-not-found',\n 'GitHub installation is not connected to this integration',\n );\n }\n const installationId = Number(installation.installationId);\n if (!Number.isSafeInteger(installationId) || installationId < 1) {\n throw new GithubIntegrationProviderError(\n 'malformed-provider-response',\n 'GitHub installation has an invalid installation ID',\n );\n }\n let tokenPromise:\n | ReturnType<GithubInstallationTokenProvider['getInstallationAccessToken']>\n | undefined;\n\n return {\n call: async (call) => {\n const tool = input.tools.find((candidate) => candidate.id === call.toolId);\n if (!tool) return githubToolError(`Unknown GitHub tool: ${call.toolId}`);\n const operation = resolveGithubOperation(tool, call);\n if (operation === undefined) return githubToolError('Unknown GitHub tool operation');\n const validationError = validateGithubToolArguments(tool, call.arguments);\n if (validationError) return githubToolError(validationError);\n tokenPromise ??= this.tokenProvider.getInstallationAccessToken(installationId);\n const token = await tokenPromise;\n if (!hasGrantedPermissions(token.permissions ?? {}, tool, call)) {\n return githubToolError(\n 'GitHub installation token is missing permission for this operation',\n );\n }\n const client = (this.options.createClient ?? createOctokitClient)(token.token);\n const method =\n typeof call.arguments.method === 'string' ? call.arguments.method : undefined;\n\n if (operation.kind === 'graphql') {\n const data = await mapGithubError(() =>\n addCommentToPendingReview(client, operation.parameters),\n );\n return data === undefined\n ? githubToolError(NO_PENDING_REVIEW_MESSAGE)\n : githubToolResult(tool.id as GithubAgentToolId, data);\n }\n\n const operationParameters = await mapGithubError(() =>\n resolvePendingReviewParameters(\n client,\n operation.parameters,\n tool.id as GithubAgentToolId,\n method,\n ),\n );\n if (operationParameters === undefined) {\n return githubToolError(NO_PENDING_REVIEW_MESSAGE);\n }\n const response = await mapGithubError(() =>\n client.request(operation.route, operationParameters),\n );\n return githubToolResult(\n tool.id as GithubAgentToolId,\n response.data,\n response,\n operationParameters,\n operation.route,\n );\n },\n };\n }\n}\n\nexport interface GithubAgentToolsProviderOptions {\n getInstallationByConnectionId?:\n | ((connectionId: string) => Promise<GithubInstallation | undefined>)\n | undefined;\n tokenProvider?: GithubInstallationTokenProvider | undefined;\n createClient?: GithubToolClientFactory | undefined;\n}\n\nexport interface GithubToolResponse {\n data: unknown;\n headers?: Record<string, string | number | undefined> | undefined;\n status?: number | undefined;\n url?: string | undefined;\n}\n\nexport interface GithubToolClient {\n request(route: string, parameters: Record<string, unknown>): Promise<GithubToolResponse>;\n graphql?: ((query: string, variables: Record<string, unknown>) => Promise<unknown>) | undefined;\n}\n\nexport type GithubToolClientFactory = (token: string) => GithubToolClient;\n\ninterface GithubToolOperation {\n route: string;\n parameters: Record<string, unknown>;\n kind: 'rest' | 'graphql';\n}\n\nfunction createOctokitClient(token: string): GithubToolClient {\n const octokit = new Octokit({\n auth: token,\n baseUrl: normalizedGithubApiBaseUrl(),\n retry: {enabled: false},\n });\n return {\n request: async (route, parameters) => {\n if (route !== GITHUB_ARTIFACT_DOWNLOAD_ROUTE) {\n return await octokit.request(route, parameters);\n }\n\n const abortController = new AbortController();\n const timeout = setTimeout(\n () => abortController.abort(),\n GITHUB_ARTIFACT_DOWNLOAD_TIMEOUT_MS,\n );\n try {\n return await octokit.request(route, {\n ...parameters,\n request: {\n redirect: 'manual',\n parseSuccessResponseBody: false,\n signal: abortController.signal,\n },\n });\n } finally {\n clearTimeout(timeout);\n }\n },\n graphql: async (query, variables) => await octokit.graphql(query, variables),\n };\n}\n\nfunction resolveGithubOperation(\n tool: AgentToolCatalogEntry<GithubAgentToolRequiredScope>,\n call: AgentToolCallInput,\n): GithubToolOperation | undefined {\n const args = call.arguments;\n const method = typeof args.method === 'string' ? args.method : undefined;\n const params = {...args};\n delete params.method;\n\n if (tool.methods && !tool.methods.some((candidate) => candidate.id === method)) return undefined;\n\n const toolId = tool.id as GithubAgentToolId;\n const route = githubOperationRoute(toolId, method, params);\n return route === undefined\n ? undefined\n : {\n route,\n parameters: projectGithubOperationParameters(toolId, method, params),\n kind: route === GITHUB_GRAPHQL_ROUTE ? 'graphql' : 'rest',\n };\n}\n\nexport function githubOperationRoute(\n toolId: GithubAgentToolId,\n method: string | undefined,\n args: Record<string, unknown>,\n): string | undefined {\n const owner = '{owner}';\n const repo = '{repo}';\n const issue = '{issue_number}';\n const pull = '{pull_number}';\n const run = '{run_id}';\n const resource = '{resource_id}';\n const repoPath = `/repos/${owner}/${repo}`;\n\n switch (`${toolId}.${method ?? ''}`) {\n case 'issue_read.get':\n return `GET ${repoPath}/issues/${issue}`;\n case 'issue_read.get_comments':\n return `GET ${repoPath}/issues/${issue}/comments`;\n case 'issue_read.get_sub_issues':\n return `GET ${repoPath}/issues/${issue}/sub_issues`;\n case 'issue_read.get_parent':\n return `GET ${repoPath}/issues/${issue}/parent`;\n case 'issue_read.get_labels':\n return `GET ${repoPath}/issues/${issue}/labels`;\n case 'list_issue_types.':\n return args.repo === undefined\n ? 'GET /orgs/{owner}/issue-types'\n : `GET ${repoPath}/issue-types`;\n case 'list_issues.':\n return `GET ${repoPath}/issues`;\n case 'search_issues.':\n return 'GET /search/issues';\n case 'add_issue_comment.':\n if (args.comment_id !== undefined)\n return `POST ${repoPath}/issues/comments/{comment_id}/reactions`;\n return args.reaction !== undefined && args.body === undefined\n ? `POST ${repoPath}/issues/${issue}/reactions`\n : `POST ${repoPath}/issues/${issue}/comments`;\n case 'issue_write.create':\n return `POST ${repoPath}/issues`;\n case 'issue_write.update':\n return `PATCH ${repoPath}/issues/${issue}`;\n case 'sub_issue_write.add':\n return `POST ${repoPath}/issues/${issue}/sub_issues`;\n case 'sub_issue_write.remove':\n return `DELETE ${repoPath}/issues/${issue}/sub_issues/{sub_issue_id}`;\n case 'sub_issue_write.reprioritize':\n return `PATCH ${repoPath}/issues/${issue}/sub_issues/priority`;\n case 'pull_request_read.get':\n return `GET ${repoPath}/pulls/${pull}`;\n case 'pull_request_read.get_diff':\n return `GET ${repoPath}/pulls/${pull}`;\n case 'pull_request_read.get_status':\n return `GET ${repoPath}/commits/{ref}/status`;\n case 'pull_request_read.get_files':\n return `GET ${repoPath}/pulls/${pull}/files`;\n case 'pull_request_read.get_commits':\n return `GET ${repoPath}/pulls/${pull}/commits`;\n case 'pull_request_read.get_review_comments':\n return `GET ${repoPath}/pulls/${pull}/comments`;\n case 'pull_request_read.get_reviews':\n return `GET ${repoPath}/pulls/${pull}/reviews`;\n case 'pull_request_read.get_comments':\n return `GET ${repoPath}/issues/${pull}/comments`;\n case 'pull_request_read.get_check_runs':\n return `GET ${repoPath}/commits/{ref}/check-runs`;\n case 'list_pull_requests.':\n return `GET ${repoPath}/pulls`;\n case 'search_pull_requests.':\n return 'GET /search/issues';\n case 'create_pull_request.':\n return `POST ${repoPath}/pulls`;\n case 'update_pull_request.':\n return `PATCH ${repoPath}/pulls/${pull}`;\n case 'add_reply_to_pull_request_comment.':\n return args.reaction !== undefined && args.body === undefined\n ? `POST ${repoPath}/pulls/comments/{comment_id}/reactions`\n : `POST ${repoPath}/pulls/${pull}/comments/{comment_id}/replies`;\n case 'merge_pull_request.':\n return `PUT ${repoPath}/pulls/${pull}/merge`;\n case 'update_pull_request_branch.':\n return `PUT ${repoPath}/pulls/${pull}/update-branch`;\n case 'pull_request_review_write.create':\n return `POST ${repoPath}/pulls/${pull}/reviews`;\n case 'pull_request_review_write.submit_pending':\n return `POST ${repoPath}/pulls/${pull}/reviews/{review_id}/events`;\n case 'pull_request_review_write.delete_pending':\n return `DELETE ${repoPath}/pulls/${pull}/reviews/{review_id}`;\n case 'add_comment_to_pending_review.':\n return GITHUB_GRAPHQL_ROUTE;\n case 'actions_list.list_workflows':\n return `GET ${repoPath}/actions/workflows`;\n case 'actions_list.list_workflow_runs':\n return `GET ${repoPath}/actions/workflows/${resource}/runs`;\n case 'actions_list.list_workflow_jobs':\n return `GET ${repoPath}/actions/runs/${resource}/jobs`;\n case 'actions_list.list_workflow_run_artifacts':\n return `GET ${repoPath}/actions/runs/${resource}/artifacts`;\n case 'actions_get.get_workflow':\n return `GET ${repoPath}/actions/workflows/${resource}`;\n case 'actions_get.get_workflow_run':\n return `GET ${repoPath}/actions/runs/${resource}`;\n case 'actions_get.get_workflow_job':\n return `GET ${repoPath}/actions/jobs/${resource}`;\n case 'actions_get.download_workflow_run_artifact':\n return GITHUB_ARTIFACT_DOWNLOAD_ROUTE;\n case 'actions_get.get_workflow_run_usage':\n return `GET ${repoPath}/actions/runs/${resource}/timing`;\n case 'actions_get.get_workflow_run_logs_url':\n return `GET ${repoPath}/actions/runs/${resource}/logs`;\n case 'actions_run_trigger.run_workflow':\n return `POST ${repoPath}/actions/workflows/{workflow_id}/dispatches`;\n case 'actions_run_trigger.rerun_workflow_run':\n return `POST ${repoPath}/actions/runs/${run}/rerun`;\n case 'actions_run_trigger.rerun_failed_jobs':\n return `POST ${repoPath}/actions/runs/${run}/rerun-failed-jobs`;\n case 'actions_run_trigger.cancel_workflow_run':\n return `POST ${repoPath}/actions/runs/${run}/cancel`;\n case 'actions_run_trigger.delete_workflow_run_logs':\n return `DELETE ${repoPath}/actions/runs/${run}/logs`;\n case 'get_job_logs.':\n return `GET ${repoPath}/actions/jobs/{job_id}/logs`;\n default:\n return undefined;\n }\n}\n\nasync function addCommentToPendingReview(\n client: GithubToolClient,\n args: Record<string, unknown>,\n): Promise<unknown | undefined> {\n if (client.graphql === undefined) {\n throw new GithubIntegrationProviderError(\n 'malformed-provider-response',\n 'GitHub client does not support GraphQL operations',\n );\n }\n\n const reviewLookup = await client.graphql(LATEST_PENDING_REVIEW_QUERY, {\n owner: args.owner,\n repo: args.repo,\n pullNumber: args.pull_number,\n });\n const reviewId = latestPendingReviewNodeId(reviewLookup);\n if (reviewId === undefined) return undefined;\n\n const input: Record<string, unknown> = {\n pullRequestReviewId: reviewId,\n path: args.path,\n body: args.body,\n subjectType: args.subject_type,\n };\n if (args.line !== undefined) input.line = args.line;\n if (args.side !== undefined) input.side = args.side;\n if (args.start_line !== undefined) input.startLine = args.start_line;\n if (args.start_side !== undefined) input.startSide = args.start_side;\n\n return await client.graphql(ADD_PENDING_REVIEW_COMMENT_MUTATION, {input});\n}\n\nfunction latestPendingReviewNodeId(data: unknown): string | undefined {\n if (!isRecord(data)) return undefined;\n\n const viewer = isRecord(data.viewer) ? data.viewer.login : undefined;\n if (typeof viewer !== 'string') return undefined;\n\n const repository = isRecord(data.repository) ? data.repository : undefined;\n const pullRequest =\n repository && isRecord(repository.pullRequest) ? repository.pullRequest : undefined;\n const reviews = pullRequest && isRecord(pullRequest.reviews) ? pullRequest.reviews : undefined;\n const nodes = reviews && Array.isArray(reviews.nodes) ? reviews.nodes : [];\n\n let latest: {createdAt: string; id: string} | undefined;\n for (const node of nodes) {\n if (!isRecord(node)) continue;\n const author = isRecord(node.author) ? node.author.login : undefined;\n const id = node.id;\n const createdAt = node.createdAt;\n if (author !== viewer || typeof id !== 'string' || typeof createdAt !== 'string') continue;\n if (latest === undefined || createdAt > latest.createdAt) latest = {createdAt, id};\n }\n\n return latest?.id;\n}\n\nexport function projectGithubOperationParameters(\n toolId: GithubAgentToolId,\n method: string | undefined,\n args: Record<string, unknown>,\n): Record<string, unknown> {\n const parameters = {...args};\n if (toolId === 'add_issue_comment' && parameters.reaction !== undefined) {\n parameters.content = parameters.reaction;\n delete parameters.reaction;\n if (parameters.body === undefined) delete parameters.body;\n }\n if (toolId === 'pull_request_read' && method === 'get_diff') {\n parameters.headers = {accept: 'application/vnd.github.diff'};\n }\n return parameters;\n}\n\nasync function resolvePendingReviewParameters(\n client: GithubToolClient,\n parameters: Record<string, unknown>,\n toolId: GithubAgentToolId,\n method: string | undefined,\n): Promise<Record<string, unknown> | undefined> {\n if (!isPendingReviewOperation(toolId, method)) return parameters;\n\n const reviewId = await latestPendingReviewId(client, parameters);\n return reviewId === undefined ? undefined : {...parameters, review_id: reviewId};\n}\n\nfunction isPendingReviewOperation(toolId: GithubAgentToolId, method: string | undefined): boolean {\n return (\n toolId === 'pull_request_review_write' &&\n (method === 'submit_pending' || method === 'delete_pending')\n );\n}\n\nasync function latestPendingReviewId(\n client: GithubToolClient,\n parameters: Record<string, unknown>,\n): Promise<number | undefined> {\n const perPage = 100;\n let page = 1;\n let reviewId: number | undefined;\n\n while (true) {\n const response = await client.request('GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews', {\n owner: parameters.owner,\n repo: parameters.repo,\n pull_number: parameters.pull_number,\n per_page: perPage,\n page,\n });\n if (!Array.isArray(response.data)) return undefined;\n\n reviewId = latestPendingReviewIdOnPage(response.data) ?? reviewId;\n if (response.data.length < perPage) return reviewId;\n page += 1;\n }\n}\n\nfunction latestPendingReviewIdOnPage(data: readonly unknown[]): number | undefined {\n for (let index = data.length - 1; index >= 0; index -= 1) {\n const review = data[index];\n if (!isRecord(review) || review.state !== 'PENDING') continue;\n if (typeof review.id === 'number' && Number.isSafeInteger(review.id)) return review.id;\n }\n\n return undefined;\n}\n\nfunction githubToolResult(\n toolId: GithubAgentToolId,\n data: unknown,\n response?: GithubToolResponse,\n parameters?: Record<string, unknown>,\n route?: string,\n): GithubToolCallResult {\n const structuredContent = projectGithubToolOutput(toolId, data, response, parameters, route);\n if (structuredContent === undefined) {\n return githubToolError('GitHub artifact download did not return a download URL');\n }\n return {\n content: [{type: 'text', text: JSON.stringify(structuredContent)}],\n structuredContent,\n };\n}\n\nfunction projectGithubToolOutput(\n toolId: GithubAgentToolId,\n data: unknown,\n response?: GithubToolResponse,\n parameters?: Record<string, unknown>,\n route?: string,\n): Record<string, unknown> | undefined {\n if (route === GITHUB_ARTIFACT_DOWNLOAD_ROUTE) {\n return projectGithubArtifactDownloadOutput(response, parameters);\n }\n\n switch (toolId) {\n case 'list_issue_types':\n return {issue_types: data};\n case 'list_issues':\n return {issues: data};\n case 'search_issues':\n return {issues: githubSearchItems(data)};\n case 'list_pull_requests':\n return {pull_requests: data};\n case 'search_pull_requests':\n return {pull_requests: githubSearchItems(data)};\n case 'create_pull_request':\n case 'update_pull_request':\n return {pull_request: data};\n case 'merge_pull_request':\n return {merge: data};\n default:\n return isRecord(data) ? data : {result: data};\n }\n}\n\nfunction projectGithubArtifactDownloadOutput(\n response: GithubToolResponse | undefined,\n parameters: Record<string, unknown> | undefined,\n): Record<string, unknown> | undefined {\n if (response === undefined) return undefined;\n const downloadUrl = response.headers?.location;\n if (typeof downloadUrl !== 'string' || downloadUrl.length === 0) return undefined;\n\n const output: Record<string, unknown> = {\n archive_format: GITHUB_ARTIFACT_ARCHIVE_FORMAT,\n download_url: downloadUrl,\n };\n if (typeof parameters?.resource_id === 'string') output.artifact_id = parameters.resource_id;\n\n const contentType = response.headers?.['content-type'];\n if (typeof contentType === 'string') output.content_type = contentType;\n\n const contentLength = response.headers?.['content-length'];\n const sizeBytes = typeof contentLength === 'number' ? contentLength : Number(contentLength);\n if (Number.isSafeInteger(sizeBytes) && sizeBytes >= 0) output.size_bytes = sizeBytes;\n\n return output;\n}\n\nfunction githubSearchItems(data: unknown): unknown {\n return isRecord(data) ? data.items : data;\n}\n\nfunction githubToolError(message: string): GithubToolCallResult {\n return {isError: true, content: [{type: 'text', text: message}]};\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction validateGithubToolArguments(\n tool: AgentToolCatalogEntry<GithubAgentToolRequiredScope>,\n arguments_: Record<string, unknown>,\n): string | undefined {\n const required = Array.isArray(tool.inputSchema.required) ? tool.inputSchema.required : [];\n for (const name of required) {\n if (typeof name === 'string' && arguments_[name] === undefined) {\n return `Missing required parameter: ${name}`;\n }\n }\n\n const methodRequired = methodRequiredParameters(tool.inputSchema, arguments_);\n for (const name of methodRequired) {\n if (arguments_[name] === undefined) return `Missing required parameter: ${name}`;\n }\n\n const properties = tool.inputSchema.properties;\n if (typeof properties !== 'object' || properties === null || Array.isArray(properties)) {\n return undefined;\n }\n const propertySchemas = properties as Record<string, unknown>;\n for (const [name, value] of Object.entries(arguments_)) {\n const schema = propertySchemas[name];\n if (typeof schema !== 'object' || schema === null || Array.isArray(schema)) continue;\n const type = (schema as {type?: unknown}).type;\n if (type === 'integer' && (!Number.isInteger(value) || typeof value !== 'number')) {\n return `Parameter ${name} must be an integer`;\n }\n if (type === 'array' && !Array.isArray(value)) return `Parameter ${name} must be an array`;\n }\n return undefined;\n}\n\nfunction methodRequiredParameters(\n inputSchema: AgentToolCatalogEntry<GithubAgentToolRequiredScope>['inputSchema'],\n arguments_: Record<string, unknown>,\n): string[] {\n const method = arguments_.method;\n if (typeof method !== 'string' || !Array.isArray(inputSchema.oneOf)) return [];\n\n for (const candidate of inputSchema.oneOf) {\n if (!isRecord(candidate) || !isRecord(candidate.properties)) continue;\n const methodSchema = candidate.properties.method;\n if (!isRecord(methodSchema) || methodSchema.const !== method) continue;\n return Array.isArray(candidate.required)\n ? candidate.required.filter((name): name is string => typeof name === 'string')\n : [];\n }\n\n return [];\n}\n\nfunction hasGrantedPermissions(\n granted: Record<string, 'read' | 'write' | 'admin'>,\n tool: AgentToolCatalogEntry<GithubAgentToolRequiredScope>,\n call: AgentToolCallInput,\n): boolean {\n const method = typeof call.arguments.method === 'string' ? call.arguments.method : undefined;\n const required =\n tool.methods?.find((candidate) => candidate.id === method)?.requiredScope ?? tool.requiredScope;\n return required.every(({permission, access}) => {\n const actual = granted[permission];\n return actual === 'write' || actual === 'admin' || actual === access;\n });\n}\n"],"names":["Octokit","mapGithubError","createGithubInstallationTokenProvider","normalizedGithubApiBaseUrl","GithubIntegrationProviderError","githubAgentToolCatalog","githubAgentToolSelectionCatalog","buildGithubAgentToolSelectionCatalog","DEFAULT_JOB_LOG_TAIL_LINES","GITHUB_GRAPHQL_ROUTE","GITHUB_ARTIFACT_ARCHIVE_FORMAT","GITHUB_ARTIFACT_DOWNLOAD_ROUTE","GITHUB_ARTIFACT_DOWNLOAD_TIMEOUT_MS","NO_PENDING_REVIEW_MESSAGE","LATEST_PENDING_REVIEW_QUERY","ADD_PENDING_REVIEW_COMMENT_MUTATION","GithubAgentToolsProvider","options","tokenProvider","catalog","selectionCatalog","openSession","input","installation","getInstallationByConnectionId","connection","id","installationId","Number","isSafeInteger","tokenPromise","call","tool","tools","find","candidate","toolId","githubToolError","operation","resolveGithubOperation","undefined","validationError","validateGithubToolArguments","arguments","getInstallationAccessToken","token","hasGrantedPermissions","permissions","client","createClient","createOctokitClient","method","kind","data","addCommentToPendingReview","parameters","githubToolResult","operationParameters","resolvePendingReviewParameters","response","request","route","octokit","auth","baseUrl","retry","enabled","abortController","AbortController","timeout","setTimeout","abort","redirect","parseSuccessResponseBody","signal","clearTimeout","graphql","query","variables","args","params","methods","some","githubOperationRoute","projectGithubOperationParameters","owner","repo","issue","pull","run","resource","repoPath","comment_id","reaction","body","reviewLookup","pullNumber","pull_number","reviewId","latestPendingReviewNodeId","pullRequestReviewId","path","subjectType","subject_type","line","side","start_line","startLine","start_side","startSide","isRecord","viewer","login","repository","pullRequest","reviews","nodes","Array","isArray","latest","node","author","createdAt","content","headers","accept","isPendingReviewOperation","latestPendingReviewId","review_id","perPage","page","per_page","latestPendingReviewIdOnPage","length","index","review","state","structuredContent","projectGithubToolOutput","type","text","JSON","stringify","projectGithubArtifactDownloadOutput","issue_types","issues","githubSearchItems","pull_requests","pull_request","merge","result","downloadUrl","location","output","archive_format","download_url","resource_id","artifact_id","contentType","content_type","contentLength","sizeBytes","size_bytes","items","message","isError","value","arguments_","required","inputSchema","name","methodRequired","methodRequiredParameters","properties","propertySchemas","Object","entries","schema","isInteger","oneOf","methodSchema","const","filter","granted","requiredScope","every","permission","access","actual"],"mappings":"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"}
@@ -575,7 +575,7 @@ export const githubAgentToolCatalog = [
575
575
  tool({
576
576
  id: 'add_comment_to_pending_review',
577
577
  category: 'pull_requests',
578
- description: "Add review comment to the requester's latest pending pull request review. A pending review needs to already exist to call this.",
578
+ description: "Add a review comment to the requester's latest pending pull request review. The comment remains part of that pending review until it is submitted; a pending review needs to already exist to call this.",
579
579
  sensitivity: 'write',
580
580
  sensitive: false,
581
581
  requiredScope: scopes.pullRequestsWrite,