Skip to content

Commit 9a36ff2

Browse files
committed
[ai-assisted] Refine onboarding dialog behavior and trim settings
1 parent 930cee4 commit 9a36ff2

4 files changed

Lines changed: 88 additions & 33 deletions

File tree

src/App.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,11 @@ Ready to bridge Figma and AI tools via MCP
278278
case 'terminal':
279279
return <TerminalPage logs={logs} />
280280
case 'settings':
281-
return <SettingsPage onNavigateToSettings={() => setCurrentPage('settings')} />
281+
return (
282+
<SettingsPage
283+
onNavigateToSettings={() => setCurrentPage('settings')}
284+
/>
285+
)
282286
case 'help':
283287
return <HelpPage />
284288
default:

src/main/assistant/OllamaGuideService.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ import { ASSISTANT_DEFAULT_MODEL } from './constants';
1010
function getInstallStepByPlatform(): string {
1111
switch (process.platform) {
1212
case 'darwin':
13-
return 'Install Ollama: `brew install --cask ollama` or download from ollama.com';
13+
return 'Install Ollama (if not installed): `brew install --cask ollama` or download from ollama.com';
1414
case 'win32':
15-
return 'Install Ollama from https://ollama.com/download/windows';
15+
return 'Install Ollama (if not installed) from https://ollama.com/download/windows';
1616
default:
17-
return 'Install Ollama from https://ollama.com/download';
17+
return 'Install Ollama (if not installed) from https://ollama.com/download';
1818
}
1919
}
2020

src/pages/Assistant.tsx

Lines changed: 79 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ export function AssistantPage() {
489489
const [deletingThreadId, setDeletingThreadId] = useState<string | null>(null)
490490

491491
const sendLockRef = useRef(false)
492+
const setupDialogPinnedRef = useRef(false)
492493
const shimmerVisibleSinceRef = useRef<number | null>(null)
493494
const shimmerHideTimerRef = useRef<number | null>(null)
494495
const fileInputRef = useRef<HTMLInputElement | null>(null)
@@ -568,25 +569,41 @@ export function AssistantPage() {
568569
}
569570
}, [shouldShowPreResponseShimmer, showPreResponseShimmer])
570571

572+
const openSetupDialog = useCallback((pinned = false) => {
573+
setupDialogPinnedRef.current = pinned
574+
setSetupDialogOpen(true)
575+
setModelDialogOpen(false)
576+
}, [])
577+
578+
const closeSetupDialog = useCallback(() => {
579+
setupDialogPinnedRef.current = false
580+
setSetupDialogOpen(false)
581+
}, [])
582+
583+
const closeSetupDialogIfAutoManaged = useCallback(() => {
584+
if (!setupDialogPinnedRef.current) {
585+
setSetupDialogOpen(false)
586+
}
587+
}, [])
588+
571589
const refreshRuntimeStatus = useCallback(async (threadId?: string) => {
572590
const status = await window.electron.assistant.getRuntimeStatus(threadId)
573591
setRuntimeStatus(status)
574592

575593
if (!status.daemonReachable) {
576-
setSetupDialogOpen(true)
577-
setModelDialogOpen(false)
594+
openSetupDialog(false)
578595
return status
579596
}
580597

581-
setSetupDialogOpen(false)
598+
closeSetupDialogIfAutoManaged()
582599

583600
if (status.daemonReachable && status.needsModelSelection) {
584601
setModelDialogOpen(true)
585602
setSelectedModel(status.installedModels.find(isLikelyVisionModel) ?? '')
586603
}
587604

588605
return status
589-
}, [])
606+
}, [closeSetupDialogIfAutoManaged, openSetupDialog])
590607

591608
const refreshThreads = async () => {
592609
const nextThreads = await window.electron.assistant.listThreads()
@@ -641,13 +658,13 @@ export function AssistantPage() {
641658
useEffect(() => {
642659
const unsubscribeStatus = window.electron.assistant.onRuntimeStatusChanged((status) => {
643660
setRuntimeStatus(status)
661+
644662
if (!status.daemonReachable) {
645-
setSetupDialogOpen(true)
646-
setModelDialogOpen(false)
663+
openSetupDialog(false)
647664
return
648665
}
649666

650-
setSetupDialogOpen(false)
667+
closeSetupDialogIfAutoManaged()
651668

652669
if (status.daemonReachable && status.needsModelSelection) {
653670
setModelDialogOpen(true)
@@ -730,7 +747,7 @@ export function AssistantPage() {
730747
unsubscribeRunEvent()
731748
unsubscribeApproval()
732749
}
733-
}, [activeThreadId, permissionMode, refreshRuntimeStatus])
750+
}, [activeThreadId, closeSetupDialogIfAutoManaged, openSetupDialog, permissionMode, refreshRuntimeStatus])
734751

735752
useEffect(() => {
736753
if (!modelDialogOpen) return
@@ -776,6 +793,20 @@ export function AssistantPage() {
776793
}
777794
}, [])
778795

796+
useEffect(() => {
797+
const handleOpenSetup = () => {
798+
openSetupDialog(true)
799+
void window.electron.assistant.getRuntimeStatus(activeThreadId ?? undefined).then((status) => {
800+
setRuntimeStatus(status)
801+
})
802+
}
803+
804+
window.addEventListener('assistant:open-setup', handleOpenSetup)
805+
return () => {
806+
window.removeEventListener('assistant:open-setup', handleOpenSetup)
807+
}
808+
}, [activeThreadId, openSetupDialog])
809+
779810
const handleCreateThread = async () => {
780811
const created = await window.electron.assistant.createThread()
781812
await refreshThreads()
@@ -824,7 +855,7 @@ export function AssistantPage() {
824855
}
825856

826857
if (appState === 'needs-setup') {
827-
setSetupDialogOpen(true)
858+
openSetupDialog(false)
828859
return
829860
}
830861

@@ -998,11 +1029,11 @@ export function AssistantPage() {
9981029
const status = await refreshRuntimeStatus(activeThreadId ?? undefined)
9991030

10001031
if (!status.daemonReachable) {
1001-
setSetupDialogOpen(true)
1032+
openSetupDialog(false)
10021033
return
10031034
}
10041035

1005-
setSetupDialogOpen(false)
1036+
closeSetupDialog()
10061037
if (status.daemonReachable && status.needsModelSelection) {
10071038
setModelDialogOpen(true)
10081039
}
@@ -1219,7 +1250,7 @@ export function AssistantPage() {
12191250
<DropdownMenuItem
12201251
onSelect={() => {
12211252
if (!runtimeStatus?.daemonReachable) {
1222-
setSetupDialogOpen(true)
1253+
openSetupDialog(false)
12231254
return
12241255
}
12251256
setModelDialogOpen(true)
@@ -1325,12 +1356,21 @@ export function AssistantPage() {
13251356
</SheetContent>
13261357
</Sheet>
13271358

1328-
<Dialog open={setupDialogOpen} onOpenChange={setSetupDialogOpen}>
1359+
<Dialog
1360+
open={setupDialogOpen}
1361+
onOpenChange={(open) => {
1362+
if (open) {
1363+
setSetupDialogOpen(true)
1364+
return
1365+
}
1366+
closeSetupDialog()
1367+
}}
1368+
>
13291369
<DialogContent>
13301370
<DialogHeader>
1331-
<DialogTitle>Set up Ollama</DialogTitle>
1371+
<DialogTitle>Set up local Ollama</DialogTitle>
13321372
<DialogDescription>
1333-
The local Ollama API is not reachable. Start Ollama and make sure the endpoint responds before selecting a model.
1373+
Ollama is required for the local assistant. Complete this onboarding: install Ollama, run it, then install <b>gemma4:e4b</b>.
13341374
</DialogDescription>
13351375
</DialogHeader>
13361376
<div className="space-y-3 text-sm">
@@ -1341,19 +1381,31 @@ export function AssistantPage() {
13411381
</div>
13421382
</div>
13431383

1344-
{setupGuide?.steps?.length ? (
1345-
<ol className="space-y-1.5 pl-5">
1346-
{setupGuide.steps.map((step) => (
1347-
<li key={step}>{step}</li>
1348-
))}
1349-
</ol>
1350-
) : null}
1351-
13521384
<div className="space-y-1.5 rounded-md border p-3">
1353-
<p className="text-muted-foreground text-xs">Recommended multimodal model</p>
1354-
<code className="block rounded bg-muted px-2 py-1 text-xs">ollama pull qwen2.5-vl</code>
1355-
<code className="block rounded bg-muted px-2 py-1 text-xs">ollama serve</code>
1356-
<code className="block rounded bg-muted px-2 py-1 text-xs">ollama list</code>
1385+
<p className="font-medium">Onboarding</p>
1386+
<ol className="space-y-2 pl-5">
1387+
<li>
1388+
<p className="font-medium">Install Ollama</p>
1389+
<p className="text-muted-foreground text-xs">
1390+
{setupGuide?.steps?.[0] ?? 'Install Ollama from the official website.'}
1391+
</p>
1392+
</li>
1393+
<li>
1394+
<p className="font-medium">Run Ollama</p>
1395+
<code className="mt-1 block rounded bg-muted px-2 py-1 text-xs">
1396+
{setupGuide?.serveCommand ?? 'ollama serve'}
1397+
</code>
1398+
</li>
1399+
<li>
1400+
<p className="font-medium">Install default model</p>
1401+
<code className="mt-1 block rounded bg-muted px-2 py-1 text-xs">
1402+
{setupGuide?.pullCommand ?? 'ollama pull gemma4:e4b'}
1403+
</code>
1404+
<code className="mt-1 block rounded bg-muted px-2 py-1 text-xs">
1405+
{setupGuide?.verifyCommand ?? 'ollama list'}
1406+
</code>
1407+
</li>
1408+
</ol>
13571409
</div>
13581410
</div>
13591411
<DialogFooter>

src/pages/Settings.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ export function SettingsPage({ onNavigateToSettings }: SettingsPageProps) {
1717
const [showMigrationDialog, setShowMigrationDialog] = useState(false)
1818

1919
useEffect(() => {
20-
// Load stdio server path
2120
if (window.electron?.mcp?.getStdioPath) {
22-
window.electron.mcp.getStdioPath().then(path => {
21+
void window.electron.mcp.getStdioPath().then(path => {
2322
setStdioPath(path)
2423
}).catch(() => {
2524
setStdioPath('Error loading path')

0 commit comments

Comments
 (0)