Refactor action with agent interface system and make anthropic_api_key optional
- Created extensible agent interface with install() and execute() methods - Moved Claude Code logic to agents/claude.ts implementing Agent interface - Added utilities directory for reusable functions (exec, files) - Refactored index.ts to be minimal (35 lines) using agent abstraction - Made anthropic_api_key optional in action.yml - Updated Node.js imports to use node: prefix convention - Bumped version to 0.0.5 - Architecture now supports multiple agents (OpenAI, Gemini, etc.)
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import * as core from "@actions/core";
|
||||
import { executeCommand } from "../utils/exec";
|
||||
import { createTempFile } from "../utils/files";
|
||||
import type { Agent, AgentConfig, AgentResult } from "./types";
|
||||
|
||||
/**
|
||||
* Claude Code agent implementation
|
||||
*/
|
||||
export class ClaudeAgent implements Agent {
|
||||
private apiKey: string;
|
||||
|
||||
constructor(config: AgentConfig) {
|
||||
if (!config.apiKey) {
|
||||
throw new Error("Claude agent requires an API key");
|
||||
}
|
||||
this.apiKey = config.apiKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install Claude Code CLI
|
||||
*/
|
||||
async install(): Promise<void> {
|
||||
core.info("Installing Claude Code...");
|
||||
try {
|
||||
await executeCommand("curl -fsSL https://claude.ai/install.sh | bash -s 1.0.93");
|
||||
core.info("Claude Code installed successfully");
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to install Claude Code: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute Claude Code with the given prompt
|
||||
*/
|
||||
async execute(prompt: string): Promise<AgentResult> {
|
||||
core.info("Executing Claude Code...");
|
||||
|
||||
try {
|
||||
// Create a temporary file for the prompt
|
||||
const promptFile = createTempFile(prompt, "prompt.txt");
|
||||
|
||||
// Execute Claude Code with the prompt
|
||||
const command = `$HOME/.local/bin/claude --dangerously-skip-permissions "${promptFile}"`;
|
||||
core.info(`Executing: ${command}`);
|
||||
|
||||
const { stdout, stderr } = await executeCommand(command, {
|
||||
ANTHROPIC_API_KEY: this.apiKey,
|
||||
});
|
||||
|
||||
if (stderr) {
|
||||
core.warning(`Claude Code stderr: ${stderr}`);
|
||||
}
|
||||
|
||||
if (stdout) {
|
||||
core.info("Claude Code output:");
|
||||
console.log(stdout);
|
||||
}
|
||||
|
||||
core.info("Claude Code executed successfully");
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: stdout,
|
||||
error: stderr || undefined,
|
||||
metadata: {
|
||||
promptFile,
|
||||
command,
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
||||
return {
|
||||
success: false,
|
||||
error: `Failed to execute Claude Code: ${errorMessage}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { ClaudeAgent } from "./claude";
|
||||
import type { Agent, AgentConfig } from "./types";
|
||||
|
||||
export type AgentType = "claude";
|
||||
|
||||
/**
|
||||
* Factory for creating agent instances
|
||||
*/
|
||||
export function createAgent(type: AgentType, config: AgentConfig): Agent {
|
||||
switch (type) {
|
||||
case "claude":
|
||||
return new ClaudeAgent(config);
|
||||
default:
|
||||
throw new Error(`Unsupported agent type: ${type}`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from "./claude";
|
||||
export * from "./factory";
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Standard interface for all Pullfrog agents
|
||||
*/
|
||||
export interface Agent {
|
||||
/**
|
||||
* Install the agent and any required dependencies
|
||||
*/
|
||||
install(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Execute the agent with the given prompt
|
||||
* @param prompt The prompt to send to the agent
|
||||
* @param options Additional options specific to the agent
|
||||
*/
|
||||
execute(prompt: string, options?: Record<string, any>): Promise<AgentResult>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Result returned by agent execution
|
||||
*/
|
||||
export interface AgentResult {
|
||||
success: boolean;
|
||||
output?: string;
|
||||
error?: string;
|
||||
metadata?: Record<string, any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration for agent creation
|
||||
*/
|
||||
export interface AgentConfig {
|
||||
apiKey?: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
Reference in New Issue
Block a user