import { Link, Navigate, createFileRoute } from "@tanstack/react-router" import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query" import { CaretRightIcon } from "@phosphor-icons/react" import { useEffect, useMemo, useState } from "react" import type { DatadogConnectBody, LangSmithConnectBody, ModelOption, PRTraceResolutionResult, TeamSettings, UserMapping, } from "@/lib/api" import { AppShell, SettingsRow, SettingsSection } from "@/components/AppShell" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Skeleton } from "@/components/ui/skeleton" import { api } from "@/lib/api" import { RequireLogin } from "@/lib/auth-redirect" import { useSession } from "@/lib/session" export const Route = createFileRoute("/admin")({ component: AdminPage }) function AdminPage() { const session = useSession() const options = useQuery({ queryKey: ["options"], queryFn: api.options, enabled: !!session.data?.is_admin, }) if (session.isLoading) { return (
) } if (!session.data) return if (!session.data.is_admin) return return (
Reviewer eval Run the offline reviewer benchmark and watch its output stream live.
) } const PR_URL_RE = /^https:\/\/github\.com\/([^/\s]+)\/([^/\s]+)\/pull\/(\d+)/ function TriggerReviewSection() { const [url, setUrl] = useState("") const [error, setError] = useState(null) const [message, setMessage] = useState(null) const [trace, setTrace] = useState(null) const parsed = useMemo(() => { const match = PR_URL_RE.exec(url.trim()) if (!match) return null const [, owner, repo, number] = match if (!owner || !repo || !number) return null return { owner, repo, number: Number(number) } }, [url]) const trigger = useMutation({ mutationFn: () => { if (!parsed) throw new Error("invalid PR URL") return api.reReview(parsed.owner, parsed.repo, parsed.number) }, onSuccess: (result) => { setError(null) setMessage( result.queued ? "Review queued — a run is already in progress on this PR." : "Review started." ) }, onError: (e: Error) => { setMessage(null) setError(e.message) }, }) const resolveTrace = useMutation({ mutationFn: () => { if (!parsed) throw new Error("invalid PR URL") return api.resolveTrace(parsed.owner, parsed.repo, parsed.number) }, onSuccess: (result) => { setError(null) setMessage(null) setTrace(result) }, onError: (e: Error) => { setTrace(null) setError(e.message) }, }) return (
{ setUrl(e.target.value) setMessage(null) setError(null) setTrace(null) }} />
{url.trim() && !parsed && (

Enter a full PR URL like https://github.com/owner/repo/pull/123

)} {message && parsed && (

{message}{" "} View review

)} {trace && (trace.resolved ? (

Resolved thread{" "} {trace.thread_id} · confidence{" "} {trace.confidence?.toFixed(2)} · {trace.evidence.join(", ")} ·{" "} {trace.run_count} run{trace.run_count === 1 ? "" : "s"} {trace.trace_url && ( <> {" · "} open trace )}

) : (

No trace resolved — {trace.detail} {trace.project ? ` (project: ${trace.project})` : ""}

))} {error &&

{error}

}
) } const PAGE_SIZE = 20 function UserMappingsSection({ enabled }: { enabled: boolean }) { const [error, setError] = useState(null) const [page, setPage] = useState(1) const [newLogin, setNewLogin] = useState("") const [newEmail, setNewEmail] = useState("") const mappings = useQuery({ queryKey: ["adminUserMappings", page], queryFn: () => api.adminListUserMappings(page, PAGE_SIZE), enabled, }) const total = mappings.data?.total ?? 0 const pageCount = Math.max(1, Math.ceil(total / PAGE_SIZE)) useEffect(() => { if (!mappings.isFetching && page > pageCount) { setPage(pageCount) } }, [mappings.isFetching, page, pageCount]) const remove = useMutation({ mutationFn: (gh: string) => api.adminDeleteUserMapping(gh), onSuccess: () => void mappings.refetch(), onError: (e: Error) => setError(e.message), }) const upsert = useMutation({ mutationFn: () => api.adminUpsertUserMapping({ github_login: newLogin.trim(), work_email: newEmail.trim(), }), onSuccess: () => { setNewLogin("") setNewEmail("") setError(null) void mappings.refetch() }, onError: (e: Error) => setError(e.message), }) const canSubmit = newLogin.trim().length > 0 && newEmail.trim().length > 0 && !upsert.isPending const items = mappings.data?.items ?? [] return (
{error && {error}}
{ e.preventDefault() if (canSubmit) upsert.mutate() }} > setNewLogin(e.target.value)} placeholder="github-login" aria-label="GitHub login" className="h-8 text-xs" /> setNewEmail(e.target.value)} placeholder="work@example.com" aria-label="Work email" type="email" className="h-8 text-xs" />
{mappings.isLoading ? ( ) : !items.length ? (

No mappings yet.

) : ( items.map((m: UserMapping) => (
{m.github_login} {m.work_email} {m.slack_user_id ? ` · ${m.slack_user_id}` : ""} {m.source ? ` · ${m.source}` : ""}
)) )}
{total > PAGE_SIZE && (
{total} mapping{total === 1 ? "" : "s"} · page {page} of{" "} {pageCount}
)}
) } function ObservabilityCredentialsSection() { const qc = useQueryClient() const creds = useQuery({ queryKey: ["teamCredentials"], queryFn: api.getTeamCredentials, }) const [error, setError] = useState(null) const [ddSite, setDdSite] = useState("datadoghq.com") const [ddApiKey, setDdApiKey] = useState("") const [ddAppKey, setDdAppKey] = useState("") const [lsApiKey, setLsApiKey] = useState("") const [lsEndpoint, setLsEndpoint] = useState("") const onError = (e: Error) => setError(e.message) const onSuccess = ( saved: Awaited> ) => { qc.setQueryData(["teamCredentials"], saved) setError(null) } const connectDd = useMutation({ mutationFn: (body: DatadogConnectBody) => api.connectDatadog(body), onSuccess: (saved) => { onSuccess(saved) setDdApiKey("") setDdAppKey("") }, onError, }) const disconnectDd = useMutation({ mutationFn: () => api.disconnectDatadog(), onSuccess, onError, }) const connectLs = useMutation({ mutationFn: (body: LangSmithConnectBody) => api.connectLangSmith(body), onSuccess: (saved) => { onSuccess(saved) setLsApiKey("") }, onError, }) const disconnectLs = useMutation({ mutationFn: () => api.disconnectLangSmith(), onSuccess, onError, }) const datadog = creds.data?.datadog const langsmith = creds.data?.langsmith const busy = creds.isLoading return (
disconnectDd.mutate()} disabled={disconnectDd.isPending} > Disconnect ) : (
setDdSite(e.target.value)} disabled={busy} /> setDdApiKey(e.target.value)} disabled={busy} /> setDdAppKey(e.target.value)} disabled={busy} />
) } /> disconnectLs.mutate()} disabled={disconnectLs.isPending} > Disconnect ) : (
setLsApiKey(e.target.value)} disabled={busy} /> setLsEndpoint(e.target.value)} disabled={busy} />
) } />
{error &&

{error}

}
) } type GatewayMode = "inherit" | "enabled" | "disabled" function gatewayMode(value: boolean | null | undefined): GatewayMode { if (value === true) return "enabled" if (value === false) return "disabled" return "inherit" } function gatewayModeValue(mode: GatewayMode): boolean | null { if (mode === "enabled") return true if (mode === "disabled") return false return null } function LLMGatewaySection() { const qc = useQueryClient() const settings = useQuery({ queryKey: ["teamSettings"], queryFn: api.getTeamSettings, }) const [error, setError] = useState(null) const save = useMutation({ mutationFn: (body: TeamSettings) => api.saveTeamSettings(body), onSuccess: (saved) => { qc.setQueryData(["teamSettings"], saved) setError(null) }, onError: (e: Error) => setError(e.message), }) const mode = gatewayMode(settings.data?.gateway_enabled) return (
settings.data && save.mutate({ ...settings.data, gateway_enabled: gatewayModeValue(next as GatewayMode), }) } disabled={!settings.data || save.isPending} > Inherit deployment default Enabled Disabled } />
{error &&

{error}

}
) } function PRTraceResolutionSection() { const qc = useQueryClient() const settings = useQuery({ queryKey: ["teamSettings"], queryFn: api.getTeamSettings, }) const [projectDraft, setProjectDraft] = useState("") const [error, setError] = useState(null) useEffect(() => { setProjectDraft(settings.data?.review_tracing_project ?? "") }, [settings.data?.review_tracing_project]) const save = useMutation({ mutationFn: (body: TeamSettings) => api.saveTeamSettings(body), onSuccess: (saved) => { qc.setQueryData(["teamSettings"], saved) setError(null) }, onError: (e: Error) => setError(e.message), }) const savedProject = settings.data?.review_tracing_project ?? "" const projectDirty = projectDraft.trim() !== savedProject const saveProject = () => { if (!settings.data || !projectDirty) return save.mutate({ ...settings.data, review_tracing_project: projectDraft.trim() || null, }) } return (
setProjectDraft(e.target.value)} onBlur={saveProject} disabled={!settings.data || save.isPending} />
} /> {error &&

{error}

}
) } function GlobalDefaultsSection({ models }: { models: Array }) { const qc = useQueryClient() const settings = useQuery({ queryKey: ["teamSettings"], queryFn: api.getTeamSettings, }) const [error, setError] = useState(null) const [defaultRepoDraft, setDefaultRepoDraft] = useState("") useEffect(() => { setDefaultRepoDraft(settings.data?.default_repo ?? "") }, [settings.data?.default_repo]) const save = useMutation({ mutationFn: (body: TeamSettings) => api.saveTeamSettings(body), onSuccess: (saved) => { qc.setQueryData(["teamSettings"], saved) setError(null) }, onError: (e: Error) => setError(e.message), }) return (
settings.data && save.mutate({ ...settings.data, default_agent_model: model, default_agent_reasoning_effort: effort, }) } disabled={!settings.data || save.isPending} /> settings.data && save.mutate({ ...settings.data, default_agent_subagent_model: model, default_agent_subagent_reasoning_effort: effort, }) } disabled={!settings.data || save.isPending} /> setDefaultRepoDraft(e.target.value)} onBlur={() => settings.data && save.mutate({ ...settings.data, default_repo: defaultRepoDraft.trim() || null, }) } disabled={!settings.data || save.isPending} /> } /> settings.data && save.mutate({ ...settings.data, default_reviewer_model: model, default_reviewer_reasoning_effort: effort, }) } disabled={!settings.data || save.isPending} /> settings.data && save.mutate({ ...settings.data, default_reviewer_subagent_model: model, default_reviewer_subagent_reasoning_effort: effort, }) } disabled={!settings.data || save.isPending} /> settings.data && save.mutate({ ...settings.data, default_grouping_model: null, default_grouping_reasoning_effort: null, }) } onChange={(model, effort) => settings.data && save.mutate({ ...settings.data, default_grouping_model: model, default_grouping_reasoning_effort: effort, }) } disabled={!settings.data || save.isPending} /> settings.data && save.mutate({ ...settings.data, default_chat_model: null, default_chat_reasoning_effort: null, }) } onChange={(model, effort) => settings.data && save.mutate({ ...settings.data, default_chat_model: model, default_chat_reasoning_effort: effort, }) } disabled={!settings.data || save.isPending} />
{error &&

{error}

}
) } interface RolePickerProps { label: string description: string models: Array model: string | null effort: string | null onChange: (model: string, effort: string) => void disabled: boolean /** * When set, the model dropdown gains a leading "inherit" option with this * label. Selecting it calls {@link onInherit} (clearing the override); an * unset `model` renders as this option. */ inheritLabel?: string onInherit?: () => void } const INHERIT_VALUE = "__inherit__" function RolePicker({ label, description, models, model, effort, onChange, disabled, inheritLabel, onInherit, }: RolePickerProps) { const inheritFallback = inheritLabel ? INHERIT_VALUE : "" const [localModel, setLocalModel] = useState(model ?? inheritFallback) const [localEffort, setLocalEffort] = useState(effort ?? "") useEffect(() => { setLocalModel(model ?? inheritFallback) setLocalEffort(effort ?? "") }, [model, effort, inheritFallback]) const isInherit = localModel === INHERIT_VALUE const selectedModel = models.find((m) => m.id === localModel) const availableEfforts = selectedModel?.efforts ?? [] const handleModelChange = (value: string | null) => { if (!value) return if (value === INHERIT_VALUE) { setLocalModel(INHERIT_VALUE) setLocalEffort("") onInherit?.() return } const nextModel = models.find((m) => m.id === value) if (!nextModel) return const nextEffort = nextModel.efforts.includes(localEffort) ? localEffort : nextModel.default_effort setLocalModel(value) setLocalEffort(nextEffort) onChange(value, nextEffort) } const handleEffortChange = (value: string | null) => { if (!value || !localModel || isInherit) return setLocalEffort(value) onChange(localModel, value) } return ( } /> ) }