import { Link, createFileRoute } from "@tanstack/react-router" import { CaretRightIcon } from "@phosphor-icons/react" import { useEffect, useRef, useState } from "react" import type { ModelOption } from "@/lib/api" import { AppShell, SettingsRow, SettingsSection } from "@/components/AppShell" import { Button } from "@/components/ui/button" import { RepoSelector } from "@/components/agents/RepoSelector" import { Input } from "@/components/ui/input" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Skeleton } from "@/components/ui/skeleton" import { Switch } from "@/components/ui/switch" import { buildProfileUpdate, useOptions, useProfile, useRepos, useSaveProfile, } from "@/lib/profile" import { RequireLogin } from "@/lib/auth-redirect" import { useSession } from "@/lib/session" export const Route = createFileRoute("/cloud-agents")({ component: CloudAgentsPage, }) function CloudAgentsPage() { const session = useSession() const profile = useProfile() const options = useOptions() const repos = useRepos() const save = useSaveProfile() const [modelId, setModelId] = useState("") const [effort, setEffort] = useState("") const [subagentModelId, setSubagentModelId] = useState("") const [subagentEffort, setSubagentEffort] = useState("") const [defaultRepo, setDefaultRepo] = useState("") const [baseBranch, setBaseBranch] = useState("") const [branchPrefix, setBranchPrefix] = useState("") const [error, setError] = useState(null) const initialized = useRef(false) const firstModel: ModelOption | undefined = options.data?.models[0] const defaultAgentModel = options.data?.default_agent_model ?? firstModel?.id ?? "" const defaultAgentEffort = options.data?.default_agent_reasoning_effort ?? firstModel?.default_effort ?? "" const defaultSubagentModel = options.data?.default_agent_subagent_model ?? defaultAgentModel const defaultSubagentEffort = options.data?.default_agent_subagent_reasoning_effort ?? defaultAgentEffort const currentModel: ModelOption | undefined = options.data?.models.find((m) => m.id === modelId) ?? firstModel const currentSubagentModel: ModelOption | undefined = options.data?.models.find((m) => m.id === subagentModelId) ?? firstModel useEffect(() => { if (!profile.data || initialized.current) return const hasModel = !!profile.data.default_model || !!defaultAgentModel if (!hasModel) return initialized.current = true setModelId(profile.data.default_model ?? defaultAgentModel) setEffort(profile.data.reasoning_effort ?? defaultAgentEffort) setSubagentModelId( profile.data.default_subagent_model ?? profile.data.default_model ?? defaultSubagentModel ) setSubagentEffort( profile.data.subagent_reasoning_effort ?? profile.data.reasoning_effort ?? defaultSubagentEffort ) setDefaultRepo(profile.data.default_repo ?? "") setBaseBranch(profile.data.base_branch ?? "") setBranchPrefix(profile.data.branch_prefix ?? "") }, [ profile.data, defaultAgentModel, defaultAgentEffort, defaultSubagentModel, defaultSubagentEffort, ]) useEffect(() => { if (currentModel && !currentModel.efforts.includes(effort)) { setEffort(currentModel.default_effort) } }, [currentModel, effort]) useEffect(() => { if ( currentSubagentModel && !currentSubagentModel.efforts.includes(subagentEffort) ) { setSubagentEffort(currentSubagentModel.default_effort) } }, [currentSubagentModel, subagentEffort]) if (session.isLoading) { return (
) } if (!session.data) return const fallbackModel = defaultAgentModel const fallbackEffort = defaultAgentEffort const persist = (patch: Parameters[1]) => { setError(null) save .mutateAsync( buildProfileUpdate(profile.data, patch, fallbackModel, fallbackEffort) ) .catch((e: Error) => setError(e.message)) } const persistDefaults = () => { persist({ default_model: modelId, reasoning_effort: effort, default_subagent_model: subagentModelId, subagent_reasoning_effort: subagentEffort, default_repo: defaultRepo || null, base_branch: baseBranch || null, branch_prefix: branchPrefix || null, }) } return (
v && setModelId(v)}> {options.data?.models.map((m) => ( {m.label} ))} } /> v && setEffort(v)}> {currentModel?.efforts.map((e) => ( {e} ))} } /> v && setSubagentModelId(v)} > {options.data?.models.map((m) => ( {m.label} ))} } /> v && setSubagentEffort(v)} > {currentSubagentModel?.efforts.map((e) => ( {e} ))} } /> setDefaultRepo(repo ?? "")} placeholder="Pick a repository…" emptySelectionLabel="No default repository" triggerClassName="h-7 w-full max-w-none rounded-md border border-input bg-input/20 px-2 py-1.5 text-xs/relaxed text-foreground transition-colors hover:opacity-100 dark:bg-input/30" dropdownClassName="w-56" />
) : ( setDefaultRepo(e.target.value)} /> ) } /> setBaseBranch(e.target.value)} /> } /> setBranchPrefix(e.target.value)} /> } />
persist({ auto_fix_ci: v })} /> } /> persist({ create_prs: v })} /> } />
Repository Instructions Per-repo custom instructions injected into the agent's system prompt.
{session.data.is_admin && (
Repository Snapshots Build a per-repo sandbox image from a custom Dockerfile. Falls back to the default image.
)}
{error &&

{error}

}
) }