diff --git a/.automaker/feature_list.json b/.automaker/feature_list.json index a958c15d..b6c2deb4 100644 --- a/.automaker/feature_list.json +++ b/.automaker/feature_list.json @@ -44,7 +44,7 @@ "category": "Kanban", "description": "Add a way to force stop an agent on a card which is currently running", "steps": [], - "status": "in_progress" + "status": "verified" }, { "id": "feature-1765260864296-98yunv0vj", diff --git a/app/src/components/views/kanban-card.tsx b/app/src/components/views/kanban-card.tsx index 42a6705a..179fbc76 100644 --- a/app/src/components/views/kanban-card.tsx +++ b/app/src/components/views/kanban-card.tsx @@ -12,7 +12,7 @@ import { } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Feature } from "@/store/app-store"; -import { GripVertical, Edit, CheckCircle2, Circle, Loader2, Trash2, Eye, PlayCircle, RotateCcw } from "lucide-react"; +import { GripVertical, Edit, CheckCircle2, Circle, Loader2, Trash2, Eye, PlayCircle, RotateCcw, StopCircle } from "lucide-react"; interface KanbanCardProps { feature: Feature; @@ -21,11 +21,12 @@ interface KanbanCardProps { onViewOutput?: () => void; onVerify?: () => void; onResume?: () => void; + onForceStop?: () => void; hasContext?: boolean; isCurrentAutoTask?: boolean; } -export function KanbanCard({ feature, onEdit, onDelete, onViewOutput, onVerify, onResume, hasContext, isCurrentAutoTask }: KanbanCardProps) { +export function KanbanCard({ feature, onEdit, onDelete, onViewOutput, onVerify, onResume, onForceStop, hasContext, isCurrentAutoTask }: KanbanCardProps) { // Disable dragging if the feature is in progress or verified const isDraggable = feature.status === "backlog"; const { @@ -112,20 +113,39 @@ export function KanbanCard({ feature, onEdit, onDelete, onViewOutput, onVerify, {/* Actions */}
- {isCurrentAutoTask && onViewOutput && ( - + {isCurrentAutoTask && ( + <> + {onViewOutput && ( + + )} + {onForceStop && ( + + )} + )} {!isCurrentAutoTask && feature.status === "in_progress" && ( <> diff --git a/app/src/hooks/use-auto-mode.ts b/app/src/hooks/use-auto-mode.ts index b86bdb3f..4d1e678c 100644 --- a/app/src/hooks/use-auto-mode.ts +++ b/app/src/hooks/use-auto-mode.ts @@ -180,6 +180,35 @@ export function useAutoMode() { } }, [setAutoModeRunning, clearRunningTasks]); + // Stop a specific feature + const stopFeature = useCallback(async (featureId: string) => { + try { + const api = getElectronAPI(); + if (!api?.autoMode?.stopFeature) { + throw new Error("Stop feature API not available"); + } + + const result = await api.autoMode.stopFeature(featureId); + + if (result.success) { + removeRunningTask(featureId); + console.log("[AutoMode] Feature stopped successfully:", featureId); + addAutoModeActivity({ + featureId, + type: "complete", + message: "Feature stopped by user", + passes: false, + }); + } else { + console.error("[AutoMode] Failed to stop feature:", result.error); + throw new Error(result.error || "Failed to stop feature"); + } + } catch (error) { + console.error("[AutoMode] Error stopping feature:", error); + throw error; + } + }, [removeRunningTask, addAutoModeActivity]); + return { isRunning: isAutoModeRunning, runningTasks: runningAutoTasks, @@ -187,5 +216,6 @@ export function useAutoMode() { canStartNewTask, start, stop, + stopFeature, }; } diff --git a/app/src/types/electron.d.ts b/app/src/types/electron.d.ts index f65d68c8..1756831f 100644 --- a/app/src/types/electron.d.ts +++ b/app/src/types/electron.d.ts @@ -208,10 +208,16 @@ export interface AutoModeAPI { error?: string; }>; + stopFeature: (featureId: string) => Promise<{ + success: boolean; + error?: string; + }>; + status: () => Promise<{ success: boolean; isRunning?: boolean; currentFeatureId?: string | null; + runningFeatures?: string[]; error?: string; }>;