From f25d62fe25f893a2ab628bfd1e84b255f67dadbe Mon Sep 17 00:00:00 2001 From: Cody Seibert Date: Mon, 15 Dec 2025 01:07:47 -0500 Subject: [PATCH] feat: implement project setup dialog and refactor sidebar integration - Added a new ProjectSetupDialog component to facilitate project specification generation, enhancing user experience by guiding users through project setup. - Refactored the Sidebar component to integrate the new ProjectSetupDialog, replacing the previous inline dialog implementation for improved code organization and maintainability. - Updated the sidebar to handle project overview and feature generation options, streamlining the project setup process. - Removed the old dialog implementation from the Sidebar, reducing code duplication and improving clarity. --- apps/app/src/app/api/chat/route.ts | 172 ----------- .../layout/project-setup-dialog.tsx | 114 +++++++ apps/app/src/components/layout/sidebar.tsx | 90 +----- apps/app/src/components/views/board-view.tsx | 26 +- apps/app/src/config/model-config.ts | 93 ++++++ apps/server/src/lib/model-resolver.ts | 9 +- apps/server/src/lib/sdk-options.ts | 291 ++++++++++++++++++ .../app-spec/generate-features-from-spec.ts | 33 +- .../src/routes/app-spec/generate-spec.ts | 147 ++++++--- .../app-spec/parse-and-create-features.ts | 19 +- .../suggestions/generate-suggestions.ts | 11 +- apps/server/src/services/agent-service.ts | 30 +- apps/server/src/services/auto-mode-service.ts | 21 +- 13 files changed, 724 insertions(+), 332 deletions(-) delete mode 100644 apps/app/src/app/api/chat/route.ts create mode 100644 apps/app/src/components/layout/project-setup-dialog.tsx create mode 100644 apps/app/src/config/model-config.ts create mode 100644 apps/server/src/lib/sdk-options.ts diff --git a/apps/app/src/app/api/chat/route.ts b/apps/app/src/app/api/chat/route.ts deleted file mode 100644 index 11f3db6a..00000000 --- a/apps/app/src/app/api/chat/route.ts +++ /dev/null @@ -1,172 +0,0 @@ -import { - query, - Options, - SDKAssistantMessage, -} from "@anthropic-ai/claude-agent-sdk"; -import { NextRequest, NextResponse } from "next/server"; -import path from "path"; - -const systemPrompt = `You are an AI assistant helping users build software. You are part of the Automaker application, -which is designed to help developers plan, design, and implement software projects autonomously. - -Your role is to: -- Help users define their project requirements and specifications -- Ask clarifying questions to better understand their needs -- Suggest technical approaches and architectures -- Guide them through the development process -- Be conversational and helpful -- Write, edit, and modify code files as requested -- Execute commands and tests -- Search and analyze the codebase - -When discussing projects, help users think through: -- Core functionality and features -- Technical stack choices -- Data models and architecture -- User experience considerations -- Testing strategies - -You have full access to the codebase and can: -- Read files to understand existing code -- Write new files -- Edit existing files -- Run bash commands -- Search for code patterns -- Execute tests and builds`; - -export async function POST(request: NextRequest) { - try { - const { messages, workingDirectory } = await request.json(); - - console.log( - "[API] CLAUDE_CODE_OAUTH_TOKEN present:", - !!process.env.CLAUDE_CODE_OAUTH_TOKEN - ); - - if (!process.env.CLAUDE_CODE_OAUTH_TOKEN) { - return NextResponse.json( - { error: "CLAUDE_CODE_OAUTH_TOKEN not configured" }, - { status: 500 } - ); - } - - // Get the last user message - const lastMessage = messages[messages.length - 1]; - - // Determine working directory - default to parent of app directory - const cwd = workingDirectory || path.resolve(process.cwd(), ".."); - - console.log("[API] Working directory:", cwd); - - // Create query with options that enable code modification - const options: Options = { - // model: "claude-sonnet-4-20250514", - model: "claude-opus-4-5-20251101", - systemPrompt, - maxTurns: 20, - cwd, - // Enable all core tools for code modification - allowedTools: [ - "Read", - "Write", - "Edit", - "Glob", - "Grep", - "Bash", - "WebSearch", - "WebFetch", - ], - // Auto-accept file edits within the working directory - permissionMode: "acceptEdits", - // Enable sandbox for safer bash execution - sandbox: { - enabled: true, - autoAllowBashIfSandboxed: true, - }, - }; - - // Convert message history to SDK format to preserve conversation context - // Include both user and assistant messages for full context - const sessionId = `api-session-${Date.now()}`; - const conversationMessages = messages.map( - (msg: { role: string; content: string }) => { - if (msg.role === "user") { - return { - type: "user" as const, - message: { - role: "user" as const, - content: msg.content, - }, - parent_tool_use_id: null, - session_id: sessionId, - }; - } else { - // Assistant message - return { - type: "assistant" as const, - message: { - role: "assistant" as const, - content: [ - { - type: "text" as const, - text: msg.content, - }, - ], - }, - session_id: sessionId, - }; - } - } - ); - - // Execute query with full conversation context - const queryResult = query({ - prompt: - conversationMessages.length > 0 - ? conversationMessages - : lastMessage.content, - options, - }); - - let responseText = ""; - const toolUses: Array<{ name: string; input: unknown }> = []; - - // Collect the response from the async generator - for await (const msg of queryResult) { - if (msg.type === "assistant") { - const assistantMsg = msg as SDKAssistantMessage; - if (assistantMsg.message.content) { - for (const block of assistantMsg.message.content) { - if (block.type === "text") { - responseText += block.text; - } else if (block.type === "tool_use") { - // Track tool usage for transparency - toolUses.push({ - name: block.name, - input: block.input, - }); - } - } - } - } else if (msg.type === "result") { - if (msg.subtype === "success") { - if (msg.result) { - responseText = msg.result; - } - } - } - } - - return NextResponse.json({ - content: responseText || "Sorry, I couldn't generate a response.", - toolUses: toolUses.length > 0 ? toolUses : undefined, - }); - } catch (error: unknown) { - console.error("Claude API error:", error); - const errorMessage = - error instanceof Error - ? error.message - : "Failed to get response from Claude"; - return NextResponse.json({ error: errorMessage }, { status: 500 }); - } -} diff --git a/apps/app/src/components/layout/project-setup-dialog.tsx b/apps/app/src/components/layout/project-setup-dialog.tsx new file mode 100644 index 00000000..4b4ce15e --- /dev/null +++ b/apps/app/src/components/layout/project-setup-dialog.tsx @@ -0,0 +1,114 @@ +"use client"; + +import { Sparkles } from "lucide-react"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { Checkbox } from "@/components/ui/checkbox"; + +interface ProjectSetupDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; + projectOverview: string; + onProjectOverviewChange: (value: string) => void; + generateFeatures: boolean; + onGenerateFeaturesChange: (value: boolean) => void; + onCreateSpec: () => void; + onSkip: () => void; + isCreatingSpec: boolean; +} + +export function ProjectSetupDialog({ + open, + onOpenChange, + projectOverview, + onProjectOverviewChange, + generateFeatures, + onGenerateFeaturesChange, + onCreateSpec, + onSkip, + isCreatingSpec, +}: ProjectSetupDialogProps) { + return ( + { + if (!open && !isCreatingSpec) { + onSkip(); + } + }} + > + + + Set Up Your Project + + We didn't find an app_spec.txt file. Let us help you generate + your app_spec.txt to help describe your project for our system. + We'll analyze your project's tech stack and create a + comprehensive specification. + + + +
+
+ +

+ Describe what your project does and what features you want to + build. Be as detailed as you want - this will help us create a + better specification. +

+