import { useEffect, useMemo, useState } from "react"; import { Button, Input, Modal } from "../atoms"; import { useAppStore } from "../../stores/useAppStore"; import * as api from "../../services/api"; import type { LaunchInstanceRequest, Profile } from "../../generated/types"; interface Props { open: boolean; profile: Profile | null; onClose: () => void; } export default function StartInstanceModal({ open, profile, onClose }: Props) { const { setInstances } = useAppStore(); const [port, setPort] = useState(""); const [headless, setHeadless] = useState(false); const [launchError, setLaunchError] = useState(""); const [launchLoading, setLaunchLoading] = useState(false); const [copyFeedback, setCopyFeedback] = useState(""); useEffect(() => { if (open) { setLaunchError(""); setCopyFeedback(""); return; } setPort(""); setHeadless(false); setLaunchError(""); setLaunchLoading(false); setCopyFeedback(""); }, [open, profile?.id, profile?.name]); const launchCommand = useMemo(() => { if (!profile) return ""; const payload: LaunchInstanceRequest = { profileId: profile.id || profile.name, mode: headless ? undefined : "headed", port: port.trim() || undefined, }; return `curl -X POST http://localhost:9867/instances/start -H "Content-Type: application/json" -d '${JSON.stringify(payload)}'`; }, [headless, port, profile]); const handleLaunch = async () => { if (!profile || launchLoading) return; setLaunchError(""); setLaunchLoading(true); try { const payload: LaunchInstanceRequest = { name: profile.name, port: port.trim() || undefined, mode: headless ? undefined : "headed", }; await api.launchInstance(payload); const updated = await api.fetchInstances(); setInstances(updated); onClose(); } catch (e) { console.error("Launch failed:", e); const msg = e instanceof Error ? e.message : "Failed to launch instance"; setLaunchError(msg); } finally { setLaunchLoading(false); } }; const handleCopyCommand = async () => { try { await navigator.clipboard.writeText(launchCommand); setCopyFeedback("Copied!"); setTimeout(() => setCopyFeedback(""), 2000); } catch { setCopyFeedback("Failed to copy"); setTimeout(() => setCopyFeedback(""), 2000); } }; return ( } >
{launchError && (
{launchError}
)} setPort(e.target.value)} />

Leave blank to auto-select a free port from the configured instance port range.