import { Loader2Icon, SearchIcon } from "lucide-react"; import { type FormEvent, useEffect, useId, useState } from "react"; import { SESSION_HARNESS_LABELS, SESSION_HARNESSES, type SessionHarness, } from "../../../../sessions/types"; import { apiFetch } from "../../hooks/use-api"; import { buildDocDeepLink } from "../../lib/deep-links"; import { renderSnippet } from "../../lib/snippet"; import { Badge } from "../ui/badge"; import { Button } from "../ui/button"; import { Input } from "../ui/input"; interface SessionSearchResult { docid: string; uri: string; title?: string; snippet: string; categories?: string[]; record?: { author?: string; categories?: string[]; dateFields?: Record; }; } interface SearchResponse { results: SessionSearchResult[]; } interface TagsResponse { tags: Array<{ tag: string; count: number }>; } type Role = "human" | "assistant"; const SELECT_CLASS = "h-9 w-full min-w-0 rounded-md border border-input bg-background px-2 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring/50"; const tagValue = (tags: readonly string[], prefix: string): string | null => tags.find((tag) => tag.startsWith(`${prefix}/`))?.slice(prefix.length + 1) ?? null; function resultRole(result: SessionSearchResult, tags: string[]): Role | null { const author = result.record?.author?.toLowerCase(); if (author === "human" || author === "assistant") return author; const role = tagValue(tags, "role"); if (role === "human" || role === "assistant") return role; const title = result.title ?? ""; if (title.startsWith("Human")) return "human"; if (title.startsWith("Assistant")) return "assistant"; return null; } function AuthorBadge({ role }: { role: Role | null }) { if (role === "human") { return ( Human ); } if (role === "assistant") { return ( Assistant — suggestion, not a user decision ); } return Author unknown; } function formatRecorded(iso: string | undefined): string { if (!iso) return "time unknown"; const date = new Date(iso); return Number.isNaN(date.getTime()) ? iso : date.toLocaleString(); } interface SessionSearchProps { collections: string[]; navigate: (to: string) => void; } export function SessionSearch({ collections, navigate }: SessionSearchProps) { const id = useId(); const [query, setQuery] = useState(""); const [harness, setHarness] = useState<"" | SessionHarness>(""); const [project, setProject] = useState(""); const [role, setRole] = useState<"" | Role>(""); const [collection, setCollection] = useState(""); const [projects, setProjects] = useState([]); const [results, setResults] = useState(null); const [error, setError] = useState(null); const [loading, setLoading] = useState(false); useEffect(() => { void apiFetch("/api/tags?prefix=project").then(({ data }) => { setProjects( (data?.tags ?? []) .map((entry) => entry.tag) .filter((tag) => tag.startsWith("project/")) .map((tag) => tag.slice("project/".length)) .sort() ); }); }, []); const submit = async (event: FormEvent) => { event.preventDefault(); const trimmed = query.trim(); if (!trimmed) return; const tagsAll = [ "session", harness ? `harness/${harness}` : null, project ? `project/${project}` : null, role ? `role/${role}` : null, ].filter((tag): tag is string => tag !== null); setLoading(true); const { data, error: err } = await apiFetch("/api/search", { method: "POST", body: JSON.stringify({ query: trimmed, limit: 20, tagsAll: tagsAll.join(","), ...(collection ? { collection } : {}), }), }); setLoading(false); setError(err); setResults(data?.results ?? null); }; return (

Search sessions

void submit(event)} role="search" >
setQuery(event.currentTarget.value)} placeholder="What was decided about…" type="search" value={query} />
{error && (

{error}

)} {results && results.length === 0 && (

No archived turns matched.

)} {results && results.length > 0 && (
    {results.map((result) => { const tags = result.categories ?? result.record?.categories ?? []; const resultHarness = tagValue(tags, "harness"); const resultProject = tagValue(tags, "project"); const href = buildDocDeepLink({ uri: result.uri }); return (
  1. {resultHarness ? (SESSION_HARNESS_LABELS[ resultHarness as SessionHarness ] ?? resultHarness) : "harness unknown"} project {resultProject ?? "none"} ·{" "} {formatRecorded(result.record?.dateFields?.recorded)}
    { event.preventDefault(); navigate(href); }} > {result.title || result.uri}

    {renderSnippet(result.snippet)}

  2. ); })}
)}
); }