import { createPlugin } from "@choiceopen/atomemo-plugin-sdk-js";
import { z } from "zod";
const plugin = await createPlugin({
name: "github-toolkit",
display_name: { en_US: "GitHub Toolkit" },
description: { en_US: "Tools for interacting with GitHub API" },
icon: "🐙",
locales: ["en_US"],
});
// Define GitHub API credential
plugin.addCredential({
name: "github_api_key",
display_name: { en_US: "GitHub API Key" },
description: { en_US: "Personal access token for GitHub API" },
icon: "🔑",
parameters: [
{
name: "api_token",
display_name: { en_US: "API Token" },
description: { en_US: "Your GitHub personal access token" },
type: "string",
required: true,
secret: true,
},
],
authenticate: async ({ args }) => {
const { api_token } = args.credential;
// Validate the token by making a test API call
const response = await fetch("https://api.github.com/user", {
headers: {
Authorization: `Bearer ${api_token}`,
Accept: "application/vnd.github+json",
},
});
if (!response.ok) {
throw new Error("Invalid GitHub API token");
}
const user = await response.json();
return {
authenticated: true,
username: user.login,
user_id: user.id,
};
},
});
// Define a tool that uses the credential
plugin.addTool({
name: "list_repositories",
display_name: { en_US: "List Repositories" },
description: { en_US: "List GitHub repositories for the authenticated user" },
icon: "📚",
credentials: ["github_api_key"],
parameters: [
{
name: "visibility",
display_name: { en_US: "Visibility" },
description: { en_US: "Filter repositories by visibility" },
type: "string",
required: false,
enum: ["all", "public", "private"],
default: "all",
},
{
name: "sort",
display_name: { en_US: "Sort By" },
description: { en_US: "Sort repositories by this field" },
type: "string",
required: false,
enum: ["created", "updated", "pushed", "full_name"],
default: "updated",
},
{
name: "limit",
display_name: { en_US: "Limit" },
description: { en_US: "Maximum number of repositories to return" },
type: "number",
required: false,
default: 10,
},
],
invoke: async ({ args }) => {
const { visibility, sort, limit } = args.parameters;
const credentials = args.credentials?.github_api_key;
if (!credentials?.api_token) {
throw new Error("GitHub API token is required");
}
// Build API URL with query parameters
const params = new URLSearchParams({
visibility: visibility || "all",
sort: sort || "updated",
per_page: String(limit || 10),
});
const response = await fetch(
`https://api.github.com/user/repos?${params}`,
{
headers: {
Authorization: `Bearer ${credentials.api_token}`,
Accept: "application/vnd.github+json",
},
}
);
if (!response.ok) {
throw new Error(`GitHub API error: ${response.statusText}`);
}
const repositories = await response.json();
return {
count: repositories.length,
repositories: repositories.map((repo: any) => ({
name: repo.name,
full_name: repo.full_name,
description: repo.description,
url: repo.html_url,
stars: repo.stargazers_count,
private: repo.private,
updated_at: repo.updated_at,
})),
};
},
});
// Add another tool that creates an issue
plugin.addTool({
name: "create_issue",
display_name: { en_US: "Create Issue" },
description: { en_US: "Create a new issue in a GitHub repository" },
icon: "🐛",
credentials: ["github_api_key"],
parameters: [
{
name: "owner",
display_name: { en_US: "Repository Owner" },
description: { en_US: "The owner of the repository" },
type: "string",
required: true,
},
{
name: "repo",
display_name: { en_US: "Repository Name" },
description: { en_US: "The name of the repository" },
type: "string",
required: true,
},
{
name: "title",
display_name: { en_US: "Issue Title" },
description: { en_US: "The title of the issue" },
type: "string",
required: true,
},
{
name: "body",
display_name: { en_US: "Issue Body" },
description: { en_US: "The body content of the issue" },
type: "string",
required: false,
},
{
name: "labels",
display_name: { en_US: "Labels" },
description: { en_US: "Comma-separated list of labels" },
type: "string",
required: false,
},
],
invoke: async ({ args }) => {
const { owner, repo, title, body, labels } = args.parameters;
const credentials = args.credentials?.github_api_key;
if (!credentials?.api_token) {
throw new Error("GitHub API token is required");
}
const issueData: any = { title, body };
if (labels) {
issueData.labels = labels.split(",").map((l: string) => l.trim());
}
const response = await fetch(
`https://api.github.com/repos/${owner}/${repo}/issues`,
{
method: "POST",
headers: {
Authorization: `Bearer ${credentials.api_token}`,
Accept: "application/vnd.github+json",
"Content-Type": "application/json",
},
body: JSON.stringify(issueData),
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(`Failed to create issue: ${error.message}`);
}
const issue = await response.json();
return {
success: true,
issue_number: issue.number,
issue_url: issue.html_url,
state: issue.state,
};
},
});
await plugin.run();