diff --git a/backend/app/api/endpoints/ai_chat.py b/backend/app/api/endpoints/ai_chat.py
index 7fb16748..defebd5e 100644
--- a/backend/app/api/endpoints/ai_chat.py
+++ b/backend/app/api/endpoints/ai_chat.py
@@ -387,12 +387,8 @@ async def import_tree(
detail="Session must be completed with a generated tree before importing",
)
- if session.generated_tree_id:
- return AIChatImportResponse(
- tree_id=session.generated_tree_id,
- tree_type=session.flow_type,
- )
-
+ # Always create a new Tree record (no duplicate check — user may
+ # want multiple copies or re-import after edits)
metadata = session.tree_metadata or {}
tree = Tree(
name=data.name or metadata.get("name", "AI-Generated Flow"),
diff --git a/frontend/src/components/ai-chat/ChatToolbar.tsx b/frontend/src/components/ai-chat/ChatToolbar.tsx
index 6624d96a..e5905801 100644
--- a/frontend/src/components/ai-chat/ChatToolbar.tsx
+++ b/frontend/src/components/ai-chat/ChatToolbar.tsx
@@ -1,4 +1,4 @@
-import { Sparkles, Download, RotateCcw, ArrowRight } from 'lucide-react'
+import { Sparkles, Save, RotateCcw, Loader2 } from 'lucide-react'
import { PhaseIndicator } from './PhaseIndicator'
import { cn } from '@/lib/utils'
import type { InterviewPhase } from '@/types'
@@ -8,8 +8,9 @@ interface ChatToolbarProps {
status: 'idle' | 'active' | 'completed' | 'abandoned'
isGenerating: boolean
hasGeneratedTree: boolean
+ isSaving: boolean
onGenerate: () => void
- onImport: () => void
+ onSave: () => void
onReset: () => void
}
@@ -18,8 +19,9 @@ export function ChatToolbar({
status,
isGenerating,
hasGeneratedTree,
+ isSaving,
onGenerate,
- onImport,
+ onSave,
onReset,
}: ChatToolbarProps) {
return (
@@ -44,22 +46,42 @@ export function ChatToolbar({
'disabled:opacity-50 disabled:cursor-not-allowed'
)}
>
-
- {isGenerating ? 'Generating...' : 'Generate Flow'}
+ {isGenerating ? (
+ <>
+
+ Generating...
+ >
+ ) : (
+ <>
+
+ Generate Flow
+ >
+ )}
)}
{hasGeneratedTree && (
)}
diff --git a/frontend/src/pages/AIChatBuilderPage.tsx b/frontend/src/pages/AIChatBuilderPage.tsx
index 005fad1d..bcd3ba9b 100644
--- a/frontend/src/pages/AIChatBuilderPage.tsx
+++ b/frontend/src/pages/AIChatBuilderPage.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useEffect } from 'react'
+import { useCallback, useEffect, useState } from 'react'
import { useNavigate, useSearchParams } from 'react-router-dom'
import { useAIChatStore } from '@/store/aiChatStore'
import { ChatPanel } from '@/components/ai-chat/ChatPanel'
@@ -62,11 +62,15 @@ export function AIChatBuilderPage() {
[sendMessage]
)
+ const [isSaving, setIsSaving] = useState(false)
+
const handleGenerate = useCallback(() => {
generateTree()
}, [generateTree])
- const handleImport = useCallback(async () => {
+ const handleSave = useCallback(async () => {
+ if (isSaving) return
+ setIsSaving(true)
try {
const treeId = await importToEditor({
name: treeMetadata?.name,
@@ -75,11 +79,13 @@ export function AIChatBuilderPage() {
})
const path = getTreeEditorPath(treeId, flowType)
navigate(path)
- toast.success('Flow imported to editor')
+ toast.success('Flow saved to library')
} catch {
- toast.error('Failed to import flow')
+ toast.error('Failed to save flow')
+ } finally {
+ setIsSaving(false)
}
- }, [importToEditor, treeMetadata, flowType, navigate])
+ }, [isSaving, importToEditor, treeMetadata, flowType, navigate])
const handleReset = useCallback(async () => {
await abandonSession()
@@ -116,8 +122,9 @@ export function AIChatBuilderPage() {
status={status}
isGenerating={isGenerating}
hasGeneratedTree={!!generatedTree}
+ isSaving={isSaving}
onGenerate={handleGenerate}
- onImport={handleImport}
+ onSave={handleSave}
onReset={handleReset}
/>