mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-31 20:03:37 +00:00
various fixes
This commit is contained in:
@@ -867,7 +867,8 @@ export function BoardView() {
|
||||
// features often have skipTests=true, and we want status-based handling first
|
||||
if (targetStatus === "verified") {
|
||||
moveFeature(featureId, "verified");
|
||||
persistFeatureUpdate(featureId, { status: "verified" });
|
||||
// Clear justFinished flag when manually verifying via drag
|
||||
persistFeatureUpdate(featureId, { status: "verified", justFinished: false });
|
||||
toast.success("Feature verified", {
|
||||
description: `Manually verified: ${draggedFeature.description.slice(
|
||||
0,
|
||||
@@ -877,7 +878,8 @@ export function BoardView() {
|
||||
} else if (targetStatus === "backlog") {
|
||||
// Allow moving waiting_approval cards back to backlog
|
||||
moveFeature(featureId, "backlog");
|
||||
persistFeatureUpdate(featureId, { status: "backlog" });
|
||||
// Clear justFinished flag when moving back to backlog
|
||||
persistFeatureUpdate(featureId, { status: "backlog", justFinished: false });
|
||||
toast.info("Feature moved to backlog", {
|
||||
description: `Moved to Backlog: ${draggedFeature.description.slice(
|
||||
0,
|
||||
@@ -1198,7 +1200,8 @@ export function BoardView() {
|
||||
description: feature.description,
|
||||
});
|
||||
moveFeature(feature.id, "verified");
|
||||
persistFeatureUpdate(feature.id, { status: "verified" });
|
||||
// Clear justFinished flag when manually verifying
|
||||
persistFeatureUpdate(feature.id, { status: "verified", justFinished: false });
|
||||
toast.success("Feature verified", {
|
||||
description: `Marked as verified: ${feature.description.slice(0, 50)}${
|
||||
feature.description.length > 50 ? "..." : ""
|
||||
@@ -1264,9 +1267,11 @@ export function BoardView() {
|
||||
}
|
||||
|
||||
// Move feature back to in_progress before sending follow-up
|
||||
// Clear justFinished flag since user is now interacting with it
|
||||
const updates = {
|
||||
status: "in_progress" as const,
|
||||
startedAt: new Date().toISOString(),
|
||||
justFinished: false,
|
||||
};
|
||||
updateFeature(featureId, updates);
|
||||
persistFeatureUpdate(featureId, updates);
|
||||
@@ -1525,6 +1530,14 @@ export function BoardView() {
|
||||
}
|
||||
});
|
||||
|
||||
// Sort waiting_approval column: justFinished features go to the top
|
||||
map.waiting_approval.sort((a, b) => {
|
||||
// Features with justFinished=true should appear first
|
||||
if (a.justFinished && !b.justFinished) return -1;
|
||||
if (!a.justFinished && b.justFinished) return 1;
|
||||
return 0; // Keep original order for features with same justFinished status
|
||||
});
|
||||
|
||||
return map;
|
||||
}, [features, runningAutoTasks, searchQuery]);
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
import { cn } from "@/lib/utils";
|
||||
import { getElectronAPI } from "@/lib/electron";
|
||||
import { Markdown } from "@/components/ui/markdown";
|
||||
import { useFileBrowser } from "@/contexts/file-browser-context";
|
||||
|
||||
interface InterviewMessage {
|
||||
id: string;
|
||||
@@ -65,6 +66,7 @@ const INTERVIEW_QUESTIONS = [
|
||||
export function InterviewView() {
|
||||
const { setCurrentView, addProject, setCurrentProject, setAppSpec } =
|
||||
useAppStore();
|
||||
const { openFileBrowser } = useFileBrowser();
|
||||
const [input, setInput] = useState("");
|
||||
const [messages, setMessages] = useState<InterviewMessage[]>([]);
|
||||
const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
|
||||
@@ -286,11 +288,13 @@ export function InterviewView() {
|
||||
};
|
||||
|
||||
const handleSelectDirectory = async () => {
|
||||
const api = getElectronAPI();
|
||||
const result = await api.openDirectory();
|
||||
const selectedPath = await openFileBrowser({
|
||||
title: "Select Base Directory",
|
||||
description: "Choose the parent directory where your new project will be created",
|
||||
});
|
||||
|
||||
if (!result.canceled && result.filePaths[0]) {
|
||||
setProjectPath(result.filePaths[0]);
|
||||
if (selectedPath) {
|
||||
setProjectPath(selectedPath);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Feature, useAppStore } from "@/store/app-store";
|
||||
import { Feature, useAppStore, ThinkingLevel } from "@/store/app-store";
|
||||
import {
|
||||
GripVertical,
|
||||
Edit,
|
||||
@@ -55,6 +55,7 @@ import {
|
||||
GitMerge,
|
||||
ChevronDown,
|
||||
ChevronUp,
|
||||
Brain,
|
||||
} from "lucide-react";
|
||||
import { CountUpTimer } from "@/components/ui/count-up-timer";
|
||||
import { getElectronAPI } from "@/lib/electron";
|
||||
@@ -72,6 +73,21 @@ import {
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
|
||||
/**
|
||||
* Formats thinking level for compact display
|
||||
*/
|
||||
function formatThinkingLevel(level: ThinkingLevel | undefined): string {
|
||||
if (!level || level === "none") return "";
|
||||
const labels: Record<ThinkingLevel, string> = {
|
||||
none: "",
|
||||
low: "Low",
|
||||
medium: "Med",
|
||||
high: "High",
|
||||
ultrathink: "Ultra",
|
||||
};
|
||||
return labels[level];
|
||||
}
|
||||
|
||||
interface KanbanCardProps {
|
||||
feature: Feature;
|
||||
onEdit: () => void;
|
||||
@@ -280,6 +296,21 @@ export const KanbanCard = memo(function KanbanCard({
|
||||
<span>Errored</span>
|
||||
</div>
|
||||
)}
|
||||
{/* Just Finished indicator badge - shows when agent just completed work */}
|
||||
{feature.justFinished && feature.status === "waiting_approval" && !feature.error && (
|
||||
<div
|
||||
className={cn(
|
||||
"absolute px-1.5 py-0.5 text-[10px] font-medium rounded flex items-center gap-1 z-10",
|
||||
feature.skipTests ? "top-8 left-2" : "top-2 left-2",
|
||||
"bg-green-500/20 border border-green-500/50 text-green-400 animate-pulse"
|
||||
)}
|
||||
data-testid={`just-finished-badge-${feature.id}`}
|
||||
title="Agent just finished working on this feature"
|
||||
>
|
||||
<Sparkles className="w-3 h-3" />
|
||||
<span>Done</span>
|
||||
</div>
|
||||
)}
|
||||
{/* Branch badge - show when feature has a worktree */}
|
||||
{hasWorktree && !isCurrentAutoTask && (
|
||||
<TooltipProvider delayDuration={300}>
|
||||
@@ -289,8 +320,8 @@ export const KanbanCard = memo(function KanbanCard({
|
||||
className={cn(
|
||||
"absolute px-1.5 py-0.5 text-[10px] font-medium rounded flex items-center gap-1 z-10 cursor-default",
|
||||
"bg-purple-500/20 border border-purple-500/50 text-purple-400",
|
||||
// Position below error badge if present, otherwise use normal position
|
||||
feature.error || feature.skipTests
|
||||
// Position below other badges if present, otherwise use normal position
|
||||
feature.error || feature.skipTests || (feature.justFinished && feature.status === "waiting_approval")
|
||||
? "top-8 left-2"
|
||||
: "top-2 left-2"
|
||||
)}
|
||||
@@ -310,14 +341,17 @@ export const KanbanCard = memo(function KanbanCard({
|
||||
className={cn(
|
||||
"p-3 pb-2 block", // Reset grid layout to block for custom kanban card layout
|
||||
// Add extra top padding when badges are present to prevent text overlap
|
||||
(feature.skipTests || feature.error) && "pt-10",
|
||||
(feature.skipTests || feature.error || (feature.justFinished && feature.status === "waiting_approval")) && "pt-10",
|
||||
// Add even more top padding when both badges and branch are shown
|
||||
hasWorktree && (feature.skipTests || feature.error) && "pt-14"
|
||||
hasWorktree && (feature.skipTests || feature.error || (feature.justFinished && feature.status === "waiting_approval")) && "pt-14"
|
||||
)}
|
||||
>
|
||||
{isCurrentAutoTask && (
|
||||
<div className="absolute top-2 right-2 flex items-center justify-center gap-2 bg-running-indicator/20 border border-running-indicator rounded px-2 py-0.5">
|
||||
<Loader2 className="w-4 h-4 text-running-indicator animate-spin" />
|
||||
<span className="text-xs text-running-indicator font-medium">
|
||||
{formatModelName(feature.model ?? DEFAULT_MODEL)}
|
||||
</span>
|
||||
{feature.startedAt && (
|
||||
<CountUpTimer
|
||||
startedAt={feature.startedAt}
|
||||
@@ -452,6 +486,28 @@ export const KanbanCard = memo(function KanbanCard({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Model/Preset Info for Backlog Cards - Show in Detailed mode */}
|
||||
{showAgentInfo && feature.status === "backlog" && (
|
||||
<div className="mb-3 space-y-2 overflow-hidden">
|
||||
<div className="flex items-center gap-2 text-xs flex-wrap">
|
||||
<div className="flex items-center gap-1 text-cyan-400">
|
||||
<Cpu className="w-3 h-3" />
|
||||
<span className="font-medium">
|
||||
{formatModelName(feature.model ?? DEFAULT_MODEL)}
|
||||
</span>
|
||||
</div>
|
||||
{feature.thinkingLevel && feature.thinkingLevel !== "none" && (
|
||||
<div className="flex items-center gap-1 text-purple-400">
|
||||
<Brain className="w-3 h-3" />
|
||||
<span className="font-medium">
|
||||
{formatThinkingLevel(feature.thinkingLevel)}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Agent Info Panel - shows for in_progress, waiting_approval, verified */}
|
||||
{/* Detailed mode: Show all agent info */}
|
||||
{showAgentInfo && feature.status !== "backlog" && agentInfo && (
|
||||
|
||||
@@ -181,7 +181,8 @@ export function WelcomeView() {
|
||||
if (!result.canceled && result.filePaths[0]) {
|
||||
const path = result.filePaths[0];
|
||||
// Extract folder name from path (works on both Windows and Mac/Linux)
|
||||
const name = path.split(/[/\\]/).filter(Boolean).pop() || "Untitled Project";
|
||||
const name =
|
||||
path.split(/[/\\]/).filter(Boolean).pop() || "Untitled Project";
|
||||
await initializeAndOpenProject(path, name);
|
||||
}
|
||||
}
|
||||
@@ -193,7 +194,8 @@ export function WelcomeView() {
|
||||
|
||||
if (!result.canceled && result.filePaths[0]) {
|
||||
const path = result.filePaths[0];
|
||||
const name = path.split(/[/\\]/).filter(Boolean).pop() || "Untitled Project";
|
||||
const name =
|
||||
path.split(/[/\\]/).filter(Boolean).pop() || "Untitled Project";
|
||||
await initializeAndOpenProject(path, name);
|
||||
}
|
||||
}
|
||||
@@ -231,7 +233,10 @@ export function WelcomeView() {
|
||||
/**
|
||||
* Create a blank project with just .automaker directory structure
|
||||
*/
|
||||
const handleCreateBlankProject = async (projectName: string, parentDir: string) => {
|
||||
const handleCreateBlankProject = async (
|
||||
projectName: string,
|
||||
parentDir: string
|
||||
) => {
|
||||
setIsCreating(true);
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
@@ -359,11 +364,15 @@ export function WelcomeView() {
|
||||
</overview>
|
||||
|
||||
<technology_stack>
|
||||
${template.techStack.map((tech) => `<technology>${tech}</technology>`).join("\n ")}
|
||||
${template.techStack
|
||||
.map((tech) => `<technology>${tech}</technology>`)
|
||||
.join("\n ")}
|
||||
</technology_stack>
|
||||
|
||||
<core_capabilities>
|
||||
${template.features.map((feature) => `<capability>${feature}</capability>`).join("\n ")}
|
||||
${template.features
|
||||
.map((feature) => `<capability>${feature}</capability>`)
|
||||
.join("\n ")}
|
||||
</core_capabilities>
|
||||
|
||||
<implemented_features>
|
||||
|
||||
Reference in New Issue
Block a user