import { useEffect, useState } from "react"; import { getRecentWorkspaces, openWorkspace, type RecentWorkspace } from "../api"; import { chooseFolder } from "../tauri"; // The mandatory workspace picker for project-scoped personas. Deliberately no // "switch persona" escape hatch: if a persona needs a folder, the choice here is // pick one or cancel — offering Chat as an exit undermined the persona the user // just chose (owner call, 2026-07-03). interface Props { onChoose: (path: string, branch?: string | null) => void; onCancel?: () => void; // present when changing folder mid-session create?: boolean; // "New project" mode: create the folder if missing } export function FolderGate({ onChoose, onCancel, create }: Props) { const [recents, setRecents] = useState([]); const [path, setPath] = useState(""); const [error, setError] = useState(""); useEffect(() => { getRecentWorkspaces().then(setRecents).catch(() => {}); }, []); const open = async (p: string, doCreate = false) => { setError(""); const res = await openWorkspace(p.trim(), doCreate); if (res.ok) onChoose(res.path, res.git_branch); else setError(res.error || "could not open that folder"); }; const browse = async () => { const picked = await chooseFolder(); if (picked) { setPath(picked); open(picked, create); // a picked folder already exists; create flag is harmless } }; return (

{create ? "New project" : "Choose a project folder"}

{create ? "Pick a folder or enter a path. If the path doesn't exist, it will be created." : "This coworker needs a workspace to read, edit, and run in."}

setPath(e.target.value)} onKeyDown={(e) => e.key === "Enter" && open(path, create)} autoFocus />
{error &&
{error}
} {recents.length > 0 && ( <>
Recent
{recents.map((w) => (
open(w.path)} title={w.path}> 📁 {w.name} {w.path}
))}
)} {onCancel && (
)}
); }