mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-04 09:13:08 +00:00
fix comment gemini
This commit is contained in:
@@ -9,30 +9,12 @@ import { Label } from "@/components/ui/label";
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import type { PlanSpec } from "@/store/app-store";
|
||||||
|
|
||||||
export type PlanningMode = 'skip' | 'lite' | 'spec' | 'full';
|
export type PlanningMode = 'skip' | 'lite' | 'spec' | 'full';
|
||||||
|
|
||||||
// Parsed task from spec (for spec and full planning modes)
|
// Re-export for backwards compatibility
|
||||||
export interface ParsedTask {
|
export type { ParsedTask, PlanSpec } from "@/store/app-store";
|
||||||
id: string; // e.g., "T001"
|
|
||||||
description: string; // e.g., "Create user model"
|
|
||||||
filePath?: string; // e.g., "src/models/user.ts"
|
|
||||||
phase?: string; // e.g., "Phase 1: Foundation" (for full mode)
|
|
||||||
status: 'pending' | 'in_progress' | 'completed' | 'failed';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PlanSpec {
|
|
||||||
status: 'pending' | 'generating' | 'generated' | 'approved' | 'rejected';
|
|
||||||
content?: string;
|
|
||||||
version: number;
|
|
||||||
generatedAt?: string;
|
|
||||||
approvedAt?: string;
|
|
||||||
reviewedByUser: boolean;
|
|
||||||
tasksCompleted?: number;
|
|
||||||
tasksTotal?: number;
|
|
||||||
currentTaskId?: string; // ID of the task currently being worked on
|
|
||||||
tasks?: ParsedTask[]; // Parsed tasks from the spec
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PlanningModeSelectorProps {
|
interface PlanningModeSelectorProps {
|
||||||
mode: PlanningMode;
|
mode: PlanningMode;
|
||||||
|
|||||||
@@ -156,12 +156,7 @@ export function useAutoMode() {
|
|||||||
case "auto_mode_error":
|
case "auto_mode_error":
|
||||||
if (event.featureId && event.error) {
|
if (event.featureId && event.error) {
|
||||||
// Check if this is a user-initiated cancellation (not a real error)
|
// Check if this is a user-initiated cancellation (not a real error)
|
||||||
const isCancellation =
|
if (event.errorType === "cancellation") {
|
||||||
event.error.includes("cancelled") ||
|
|
||||||
event.error.includes("stopped") ||
|
|
||||||
event.error.includes("aborted");
|
|
||||||
|
|
||||||
if (isCancellation) {
|
|
||||||
// User cancelled the feature - just log as info, not an error
|
// User cancelled the feature - just log as info, not an error
|
||||||
console.log("[AutoMode] Feature cancelled:", event.error);
|
console.log("[AutoMode] Feature cancelled:", event.error);
|
||||||
// Remove from running tasks
|
// Remove from running tasks
|
||||||
|
|||||||
2
apps/app/src/types/electron.d.ts
vendored
2
apps/app/src/types/electron.d.ts
vendored
@@ -193,7 +193,7 @@ export type AutoModeEvent =
|
|||||||
| {
|
| {
|
||||||
type: "auto_mode_error";
|
type: "auto_mode_error";
|
||||||
error: string;
|
error: string;
|
||||||
errorType?: "authentication" | "execution";
|
errorType?: "authentication" | "cancellation" | "execution";
|
||||||
featureId?: string;
|
featureId?: string;
|
||||||
projectId?: string;
|
projectId?: string;
|
||||||
projectPath?: string;
|
projectPath?: string;
|
||||||
|
|||||||
@@ -21,6 +21,22 @@ export function isAbortError(error: unknown): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an error is a user-initiated cancellation
|
||||||
|
*
|
||||||
|
* @param errorMessage - The error message to check
|
||||||
|
* @returns True if the error is a user-initiated cancellation
|
||||||
|
*/
|
||||||
|
export function isCancellationError(errorMessage: string): boolean {
|
||||||
|
const lowerMessage = errorMessage.toLowerCase();
|
||||||
|
return (
|
||||||
|
lowerMessage.includes("cancelled") ||
|
||||||
|
lowerMessage.includes("canceled") ||
|
||||||
|
lowerMessage.includes("stopped") ||
|
||||||
|
lowerMessage.includes("aborted")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if an error is an authentication/API key error
|
* Check if an error is an authentication/API key error
|
||||||
*
|
*
|
||||||
@@ -39,7 +55,7 @@ export function isAuthenticationError(errorMessage: string): boolean {
|
|||||||
/**
|
/**
|
||||||
* Error type classification
|
* Error type classification
|
||||||
*/
|
*/
|
||||||
export type ErrorType = "authentication" | "abort" | "execution" | "unknown";
|
export type ErrorType = "authentication" | "cancellation" | "abort" | "execution" | "unknown";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Classified error information
|
* Classified error information
|
||||||
@@ -49,6 +65,7 @@ export interface ErrorInfo {
|
|||||||
message: string;
|
message: string;
|
||||||
isAbort: boolean;
|
isAbort: boolean;
|
||||||
isAuth: boolean;
|
isAuth: boolean;
|
||||||
|
isCancellation: boolean;
|
||||||
originalError: unknown;
|
originalError: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,12 +79,13 @@ export function classifyError(error: unknown): ErrorInfo {
|
|||||||
const message = error instanceof Error ? error.message : String(error || "Unknown error");
|
const message = error instanceof Error ? error.message : String(error || "Unknown error");
|
||||||
const isAbort = isAbortError(error);
|
const isAbort = isAbortError(error);
|
||||||
const isAuth = isAuthenticationError(message);
|
const isAuth = isAuthenticationError(message);
|
||||||
|
const isCancellation = isCancellationError(message);
|
||||||
|
|
||||||
let type: ErrorType;
|
let type: ErrorType;
|
||||||
if (isAuth) {
|
if (isAuth) {
|
||||||
type = "authentication";
|
type = "authentication";
|
||||||
} else if (isAbort) {
|
} else if (isCancellation || isAbort) {
|
||||||
type = "abort";
|
type = "cancellation";
|
||||||
} else if (error instanceof Error) {
|
} else if (error instanceof Error) {
|
||||||
type = "execution";
|
type = "execution";
|
||||||
} else {
|
} else {
|
||||||
@@ -79,6 +97,7 @@ export function classifyError(error: unknown): ErrorInfo {
|
|||||||
message,
|
message,
|
||||||
isAbort,
|
isAbort,
|
||||||
isAuth,
|
isAuth,
|
||||||
|
isCancellation,
|
||||||
originalError: error,
|
originalError: error,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import type { EventEmitter } from "../lib/events.js";
|
|||||||
import { buildPromptWithImages } from "../lib/prompt-builder.js";
|
import { buildPromptWithImages } from "../lib/prompt-builder.js";
|
||||||
import { resolveModelString, DEFAULT_MODELS } from "../lib/model-resolver.js";
|
import { resolveModelString, DEFAULT_MODELS } from "../lib/model-resolver.js";
|
||||||
import { createAutoModeOptions } from "../lib/sdk-options.js";
|
import { createAutoModeOptions } from "../lib/sdk-options.js";
|
||||||
import { isAbortError, classifyError } from "../lib/error-handler.js";
|
import { classifyError } from "../lib/error-handler.js";
|
||||||
import { resolveDependencies, areDependenciesSatisfied } from "../lib/dependency-resolver.js";
|
import { resolveDependencies, areDependenciesSatisfied } from "../lib/dependency-resolver.js";
|
||||||
import type { Feature } from "./feature-loader.js";
|
import type { Feature } from "./feature-loader.js";
|
||||||
import {
|
import {
|
||||||
@@ -362,8 +362,10 @@ export class AutoModeService {
|
|||||||
// Run the loop in the background
|
// Run the loop in the background
|
||||||
this.runAutoLoop().catch((error) => {
|
this.runAutoLoop().catch((error) => {
|
||||||
console.error("[AutoMode] Loop error:", error);
|
console.error("[AutoMode] Loop error:", error);
|
||||||
|
const errorInfo = classifyError(error);
|
||||||
this.emitAutoModeEvent("auto_mode_error", {
|
this.emitAutoModeEvent("auto_mode_error", {
|
||||||
error: error.message,
|
error: errorInfo.message,
|
||||||
|
errorType: errorInfo.type,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -457,7 +459,10 @@ export class AutoModeService {
|
|||||||
featureId: string,
|
featureId: string,
|
||||||
useWorktrees = false,
|
useWorktrees = false,
|
||||||
isAutoMode = false,
|
isAutoMode = false,
|
||||||
providedWorktreePath?: string
|
providedWorktreePath?: string,
|
||||||
|
options?: {
|
||||||
|
continuationPrompt?: string;
|
||||||
|
}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (this.runningFeatures.has(featureId)) {
|
if (this.runningFeatures.has(featureId)) {
|
||||||
throw new Error(`Feature ${featureId} is already running`);
|
throw new Error(`Feature ${featureId} is already running`);
|
||||||
@@ -531,18 +536,27 @@ export class AutoModeService {
|
|||||||
// Update feature status to in_progress
|
// Update feature status to in_progress
|
||||||
await this.updateFeatureStatus(projectPath, featureId, "in_progress");
|
await this.updateFeatureStatus(projectPath, featureId, "in_progress");
|
||||||
|
|
||||||
// Build the prompt with planning phase
|
// Build the prompt - use continuation prompt if provided (for recovery after plan approval)
|
||||||
const featurePrompt = this.buildFeaturePrompt(feature);
|
let prompt: string;
|
||||||
const planningPrefix = this.getPlanningPromptPrefix(feature);
|
if (options?.continuationPrompt) {
|
||||||
const prompt = planningPrefix + featurePrompt;
|
// Continuation prompt is used when recovering from a plan approval
|
||||||
|
// The plan was already approved, so skip the planning phase
|
||||||
|
prompt = options.continuationPrompt;
|
||||||
|
console.log(`[AutoMode] Using continuation prompt for feature ${featureId}`);
|
||||||
|
} else {
|
||||||
|
// Normal flow: build prompt with planning phase
|
||||||
|
const featurePrompt = this.buildFeaturePrompt(feature);
|
||||||
|
const planningPrefix = this.getPlanningPromptPrefix(feature);
|
||||||
|
prompt = planningPrefix + featurePrompt;
|
||||||
|
|
||||||
// Emit planning mode info
|
// Emit planning mode info
|
||||||
if (feature.planningMode && feature.planningMode !== 'skip') {
|
if (feature.planningMode && feature.planningMode !== 'skip') {
|
||||||
this.emitAutoModeEvent('planning_started', {
|
this.emitAutoModeEvent('planning_started', {
|
||||||
featureId: feature.id,
|
featureId: feature.id,
|
||||||
mode: feature.planningMode,
|
mode: feature.planningMode,
|
||||||
message: `Starting ${feature.planningMode} planning phase`
|
message: `Starting ${feature.planningMode} planning phase`
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract image paths from feature
|
// Extract image paths from feature
|
||||||
@@ -602,7 +616,7 @@ export class AutoModeService {
|
|||||||
this.emitAutoModeEvent("auto_mode_error", {
|
this.emitAutoModeEvent("auto_mode_error", {
|
||||||
featureId,
|
featureId,
|
||||||
error: errorInfo.message,
|
error: errorInfo.message,
|
||||||
errorType: errorInfo.isAuth ? "authentication" : "execution",
|
errorType: errorInfo.type,
|
||||||
projectPath,
|
projectPath,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -862,10 +876,12 @@ Address the follow-up instructions above. Review the previous work and make the
|
|||||||
projectPath,
|
projectPath,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!isAbortError(error)) {
|
const errorInfo = classifyError(error);
|
||||||
|
if (!errorInfo.isCancellation) {
|
||||||
this.emitAutoModeEvent("auto_mode_error", {
|
this.emitAutoModeEvent("auto_mode_error", {
|
||||||
featureId,
|
featureId,
|
||||||
error: (error as Error).message,
|
error: errorInfo.message,
|
||||||
|
errorType: errorInfo.type,
|
||||||
projectPath,
|
projectPath,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1109,9 +1125,11 @@ Format your response as a structured markdown document.`;
|
|||||||
projectPath,
|
projectPath,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
const errorInfo = classifyError(error);
|
||||||
this.emitAutoModeEvent("auto_mode_error", {
|
this.emitAutoModeEvent("auto_mode_error", {
|
||||||
featureId: analysisFeatureId,
|
featureId: analysisFeatureId,
|
||||||
error: (error as Error).message,
|
error: errorInfo.message,
|
||||||
|
errorType: errorInfo.type,
|
||||||
projectPath,
|
projectPath,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1219,7 +1237,10 @@ Format your response as a structured markdown document.`;
|
|||||||
console.log(`[AutoMode] Starting recovery execution for feature ${featureId}`);
|
console.log(`[AutoMode] Starting recovery execution for feature ${featureId}`);
|
||||||
|
|
||||||
// Start feature execution with the continuation prompt (async, don't await)
|
// Start feature execution with the continuation prompt (async, don't await)
|
||||||
this.executeFeature(projectPathFromClient, featureId, true, false, continuationPrompt)
|
// Pass undefined for providedWorktreePath, use options for continuation prompt
|
||||||
|
this.executeFeature(projectPathFromClient, featureId, true, false, undefined, {
|
||||||
|
continuationPrompt,
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error(`[AutoMode] Recovery execution failed for feature ${featureId}:`, error);
|
console.error(`[AutoMode] Recovery execution failed for feature ${featureId}:`, error);
|
||||||
});
|
});
|
||||||
@@ -2306,7 +2327,9 @@ ${context}
|
|||||||
## Instructions
|
## Instructions
|
||||||
Review the previous work and continue the implementation. If the feature appears complete, verify it works correctly.`;
|
Review the previous work and continue the implementation. If the feature appears complete, verify it works correctly.`;
|
||||||
|
|
||||||
return this.executeFeature(projectPath, featureId, useWorktrees, false, prompt);
|
return this.executeFeature(projectPath, featureId, useWorktrees, false, undefined, {
|
||||||
|
continuationPrompt: prompt,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user