Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1922352d86 | |||
| c0f31415a3 | |||
| 706ce04895 | |||
| 09be8e3068 | |||
| c6c1210fa0 | |||
| 0368512b9e | |||
| 9fb6135fd2 | |||
| bb78e5f94b | |||
| c668578c6f | |||
| 7f1566d9c2 | |||
| dd482566c2 | |||
| 57029c32a3 | |||
| 757d336475 | |||
| d03debab4b | |||
| a05829f781 | |||
| c8ba7940e3 |
@@ -10,9 +10,6 @@ inputs:
|
||||
anthropic_api_key:
|
||||
description: "Anthropic API key for Claude Code authentication"
|
||||
required: false
|
||||
github_installation_token:
|
||||
description: "GitHub App installation token"
|
||||
required: false
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
|
||||
+29
-41
@@ -3,6 +3,7 @@ import * as core from "@actions/core";
|
||||
import { createMcpConfig } from "../mcp/config.ts";
|
||||
import { spawn } from "../utils/subprocess.ts";
|
||||
import { boxString, tableString } from "../utils/table.ts";
|
||||
import { instructions } from "./shared.ts";
|
||||
import type { Agent, AgentConfig, AgentResult } from "./types.ts";
|
||||
|
||||
/**
|
||||
@@ -10,6 +11,7 @@ import type { Agent, AgentConfig, AgentResult } from "./types.ts";
|
||||
*/
|
||||
export class ClaudeAgent implements Agent {
|
||||
private apiKey: string;
|
||||
private githubInstallationToken: string;
|
||||
public runStats = {
|
||||
toolsUsed: 0,
|
||||
turns: 0,
|
||||
@@ -17,10 +19,8 @@ export class ClaudeAgent implements Agent {
|
||||
};
|
||||
|
||||
constructor(config: AgentConfig) {
|
||||
if (!config.apiKey) {
|
||||
throw new Error("Claude agent requires an API key");
|
||||
}
|
||||
this.apiKey = config.apiKey;
|
||||
this.githubInstallationToken = config.githubInstallationToken;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,10 +49,7 @@ export class ClaudeAgent implements Agent {
|
||||
try {
|
||||
const result = await spawn({
|
||||
cmd: "bash",
|
||||
args: [
|
||||
"-c",
|
||||
"curl -fsSL https://claude.ai/install.sh | bash -s 1.0.93",
|
||||
],
|
||||
args: ["-c", "curl -fsSL https://claude.ai/install.sh | bash -s 1.0.93"],
|
||||
env: { ANTHROPIC_API_KEY: this.apiKey },
|
||||
timeout: 120000, // 2 minute timeout
|
||||
onStdout: () => {},
|
||||
@@ -60,9 +57,7 @@ export class ClaudeAgent implements Agent {
|
||||
});
|
||||
|
||||
if (result.exitCode !== 0) {
|
||||
throw new Error(
|
||||
`Installation failed with exit code ${result.exitCode}: ${result.stderr}`
|
||||
);
|
||||
throw new Error(`Installation failed with exit code ${result.exitCode}: ${result.stderr}`);
|
||||
}
|
||||
|
||||
core.info("Claude Code installed successfully");
|
||||
@@ -79,7 +74,16 @@ export class ClaudeAgent implements Agent {
|
||||
|
||||
try {
|
||||
const claudePath = `${process.env.HOME}/.local/bin/claude`;
|
||||
|
||||
const env = {
|
||||
ANTHROPIC_API_KEY: this.apiKey,
|
||||
};
|
||||
|
||||
console.log(boxString(prompt, { title: "Prompt" }));
|
||||
|
||||
const mcpConfig = createMcpConfig(this.githubInstallationToken);
|
||||
console.log("📋 MCP Config:", mcpConfig);
|
||||
|
||||
const args = [
|
||||
"--print",
|
||||
"--output-format",
|
||||
@@ -88,22 +92,10 @@ export class ClaudeAgent implements Agent {
|
||||
"--debug",
|
||||
"--permission-mode",
|
||||
"bypassPermissions",
|
||||
"--mcp-config",
|
||||
mcpConfig,
|
||||
];
|
||||
|
||||
if (!process.env.GITHUB_INSTALLATION_TOKEN) {
|
||||
throw new Error(
|
||||
"GITHUB_INSTALLATION_TOKEN is required for GitHub integration"
|
||||
);
|
||||
}
|
||||
|
||||
const mcpConfig = createMcpConfig(process.env.GITHUB_INSTALLATION_TOKEN);
|
||||
console.log("📋 MCP Config:", mcpConfig);
|
||||
args.push("--mcp-config", mcpConfig);
|
||||
|
||||
const env = {
|
||||
ANTHROPIC_API_KEY: this.apiKey,
|
||||
};
|
||||
|
||||
core.startGroup("🔄 Run details");
|
||||
|
||||
this.runStats = {
|
||||
@@ -119,7 +111,7 @@ export class ClaudeAgent implements Agent {
|
||||
cmd: claudePath,
|
||||
args,
|
||||
env,
|
||||
input: prompt,
|
||||
input: `${instructions} ${prompt}`,
|
||||
timeout: 10 * 60 * 1000, // 10 minutes
|
||||
onStdout: (_chunk) => {
|
||||
processJSONChunk(_chunk, this);
|
||||
@@ -159,8 +151,7 @@ export class ClaudeAgent implements Agent {
|
||||
try {
|
||||
core.endGroup();
|
||||
} catch {}
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : "Unknown error";
|
||||
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
||||
return {
|
||||
success: false,
|
||||
error: `Failed to execute Claude Code: ${errorMessage}`,
|
||||
@@ -174,8 +165,15 @@ export class ClaudeAgent implements Agent {
|
||||
*/
|
||||
function processJSONChunk(chunk: string, agent?: ClaudeAgent): void {
|
||||
try {
|
||||
// Skip debug lines that start with [DEBUG] or [debug]
|
||||
const trimmedChunk = chunk.trim();
|
||||
if (trimmedChunk.startsWith("[DEBUG]") || trimmedChunk.startsWith("[debug]")) {
|
||||
console.log(chunk);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(chunk);
|
||||
const parsedChunk = JSON.parse(chunk.trim());
|
||||
const parsedChunk = JSON.parse(trimmedChunk);
|
||||
|
||||
switch (parsedChunk.type) {
|
||||
case "system":
|
||||
@@ -186,12 +184,7 @@ function processJSONChunk(chunk: string, agent?: ClaudeAgent): void {
|
||||
["model", parsedChunk.model],
|
||||
["cwd", parsedChunk.cwd],
|
||||
["permission_mode", parsedChunk.permissionMode],
|
||||
[
|
||||
"tools",
|
||||
parsedChunk.tools?.length
|
||||
? `${parsedChunk.tools.length} tools`
|
||||
: "none",
|
||||
],
|
||||
["tools", parsedChunk.tools?.length ? `${parsedChunk.tools.length} tools` : "none"],
|
||||
[
|
||||
"mcp_servers",
|
||||
parsedChunk.mcp_servers?.length
|
||||
@@ -218,9 +211,7 @@ function processJSONChunk(chunk: string, agent?: ClaudeAgent): void {
|
||||
for (const content of parsedChunk.message.content) {
|
||||
if (content.type === "text") {
|
||||
if (content.text.trim()) {
|
||||
core.info(
|
||||
boxString(content.text.trim(), { title: "Claude Code" })
|
||||
);
|
||||
core.info(boxString(content.text.trim(), { title: "Claude Code" }));
|
||||
}
|
||||
} else if (content.type === "tool_use") {
|
||||
if (agent) {
|
||||
@@ -305,10 +296,7 @@ function processJSONChunk(chunk: string, agent?: ClaudeAgent): void {
|
||||
if (parsedChunk.subtype === "success") {
|
||||
core.info(
|
||||
tableString([
|
||||
[
|
||||
"Cost",
|
||||
`$${parsedChunk.total_cost_usd?.toFixed(4) || "0.0000"}`,
|
||||
],
|
||||
["Cost", `$${parsedChunk.total_cost_usd?.toFixed(4) || "0.0000"}`],
|
||||
["Input Tokens", parsedChunk.usage?.input_tokens || 0],
|
||||
["Output Tokens", parsedChunk.usage?.output_tokens || 0],
|
||||
["Duration", `${parsedChunk.duration_ms}ms`],
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { mcpServerName } from "../mcp/config.ts";
|
||||
|
||||
export const instructions = `- use the ${mcpServerName} MCP server to interact with github
|
||||
- if ${mcpServerName} is not available or doesn't include the functionality you need, describe why and bail
|
||||
- do not under any circumstances use the gh cli
|
||||
- if prompted by a comment to respond to create a new issue, pr or anything else, after succeeding,
|
||||
also respond to the original comment with a very brief message containing a link to it
|
||||
`;
|
||||
+2
-2
@@ -29,6 +29,6 @@ export interface AgentResult {
|
||||
* Configuration for agent creation
|
||||
*/
|
||||
export interface AgentConfig {
|
||||
apiKey?: string;
|
||||
[key: string]: any;
|
||||
apiKey: string;
|
||||
githubInstallationToken: string;
|
||||
}
|
||||
|
||||
+5
-9
@@ -1,13 +1,9 @@
|
||||
import type { MainParams } from "../main.ts";
|
||||
import type { Inputs } from "../main.ts";
|
||||
|
||||
const testParams = {
|
||||
inputs: {
|
||||
prompt:
|
||||
"List all files in the current directory, then create a file called dynamic-test.txt with the content 'This was loaded from a TypeScript file!', then delete it.",
|
||||
anthropic_api_key: "sk-test-key",
|
||||
},
|
||||
env: {},
|
||||
cwd: process.cwd(),
|
||||
} satisfies MainParams;
|
||||
prompt:
|
||||
"List all files in the current directory, then create a file called dynamic-test.txt with the content 'This was loaded from a TypeScript file!', then delete it.",
|
||||
anthropic_api_key: "sk-test-key",
|
||||
} satisfies Inputs;
|
||||
|
||||
export default testParams;
|
||||
|
||||
+1
-3
@@ -1,3 +1 @@
|
||||
Use the MCP GitHub comment tool to add a comment containing your best frog joke to GitHub issue https://github.com/pullfrogai/scratch/issues/2.
|
||||
|
||||
Do not use the gh cli. If the mcp tool does not work, bail.
|
||||
create a PR implementing bogosort to https://github.com/pullfrogai/scratch/
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
export { ClaudeAgent } from "./agents/claude.ts";
|
||||
export type { Agent, AgentConfig, AgentResult } from "./agents/types.ts";
|
||||
export {
|
||||
type ActionInputs as ExecutionInputs,
|
||||
type Inputs as ExecutionInputs,
|
||||
type MainResult,
|
||||
main,
|
||||
} from "./main.ts";
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import * as core from "@actions/core";
|
||||
import { type } from "arktype";
|
||||
import { ClaudeAgent } from "./agents/claude.ts";
|
||||
import { setupGitHubInstallationToken, parseRepoContext } from "./utils/github.ts";
|
||||
import { setupGitConfig, setupGitAuth } from "./utils/setup.ts";
|
||||
|
||||
export const Inputs = type({
|
||||
prompt: "string",
|
||||
"anthropic_api_key?": "string | undefined",
|
||||
"github_installation_token?": "string | undefined",
|
||||
});
|
||||
|
||||
export type ActionInputs = typeof Inputs.infer;
|
||||
export type Inputs = typeof Inputs.infer;
|
||||
|
||||
export interface MainResult {
|
||||
success: boolean;
|
||||
@@ -16,11 +17,22 @@ export interface MainResult {
|
||||
error?: string | undefined;
|
||||
}
|
||||
|
||||
export async function main(inputs: ActionInputs): Promise<MainResult> {
|
||||
export async function main(inputs: Inputs): Promise<MainResult> {
|
||||
try {
|
||||
core.info(`→ Starting agent run with Claude Code`);
|
||||
|
||||
const agent = new ClaudeAgent({ apiKey: inputs.anthropic_api_key! });
|
||||
setupGitConfig();
|
||||
|
||||
const githubInstallationToken = await setupGitHubInstallationToken();
|
||||
const repoContext = parseRepoContext();
|
||||
|
||||
setupGitAuth(githubInstallationToken, repoContext);
|
||||
|
||||
const agent = new ClaudeAgent({
|
||||
apiKey: inputs.anthropic_api_key!,
|
||||
githubInstallationToken,
|
||||
});
|
||||
|
||||
await agent.install();
|
||||
|
||||
const result = await agent.execute(inputs.prompt);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { type } from "arktype";
|
||||
import { contextualize, tool } from "./shared.ts";
|
||||
|
||||
export const Comment = type({
|
||||
issueNumber: type.number.describe("the issue number to comment on"),
|
||||
body: type.string.describe("the comment body content"),
|
||||
});
|
||||
|
||||
export const CommentTool = tool({
|
||||
name: "create_issue_comment",
|
||||
description: "Create a comment on a GitHub issue",
|
||||
parameters: Comment,
|
||||
execute: contextualize(async ({ issueNumber, body }, ctx) => {
|
||||
const result = await ctx.octokit.rest.issues.createComment({
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
issue_number: issueNumber,
|
||||
body: body,
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
commentId: result.data.id,
|
||||
url: result.data.html_url,
|
||||
body: result.data.body,
|
||||
};
|
||||
}),
|
||||
});
|
||||
+6
-9
@@ -1,24 +1,21 @@
|
||||
/**
|
||||
* Simple MCP configuration helper for adding our minimal GitHub comment server
|
||||
*/
|
||||
// const actionPath = process.env.GITHUB_ACTION_PATH || process.cwd();
|
||||
|
||||
import { fromHere } from "@ark/fs";
|
||||
import { parseRepoContext } from "../utils/github.ts";
|
||||
|
||||
const actionPath = fromHere("..");
|
||||
|
||||
export const mcpServerName = "gh-pullfrog";
|
||||
|
||||
export function createMcpConfig(githubInstallationToken: string) {
|
||||
const githubRepository = process.env.GITHUB_REPOSITORY;
|
||||
if (!githubRepository) {
|
||||
throw new Error(
|
||||
"GITHUB_REPOSITORY environment variable is required for MCP GitHub integration"
|
||||
);
|
||||
}
|
||||
const repoContext = parseRepoContext();
|
||||
const githubRepository = `${repoContext.owner}/${repoContext.name}`;
|
||||
|
||||
return JSON.stringify(
|
||||
{
|
||||
mcpServers: {
|
||||
minimal_github_comment: {
|
||||
[mcpServerName]: {
|
||||
command: "node",
|
||||
args: [`${actionPath}/mcp/server.ts`],
|
||||
env: {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { type } from "arktype";
|
||||
import { contextualize, tool } from "./shared.ts";
|
||||
|
||||
export const Issue = type({
|
||||
title: type.string.describe("the title of the issue"),
|
||||
body: type.string.describe("the body content of the issue"),
|
||||
labels: type.string
|
||||
.array()
|
||||
.describe("optional array of label names to apply to the issue")
|
||||
.optional(),
|
||||
assignees: type.string
|
||||
.array()
|
||||
.describe("optional array of usernames to assign to the issue")
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export const IssueTool = tool({
|
||||
name: "create_issue",
|
||||
description: "Create a new GitHub issue",
|
||||
parameters: Issue,
|
||||
execute: contextualize(async ({ title, body, labels, assignees }, ctx) => {
|
||||
const result = await ctx.octokit.rest.issues.create({
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
title: title,
|
||||
body: body,
|
||||
labels: labels ?? [],
|
||||
assignees: assignees ?? [],
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
issueId: result.data.id,
|
||||
number: result.data.number,
|
||||
url: result.data.html_url,
|
||||
title: result.data.title,
|
||||
state: result.data.state,
|
||||
labels: result.data.labels?.map((label) => (typeof label === "string" ? label : label.name)),
|
||||
assignees: result.data.assignees?.map((assignee) => assignee.login),
|
||||
};
|
||||
}),
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
import { execSync } from "node:child_process";
|
||||
import { type } from "arktype";
|
||||
import { contextualize, tool } from "./shared.ts";
|
||||
|
||||
export const PullRequest = type({
|
||||
title: type.string.describe("the title of the pull request"),
|
||||
body: type.string.describe("the body content of the pull request"),
|
||||
base: type.string.describe("the base branch to merge into (e.g., 'main')"),
|
||||
});
|
||||
|
||||
export const PullRequestTool = tool({
|
||||
name: "create_pull_request",
|
||||
description: "Create a pull request from the current branch",
|
||||
parameters: PullRequest,
|
||||
execute: contextualize(async ({ title, body, base }, ctx) => {
|
||||
// Get the current branch name
|
||||
const currentBranch = execSync("git rev-parse --abbrev-ref HEAD", {
|
||||
encoding: "utf8",
|
||||
}).trim();
|
||||
|
||||
console.log(`Current branch: ${currentBranch}`);
|
||||
|
||||
const result = await ctx.octokit.rest.pulls.create({
|
||||
owner: ctx.owner,
|
||||
repo: ctx.name,
|
||||
title: title,
|
||||
body: body,
|
||||
head: currentBranch,
|
||||
base: base,
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
pullRequestId: result.data.id,
|
||||
number: result.data.number,
|
||||
url: result.data.html_url,
|
||||
title: result.data.title,
|
||||
head: result.data.head.ref,
|
||||
base: result.data.base.ref,
|
||||
};
|
||||
}),
|
||||
});
|
||||
+9
-85
@@ -1,92 +1,16 @@
|
||||
#!/usr/bin/env node
|
||||
// Minimal GitHub Issue Comment MCP Server
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
||||
import { Octokit } from "@octokit/rest";
|
||||
import { type } from "arktype";
|
||||
import { z } from "zod";
|
||||
import { resolveRepoContext } from "../utils/repo-context.ts";
|
||||
import { FastMCP } from "fastmcp";
|
||||
import { CommentTool } from "./comment.ts";
|
||||
import { IssueTool } from "./issue.ts";
|
||||
import { PullRequestTool } from "./pr.ts";
|
||||
import { addTools } from "./shared.ts";
|
||||
|
||||
const server = new McpServer({
|
||||
name: "Minimal GitHub Issue Comment Server",
|
||||
const server = new FastMCP({
|
||||
name: "gh-pullfrog",
|
||||
version: "0.0.1",
|
||||
});
|
||||
|
||||
// Define the schema for creating issue comments
|
||||
const Comment = type({
|
||||
issueNumber: type.number.describe("the issue number to comment on"),
|
||||
body: type.string.describe("the comment body content"),
|
||||
});
|
||||
addTools(server, [CommentTool, IssueTool, PullRequestTool]);
|
||||
|
||||
server.tool(
|
||||
"create_issue_comment",
|
||||
"Create a comment on a GitHub issue",
|
||||
{
|
||||
issueNumber: z.number().describe("the issue number to comment on"),
|
||||
body: z.string().describe("the comment body content"),
|
||||
},
|
||||
async ({ issueNumber, body }) => {
|
||||
try {
|
||||
Comment.assert({ issueNumber, body });
|
||||
|
||||
const githubInstallationToken = process.env.GITHUB_INSTALLATION_TOKEN;
|
||||
if (!githubInstallationToken) {
|
||||
throw new Error("GITHUB_INSTALLATION_TOKEN environment variable is required");
|
||||
}
|
||||
|
||||
// Resolve repository context from environment
|
||||
const repoContext = resolveRepoContext();
|
||||
|
||||
const octokit = new Octokit({
|
||||
auth: githubInstallationToken,
|
||||
});
|
||||
|
||||
const result = await octokit.rest.issues.createComment({
|
||||
owner: repoContext.owner,
|
||||
repo: repoContext.name,
|
||||
issue_number: issueNumber,
|
||||
body: body,
|
||||
});
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: JSON.stringify(
|
||||
{
|
||||
success: true,
|
||||
commentId: result.data.id,
|
||||
url: result.data.html_url,
|
||||
body: result.data.body,
|
||||
},
|
||||
null,
|
||||
2
|
||||
),
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error creating comment: ${errorMessage}`,
|
||||
},
|
||||
],
|
||||
error: errorMessage,
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
async function runServer() {
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
process.on("exit", () => {
|
||||
server.close();
|
||||
});
|
||||
}
|
||||
|
||||
await runServer();
|
||||
server.start();
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import { cached } from "@ark/util";
|
||||
import { Octokit } from "@octokit/rest";
|
||||
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
||||
import type { FastMCP, Tool } from "fastmcp";
|
||||
import { parseRepoContext, type RepoContext } from "../utils/github.ts";
|
||||
|
||||
export interface ToolResult {
|
||||
content: {
|
||||
type: "text";
|
||||
text: string;
|
||||
}[];
|
||||
error?: string;
|
||||
isError?: boolean;
|
||||
}
|
||||
|
||||
export const getMcpContext = cached((): McpContext => {
|
||||
const githubInstallationToken = process.env.GITHUB_INSTALLATION_TOKEN;
|
||||
if (!githubInstallationToken) {
|
||||
throw new Error("GITHUB_INSTALLATION_TOKEN environment variable is required");
|
||||
}
|
||||
|
||||
return {
|
||||
...parseRepoContext(),
|
||||
octokit: new Octokit({
|
||||
auth: githubInstallationToken,
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
export interface McpContext extends RepoContext {
|
||||
octokit: Octokit;
|
||||
}
|
||||
|
||||
export const tool = <const params>(tool: Tool<any, StandardSchemaV1<params>>) => tool;
|
||||
|
||||
export const addTools = (server: FastMCP, tools: Tool<any, any>[]) => {
|
||||
for (const tool of tools) {
|
||||
server.addTool(tool);
|
||||
}
|
||||
return server;
|
||||
};
|
||||
|
||||
export const contextualize =
|
||||
<T>(executor: (params: T, ctx: McpContext) => Promise<Record<string, any>>) =>
|
||||
async (params: T): Promise<ToolResult> => {
|
||||
try {
|
||||
const ctx = getMcpContext();
|
||||
const result = await executor(params, ctx);
|
||||
return handleToolSuccess(result);
|
||||
} catch (error) {
|
||||
return handleToolError(error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleToolSuccess = (data: Record<string, any>): ToolResult => {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: JSON.stringify(data, null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
const handleToolError = (error: unknown): ToolResult => {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error: ${errorMessage}`,
|
||||
},
|
||||
],
|
||||
error: errorMessage,
|
||||
isError: true,
|
||||
};
|
||||
};
|
||||
+7
-6
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@pullfrog/action",
|
||||
"version": "0.0.45",
|
||||
"version": "0.0.57",
|
||||
"type": "module",
|
||||
"files": [
|
||||
"index.js",
|
||||
@@ -21,15 +21,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.11.1",
|
||||
"@ark/fs": "0.49.0",
|
||||
"@modelcontextprotocol/sdk": "^1.20.0",
|
||||
"@ark/fs": "0.50.0",
|
||||
"@ark/util": "0.50.0",
|
||||
"@octokit/rest": "^22.0.0",
|
||||
"@octokit/webhooks-types": "^7.6.1",
|
||||
"arktype": "^2.1.22",
|
||||
"@standard-schema/spec": "1.0.0",
|
||||
"arktype": "^2.1.23",
|
||||
"dotenv": "^17.2.3",
|
||||
"execa": "^9.6.0",
|
||||
"table": "^6.9.0",
|
||||
"zod": "^3.24.4"
|
||||
"fastmcp": "^3.20.0",
|
||||
"table": "^6.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.7.2",
|
||||
|
||||
@@ -4,10 +4,9 @@ import { pathToFileURL } from "node:url";
|
||||
import { fromHere } from "@ark/fs";
|
||||
import arg from "arg";
|
||||
import { config } from "dotenv";
|
||||
import { type ActionInputs, main } from "./main.ts";
|
||||
import { type Inputs, main } from "./main.ts";
|
||||
import packageJson from "./package.json" with { type: "json" };
|
||||
import { runAct } from "./utils/act.ts";
|
||||
import { setupGitHubInstallationToken } from "./utils/github.ts";
|
||||
import { setupTestRepo } from "./utils/setup.ts";
|
||||
|
||||
config();
|
||||
@@ -36,16 +35,9 @@ export async function run(
|
||||
console.log(prompt);
|
||||
console.log("─".repeat(50));
|
||||
|
||||
console.log("🔑 Setting up GitHub installation token...");
|
||||
const installationToken = await setupGitHubInstallationToken();
|
||||
process.env.GITHUB_INSTALLATION_TOKEN = installationToken;
|
||||
|
||||
console.log("✅ GitHub installation token setup successfully");
|
||||
|
||||
const inputs: ActionInputs = {
|
||||
const inputs: Inputs = {
|
||||
prompt,
|
||||
anthropic_api_key: process.env.ANTHROPIC_API_KEY,
|
||||
github_installation_token: installationToken,
|
||||
};
|
||||
|
||||
const result = await main(inputs);
|
||||
|
||||
Generated
+291
-25
@@ -12,32 +12,35 @@ importers:
|
||||
specifier: ^1.11.1
|
||||
version: 1.11.1
|
||||
'@ark/fs':
|
||||
specifier: 0.49.0
|
||||
version: 0.49.0
|
||||
'@modelcontextprotocol/sdk':
|
||||
specifier: ^1.20.0
|
||||
version: 1.20.0
|
||||
specifier: 0.50.0
|
||||
version: 0.50.0
|
||||
'@ark/util':
|
||||
specifier: 0.50.0
|
||||
version: 0.50.0
|
||||
'@octokit/rest':
|
||||
specifier: ^22.0.0
|
||||
version: 22.0.0
|
||||
'@octokit/webhooks-types':
|
||||
specifier: ^7.6.1
|
||||
version: 7.6.1
|
||||
'@standard-schema/spec':
|
||||
specifier: 1.0.0
|
||||
version: 1.0.0
|
||||
arktype:
|
||||
specifier: ^2.1.22
|
||||
version: 2.1.22
|
||||
specifier: ^2.1.23
|
||||
version: 2.1.23
|
||||
dotenv:
|
||||
specifier: ^17.2.3
|
||||
version: 17.2.3
|
||||
execa:
|
||||
specifier: ^9.6.0
|
||||
version: 9.6.0
|
||||
fastmcp:
|
||||
specifier: ^3.20.0
|
||||
version: 3.20.0(arktype@2.1.23)
|
||||
table:
|
||||
specifier: ^6.9.0
|
||||
version: 6.9.0
|
||||
zod:
|
||||
specifier: ^3.24.4
|
||||
version: 3.25.76
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^24.7.2
|
||||
@@ -63,14 +66,20 @@ packages:
|
||||
'@actions/io@1.1.3':
|
||||
resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==}
|
||||
|
||||
'@ark/fs@0.49.0':
|
||||
resolution: {integrity: sha512-AEjAQS/bu1CGIRiKK/XLaQ73cSJHixfexq28wNt+kBpQ0h1RwVIVzaGsn/+5IWw6DEbR7LB+3hil5gzrzEeyZQ==}
|
||||
'@ark/fs@0.50.0':
|
||||
resolution: {integrity: sha512-6OrxNt2T+/pL4RUMZK/aiVRLIS3acNs5uSpHDyZAP6+OXwXchFSQ1lJTH+uuGBlDWeQxPD7VmymYXLF5s1Eyhw==}
|
||||
|
||||
'@ark/schema@0.49.0':
|
||||
resolution: {integrity: sha512-GphZBLpW72iS0v4YkeUtV3YIno35Gimd7+ezbPO9GwEi9kzdUrPVjvf6aXSBAfHikaFc/9pqZOpv3pOXnC71tw==}
|
||||
'@ark/regex@0.0.0':
|
||||
resolution: {integrity: sha512-p4vsWnd/LRGOdGQglbwOguIVhPmCAf5UzquvnDoxqhhPWTP84wWgi1INea8MgJ4SnI2gp37f13oA4Waz9vwNYg==}
|
||||
|
||||
'@ark/util@0.49.0':
|
||||
resolution: {integrity: sha512-/BtnX7oCjNkxi2vi6y1399b+9xd1jnCrDYhZ61f0a+3X8x8DxlK52VgEEzyuC2UQMPACIfYrmHkhD3lGt2GaMA==}
|
||||
'@ark/schema@0.50.0':
|
||||
resolution: {integrity: sha512-hfmP82GltBZDadIOeR3argKNlYYyB2wyzHp0eeAqAOFBQguglMV/S7Ip2q007bRtKxIMLDqFY6tfPie1dtssaQ==}
|
||||
|
||||
'@ark/util@0.50.0':
|
||||
resolution: {integrity: sha512-tIkgIMVRpkfXRQIEf0G2CJryZVtHVrqcWHMDa5QKo0OEEBu0tHkRSIMm4Ln8cd8Bn9TPZtvc/kE2Gma8RESPSg==}
|
||||
|
||||
'@borewit/text-codec@0.1.1':
|
||||
resolution: {integrity: sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==}
|
||||
|
||||
'@fastify/busboy@2.1.1':
|
||||
resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
|
||||
@@ -142,6 +151,16 @@ packages:
|
||||
resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@standard-schema/spec@1.0.0':
|
||||
resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
|
||||
|
||||
'@tokenizer/inflate@0.2.7':
|
||||
resolution: {integrity: sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@tokenizer/token@0.3.0':
|
||||
resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
|
||||
|
||||
'@types/node@24.7.2':
|
||||
resolution: {integrity: sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA==}
|
||||
|
||||
@@ -159,15 +178,23 @@ packages:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-regex@6.2.2:
|
||||
resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
ansi-styles@4.3.0:
|
||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-styles@6.2.3:
|
||||
resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
arg@5.0.2:
|
||||
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
|
||||
|
||||
arktype@2.1.22:
|
||||
resolution: {integrity: sha512-xdzl6WcAhrdahvRRnXaNwsipCgHuNoLobRqhiP8RjnfL9Gp947abGlo68GAIyLtxbD+MLzNyH2YR4kEqioMmYQ==}
|
||||
arktype@2.1.23:
|
||||
resolution: {integrity: sha512-tyxNWX6xJVMb2EPJJ3OjgQS1G/vIeQRrZuY4DeBNQmh8n7geS+czgbauQWB6Pr+RXiOO8ChEey44XdmxsqGmfQ==}
|
||||
|
||||
astral-regex@2.0.0:
|
||||
resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
|
||||
@@ -192,6 +219,10 @@ packages:
|
||||
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
cliui@9.0.1:
|
||||
resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
@@ -247,6 +278,9 @@ packages:
|
||||
ee-first@1.1.1:
|
||||
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
||||
|
||||
emoji-regex@10.6.0:
|
||||
resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
|
||||
|
||||
emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
|
||||
@@ -266,6 +300,10 @@ packages:
|
||||
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
escalade@3.2.0:
|
||||
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
escape-html@1.0.3:
|
||||
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
|
||||
|
||||
@@ -307,10 +345,21 @@ packages:
|
||||
fast-uri@3.1.0:
|
||||
resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
|
||||
|
||||
fastmcp@3.20.0:
|
||||
resolution: {integrity: sha512-W4Mx0Ft0mqb+BvZ2rHijQQSIKCX8FlRhLOCpK22rMJMxFR33rRyoDRa/WZ4+sDTQc099G7JvkrMBpkTJv1O12g==}
|
||||
hasBin: true
|
||||
|
||||
fflate@0.8.2:
|
||||
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
|
||||
|
||||
figures@6.1.0:
|
||||
resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
file-type@21.0.0:
|
||||
resolution: {integrity: sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
finalhandler@2.1.0:
|
||||
resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@@ -326,6 +375,18 @@ packages:
|
||||
function-bind@1.1.2:
|
||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||
|
||||
fuse.js@7.1.0:
|
||||
resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
get-caller-file@2.0.5:
|
||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||
engines: {node: 6.* || 8.* || >= 10.*}
|
||||
|
||||
get-east-asian-width@1.4.0:
|
||||
resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
get-intrinsic@1.3.0:
|
||||
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -366,6 +427,9 @@ packages:
|
||||
resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
ieee754@1.2.1:
|
||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
||||
|
||||
inherits@2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
|
||||
@@ -408,6 +472,10 @@ packages:
|
||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
mcp-proxy@5.9.0:
|
||||
resolution: {integrity: sha512-xonJSkuy4wmwXeykBFl0mjRMt4D0pAGCtFIfBFUz4O80VrO92ruJseIdASJO3wN6MdYHi3vbZLOQol3NsUpg4g==}
|
||||
hasBin: true
|
||||
|
||||
media-typer@1.1.0:
|
||||
resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@@ -562,18 +630,33 @@ packages:
|
||||
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
strict-event-emitter-types@2.0.0:
|
||||
resolution: {integrity: sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==}
|
||||
|
||||
string-width@4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
string-width@7.2.0:
|
||||
resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
strip-ansi@6.0.1:
|
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
strip-ansi@7.1.2:
|
||||
resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
strip-final-newline@4.0.0:
|
||||
resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
strtok3@10.3.4:
|
||||
resolution: {integrity: sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
table@6.9.0:
|
||||
resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
@@ -582,6 +665,10 @@ packages:
|
||||
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
|
||||
engines: {node: '>=0.6'}
|
||||
|
||||
token-types@6.1.1:
|
||||
resolution: {integrity: sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
tunnel@0.0.6:
|
||||
resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==}
|
||||
engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'}
|
||||
@@ -595,6 +682,10 @@ packages:
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
uint8array-extras@1.5.0:
|
||||
resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
undici-types@7.14.0:
|
||||
resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==}
|
||||
|
||||
@@ -602,6 +693,10 @@ packages:
|
||||
resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==}
|
||||
engines: {node: '>=14.0'}
|
||||
|
||||
undici@7.16.0:
|
||||
resolution: {integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==}
|
||||
engines: {node: '>=20.18.1'}
|
||||
|
||||
unicorn-magic@0.3.0:
|
||||
resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -616,6 +711,9 @@ packages:
|
||||
uri-js@4.4.1:
|
||||
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||
|
||||
uri-templates@0.2.0:
|
||||
resolution: {integrity: sha512-EWkjYEN0L6KOfEoOH6Wj4ghQqU7eBZMJqRHQnxQAq+dSEzRPClkWjf8557HkWQXF6BrAUoLSAyy9i3RVTliaNg==}
|
||||
|
||||
vary@1.1.2:
|
||||
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@@ -625,9 +723,48 @@ packages:
|
||||
engines: {node: '>= 8'}
|
||||
hasBin: true
|
||||
|
||||
wrap-ansi@9.0.2:
|
||||
resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
wrappy@1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
|
||||
xsschema@0.3.5:
|
||||
resolution: {integrity: sha512-f+dcy11dTv7aBEEfTbXWnrm/1b/Ds2k4taN0TpN6KCtPAD58kyE/R1znUdrHdBnhIFexj9k+pS1fm6FgtSISrQ==}
|
||||
peerDependencies:
|
||||
'@valibot/to-json-schema': ^1.0.0
|
||||
arktype: ^2.1.20
|
||||
effect: ^3.16.0
|
||||
sury: ^10.0.0
|
||||
zod: ^3.25.0 || ^4.0.0
|
||||
zod-to-json-schema: ^3.24.5
|
||||
peerDependenciesMeta:
|
||||
'@valibot/to-json-schema':
|
||||
optional: true
|
||||
arktype:
|
||||
optional: true
|
||||
effect:
|
||||
optional: true
|
||||
sury:
|
||||
optional: true
|
||||
zod:
|
||||
optional: true
|
||||
zod-to-json-schema:
|
||||
optional: true
|
||||
|
||||
y18n@5.0.8:
|
||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
yargs-parser@22.0.0:
|
||||
resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==}
|
||||
engines: {node: ^20.19.0 || ^22.12.0 || >=23}
|
||||
|
||||
yargs@18.0.0:
|
||||
resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==}
|
||||
engines: {node: ^20.19.0 || ^22.12.0 || >=23}
|
||||
|
||||
yoctocolors@2.1.2:
|
||||
resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -658,13 +795,19 @@ snapshots:
|
||||
|
||||
'@actions/io@1.1.3': {}
|
||||
|
||||
'@ark/fs@0.49.0': {}
|
||||
'@ark/fs@0.50.0': {}
|
||||
|
||||
'@ark/schema@0.49.0':
|
||||
'@ark/regex@0.0.0':
|
||||
dependencies:
|
||||
'@ark/util': 0.49.0
|
||||
'@ark/util': 0.50.0
|
||||
|
||||
'@ark/util@0.49.0': {}
|
||||
'@ark/schema@0.50.0':
|
||||
dependencies:
|
||||
'@ark/util': 0.50.0
|
||||
|
||||
'@ark/util@0.50.0': {}
|
||||
|
||||
'@borewit/text-codec@0.1.1': {}
|
||||
|
||||
'@fastify/busboy@2.1.1': {}
|
||||
|
||||
@@ -753,6 +896,18 @@ snapshots:
|
||||
|
||||
'@sindresorhus/merge-streams@4.0.0': {}
|
||||
|
||||
'@standard-schema/spec@1.0.0': {}
|
||||
|
||||
'@tokenizer/inflate@0.2.7':
|
||||
dependencies:
|
||||
debug: 4.4.3
|
||||
fflate: 0.8.2
|
||||
token-types: 6.1.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@tokenizer/token@0.3.0': {}
|
||||
|
||||
'@types/node@24.7.2':
|
||||
dependencies:
|
||||
undici-types: 7.14.0
|
||||
@@ -778,16 +933,21 @@ snapshots:
|
||||
|
||||
ansi-regex@5.0.1: {}
|
||||
|
||||
ansi-regex@6.2.2: {}
|
||||
|
||||
ansi-styles@4.3.0:
|
||||
dependencies:
|
||||
color-convert: 2.0.1
|
||||
|
||||
ansi-styles@6.2.3: {}
|
||||
|
||||
arg@5.0.2: {}
|
||||
|
||||
arktype@2.1.22:
|
||||
arktype@2.1.23:
|
||||
dependencies:
|
||||
'@ark/schema': 0.49.0
|
||||
'@ark/util': 0.49.0
|
||||
'@ark/regex': 0.0.0
|
||||
'@ark/schema': 0.50.0
|
||||
'@ark/util': 0.50.0
|
||||
|
||||
astral-regex@2.0.0: {}
|
||||
|
||||
@@ -819,6 +979,12 @@ snapshots:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
get-intrinsic: 1.3.0
|
||||
|
||||
cliui@9.0.1:
|
||||
dependencies:
|
||||
string-width: 7.2.0
|
||||
strip-ansi: 7.1.2
|
||||
wrap-ansi: 9.0.2
|
||||
|
||||
color-convert@2.0.1:
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
@@ -862,6 +1028,8 @@ snapshots:
|
||||
|
||||
ee-first@1.1.1: {}
|
||||
|
||||
emoji-regex@10.6.0: {}
|
||||
|
||||
emoji-regex@8.0.0: {}
|
||||
|
||||
encodeurl@2.0.0: {}
|
||||
@@ -874,6 +1042,8 @@ snapshots:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
||||
escalade@3.2.0: {}
|
||||
|
||||
escape-html@1.0.3: {}
|
||||
|
||||
etag@1.8.1: {}
|
||||
@@ -943,10 +1113,43 @@ snapshots:
|
||||
|
||||
fast-uri@3.1.0: {}
|
||||
|
||||
fastmcp@3.20.0(arktype@2.1.23):
|
||||
dependencies:
|
||||
'@modelcontextprotocol/sdk': 1.20.0
|
||||
'@standard-schema/spec': 1.0.0
|
||||
execa: 9.6.0
|
||||
file-type: 21.0.0
|
||||
fuse.js: 7.1.0
|
||||
mcp-proxy: 5.9.0
|
||||
strict-event-emitter-types: 2.0.0
|
||||
undici: 7.16.0
|
||||
uri-templates: 0.2.0
|
||||
xsschema: 0.3.5(arktype@2.1.23)(zod-to-json-schema@3.24.6(zod@3.25.76))(zod@3.25.76)
|
||||
yargs: 18.0.0
|
||||
zod: 3.25.76
|
||||
zod-to-json-schema: 3.24.6(zod@3.25.76)
|
||||
transitivePeerDependencies:
|
||||
- '@valibot/to-json-schema'
|
||||
- arktype
|
||||
- effect
|
||||
- supports-color
|
||||
- sury
|
||||
|
||||
fflate@0.8.2: {}
|
||||
|
||||
figures@6.1.0:
|
||||
dependencies:
|
||||
is-unicode-supported: 2.1.0
|
||||
|
||||
file-type@21.0.0:
|
||||
dependencies:
|
||||
'@tokenizer/inflate': 0.2.7
|
||||
strtok3: 10.3.4
|
||||
token-types: 6.1.1
|
||||
uint8array-extras: 1.5.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
finalhandler@2.1.0:
|
||||
dependencies:
|
||||
debug: 4.4.3
|
||||
@@ -964,6 +1167,12 @@ snapshots:
|
||||
|
||||
function-bind@1.1.2: {}
|
||||
|
||||
fuse.js@7.1.0: {}
|
||||
|
||||
get-caller-file@2.0.5: {}
|
||||
|
||||
get-east-asian-width@1.4.0: {}
|
||||
|
||||
get-intrinsic@1.3.0:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
@@ -1013,6 +1222,8 @@ snapshots:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
ieee754@1.2.1: {}
|
||||
|
||||
inherits@2.0.4: {}
|
||||
|
||||
ipaddr.js@1.9.1: {}
|
||||
@@ -1037,6 +1248,8 @@ snapshots:
|
||||
|
||||
math-intrinsics@1.1.0: {}
|
||||
|
||||
mcp-proxy@5.9.0: {}
|
||||
|
||||
media-typer@1.1.0: {}
|
||||
|
||||
merge-descriptors@2.0.0: {}
|
||||
@@ -1193,18 +1406,34 @@ snapshots:
|
||||
|
||||
statuses@2.0.2: {}
|
||||
|
||||
strict-event-emitter-types@2.0.0: {}
|
||||
|
||||
string-width@4.2.3:
|
||||
dependencies:
|
||||
emoji-regex: 8.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
string-width@7.2.0:
|
||||
dependencies:
|
||||
emoji-regex: 10.6.0
|
||||
get-east-asian-width: 1.4.0
|
||||
strip-ansi: 7.1.2
|
||||
|
||||
strip-ansi@6.0.1:
|
||||
dependencies:
|
||||
ansi-regex: 5.0.1
|
||||
|
||||
strip-ansi@7.1.2:
|
||||
dependencies:
|
||||
ansi-regex: 6.2.2
|
||||
|
||||
strip-final-newline@4.0.0: {}
|
||||
|
||||
strtok3@10.3.4:
|
||||
dependencies:
|
||||
'@tokenizer/token': 0.3.0
|
||||
|
||||
table@6.9.0:
|
||||
dependencies:
|
||||
ajv: 8.17.1
|
||||
@@ -1215,6 +1444,12 @@ snapshots:
|
||||
|
||||
toidentifier@1.0.1: {}
|
||||
|
||||
token-types@6.1.1:
|
||||
dependencies:
|
||||
'@borewit/text-codec': 0.1.1
|
||||
'@tokenizer/token': 0.3.0
|
||||
ieee754: 1.2.1
|
||||
|
||||
tunnel@0.0.6: {}
|
||||
|
||||
type-is@2.0.1:
|
||||
@@ -1225,12 +1460,16 @@ snapshots:
|
||||
|
||||
typescript@5.9.3: {}
|
||||
|
||||
uint8array-extras@1.5.0: {}
|
||||
|
||||
undici-types@7.14.0: {}
|
||||
|
||||
undici@5.29.0:
|
||||
dependencies:
|
||||
'@fastify/busboy': 2.1.1
|
||||
|
||||
undici@7.16.0: {}
|
||||
|
||||
unicorn-magic@0.3.0: {}
|
||||
|
||||
universal-user-agent@7.0.3: {}
|
||||
@@ -1241,14 +1480,41 @@ snapshots:
|
||||
dependencies:
|
||||
punycode: 2.3.1
|
||||
|
||||
uri-templates@0.2.0: {}
|
||||
|
||||
vary@1.1.2: {}
|
||||
|
||||
which@2.0.2:
|
||||
dependencies:
|
||||
isexe: 2.0.0
|
||||
|
||||
wrap-ansi@9.0.2:
|
||||
dependencies:
|
||||
ansi-styles: 6.2.3
|
||||
string-width: 7.2.0
|
||||
strip-ansi: 7.1.2
|
||||
|
||||
wrappy@1.0.2: {}
|
||||
|
||||
xsschema@0.3.5(arktype@2.1.23)(zod-to-json-schema@3.24.6(zod@3.25.76))(zod@3.25.76):
|
||||
optionalDependencies:
|
||||
arktype: 2.1.23
|
||||
zod: 3.25.76
|
||||
zod-to-json-schema: 3.24.6(zod@3.25.76)
|
||||
|
||||
y18n@5.0.8: {}
|
||||
|
||||
yargs-parser@22.0.0: {}
|
||||
|
||||
yargs@18.0.0:
|
||||
dependencies:
|
||||
cliui: 9.0.1
|
||||
escalade: 3.2.0
|
||||
get-caller-file: 2.0.5
|
||||
string-width: 7.2.0
|
||||
y18n: 5.0.8
|
||||
yargs-parser: 22.0.0
|
||||
|
||||
yoctocolors@2.1.2: {}
|
||||
|
||||
zod-to-json-schema@3.24.6(zod@3.25.76):
|
||||
|
||||
+1
-4
@@ -3,7 +3,7 @@ import { existsSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { config } from "dotenv";
|
||||
import { buildAction, setupTestRepo } from "./setup.ts";
|
||||
import { setupTestRepo } from "./setup.ts";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
@@ -19,8 +19,6 @@ export function runAct(prompt: string): void {
|
||||
|
||||
config({ path: envPath });
|
||||
|
||||
buildAction(actionPath);
|
||||
|
||||
const workflowPath = join(tempDir, ".github", "workflows", "pullfrog.yml");
|
||||
|
||||
const distPath = join(actionPath, ".act-dist");
|
||||
@@ -54,7 +52,6 @@ export function runAct(prompt: string): void {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const actCommand = actCommandParts.join(" ");
|
||||
|
||||
console.log("🚀 Running act with prompt:");
|
||||
|
||||
+26
-5
@@ -1,6 +1,5 @@
|
||||
import { createSign } from "node:crypto";
|
||||
import * as core from "@actions/core";
|
||||
import { resolveRepoContext } from "./repo-context.ts";
|
||||
|
||||
export interface InstallationToken {
|
||||
token: string;
|
||||
@@ -55,7 +54,7 @@ function isGitHubActionsEnvironment(): boolean {
|
||||
|
||||
async function acquireTokenViaOIDC(): Promise<string> {
|
||||
core.info("Generating OIDC token...");
|
||||
|
||||
|
||||
const oidcToken = await core.getIDToken("pullfrog-api");
|
||||
core.info("OIDC token generated successfully");
|
||||
|
||||
@@ -208,7 +207,7 @@ const findInstallationId = async (
|
||||
};
|
||||
|
||||
async function acquireTokenViaGitHubApp(): Promise<string> {
|
||||
const repoContext = resolveRepoContext();
|
||||
const repoContext = parseRepoContext();
|
||||
|
||||
const config: GitHubAppConfig = {
|
||||
appId: process.env.GITHUB_APP_ID!,
|
||||
@@ -244,9 +243,31 @@ export async function setupGitHubInstallationToken(): Promise<string> {
|
||||
}
|
||||
|
||||
const token = await acquireNewToken();
|
||||
|
||||
|
||||
core.setSecret(token);
|
||||
process.env.GITHUB_INSTALLATION_TOKEN = token;
|
||||
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
export interface RepoContext {
|
||||
owner: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse repository context from GITHUB_REPOSITORY environment variable.
|
||||
*/
|
||||
export function parseRepoContext(): RepoContext {
|
||||
const githubRepo = process.env.GITHUB_REPOSITORY;
|
||||
if (!githubRepo) {
|
||||
throw new Error("GITHUB_REPOSITORY environment variable is required");
|
||||
}
|
||||
|
||||
const [owner, name] = githubRepo.split("/");
|
||||
if (!owner || !name) {
|
||||
throw new Error(`Invalid GITHUB_REPOSITORY format: ${githubRepo}. Expected 'owner/repo'`);
|
||||
}
|
||||
|
||||
return { owner, name };
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
export interface RepoContext {
|
||||
owner: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve repository context from GITHUB_REPOSITORY environment variable.
|
||||
* Throws if not available.
|
||||
*/
|
||||
export function resolveRepoContext(): RepoContext {
|
||||
const githubRepo = process.env.GITHUB_REPOSITORY;
|
||||
if (!githubRepo) {
|
||||
throw new Error('GITHUB_REPOSITORY environment variable is required');
|
||||
}
|
||||
|
||||
const [owner, name] = githubRepo.split('/');
|
||||
if (!owner || !name) {
|
||||
throw new Error(`Invalid GITHUB_REPOSITORY format: ${githubRepo}. Expected 'owner/repo'`);
|
||||
}
|
||||
|
||||
return { owner, name };
|
||||
}
|
||||
+26
-7
@@ -1,5 +1,6 @@
|
||||
import { execSync } from "node:child_process";
|
||||
import { existsSync, rmSync } from "node:fs";
|
||||
import type { RepoContext } from "./github.ts";
|
||||
|
||||
export interface SetupOptions {
|
||||
tempDir: string;
|
||||
@@ -38,12 +39,30 @@ export function setupTestRepo(options: SetupOptions): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the action bundles
|
||||
* Setup git configuration to avoid identity errors
|
||||
*/
|
||||
export function buildAction(actionPath: string): void {
|
||||
console.log("🔨 Building fresh bundles with esbuild...");
|
||||
execSync("node esbuild.config.js", {
|
||||
cwd: actionPath,
|
||||
stdio: "inherit",
|
||||
});
|
||||
export function setupGitConfig(): void {
|
||||
console.log("🔧 Setting up git configuration...");
|
||||
execSync('git config --global user.email "action@pullfrog.ai"', { stdio: "inherit" });
|
||||
execSync('git config --global user.name "Pullfrog Action"', { stdio: "inherit" });
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup git authentication using GitHub token
|
||||
*/
|
||||
export function setupGitAuth(githubToken: string, repoContext: RepoContext): void {
|
||||
console.log("🔐 Setting up git authentication...");
|
||||
|
||||
// Remove existing git auth headers that actions/checkout might have set
|
||||
try {
|
||||
execSync("git config --unset-all http.https://github.com/.extraheader", { stdio: "inherit" });
|
||||
console.log("✓ Removed existing authentication headers");
|
||||
} catch {
|
||||
console.log("No existing authentication headers to remove");
|
||||
}
|
||||
|
||||
// Update remote URL to embed the token
|
||||
const remoteUrl = `https://x-access-token:${githubToken}@github.com/${repoContext.owner}/${repoContext.name}.git`;
|
||||
execSync(`git remote set-url origin "${remoteUrl}"`, { stdio: "inherit" });
|
||||
console.log("✓ Updated remote URL with authentication token");
|
||||
}
|
||||
|
||||
+3
-1
@@ -6,6 +6,7 @@ export interface SpawnOptions {
|
||||
env?: Record<string, string>;
|
||||
input?: string;
|
||||
timeout?: number;
|
||||
cwd?: string;
|
||||
onStdout?: (chunk: string) => void;
|
||||
onStderr?: (chunk: string) => void;
|
||||
}
|
||||
@@ -21,7 +22,7 @@ export interface SpawnResult {
|
||||
* Spawn a subprocess with streaming callbacks and buffered results
|
||||
*/
|
||||
export async function spawn(options: SpawnOptions): Promise<SpawnResult> {
|
||||
const { cmd, args, env, input, timeout, onStdout, onStderr } = options;
|
||||
const { cmd, args, env, input, timeout, cwd, onStdout, onStderr } = options;
|
||||
|
||||
const startTime = Date.now();
|
||||
let stdoutBuffer = "";
|
||||
@@ -31,6 +32,7 @@ export async function spawn(options: SpawnOptions): Promise<SpawnResult> {
|
||||
const child = nodeSpawn(cmd, args, {
|
||||
env: env ? { ...process.env, ...env } : process.env,
|
||||
stdio: ["pipe", "pipe", "pipe"],
|
||||
cwd: cwd || process.cwd(),
|
||||
});
|
||||
|
||||
let timeoutId: NodeJS.Timeout | undefined;
|
||||
|
||||
Reference in New Issue
Block a user