@tpmjs/tools-github 0.1.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.
- package/README.md +56 -0
- package/dist/index.d.ts +175 -0
- package/dist/index.js +734 -0
- package/package.json +134 -0
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# @tpmjs/tools-github
|
|
2
|
+
|
|
3
|
+
GitHub API tools for AI agents. Manage repos, issues, pull requests, commits, branches, releases, gists, and Actions workflows.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @tpmjs/tools-github
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Set your GitHub personal access token:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
export GITHUB_TOKEN="ghp_..."
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { getRepo, listIssues, searchCode } from '@tpmjs/tools-github';
|
|
23
|
+
|
|
24
|
+
const repo = await getRepo.execute({ owner: 'vercel', repo: 'next.js' });
|
|
25
|
+
const issues = await listIssues.execute({ owner: 'vercel', repo: 'next.js', state: 'open', per_page: 5 });
|
|
26
|
+
const results = await searchCode.execute({ q: 'useState language:typescript', per_page: 10 });
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Tools
|
|
30
|
+
|
|
31
|
+
| Tool | Description |
|
|
32
|
+
|------|-------------|
|
|
33
|
+
| `getRepo` | Get details of a GitHub repository |
|
|
34
|
+
| `listRepos` | List repositories for a user or organization |
|
|
35
|
+
| `searchRepositories` | Search GitHub repositories by query |
|
|
36
|
+
| `createIssue` | Create a new issue on a repository |
|
|
37
|
+
| `getIssue` | Get details of a specific issue |
|
|
38
|
+
| `listIssues` | List issues with state and label filters |
|
|
39
|
+
| `createIssueComment` | Add a comment to an issue or PR |
|
|
40
|
+
| `getPullRequest` | Get details of a specific pull request |
|
|
41
|
+
| `listPullRequests` | List pull requests with filters |
|
|
42
|
+
| `getFileContent` | Get file or directory contents from a repo |
|
|
43
|
+
| `searchCode` | Search for code across GitHub |
|
|
44
|
+
| `listBranches` | List branches on a repository |
|
|
45
|
+
| `getCommit` | Get details of a specific commit |
|
|
46
|
+
| `listCommits` | List commits with path and author filters |
|
|
47
|
+
| `listReleases` | List releases on a repository |
|
|
48
|
+
| `getRelease` | Get a specific release by tag name |
|
|
49
|
+
| `createGist` | Create a new GitHub Gist |
|
|
50
|
+
| `listGists` | List gists for a user |
|
|
51
|
+
| `listWorkflowRuns` | List GitHub Actions workflow runs |
|
|
52
|
+
| `getWorkflowRun` | Get details of a workflow run |
|
|
53
|
+
|
|
54
|
+
## License
|
|
55
|
+
|
|
56
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import * as ai from 'ai';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @tpmjs/tools-github — GitHub API Tools for AI Agents
|
|
5
|
+
*
|
|
6
|
+
* Full access to the GitHub REST API: repos, issues, pull requests, commits,
|
|
7
|
+
* releases, gists, workflow runs, and code search.
|
|
8
|
+
*
|
|
9
|
+
* @requires GITHUB_TOKEN environment variable
|
|
10
|
+
*/
|
|
11
|
+
interface GetRepoInput {
|
|
12
|
+
owner: string;
|
|
13
|
+
repo: string;
|
|
14
|
+
}
|
|
15
|
+
declare const getRepo: ai.Tool<GetRepoInput, Record<string, unknown>>;
|
|
16
|
+
interface ListReposInput {
|
|
17
|
+
username: string;
|
|
18
|
+
sort?: string;
|
|
19
|
+
direction?: string;
|
|
20
|
+
per_page?: number;
|
|
21
|
+
}
|
|
22
|
+
declare const listRepos: ai.Tool<ListReposInput, unknown[]>;
|
|
23
|
+
interface SearchRepositoriesInput {
|
|
24
|
+
q: string;
|
|
25
|
+
sort?: string;
|
|
26
|
+
order?: string;
|
|
27
|
+
per_page?: number;
|
|
28
|
+
}
|
|
29
|
+
declare const searchRepositories: ai.Tool<SearchRepositoriesInput, Record<string, unknown>>;
|
|
30
|
+
interface CreateIssueInput {
|
|
31
|
+
owner: string;
|
|
32
|
+
repo: string;
|
|
33
|
+
title: string;
|
|
34
|
+
body?: string;
|
|
35
|
+
labels?: string[];
|
|
36
|
+
assignees?: string[];
|
|
37
|
+
}
|
|
38
|
+
declare const createIssue: ai.Tool<CreateIssueInput, Record<string, unknown>>;
|
|
39
|
+
interface GetIssueInput {
|
|
40
|
+
owner: string;
|
|
41
|
+
repo: string;
|
|
42
|
+
issue_number: number;
|
|
43
|
+
}
|
|
44
|
+
declare const getIssue: ai.Tool<GetIssueInput, Record<string, unknown>>;
|
|
45
|
+
interface ListIssuesInput {
|
|
46
|
+
owner: string;
|
|
47
|
+
repo: string;
|
|
48
|
+
state?: string;
|
|
49
|
+
labels?: string;
|
|
50
|
+
sort?: string;
|
|
51
|
+
per_page?: number;
|
|
52
|
+
}
|
|
53
|
+
declare const listIssues: ai.Tool<ListIssuesInput, unknown[]>;
|
|
54
|
+
interface CreateIssueCommentInput {
|
|
55
|
+
owner: string;
|
|
56
|
+
repo: string;
|
|
57
|
+
issue_number: number;
|
|
58
|
+
body: string;
|
|
59
|
+
}
|
|
60
|
+
declare const createIssueComment: ai.Tool<CreateIssueCommentInput, Record<string, unknown>>;
|
|
61
|
+
interface GetPullRequestInput {
|
|
62
|
+
owner: string;
|
|
63
|
+
repo: string;
|
|
64
|
+
pull_number: number;
|
|
65
|
+
}
|
|
66
|
+
declare const getPullRequest: ai.Tool<GetPullRequestInput, Record<string, unknown>>;
|
|
67
|
+
interface ListPullRequestsInput {
|
|
68
|
+
owner: string;
|
|
69
|
+
repo: string;
|
|
70
|
+
state?: string;
|
|
71
|
+
head?: string;
|
|
72
|
+
base?: string;
|
|
73
|
+
sort?: string;
|
|
74
|
+
per_page?: number;
|
|
75
|
+
}
|
|
76
|
+
declare const listPullRequests: ai.Tool<ListPullRequestsInput, unknown[]>;
|
|
77
|
+
interface GetFileContentInput {
|
|
78
|
+
owner: string;
|
|
79
|
+
repo: string;
|
|
80
|
+
path: string;
|
|
81
|
+
ref?: string;
|
|
82
|
+
}
|
|
83
|
+
declare const getFileContent: ai.Tool<GetFileContentInput, Record<string, unknown>>;
|
|
84
|
+
interface SearchCodeInput {
|
|
85
|
+
q: string;
|
|
86
|
+
sort?: string;
|
|
87
|
+
order?: string;
|
|
88
|
+
per_page?: number;
|
|
89
|
+
}
|
|
90
|
+
declare const searchCode: ai.Tool<SearchCodeInput, Record<string, unknown>>;
|
|
91
|
+
interface ListBranchesInput {
|
|
92
|
+
owner: string;
|
|
93
|
+
repo: string;
|
|
94
|
+
per_page?: number;
|
|
95
|
+
}
|
|
96
|
+
declare const listBranches: ai.Tool<ListBranchesInput, unknown[]>;
|
|
97
|
+
interface GetCommitInput {
|
|
98
|
+
owner: string;
|
|
99
|
+
repo: string;
|
|
100
|
+
ref: string;
|
|
101
|
+
}
|
|
102
|
+
declare const getCommit: ai.Tool<GetCommitInput, Record<string, unknown>>;
|
|
103
|
+
interface ListCommitsInput {
|
|
104
|
+
owner: string;
|
|
105
|
+
repo: string;
|
|
106
|
+
sha?: string;
|
|
107
|
+
path?: string;
|
|
108
|
+
author?: string;
|
|
109
|
+
since?: string;
|
|
110
|
+
until?: string;
|
|
111
|
+
per_page?: number;
|
|
112
|
+
}
|
|
113
|
+
declare const listCommits: ai.Tool<ListCommitsInput, unknown[]>;
|
|
114
|
+
interface ListReleasesInput {
|
|
115
|
+
owner: string;
|
|
116
|
+
repo: string;
|
|
117
|
+
per_page?: number;
|
|
118
|
+
}
|
|
119
|
+
declare const listReleases: ai.Tool<ListReleasesInput, unknown[]>;
|
|
120
|
+
interface GetReleaseInput {
|
|
121
|
+
owner: string;
|
|
122
|
+
repo: string;
|
|
123
|
+
tag: string;
|
|
124
|
+
}
|
|
125
|
+
declare const getRelease: ai.Tool<GetReleaseInput, Record<string, unknown>>;
|
|
126
|
+
interface CreateGistInput {
|
|
127
|
+
description?: string;
|
|
128
|
+
files: Record<string, {
|
|
129
|
+
content: string;
|
|
130
|
+
}>;
|
|
131
|
+
public?: boolean;
|
|
132
|
+
}
|
|
133
|
+
declare const createGist: ai.Tool<CreateGistInput, Record<string, unknown>>;
|
|
134
|
+
interface ListGistsInput {
|
|
135
|
+
username?: string;
|
|
136
|
+
per_page?: number;
|
|
137
|
+
}
|
|
138
|
+
declare const listGists: ai.Tool<ListGistsInput, unknown[]>;
|
|
139
|
+
interface ListWorkflowRunsInput {
|
|
140
|
+
owner: string;
|
|
141
|
+
repo: string;
|
|
142
|
+
status?: string;
|
|
143
|
+
per_page?: number;
|
|
144
|
+
}
|
|
145
|
+
declare const listWorkflowRuns: ai.Tool<ListWorkflowRunsInput, Record<string, unknown>>;
|
|
146
|
+
interface GetWorkflowRunInput {
|
|
147
|
+
owner: string;
|
|
148
|
+
repo: string;
|
|
149
|
+
run_id: number;
|
|
150
|
+
}
|
|
151
|
+
declare const getWorkflowRun: ai.Tool<GetWorkflowRunInput, Record<string, unknown>>;
|
|
152
|
+
declare const _default: {
|
|
153
|
+
getRepo: ai.Tool<GetRepoInput, Record<string, unknown>>;
|
|
154
|
+
listRepos: ai.Tool<ListReposInput, unknown[]>;
|
|
155
|
+
searchRepositories: ai.Tool<SearchRepositoriesInput, Record<string, unknown>>;
|
|
156
|
+
createIssue: ai.Tool<CreateIssueInput, Record<string, unknown>>;
|
|
157
|
+
getIssue: ai.Tool<GetIssueInput, Record<string, unknown>>;
|
|
158
|
+
listIssues: ai.Tool<ListIssuesInput, unknown[]>;
|
|
159
|
+
createIssueComment: ai.Tool<CreateIssueCommentInput, Record<string, unknown>>;
|
|
160
|
+
getPullRequest: ai.Tool<GetPullRequestInput, Record<string, unknown>>;
|
|
161
|
+
listPullRequests: ai.Tool<ListPullRequestsInput, unknown[]>;
|
|
162
|
+
getFileContent: ai.Tool<GetFileContentInput, Record<string, unknown>>;
|
|
163
|
+
searchCode: ai.Tool<SearchCodeInput, Record<string, unknown>>;
|
|
164
|
+
listBranches: ai.Tool<ListBranchesInput, unknown[]>;
|
|
165
|
+
getCommit: ai.Tool<GetCommitInput, Record<string, unknown>>;
|
|
166
|
+
listCommits: ai.Tool<ListCommitsInput, unknown[]>;
|
|
167
|
+
listReleases: ai.Tool<ListReleasesInput, unknown[]>;
|
|
168
|
+
getRelease: ai.Tool<GetReleaseInput, Record<string, unknown>>;
|
|
169
|
+
createGist: ai.Tool<CreateGistInput, Record<string, unknown>>;
|
|
170
|
+
listGists: ai.Tool<ListGistsInput, unknown[]>;
|
|
171
|
+
listWorkflowRuns: ai.Tool<ListWorkflowRunsInput, Record<string, unknown>>;
|
|
172
|
+
getWorkflowRun: ai.Tool<GetWorkflowRunInput, Record<string, unknown>>;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
export { type CreateGistInput, type CreateIssueCommentInput, type CreateIssueInput, type GetCommitInput, type GetFileContentInput, type GetIssueInput, type GetPullRequestInput, type GetReleaseInput, type GetRepoInput, type GetWorkflowRunInput, type ListBranchesInput, type ListCommitsInput, type ListGistsInput, type ListIssuesInput, type ListPullRequestsInput, type ListReleasesInput, type ListReposInput, type ListWorkflowRunsInput, type SearchCodeInput, type SearchRepositoriesInput, createGist, createIssue, createIssueComment, _default as default, getCommit, getFileContent, getIssue, getPullRequest, getRelease, getRepo, getWorkflowRun, listBranches, listCommits, listGists, listIssues, listPullRequests, listReleases, listRepos, listWorkflowRuns, searchCode, searchRepositories };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,734 @@
|
|
|
1
|
+
import { tool, jsonSchema } from 'ai';
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
var BASE_URL = "https://api.github.com";
|
|
5
|
+
function getApiKey() {
|
|
6
|
+
const key = process.env.GITHUB_TOKEN;
|
|
7
|
+
if (!key) {
|
|
8
|
+
throw new Error(
|
|
9
|
+
"GITHUB_TOKEN environment variable is required. Get your token from https://github.com/settings/tokens"
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
return key;
|
|
13
|
+
}
|
|
14
|
+
async function apiRequest(method, path, body) {
|
|
15
|
+
const key = getApiKey();
|
|
16
|
+
const headers = {
|
|
17
|
+
Authorization: `Bearer ${key}`,
|
|
18
|
+
Accept: "application/vnd.github+json",
|
|
19
|
+
"X-GitHub-API-Version": "2022-11-28",
|
|
20
|
+
"Content-Type": "application/json"
|
|
21
|
+
};
|
|
22
|
+
const options = { method, headers };
|
|
23
|
+
if (body !== void 0) {
|
|
24
|
+
options.body = JSON.stringify(body);
|
|
25
|
+
}
|
|
26
|
+
const response = await fetch(`${BASE_URL}${path}`, options);
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
await handleApiError(response);
|
|
29
|
+
}
|
|
30
|
+
const text = await response.text();
|
|
31
|
+
if (!text) {
|
|
32
|
+
return {};
|
|
33
|
+
}
|
|
34
|
+
return JSON.parse(text);
|
|
35
|
+
}
|
|
36
|
+
async function handleApiError(response) {
|
|
37
|
+
let errorMessage;
|
|
38
|
+
try {
|
|
39
|
+
const errorData = await response.json();
|
|
40
|
+
errorMessage = errorData.message || errorData.error || `HTTP ${response.status}`;
|
|
41
|
+
} catch {
|
|
42
|
+
errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
43
|
+
}
|
|
44
|
+
switch (response.status) {
|
|
45
|
+
case 400:
|
|
46
|
+
throw new Error(`Bad request: ${errorMessage}`);
|
|
47
|
+
case 401:
|
|
48
|
+
throw new Error("Authentication failed: Invalid GitHub token. Check GITHUB_TOKEN.");
|
|
49
|
+
case 403:
|
|
50
|
+
throw new Error(`Access forbidden: ${errorMessage}`);
|
|
51
|
+
case 404:
|
|
52
|
+
throw new Error(`Not found: ${errorMessage}`);
|
|
53
|
+
case 422:
|
|
54
|
+
throw new Error(`Validation error: ${errorMessage}`);
|
|
55
|
+
case 429:
|
|
56
|
+
throw new Error(`Rate limit exceeded: ${errorMessage}`);
|
|
57
|
+
default:
|
|
58
|
+
throw new Error(`GitHub API error (${response.status}): ${errorMessage}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function buildQueryString(params) {
|
|
62
|
+
const entries = Object.entries(params).filter(
|
|
63
|
+
([, v]) => v !== void 0 && v !== null && v !== ""
|
|
64
|
+
);
|
|
65
|
+
if (entries.length === 0) return "";
|
|
66
|
+
return "?" + entries.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
|
|
67
|
+
}
|
|
68
|
+
var getRepo = tool({
|
|
69
|
+
description: "Get detailed information about a GitHub repository including description, stars, forks, and topics.",
|
|
70
|
+
inputSchema: jsonSchema({
|
|
71
|
+
type: "object",
|
|
72
|
+
properties: {
|
|
73
|
+
owner: { type: "string", description: "Repository owner (username or organization)." },
|
|
74
|
+
repo: { type: "string", description: "Repository name." }
|
|
75
|
+
},
|
|
76
|
+
required: ["owner", "repo"],
|
|
77
|
+
additionalProperties: false
|
|
78
|
+
}),
|
|
79
|
+
async execute(input) {
|
|
80
|
+
try {
|
|
81
|
+
if (!input.owner || !input.repo) {
|
|
82
|
+
throw new Error("Owner and repo are required");
|
|
83
|
+
}
|
|
84
|
+
return await apiRequest("GET", `/repos/${input.owner}/${input.repo}`);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
throw new Error(`Failed to get repository: ${error.message}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
var listRepos = tool({
|
|
91
|
+
description: "List public repositories for a specified user with optional sorting and pagination.",
|
|
92
|
+
inputSchema: jsonSchema({
|
|
93
|
+
type: "object",
|
|
94
|
+
properties: {
|
|
95
|
+
username: { type: "string", description: "GitHub username to list repositories for." },
|
|
96
|
+
sort: {
|
|
97
|
+
type: "string",
|
|
98
|
+
description: "Sort by: created, updated, pushed, full_name (default: full_name)."
|
|
99
|
+
},
|
|
100
|
+
direction: { type: "string", description: "Sort direction: asc or desc (default: asc)." },
|
|
101
|
+
per_page: { type: "number", description: "Results per page (1-100, default: 30)." }
|
|
102
|
+
},
|
|
103
|
+
required: ["username"],
|
|
104
|
+
additionalProperties: false
|
|
105
|
+
}),
|
|
106
|
+
async execute(input) {
|
|
107
|
+
try {
|
|
108
|
+
if (!input.username) {
|
|
109
|
+
throw new Error("Username is required");
|
|
110
|
+
}
|
|
111
|
+
const qs = buildQueryString({
|
|
112
|
+
sort: input.sort,
|
|
113
|
+
direction: input.direction,
|
|
114
|
+
per_page: input.per_page
|
|
115
|
+
});
|
|
116
|
+
return await apiRequest("GET", `/users/${input.username}/repos${qs}`);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
throw new Error(`Failed to list repositories: ${error.message}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
var searchRepositories = tool({
|
|
123
|
+
description: "Search for GitHub repositories by keyword, language, stars, or other criteria using GitHub search syntax.",
|
|
124
|
+
inputSchema: jsonSchema({
|
|
125
|
+
type: "object",
|
|
126
|
+
properties: {
|
|
127
|
+
q: {
|
|
128
|
+
type: "string",
|
|
129
|
+
description: 'Search query (e.g., "react language:typescript stars:>1000"). See GitHub search syntax.'
|
|
130
|
+
},
|
|
131
|
+
sort: {
|
|
132
|
+
type: "string",
|
|
133
|
+
description: "Sort by: stars, forks, help-wanted-issues, updated (default: best match)."
|
|
134
|
+
},
|
|
135
|
+
order: { type: "string", description: "Sort order: asc or desc (default: desc)." },
|
|
136
|
+
per_page: { type: "number", description: "Results per page (1-100, default: 30)." }
|
|
137
|
+
},
|
|
138
|
+
required: ["q"],
|
|
139
|
+
additionalProperties: false
|
|
140
|
+
}),
|
|
141
|
+
async execute(input) {
|
|
142
|
+
try {
|
|
143
|
+
if (!input.q) {
|
|
144
|
+
throw new Error("Search query is required");
|
|
145
|
+
}
|
|
146
|
+
const qs = buildQueryString({
|
|
147
|
+
q: input.q,
|
|
148
|
+
sort: input.sort,
|
|
149
|
+
order: input.order,
|
|
150
|
+
per_page: input.per_page
|
|
151
|
+
});
|
|
152
|
+
return await apiRequest("GET", `/search/repositories${qs}`);
|
|
153
|
+
} catch (error) {
|
|
154
|
+
throw new Error(`Failed to search repositories: ${error.message}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
var createIssue = tool({
|
|
159
|
+
description: "Create a new issue in a GitHub repository with title, body, labels, and assignees.",
|
|
160
|
+
inputSchema: jsonSchema({
|
|
161
|
+
type: "object",
|
|
162
|
+
properties: {
|
|
163
|
+
owner: { type: "string", description: "Repository owner." },
|
|
164
|
+
repo: { type: "string", description: "Repository name." },
|
|
165
|
+
title: { type: "string", description: "Issue title." },
|
|
166
|
+
body: { type: "string", description: "Issue body content (supports Markdown)." },
|
|
167
|
+
labels: {
|
|
168
|
+
type: "array",
|
|
169
|
+
items: { type: "string" },
|
|
170
|
+
description: "Array of label names to add to the issue."
|
|
171
|
+
},
|
|
172
|
+
assignees: {
|
|
173
|
+
type: "array",
|
|
174
|
+
items: { type: "string" },
|
|
175
|
+
description: "Array of GitHub usernames to assign to the issue."
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
required: ["owner", "repo", "title"],
|
|
179
|
+
additionalProperties: false
|
|
180
|
+
}),
|
|
181
|
+
async execute(input) {
|
|
182
|
+
try {
|
|
183
|
+
if (!input.owner || !input.repo || !input.title) {
|
|
184
|
+
throw new Error("Owner, repo, and title are required");
|
|
185
|
+
}
|
|
186
|
+
return await apiRequest(
|
|
187
|
+
"POST",
|
|
188
|
+
`/repos/${input.owner}/${input.repo}/issues`,
|
|
189
|
+
{
|
|
190
|
+
title: input.title,
|
|
191
|
+
body: input.body,
|
|
192
|
+
labels: input.labels,
|
|
193
|
+
assignees: input.assignees
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
} catch (error) {
|
|
197
|
+
throw new Error(`Failed to create issue: ${error.message}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
var getIssue = tool({
|
|
202
|
+
description: "Get details of a specific issue by its number including comments count and state.",
|
|
203
|
+
inputSchema: jsonSchema({
|
|
204
|
+
type: "object",
|
|
205
|
+
properties: {
|
|
206
|
+
owner: { type: "string", description: "Repository owner." },
|
|
207
|
+
repo: { type: "string", description: "Repository name." },
|
|
208
|
+
issue_number: { type: "number", description: "Issue number." }
|
|
209
|
+
},
|
|
210
|
+
required: ["owner", "repo", "issue_number"],
|
|
211
|
+
additionalProperties: false
|
|
212
|
+
}),
|
|
213
|
+
async execute(input) {
|
|
214
|
+
try {
|
|
215
|
+
if (!input.owner || !input.repo || !input.issue_number) {
|
|
216
|
+
throw new Error("Owner, repo, and issue_number are required");
|
|
217
|
+
}
|
|
218
|
+
return await apiRequest(
|
|
219
|
+
"GET",
|
|
220
|
+
`/repos/${input.owner}/${input.repo}/issues/${input.issue_number}`
|
|
221
|
+
);
|
|
222
|
+
} catch (error) {
|
|
223
|
+
throw new Error(`Failed to get issue: ${error.message}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
var listIssues = tool({
|
|
228
|
+
description: "List issues for a repository with optional filtering by state, labels, and sorting options.",
|
|
229
|
+
inputSchema: jsonSchema({
|
|
230
|
+
type: "object",
|
|
231
|
+
properties: {
|
|
232
|
+
owner: { type: "string", description: "Repository owner." },
|
|
233
|
+
repo: { type: "string", description: "Repository name." },
|
|
234
|
+
state: {
|
|
235
|
+
type: "string",
|
|
236
|
+
description: "Filter by state: open, closed, or all (default: open)."
|
|
237
|
+
},
|
|
238
|
+
labels: {
|
|
239
|
+
type: "string",
|
|
240
|
+
description: "Comma-separated list of label names to filter by."
|
|
241
|
+
},
|
|
242
|
+
sort: {
|
|
243
|
+
type: "string",
|
|
244
|
+
description: "Sort by: created, updated, comments (default: created)."
|
|
245
|
+
},
|
|
246
|
+
per_page: { type: "number", description: "Results per page (1-100, default: 30)." }
|
|
247
|
+
},
|
|
248
|
+
required: ["owner", "repo"],
|
|
249
|
+
additionalProperties: false
|
|
250
|
+
}),
|
|
251
|
+
async execute(input) {
|
|
252
|
+
try {
|
|
253
|
+
if (!input.owner || !input.repo) {
|
|
254
|
+
throw new Error("Owner and repo are required");
|
|
255
|
+
}
|
|
256
|
+
const qs = buildQueryString({
|
|
257
|
+
state: input.state,
|
|
258
|
+
labels: input.labels,
|
|
259
|
+
sort: input.sort,
|
|
260
|
+
per_page: input.per_page
|
|
261
|
+
});
|
|
262
|
+
return await apiRequest("GET", `/repos/${input.owner}/${input.repo}/issues${qs}`);
|
|
263
|
+
} catch (error) {
|
|
264
|
+
throw new Error(`Failed to list issues: ${error.message}`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
var createIssueComment = tool({
|
|
269
|
+
description: "Add a comment to an existing issue with Markdown-formatted content.",
|
|
270
|
+
inputSchema: jsonSchema({
|
|
271
|
+
type: "object",
|
|
272
|
+
properties: {
|
|
273
|
+
owner: { type: "string", description: "Repository owner." },
|
|
274
|
+
repo: { type: "string", description: "Repository name." },
|
|
275
|
+
issue_number: { type: "number", description: "Issue number to comment on." },
|
|
276
|
+
body: { type: "string", description: "Comment body (supports Markdown)." }
|
|
277
|
+
},
|
|
278
|
+
required: ["owner", "repo", "issue_number", "body"],
|
|
279
|
+
additionalProperties: false
|
|
280
|
+
}),
|
|
281
|
+
async execute(input) {
|
|
282
|
+
try {
|
|
283
|
+
if (!input.owner || !input.repo || !input.issue_number || !input.body) {
|
|
284
|
+
throw new Error("Owner, repo, issue_number, and body are required");
|
|
285
|
+
}
|
|
286
|
+
return await apiRequest(
|
|
287
|
+
"POST",
|
|
288
|
+
`/repos/${input.owner}/${input.repo}/issues/${input.issue_number}/comments`,
|
|
289
|
+
{ body: input.body }
|
|
290
|
+
);
|
|
291
|
+
} catch (error) {
|
|
292
|
+
throw new Error(`Failed to create issue comment: ${error.message}`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
var getPullRequest = tool({
|
|
297
|
+
description: "Get details of a specific pull request including mergeable state, review status, and commits.",
|
|
298
|
+
inputSchema: jsonSchema({
|
|
299
|
+
type: "object",
|
|
300
|
+
properties: {
|
|
301
|
+
owner: { type: "string", description: "Repository owner." },
|
|
302
|
+
repo: { type: "string", description: "Repository name." },
|
|
303
|
+
pull_number: { type: "number", description: "Pull request number." }
|
|
304
|
+
},
|
|
305
|
+
required: ["owner", "repo", "pull_number"],
|
|
306
|
+
additionalProperties: false
|
|
307
|
+
}),
|
|
308
|
+
async execute(input) {
|
|
309
|
+
try {
|
|
310
|
+
if (!input.owner || !input.repo || !input.pull_number) {
|
|
311
|
+
throw new Error("Owner, repo, and pull_number are required");
|
|
312
|
+
}
|
|
313
|
+
return await apiRequest(
|
|
314
|
+
"GET",
|
|
315
|
+
`/repos/${input.owner}/${input.repo}/pulls/${input.pull_number}`
|
|
316
|
+
);
|
|
317
|
+
} catch (error) {
|
|
318
|
+
throw new Error(`Failed to get pull request: ${error.message}`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
var listPullRequests = tool({
|
|
323
|
+
description: "List pull requests for a repository with optional filtering by state, branch, and sorting.",
|
|
324
|
+
inputSchema: jsonSchema({
|
|
325
|
+
type: "object",
|
|
326
|
+
properties: {
|
|
327
|
+
owner: { type: "string", description: "Repository owner." },
|
|
328
|
+
repo: { type: "string", description: "Repository name." },
|
|
329
|
+
state: {
|
|
330
|
+
type: "string",
|
|
331
|
+
description: "Filter by state: open, closed, or all (default: open)."
|
|
332
|
+
},
|
|
333
|
+
head: {
|
|
334
|
+
type: "string",
|
|
335
|
+
description: "Filter by head branch (format: user:ref-name or organization:ref-name)."
|
|
336
|
+
},
|
|
337
|
+
base: { type: "string", description: "Filter by base branch name." },
|
|
338
|
+
sort: {
|
|
339
|
+
type: "string",
|
|
340
|
+
description: "Sort by: created, updated, popularity, long-running (default: created)."
|
|
341
|
+
},
|
|
342
|
+
per_page: { type: "number", description: "Results per page (1-100, default: 30)." }
|
|
343
|
+
},
|
|
344
|
+
required: ["owner", "repo"],
|
|
345
|
+
additionalProperties: false
|
|
346
|
+
}),
|
|
347
|
+
async execute(input) {
|
|
348
|
+
try {
|
|
349
|
+
if (!input.owner || !input.repo) {
|
|
350
|
+
throw new Error("Owner and repo are required");
|
|
351
|
+
}
|
|
352
|
+
const qs = buildQueryString({
|
|
353
|
+
state: input.state,
|
|
354
|
+
head: input.head,
|
|
355
|
+
base: input.base,
|
|
356
|
+
sort: input.sort,
|
|
357
|
+
per_page: input.per_page
|
|
358
|
+
});
|
|
359
|
+
return await apiRequest("GET", `/repos/${input.owner}/${input.repo}/pulls${qs}`);
|
|
360
|
+
} catch (error) {
|
|
361
|
+
throw new Error(`Failed to list pull requests: ${error.message}`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
var getFileContent = tool({
|
|
366
|
+
description: "Get the contents of a file or directory in a repository at a specific ref (branch, tag, or commit SHA).",
|
|
367
|
+
inputSchema: jsonSchema({
|
|
368
|
+
type: "object",
|
|
369
|
+
properties: {
|
|
370
|
+
owner: { type: "string", description: "Repository owner." },
|
|
371
|
+
repo: { type: "string", description: "Repository name." },
|
|
372
|
+
path: { type: "string", description: "File or directory path within the repository." },
|
|
373
|
+
ref: {
|
|
374
|
+
type: "string",
|
|
375
|
+
description: "Git ref (branch name, tag, or commit SHA). Defaults to default branch."
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
required: ["owner", "repo", "path"],
|
|
379
|
+
additionalProperties: false
|
|
380
|
+
}),
|
|
381
|
+
async execute(input) {
|
|
382
|
+
try {
|
|
383
|
+
if (!input.owner || !input.repo || !input.path) {
|
|
384
|
+
throw new Error("Owner, repo, and path are required");
|
|
385
|
+
}
|
|
386
|
+
const qs = buildQueryString({ ref: input.ref });
|
|
387
|
+
return await apiRequest(
|
|
388
|
+
"GET",
|
|
389
|
+
`/repos/${input.owner}/${input.repo}/contents/${input.path}${qs}`
|
|
390
|
+
);
|
|
391
|
+
} catch (error) {
|
|
392
|
+
throw new Error(`Failed to get file content: ${error.message}`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
var searchCode = tool({
|
|
397
|
+
description: "Search for code across all GitHub repositories using keyword, filename, language, or other filters.",
|
|
398
|
+
inputSchema: jsonSchema({
|
|
399
|
+
type: "object",
|
|
400
|
+
properties: {
|
|
401
|
+
q: {
|
|
402
|
+
type: "string",
|
|
403
|
+
description: 'Search query (e.g., "addClass in:file language:js repo:jquery/jquery"). See GitHub search syntax.'
|
|
404
|
+
},
|
|
405
|
+
sort: { type: "string", description: "Sort by: indexed (default: best match)." },
|
|
406
|
+
order: { type: "string", description: "Sort order: asc or desc (default: desc)." },
|
|
407
|
+
per_page: { type: "number", description: "Results per page (1-100, default: 30)." }
|
|
408
|
+
},
|
|
409
|
+
required: ["q"],
|
|
410
|
+
additionalProperties: false
|
|
411
|
+
}),
|
|
412
|
+
async execute(input) {
|
|
413
|
+
try {
|
|
414
|
+
if (!input.q) {
|
|
415
|
+
throw new Error("Search query is required");
|
|
416
|
+
}
|
|
417
|
+
const qs = buildQueryString({
|
|
418
|
+
q: input.q,
|
|
419
|
+
sort: input.sort,
|
|
420
|
+
order: input.order,
|
|
421
|
+
per_page: input.per_page
|
|
422
|
+
});
|
|
423
|
+
return await apiRequest("GET", `/search/code${qs}`);
|
|
424
|
+
} catch (error) {
|
|
425
|
+
throw new Error(`Failed to search code: ${error.message}`);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
var listBranches = tool({
|
|
430
|
+
description: "List all branches in a repository with their latest commit SHA and protection status.",
|
|
431
|
+
inputSchema: jsonSchema({
|
|
432
|
+
type: "object",
|
|
433
|
+
properties: {
|
|
434
|
+
owner: { type: "string", description: "Repository owner." },
|
|
435
|
+
repo: { type: "string", description: "Repository name." },
|
|
436
|
+
per_page: { type: "number", description: "Results per page (1-100, default: 30)." }
|
|
437
|
+
},
|
|
438
|
+
required: ["owner", "repo"],
|
|
439
|
+
additionalProperties: false
|
|
440
|
+
}),
|
|
441
|
+
async execute(input) {
|
|
442
|
+
try {
|
|
443
|
+
if (!input.owner || !input.repo) {
|
|
444
|
+
throw new Error("Owner and repo are required");
|
|
445
|
+
}
|
|
446
|
+
const qs = buildQueryString({ per_page: input.per_page });
|
|
447
|
+
return await apiRequest(
|
|
448
|
+
"GET",
|
|
449
|
+
`/repos/${input.owner}/${input.repo}/branches${qs}`
|
|
450
|
+
);
|
|
451
|
+
} catch (error) {
|
|
452
|
+
throw new Error(`Failed to list branches: ${error.message}`);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
var getCommit = tool({
|
|
457
|
+
description: "Get detailed information about a specific commit including changes, author, and committer.",
|
|
458
|
+
inputSchema: jsonSchema({
|
|
459
|
+
type: "object",
|
|
460
|
+
properties: {
|
|
461
|
+
owner: { type: "string", description: "Repository owner." },
|
|
462
|
+
repo: { type: "string", description: "Repository name." },
|
|
463
|
+
ref: { type: "string", description: "Commit SHA, branch name, or tag." }
|
|
464
|
+
},
|
|
465
|
+
required: ["owner", "repo", "ref"],
|
|
466
|
+
additionalProperties: false
|
|
467
|
+
}),
|
|
468
|
+
async execute(input) {
|
|
469
|
+
try {
|
|
470
|
+
if (!input.owner || !input.repo || !input.ref) {
|
|
471
|
+
throw new Error("Owner, repo, and ref are required");
|
|
472
|
+
}
|
|
473
|
+
return await apiRequest(
|
|
474
|
+
"GET",
|
|
475
|
+
`/repos/${input.owner}/${input.repo}/commits/${input.ref}`
|
|
476
|
+
);
|
|
477
|
+
} catch (error) {
|
|
478
|
+
throw new Error(`Failed to get commit: ${error.message}`);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
var listCommits = tool({
|
|
483
|
+
description: "List commits in a repository with optional filtering by branch, path, author, and date range.",
|
|
484
|
+
inputSchema: jsonSchema({
|
|
485
|
+
type: "object",
|
|
486
|
+
properties: {
|
|
487
|
+
owner: { type: "string", description: "Repository owner." },
|
|
488
|
+
repo: { type: "string", description: "Repository name." },
|
|
489
|
+
sha: {
|
|
490
|
+
type: "string",
|
|
491
|
+
description: "SHA or branch to start listing from (defaults to default branch)."
|
|
492
|
+
},
|
|
493
|
+
path: { type: "string", description: "Only commits containing this file path." },
|
|
494
|
+
author: { type: "string", description: "GitHub username or email to filter by author." },
|
|
495
|
+
since: {
|
|
496
|
+
type: "string",
|
|
497
|
+
description: "Only commits after this date (ISO 8601 timestamp)."
|
|
498
|
+
},
|
|
499
|
+
until: {
|
|
500
|
+
type: "string",
|
|
501
|
+
description: "Only commits before this date (ISO 8601 timestamp)."
|
|
502
|
+
},
|
|
503
|
+
per_page: { type: "number", description: "Results per page (1-100, default: 30)." }
|
|
504
|
+
},
|
|
505
|
+
required: ["owner", "repo"],
|
|
506
|
+
additionalProperties: false
|
|
507
|
+
}),
|
|
508
|
+
async execute(input) {
|
|
509
|
+
try {
|
|
510
|
+
if (!input.owner || !input.repo) {
|
|
511
|
+
throw new Error("Owner and repo are required");
|
|
512
|
+
}
|
|
513
|
+
const qs = buildQueryString({
|
|
514
|
+
sha: input.sha,
|
|
515
|
+
path: input.path,
|
|
516
|
+
author: input.author,
|
|
517
|
+
since: input.since,
|
|
518
|
+
until: input.until,
|
|
519
|
+
per_page: input.per_page
|
|
520
|
+
});
|
|
521
|
+
return await apiRequest(
|
|
522
|
+
"GET",
|
|
523
|
+
`/repos/${input.owner}/${input.repo}/commits${qs}`
|
|
524
|
+
);
|
|
525
|
+
} catch (error) {
|
|
526
|
+
throw new Error(`Failed to list commits: ${error.message}`);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
var listReleases = tool({
|
|
531
|
+
description: "List published releases for a repository including tags, assets, and release notes.",
|
|
532
|
+
inputSchema: jsonSchema({
|
|
533
|
+
type: "object",
|
|
534
|
+
properties: {
|
|
535
|
+
owner: { type: "string", description: "Repository owner." },
|
|
536
|
+
repo: { type: "string", description: "Repository name." },
|
|
537
|
+
per_page: { type: "number", description: "Results per page (1-100, default: 30)." }
|
|
538
|
+
},
|
|
539
|
+
required: ["owner", "repo"],
|
|
540
|
+
additionalProperties: false
|
|
541
|
+
}),
|
|
542
|
+
async execute(input) {
|
|
543
|
+
try {
|
|
544
|
+
if (!input.owner || !input.repo) {
|
|
545
|
+
throw new Error("Owner and repo are required");
|
|
546
|
+
}
|
|
547
|
+
const qs = buildQueryString({ per_page: input.per_page });
|
|
548
|
+
return await apiRequest(
|
|
549
|
+
"GET",
|
|
550
|
+
`/repos/${input.owner}/${input.repo}/releases${qs}`
|
|
551
|
+
);
|
|
552
|
+
} catch (error) {
|
|
553
|
+
throw new Error(`Failed to list releases: ${error.message}`);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
var getRelease = tool({
|
|
558
|
+
description: "Get details of a specific release by its tag name including assets and body.",
|
|
559
|
+
inputSchema: jsonSchema({
|
|
560
|
+
type: "object",
|
|
561
|
+
properties: {
|
|
562
|
+
owner: { type: "string", description: "Repository owner." },
|
|
563
|
+
repo: { type: "string", description: "Repository name." },
|
|
564
|
+
tag: { type: "string", description: 'Release tag name (e.g., "v1.0.0").' }
|
|
565
|
+
},
|
|
566
|
+
required: ["owner", "repo", "tag"],
|
|
567
|
+
additionalProperties: false
|
|
568
|
+
}),
|
|
569
|
+
async execute(input) {
|
|
570
|
+
try {
|
|
571
|
+
if (!input.owner || !input.repo || !input.tag) {
|
|
572
|
+
throw new Error("Owner, repo, and tag are required");
|
|
573
|
+
}
|
|
574
|
+
return await apiRequest(
|
|
575
|
+
"GET",
|
|
576
|
+
`/repos/${input.owner}/${input.repo}/releases/tags/${input.tag}`
|
|
577
|
+
);
|
|
578
|
+
} catch (error) {
|
|
579
|
+
throw new Error(`Failed to get release: ${error.message}`);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
var createGist = tool({
|
|
584
|
+
description: "Create a new gist with one or more files. Gists can be public or secret (unlisted).",
|
|
585
|
+
inputSchema: jsonSchema({
|
|
586
|
+
type: "object",
|
|
587
|
+
properties: {
|
|
588
|
+
description: { type: "string", description: "Description of the gist." },
|
|
589
|
+
files: {
|
|
590
|
+
type: "object",
|
|
591
|
+
additionalProperties: {
|
|
592
|
+
type: "object",
|
|
593
|
+
properties: {
|
|
594
|
+
content: { type: "string", description: "File content." }
|
|
595
|
+
},
|
|
596
|
+
required: ["content"]
|
|
597
|
+
},
|
|
598
|
+
description: "Files to include in the gist as an object with filename keys and { content } values."
|
|
599
|
+
},
|
|
600
|
+
public: {
|
|
601
|
+
type: "boolean",
|
|
602
|
+
description: "Whether the gist is public (true) or secret/unlisted (false)."
|
|
603
|
+
}
|
|
604
|
+
},
|
|
605
|
+
required: ["files"],
|
|
606
|
+
additionalProperties: false
|
|
607
|
+
}),
|
|
608
|
+
async execute(input) {
|
|
609
|
+
try {
|
|
610
|
+
if (!input.files || Object.keys(input.files).length === 0) {
|
|
611
|
+
throw new Error("At least one file is required");
|
|
612
|
+
}
|
|
613
|
+
return await apiRequest("POST", "/gists", {
|
|
614
|
+
description: input.description,
|
|
615
|
+
files: input.files,
|
|
616
|
+
public: input.public ?? true
|
|
617
|
+
});
|
|
618
|
+
} catch (error) {
|
|
619
|
+
throw new Error(`Failed to create gist: ${error.message}`);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
});
|
|
623
|
+
var listGists = tool({
|
|
624
|
+
description: "List public gists for a specified user, or list all public gists if no username provided.",
|
|
625
|
+
inputSchema: jsonSchema({
|
|
626
|
+
type: "object",
|
|
627
|
+
properties: {
|
|
628
|
+
username: {
|
|
629
|
+
type: "string",
|
|
630
|
+
description: "GitHub username to list gists for. Omit to list all public gists."
|
|
631
|
+
},
|
|
632
|
+
per_page: { type: "number", description: "Results per page (1-100, default: 30)." }
|
|
633
|
+
},
|
|
634
|
+
additionalProperties: false
|
|
635
|
+
}),
|
|
636
|
+
async execute(input) {
|
|
637
|
+
try {
|
|
638
|
+
const qs = buildQueryString({ per_page: input.per_page });
|
|
639
|
+
const path = input.username ? `/users/${input.username}/gists${qs}` : `/gists${qs}`;
|
|
640
|
+
return await apiRequest("GET", path);
|
|
641
|
+
} catch (error) {
|
|
642
|
+
throw new Error(`Failed to list gists: ${error.message}`);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
var listWorkflowRuns = tool({
|
|
647
|
+
description: "List GitHub Actions workflow runs for a repository with optional filtering by status.",
|
|
648
|
+
inputSchema: jsonSchema({
|
|
649
|
+
type: "object",
|
|
650
|
+
properties: {
|
|
651
|
+
owner: { type: "string", description: "Repository owner." },
|
|
652
|
+
repo: { type: "string", description: "Repository name." },
|
|
653
|
+
status: {
|
|
654
|
+
type: "string",
|
|
655
|
+
description: "Filter by status: completed, action_required, cancelled, failure, neutral, skipped, stale, success, timed_out, in_progress, queued, requested, waiting."
|
|
656
|
+
},
|
|
657
|
+
per_page: { type: "number", description: "Results per page (1-100, default: 30)." }
|
|
658
|
+
},
|
|
659
|
+
required: ["owner", "repo"],
|
|
660
|
+
additionalProperties: false
|
|
661
|
+
}),
|
|
662
|
+
async execute(input) {
|
|
663
|
+
try {
|
|
664
|
+
if (!input.owner || !input.repo) {
|
|
665
|
+
throw new Error("Owner and repo are required");
|
|
666
|
+
}
|
|
667
|
+
const qs = buildQueryString({ status: input.status, per_page: input.per_page });
|
|
668
|
+
return await apiRequest(
|
|
669
|
+
"GET",
|
|
670
|
+
`/repos/${input.owner}/${input.repo}/actions/runs${qs}`
|
|
671
|
+
);
|
|
672
|
+
} catch (error) {
|
|
673
|
+
throw new Error(`Failed to list workflow runs: ${error.message}`);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
var getWorkflowRun = tool({
|
|
678
|
+
description: "Get details of a specific workflow run including status, conclusion, and job information.",
|
|
679
|
+
inputSchema: jsonSchema({
|
|
680
|
+
type: "object",
|
|
681
|
+
properties: {
|
|
682
|
+
owner: { type: "string", description: "Repository owner." },
|
|
683
|
+
repo: { type: "string", description: "Repository name." },
|
|
684
|
+
run_id: { type: "number", description: "Workflow run ID." }
|
|
685
|
+
},
|
|
686
|
+
required: ["owner", "repo", "run_id"],
|
|
687
|
+
additionalProperties: false
|
|
688
|
+
}),
|
|
689
|
+
async execute(input) {
|
|
690
|
+
try {
|
|
691
|
+
if (!input.owner || !input.repo || !input.run_id) {
|
|
692
|
+
throw new Error("Owner, repo, and run_id are required");
|
|
693
|
+
}
|
|
694
|
+
return await apiRequest(
|
|
695
|
+
"GET",
|
|
696
|
+
`/repos/${input.owner}/${input.repo}/actions/runs/${input.run_id}`
|
|
697
|
+
);
|
|
698
|
+
} catch (error) {
|
|
699
|
+
throw new Error(`Failed to get workflow run: ${error.message}`);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
var index_default = {
|
|
704
|
+
// Repositories
|
|
705
|
+
getRepo,
|
|
706
|
+
listRepos,
|
|
707
|
+
searchRepositories,
|
|
708
|
+
// Issues
|
|
709
|
+
createIssue,
|
|
710
|
+
getIssue,
|
|
711
|
+
listIssues,
|
|
712
|
+
createIssueComment,
|
|
713
|
+
// Pull Requests
|
|
714
|
+
getPullRequest,
|
|
715
|
+
listPullRequests,
|
|
716
|
+
// Content
|
|
717
|
+
getFileContent,
|
|
718
|
+
searchCode,
|
|
719
|
+
// Branches & Commits
|
|
720
|
+
listBranches,
|
|
721
|
+
getCommit,
|
|
722
|
+
listCommits,
|
|
723
|
+
// Releases
|
|
724
|
+
listReleases,
|
|
725
|
+
getRelease,
|
|
726
|
+
// Gists
|
|
727
|
+
createGist,
|
|
728
|
+
listGists,
|
|
729
|
+
// Actions
|
|
730
|
+
listWorkflowRuns,
|
|
731
|
+
getWorkflowRun
|
|
732
|
+
};
|
|
733
|
+
|
|
734
|
+
export { createGist, createIssue, createIssueComment, index_default as default, getCommit, getFileContent, getIssue, getPullRequest, getRelease, getRepo, getWorkflowRun, listBranches, listCommits, listGists, listIssues, listPullRequests, listReleases, listRepos, listWorkflowRuns, searchCode, searchRepositories };
|
package/package.json
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tpmjs/tools-github",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "GitHub API tools for AI agents. Manage repos, issues, pull requests, commits, branches, releases, and gists.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"tpmjs",
|
|
8
|
+
"github",
|
|
9
|
+
"git",
|
|
10
|
+
"devops",
|
|
11
|
+
"agent"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"dev": "tsup --watch",
|
|
25
|
+
"type-check": "tsc --noEmit",
|
|
26
|
+
"clean": "rm -rf dist .turbo"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@tpmjs/tsconfig": "workspace:*",
|
|
30
|
+
"tsup": "^8.5.1",
|
|
31
|
+
"typescript": "^5.9.3"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"ai": "6.0.49"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/tpmjs/tpmjs.git",
|
|
42
|
+
"directory": "packages/tools/official/github"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://tpmjs.com",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"tpmjs": {
|
|
47
|
+
"category": "ops",
|
|
48
|
+
"frameworks": [
|
|
49
|
+
"vercel-ai"
|
|
50
|
+
],
|
|
51
|
+
"tools": [
|
|
52
|
+
{
|
|
53
|
+
"name": "getRepo",
|
|
54
|
+
"description": "Get details of a GitHub repository including stars, forks, and language."
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "listRepos",
|
|
58
|
+
"description": "List repositories for a user or organization with optional filtering."
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"name": "createIssue",
|
|
62
|
+
"description": "Create a new issue on a GitHub repository."
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "getIssue",
|
|
66
|
+
"description": "Get details of a specific issue by number."
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "listIssues",
|
|
70
|
+
"description": "List issues on a repository with state and label filters."
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"name": "createIssueComment",
|
|
74
|
+
"description": "Add a comment to an existing GitHub issue or pull request."
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "getPullRequest",
|
|
78
|
+
"description": "Get details of a specific pull request by number."
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"name": "listPullRequests",
|
|
82
|
+
"description": "List pull requests on a repository with state and head/base filters."
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "getFileContent",
|
|
86
|
+
"description": "Get the contents of a file or directory from a GitHub repository."
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "searchCode",
|
|
90
|
+
"description": "Search for code across GitHub repositories."
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"name": "searchRepositories",
|
|
94
|
+
"description": "Search GitHub repositories by query with sort and order options."
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"name": "listBranches",
|
|
98
|
+
"description": "List branches on a GitHub repository."
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"name": "getCommit",
|
|
102
|
+
"description": "Get details of a specific commit by SHA."
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "listCommits",
|
|
106
|
+
"description": "List commits on a repository with optional path and author filters."
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"name": "listReleases",
|
|
110
|
+
"description": "List releases on a GitHub repository."
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"name": "getRelease",
|
|
114
|
+
"description": "Get details of a specific release by tag name."
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"name": "createGist",
|
|
118
|
+
"description": "Create a new GitHub Gist with one or more files."
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"name": "listGists",
|
|
122
|
+
"description": "List gists for the authenticated user or a specific user."
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"name": "listWorkflowRuns",
|
|
126
|
+
"description": "List recent GitHub Actions workflow runs for a repository."
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "getWorkflowRun",
|
|
130
|
+
"description": "Get details of a specific GitHub Actions workflow run."
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
}
|