cleanup
This commit is contained in:
parent
9be6268005
commit
1b33f678da
1 changed files with 103 additions and 113 deletions
|
|
@ -144,8 +144,12 @@ async function getDefaultBranchSHA(
|
||||||
return data.object.sha;
|
return data.object.sha;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getFileContents(owner: string, repo: string, path: string): Promise<GitHubContent> {
|
async function getFileContents(owner: string, repo: string, path: string, branch?: string): Promise<GitHubContent> {
|
||||||
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path}`;
|
let url = `https://api.github.com/repos/${owner}/${repo}/contents/${path}`;
|
||||||
|
if (branch) {
|
||||||
|
url += `?ref=${branch}`;
|
||||||
|
}
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
"Authorization": `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
|
"Authorization": `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
|
||||||
|
|
@ -155,7 +159,8 @@ async function getFileContents(owner: string, repo: string, path: string): Promi
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`GitHub API error: ${response.statusText}`);
|
const errorData = await response.text();
|
||||||
|
throw new Error(`GitHub API error (${response.status}): ${errorData}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json() as GitHubContent;
|
const data = await response.json() as GitHubContent;
|
||||||
|
|
@ -230,14 +235,33 @@ async function createOrUpdateFile(
|
||||||
path: string,
|
path: string,
|
||||||
content: string,
|
content: string,
|
||||||
message: string,
|
message: string,
|
||||||
|
branch: string,
|
||||||
sha?: string
|
sha?: string
|
||||||
): Promise<GitHubCreateUpdateFileResponse> {
|
): Promise<GitHubCreateUpdateFileResponse> {
|
||||||
|
// Properly encode content to base64
|
||||||
|
const encodedContent = Buffer.from(content).toString('base64');
|
||||||
|
|
||||||
|
let currentSha = sha;
|
||||||
|
if (!currentSha) {
|
||||||
|
// Try to get current file SHA if it exists in the specified branch
|
||||||
|
try {
|
||||||
|
const existingFile = await getFileContents(owner, repo, path, branch);
|
||||||
|
if (!Array.isArray(existingFile)) {
|
||||||
|
currentSha = existingFile.sha;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// File doesn't exist in this branch, which is fine for creation
|
||||||
|
console.error('Note: File does not exist in branch, will create new file');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path}`;
|
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path}`;
|
||||||
|
|
||||||
const body = {
|
const body = {
|
||||||
message,
|
message,
|
||||||
content: Buffer.from(content).toString('base64'),
|
content: encodedContent,
|
||||||
sha
|
branch,
|
||||||
|
...(currentSha ? { sha: currentSha } : {})
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
|
|
@ -252,7 +276,8 @@ async function createOrUpdateFile(
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`GitHub API error: ${response.statusText}`);
|
const errorData = await response.text();
|
||||||
|
throw new Error(`GitHub API error (${response.status}): ${errorData}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await response.json() as GitHubCreateUpdateFileResponse;
|
return await response.json() as GitHubCreateUpdateFileResponse;
|
||||||
|
|
@ -434,6 +459,44 @@ async function createRepository(options: CreateRepositoryOptions): Promise<GitHu
|
||||||
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||||
return {
|
return {
|
||||||
tools: [
|
tools: [
|
||||||
|
{
|
||||||
|
name: "create_or_update_file",
|
||||||
|
description: "Create or update a single file in a GitHub repository",
|
||||||
|
inputSchema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
owner: {
|
||||||
|
type: "string",
|
||||||
|
description: "Repository owner (username or organization)"
|
||||||
|
},
|
||||||
|
repo: {
|
||||||
|
type: "string",
|
||||||
|
description: "Repository name"
|
||||||
|
},
|
||||||
|
path: {
|
||||||
|
type: "string",
|
||||||
|
description: "Path where to create/update the file"
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
type: "string",
|
||||||
|
description: "Content of the file"
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
type: "string",
|
||||||
|
description: "Commit message"
|
||||||
|
},
|
||||||
|
branch: {
|
||||||
|
type: "string",
|
||||||
|
description: "Branch to create/update the file in"
|
||||||
|
},
|
||||||
|
sha: {
|
||||||
|
type: "string",
|
||||||
|
description: "SHA of the file being replaced (required when updating existing files)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
required: ["owner", "repo", "path", "content", "message", "branch"]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "search_repositories",
|
name: "search_repositories",
|
||||||
description: "Search for GitHub repositories",
|
description: "Search for GitHub repositories",
|
||||||
|
|
@ -504,40 +567,6 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||||
required: ["owner", "repo", "path"]
|
required: ["owner", "repo", "path"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "create_or_update_file",
|
|
||||||
description: "Create or update a single file in a GitHub repository",
|
|
||||||
inputSchema: {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
owner: {
|
|
||||||
type: "string",
|
|
||||||
description: "Repository owner (username or organization)"
|
|
||||||
},
|
|
||||||
repo: {
|
|
||||||
type: "string",
|
|
||||||
description: "Repository name"
|
|
||||||
},
|
|
||||||
path: {
|
|
||||||
type: "string",
|
|
||||||
description: "Path where to create/update the file"
|
|
||||||
},
|
|
||||||
content: {
|
|
||||||
type: "string",
|
|
||||||
description: "Content of the file"
|
|
||||||
},
|
|
||||||
message: {
|
|
||||||
type: "string",
|
|
||||||
description: "Commit message"
|
|
||||||
},
|
|
||||||
sha: {
|
|
||||||
type: "string",
|
|
||||||
description: "SHA of the file being replaced (required when updating existing files)"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
required: ["owner", "repo", "path", "content", "message"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "push_files",
|
name: "push_files",
|
||||||
description: "Push multiple files to a GitHub repository in a single commit",
|
description: "Push multiple files to a GitHub repository in a single commit",
|
||||||
|
|
@ -582,37 +611,6 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||||
required: ["owner", "repo", "branch", "files", "message"]
|
required: ["owner", "repo", "branch", "files", "message"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "open_in_browser",
|
|
||||||
description: "Open a GitHub repository, file, issue, or pull request in the browser",
|
|
||||||
inputSchema: {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
owner: {
|
|
||||||
type: "string",
|
|
||||||
description: "Repository owner (username or organization)"
|
|
||||||
},
|
|
||||||
repo: {
|
|
||||||
type: "string",
|
|
||||||
description: "Repository name"
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
type: "string",
|
|
||||||
enum: ["repository", "file", "issue", "pull_request"],
|
|
||||||
description: "Type of resource to open"
|
|
||||||
},
|
|
||||||
path: {
|
|
||||||
type: "string",
|
|
||||||
description: "Path to the file (only for type='file')"
|
|
||||||
},
|
|
||||||
number: {
|
|
||||||
type: "number",
|
|
||||||
description: "Issue or PR number (only for type='issue' or type='pull_request')"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
required: ["owner", "repo", "type"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "create_issue",
|
name: "create_issue",
|
||||||
description: "Create a new issue in a GitHub repository",
|
description: "Create a new issue in a GitHub repository",
|
||||||
|
|
@ -826,30 +824,56 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.params.name === "get_file_contents") {
|
if (request.params.name === "get_file_contents") {
|
||||||
const { owner, repo, path } = request.params.arguments as {
|
if (!request.params.arguments) {
|
||||||
|
throw new Error("Arguments are required");
|
||||||
|
}
|
||||||
|
|
||||||
|
const args = request.params.arguments as {
|
||||||
owner: string;
|
owner: string;
|
||||||
repo: string;
|
repo: string;
|
||||||
path: string;
|
path: string;
|
||||||
|
branch?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const contents = await getFileContents(owner, repo, path);
|
const contents = await getFileContents(args.owner, args.repo, args.path, args.branch);
|
||||||
return { toolResult: contents };
|
return { toolResult: contents };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.params.name === "create_or_update_file") {
|
if (request.params.name === "create_or_update_file") {
|
||||||
const { owner, repo, path, content, message, sha } = request.params.arguments as {
|
if (!request.params.arguments) {
|
||||||
|
throw new Error("Arguments are required");
|
||||||
|
}
|
||||||
|
|
||||||
|
const args = request.params.arguments as {
|
||||||
owner: string;
|
owner: string;
|
||||||
repo: string;
|
repo: string;
|
||||||
path: string;
|
path: string;
|
||||||
content: string;
|
content: string;
|
||||||
message: string;
|
message: string;
|
||||||
|
branch: string;
|
||||||
sha?: string;
|
sha?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = await createOrUpdateFile(owner, repo, path, content, message, sha);
|
try {
|
||||||
return { toolResult: result };
|
const result = await createOrUpdateFile(
|
||||||
|
args.owner,
|
||||||
|
args.repo,
|
||||||
|
args.path,
|
||||||
|
args.content,
|
||||||
|
args.message,
|
||||||
|
args.branch,
|
||||||
|
args.sha
|
||||||
|
);
|
||||||
|
return { toolResult: result };
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
throw new Error(`Failed to create/update file: ${error.message}`);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (request.params.name === "push_files") {
|
if (request.params.name === "push_files") {
|
||||||
const { owner, repo, branch, files, message } = request.params.arguments as {
|
const { owner, repo, branch, files, message } = request.params.arguments as {
|
||||||
owner: string;
|
owner: string;
|
||||||
|
|
@ -863,40 +887,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||||
return { toolResult: result };
|
return { toolResult: result };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (request.params.name === "open_in_browser") {
|
|
||||||
const { owner, repo, type, path, number } = request.params.arguments as {
|
|
||||||
owner: string;
|
|
||||||
repo: string;
|
|
||||||
type: "repository" | "file" | "issue" | "pull_request";
|
|
||||||
path?: string;
|
|
||||||
number?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
let url: string;
|
|
||||||
switch (type) {
|
|
||||||
case "repository":
|
|
||||||
url = `https://github.com/${owner}/${repo}`;
|
|
||||||
break;
|
|
||||||
case "file":
|
|
||||||
if (!path) throw new Error("Path is required for file URLs");
|
|
||||||
url = `https://github.com/${owner}/${repo}/blob/main/${path}`;
|
|
||||||
break;
|
|
||||||
case "issue":
|
|
||||||
if (!number) throw new Error("Number is required for issue URLs");
|
|
||||||
url = `https://github.com/${owner}/${repo}/issues/${number}`;
|
|
||||||
break;
|
|
||||||
case "pull_request":
|
|
||||||
if (!number) throw new Error("Number is required for pull request URLs");
|
|
||||||
url = `https://github.com/${owner}/${repo}/pull/${number}`;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error(`Invalid type: ${type}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return { toolResult: { url } };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.params.name === "create_issue") {
|
if (request.params.name === "create_issue") {
|
||||||
if (!request.params.arguments) {
|
if (!request.params.arguments) {
|
||||||
throw new Error("Arguments are required");
|
throw new Error("Arguments are required");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue