UNPKG

miyabi-agent-sdk

Version:

Miyabi Autonomous Agent SDK - 7 Agents based on Shikigaku Theory with 100% cost reduction mode

204 lines (195 loc) 6.71 kB
/** * Claude Code Client * * Phase 9: Integration with Claude Code CLI * * This client replaces AnthropicClient by using the local Claude Code CLI * instead of calling external Anthropic API. * * Usage: * const client = new ClaudeCodeClient(); * const response = await client.executePrompt("Analyze this issue..."); */ import { spawn } from "child_process"; export class ClaudeCodeClient { codexCommand; constructor(codexCommand = "codex") { this.codexCommand = codexCommand; } /** * Execute a prompt using Claude Code CLI * * @param prompt - The prompt to execute * @param options - Additional options * @returns The response from Claude Code */ async executePrompt(prompt, options) { return new Promise((resolve, reject) => { const args = ["exec", prompt]; const proc = spawn(this.codexCommand, args, { cwd: options?.workingDir || process.cwd(), shell: true, }); let stdout = ""; let stderr = ""; proc.stdout.on("data", (data) => { stdout += data.toString(); }); proc.stderr.on("data", (data) => { stderr += data.toString(); }); // Handle timeout const timeoutId = options?.timeout ? setTimeout(() => { proc.kill(); reject(new Error(`Claude Code execution timed out after ${options.timeout}ms`)); }, options.timeout) : null; proc.on("close", (code) => { if (timeoutId) clearTimeout(timeoutId); if (code === 0) { resolve({ content: stdout.trim(), // Claude Code doesn't provide token usage, so we estimate tokensUsed: { input: Math.floor(prompt.length / 4), // rough estimate output: Math.floor(stdout.length / 4), }, cost: 0, // Free when using local Claude Code }); } else { reject(new Error(`Claude Code failed with exit code ${code}\nStderr: ${stderr}`)); } }); proc.on("error", (error) => { if (timeoutId) clearTimeout(timeoutId); reject(new Error(`Failed to spawn Claude Code: ${error.message}`)); }); }); } /** * Analyze a GitHub issue using Claude Code * * @param issueData - Issue data to analyze * @returns Analysis result */ async analyzeIssue(issueData) { const prompt = `Analyze this GitHub issue and return ONLY a JSON object (no markdown code blocks): Issue #${issueData.number}: ${issueData.title} ${issueData.body} Return JSON format: { "type": "bug|feature|refactor|docs|test", "complexity": "small|medium|large|xlarge", "priority": "P0|P1|P2|P3", "relatedFiles": ["file1.ts", "file2.ts"], "labels": ["🏷️ type:bug", "🎯 priority:P2-Medium", ...] }`; const response = await this.executePrompt(prompt, { timeout: 60000 }); try { // Try to extract JSON from response const jsonMatch = response.content.match(/\{[\s\S]*\}/); if (!jsonMatch) { throw new Error("No JSON found in response"); } const parsed = JSON.parse(jsonMatch[0]); return parsed; } catch (error) { console.error("[ClaudeCodeClient] Failed to parse issue analysis:", error); console.error("[ClaudeCodeClient] Response:", response.content); throw new Error(`Failed to parse issue analysis: ${error}`); } } /** * Generate code using Claude Code * * @param requirements - Code generation requirements * @returns Generated files */ async generateCode(requirements) { const prompt = `Generate code for this task. Return ONLY a JSON object (no markdown code blocks): Task: ${requirements.requirements} Context: ${requirements.context} Language: ${requirements.language} Return JSON format: { "files": [ { "path": "src/example.ts", "content": "...", "action": "create" } ], "tests": [ { "path": "src/example.test.ts", "content": "...", "action": "create" } ], "qualityScore": 95 }`; const response = await this.executePrompt(prompt, { timeout: 120000 }); try { // Try to extract JSON from response const jsonMatch = response.content.match(/\{[\s\S]*\}/); if (!jsonMatch) { throw new Error("No JSON found in response"); } const parsed = JSON.parse(jsonMatch[0]); return parsed; } catch (error) { console.error("[ClaudeCodeClient] Failed to parse code generation:", error); console.error("[ClaudeCodeClient] Response:", response.content); throw new Error(`Failed to parse code generation: ${error}`); } } /** * Review code using Claude Code * * @param files - Files to review * @returns Review result */ async reviewCode(files) { const filesStr = files .map((f) => `File: ${f.path}\n\`\`\`\n${f.content}\n\`\`\``) .join("\n\n"); const prompt = `Review this code and return ONLY a JSON object (no markdown code blocks): ${filesStr} Return JSON format: { "qualityScore": 85, "passed": true, "issues": [ { "severity": "warning", "message": "Consider adding error handling", "file": "src/example.ts", "line": 42 } ], "suggestions": ["Add more test cases", "Improve documentation"] }`; const response = await this.executePrompt(prompt, { timeout: 90000 }); try { // Try to extract JSON from response const jsonMatch = response.content.match(/\{[\s\S]*\}/); if (!jsonMatch) { throw new Error("No JSON found in response"); } const parsed = JSON.parse(jsonMatch[0]); return parsed; } catch (error) { console.error("[ClaudeCodeClient] Failed to parse code review:", error); console.error("[ClaudeCodeClient] Response:", response.content); throw new Error(`Failed to parse code review: ${error}`); } } } //# sourceMappingURL=ClaudeCodeClient.js.map