UNPKG

@posthog/agent

Version:

TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog

109 lines (106 loc) 3.87 kB
import { query } from '@anthropic-ai/claude-agent-sdk'; import { POSTHOG_NOTIFICATIONS } from '../../acp-extensions.js'; import { EXECUTION_SYSTEM_PROMPT } from '../../agents/execution.js'; import { TodoManager } from '../../todo-manager.js'; import { PermissionMode } from '../../types.js'; const buildStep = async ({ step, context }) => { const { task, cwd, options, logger, promptBuilder, sessionId, mcpServers, gitManager, sendNotification, } = context; const stepLogger = logger.child("BuildStep"); const latestRun = task.latest_run; const prExists = latestRun?.output && typeof latestRun.output === "object" ? latestRun.output.pr_url : null; if (prExists) { stepLogger.info("PR already exists, skipping build phase", { taskId: task.id, }); return { status: "skipped" }; } stepLogger.info("Starting build phase", { taskId: task.id }); await sendNotification(POSTHOG_NOTIFICATIONS.PHASE_START, { sessionId, phase: "build", }); const executionPrompt = await promptBuilder.buildExecutionPrompt(task, cwd); const fullPrompt = `${EXECUTION_SYSTEM_PROMPT}\n\n${executionPrompt}`; const configuredPermissionMode = options.permissionMode ?? (typeof step.permissionMode === "string" ? step.permissionMode : step.permissionMode) ?? PermissionMode.ACCEPT_EDITS; const baseOptions = { model: step.model, cwd, permissionMode: configuredPermissionMode, settingSources: ["local"], mcpServers, // Allow all tools for build phase - full read/write access needed for implementation allowedTools: [ "Task", "Bash", "BashOutput", "KillBash", "Edit", "Read", "Write", "Glob", "Grep", "NotebookEdit", "WebFetch", "WebSearch", "ListMcpResources", "ReadMcpResource", "TodoWrite", ], }; // Add fine-grained permission hook if provided if (options.canUseTool) { baseOptions.canUseTool = options.canUseTool; } const response = query({ prompt: fullPrompt, options: { ...baseOptions, ...(options.queryOverrides || {}) }, }); // Track commits made during Claude Code execution const commitTracker = await gitManager.trackCommitsDuring(); // Track todos from TodoWrite tool calls const todoManager = new TodoManager(context.fileManager, stepLogger); try { for await (const message of response) { const todoList = await todoManager.checkAndPersistFromMessage(message, task.id); if (todoList) { await sendNotification(POSTHOG_NOTIFICATIONS.ARTIFACT, { sessionId, kind: "todos", content: todoList, }); } } } catch (error) { stepLogger.error("Error during build step query", error); throw error; } // Finalize: commit any remaining changes and optionally push const { commitCreated, pushedBranch } = await commitTracker.finalize({ commitMessage: `Implementation for ${task.title}`, push: step.push, }); context.stepResults[step.id] = { commitCreated }; if (!commitCreated) { stepLogger.warn("No changes to commit in build phase", { taskId: task.id }); } else { stepLogger.info("Build commits finalized", { taskId: task.id, pushedBranch, }); } await sendNotification(POSTHOG_NOTIFICATIONS.PHASE_COMPLETE, { sessionId, phase: "build", }); return { status: "completed" }; }; export { buildStep }; //# sourceMappingURL=build.js.map