mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-31 06:42:03 +00:00
- Added functionality to allow users to send follow-up prompts for features in the waiting_approval status, enabling continued work with additional instructions. - Implemented a commit feature that allows users to mark waiting_approval features as verified and commit changes directly. - Updated the UI to include buttons for follow-up and commit actions on Kanban cards and integrated dialogs for user interaction. - Enhanced the feature loader and executor to handle the new status and actions appropriately. This update improves the workflow for managing features that require manual review and enhances user experience in the auto mode.
151 lines
5.0 KiB
JavaScript
151 lines
5.0 KiB
JavaScript
const { query, AbortError } = require("@anthropic-ai/claude-agent-sdk");
|
|
const promptBuilder = require("./prompt-builder");
|
|
const contextManager = require("./context-manager");
|
|
const featureLoader = require("./feature-loader");
|
|
const mcpServerFactory = require("./mcp-server-factory");
|
|
|
|
/**
|
|
* Feature Verifier - Handles feature verification by running tests
|
|
*/
|
|
class FeatureVerifier {
|
|
/**
|
|
* Verify feature tests (runs tests and checks if they pass)
|
|
*/
|
|
async verifyFeatureTests(feature, projectPath, sendToRenderer, execution) {
|
|
console.log(`[FeatureVerifier] Verifying tests for: ${feature.description}`);
|
|
|
|
try {
|
|
const verifyMsg = `\n✅ Verifying tests for: ${feature.description}\n`;
|
|
await contextManager.writeToContextFile(projectPath, feature.id, verifyMsg);
|
|
|
|
sendToRenderer({
|
|
type: "auto_mode_phase",
|
|
featureId: feature.id,
|
|
phase: "verification",
|
|
message: `Verifying tests for: ${feature.description}`,
|
|
});
|
|
|
|
const abortController = new AbortController();
|
|
execution.abortController = abortController;
|
|
|
|
// Create custom MCP server with UpdateFeatureStatus tool
|
|
const featureToolsServer = mcpServerFactory.createFeatureToolsServer(
|
|
featureLoader.updateFeatureStatus.bind(featureLoader),
|
|
projectPath
|
|
);
|
|
|
|
const options = {
|
|
model: "claude-opus-4-5-20251101",
|
|
systemPrompt: promptBuilder.getVerificationPrompt(),
|
|
maxTurns: 1000,
|
|
cwd: projectPath,
|
|
mcpServers: {
|
|
"automaker-tools": featureToolsServer
|
|
},
|
|
allowedTools: ["Read", "Write", "Edit", "Glob", "Grep", "Bash", "mcp__automaker-tools__UpdateFeatureStatus"],
|
|
permissionMode: "acceptEdits",
|
|
sandbox: {
|
|
enabled: true,
|
|
autoAllowBashIfSandboxed: true,
|
|
},
|
|
abortController: abortController,
|
|
};
|
|
|
|
const prompt = promptBuilder.buildVerificationPrompt(feature);
|
|
|
|
const runningTestsMsg =
|
|
"Running Playwright tests to verify feature implementation...\n";
|
|
await contextManager.writeToContextFile(projectPath, feature.id, runningTestsMsg);
|
|
|
|
sendToRenderer({
|
|
type: "auto_mode_progress",
|
|
featureId: feature.id,
|
|
content: runningTestsMsg,
|
|
});
|
|
|
|
const currentQuery = query({ prompt, options });
|
|
execution.query = currentQuery;
|
|
|
|
let responseText = "";
|
|
for await (const msg of currentQuery) {
|
|
// Check if this specific feature was aborted
|
|
if (!execution.isActive()) break;
|
|
|
|
if (msg.type === "assistant" && msg.message?.content) {
|
|
for (const block of msg.message.content) {
|
|
if (block.type === "text") {
|
|
responseText += block.text;
|
|
|
|
await contextManager.writeToContextFile(projectPath, feature.id, block.text);
|
|
|
|
sendToRenderer({
|
|
type: "auto_mode_progress",
|
|
featureId: feature.id,
|
|
content: block.text,
|
|
});
|
|
} else if (block.type === "tool_use") {
|
|
const toolMsg = `\n🔧 Tool: ${block.name}\n`;
|
|
await contextManager.writeToContextFile(projectPath, feature.id, toolMsg);
|
|
|
|
sendToRenderer({
|
|
type: "auto_mode_tool",
|
|
featureId: feature.id,
|
|
tool: block.name,
|
|
input: block.input,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
execution.query = null;
|
|
execution.abortController = null;
|
|
|
|
// Re-load features to check if it was marked as verified or waiting_approval (for skipTests)
|
|
const updatedFeatures = await featureLoader.loadFeatures(projectPath);
|
|
const updatedFeature = updatedFeatures.find((f) => f.id === feature.id);
|
|
// For skipTests features, waiting_approval is also considered a success
|
|
const passes = updatedFeature?.status === "verified" ||
|
|
(updatedFeature?.skipTests && updatedFeature?.status === "waiting_approval");
|
|
|
|
const finalMsg = passes
|
|
? "✓ Verification successful: All tests passed\n"
|
|
: "✗ Tests failed or not all passing - feature remains in progress\n";
|
|
|
|
await contextManager.writeToContextFile(projectPath, feature.id, finalMsg);
|
|
|
|
sendToRenderer({
|
|
type: "auto_mode_progress",
|
|
featureId: feature.id,
|
|
content: finalMsg,
|
|
});
|
|
|
|
return {
|
|
passes,
|
|
message: responseText.substring(0, 500),
|
|
};
|
|
} catch (error) {
|
|
if (error instanceof AbortError || error?.name === "AbortError") {
|
|
console.log("[FeatureVerifier] Verification aborted");
|
|
if (execution) {
|
|
execution.abortController = null;
|
|
execution.query = null;
|
|
}
|
|
return {
|
|
passes: false,
|
|
message: "Verification aborted",
|
|
};
|
|
}
|
|
|
|
console.error("[FeatureVerifier] Error verifying feature:", error);
|
|
if (execution) {
|
|
execution.abortController = null;
|
|
execution.query = null;
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = new FeatureVerifier();
|