@ai-matrx/coding-sessions 0.1.134 → 0.1.135
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/react/index.cjs +11 -14
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +11 -14
- package/dist/react/index.js.map +1 -1
- package/dist/ui/assets/{index-TQJcipgr.css → index-CS9dgyXY.css} +1 -1
- package/dist/ui/assets/{index-Dzam1sJ_.js → index-CYN1nkNV.js} +1 -1
- package/dist/ui/index.html +2 -2
- package/package.json +4 -4
package/dist/react/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/index.ts","../../src/react/app.tsx","../../src/types.ts","../../src/provider-health.ts","../../src/tool-labels.ts","../../src/react/changes-panel.tsx","../../src/changes.ts","../../src/react/chat-menu.tsx","../../src/react/grouping.ts","../../src/react/hooks.ts","../../src/react/icons.tsx","../../src/react/toast.ts","../../src/react/model-picker.tsx","../../src/react/agent-field.tsx","../../src/react/sidebar.tsx","../../src/react/client.ts","../../src/transcript.ts","../../src/react/new-session.ts"],"sourcesContent":["/**\n * `@ai-matrx/coding-sessions/react` — the screen. `<CodingSessionsApp>` is the\n * whole product; the provider and hooks exist for a host composing its own\n * layout around the same state.\n *\n * Styling: the components use the design system's semantic Tailwind classes\n * plus the package's own `cs-*` rules. The standalone page served by\n * `./server` ships them compiled; a Tailwind host adds this package's `dist`\n * as an `@source` and imports the chat + design-system sheets (see README).\n */\n\nexport { CodingSessionsApp, CodingSessionsProvider } from \"./app\";\nexport type { CodingSessionsAppProps, CodingSessionsProviderProps } from \"./app\";\nexport { CodingSessionsClient, SessionTranscript } from \"./client\";\nexport type { CodingSessionsState, Loadable, PreviewState } from \"./client\";\nexport {\n useCodingSessionsClient,\n useCodingSessionsState,\n useSessionTranscript,\n relativeTime,\n prettyPath,\n} from \"./hooks\";\n","/**\n * THE SCREEN. A three-group list (Running · Recent · Your other chats), a live\n * transcript rendered by `@ai-matrx/chat` (markdown answers, collapsible tool\n * cards, streaming), a composer, and a New session flow. No terminal anywhere:\n * the person never sees a command, a flag or a log line.\n *\n * Every state is honest: loading, empty, host unreachable, provider not\n * installed or not signed in (with the fix in plain English), a run that failed\n * with its real error. A control is present and working, or absent.\n */\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\n\nimport {\n ChatComposer,\n ChatMessageList,\n ChatProvider,\n type ChatNotifierPort,\n} from \"@ai-matrx/chat/react\";\nimport { createExternalThreadSource } from \"@ai-matrx/chat/external-store\";\nimport {\n Button,\n Dialog,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n Textarea,\n cn,\n} from \"@ai-matrx/design-system\";\n\nimport { formatCount, formatUsd } from \"@ai-matrx/kit/format\";\nimport { formatUntil } from \"../provider-health\";\nimport { friendlyToolName } from \"../tool-labels\";\nimport {\n PROVIDER_LABEL,\n isTerminalRunStatus,\n type ActiveElsewhere,\n type AgentDetails,\n type AgentSelection,\n type CodingProvider,\n type CodingSession,\n type CodingSessionsTransport,\n type DiscoveredSession,\n type ProviderStatus,\n type RunRecord,\n} from \"../types\";\nimport { ChangesPanel, useChangedFiles } from \"./changes-panel\";\nimport { ChatMenuItems } from \"./chat-menu\";\nimport { discoveredEntry, sessionEntry, type ListEntry } from \"./grouping\";\nimport { ModelPicker, defaultModelWords, modelLabel, type ModelChoice } from \"./model-picker\";\nimport { AgentField, AgentMenu, ChooseAgentDialog, missingRequiredVariable } from \"./agent-field\";\nimport { MODEL_UNAVAILABLE_LABEL, isModelUnavailable, runErrorLabel } from \"../provider-health\";\nimport { Sidebar, type Selection } from \"./sidebar\";\nimport { ToastContext } from \"./toast\";\nimport { CodingSessionsClient, type PreviewState } from \"./client\";\nimport { firstInvalidField, validateNewSession, type NewSessionErrors, type NewSessionField } from \"./new-session\";\nimport {\n CodingSessionsContext,\n prettyPath,\n relativeTime,\n useCodingSessionsClient,\n useCodingSessionsState,\n useMinuteClock,\n useSessionTranscript,\n} from \"./hooks\";\nimport {\n AlertIcon,\n BellIcon,\n ChatBubbleIcon,\n CheckIcon,\n FileIcon,\n FolderIcon,\n KeyboardIcon,\n MoreIcon,\n SidebarIcon,\n HandoffIcon,\n MonitorIcon,\n MoonIcon,\n PlusIcon,\n ProviderMark,\n RefreshIcon,\n SpinnerIcon,\n StopIcon,\n SunIcon,\n} from \"./icons\";\n\n/* ------------------------------------------------------------------------ */\n/* Provider */\n/* ------------------------------------------------------------------------ */\n\nexport interface CodingSessionsProviderProps {\n transport: CodingSessionsTransport;\n children: ReactNode;\n}\n\nexport function CodingSessionsProvider({ transport, children }: CodingSessionsProviderProps): ReactNode {\n const [client] = useState(() => new CodingSessionsClient(transport));\n useEffect(() => {\n if (transport.status().state === \"open\") void client.refreshAll();\n }, [client, transport]);\n return <CodingSessionsContext.Provider value={client}>{children}</CodingSessionsContext.Provider>;\n}\n\n/* ------------------------------------------------------------------------ */\n/* Selection (kept in the URL hash so a reload lands where you were) */\n/* ------------------------------------------------------------------------ */\n\nfunction readHash(): Selection {\n if (typeof location === \"undefined\") return { kind: \"none\" };\n const [kind, a, b] = location.hash.replace(/^#/, \"\").split(\"/\");\n if (kind === \"s\" && a) return { kind: \"session\", id: a };\n if (kind === \"d\" && (a === \"claude\" || a === \"codex\") && b) return { kind: \"discovered\", provider: a, id: b };\n return { kind: \"none\" };\n}\n\nfunction writeHash(selection: Selection): void {\n if (typeof history === \"undefined\") return;\n const hash =\n selection.kind === \"session\"\n ? `#s/${selection.id}`\n : selection.kind === \"discovered\"\n ? `#d/${selection.provider}/${selection.id}`\n : \"\";\n history.replaceState(null, \"\", `${location.pathname}${location.search}${hash}`);\n}\n\n/* ------------------------------------------------------------------------ */\n/* Theme: system by default, light/dark on demand */\n/* ------------------------------------------------------------------------ */\n\ntype ThemeChoice = \"system\" | \"light\" | \"dark\";\n\nfunction readTheme(): ThemeChoice {\n try {\n const stored = localStorage.getItem(\"coding-sessions.theme\");\n return stored === \"light\" || stored === \"dark\" ? stored : \"system\";\n } catch {\n return \"system\";\n }\n}\n\nfunction useTheme(): [ThemeChoice, (next: ThemeChoice) => void] {\n const [choice, setChoice] = useState<ThemeChoice>(readTheme);\n useEffect(() => {\n // A host without matchMedia (a test DOM, an old webview) follows the choice.\n const media = typeof window.matchMedia === \"function\" ? window.matchMedia(\"(prefers-color-scheme: dark)\") : null;\n const apply = () => {\n const dark = choice === \"dark\" || (choice === \"system\" && media?.matches === true);\n document.documentElement.classList.toggle(\"dark\", dark);\n document.documentElement.setAttribute(\"data-theme\", dark ? \"dark\" : \"light\");\n };\n apply();\n media?.addEventListener(\"change\", apply);\n return () => media?.removeEventListener(\"change\", apply);\n }, [choice]);\n const set = useCallback((next: ThemeChoice) => {\n setChoice(next);\n try {\n localStorage.setItem(\"coding-sessions.theme\", next);\n } catch {\n /* a private window keeps the choice for this visit only */\n }\n }, []);\n return [choice, set];\n}\n\n/* ------------------------------------------------------------------------ */\n/* Small pieces */\n/* ------------------------------------------------------------------------ */\n\nconst RUN_LABEL: Record<RunRecord[\"status\"], string> = {\n starting: \"Starting\",\n running: \"Working\",\n completed: \"Done\",\n stopped: \"Stopped\",\n failed: \"Failed\",\n};\n\nfunction RunPill({ run }: { run: RunRecord | undefined }): ReactNode {\n if (!run) return null;\n const live = !isTerminalRunStatus(run.status);\n return (\n <span className={cn(\"cs-pill\", `cs-pill--${run.status}`)}>\n {live ? <span className=\"cs-pill__dot\" aria-hidden=\"true\" /> : null}\n {RUN_LABEL[run.status]}\n </span>\n );\n}\n\nfunction ConnectionBanner(): ReactNode {\n const { connection } = useCodingSessionsState();\n if (connection.state === \"open\") return null;\n const closed = connection.state === \"closed\";\n return (\n <div\n role=\"status\"\n className={cn(\n \"flex items-center gap-2 border-b px-4 py-2 text-[13px]\",\n closed ? \"border-destructive/30 bg-destructive/10 text-destructive\" : \"border-border bg-muted/60 text-muted-foreground\",\n )}\n >\n {closed ? <AlertIcon size={15} /> : <SpinnerIcon size={14} />}\n <span>{closed ? connection.reason : \"Connecting to the coding sessions host…\"}</span>\n </div>\n );\n}\n\nfunction ProvidersFooter(props: { theme: ThemeChoice; setTheme: (next: ThemeChoice) => void; extra?: ReactNode }): ReactNode {\n const state = useCodingSessionsState();\n const client = useCodingSessionsClient();\n const next: Record<ThemeChoice, ThemeChoice> = { system: \"light\", light: \"dark\", dark: \"system\" };\n const themeLabel: Record<ThemeChoice, string> = { system: \"Match system\", light: \"Light\", dark: \"Dark\" };\n return (\n <div className=\"border-t border-border px-3 py-2.5\">\n <div className=\"flex items-center gap-1.5\">\n <div className=\"flex min-w-0 flex-1 flex-wrap gap-1.5\">\n {state.providers.loading && state.providers.loadedAt === null ? (\n <span className=\"text-[11.5px] text-muted-foreground\">Checking Claude Code and Codex…</span>\n ) : (\n state.providers.data.map((p) => (\n <span\n key={p.provider}\n className={cn(\"cs-provider-chip\", p.ready ? \"\" : \"cs-provider-chip--problem\")}\n title={\n p.problem\n ? `${p.problem} ${p.fix ?? \"\"}`\n : [binaryWords(p) ?? p.label, p.plan, newerWords(p)].filter(Boolean).join(\" · \")\n }\n >\n <ProviderMark provider={p.provider} size={13} />\n {p.label}\n {p.lastProblem ? (\n <span className=\"cs-provider-chip__note\">\n {p.lastProblem.kind === \"signed-out\"\n ? \"· sign in again\"\n : `· limit${formatUntil(p.lastProblem.until) ? ` until ${formatUntil(p.lastProblem.until)}` : \"\"}`}\n </span>\n ) : null}\n {p.ready ? <CheckIcon size={12} /> : <AlertIcon size={12} />}\n </span>\n ))\n )}\n </div>\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => void client.refreshProviders()}\n aria-label=\"Check Claude Code and Codex again\"\n title=\"Check again\"\n >\n {state.providers.loading ? <SpinnerIcon size={13} /> : <RefreshIcon size={13} />}\n </button>\n {props.extra}\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => props.setTheme(next[props.theme])}\n aria-label={`Theme: ${themeLabel[props.theme]}. Switch to ${themeLabel[next[props.theme]]}.`}\n title={`Theme: ${themeLabel[props.theme]}`}\n >\n {props.theme === \"system\" ? <MonitorIcon size={14} /> : props.theme === \"light\" ? <SunIcon size={14} /> : <MoonIcon size={14} />}\n </button>\n </div>\n </div>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* Session view */\n/* ------------------------------------------------------------------------ */\n\nfunction useNotifier(): ChatNotifierPort {\n const show = useContext(ToastContext);\n return useMemo<ChatNotifierPort>(\n () => ({\n notify(event) {\n // The chat package speaks to developers through remedies that name its\n // components; the reader gets the sentence.\n show(event.message);\n },\n }),\n [show],\n );\n}\n\n/**\n * Is this chat live somewhere else right now? Re-checked every 10 seconds\n * while it is on screen; `provider` null switches the check off.\n */\nfunction useLiveElsewhere(\n provider: CodingProvider | null,\n providerSessionId: string | null,\n initial: ActiveElsewhere | null = null,\n): ActiveElsewhere | null {\n const client = useCodingSessionsClient();\n const [state, setState] = useState<ActiveElsewhere | null>(initial);\n useEffect(() => {\n if (!provider || !providerSessionId) {\n setState(null);\n return;\n }\n let cancelled = false;\n const check = () =>\n client.transport\n .call(\"sessionActivity\", provider, providerSessionId)\n .then((next) => {\n if (!cancelled) setState(next);\n })\n .catch(() => undefined);\n void check();\n const timer = setInterval(check, 10_000);\n return () => {\n cancelled = true;\n clearInterval(timer);\n };\n }, [client, provider, providerSessionId]);\n return state;\n}\n\n/** What this session has used, summed over its runs (refreshed as runs end). */\nfunction useSessionUsage(sessionId: string, lastRunKey: string): { tokens: number; cost: number | null; billing: RunRecord[\"billing\"]; runs: number } | null {\n const client = useCodingSessionsClient();\n const [usage, setUsage] = useState<{ tokens: number; cost: number | null; billing: RunRecord[\"billing\"]; runs: number } | null>(null);\n useEffect(() => {\n let cancelled = false;\n void client.transport\n .call(\"listRuns\", sessionId)\n .then((runs) => {\n if (cancelled) return;\n let tokens = 0;\n let cost: number | null = null;\n let billing: RunRecord[\"billing\"] = null;\n for (const run of runs) {\n if (run.usage) tokens += run.usage.inputTokens + run.usage.outputTokens + run.usage.cachedInputTokens;\n if (run.costUsd !== null) cost = (cost ?? 0) + run.costUsd;\n billing = run.billing ?? billing;\n }\n setUsage(tokens > 0 || cost !== null ? { tokens, cost, billing, runs: runs.length } : null);\n })\n .catch(() => undefined);\n return () => {\n cancelled = true;\n };\n }, [client, sessionId, lastRunKey]);\n return usage;\n}\n\n/**\n * The header's ⋯. Header actions never wrap: at narrow widths the secondary ones hide from the\n * header (container query) and stay reachable here.\n */\nfunction HeaderMenu(props: { entry: ListEntry; onRename: () => void; onChanges?: () => void; changesOpen?: boolean }): ReactNode {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button type=\"button\" className=\"cs-icon-button shrink-0\" aria-label=\"More for this chat\" title=\"More\">\n <MoreIcon size={16} />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-64\" onCloseAutoFocus={(e) => e.preventDefault()}>\n {props.onChanges ? (\n <DropdownMenuItem onSelect={props.onChanges}>\n <FileIcon size={14} />\n {props.changesOpen ? \"Hide changed files\" : \"Files this chat changed\"}\n </DropdownMenuItem>\n ) : null}\n <ChatMenuItems entry={props.entry} variant=\"dropdown\" onRename={props.onRename} />\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\n/** The chat's title in a header, renameable in place. */\nfunction HeaderTitle(props: { entry: ListEntry; renaming: boolean; setRenaming: (on: boolean) => void }): ReactNode {\n const client = useCodingSessionsClient();\n const show = useContext(ToastContext);\n const [value, setValue] = useState(props.entry.title);\n useEffect(() => setValue(props.entry.title), [props.entry.title, props.renaming]);\n // The header menu's focus trap takes focus back from a freshly mounted input and then\n // unmounts, leaving focus on <body> — the next keystrokes went to the composer and were\n // SENT. Focus once the menu has gone, so typing lands in the title.\n const inputRef = useRef<HTMLInputElement>(null);\n useEffect(() => {\n if (!props.renaming) return;\n const timer = setTimeout(() => {\n const input = inputRef.current;\n if (input && document.activeElement !== input) {\n input.focus();\n input.select();\n }\n }, 0);\n return () => clearTimeout(timer);\n }, [props.renaming]);\n if (!props.renaming) {\n return (\n <h1\n className=\"truncate text-[15px] font-semibold leading-5 tracking-[-0.01em]\"\n title={props.entry.title !== props.entry.originalTitle ? `${props.entry.title} (${props.entry.originalTitle})` : props.entry.title}\n onDoubleClick={() => props.setRenaming(true)}\n >\n {props.entry.title}\n </h1>\n );\n }\n const save = () => {\n props.setRenaming(false);\n const title = value.trim();\n if (title === props.entry.title) return;\n const next = title === \"\" || title === props.entry.originalTitle ? null : title;\n client\n .setPreference(props.entry.key, { title: next })\n .catch((error: unknown) => show(`The new name didn't save: ${error instanceof Error ? error.message : String(error)}`));\n };\n return (\n <input\n ref={inputRef}\n autoFocus\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onFocus={(e) => e.currentTarget.select()}\n onBlur={save}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") save();\n if (e.key === \"Escape\") props.setRenaming(false);\n }}\n aria-label=\"New name for this chat\"\n className=\"cs-rename-input !m-0 !h-6 !text-[15px] !font-semibold\"\n />\n );\n}\n\nfunction LongChatNote(props: { onEarlier: () => void; loading: boolean }): ReactNode {\n return (\n <p className=\"mx-auto mt-3 flex items-center gap-2 text-[12px] text-muted-foreground\">\n This chat is very long — showing its most recent part.\n <button type=\"button\" className=\"cs-link\" onClick={props.onEarlier} disabled={props.loading}>\n {props.loading ? \"Reading…\" : \"Show earlier\"}\n </button>\n </p>\n );\n}\n\n/** \"Codex 0.159.2 · from ChatGPT app\" — which CLI runs. */\nfunction binaryWords(p: ProviderStatus): string | null {\n if (!p.version) return null;\n return `${p.label} ${p.version}${p.binary ? ` · ${p.binary.sourceLabel}` : \"\"}`;\n}\n\n/** \"Newer: 0.160.0 from npm\" when a newer copy than the one in use exists. */\nfunction newerWords(p: ProviderStatus): string | null {\n return p.binary?.newer ? `Newer: ${p.binary.newer.version} ${p.binary.newer.sourceLabel}` : null;\n}\n\nfunction SessionView({ session, changesOpen, setChangesOpen }: { session: CodingSession; changesOpen: boolean; setChangesOpen: (open: boolean) => void }): ReactNode {\n const client = useCodingSessionsClient();\n const state = useCodingSessionsState();\n const show = useContext(ToastContext);\n const transcript = useSessionTranscript(session.id);\n const run = state.runs[session.id];\n const live = run !== undefined && !isTerminalRunStatus(run.status);\n const notifier = useNotifier();\n const provider = state.providers.data.find((p) => p.provider === session.provider) ?? null;\n const blocked = provider && (!provider.installed || !provider.loggedIn) ? provider : null;\n // A usage limit or expired sign-in WARNS (the person may have fixed it);\n // only a provider that cannot run at all holds the composer.\n const limited = !blocked && provider?.lastProblem ? provider : null;\n // The last run was refused for its MODEL: offer the picker right here.\n const modelRefused = run?.status === \"failed\" && isModelUnavailable(run.error);\n const [stopping, setStopping] = useState(false);\n const [renaming, setRenaming] = useState(false);\n const elsewhere = useLiveElsewhere(\n session.origin === \"takeover\" && !live ? session.provider : null,\n session.providerSessionId,\n );\n const entry = sessionEntry(session, state.preferences);\n const messages = transcript.thread.getSnapshot().messages;\n const files = useChangedFiles(messages);\n const usage = useSessionUsage(session.id, `${run?.runId ?? \"\"}:${run?.status ?? \"\"}`);\n\n useEffect(() => {\n if (!live) setStopping(false);\n }, [live]);\n\n const stop = async () => {\n if (!run) return;\n setStopping(true);\n await client.stop(run.runId).catch(() => setStopping(false));\n };\n\n const setOptions = (next: ModelChoice) => {\n client\n .setSessionOptions(session.id, { model: next.model, effort: next.effort })\n .then(() => show(`The next message uses ${modelLabel(next, provider)}.`))\n .catch((error: unknown) => show(`That didn't save: ${error instanceof Error ? error.message : String(error)}`));\n };\n\n const usageWords = usage\n ? `${formatCount(usage.tokens, { style: \"compact\" })} tokens${usage.cost !== null ? ` · ${formatUsd(usage.cost)}` : \"\"}`\n : null;\n const usageTitle = usage\n ? `${formatCount(usage.tokens)} tokens over ${usage.runs} ${usage.runs === 1 ? \"message\" : \"messages\"} sent from here.` +\n (usage.cost !== null\n ? usage.billing === \"subscription\"\n ? ` ${formatUsd(usage.cost)} is what this would cost at API prices — it's covered by your ${provider?.plan ?? \"\"} plan.`.replace(\" \", \" \")\n : ` Billed ${formatUsd(usage.cost)} to your API key.`\n : \"\")\n : \"\";\n\n return (\n <div className=\"flex min-w-0 flex-1\">\n <section className=\"flex min-w-0 flex-1 flex-col\" aria-label={entry.title}>\n <header className=\"@container/header flex items-center gap-2 border-b border-border px-5 pt-2.5 pb-2.5\">\n <ProviderMark provider={session.provider} size={22} />\n {/* overflow-hidden: the meta line never runs under the badges beside it. */}\n <div className=\"min-w-0 flex-1 overflow-hidden\">\n <HeaderTitle entry={entry} renaming={renaming} setRenaming={setRenaming} />\n <div className=\"flex min-w-0 items-center gap-1 text-[12px] leading-5 text-muted-foreground\">\n <span className=\"shrink-0\">{PROVIDER_LABEL[session.provider]}</span>\n <span aria-hidden=\"true\">·</span>\n <ModelPicker\n status={provider}\n value={{ model: session.model, effort: session.effort ?? null }}\n onChange={setOptions}\n />\n <span aria-hidden=\"true\">·</span>\n <FolderIcon size={12} className=\"shrink-0\" />\n <span className=\"min-w-[4rem] truncate\" title={session.cwd}>\n {prettyPath(session.cwd)}\n </span>\n {usageWords ? (\n <span className=\"shrink-0\" title={usageTitle}>\n · {usageWords}\n </span>\n ) : null}\n </div>\n </div>\n <AgentMenu transport={client.transport} sessionId={session.id} agent={session.agent ?? null} onChange={() => undefined} />\n <button\n type=\"button\"\n className={cn(\"cs-chip-button shrink-0 @max-[620px]/header:hidden\", changesOpen && \"cs-chip-button--on\")}\n onClick={() => setChangesOpen(!changesOpen)}\n aria-pressed={changesOpen}\n title=\"Files this chat changed\"\n >\n <FileIcon size={13} />\n {files.length > 0 ? `${files.length} ${files.length === 1 ? \"file\" : \"files\"} changed` : \"Changes\"}\n </button>\n <RunPill run={run} />\n {live ? (\n <Button variant=\"outline\" size=\"sm\" onClick={() => void stop()} disabled={stopping} className=\"gap-1.5\" title=\"Stop Esc\">\n {stopping ? <SpinnerIcon size={13} /> : <StopIcon size={13} />}\n {stopping ? \"Stopping…\" : \"Stop\"}\n </Button>\n ) : null}\n <HeaderMenu entry={entry} onRename={() => setRenaming(true)} onChanges={() => setChangesOpen(!changesOpen)} changesOpen={changesOpen} />\n </header>\n\n <div className=\"mx-chat flex min-h-0 flex-1 flex-col\">\n <ChatProvider thread={transcript.thread} ports={{ notifier, toolLabel: friendlyToolName }}>\n <div className=\"min-h-0 flex-1 overflow-hidden\">\n {transcript.state.loading ? (\n <div className=\"flex h-full items-center justify-center gap-2 text-[13px] text-muted-foreground\">\n <SpinnerIcon size={15} /> Loading the conversation…\n </div>\n ) : (\n <div className=\"flex h-full flex-col\">\n {transcript.state.unavailable ? (\n <p className=\"mx-auto mt-4 max-w-[720px] rounded-lg border border-border bg-muted/50 px-4 py-2.5 text-[13px] text-muted-foreground\">\n {transcript.state.unavailable}\n </p>\n ) : null}\n {transcript.state.truncated ? (\n <LongChatNote\n loading={transcript.state.loadingEarlier === true}\n onEarlier={() => void transcript.loadEarlier()}\n />\n ) : null}\n {messages.length === 0 && !live ? (\n <div className=\"flex flex-1 items-center justify-center text-[13px] text-muted-foreground\">\n {session.origin === \"takeover\"\n ? \"You've taken over this chat. Send a message to continue it.\"\n : \"Nothing here yet.\"}\n </div>\n ) : (\n <ChatMessageList className=\"min-h-0 flex-1\" label={`Conversation: ${entry.title}`} />\n )}\n </div>\n )}\n </div>\n <div data-cs-composer className=\"mx-auto w-full max-w-[820px] px-4 pb-4\">\n {limited ? (\n <div className=\"mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]\">\n <AlertIcon size={15} className=\"mt-0.5 shrink-0 text-warning\" />\n <span>\n {limited.problem} {limited.fix}\n </span>\n </div>\n ) : null}\n {modelRefused && !blocked ? (\n <div\n className=\"mb-2 flex items-center gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]\"\n role=\"alert\"\n >\n <AlertIcon size={15} className=\"shrink-0 text-warning\" />\n <span className=\"min-w-0 flex-1 truncate\" title={run?.error ?? undefined}>\n {MODEL_UNAVAILABLE_LABEL}\n </span>\n <ModelPicker\n status={provider}\n value={{ model: session.model, effort: session.effort ?? null }}\n onChange={setOptions}\n />\n </div>\n ) : null}\n {blocked ? (\n <div className=\"mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]\">\n <AlertIcon size={15} className=\"mt-0.5 shrink-0 text-warning\" />\n <span>\n {blocked.problem} {blocked.fix}\n </span>\n </div>\n ) : null}\n {/* ALWAYS in the layout (hidden when idle): a line that came and\n went with each run moved the composer under the pointer. */}\n <div className=\"cs-activity\" role=\"status\" aria-live=\"polite\" data-idle={live ? undefined : true}>\n {live ? (\n <>\n <SpinnerIcon size={13} />\n <span className=\"truncate\">\n {run?.status === \"starting\"\n ? `Starting ${PROVIDER_LABEL[session.provider]}…`\n : (transcript.activity ?? \"Thinking…\")}\n </span>\n <span className=\"ml-auto shrink-0 text-[11px] opacity-70\">Esc to stop</span>\n </>\n ) : null}\n </div>\n {elsewhere ? (\n <div className=\"mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]\">\n <AlertIcon size={15} className=\"mt-0.5 shrink-0 text-warning\" />\n <span>\n {elsewhere.message} A message sent here would put a second agent on the same chat.\n </span>\n </div>\n ) : null}\n {session.queued.length > 0 ? (\n <ul className=\"mb-2 space-y-1.5\" aria-label=\"Queued messages\">\n {session.queued.map((text, index) => (\n <li key={`${index}-${text.slice(0, 16)}`} className=\"cs-queued\">\n <span className=\"cs-queued__label\">Queued · sends when this run finishes</span>\n <span className=\"cs-queued__text\">{text}</span>\n </li>\n ))}\n </ul>\n ) : null}\n <ChatComposer\n placeholder={`Message ${PROVIDER_LABEL[session.provider]}…`}\n autoFocus\n {...(blocked ? { held: { reason: `${blocked.problem} ${blocked.fix ?? \"\"}`.trim() } } : {})}\n />\n </div>\n </ChatProvider>\n </div>\n </section>\n {changesOpen ? (\n <ChangesPanel files={files} cwd={session.cwd} truncated={transcript.state.truncated} onClose={() => setChangesOpen(false)} />\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* Discovered chat preview */\n/* ------------------------------------------------------------------------ */\n\n/**\n * A read-only thread for the preview whose identity never changes, so a\n * refresh (the chat is live elsewhere and growing) updates the list in place\n * instead of remounting it and losing the reader's scroll.\n */\nfunction usePreviewThread(id: string, onSend: () => void) {\n const ref = useRef<{ messages: PreviewState[\"messages\"]; listeners: Set<() => void> }>({ messages: [], listeners: new Set() });\n const send = useRef(onSend);\n send.current = onSend;\n const thread = useMemo(\n () =>\n createExternalThreadSource({\n getSnapshot: () => ({ messages: ref.current.messages, status: \"idle\", conversationId: id }),\n subscribe: (listener) => {\n ref.current.listeners.add(listener);\n return () => {\n ref.current.listeners.delete(listener);\n };\n },\n // Read-only here: \"Ask again\" and \"Edit\" SAY so instead of doing nothing.\n onSubmit: () => send.current(),\n }),\n [id],\n );\n const set = useCallback((messages: PreviewState[\"messages\"]) => {\n ref.current.messages = messages;\n for (const listener of ref.current.listeners) listener();\n }, []);\n return [thread, set] as const;\n}\n\nfunction DiscoveredView(props: {\n session: DiscoveredSession | null;\n provider: CodingProvider;\n id: string;\n onTakenOver: (id: string) => void;\n changesOpen: boolean;\n setChangesOpen: (open: boolean) => void;\n}): ReactNode {\n const client = useCodingSessionsClient();\n const state = useCodingSessionsState();\n const show = useContext(ToastContext);\n const now = useMinuteClock();\n const [preview, setPreview] = useState<PreviewState>({ loading: true, messages: [], unavailable: null, truncated: false });\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [confirming, setConfirming] = useState(false);\n const [renaming, setRenaming] = useState(false);\n const [maxBytes, setMaxBytes] = useState<number | undefined>(undefined);\n const [readingEarlier, setReadingEarlier] = useState(false);\n const elsewhere = useLiveElsewhere(props.provider, props.id, props.session?.activeElsewhere ?? null);\n const files = useChangedFiles(preview.messages);\n const d = props.session;\n const [thread, setThreadMessages] = usePreviewThread(props.id, () =>\n show(\n d?.cwd\n ? `This chat is read-only until you take it over. Press Take over to continue it here.`\n : \"This chat is read-only here: it doesn't record its folder, so it can't be continued.\",\n ),\n );\n\n useEffect(() => {\n let cancelled = false;\n const read = (first: boolean) =>\n client.readPreview(props.provider, props.id, maxBytes).then((next) => {\n if (cancelled) return;\n setThreadMessages(next.messages);\n setPreview(next);\n if (first) setReadingEarlier(false);\n });\n if (maxBytes === undefined) setPreview({ loading: true, messages: [], unavailable: null, truncated: false });\n void read(true);\n // Live elsewhere: follow it, so the preview is not a stale snapshot.\n const timer = elsewhere ? setInterval(() => void read(false), 8000) : null;\n return () => {\n cancelled = true;\n if (timer) clearInterval(timer);\n };\n }, [client, props.provider, props.id, maxBytes, elsewhere !== null, setThreadMessages]);\n\n const notifier = useNotifier();\n const entry = discoveredEntry(\n d ?? { provider: props.provider, providerSessionId: props.id, cwd: null, title: \"Chat\", updatedAt: \"\", source: null, activeElsewhere: null },\n state.preferences,\n );\n\n // Validation offers, never blocks: a live chat asks first, then proceeds.\n const requestTakeover = () => {\n if (elsewhere) setConfirming(true);\n else void takeover();\n };\n const [choosingAgent, setChoosingAgent] = useState(false);\n const takeover = async (agent?: AgentSelection) => {\n if (!d) return;\n setConfirming(false);\n setBusy(true);\n setError(null);\n try {\n const taken = await client.takeover(d, agent);\n props.onTakenOver(taken.id);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <div className=\"flex min-w-0 flex-1\">\n <section className=\"flex min-w-0 flex-1 flex-col\" aria-label={entry.title}>\n <header className=\"@container/header flex items-center gap-2 border-b border-border px-5 pt-2.5 pb-2.5\">\n <ProviderMark provider={props.provider} size={22} />\n <div className=\"min-w-0 flex-1\">\n <HeaderTitle entry={entry} renaming={renaming} setRenaming={setRenaming} />\n <p className=\"flex items-center gap-1.5 truncate text-[12px] leading-4 text-muted-foreground\">\n <span>{PROVIDER_LABEL[props.provider]}</span>\n {d?.cwd ? (\n <>\n <span aria-hidden=\"true\">·</span>\n <FolderIcon size={12} />\n <span className=\"truncate\" title={d.cwd}>\n {prettyPath(d.cwd)}\n </span>\n </>\n ) : null}\n {d ? <span>· last active {relativeTime(d.updatedAt, now)}</span> : null}\n </p>\n </div>\n {files.length > 0 ? (\n <button\n type=\"button\"\n className=\"cs-chip-button\"\n onClick={() => props.setChangesOpen(!props.changesOpen)}\n aria-pressed={props.changesOpen}\n title=\"Files this chat changed\"\n >\n <FileIcon size={13} />\n {`${files.length} ${files.length === 1 ? \"file\" : \"files\"} changed`}\n </button>\n ) : null}\n {d?.cwd ? (\n <Button\n size=\"sm\"\n variant={elsewhere ? \"outline\" : \"default\"}\n onClick={requestTakeover}\n disabled={busy}\n className=\"gap-1.5\"\n title={elsewhere ? elsewhere.message : undefined}\n >\n {busy ? <SpinnerIcon size={13} /> : elsewhere ? <AlertIcon size={14} className=\"text-warning\" /> : <HandoffIcon size={14} />}\n {elsewhere ? \"Take over anyway…\" : \"Take over\"}\n </Button>\n ) : null}\n {d?.cwd && !elsewhere ? (\n <Button size=\"sm\" variant=\"outline\" onClick={() => setChoosingAgent(true)} disabled={busy}>\n Continue with agent…\n </Button>\n ) : null}\n <ChooseAgentDialog\n transport={client.transport}\n open={choosingAgent}\n onOpenChange={setChoosingAgent}\n title=\"Continue with an agent\"\n action=\"Take over with this agent\"\n onConfirm={(agent) => takeover(agent)}\n />\n {d ? <HeaderMenu entry={entry} onRename={() => setRenaming(true)} /> : null}\n </header>\n {elsewhere ? (\n <div role=\"status\" className=\"flex items-start gap-2 border-b border-warning/40 bg-warning/10 px-5 py-2.5 text-[13px]\">\n <AlertIcon size={15} className=\"mt-0.5 shrink-0 text-warning\" />\n <span>\n <span className=\"font-medium\">{elsewhere.message}</span> Taking it over now would put two agents on the same\n chat, and they could overwrite each other's work. Finish or stop it there first if you can. This preview\n follows it as it runs.\n </span>\n </div>\n ) : null}\n <Dialog open={confirming} onOpenChange={setConfirming}>\n <DialogContent className=\"max-w-[460px]\">\n <DialogHeader>\n <DialogTitle>This chat is running right now in {PROVIDER_LABEL[props.provider]}</DialogTitle>\n <DialogDescription>\n {elsewhere?.message} If you take it over, two agents will work in the same conversation at once and may\n overwrite each other's changes.\n </DialogDescription>\n </DialogHeader>\n <DialogFooter>\n <Button variant=\"ghost\" onClick={() => setConfirming(false)}>\n Cancel\n </Button>\n <Button variant=\"destructive\" onClick={() => void takeover()}>\n Take over anyway\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n {error ? (\n <p className=\"border-b border-destructive/30 bg-destructive/10 px-5 py-2 text-[13px] text-destructive\">{error}</p>\n ) : null}\n {d && !d.cwd ? (\n <p className=\"border-b border-border bg-muted/50 px-5 py-2 text-[13px] text-muted-foreground\">\n This chat doesn't record which folder it ran in, so it can't be continued from here.\n </p>\n ) : null}\n <div className=\"mx-chat flex min-h-0 flex-1 flex-col\">\n {preview.loading ? (\n <div className=\"flex flex-1 items-center justify-center gap-2 text-[13px] text-muted-foreground\">\n <SpinnerIcon size={15} /> Reading this chat…\n </div>\n ) : preview.unavailable ? (\n <div className=\"flex flex-1 items-center justify-center px-6 text-center text-[13px] text-muted-foreground\">\n {preview.unavailable}\n </div>\n ) : (\n <ChatProvider thread={thread} ports={{ notifier, toolLabel: friendlyToolName }}>\n {preview.truncated ? (\n <LongChatNote\n loading={readingEarlier}\n onEarlier={() => {\n setReadingEarlier(true);\n setMaxBytes((m) => (m ?? 24 * 1024 * 1024) * 4);\n }}\n />\n ) : null}\n <ChatMessageList className=\"min-h-0 flex-1\" label=\"Chat preview\" />\n </ChatProvider>\n )}\n {d?.cwd ? (\n <div className=\"border-t border-border bg-muted/30 px-5 py-3 text-center text-[13px] text-muted-foreground\">\n This chat was started in {PROVIDER_LABEL[props.provider]}.{\" \"}\n <button type=\"button\" className=\"font-medium text-foreground underline-offset-4 hover:underline\" onClick={requestTakeover}>\n Take it over\n </button>{\" \"}\n to continue it here — it stays in your {PROVIDER_LABEL[props.provider]} history too.\n </div>\n ) : null}\n </div>\n </section>\n {props.changesOpen && files.length > 0 ? (\n <ChangesPanel files={files} cwd={d?.cwd ?? null} truncated={preview.truncated} onClose={() => props.setChangesOpen(false)} />\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* New session */\n/* ------------------------------------------------------------------------ */\n\nfunction ProviderCard(props: { status: ProviderStatus; selected: boolean; onSelect: () => void }): ReactNode {\n const ready = props.status.ready;\n return (\n <button\n type=\"button\"\n onClick={props.onSelect}\n aria-pressed={props.selected}\n className={cn(\n \"flex flex-1 flex-col gap-1.5 rounded-xl border px-3.5 py-3 text-left transition-colors\",\n props.selected ? \"border-primary bg-primary/5 ring-1 ring-primary\" : \"border-border hover:bg-accent/50\",\n )}\n >\n <span className=\"flex items-center gap-2\">\n <ProviderMark provider={props.status.provider} size={18} />\n <span className=\"text-[13.5px] font-semibold\">{props.status.label}</span>\n </span>\n {ready ? (\n <span className=\"flex items-center gap-1 text-[12px] text-success\">\n <CheckIcon size={13} />\n {props.status.billing === \"subscription\"\n ? `Signed in${props.status.plan ? ` · ${props.status.plan} plan` : \"\"}`\n : \"Signed in with an API key (billed per use)\"}\n </span>\n ) : (\n <span className=\"flex items-start gap-1 text-[12px] leading-4 text-warning\">\n <AlertIcon size={13} className=\"mt-px shrink-0\" />\n {props.status.problem}\n </span>\n )}\n {props.status.quota.filter((w) => w.usedPercent !== null).length > 0 ? (\n <span className=\"text-[11.5px] leading-4 text-muted-foreground\">\n {props.status.quota\n .filter((w) => w.usedPercent !== null)\n .map((w) => `${w.label}: ${w.usedPercent}% used`)\n .join(\" · \")}\n </span>\n ) : null}\n </button>\n );\n}\n\nfunction FieldError({ id, children }: { id: string; children: ReactNode }): ReactNode {\n return (\n <p id={id} role=\"alert\" className=\"flex items-start gap-1.5 text-[12.5px] leading-5 text-destructive\">\n <AlertIcon size={14} className=\"mt-0.5 shrink-0\" />\n <span>{children}</span>\n </p>\n );\n}\n\nfunction NewSessionDialog(props: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onStarted: (sessionId: string) => void;\n}): ReactNode {\n const client = useCodingSessionsClient();\n const state = useCodingSessionsState();\n const now = useMinuteClock();\n const [provider, setProvider] = useState<CodingProvider>(\"claude\");\n const [folder, setFolder] = useState(\"\");\n const [choice, setChoice] = useState<ModelChoice>({ model: null, effort: null });\n const [prompt, setPrompt] = useState(\"\");\n const [errors, setErrors] = useState<NewSessionErrors>({});\n const [problem, setProblem] = useState<string | null>(null);\n const [starting, setStarting] = useState(false);\n const [creating, setCreating] = useState(false);\n const [agent, setAgent] = useState<AgentSelection | null>(null);\n const [agentDetails, setAgentDetails] = useState<AgentDetails | null>(null);\n const [agentMissing, setAgentMissing] = useState<string | null>(null);\n const promptRef = useRef<HTMLTextAreaElement | null>(null);\n const folderRef = useRef<HTMLInputElement | null>(null);\n const agentRef = useRef<HTMLFieldSetElement | null>(null);\n\n useEffect(() => {\n if (!props.open) return;\n setProblem(null);\n setErrors({});\n void client.refreshProviders();\n void client.refreshFolders();\n }, [props.open, client]);\n\n useEffect(() => {\n if (!folder && state.folders.data[0]?.exists) setFolder(state.folders.data[0].path);\n }, [state.folders.data, folder]);\n\n useEffect(() => {\n const ready = state.providers.data.filter((p) => p.ready);\n const current = state.providers.data.find((p) => p.provider === provider);\n if (current && !current.ready && ready[0]) setProvider(ready[0].provider);\n // Only when the statuses first arrive.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.providers.loadedAt]);\n\n const selected = state.providers.data.find((p) => p.provider === provider) ?? null;\n\n const focusField = (field: NewSessionField | null) => {\n if (field === \"prompt\") promptRef.current?.focus();\n else if (field === \"folder\") folderRef.current?.focus();\n else if (field === \"agent\") agentRef.current?.querySelector<HTMLButtonElement>(\"button\")?.focus();\n };\n\n const start = async () => {\n if (starting) return;\n setProblem(null);\n const found = await validateNewSession({\n provider: selected,\n folder,\n prompt,\n checkFolder: (path) => client.transport.call(\"checkFolder\", path),\n });\n setErrors(found);\n const first = firstInvalidField(found);\n if (first) {\n focusField(first);\n return;\n }\n const missing = missingRequiredVariable(agentDetails, agent);\n setAgentMissing(missing);\n if (missing) {\n document.getElementById(`cs-agent-var-${missing}`)?.focus();\n return;\n }\n setStarting(true);\n try {\n const result = await client.start({\n provider,\n cwd: folder.trim(),\n prompt,\n model: choice.model,\n effort: choice.effort,\n ...(agent ? { agent } : {}),\n });\n setPrompt(\"\");\n props.onStarted(result.session.id);\n } catch (error) {\n setProblem(error instanceof Error ? error.message : String(error));\n } finally {\n setStarting(false);\n }\n };\n\n const createFolder = async () => {\n if (!errors.createFolder) return;\n setCreating(true);\n try {\n const made = await client.transport.call(\"createFolder\", errors.createFolder);\n setFolder(made.path);\n setErrors((e) => {\n const next = { ...e };\n delete next.folder;\n delete next.createFolder;\n return next;\n });\n void client.refreshFolders();\n folderRef.current?.focus();\n } catch (error) {\n setErrors((e) => ({ ...e, folder: `Couldn't create it: ${error instanceof Error ? error.message : String(error)}` }));\n } finally {\n setCreating(false);\n }\n };\n\n const clear = (field: NewSessionField) =>\n setErrors((e) => {\n if (e[field] === undefined) return e;\n const next = { ...e };\n delete next[field];\n if (field === \"folder\") delete next.createFolder;\n return next;\n });\n\n return (\n <Dialog open={props.open} onOpenChange={props.onOpenChange}>\n <DialogContent className=\"max-w-[560px]\">\n <DialogHeader>\n <DialogTitle>New coding session</DialogTitle>\n <DialogDescription>\n Runs on your own {provider === \"claude\" ? \"Claude\" : \"ChatGPT\"} sign-in, in a folder on this computer.\n </DialogDescription>\n </DialogHeader>\n\n <form\n noValidate\n onSubmit={(e) => {\n e.preventDefault();\n void start();\n }}\n className=\"flex min-h-0 flex-col\"\n >\n {/* The body scrolls; the footer never hides a message below the fold. */}\n <div className=\"cs-dialog-body space-y-5 py-1 pr-1\">\n <fieldset className=\"space-y-2\" ref={agentRef}>\n <legend className=\"mb-2 text-[12.5px] font-medium\">Agent</legend>\n {state.providers.loading && state.providers.loadedAt === null ? (\n <div className=\"flex gap-2\">\n <div className=\"cs-skeleton h-[68px] flex-1 rounded-xl\" />\n <div className=\"cs-skeleton h-[68px] flex-1 rounded-xl\" />\n </div>\n ) : state.providers.error ? (\n <p className=\"text-[12.5px] text-destructive\">{state.providers.error}</p>\n ) : (\n <div className=\"flex gap-2\">\n {state.providers.data.map((p) => (\n <ProviderCard\n key={p.provider}\n status={p}\n selected={p.provider === provider}\n onSelect={() => {\n if (p.provider !== provider) setChoice({ model: null, effort: null });\n setProvider(p.provider);\n clear(\"agent\");\n }}\n />\n ))}\n </div>\n )}\n {errors.agent ? (\n <FieldError id=\"cs-err-agent\">{errors.agent}</FieldError>\n ) : selected && !selected.ready && selected.fix ? (\n <p className=\"text-[12px] leading-4 text-muted-foreground\">\n {selected.fix}\n {selected.installed && selected.loggedIn ? \" You can still try — the run will say if it's still blocked.\" : \"\"}\n </p>\n ) : null}\n </fieldset>\n\n <fieldset className=\"space-y-2\">\n <legend className=\"mb-2 text-[12.5px] font-medium\">AI Matrx agent</legend>\n <AgentField\n transport={client.transport}\n open={props.open}\n value={agent}\n onChange={(next) => {\n setAgent(next);\n setAgentMissing(null);\n }}\n missing={agentMissing}\n onDetails={setAgentDetails}\n />\n </fieldset>\n\n <fieldset className=\"space-y-2\">\n <legend className=\"mb-2 text-[12.5px] font-medium\">Folder</legend>\n {state.folders.data.length > 0 ? (\n <div className=\"max-h-[132px] space-y-0.5 overflow-y-auto rounded-lg border border-border p-1\">\n {state.folders.data.map((f) => (\n <button\n type=\"button\"\n key={f.path}\n onClick={() => {\n setFolder(f.path);\n clear(\"folder\");\n }}\n disabled={!f.exists}\n title={f.exists ? f.path : `${f.path} no longer exists`}\n className={cn(\n \"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-[12.5px]\",\n folder === f.path ? \"bg-accent text-accent-foreground\" : \"hover:bg-accent/50\",\n !f.exists && \"opacity-50\",\n )}\n >\n <FolderIcon size={14} className=\"shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 flex-1 truncate\">{prettyPath(f.path)}</span>\n <span className=\"shrink-0 text-[11px] text-muted-foreground\">\n {f.exists ? relativeTime(f.lastUsedAt, now) : \"missing\"}\n </span>\n </button>\n ))}\n </div>\n ) : state.folders.loading ? (\n <div className=\"cs-skeleton h-10 rounded-lg\" />\n ) : null}\n <Input\n ref={folderRef}\n value={folder}\n onChange={(e) => {\n setFolder(e.target.value);\n clear(\"folder\");\n }}\n placeholder=\"Or type a folder path, like ~/code/my-app\"\n aria-label=\"Folder path\"\n aria-invalid={errors.folder ? true : undefined}\n aria-describedby={errors.folder ? \"cs-err-folder\" : undefined}\n spellCheck={false}\n />\n {errors.folder ? (\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-1\">\n <FieldError id=\"cs-err-folder\">{errors.folder}</FieldError>\n {errors.createFolder ? (\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={() => void createFolder()} disabled={creating} className=\"gap-1.5\">\n {creating ? <SpinnerIcon size={13} /> : <FolderIcon size={13} />}\n Create this folder\n </Button>\n ) : null}\n </div>\n ) : null}\n </fieldset>\n\n <fieldset className=\"space-y-2\">\n <legend className=\"mb-2 text-[12.5px] font-medium\">What should it do?</legend>\n <Textarea\n ref={promptRef}\n value={prompt}\n onChange={(e) => {\n setPrompt(e.target.value);\n clear(\"prompt\");\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n void start();\n }\n }}\n placeholder=\"Describe the change, the bug, or the question…\"\n rows={4}\n aria-label=\"First message\"\n aria-invalid={errors.prompt ? true : undefined}\n aria-describedby={errors.prompt ? \"cs-err-prompt\" : undefined}\n />\n {errors.prompt ? <FieldError id=\"cs-err-prompt\">{errors.prompt}</FieldError> : null}\n </fieldset>\n\n <fieldset className=\"space-y-2\">\n <legend className=\"mb-2 text-[12.5px] font-medium\">Model and thinking effort</legend>\n <ModelPicker status={selected} value={choice} onChange={setChoice} appearance=\"field\" />\n <p className=\"text-[11.5px] leading-4 text-muted-foreground\">\n Default is {defaultModelWords(selected)}. You can change it later from the chat's header.\n </p>\n </fieldset>\n\n {problem ? <FieldError id=\"cs-err-start\">{problem}</FieldError> : null}\n </div>\n\n <DialogFooter className=\"pt-4\">\n <Button type=\"button\" variant=\"ghost\" onClick={() => props.onOpenChange(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={starting} className=\"gap-1.5\">\n {starting ? <SpinnerIcon size={14} /> : null}\n {starting ? \"Starting…\" : \"Start session\"}\n {!starting ? <kbd className=\"cs-kbd\">⌘↵</kbd> : null}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* Home (nothing selected) */\n/* ------------------------------------------------------------------------ */\n\nfunction Home({ onNew }: { onNew: () => void }): ReactNode {\n const state = useCodingSessionsState();\n return (\n <section className=\"flex flex-1 items-center justify-center px-6\">\n <div className=\"w-full max-w-[460px] text-center\">\n <span className=\"mx-auto mb-4 flex h-11 w-11 items-center justify-center rounded-2xl bg-primary/10 text-primary\">\n <ChatBubbleIcon size={22} />\n </span>\n <h1 className=\"text-[15px] font-semibold leading-5 tracking-[-0.01em]\">Drive Claude Code and Codex from here</h1>\n <p className=\"mx-auto mt-2 max-w-[400px] text-[13.5px] leading-6 text-muted-foreground\">\n Start a session in any folder, or pick up a chat you began somewhere else. Everything runs on your own\n subscriptions — no API keys.\n </p>\n <Button className=\"mt-5 gap-1.5\" onClick={onNew}>\n <PlusIcon size={15} />\n New session\n </Button>\n <p className=\"mt-3 text-[12px] text-muted-foreground\">\n <kbd className=\"cs-kbd\">⌥⌘N</kbd> new session · <kbd className=\"cs-kbd\">⌘K</kbd> search your chats ·{\" \"}\n <kbd className=\"cs-kbd\">⌘/</kbd> all shortcuts\n </p>\n <div className=\"mt-6 flex flex-wrap justify-center gap-2 text-left\">\n {state.providers.data.map((p) => (\n <div\n key={p.provider}\n data-provider-card={p.provider}\n title={p.installed && p.version ? [binaryWords(p), newerWords(p) ?? p.binary?.path].filter(Boolean).join(\" · \") : undefined}\n className=\"flex w-[260px] items-start gap-2.5 rounded-lg border border-border bg-card px-3 py-2.5\"\n >\n <ProviderMark provider={p.provider} size={16} />\n <div className=\"min-w-0 flex-1 leading-5\">\n <span className=\"block truncate text-[14px] font-semibold\">{p.label}</span>\n {/* Two lines: the name, then one 12px status line; the version lives in the tooltip. */}\n {p.ready ? (\n <span className=\"block truncate text-[12px] text-muted-foreground\">\n Ready{p.plan ? ` on your ${p.plan} plan` : \"\"}\n {p.billing === \"api\" ? \" (API key, billed per use)\" : \"\"}\n </span>\n ) : (\n <span className=\"block text-[12px] text-muted-foreground\">\n {p.problem} {p.fix}\n </span>\n )}\n </div>\n {p.ready ? (\n <CheckIcon size={15} className=\"mt-0.5 text-success\" />\n ) : (\n <AlertIcon size={15} className=\"mt-0.5 text-warning\" />\n )}\n </div>\n ))}\n </div>\n </div>\n </section>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* The app */\n/* ------------------------------------------------------------------------ */\n\ninterface ToastHandle {\n text: string | null;\n /** The session a run notice is about; null for other notices. */\n sessionId: string | null;\n show: (text: string, sessionId?: string | null) => void;\n dismiss: () => void;\n}\n\nfunction useToast(): ToastHandle {\n const [current, setCurrent] = useState<{ text: string; sessionId: string | null } | null>(null);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(() => () => {\n if (timer.current) clearTimeout(timer.current);\n }, []);\n const show = useCallback((next: string, sessionId: string | null = null) => {\n setCurrent({ text: next, sessionId });\n if (timer.current) clearTimeout(timer.current);\n timer.current = setTimeout(() => setCurrent(null), 6000);\n }, []);\n const dismiss = useCallback(() => {\n if (timer.current) clearTimeout(timer.current);\n setCurrent(null);\n }, []);\n return { text: current?.text ?? null, sessionId: current?.sessionId ?? null, show, dismiss };\n}\n\n/** Bottom-right of the chat pane, above the composer when one is on screen. */\nfunction Toast({ text }: { text: string | null }): ReactNode {\n const ref = useRef<HTMLDivElement | null>(null);\n useLayoutEffect(() => {\n const el = ref.current;\n const pane = el?.parentElement;\n if (!el || !pane) return;\n const composer = pane.querySelector(\"[data-cs-composer]\");\n const gap = composer ? pane.getBoundingClientRect().bottom - composer.getBoundingClientRect().top + 8 : 20;\n el.style.setProperty(\"--cs-toast-bottom\", `${Math.max(20, Math.round(gap))}px`);\n }, [text]);\n if (!text) return null;\n return (\n <div ref={ref} role=\"status\" data-cs-toast className=\"cs-toast\">\n {text}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* Sidebar width, collapse, shortcuts, finished-run notices */\n/* ------------------------------------------------------------------------ */\n\nconst SIDEBAR_DEFAULT = 300;\nconst SIDEBAR_MIN = 220;\nconst SIDEBAR_MAX = 560;\n\nfunction clampWidth(n: number): number {\n return Math.round(Math.min(SIDEBAR_MAX, Math.max(SIDEBAR_MIN, n)));\n}\n\nfunction useSidebarLayout(): {\n width: number;\n setWidth: (n: number) => void;\n collapsed: boolean;\n setCollapsed: (v: boolean) => void;\n} {\n const [width, setWidthState] = useState(() => {\n try {\n const n = Number(localStorage.getItem(\"coding-sessions.sidebar-width\"));\n return Number.isFinite(n) && n > 0 ? clampWidth(n) : SIDEBAR_DEFAULT;\n } catch {\n return SIDEBAR_DEFAULT;\n }\n });\n const [collapsed, setCollapsedState] = useState(() => {\n try {\n return localStorage.getItem(\"coding-sessions.sidebar-collapsed\") === \"1\";\n } catch {\n return false;\n }\n });\n const setWidth = useCallback((n: number) => {\n const next = clampWidth(n);\n setWidthState(next);\n try {\n localStorage.setItem(\"coding-sessions.sidebar-width\", String(next));\n } catch {\n /* this visit only */\n }\n }, []);\n const setCollapsed = useCallback((v: boolean) => {\n setCollapsedState(v);\n try {\n localStorage.setItem(\"coding-sessions.sidebar-collapsed\", v ? \"1\" : \"0\");\n } catch {\n /* this visit only */\n }\n }, []);\n return { width, setWidth, collapsed, setCollapsed };\n}\n\nfunction Resizer(props: { width: number; setWidth: (n: number) => void }): ReactNode {\n const [dragging, setDragging] = useState(false);\n return (\n <div className={cn(\"cs-resizer\", dragging && \"cs-resizer--dragging\")}>\n <button\n type=\"button\"\n className=\"cs-resizer__grip\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label=\"Resize the sidebar\"\n aria-valuenow={props.width}\n aria-valuemin={SIDEBAR_MIN}\n aria-valuemax={SIDEBAR_MAX}\n title=\"Drag to resize · double-click to reset\"\n onDoubleClick={() => props.setWidth(SIDEBAR_DEFAULT)}\n onKeyDown={(e) => {\n if (e.key === \"ArrowLeft\") props.setWidth(props.width - 16);\n if (e.key === \"ArrowRight\") props.setWidth(props.width + 16);\n }}\n onPointerDown={(e) => {\n e.preventDefault();\n const startX = e.clientX;\n const startWidth = props.width;\n setDragging(true);\n document.body.style.cursor = \"col-resize\";\n document.body.style.userSelect = \"none\";\n const move = (ev: PointerEvent) => props.setWidth(startWidth + ev.clientX - startX);\n const up = () => {\n setDragging(false);\n document.body.style.cursor = \"\";\n document.body.style.userSelect = \"\";\n window.removeEventListener(\"pointermove\", move);\n window.removeEventListener(\"pointerup\", up);\n };\n window.addEventListener(\"pointermove\", move);\n window.addEventListener(\"pointerup\", up);\n }}\n />\n </div>\n );\n}\n\nconst SHORTCUTS: { keys: string; what: string }[] = [\n { keys: \"⌘K\", what: \"Search chats\" },\n { keys: \"⌥⌘N\", what: \"New session\" },\n { keys: \"Enter\", what: \"Send (Shift+Enter for a new line)\" },\n { keys: \"Esc\", what: \"Stop the run in the open chat\" },\n { keys: \"⌘B\", what: \"Show or hide the sidebar\" },\n { keys: \"⌥↑ / ⌥↓\", what: \"Previous or next chat in the list\" },\n { keys: \"⌘/\", what: \"These shortcuts\" },\n];\n\nfunction ShortcutsDialog(props: { open: boolean; onOpenChange: (open: boolean) => void }): ReactNode {\n return (\n <Dialog open={props.open} onOpenChange={props.onOpenChange}>\n <DialogContent className=\"max-w-[420px]\">\n <DialogHeader>\n <DialogTitle>Keyboard shortcuts</DialogTitle>\n <DialogDescription>Ctrl works in place of ⌘ on Windows and Linux.</DialogDescription>\n </DialogHeader>\n <dl className=\"divide-y divide-border text-[13px]\">\n {SHORTCUTS.map((s) => (\n <div key={s.keys} className=\"flex items-center justify-between gap-4 py-2\">\n <dt className=\"text-muted-foreground\">{s.what}</dt>\n <dd>\n <kbd className=\"rounded border border-border px-1.5 py-0.5 font-sans text-[12px]\">{s.keys}</kbd>\n </dd>\n </div>\n ))}\n </dl>\n </DialogContent>\n </Dialog>\n );\n}\n\nconst BASE_TITLE = \"Coding sessions\";\n\n/**\n * A run that ends while you are looking elsewhere: a count in the tab's title\n * until you come back, a desktop notification when you allowed them, and a\n * toast when it was a different chat than the one on screen.\n */\nfunction useRunFinishedNotices(openSessionId: string | null, toast: ToastHandle): void {\n const { show, dismiss, sessionId: toastSession } = toast;\n const state = useCodingSessionsState();\n // A notice about a run never outlives what it says: it goes once that chat is opened, or once\n // the chat runs again (the pane would otherwise show \"Starting\" under \"finished\").\n useEffect(() => {\n if (!toastSession) return;\n const run = state.runs[toastSession];\n if (openSessionId === toastSession || (run && (run.status === \"starting\" || run.status === \"running\"))) dismiss();\n }, [toastSession, openSessionId, state.runs, dismiss]);\n const client = useCodingSessionsClient();\n const unseen = useRef(0);\n const openRef = useRef(openSessionId);\n openRef.current = openSessionId;\n useEffect(() => {\n const reset = () => {\n if (document.visibilityState === \"visible\") {\n unseen.current = 0;\n document.title = BASE_TITLE;\n }\n };\n document.addEventListener(\"visibilitychange\", reset);\n const off = client.onRunFinished(({ run, session }) => {\n const title = session?.title ?? \"A session\";\n const outcome = run.status === \"completed\" ? \"finished\" : run.status === \"failed\" ? \"failed\" : \"was stopped\";\n const sentence = `${PROVIDER_LABEL[run.provider]} ${outcome}: ${title}`;\n if (document.visibilityState === \"hidden\") {\n unseen.current += 1;\n document.title = `(${unseen.current}) ${BASE_TITLE}`;\n if (typeof Notification !== \"undefined\" && Notification.permission === \"granted\") {\n const note = new Notification(sentence, run.error ? { tag: run.runId, body: runErrorLabel(run.error) } : { tag: run.runId });\n note.onclick = () => {\n window.focus();\n location.hash = `#s/${run.sessionId}`;\n note.close();\n };\n }\n } else if (openRef.current !== run.sessionId && run.status !== \"stopped\") {\n show(sentence, run.sessionId);\n }\n });\n return () => {\n off();\n document.removeEventListener(\"visibilitychange\", reset);\n };\n }, [client, show]);\n}\n\nfunction NotifyToggle(): ReactNode {\n const supported = typeof Notification !== \"undefined\";\n const [permission, setPermission] = useState(supported ? Notification.permission : \"denied\");\n if (!supported || permission === \"granted\") return null;\n return (\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => void Notification.requestPermission().then(setPermission)}\n aria-label={\n permission === \"denied\"\n ? \"Notifications are blocked for this page in your browser's site settings\"\n : \"Notify me when a run finishes\"\n }\n title={permission === \"denied\" ? \"Notifications are blocked in your browser's site settings\" : \"Notify me when a run finishes\"}\n disabled={permission === \"denied\"}\n >\n <BellIcon size={14} />\n </button>\n );\n}\n\nfunction isTyping(target: EventTarget | null): boolean {\n const el = target as HTMLElement | null;\n if (!el) return false;\n return el.isContentEditable || el.tagName === \"INPUT\" || el.tagName === \"TEXTAREA\" || el.tagName === \"SELECT\";\n}\n\nfunction Shell(): ReactNode {\n const client = useCodingSessionsClient();\n const state = useCodingSessionsState();\n const [selection, setSelection] = useState<Selection>(readHash);\n const [newOpen, setNewOpen] = useState(false);\n const [shortcutsOpen, setShortcutsOpen] = useState(false);\n const [changesOpen, setChangesOpen] = useState(false);\n const [found, setFound] = useState<Record<string, DiscoveredSession>>({});\n const [theme, setTheme] = useTheme();\n const toast = useToast();\n const showToast = toast.show;\n const layout = useSidebarLayout();\n const searchRef = useRef<HTMLInputElement | null>(null);\n\n const select = useCallback((next: Selection) => {\n setSelection(next);\n writeHash(next);\n }, []);\n\n useEffect(() => {\n const onHash = () => setSelection(readHash());\n window.addEventListener(\"hashchange\", onHash);\n return () => window.removeEventListener(\"hashchange\", onHash);\n }, []);\n\n useRunFinishedNotices(selection.kind === \"session\" ? selection.id : null, toast);\n\n const session =\n selection.kind === \"session\" ? (state.sessions.data.find((s) => s.id === selection.id) ?? null) : null;\n const discovered =\n selection.kind === \"discovered\"\n ? (state.discovered.data.find((d) => d.providerSessionId === selection.id) ??\n found[`${selection.provider}:${selection.id}`] ??\n null)\n : null;\n const run = session ? state.runs[session.id] : undefined;\n const live = run !== undefined && !isTerminalRunStatus(run.status);\n\n // The list order the sidebar shows, for ⌥↑ / ⌥↓.\n const order = useMemo((): Selection[] => {\n const known = new Set(state.sessions.data.map((s) => s.providerSessionId).filter(Boolean));\n return [\n ...state.sessions.data.map((s): Selection => ({ kind: \"session\", id: s.id })),\n ...state.discovered.data\n .filter((d) => !known.has(d.providerSessionId))\n .map((d): Selection => ({ kind: \"discovered\", provider: d.provider, id: d.providerSessionId })),\n ];\n }, [state.sessions.data, state.discovered.data]);\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n const mod = e.metaKey || e.ctrlKey;\n const key = e.key.toLowerCase();\n if (mod && !e.shiftKey && !e.altKey && key === \"k\") {\n e.preventDefault();\n layout.setCollapsed(false);\n requestAnimationFrame(() => {\n searchRef.current?.focus();\n searchRef.current?.select();\n });\n return;\n }\n if ((mod && e.altKey && (key === \"n\" || e.code === \"KeyN\")) || (mod && e.shiftKey && key === \"o\")) {\n e.preventDefault();\n setNewOpen(true);\n return;\n }\n if (mod && !e.shiftKey && !e.altKey && key === \"b\") {\n e.preventDefault();\n layout.setCollapsed(!layout.collapsed);\n return;\n }\n if (mod && key === \"/\") {\n e.preventDefault();\n setShortcutsOpen(true);\n return;\n }\n if (e.altKey && !mod && (e.key === \"ArrowUp\" || e.key === \"ArrowDown\")) {\n const at = order.findIndex((o) =>\n o.kind === \"session\" && selection.kind === \"session\"\n ? o.id === selection.id\n : o.kind === \"discovered\" && selection.kind === \"discovered\" && o.id === selection.id,\n );\n const next = order[e.key === \"ArrowUp\" ? Math.max(0, at - 1) : Math.min(order.length - 1, at + 1)];\n if (next) {\n e.preventDefault();\n select(next);\n }\n return;\n }\n if (e.key === \"Escape\" && live && run && !e.defaultPrevented) {\n // Never while a dialog or menu is open (Esc closes those), and never\n // from the search box (Esc clears it).\n if (document.querySelector('[role=\"dialog\"], [role=\"menu\"], [data-radix-popper-content-wrapper]')) return;\n if (e.target === searchRef.current) return;\n e.preventDefault();\n void client.stop(run.runId);\n showToast(\"Stopping…\");\n return;\n }\n if (e.key === \"?\" && !isTyping(e.target)) {\n setShortcutsOpen(true);\n }\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [client, layout, live, run, order, selection, select, showToast]);\n\n let main: ReactNode;\n if (selection.kind === \"session\") {\n main = session ? (\n <SessionView key={session.id} session={session} changesOpen={changesOpen} setChangesOpen={setChangesOpen} />\n ) : state.sessions.loadedAt === null ? (\n <div className=\"flex flex-1 items-center justify-center gap-2 text-[13px] text-muted-foreground\">\n <SpinnerIcon size={15} /> Loading…\n </div>\n ) : (\n <div className=\"flex flex-1 items-center justify-center text-[13px] text-muted-foreground\">\n That session is not in the list anymore.\n </div>\n );\n } else if (selection.kind === \"discovered\") {\n main = (\n <DiscoveredView\n key={`${selection.provider}:${selection.id}`}\n session={discovered}\n provider={selection.provider}\n id={selection.id}\n onTakenOver={(id) => select({ kind: \"session\", id })}\n changesOpen={changesOpen}\n setChangesOpen={setChangesOpen}\n />\n );\n } else {\n main = <Home onNew={() => setNewOpen(true)} />;\n }\n\n return (\n <ToastContext.Provider value={showToast}>\n <div className=\"cs-app flex h-full flex-col bg-background text-foreground\">\n <ConnectionBanner />\n <div className=\"flex min-h-0 flex-1\">\n {layout.collapsed ? (\n <div className=\"flex flex-col items-center gap-1 border-r border-border bg-muted/30 px-1.5 py-3\">\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => layout.setCollapsed(false)}\n aria-label=\"Show the sidebar (⌘B)\"\n title=\"Show sidebar ⌘B\"\n >\n <SidebarIcon size={15} />\n </button>\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => setNewOpen(true)}\n aria-label=\"New session\"\n title=\"New session ⌥⌘N\"\n >\n <PlusIcon size={15} />\n </button>\n </div>\n ) : (\n <>\n <Sidebar\n selection={selection}\n select={select}\n onNew={() => setNewOpen(true)}\n onCollapse={() => layout.setCollapsed(true)}\n width={layout.width}\n searchRef={searchRef}\n onFound={(d) => setFound((f) => ({ ...f, [`${d.provider}:${d.providerSessionId}`]: d }))}\n footer={\n <ProvidersFooter\n theme={theme}\n setTheme={setTheme}\n extra={\n <>\n <NotifyToggle />\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => setShortcutsOpen(true)}\n aria-label=\"Keyboard shortcuts (⌘/)\"\n title=\"Keyboard shortcuts ⌘/\"\n >\n <KeyboardIcon size={14} />\n </button>\n </>\n }\n />\n }\n />\n <Resizer width={layout.width} setWidth={layout.setWidth} />\n </>\n )}\n <main className=\"relative flex min-w-0 flex-1\">\n {main}\n <Toast text={toast.text} />\n </main>\n </div>\n <NewSessionDialog\n open={newOpen}\n onOpenChange={setNewOpen}\n onStarted={(id) => {\n setNewOpen(false);\n select({ kind: \"session\", id });\n }}\n />\n <ShortcutsDialog open={shortcutsOpen} onOpenChange={setShortcutsOpen} />\n </div>\n </ToastContext.Provider>\n );\n}\n\nexport interface CodingSessionsAppProps {\n transport: CodingSessionsTransport;\n}\n\n/** The whole product screen. Mount it full-height. */\nexport function CodingSessionsApp({ transport }: CodingSessionsAppProps): ReactNode {\n return (\n <CodingSessionsProvider transport={transport}>\n <Shell />\n </CodingSessionsProvider>\n );\n}\n","/**\n * The public contract of `@ai-matrx/coding-sessions`, shared by the engine\n * (Node), the local host (Node) and the UI (browser). Pure types — nothing here\n * touches Node or the DOM, and every value is JSON-serializable because it\n * crosses a transport (WebSocket today, desktop IPC later).\n */\n\nimport type { JsonValue } from \"@ai-matrx/agents/portable\";\n\n/** The coding agents this package drives. \"coding session\" is the canonical\n * platform term (chat.coding_session, the Coding Session Bridge). */\nexport type CodingProvider = \"claude\" | \"codex\";\n\nexport const CODING_PROVIDERS: readonly CodingProvider[] = [\"claude\", \"codex\"];\n\nexport const PROVIDER_LABEL: Record<CodingProvider, string> = {\n claude: \"Claude Code\",\n codex: \"Codex\",\n};\n\nexport type Billing = \"subscription\" | \"api\" | \"unknown\";\n\n/** Where the CLI a provider runs came from. */\nexport type BinarySource = \"desktop-app\" | \"path\" | \"npm-global\" | \"configured\";\n\n/** The exact CLI runs use: the newest copy on this computer (or the host's pick). */\nexport interface ProviderBinary {\n path: string;\n version: string | null;\n source: BinarySource;\n /** \"from ChatGPT app\", \"from PATH\", … */\n sourceLabel: string;\n /** A newer copy than the one in use, when one exists. */\n newer: { path: string; version: string; sourceLabel: string } | null;\n}\n\n/** What `providers()` answers for one provider, in plain terms. */\nexport interface ProviderStatus {\n provider: CodingProvider;\n label: string;\n installed: boolean;\n version: string | null;\n loggedIn: boolean;\n billing: Billing;\n /** \"Max\", \"Pro\", \"Plus\", … when the provider reports a plan. */\n plan: string | null;\n /** The signed-in account label, when the provider reports one. */\n account: string | null;\n /** A plain-English sentence for the screen when it is not ready. */\n problem: string | null;\n /** A plain-English fix for `problem`. */\n fix: string | null;\n /** Installed, signed in, and no known usage limit or expired sign-in. */\n ready: boolean;\n /** The last usage-limit or sign-in failure a run reported, until a run succeeds. */\n lastProblem: ProviderProblem | null;\n /** Usage windows, when the provider exposes them (Codex does; see FEATURE.md). */\n quota: QuotaWindow[];\n /** Models the driver knows for this provider (the person may type any other). */\n models?: ModelOption[] | undefined;\n /** Reasoning-effort levels this provider accepts, lowest first. */\n efforts?: string[] | undefined;\n /**\n * The model a run uses when none is picked, and where that comes from: the\n * person's own settings (`~/.claude/settings.json`, `~/.codex/config.toml`)\n * or the driver's built-in default.\n */\n defaultModel?: { id: string; source: \"settings\" | \"driver\" } | null | undefined;\n /** The effort a run uses when none is picked (the person's own settings). */\n defaultEffort?: string | null | undefined;\n /** Which CLI runs use, and its version. */\n binary?: ProviderBinary | null | undefined;\n}\n\nexport interface ModelOption {\n id: string;\n label: string;\n}\n\n/**\n * The person's own organisation of their chats — a rename, a pin, a hide. Kept\n * in this package's data dir, keyed by `chatKey()`; the providers' own files\n * are NEVER touched (a rename here does not rename the chat in Claude Code).\n */\nexport interface ChatPreference {\n /** Shown instead of the chat's own title. */\n title?: string | null | undefined;\n pinned?: boolean | undefined;\n /** Hidden from the lists (still found by search, restorable). */\n hidden?: boolean | undefined;\n updatedAt?: string | undefined;\n}\n\n/** The one key a chat's preference lives under, for ours and discovered alike. */\nexport function chatKey(provider: CodingProvider, providerSessionId: string | null, sessionId?: string | null): string {\n return providerSessionId ? `${provider}:${providerSessionId}` : `session:${sessionId ?? \"\"}`;\n}\n\n/** One chat that matched a search. */\nexport interface ChatSearchHit {\n provider: CodingProvider;\n providerSessionId: string;\n title: string;\n cwd: string | null;\n updatedAt: string;\n /** Where the words were found. */\n where: \"title\" | \"content\";\n /** A short excerpt around the first match in the conversation. */\n snippet: string | null;\n}\n\nexport interface ChatSearchResult {\n query: string;\n hits: ChatSearchHit[];\n /** How many chats were read, newest first, starting from the cursor. */\n scanned: number;\n /** How many chats exist on this computer. */\n total: number;\n /** Pass back to keep searching older chats; null when every chat was read. */\n nextCursor: number | null;\n}\n\n/** Where \"Open folder\" can open a session's folder. */\nexport type OpenTarget = \"finder\" | \"vscode\" | \"cursor\" | \"terminal\";\n\nexport interface ProviderProblem {\n kind: \"usage-limit\" | \"signed-out\";\n /** The provider's own words, verbatim. */\n message: string;\n /** When a usage limit lifts: ISO when parseable, else the provider's phrase. */\n until: string | null;\n at: string;\n}\n\nexport interface QuotaWindow {\n label: string;\n usedPercent: number | null;\n resetsAt: string | null;\n valueLabel: string | null;\n}\n\n/** An existing local Claude Code or Codex chat, found on disk (metadata only). */\nexport interface DiscoveredSession {\n provider: CodingProvider;\n providerSessionId: string;\n cwd: string | null;\n title: string;\n updatedAt: string;\n /** Where it was started, when the provider records it (\"cli\", \"vscode\", \"exec\", …). */\n source: string | null;\n /** Set when the chat looks live somewhere else right now (see `ActiveElsewhere`). */\n activeElsewhere: ActiveElsewhere | null;\n}\n\n/**\n * Evidence that a chat is being driven somewhere else RIGHT NOW. Taking it\n * over then puts two agents on one conversation, so the screen warns and asks —\n * it never blocks (validation offers, never blocks).\n */\nexport interface ActiveElsewhere {\n /** How we know, strongest first. */\n reason: \"process\" | \"recent-write\" | \"open-tool-call\";\n /** One plain sentence for the screen. */\n message: string;\n}\n\nexport type RunStatus = \"starting\" | \"running\" | \"completed\" | \"stopped\" | \"failed\";\n\nexport const TERMINAL_RUN_STATUSES: readonly RunStatus[] = [\"completed\", \"stopped\", \"failed\"];\n\nexport function isTerminalRunStatus(status: RunStatus): boolean {\n return TERMINAL_RUN_STATUSES.includes(status);\n}\n\nexport interface RunUsage {\n inputTokens: number;\n outputTokens: number;\n cachedInputTokens: number;\n}\n\n/** One turn: one prompt sent to one provider process. */\nexport interface RunRecord {\n runId: string;\n /** Our session id (`CodingSession.id`). */\n sessionId: string;\n provider: CodingProvider;\n cwd: string;\n prompt: string;\n model: string | null;\n status: RunStatus;\n startedAt: string;\n endedAt: string | null;\n /** The real error, verbatim from the provider or the driver, when failed. */\n error: string | null;\n usage: RunUsage | null;\n costUsd: number | null;\n billing: Billing | null;\n}\n\n/** How a session came to be listed here. */\nexport type SessionOrigin = \"started\" | \"takeover\";\n\n/** A conversation driven from here. Its transcript lives in the provider's own\n * files; this is only the index row. */\nexport interface CodingSession {\n /** Our stable id. */\n id: string;\n provider: CodingProvider;\n /** The provider's own session/thread id — null until the first run reports it. */\n providerSessionId: string | null;\n cwd: string;\n title: string;\n model: string | null;\n /** Reasoning effort for the next run; null = the provider's own default. */\n effort?: string | null | undefined;\n origin: SessionOrigin;\n createdAt: string;\n updatedAt: string;\n /** The live or most recent run. */\n lastRunId: string | null;\n lastRunStatus: RunStatus | null;\n /** Prompts waiting for the active run to finish, oldest first. */\n queued: string[];\n /** The AI Matrx agent loaded into every run of this session, when one was picked. */\n agent?: SessionAgent | null | undefined;\n /** Codex must be told, in the next prompt, that an earlier agent no longer applies. */\n agentRemovedDue?: boolean | undefined;\n}\n\n/**\n * One normalized transcript item — the same shape from Claude and Codex, from\n * a live stream and from a provider's saved session file.\n */\nexport type TranscriptItem =\n | { kind: \"user\"; id: string; text: string; at: string | null }\n | { kind: \"text\"; id: string; text: string }\n | { kind: \"text-delta\"; id: string; text: string }\n | { kind: \"reasoning\"; id: string; text: string }\n | { kind: \"tool-call\"; id: string; name: string; input: unknown }\n | { kind: \"tool-result\"; id: string; output: string; isError: boolean }\n | { kind: \"usage\"; usage: RunUsage; costUsd: number | null }\n | { kind: \"notice\"; id: string; level: \"info\" | \"warning\"; text: string }\n | { kind: \"error\"; id: string; text: string };\n\n/** Everything the engine pushes to a listener. */\nexport type CodingEvent =\n | { type: \"session\"; session: CodingSession }\n | { type: \"run\"; run: RunRecord }\n | { type: \"preferences\"; preferences: Record<string, ChatPreference> }\n | {\n type: \"item\";\n sessionId: string;\n runId: string;\n /** Monotonic per session; a history read reports the last `seq` it includes. */\n seq: number;\n item: TranscriptItem;\n };\n\n/** A transcript read back from the provider's own file. */\nexport interface SessionHistory {\n items: TranscriptItem[];\n /** True when the file was larger than the read budget and only its end was read. */\n truncated: boolean;\n /** Plain-English reason when history could not be read (never thrown at the UI). */\n unavailable: string | null;\n /** The last live item `seq` this read already contains; apply only newer ones. */\n seq: number;\n}\n\nexport interface StartInput {\n provider: CodingProvider;\n cwd: string;\n prompt: string;\n model?: string | null | undefined;\n effort?: string | null | undefined;\n /** An AI Matrx agent to load into the CLI. Needs the host's `agents` credentials. */\n agent?: AgentSelection | null | undefined;\n}\n\n/** Which AI Matrx agent a new session loads, and the person's variable values. */\nexport interface AgentSelection {\n agentId: string;\n /** Pin one saved version; omitted = the latest, pinned at start. */\n versionId?: string | null | undefined;\n variables?: Record<string, JsonValue> | undefined;\n}\n\n/** One part of an agent and whether this session's CLI carries it. */\nexport interface SessionAgentPart {\n part: \"instructions\" | \"skills\" | \"tools\";\n loaded: number;\n total: number;\n}\n\n/**\n * The agent a session runs with. Recorded at start and never drifts: every\n * later turn reloads the SAME bundle (same version, same hash).\n */\nexport interface SessionAgent {\n agentId: string;\n versionId: string | null;\n versionNumber: number | null;\n name: string;\n definitionHash: string;\n loaded: SessionAgentPart[];\n /** What could not be carried, with the reason. */\n unavailable: { kind: string; name: string; reason: string }[];\n /** The skills it carries (labels) and the tools it serves (names) — the agent's own set. */\n skills?: string[] | undefined;\n tools?: string[] | undefined;\n /** The person's variable values, kept so \"Update to vN\" can reuse them. */\n variables?: Record<string, JsonValue> | undefined;\n /**\n * The CLI must be TOLD in the next prompt (a delimited block): a Codex\n * takeover or agent switch (Codex ignores developer_instructions on resume),\n * or a Codex compaction that dropped the block. Cleared once delivered.\n */\n blockDue?: boolean | undefined;\n /** When the block (or native instructions) last reached the CLI. */\n deliveredAt?: string | null | undefined;\n /** The agent this one replaced mid-chat (\"Code Reviewer v1\"), named in the block. */\n replaces?: string | null | undefined;\n}\n\n/** Whether this host can reach AI Matrx as a signed-in person. */\nexport interface AgentAccess {\n signedIn: boolean;\n userId: string | null;\n organizationId: string | null;\n /** True when the host was started with no AI Matrx connection at all. */\n configured: boolean;\n}\n\n/** A catalogue read the picker asks the host to make (PostgREST RPC shape). */\nexport interface AgentCatalogRpcRequest {\n fn: string;\n args?: Record<string, unknown> | undefined;\n count?: \"exact\" | \"planned\" | \"estimated\" | undefined;\n range?: [number, number] | undefined;\n order?: { column: string; ascending?: boolean | undefined } | undefined;\n}\n\nexport interface AgentCatalogRpcResult {\n data: unknown;\n error: {\n message: string;\n code?: string | undefined;\n details?: string | null | undefined;\n hint?: string | null | undefined;\n } | null;\n count?: number | null;\n}\n\n/** What a picker needs about one agent — the LIGHT read (no skills, no tools). */\nexport interface AgentDetails {\n agentId: string;\n name: string;\n /** Variable declarations as authored (camelCase). */\n variables: Record<string, JsonValue>[];\n /** Newest first. */\n versions: { id: string; versionNumber: number; changedAt: string | null }[];\n /** The version \"Latest\" resolves to right now. */\n latestVersionNumber: number | null;\n latestVersionId: string | null;\n}\n\nexport interface TakeoverInput {\n provider: CodingProvider;\n providerSessionId: string;\n cwd: string;\n title?: string | undefined;\n /** Continue the chat WITH an AI Matrx agent (\"Continue with agent\"). */\n agent?: AgentSelection | null | undefined;\n}\n\nexport interface SendResult {\n session: CodingSession;\n /** The run that started, or null when the prompt was queued behind a live run. */\n run: RunRecord | null;\n queued: boolean;\n}\n\nexport interface FolderCheck {\n /** The absolute path the check resolved. */\n path: string;\n exists: boolean;\n /** False when something that is NOT a folder sits at the path. */\n isDirectory: boolean;\n}\n\n/** A folder the New session flow offers (from discovered and driven sessions). */\nexport interface RecentFolder {\n path: string;\n lastUsedAt: string;\n exists: boolean;\n}\n\n/**\n * THE ENGINE CONTRACT — what the UI can ask for, independent of transport.\n * The WebSocket host implements it over the wire; a desktop app implements it\n * over IPC; the UI never knows which.\n */\nexport interface CodingSessionsApi {\n providers(): Promise<ProviderStatus[]>;\n discoverSessions(options?: { limit?: number }): Promise<DiscoveredSession[]>;\n recentFolders(): Promise<RecentFolder[]>;\n listSessions(): Promise<CodingSession[]>;\n listRuns(sessionId: string): Promise<RunRecord[]>;\n /** `maxBytes` reads more of a long chat's file (\"Show earlier\"). */\n history(sessionId: string, options?: HistoryOptions): Promise<SessionHistory>;\n /** Read-only transcript of a chat found on disk, before taking it over. */\n readTranscript(provider: CodingProvider, providerSessionId: string, options?: HistoryOptions): Promise<SessionHistory>;\n /**\n * FULL DOWNLOAD: the provider's own complete transcript file for this chat,\n * byte for byte (every tool input and output). AI Matrx's cloud keeps only\n * text and tool names, so this computer is the first place the full file\n * lives. `available: false` carries the sentence saying why.\n */\n readRawTranscript(provider: CodingProvider, providerSessionId: string): Promise<RawTranscript>;\n /** Does this folder exist here? `~` is the person's home. */\n checkFolder(path: string): Promise<FolderCheck>;\n /** Create a folder (and any missing parents), then report on it. */\n createFolder(path: string): Promise<FolderCheck>;\n /** Fresh check: is this chat live somewhere else right now? null when not. */\n sessionActivity(provider: CodingProvider, providerSessionId: string): Promise<ActiveElsewhere | null>;\n start(input: StartInput): Promise<SendResult>;\n takeover(input: TakeoverInput): Promise<CodingSession>;\n send(sessionId: string, prompt: string): Promise<SendResult>;\n stop(runId: string): Promise<RunRecord | null>;\n /** The person's renames, pins and hides, by `chatKey()`. */\n chatPreferences(): Promise<Record<string, ChatPreference>>;\n /** Merge a change into one chat's preference; `null` fields clear. Returns them all. */\n setChatPreference(key: string, patch: ChatPreference): Promise<Record<string, ChatPreference>>;\n /** Find chats by title and by what was said in them, newest first, within a time budget. */\n searchChats(query: string, options?: { cursor?: number; limit?: number }): Promise<ChatSearchResult>;\n /** Open a folder in Finder, VS Code, Cursor or Terminal. */\n openFolder(path: string, target: OpenTarget): Promise<void>;\n /** Change the model or effort the NEXT run of a session uses. */\n setSessionOptions(sessionId: string, options: { model?: string | null; effort?: string | null }): Promise<CodingSession>;\n /** Is this host signed in to AI Matrx (so agents can load)? */\n agentAccess(): Promise<AgentAccess>;\n /** One allowlisted agent-catalogue read, made by the host as the signed-in person. */\n agentCatalogRpc(request: AgentCatalogRpcRequest): Promise<AgentCatalogRpcResult>;\n /** An agent's variables and saved versions, for the New session form. */\n agentDetails(agentId: string): Promise<AgentDetails>;\n /**\n * Load a different agent into a session from its next message on (or\n * remove it, with `null`). Claude reads it every turn; Codex is told in the\n * next prompt.\n */\n setAgent(sessionId: string, agent: AgentSelection | null): Promise<CodingSession>;\n}\n\nexport type RawTranscript =\n | { available: true; fileName: string; bytes: number; content: string }\n | { available: false; reason: string };\n\nexport interface HistoryOptions {\n /** Read up to this many bytes from the end of the file (default 24 MB). */\n maxBytes?: number | undefined;\n}\n\nexport type CodingSessionsMethod = keyof CodingSessionsApi;\n\n/** The transport the UI talks through (WebSocket, IPC, in-process). */\nexport interface CodingSessionsTransport {\n call<M extends CodingSessionsMethod>(\n method: M,\n ...args: Parameters<CodingSessionsApi[M]>\n ): ReturnType<CodingSessionsApi[M]>;\n subscribe(listener: (event: CodingEvent) => void): () => void;\n /** Connection state, for an honest banner. */\n status(): TransportStatus;\n onStatus(listener: (status: TransportStatus) => void): () => void;\n}\n\nexport type TransportStatus =\n | { state: \"connecting\" }\n | { state: \"open\" }\n | { state: \"closed\"; reason: string };\n","/**\n * USAGE LIMITS AND EXPIRED SIGN-INS, in plain English.\n *\n * A provider can be installed and signed in and still unable to run: the\n * ChatGPT or Claude plan hit its usage limit, or the saved login expired.\n * Runs report that in the provider's own words; this turns those words into\n * a remembered, honest status. Built from the real texts captured on\n * 2026-09-27 (Codex usage limit, Codex refresh failure).\n */\n\nimport { PROVIDER_LABEL, type CodingProvider, type ProviderProblem, type QuotaWindow } from \"./types\";\n\nconst USAGE_LIMIT = [\n /hit your usage limit/i,\n /usage limit (?:reached|exceeded)/i,\n /\\blimit reached\\b/i,\n /you'?ve hit your limit/i,\n /rate limit/i,\n /quota (?:exceeded|exhausted)/i,\n /purchase more credits/i,\n];\n\nconst SIGNED_OUT = [\n /access token could not be refreshed/i,\n /please sign in again/i,\n /(?:not|no longer) (?:logged|signed) in/i,\n /please run \\/login/i,\n /invalid api key/i,\n /oauth token (?:has )?expired/i,\n /authentication_error/i,\n /401 unauthorized/i,\n];\n\n/** \"Oct 4th, 2026 8:34 AM\" → ISO. null when the phrase is not a date. */\nexport function parseLimitDate(phrase: string): string | null {\n const cleaned = phrase.replace(/(\\d{1,2})(st|nd|rd|th)\\b/gi, \"$1\").replace(/[.,]\\s*$/, \"\").trim();\n const ms = Date.parse(cleaned);\n return Number.isNaN(ms) ? null : new Date(ms).toISOString();\n}\n\nfunction limitPhrase(text: string): string | null {\n const match =\n /try again (?:at|after|on) ([^\\n]+?)(?:\\.\\s|\\.$|$)/i.exec(text) ??\n /resets? (?:at |on )?([^\\n∙·|]+?)(?:\\.\\s|\\.$|$|\\s*[∙·|])/i.exec(text);\n return match?.[1]?.trim() ?? null;\n}\n\nexport function classifyProviderError(text: string, at = new Date().toISOString()): ProviderProblem | null {\n const trimmed = text.trim();\n if (!trimmed) return null;\n if (SIGNED_OUT.some((re) => re.test(trimmed))) {\n return { kind: \"signed-out\", message: trimmed, until: null, at };\n }\n if (USAGE_LIMIT.some((re) => re.test(trimmed))) {\n const phrase = limitPhrase(trimmed);\n return { kind: \"usage-limit\", message: trimmed, until: phrase ? (parseLimitDate(phrase) ?? phrase) : null, at };\n }\n return null;\n}\n\n/** A usage limit whose reset time has passed no longer applies. */\nexport function problemStillApplies(problem: ProviderProblem, now = Date.now()): boolean {\n if (problem.kind !== \"usage-limit\" || !problem.until) return true;\n const ms = Date.parse(problem.until);\n return Number.isNaN(ms) || ms > now;\n}\n\nexport function formatUntil(until: string | null): string | null {\n if (!until) return null;\n const ms = Date.parse(until);\n if (Number.isNaN(ms)) return until;\n return new Date(ms).toLocaleString(undefined, { month: \"short\", day: \"numeric\", hour: \"numeric\", minute: \"2-digit\" });\n}\n\n/** A full quota window (100% used) is a usage limit even before a run hits it. */\nexport function problemFromQuota(windows: readonly QuotaWindow[], at = new Date().toISOString()): ProviderProblem | null {\n const full = windows.find((w) => typeof w.usedPercent === \"number\" && w.usedPercent >= 100);\n if (!full) return null;\n return {\n kind: \"usage-limit\",\n message: `${full.label} is used up.`,\n until: full.resetsAt,\n at,\n };\n}\n\nexport function describeProblem(provider: CodingProvider, problem: ProviderProblem): { problem: string; fix: string } {\n const label = PROVIDER_LABEL[provider];\n if (problem.kind === \"signed-out\") {\n return {\n problem: `${label} — sign-in expired.`,\n fix: `Open ${label} and sign in again, then check again.`,\n };\n }\n const until = formatUntil(problem.until);\n return {\n problem: until ? `${label} — usage limit reached until ${until}.` : `${label} — usage limit reached.`,\n fix: until\n ? `It lifts on its own then, or add more usage in your ${provider === \"codex\" ? \"ChatGPT\" : \"Claude\"} account.`\n : `Wait for it to reset, or add more usage in your ${provider === \"codex\" ? \"ChatGPT\" : \"Claude\"} account.`,\n };\n}\n\n/**\n * A run refused because the CHOSEN MODEL is not available — to this account,\n * or to this version of the CLI. It is about the model, not the provider, so\n * the screen offers the model picker rather than a provider-wide warning.\n * Built from the real Codex text captured 2026-10-01\n * (fixtures/codex-model-unsupported.error.txt) and Claude Code's wording.\n */\nconst MODEL_UNAVAILABLE = [\n /model is not supported when using codex/i,\n /\\bmodel[\\s:'\"`][^.\\n]{0,80}\\b(?:not supported|does not exist|not available|not found)\\b/i,\n /\\bmodel_not_found\\b/i,\n /issue with the selected model/i,\n /may not exist or you may not have access to it/i,\n];\n\nexport const MODEL_UNAVAILABLE_LABEL = \"Model not available on this account\";\n\nexport function isModelUnavailable(text: string | null | undefined): boolean {\n const trimmed = (text ?? \"\").trim();\n return trimmed !== \"\" && MODEL_UNAVAILABLE.some((re) => re.test(trimmed));\n}\n\n/** What the screen says for a failed run: a short label for a known class, else the text itself. */\nexport function runErrorLabel(text: string): string {\n return isModelUnavailable(text) ? MODEL_UNAVAILABLE_LABEL : text;\n}\n","/**\n * What a tool call is CALLED on screen, and the one argument that says what\n * it is doing. `mcp__claude-in-chrome__browser_batch` reads \"Browser batch ·\n * Claude in chrome\"; `Bash {command: \"ls -la\"}` reads \"Run command\" with\n * \"ls -la\" beside it. The machine name stays on the card as `data-tool`.\n */\n\nconst BUILTIN: Record<string, string> = {\n Bash: \"Run command\",\n Shell: \"Run command\",\n BashOutput: \"Read command output\",\n KillShell: \"Stop command\",\n Read: \"Read file\",\n Write: \"Write file\",\n Edit: \"Edit file\",\n MultiEdit: \"Edit file\",\n NotebookEdit: \"Edit notebook\",\n Glob: \"Find files\",\n Grep: \"Search code\",\n LS: \"List folder\",\n WebFetch: \"Fetch page\",\n WebSearch: \"Web search\",\n \"Web search\": \"Web search\",\n Task: \"Sub-agent\",\n Agent: \"Sub-agent\",\n TodoWrite: \"Update plan\",\n Plan: \"Update plan\",\n \"Edit files\": \"Edit files\",\n ExitPlanMode: \"Finish planning\",\n Skill: \"Use skill\",\n ToolSearch: \"Load tools\",\n};\n\nfunction words(identifier: string): string {\n const spaced = identifier\n .replace(/[._-]+/g, \" \")\n .replace(/([a-z\\d])([A-Z])/g, \"$1 $2\")\n .replace(/\\s+/g, \" \")\n .trim()\n .toLowerCase();\n return spaced ? spaced.charAt(0).toUpperCase() + spaced.slice(1) : \"\";\n}\n\n/** `mcp__<server>__<tool>` → { server, tool }, or null. */\nexport function parseMcpToolName(name: string): { server: string; tool: string } | null {\n const match = /^mcp__(.+?)__(.+)$/.exec(name);\n return match?.[1] && match[2] ? { server: match[1], tool: match[2] } : null;\n}\n\nexport function friendlyToolName(name: string): string {\n const builtin = BUILTIN[name];\n if (builtin) return builtin;\n const mcp = parseMcpToolName(name);\n if (mcp) {\n // A server name often repeats in its tool (\"claude_browser\" + \"browser_batch\").\n return `${words(mcp.tool) || \"Tool\"} · ${words(mcp.server)}`;\n }\n // Codex MCP calls arrive as \"<server>.<tool>\".\n const dotted = /^([\\w-]+)\\.([\\w-]+)$/.exec(name);\n if (dotted?.[1] && dotted[2]) return `${words(dotted[2])} · ${words(dotted[1])}`;\n return words(name) || \"Working…\";\n}\n\nfunction prettyPath(value: string): string {\n const home = value.match(/^\\/(?:Users|home)\\/[^/]+/)?.[0];\n return home ? `~${value.slice(home.length)}` : value;\n}\n\nfunction clip(value: string, max = 90): string {\n const flat = value.replace(/\\s+/g, \" \").trim();\n return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;\n}\n\n/** The key argument, for the card's subtitle. null when there is none worth showing. */\nexport function toolSubtitle(name: string, input: unknown): string | null {\n if (typeof input !== \"object\" || input === null) return typeof input === \"string\" && input ? clip(input) : null;\n const args = input as Record<string, unknown>;\n const pick = (...keys: string[]): string | null => {\n for (const key of keys) {\n const value = args[key];\n if (typeof value === \"string\" && value.trim()) return value;\n }\n return null;\n };\n switch (name) {\n case \"Bash\":\n case \"Shell\": {\n const command = pick(\"command\", \"description\");\n return command ? clip(command) : null;\n }\n case \"Read\":\n case \"Write\":\n case \"Edit\":\n case \"MultiEdit\":\n case \"NotebookEdit\": {\n const file = pick(\"file_path\", \"notebook_path\", \"path\");\n return file ? clip(prettyPath(file)) : null;\n }\n case \"Glob\":\n case \"Grep\":\n return pick(\"pattern\") ? clip(pick(\"pattern\") as string) : null;\n case \"WebFetch\":\n return pick(\"url\") ? clip(pick(\"url\") as string) : null;\n case \"WebSearch\":\n case \"Web search\":\n return pick(\"query\") ? clip(pick(\"query\") as string) : null;\n case \"Task\":\n case \"Agent\":\n return pick(\"description\", \"prompt\") ? clip(pick(\"description\", \"prompt\") as string) : null;\n case \"Edit files\": {\n // The live stream lists `{ path, kind }`; a saved rollout maps path → change.\n const raw = args.changes;\n const paths = Array.isArray(raw)\n ? raw\n .map((c) => (typeof c === \"object\" && c !== null ? (c as { path?: unknown }).path : null))\n .filter((p): p is string => typeof p === \"string\")\n : typeof raw === \"object\" && raw !== null\n ? Object.keys(raw)\n : [];\n return paths.length ? clip(paths.map(prettyPath).join(\", \")) : null;\n }\n default: {\n const first = pick(\"url\", \"query\", \"command\", \"path\", \"file_path\", \"name\", \"description\");\n return first ? clip(first) : null;\n }\n }\n}\n","/**\n * THE CHANGES PANEL — every file this chat's agent wrote, with what changed,\n * read from the conversation itself (see `../changes.ts`).\n */\n\nimport { useMemo, useState, type ReactNode } from \"react\";\n\nimport type { ChatMessage } from \"@ai-matrx/chat\";\nimport { cn } from \"@ai-matrx/design-system\";\n\nimport { changedFiles, lineCounts, type ChangedFile, type FileEdit } from \"../changes\";\nimport { copyText } from \"./chat-menu\";\nimport { prettyPath } from \"./hooks\";\nimport { ChevronDownIcon, CloseIcon, FileIcon } from \"./icons\";\nimport { useToastShow } from \"./toast\";\n\nconst MAX_LINES = 400;\n\n/** A file's path inside the chat's folder; macOS's `/tmp` is `/private/tmp`, so both spellings count. */\nexport function relativeTo(file: string, cwd: string | null): string {\n if (cwd) {\n const base = cwd.replace(/\\/+$/, \"\");\n for (const root of [base, `/private${base}`, base.replace(/^\\/private(?=\\/)/, \"\")]) {\n if (file.startsWith(`${root}/`)) return file.slice(root.length + 1);\n }\n }\n return prettyPath(file);\n}\n\nfunction DiffLines({ edit }: { edit: FileEdit }): ReactNode {\n const lines: { kind: \"add\" | \"del\" | \"hunk\" | \"ctx\"; text: string }[] = [];\n if (edit.diff) {\n for (const line of edit.diff.split(\"\\n\")) {\n if (line.startsWith(\"@@\")) lines.push({ kind: \"hunk\", text: line });\n else if (line.startsWith(\"+\")) lines.push({ kind: \"add\", text: line });\n else if (line.startsWith(\"-\")) lines.push({ kind: \"del\", text: line });\n else if (line !== \"\") lines.push({ kind: \"ctx\", text: line });\n }\n } else {\n if (edit.removed) for (const line of edit.removed.split(\"\\n\")) lines.push({ kind: \"del\", text: `-${line}` });\n if (edit.added) for (const line of edit.added.split(\"\\n\")) lines.push({ kind: \"add\", text: `+${line}` });\n }\n if (lines.length === 0) {\n return (\n <p className=\"text-[12px] text-muted-foreground\">\n {edit.failed ? \"This change failed.\" : \"The agent didn't record the text of this change.\"}\n </p>\n );\n }\n const shown = lines.slice(0, MAX_LINES);\n return (\n <>\n {edit.failed ? <p className=\"mb-1 text-[11.5px] text-destructive\">This change failed and was not applied.</p> : null}\n <pre className={cn(\"cs-diff\", edit.failed && \"opacity-60\")}>\n {shown.map((line, i) => (\n <span key={i} className={cn(\"cs-diff__line\", line.kind !== \"ctx\" && `cs-diff__line--${line.kind}`)}>\n {line.text || \" \"}\n </span>\n ))}\n </pre>\n {lines.length > MAX_LINES ? (\n <p className=\"mt-1 text-[11.5px] text-muted-foreground\">\n Showing the first {MAX_LINES} of {lines.length} lines.\n </p>\n ) : null}\n </>\n );\n}\n\nfunction FileRow({ file, cwd }: { file: ChangedFile; cwd: string | null }): ReactNode {\n const [open, setOpen] = useState(false);\n const show = useToastShow();\n const counts = lineCounts(file);\n const shown = relativeTo(file.path, cwd);\n const kind = { created: \"New\", edited: \"Edited\", deleted: \"Deleted\", moved: \"Moved\" }[file.kind];\n return (\n <li className=\"border-b border-border\">\n <div className=\"flex items-center gap-2 px-4 py-2\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n aria-expanded={open}\n className=\"flex min-w-0 flex-1 items-center gap-2 text-left\"\n >\n <ChevronDownIcon size={13} className={cn(\"shrink-0 transition-transform\", !open && \"-rotate-90\")} />\n <FileIcon size={14} className=\"shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 truncate text-[12.5px] font-medium\" title={file.path}>\n {shown}\n </span>\n </button>\n <span className=\"shrink-0 text-[11px] text-muted-foreground\">{kind}</span>\n <span className=\"shrink-0 font-mono text-[11px]\">\n {counts.added ? <span className=\"cs-count-add\">+{counts.added}</span> : null}{\" \"}\n {counts.removed ? <span className=\"cs-count-del\">−{counts.removed}</span> : null}\n </span>\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => void copyText(file.path, show, \"File path\")}\n aria-label={`Copy the path of ${shown}`}\n title=\"Copy path\"\n >\n <FileIcon size={12} />\n </button>\n </div>\n {open ? (\n <div className=\"space-y-3 px-4 pb-3\">\n {file.edits.map((edit, i) => (\n <DiffLines key={`${edit.toolCallId}-${i}`} edit={edit} />\n ))}\n </div>\n ) : null}\n </li>\n );\n}\n\nexport function useChangedFiles(messages: readonly ChatMessage[]): ChangedFile[] {\n return useMemo(() => changedFiles(messages), [messages]);\n}\n\nexport function ChangesPanel(props: {\n files: ChangedFile[];\n cwd: string | null;\n truncated: boolean;\n onClose: () => void;\n}): ReactNode {\n return (\n <aside className=\"cs-changes\" aria-label=\"Files changed in this chat\">\n <div className=\"flex items-center justify-between border-b border-border px-4 py-3\">\n <div>\n <h2 className=\"text-[13.5px] font-semibold\">Files changed</h2>\n <p className=\"text-[11.5px] text-muted-foreground\">\n {props.files.length === 0\n ? \"Nothing yet\"\n : `${props.files.length} ${props.files.length === 1 ? \"file\" : \"files\"}, from this chat's own record`}\n {props.truncated ? \" · only the part of the chat shown here\" : \"\"}\n </p>\n </div>\n <button type=\"button\" className=\"cs-icon-button\" onClick={props.onClose} aria-label=\"Close files changed\">\n <CloseIcon size={14} />\n </button>\n </div>\n {props.files.length === 0 ? (\n <p className=\"px-4 py-6 text-center text-[12.5px] leading-5 text-muted-foreground\">\n The agent hasn't written any files in this chat yet.\n </p>\n ) : (\n <ul className=\"min-h-0 flex-1 overflow-y-auto\">\n {props.files.map((file) => (\n <FileRow key={file.path} file={file} cwd={props.cwd} />\n ))}\n </ul>\n )}\n </aside>\n );\n}\n","/**\n * WHAT CHANGED — the files a session's agent wrote, read straight from the\n * transcript's own tool calls (no git, no second read of the disk):\n *\n * - Claude Code: `Write`, `Edit`, `MultiEdit`, `NotebookEdit` — their inputs\n * carry the text, so each change has a real before/after.\n * - Codex: a completed `FileChange` item — `changes` is a map of path →\n * `{ type, unified_diff }` in saved rollouts, or a list of `{ path, kind }`\n * in the live stream (no diff there; the list says so).\n *\n * Pure: no Node, no DOM. The screen's Changes panel renders the result.\n */\n\nimport type { ChatMessage } from \"@ai-matrx/chat\";\n\nexport type ChangeKind = \"created\" | \"edited\" | \"deleted\" | \"moved\";\n\n/** One edit to one file, with whatever text the provider recorded. */\nexport interface FileEdit {\n /** Lines removed / added, when the provider recorded them. */\n removed: string | null;\n added: string | null;\n /** A unified diff, when that is what the provider recorded. */\n diff: string | null;\n /** The tool call that made it (for \"show in conversation\"). */\n toolCallId: string;\n failed: boolean;\n}\n\nexport interface ChangedFile {\n path: string;\n kind: ChangeKind;\n edits: FileEdit[];\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction str(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction codexKind(value: unknown): ChangeKind {\n const kind = isObject(value) ? str(value.type) : str(value);\n if (kind === \"add\" || kind === \"create\") return \"created\";\n if (kind === \"delete\") return \"deleted\";\n if (kind === \"move\" || kind === \"rename\") return \"moved\";\n return \"edited\";\n}\n\n/** Every file the transcript's tool calls changed, in first-touched order. */\nexport function changedFiles(messages: readonly ChatMessage[]): ChangedFile[] {\n const byPath = new Map<string, ChangedFile>();\n const add = (path: string, kind: ChangeKind, edit: FileEdit) => {\n const existing = byPath.get(path);\n if (existing) {\n existing.edits.push(edit);\n // A file created in this session stays \"created\" however often it is edited after.\n if (kind === \"deleted\") existing.kind = \"deleted\";\n } else {\n byPath.set(path, { path, kind, edits: [edit] });\n }\n };\n\n for (const message of messages) {\n for (const part of message.parts) {\n if (part.type !== \"tool\") continue;\n const input = part.input;\n if (!isObject(input)) continue;\n const failed = part.state === \"output-error\" || Boolean((part as { errorText?: unknown }).errorText);\n const base = { toolCallId: part.toolCallId, failed };\n switch (part.toolName) {\n case \"Write\": {\n const path = str(input.file_path);\n if (path) add(path, \"created\", { ...base, removed: null, added: str(input.content), diff: null });\n break;\n }\n case \"Edit\": {\n const path = str(input.file_path);\n if (path) {\n add(path, \"edited\", { ...base, removed: str(input.old_string), added: str(input.new_string), diff: null });\n }\n break;\n }\n case \"MultiEdit\": {\n const path = str(input.file_path);\n const edits = Array.isArray(input.edits) ? input.edits : [];\n if (path) {\n for (const edit of edits.filter(isObject)) {\n add(path, \"edited\", { ...base, removed: str(edit.old_string), added: str(edit.new_string), diff: null });\n }\n }\n break;\n }\n case \"NotebookEdit\": {\n const path = str(input.notebook_path);\n if (path) add(path, \"edited\", { ...base, removed: null, added: str(input.new_source), diff: null });\n break;\n }\n case \"Edit files\": {\n const changes = input.changes;\n if (Array.isArray(changes)) {\n for (const change of changes.filter(isObject)) {\n const path = str(change.path);\n if (path) add(path, codexKind(change.kind), { ...base, removed: null, added: null, diff: null });\n }\n } else if (isObject(changes)) {\n for (const [path, change] of Object.entries(changes)) {\n const diff = isObject(change) ? str(change.unified_diff) : null;\n add(path, codexKind(change), { ...base, removed: null, added: null, diff });\n }\n }\n break;\n }\n default:\n break;\n }\n }\n }\n return [...byPath.values()];\n}\n\n/** Lines added and removed across a file's edits, for the list's \"+12 −3\". */\nexport function lineCounts(file: ChangedFile): { added: number; removed: number } {\n let added = 0;\n let removed = 0;\n const count = (text: string | null) => (text ? text.split(\"\\n\").length : 0);\n for (const edit of file.edits) {\n if (edit.failed) continue;\n if (edit.diff) {\n for (const line of edit.diff.split(\"\\n\")) {\n if (line.startsWith(\"+\") && !line.startsWith(\"+++\")) added += 1;\n else if (line.startsWith(\"-\") && !line.startsWith(\"---\")) removed += 1;\n }\n } else {\n added += count(edit.added);\n removed += count(edit.removed);\n }\n }\n return { added, removed };\n}\n","/**\n * THE CHAT MENU — one list of actions for a chat, shown from the row's `…`\n * button, a right-click on the row, and the open chat's header: rename, pin,\n * hide, copy its id or the command that reopens it, open its folder.\n *\n * Every action is present and working, or absent: no id yet → no \"Copy chat\n * ID\"; no folder → no \"Open folder\". A failure is said in a toast.\n */\n\nimport type { ReactNode } from \"react\";\n\nimport {\n ContextMenuItem,\n ContextMenuSeparator,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n} from \"@ai-matrx/design-system\";\n\nimport { formatFileSize } from \"@ai-matrx/kit/format\";\nimport type { OpenTarget } from \"../types\";\nimport { resumeCommand, type ListEntry } from \"./grouping\";\nimport { useCodingSessionsClient } from \"./hooks\";\nimport { CopyIcon, EyeOffIcon, FolderIcon, PencilIcon, PinIcon } from \"./icons\";\nimport { useToastShow } from \"./toast\";\n\nconst OPEN_TARGETS: { target: OpenTarget; label: string }[] = [\n { target: \"finder\", label: \"Finder\" },\n { target: \"vscode\", label: \"VS Code\" },\n { target: \"cursor\", label: \"Cursor\" },\n { target: \"terminal\", label: \"Terminal\" },\n];\n\nexport async function copyText(text: string, show: (text: string) => void, what: string): Promise<void> {\n try {\n await navigator.clipboard.writeText(text);\n show(`${what} copied.`);\n } catch {\n show(`This browser didn't allow copying. Select the text and copy it with your keyboard instead: ${text}`);\n }\n}\n\n/**\n * FULL DOWNLOAD — the chat's complete provider file (every tool input and\n * output) saved from THIS computer. AI Matrx's cloud keeps only text and tool\n * names; the web app falls back to the opt-in cloud backup when the computer\n * that ran the chat cannot answer.\n */\nasync function fullDownload(\n client: ReturnType<typeof useCodingSessionsClient>,\n entry: ListEntry,\n show: (text: string) => void,\n): Promise<void> {\n try {\n const raw = await client.readRawTranscript(entry.provider, entry.providerSessionId as string);\n if (!raw.available) {\n show(raw.reason);\n return;\n }\n const url = URL.createObjectURL(new Blob([raw.content], { type: \"application/x-ndjson\" }));\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = raw.fileName;\n anchor.click();\n setTimeout(() => URL.revokeObjectURL(url), 10_000);\n show(`Downloaded ${raw.fileName} (${formatFileSize(raw.bytes)}).`);\n } catch (error) {\n show(`Full Download failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\nexport function ChatMenuItems(props: {\n entry: ListEntry;\n variant: \"dropdown\" | \"context\";\n onRename: () => void;\n}): ReactNode {\n const client = useCodingSessionsClient();\n const show = useToastShow();\n const { entry } = props;\n const P =\n props.variant === \"dropdown\"\n ? {\n Item: DropdownMenuItem,\n Separator: DropdownMenuSeparator,\n Sub: DropdownMenuSub,\n SubTrigger: DropdownMenuSubTrigger,\n SubContent: DropdownMenuSubContent,\n }\n : {\n Item: ContextMenuItem,\n Separator: ContextMenuSeparator,\n Sub: ContextMenuSub,\n SubTrigger: ContextMenuSubTrigger,\n SubContent: ContextMenuSubContent,\n };\n\n const setPref = (patch: { pinned?: boolean; hidden?: boolean }, done: string) => {\n client.setPreference(entry.key, patch).then(\n () => show(done),\n (error: unknown) => show(`That didn't save: ${error instanceof Error ? error.message : String(error)}`),\n );\n };\n const resume = resumeCommand(entry);\n\n return (\n <>\n <P.Item onSelect={props.onRename}>\n <PencilIcon size={14} />\n Rename\n </P.Item>\n <P.Item onSelect={() => setPref({ pinned: !entry.pinned }, entry.pinned ? \"Unpinned.\" : \"Pinned to the top.\")}>\n <PinIcon size={14} />\n {entry.pinned ? \"Unpin\" : \"Pin to top\"}\n </P.Item>\n <P.Item\n onSelect={() =>\n setPref(\n { hidden: !entry.hidden },\n entry.hidden ? \"Back in the list.\" : \"Hidden from the list. Search still finds it.\",\n )\n }\n >\n <EyeOffIcon size={14} />\n {entry.hidden ? \"Show in the list\" : \"Hide from the list\"}\n </P.Item>\n {entry.providerSessionId || entry.cwd ? <P.Separator /> : null}\n {entry.providerSessionId ? (\n <P.Item onSelect={() => void copyText(entry.providerSessionId as string, show, \"Chat ID\")}>\n <CopyIcon size={14} />\n Copy chat ID\n </P.Item>\n ) : null}\n {resume ? (\n <P.Item onSelect={() => void copyText(resume, show, \"Resume command\")}>\n <CopyIcon size={14} />\n Copy resume command\n </P.Item>\n ) : null}\n {entry.providerSessionId ? (\n <P.Item onSelect={() => void fullDownload(client, entry, show)}>\n <CopyIcon size={14} />\n Full Download\n </P.Item>\n ) : null}\n {entry.cwd ? (\n <P.Item onSelect={() => void copyText(entry.cwd as string, show, \"Folder path\")}>\n <CopyIcon size={14} />\n Copy folder path\n </P.Item>\n ) : null}\n {entry.cwd ? (\n <P.Sub>\n <P.SubTrigger className=\"gap-2\">\n <FolderIcon size={14} />\n Open folder in\n </P.SubTrigger>\n <P.SubContent>\n {OPEN_TARGETS.map(({ target, label }) => (\n <P.Item\n key={target}\n onSelect={() =>\n client.openFolder(entry.cwd as string, target).catch((error: unknown) =>\n show(error instanceof Error ? error.message : String(error)),\n )\n }\n >\n {label}\n </P.Item>\n ))}\n </P.SubContent>\n </P.Sub>\n ) : null}\n </>\n );\n}\n","/**\n * The sidebar's lists, as data: one entry shape for chats driven from here and\n * chats found on disk, the person's renames/pins/hides applied, grouped by\n * date (Today, Yesterday, Previous 7 days, …) or by folder. Pure — tested\n * without a DOM.\n */\n\nimport {\n chatKey,\n type ChatPreference,\n type CodingProvider,\n type CodingSession,\n type DiscoveredSession,\n} from \"../types\";\n\nexport interface ListEntry {\n /** `chatKey()` — where this chat's preference lives. */\n key: string;\n kind: \"session\" | \"discovered\";\n provider: CodingProvider;\n providerSessionId: string | null;\n /** The shown title: the person's rename, else the chat's own. */\n title: string;\n /** The chat's own title (shown under a rename, searched too). */\n originalTitle: string;\n cwd: string | null;\n updatedAt: string;\n pinned: boolean;\n hidden: boolean;\n session: CodingSession | null;\n discovered: DiscoveredSession | null;\n}\n\nexport function sessionEntry(session: CodingSession, prefs: Record<string, ChatPreference>): ListEntry {\n const key = chatKey(session.provider, session.providerSessionId, session.id);\n const pref = prefs[key] ?? prefs[chatKey(session.provider, null, session.id)] ?? {};\n return {\n key,\n kind: \"session\",\n provider: session.provider,\n providerSessionId: session.providerSessionId,\n title: pref.title || session.title,\n originalTitle: session.title,\n cwd: session.cwd,\n updatedAt: session.updatedAt,\n pinned: pref.pinned === true,\n hidden: pref.hidden === true,\n session,\n discovered: null,\n };\n}\n\nexport function discoveredEntry(d: DiscoveredSession, prefs: Record<string, ChatPreference>): ListEntry {\n const key = chatKey(d.provider, d.providerSessionId);\n const pref = prefs[key] ?? {};\n return {\n key,\n kind: \"discovered\",\n provider: d.provider,\n providerSessionId: d.providerSessionId,\n title: pref.title || d.title,\n originalTitle: d.title,\n cwd: d.cwd,\n updatedAt: d.updatedAt,\n pinned: pref.pinned === true,\n hidden: pref.hidden === true,\n session: null,\n discovered: d,\n };\n}\n\nexport interface EntryGroup {\n label: string;\n entries: ListEntry[];\n}\n\nconst DAY = 24 * 60 * 60 * 1000;\n\nfunction startOfDay(ms: number): number {\n const d = new Date(ms);\n d.setHours(0, 0, 0, 0);\n return d.getTime();\n}\n\n/** The date bucket a time falls in, as the Claude and ChatGPT apps name them. */\nexport function dateGroup(iso: string, now: number): string {\n const then = Date.parse(iso);\n if (Number.isNaN(then)) return \"Older\";\n const today = startOfDay(now);\n if (then >= today) return \"Today\";\n if (then >= today - DAY) return \"Yesterday\";\n if (then >= today - 7 * DAY) return \"Previous 7 days\";\n if (then >= today - 30 * DAY) return \"Previous 30 days\";\n const date = new Date(then);\n const thisYear = new Date(now).getFullYear();\n return date.getFullYear() === thisYear\n ? date.toLocaleDateString(undefined, { month: \"long\" })\n : String(date.getFullYear());\n}\n\n/** The last folder name, for a folder group's label. */\nexport function folderLabel(cwd: string | null): string {\n if (!cwd) return \"Unknown folder\";\n const parts = cwd.split(\"/\").filter(Boolean);\n return parts[parts.length - 1] ?? cwd;\n}\n\n/**\n * Group entries, keeping their order (newest first) inside each group. Date\n * groups come in time order; folder groups by their newest chat.\n */\nexport function groupEntries(entries: readonly ListEntry[], mode: \"date\" | \"folder\", now: number): EntryGroup[] {\n const groups = new Map<string, EntryGroup>();\n for (const entry of entries) {\n const id = mode === \"date\" ? dateGroup(entry.updatedAt, now) : (entry.cwd ?? \"\");\n let group = groups.get(id);\n if (!group) {\n group = { label: mode === \"date\" ? id : folderLabel(entry.cwd), entries: [] };\n groups.set(id, group);\n }\n group.entries.push(entry);\n }\n if (mode === \"folder\") {\n // Two folders with the same last name get their parent too.\n const byLabel = new Map<string, number>();\n for (const g of groups.values()) byLabel.set(g.label, (byLabel.get(g.label) ?? 0) + 1);\n for (const [cwd, g] of groups) {\n if ((byLabel.get(g.label) ?? 0) > 1 && cwd) {\n const parts = cwd.split(\"/\").filter(Boolean);\n g.label = parts.slice(-2).join(\"/\");\n }\n }\n }\n return [...groups.values()];\n}\n\n/** Does this entry's title, own title or folder contain the query? */\nexport function matchesQuery(entry: ListEntry, query: string): boolean {\n const q = query.trim().toLowerCase();\n if (!q) return true;\n return (\n entry.title.toLowerCase().includes(q) ||\n entry.originalTitle.toLowerCase().includes(q) ||\n (entry.cwd ?? \"\").toLowerCase().includes(q)\n );\n}\n\n/** Sort key: newest first. */\nexport function byNewest(a: ListEntry, b: ListEntry): number {\n return b.updatedAt.localeCompare(a.updatedAt);\n}\n\n/** The shell command that reopens this chat in its own app. */\nexport function resumeCommand(entry: Pick<ListEntry, \"provider\" | \"providerSessionId\" | \"cwd\">): string | null {\n if (!entry.providerSessionId) return null;\n const cli = entry.provider === \"claude\" ? `claude --resume ${entry.providerSessionId}` : `codex resume ${entry.providerSessionId}`;\n if (!entry.cwd) return cli;\n const quoted = /^[A-Za-z0-9_./~-]+$/.test(entry.cwd) ? entry.cwd : `'${entry.cwd.replace(/'/g, `'\\\\''`)}'`;\n return `cd ${quoted} && ${cli}`;\n}\n","import { createContext, useContext, useEffect, useState, useSyncExternalStore } from \"react\";\n\nimport { formatRelativeTime } from \"@ai-matrx/kit/format\";\nimport type { CodingSessionsClient, CodingSessionsState, SessionTranscript } from \"./client\";\n\nexport const CodingSessionsContext = createContext<CodingSessionsClient | null>(null);\n\nexport function useCodingSessionsClient(): CodingSessionsClient {\n const client = useContext(CodingSessionsContext);\n if (!client) {\n throw new Error(\n \"[@ai-matrx/coding-sessions] Render this inside <CodingSessionsProvider transport={…}> (or <CodingSessionsApp>).\",\n );\n }\n return client;\n}\n\nexport function useCodingSessionsState(): CodingSessionsState {\n const client = useCodingSessionsClient();\n return useSyncExternalStore(client.subscribe, client.getState, client.getState);\n}\n\n/** The open transcript for a session, re-rendering when its load state changes. */\nexport function useSessionTranscript(sessionId: string): SessionTranscript {\n const client = useCodingSessionsClient();\n const transcript = client.transcript(sessionId);\n const [, bump] = useState(0);\n useEffect(() => transcript.thread.subscribe(() => bump((n) => n + 1)), [transcript]);\n return transcript;\n}\n\n/** A clock that ticks once a minute, for \"3 min ago\" labels. */\nexport function useMinuteClock(): number {\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), 60_000);\n return () => clearInterval(timer);\n }, []);\n return now;\n}\n\n/** \"5 minutes ago\" — kit's long relative voice, bound to this app's clock tick. */\nexport function relativeTime(iso: string | null | undefined, now: number): string {\n return iso ? formatRelativeTime(iso, { style: \"long\", now, fallback: \"\" }) : \"\";\n}\n\n/** `/Users/me/code/app` → `~/code/app`; long paths keep their last segments. */\nexport function prettyPath(path: string | null | undefined): string {\n if (!path) return \"\";\n const home = path.match(/^\\/(?:Users|home)\\/[^/]+/)?.[0];\n const short = home ? `~${path.slice(home.length)}` : path;\n if (short.length <= 48) return short;\n const parts = short.split(\"/\");\n return `…/${parts.slice(-3).join(\"/\")}`;\n}\n","/**\n * Package-owned glyphs (C19: inlined SVG, no icon-library dependency).\n * Lucide-style 24×24 strokes, `currentColor`, sized by the caller.\n */\n\nimport type { ReactNode, SVGProps } from \"react\";\n\ntype IconProps = SVGProps<SVGSVGElement> & { size?: number };\n\nfunction Svg({ size = 16, children, ...rest }: IconProps & { children: ReactNode }): ReactNode {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.8}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n {...rest}\n >\n {children}\n </svg>\n );\n}\n\nexport const PlusIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M12 5v14M5 12h14\" />\n </Svg>\n);\n\nexport const StopIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" fill=\"currentColor\" stroke=\"none\" />\n </Svg>\n);\n\nexport const FolderIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M3 7.5A2.5 2.5 0 0 1 5.5 5H9l2 2.5h7.5A2.5 2.5 0 0 1 21 10v7.5a2.5 2.5 0 0 1-2.5 2.5h-13A2.5 2.5 0 0 1 3 17.5z\" />\n </Svg>\n);\n\nexport const CheckIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m5 12.5 4.5 4.5L19 7.5\" />\n </Svg>\n);\n\nexport const AlertIcon = (p: IconProps) => (\n <Svg {...p}>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 7.5v5.5M12 16.5h.01\" />\n </Svg>\n);\n\nexport const RefreshIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M20 11a8 8 0 0 0-14.3-4.9L4 8M4 4v4h4M4 13a8 8 0 0 0 14.3 4.9L20 16M20 20v-4h-4\" />\n </Svg>\n);\n\nexport const HandoffIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M5 12h12M13 7l5 5-5 5\" />\n <path d=\"M5 5v14\" />\n </Svg>\n);\n\nexport const SunIcon = (p: IconProps) => (\n <Svg {...p}>\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 2.5v2M12 19.5v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M2.5 12h2M19.5 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4\" />\n </Svg>\n);\n\nexport const MoonIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5z\" />\n </Svg>\n);\n\nexport const MonitorIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"12\" rx=\"2\" />\n <path d=\"M8.5 20h7M12 16.5V20\" />\n </Svg>\n);\n\nexport const ChatBubbleIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M20 12.5a7.5 7.5 0 0 1-10.9 6.7L4 20.5l1.3-4.6A7.5 7.5 0 1 1 20 12.5z\" />\n </Svg>\n);\n\nexport const SpinnerIcon = ({ size = 16, className }: { size?: number; className?: string }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n className={`cs-spin ${className ?? \"\"}`}\n >\n <circle cx=\"12\" cy=\"12\" r=\"9\" fill=\"none\" stroke=\"currentColor\" strokeOpacity=\"0.2\" strokeWidth=\"2.5\" />\n <path d=\"M21 12a9 9 0 0 0-9-9\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" />\n </svg>\n);\n\n/** A small provider mark: a tinted rounded square with the provider's initial. */\n/** The providers' own marks (Claude's, and OpenAI's for Codex), drawn at 16px by default. Paths: simple-icons (CC0). */\nconst CLAUDE_MARK = \"m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z\";\nconst OPENAI_MARK = \"M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z\";\n\nexport function ProviderMark({ provider, size = 16 }: { provider: \"claude\" | \"codex\"; size?: number }): ReactNode {\n return (\n <svg\n className={`cs-provider-mark cs-provider-mark--${provider}`}\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n data-provider-mark={provider}\n >\n <path d={provider === \"claude\" ? CLAUDE_MARK : OPENAI_MARK} />\n </svg>\n );\n}\n\nexport const SearchIcon = (p: IconProps) => (\n <Svg {...p}>\n <circle cx=\"11\" cy=\"11\" r=\"6.5\" />\n <path d=\"m20 20-4.2-4.2\" />\n </Svg>\n);\n\nexport const MoreIcon = (p: IconProps) => (\n <Svg {...p}>\n <circle cx=\"5.5\" cy=\"12\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"12\" cy=\"12\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"18.5\" cy=\"12\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\" />\n </Svg>\n);\n\nexport const PinIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M9 4h6l-1 5 3 3v2H7v-2l3-3z\" />\n <path d=\"M12 14v6\" />\n </Svg>\n);\n\nexport const EyeOffIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M3 3l18 18\" />\n <path d=\"M10.6 5.1A9.8 9.8 0 0 1 12 5c5 0 8.5 4.5 9.5 7a13 13 0 0 1-2.6 3.9M6.4 6.4C4.3 7.8 2.9 9.9 2.5 12c1 2.5 4.5 7 9.5 7 1.8 0 3.4-.6 4.8-1.4\" />\n <path d=\"M9.9 9.9a3 3 0 0 0 4.2 4.2\" />\n </Svg>\n);\n\nexport const CopyIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"8.5\" y=\"8.5\" width=\"11\" height=\"11\" rx=\"2\" />\n <path d=\"M15.5 8.5V6.5a2 2 0 0 0-2-2h-7a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h2\" />\n </Svg>\n);\n\nexport const PencilIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M4 20h4L19 9a2.8 2.8 0 0 0-4-4L4 16z\" />\n <path d=\"m13.5 6.5 4 4\" />\n </Svg>\n);\n\nexport const SidebarIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"3.5\" y=\"4.5\" width=\"17\" height=\"15\" rx=\"2.5\" />\n <path d=\"M9.5 4.5v15\" />\n </Svg>\n);\n\nexport const ChevronDownIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m6.5 9.5 5.5 5.5 5.5-5.5\" />\n </Svg>\n);\n\nexport const FileIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M14 3.5H7.5a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2V8z\" />\n <path d=\"M14 3.5V8h4.5\" />\n </Svg>\n);\n\nexport const CloseIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M6.5 6.5l11 11M17.5 6.5l-11 11\" />\n </Svg>\n);\n\nexport const KeyboardIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"3\" y=\"6.5\" width=\"18\" height=\"11\" rx=\"2\" />\n <path d=\"M7 10.5h.01M11 10.5h.01M15 10.5h.01M8 14h8\" />\n </Svg>\n);\n\nexport const BellIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M6 16.5V11a6 6 0 1 1 12 0v5.5l1.5 1.5h-15z\" />\n <path d=\"M10 20.5a2 2 0 0 0 4 0\" />\n </Svg>\n);\n","import { createContext, useContext } from \"react\";\n\n/** One short sentence at the bottom of the screen (copied, couldn't open, …). */\nexport const ToastContext = createContext<(text: string) => void>(() => undefined);\n\nexport function useToastShow(): (text: string) => void {\n return useContext(ToastContext);\n}\n","/**\n * MODEL AND EFFORT — one small picker used by New session and by an open\n * chat's header (the next message uses the change). \"Default\" says WHICH\n * model that is and where it comes from: the person's own Claude Code or\n * Codex settings, or the driver's built-in default when they set none.\n */\n\nimport { useState, type ReactNode } from \"react\";\n\nimport { Popover, PopoverContent, PopoverTrigger, cn } from \"@ai-matrx/design-system\";\n\nimport type { ProviderStatus } from \"../types\";\nimport { CheckIcon, ChevronDownIcon } from \"./icons\";\n\nexport interface ModelChoice {\n model: string | null;\n effort: string | null;\n}\n\nexport function defaultModelWords(status: ProviderStatus | null): string {\n const d = status?.defaultModel;\n if (!d) return `${status?.label ?? \"the agent\"}'s own default`;\n return d.source === \"settings\" ? `${d.id}, from your settings` : `${d.id}, the built-in default`;\n}\n\nexport function modelLabel(choice: ModelChoice, status: ProviderStatus | null): string {\n const model = choice.model ?? status?.defaultModel?.id ?? \"Default model\";\n const effort = choice.effort ?? status?.defaultEffort ?? null;\n return effort ? `${model} · ${effort}` : model;\n}\n\nexport function ModelPicker(props: {\n status: ProviderStatus | null;\n value: ModelChoice;\n onChange: (next: ModelChoice) => void;\n /** What the chip sits in: a form field or a quiet header chip. */\n appearance?: \"field\" | \"chip\";\n disabled?: boolean;\n}): ReactNode {\n const [open, setOpen] = useState(false);\n const [custom, setCustom] = useState(\"\");\n const models = props.status?.models ?? [];\n const efforts = props.status?.efforts ?? [];\n const known = props.value.model === null || models.some((m) => m.id === props.value.model);\n\n const pick = (patch: Partial<ModelChoice>) => props.onChange({ ...props.value, ...patch });\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n disabled={props.disabled}\n className={cn(props.appearance === \"field\" ? \"cs-model-field\" : \"cs-chip-button\")}\n aria-label={`Model and effort: ${modelLabel(props.value, props.status)}. Change`}\n title=\"Model and effort\"\n >\n <span className=\"truncate\">{modelLabel(props.value, props.status)}</span>\n <ChevronDownIcon size={12} className=\"shrink-0\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-[300px] p-0\">\n <div className=\"max-h-[320px] overflow-y-auto p-1\" role=\"listbox\" aria-label=\"Model\">\n <p className=\"px-2 pb-1 pt-1.5 text-[11px] font-medium uppercase tracking-[0.05em] text-muted-foreground\">Model</p>\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={props.value.model === null}\n className=\"cs-option\"\n onClick={() => pick({ model: null })}\n >\n <span className=\"min-w-0 flex-1\">\n <span className=\"block text-[13px]\">Default</span>\n <span className=\"block truncate text-[11.5px] text-muted-foreground\">{defaultModelWords(props.status)}</span>\n </span>\n {props.value.model === null ? <CheckIcon size={14} /> : null}\n </button>\n {models.map((m) => (\n <button\n key={m.id}\n type=\"button\"\n role=\"option\"\n aria-selected={props.value.model === m.id}\n className=\"cs-option\"\n onClick={() => pick({ model: m.id })}\n >\n <span className=\"min-w-0 flex-1 truncate text-[13px]\">{m.label}</span>\n {props.value.model === m.id ? <CheckIcon size={14} /> : null}\n </button>\n ))}\n {!known ? (\n <div className=\"cs-option\" aria-selected=\"true\" role=\"option\">\n <span className=\"min-w-0 flex-1 truncate text-[13px]\">{props.value.model}</span>\n <CheckIcon size={14} />\n </div>\n ) : null}\n {/* Not a <form>: this popover can sit inside New session's form, and a\n nested Enter would start the session instead of picking the model. */}\n <div className=\"flex gap-1 px-1 pb-1 pt-1.5\">\n <input\n value={custom}\n onChange={(e) => setCustom(e.target.value)}\n onKeyDown={(e) => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n e.stopPropagation();\n if (custom.trim()) {\n pick({ model: custom.trim() });\n setCustom(\"\");\n }\n }}\n placeholder=\"Another model name…\"\n aria-label=\"Another model name\"\n spellCheck={false}\n className=\"cs-option-input\"\n />\n </div>\n </div>\n {efforts.length > 0 ? (\n <div className=\"border-t border-border p-2\">\n <p className=\"px-1 pb-1.5 text-[11px] font-medium uppercase tracking-[0.05em] text-muted-foreground\">\n Thinking effort\n </p>\n <div className=\"flex flex-wrap gap-1\" role=\"radiogroup\" aria-label=\"Thinking effort\">\n {[null, ...efforts].map((level) => (\n <button\n key={level ?? \"default\"}\n type=\"button\"\n role=\"radio\"\n aria-checked={props.value.effort === level}\n className={cn(\"cs-seg\", props.value.effort === level && \"cs-seg--on\")}\n onClick={() => pick({ effort: level })}\n title={level === null ? `Default${props.status?.defaultEffort ? ` (${props.status.defaultEffort}, from your settings)` : \"\"}` : undefined}\n >\n {level === null ? \"Default\" : level}\n </button>\n ))}\n </div>\n </div>\n ) : null}\n </PopoverContent>\n </Popover>\n );\n}\n","/**\n * AI MATRX AGENTS ON THE SCREEN — the New session agent field and the header\n * chip that says what loaded.\n *\n * The picker is THE platform picker (`AgentListDropdown` over\n * `createAgentCatalog`); its catalogue reads go through the host\n * (`agentCatalogRpc`), so the person's token never reaches this page. The\n * variables form is `deriveRunInputs` — the one derivation every run surface\n * uses. Signed out is a state: one line, and plain sessions work as before.\n */\n\nimport { useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\n\nimport { deriveRunInputs, type RunInputVariable } from \"@ai-matrx/agents\";\nimport {\n createAgentCatalog,\n type AgentCatalog,\n type AgentCatalogClient,\n type AgentCatalogRpcCall,\n type PgResultLike,\n} from \"@ai-matrx/agents/catalog\";\nimport { AgentCatalogProvider, AgentListDropdown } from \"@ai-matrx/agents/catalog/react\";\nimport type { JsonValue } from \"@ai-matrx/agents/portable\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Input,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Textarea,\n TooltipProvider,\n cn,\n} from \"@ai-matrx/design-system\";\n\nimport type {\n AgentAccess,\n AgentCatalogRpcRequest,\n AgentDetails,\n AgentSelection,\n CodingSessionsTransport,\n SessionAgent,\n} from \"../types\";\nimport { ChevronDownIcon } from \"./icons\";\nimport { useToastShow } from \"./toast\";\n\nexport const SIGNED_OUT_AGENTS = \"Sign in to AI Matrx to use your agents\";\nconst LATEST = \"latest\";\n\nfunction bridgedClient(transport: CodingSessionsTransport): AgentCatalogClient {\n const call = (request: AgentCatalogRpcRequest): AgentCatalogRpcCall => {\n const run = (): Promise<PgResultLike> =>\n transport.call(\"agentCatalogRpc\", request).then((result) => ({\n data: result.data,\n error: result.error\n ? {\n message: result.error.message,\n ...(result.error.code ? { code: result.error.code } : {}),\n details: result.error.details ?? null,\n hint: result.error.hint ?? null,\n }\n : null,\n count: result.count ?? null,\n }));\n return {\n then: (onOk, onErr) => run().then(onOk, onErr),\n range: (from, to) => call({ ...request, range: [from, to] }),\n order: (column, options) =>\n call({ ...request, order: { column, ascending: options?.ascending !== false } }),\n };\n };\n return {\n rpc: (fn, args, options) =>\n call({ fn, ...(args ? { args } : {}), ...(options?.count ? { count: options.count } : {}) }),\n };\n}\n\n/** Whether the host is signed in to AI Matrx. Re-asks when the dialog opens. */\nexport function useAgentAccess(transport: CodingSessionsTransport, open: boolean): AgentAccess | null {\n const [access, setAccess] = useState<AgentAccess | null>(null);\n useEffect(() => {\n if (!open) return;\n let alive = true;\n transport\n .call(\"agentAccess\")\n .then((next) => alive && setAccess(next))\n .catch(() => alive && setAccess({ signedIn: false, userId: null, organizationId: null, configured: false }));\n return () => {\n alive = false;\n };\n }, [transport, open]);\n return access;\n}\n\nfunction useCatalog(\n transport: CodingSessionsTransport,\n userId: string | null,\n onError: (message: string) => void,\n): AgentCatalog | null {\n const report = useRef(onError);\n report.current = onError;\n return useMemo(() => {\n if (!userId) return null;\n return createAgentCatalog({\n client: bridgedClient(transport),\n identity: { requireUserId: () => userId, getUserId: () => userId },\n catalogId: `coding-sessions:${userId}`,\n // A failed catalogue read shows at the field, never only in the console.\n errorSink: (event) => {\n console.error(`[coding-sessions] agent catalogue: ${event.code}: ${event.message}`);\n if (event.code === \"list_read_failed\") report.current(\"Couldn't load your agents. Reopen to retry.\");\n },\n });\n }, [transport, userId]);\n}\n\nfunction asRunInputVariables(defs: Record<string, JsonValue>[]): RunInputVariable[] {\n return defs.flatMap((def) => (typeof def.name === \"string\" ? [def as unknown as RunInputVariable] : []));\n}\n\nexport interface AgentFieldProps {\n transport: CodingSessionsTransport;\n open: boolean;\n value: AgentSelection | null;\n onChange: (next: AgentSelection | null) => void;\n /** A missing required variable, by name — shown at its input. */\n missing: string | null;\n /** The picked agent's variables and versions, once loaded (null while none). */\n onDetails?: ((details: AgentDetails | null) => void) | undefined;\n}\n\n/** The New session \"AI Matrx agent\" field: picker, version menu, variables. */\nexport function AgentField(props: AgentFieldProps): ReactNode {\n const access = useAgentAccess(props.transport, props.open);\n const [details, setDetails] = useState<AgentDetails | null>(null);\n const [problem, setProblem] = useState<string | null>(null);\n const catalog = useCatalog(props.transport, access?.signedIn ? access.userId : null, setProblem);\n const agentId = props.value?.agentId ?? null;\n\n useEffect(() => {\n setDetails(null);\n setProblem(null);\n if (!agentId) return;\n let alive = true;\n props.transport\n .call(\"agentDetails\", agentId)\n .then((next) => alive && setDetails(next))\n .catch((error: unknown) => alive && setProblem(error instanceof Error ? error.message : String(error)));\n return () => {\n alive = false;\n };\n }, [agentId, props.transport]);\n\n const { onDetails } = props;\n useEffect(() => {\n onDetails?.(details);\n }, [details, onDetails]);\n\n const inputs = useMemo(() => deriveRunInputs(asRunInputVariables(details?.variables ?? [])), [details]);\n\n if (access === null) return <div className=\"cs-skeleton h-9 rounded-lg\" />;\n if (!access.signedIn || !catalog) {\n return <p className=\"text-[12.5px] text-muted-foreground\">{SIGNED_OUT_AGENTS}</p>;\n }\n\n const setVariable = (name: string, value: string) => {\n if (!props.value) return;\n props.onChange({ ...props.value, variables: { ...(props.value.variables ?? {}), [name]: value } });\n };\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n {/* The picker's trigger carries tooltips; this page has no app-wide provider. */}\n <TooltipProvider>\n <AgentCatalogProvider catalog={catalog}>\n <AgentListDropdown\n consumerId=\"coding-sessions-new-session\"\n activeAgentId={agentId}\n label={details?.name ?? (agentId ? \"Loading…\" : \"None\")}\n onSelect={(id) => props.onChange({ agentId: id, versionId: null, variables: {} })}\n />\n </AgentCatalogProvider>\n </TooltipProvider>\n {agentId ? (\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => props.onChange(null)}>\n Remove\n </Button>\n ) : null}\n </div>\n\n {problem ? <p className=\"text-[12px] text-destructive\">{problem}</p> : null}\n\n {details && props.value ? (\n <>\n <div className=\"flex items-center gap-2\">\n <span className=\"w-[72px] shrink-0 text-[12px] text-muted-foreground\">Version</span>\n <Select\n value={props.value.versionId ?? LATEST}\n onValueChange={(next) =>\n props.value && props.onChange({ ...props.value, versionId: next === LATEST ? null : next })\n }\n >\n <SelectTrigger className=\"h-8 w-[200px] text-[12.5px]\" aria-label=\"Agent version\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={LATEST}>\n {details.latestVersionNumber !== null ? `Latest (v${details.latestVersionNumber})` : \"Latest\"}\n </SelectItem>\n {details.versions.map((v) => (\n <SelectItem key={v.id} value={v.id}>\n v{v.versionNumber}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {inputs.map((input) => {\n const raw = props.value?.variables?.[input.name];\n const value = typeof raw === \"string\" ? raw : \"\";\n const id = `cs-agent-var-${input.name}`;\n const invalid = props.missing === input.name;\n return (\n <div key={input.name} className=\"space-y-1\">\n <label htmlFor={id} className=\"text-[12px] font-medium\">\n {input.label}\n {input.required ? <span className=\"text-muted-foreground\"> · required</span> : null}\n </label>\n {input.options && input.options.length > 0 ? (\n <Select value={value} onValueChange={(next) => setVariable(input.name, next)}>\n <SelectTrigger id={id} className=\"h-8 text-[12.5px]\" aria-invalid={invalid || undefined}>\n <SelectValue placeholder=\"Choose…\" />\n </SelectTrigger>\n <SelectContent>\n {input.options.map((option) => (\n <SelectItem key={option} value={option}>\n {option}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : input.variable.customComponent?.type === \"textarea\" ? (\n <Textarea\n id={id}\n rows={2}\n value={value}\n onChange={(e) => setVariable(input.name, e.target.value)}\n placeholder={input.hint ?? \"\"}\n aria-invalid={invalid || undefined}\n />\n ) : (\n <Input\n id={id}\n value={value}\n onChange={(e) => setVariable(input.name, e.target.value)}\n placeholder={input.hint ?? \"\"}\n aria-invalid={invalid || undefined}\n />\n )}\n {invalid ? <p className=\"text-[12px] text-destructive\">Fill this in to use the agent</p> : null}\n </div>\n );\n })}\n </>\n ) : null}\n </div>\n );\n}\n\n/** The first required variable the selection leaves empty, or null. */\nexport function missingRequiredVariable(details: AgentDetails | null, selection: AgentSelection | null): string | null {\n if (!details || !selection) return null;\n for (const input of deriveRunInputs(asRunInputVariables(details.variables))) {\n if (!input.required) continue;\n const value = selection.variables?.[input.name];\n if (typeof value !== \"string\" || !value.trim()) return input.name;\n }\n return null;\n}\n\nconst PART_LABEL: Record<SessionAgent[\"loaded\"][number][\"part\"], string> = {\n instructions: \"Instructions\",\n skills: \"Skills\",\n tools: \"Tools\",\n};\n\n/** `Code Reviewer v7 · Instructions ✓ · Skills 3/3 · Tools 5/6` — the trigger's words. */\nexport function agentChipText(agent: SessionAgent): string {\n const parts = agent.loaded.map((part) =>\n part.part === \"instructions\"\n ? `${PART_LABEL.instructions} ${part.loaded === 1 ? \"✓\" : \"—\"}`\n : `${PART_LABEL[part.part]} ${part.loaded}/${part.total}`,\n );\n return `${agent.name}${agent.versionNumber !== null ? ` v${agent.versionNumber}` : \"\"} · ${parts.join(\" · \")}`;\n}\n\n/**\n * The header's agent control: what loaded (every skill and tool the agent\n * carries, by name — the agent's own resolved set), what did not and why, and\n * the actions: update to the latest version, change the agent, remove it.\n */\nexport function AgentMenu(props: {\n transport: CodingSessionsTransport;\n sessionId: string;\n agent: SessionAgent | null;\n onChange: () => void;\n}): ReactNode {\n const { agent } = props;\n const show = useToastShow();\n const [open, setOpen] = useState(false);\n const [choosing, setChoosing] = useState(false);\n const [latest, setLatest] = useState<{ id: string; number: number } | null>(null);\n const [access, setAccess] = useState<AgentAccess | null>(null);\n\n useEffect(() => {\n if (!open) return;\n let alive = true;\n void props.transport.call(\"agentAccess\").then((next) => alive && setAccess(next)).catch(() => undefined);\n if (agent) {\n props.transport\n .call(\"agentDetails\", agent.agentId)\n .then((d) => {\n if (alive && d.latestVersionId && d.latestVersionNumber !== null) setLatest({ id: d.latestVersionId, number: d.latestVersionNumber });\n })\n .catch(() => undefined);\n }\n return () => {\n alive = false;\n };\n }, [open, agent, props.transport]);\n\n const apply = async (selection: AgentSelection | null, done: string) => {\n try {\n await props.transport.call(\"setAgent\", props.sessionId, selection);\n show(done);\n props.onChange();\n } catch (error) {\n show(`That didn't change: ${error instanceof Error ? error.message : String(error)}`);\n }\n };\n\n const behind = agent && latest && agent.versionNumber !== null && latest.number > agent.versionNumber ? latest : null;\n const complete = agent ? agent.loaded.every((part) => part.loaded === part.total) : true;\n const signedIn = access?.signedIn ?? false;\n\n return (\n <>\n <DropdownMenu open={open} onOpenChange={setOpen}>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className={cn(\"cs-agent-chip\", agent ? \"cs-agent-chip--set\" : \"cs-agent-chip--none\", !complete && \"cs-agent-chip--partial\")}\n data-testid=\"cs-agent-chip\"\n aria-label={agent ? `AI Matrx agent: ${agent.name}` : \"Add an AI Matrx agent\"}\n >\n {agent ? agentChipText(agent) : \"No agent\"}\n {behind ? <span className=\"cs-agent-chip-dot\" aria-label=\"Update available\" /> : null}\n <ChevronDownIcon size={12} className=\"ml-1 inline shrink-0\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-[320px]\">\n {agent ? (\n <>\n <DropdownMenuLabel className=\"truncate\">\n {agent.name}\n {agent.versionNumber !== null ? ` · v${agent.versionNumber}` : \"\"}\n </DropdownMenuLabel>\n <div className=\"cs-agent-parts\">\n {agent.blockDue ? <p className=\"text-[12px] text-muted-foreground\">Sent with your next message</p> : null}\n <AgentPartList title=\"Skills\" items={agent.skills ?? []} />\n <AgentPartList title=\"Tools\" items={agent.tools ?? []} />\n {agent.unavailable.length > 0 ? (\n <AgentPartList\n title=\"Not loaded\"\n items={agent.unavailable.map((u) => `${u.name} — ${u.reason}`)}\n />\n ) : null}\n </div>\n <DropdownMenuSeparator />\n </>\n ) : null}\n {signedIn ? (\n <>\n {behind && agent ? (\n <DropdownMenuItem\n onSelect={() =>\n void apply(\n { agentId: agent.agentId, versionId: behind.id, variables: agent.variables ?? {} },\n `The next message uses ${agent.name} v${behind.number}.`,\n )\n }\n >\n Update to v{behind.number}\n </DropdownMenuItem>\n ) : null}\n <DropdownMenuItem onSelect={() => setChoosing(true)}>{agent ? \"Change agent…\" : \"Choose agent…\"}</DropdownMenuItem>\n {agent ? (\n <DropdownMenuItem onSelect={() => void apply(null, \"The next message runs without an agent.\")}>\n Remove agent\n </DropdownMenuItem>\n ) : null}\n </>\n ) : access ? (\n <p className=\"px-2 py-1.5 text-[12px] text-muted-foreground\">{SIGNED_OUT_AGENTS}</p>\n ) : null}\n </DropdownMenuContent>\n </DropdownMenu>\n <ChooseAgentDialog\n transport={props.transport}\n open={choosing}\n onOpenChange={setChoosing}\n title={agent ? \"Change agent\" : \"Choose an agent\"}\n action=\"Use this agent\"\n onConfirm={(selection) => apply(selection, \"The next message uses the new agent.\")}\n />\n </>\n );\n}\n\nfunction AgentPartList({ title, items }: { title: string; items: string[] }): ReactNode {\n return (\n <div>\n <p className=\"text-[11.5px] font-medium text-muted-foreground\">\n {title} · {items.length}\n </p>\n {items.length > 0 ? (\n <ul className=\"cs-agent-part-list\">\n {items.map((item) => (\n <li key={item} className=\"truncate\" title={item}>\n {item}\n </li>\n ))}\n </ul>\n ) : null}\n </div>\n );\n}\n\n/** Pick an agent (and its version and values) outside New session: a switch, a takeover. */\nexport function ChooseAgentDialog(props: {\n transport: CodingSessionsTransport;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n title: string;\n action: string;\n onConfirm: (selection: AgentSelection) => Promise<void>;\n}): ReactNode {\n const [value, setValue] = useState<AgentSelection | null>(null);\n const [details, setDetails] = useState<AgentDetails | null>(null);\n const [missing, setMissing] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n\n useEffect(() => {\n if (props.open) {\n setValue(null);\n setMissing(null);\n }\n }, [props.open]);\n\n const confirm = async () => {\n if (!value) return;\n const gap = missingRequiredVariable(details, value);\n setMissing(gap);\n if (gap) return;\n setBusy(true);\n try {\n await props.onConfirm(value);\n props.onOpenChange(false);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Dialog open={props.open} onOpenChange={props.onOpenChange}>\n <DialogContent className=\"max-w-[480px]\">\n <DialogHeader>\n <DialogTitle>{props.title}</DialogTitle>\n </DialogHeader>\n <AgentField\n transport={props.transport}\n open={props.open}\n value={value}\n onChange={(next) => {\n setValue(next);\n setMissing(null);\n }}\n missing={missing}\n onDetails={setDetails}\n />\n <DialogFooter>\n <Button type=\"button\" variant=\"ghost\" onClick={() => props.onOpenChange(false)}>\n Cancel\n </Button>\n {/* Absent until there is something to use — never a dead button. */}\n {value ? (\n <Button type=\"button\" disabled={busy} onClick={() => void confirm()}>\n {props.action}\n </Button>\n ) : null}\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n","/**\n * THE SIDEBAR — search, then Pinned · Running · Recent · Your other chats,\n * grouped by date or by folder, each row renameable, pinnable and hideable\n * from its `…` menu or a right-click.\n *\n * A row's title uses the full width: the hover actions take room only while\n * they are showing (an always-reserved invisible button cut every title short).\n * Search is two-speed: titles and folders filter instantly; what was SAID is\n * searched on this computer's files, newest first, and the list says exactly\n * how many chats it read.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\n\nimport {\n Button,\n ContextMenu,\n ContextMenuContent,\n ContextMenuTrigger,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n cn,\n} from \"@ai-matrx/design-system\";\n\nimport { PROVIDER_LABEL, chatKey, isTerminalRunStatus, type ChatSearchHit, type ChatSearchResult, type DiscoveredSession } from \"../types\";\nimport { ChatMenuItems } from \"./chat-menu\";\nimport {\n byNewest,\n discoveredEntry,\n groupEntries,\n matchesQuery,\n sessionEntry,\n type ListEntry,\n} from \"./grouping\";\nimport { prettyPath, relativeTime, useCodingSessionsClient, useCodingSessionsState, useMinuteClock } from \"./hooks\";\nimport {\n CloseIcon,\n MoreIcon,\n PinIcon,\n PlusIcon,\n ProviderMark,\n RefreshIcon,\n SearchIcon,\n SidebarIcon,\n SpinnerIcon,\n} from \"./icons\";\nimport { useToastShow } from \"./toast\";\n\nexport type Selection =\n | { kind: \"none\" }\n | { kind: \"session\"; id: string }\n | { kind: \"discovered\"; provider: \"claude\" | \"codex\"; id: string };\n\ntype GroupMode = \"date\" | \"folder\";\n\nfunction readLocal<T extends string>(key: string, allowed: readonly T[], fallback: T): T {\n try {\n const value = localStorage.getItem(key);\n return (allowed as readonly string[]).includes(value ?? \"\") ? (value as T) : fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction writeLocal(key: string, value: string): void {\n try {\n localStorage.setItem(key, value);\n } catch {\n /* a private window keeps it for this visit only */\n }\n}\n\n/* ------------------------------------------------------------------------ */\n/* Row */\n/* ------------------------------------------------------------------------ */\n\nfunction SectionLabel({ children, action }: { children: ReactNode; action?: ReactNode }): ReactNode {\n return (\n <div data-cs-section-label className=\"flex h-8 items-center justify-between px-3 pt-3\">\n <span className=\"text-[12px] font-medium text-muted-foreground\">{children}</span>\n {action}\n </div>\n );\n}\n\nfunction GroupLabel({ children }: { children: ReactNode }): ReactNode {\n return <div className=\"truncate px-4 pb-0.5 pt-2.5 text-[12px] font-medium text-muted-foreground\">{children}</div>;\n}\n\nfunction RenameInput(props: { initial: string; onDone: (title: string | null) => void }): ReactNode {\n const [value, setValue] = useState(props.initial);\n const done = useRef(false);\n const finish = (title: string | null) => {\n if (done.current) return;\n done.current = true;\n props.onDone(title);\n };\n return (\n <input\n autoFocus\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onFocus={(e) => e.currentTarget.select()}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") finish(value);\n if (e.key === \"Escape\") finish(null);\n }}\n onBlur={() => finish(value)}\n aria-label=\"New name for this chat\"\n className=\"cs-rename-input\"\n />\n );\n}\n\n/** The page's own address for an entry (the same hash the list writes when it is picked). */\nfunction entryTarget(entry: ListEntry): string {\n if (entry.kind === \"session\" && entry.session) return `#s/${entry.session.id}`;\n if (entry.providerSessionId) return `#d/${entry.provider}/${entry.providerSessionId}`;\n return \"\";\n}\n\nfunction Row(props: {\n entry: ListEntry;\n active: boolean;\n onSelect: () => void;\n meta: ReactNode;\n live?: boolean;\n snippet?: ReactNode;\n takeover?: ReactNode;\n}): ReactNode {\n const client = useCodingSessionsClient();\n const show = useToastShow();\n const [renaming, setRenaming] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const { entry } = props;\n\n const rename = (title: string | null) => {\n setRenaming(false);\n if (title === null || title.trim() === entry.title) return;\n // Empty, or back to its own title, clears the rename.\n const next = title.trim() === \"\" || title.trim() === entry.originalTitle ? null : title;\n client.setPreference(entry.key, { title: next }).catch((error: unknown) =>\n show(`The new name didn't save: ${error instanceof Error ? error.message : String(error)}`),\n );\n };\n\n return (\n <ContextMenu>\n <ContextMenuTrigger asChild>\n <div\n className={cn(\"cs-row group\", props.active && \"cs-row--active\", menuOpen && \"cs-row--menu\")}\n data-hidden={entry.hidden || undefined}\n // A host that shows this list in its own chrome (Matrx 2) reads rows by these.\n data-cs-row={entry.key}\n data-cs-target={entryTarget(entry)}\n data-cs-provider={entry.provider}\n data-cs-title={entry.title}\n data-cs-live={props.live ? \"true\" : undefined}\n data-cs-active={props.active ? \"true\" : undefined}\n >\n <button\n type=\"button\"\n onClick={props.onSelect}\n className=\"cs-row__hit\"\n aria-current={props.active ? \"true\" : undefined}\n aria-label={entry.title}\n title={entry.title !== entry.originalTitle ? `${entry.title}\\n(${entry.originalTitle})` : entry.title}\n />\n <span className=\"pointer-events-none mt-0.5 shrink-0\">\n {props.live ? <SpinnerIcon size={16} className=\"text-primary\" /> : <ProviderMark provider={entry.provider} size={16} />}\n </span>\n <span className=\"cs-row__body\">\n {renaming ? (\n <span className=\"pointer-events-auto relative z-10 block\">\n <RenameInput initial={entry.title} onDone={rename} />\n </span>\n ) : (\n <span className=\"flex items-center gap-1\">\n <span className=\"min-w-0 truncate text-[13px] font-medium leading-5\">{entry.title}</span>\n {entry.pinned ? <PinIcon size={11} className=\"shrink-0 text-muted-foreground\" aria-label=\"Pinned\" /> : null}\n </span>\n )}\n <span className=\"block truncate text-[11.5px] leading-4 text-muted-foreground\">{props.meta}</span>\n {props.snippet ? <span className=\"cs-row__snippet\">{props.snippet}</span> : null}\n </span>\n {renaming ? null : (\n <span className=\"cs-row__actions\">\n {props.takeover}\n <DropdownMenu open={menuOpen} onOpenChange={setMenuOpen}>\n <DropdownMenuTrigger asChild>\n <button type=\"button\" className=\"cs-icon-button\" aria-label={`More for ${entry.title}`} title=\"More\">\n <MoreIcon size={15} />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-60\" onCloseAutoFocus={(e) => e.preventDefault()}>\n <ChatMenuItems entry={entry} variant=\"dropdown\" onRename={() => setRenaming(true)} />\n </DropdownMenuContent>\n </DropdownMenu>\n </span>\n )}\n </div>\n </ContextMenuTrigger>\n <ContextMenuContent className=\"w-60\" onCloseAutoFocus={(e) => e.preventDefault()}>\n <ChatMenuItems entry={entry} variant=\"context\" onRename={() => setRenaming(true)} />\n </ContextMenuContent>\n </ContextMenu>\n );\n}\n\nfunction SidebarSkeleton(): ReactNode {\n return (\n <div className=\"space-y-1.5 px-3 py-2\" aria-hidden=\"true\">\n {[0, 1, 2].map((i) => (\n <div key={i} className=\"cs-skeleton h-9 rounded-lg\" />\n ))}\n </div>\n );\n}\n\n/** The query's words, marked where they appear in `text`. */\nexport function Highlight({ text, query }: { text: string; query: string }): ReactNode {\n const q = query.trim().toLowerCase();\n if (!q) return text;\n const at = text.toLowerCase().indexOf(q);\n if (at < 0) return text;\n return (\n <>\n {text.slice(0, at)}\n <mark className=\"cs-mark\">{text.slice(at, at + q.length)}</mark>\n {text.slice(at + q.length)}\n </>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* Search */\n/* ------------------------------------------------------------------------ */\n\ninterface SearchState {\n query: string;\n loading: boolean;\n error: string | null;\n hits: ChatSearchHit[];\n scanned: number;\n total: number;\n nextCursor: number | null;\n}\n\nconst EMPTY_SEARCH: SearchState = {\n query: \"\",\n loading: false,\n error: null,\n hits: [],\n scanned: 0,\n total: 0,\n nextCursor: null,\n};\n\nfunction useContentSearch(query: string): [SearchState, () => void] {\n const client = useCodingSessionsClient();\n const [state, setState] = useState<SearchState>(EMPTY_SEARCH);\n const latest = useRef(query);\n latest.current = query;\n\n const run = useCallback(\n async (q: string, cursor: number, append: boolean) => {\n setState((s) => ({ ...(append ? s : EMPTY_SEARCH), query: q, loading: true, error: null }));\n try {\n const result: ChatSearchResult = await client.search(q, cursor);\n if (latest.current.trim() !== q) return;\n setState((s) => ({\n query: q,\n loading: false,\n error: null,\n hits: append ? [...s.hits, ...result.hits] : result.hits,\n scanned: (append ? s.scanned : cursor) + result.scanned,\n total: result.total,\n nextCursor: result.nextCursor,\n }));\n } catch (error) {\n if (latest.current.trim() !== q) return;\n setState((s) => ({ ...s, loading: false, error: error instanceof Error ? error.message : String(error) }));\n }\n },\n [client],\n );\n\n useEffect(() => {\n const q = query.trim();\n if (q.length < 2) {\n setState(EMPTY_SEARCH);\n return;\n }\n const timer = setTimeout(() => void run(q, 0, false), 350);\n return () => clearTimeout(timer);\n }, [query, run]);\n\n const more = useCallback(() => {\n if (state.nextCursor !== null && !state.loading) void run(state.query, state.nextCursor, true);\n }, [run, state.nextCursor, state.loading, state.query]);\n\n return [state, more];\n}\n\nfunction hitToDiscovered(hit: ChatSearchHit): DiscoveredSession {\n return {\n provider: hit.provider,\n providerSessionId: hit.providerSessionId,\n cwd: hit.cwd,\n title: hit.title,\n updatedAt: hit.updatedAt,\n source: null,\n activeElsewhere: null,\n };\n}\n\n/* ------------------------------------------------------------------------ */\n/* Sidebar */\n/* ------------------------------------------------------------------------ */\n\nexport interface SidebarHandle {\n focusSearch: () => void;\n}\n\nexport function Sidebar(props: {\n selection: Selection;\n select: (selection: Selection) => void;\n onNew: () => void;\n onCollapse: () => void;\n width: number;\n searchRef: React.RefObject<HTMLInputElement | null>;\n /** A chat opened from search that is older than the listed ones. */\n onFound: (found: DiscoveredSession) => void;\n footer: ReactNode;\n}): ReactNode {\n const client = useCodingSessionsClient();\n const state = useCodingSessionsState();\n const now = useMinuteClock();\n const [query, setQuery] = useState(\"\");\n const [search, searchMore] = useContentSearch(query);\n const [groupMode, setGroupMode] = useState<GroupMode>(() => readLocal(\"coding-sessions.group\", [\"date\", \"folder\"], \"date\"));\n const [showHidden, setShowHidden] = useState(false);\n const [takingOver, setTakingOver] = useState<string | null>(null);\n const [takeoverError, setTakeoverError] = useState<{ id: string; message: string } | null>(null);\n\n const prefs = state.preferences;\n const sessions = state.sessions.data;\n const isLive = (id: string) => {\n const run = state.runs[id];\n return run !== undefined && !isTerminalRunStatus(run.status);\n };\n\n const { ours, others, hiddenCount } = useMemo(() => {\n const oursList = sessions.map((s) => sessionEntry(s, prefs));\n const known = new Set(sessions.map((s) => s.providerSessionId).filter(Boolean));\n const othersList = state.discovered.data\n .filter((d) => !known.has(d.providerSessionId))\n .map((d) => discoveredEntry(d, prefs));\n const hidden = [...oursList, ...othersList].filter((e) => e.hidden).length;\n return { ours: oursList, others: othersList, hiddenCount: hidden };\n }, [sessions, state.discovered.data, prefs]);\n\n const visible = (e: ListEntry) => showHidden || !e.hidden;\n const pinned = [...ours, ...others].filter((e) => e.pinned && visible(e)).sort(byNewest);\n const running = ours.filter((e) => !e.pinned && e.session && isLive(e.session.id) && visible(e));\n const recent = ours.filter((e) => !e.pinned && !(e.session && isLive(e.session.id)) && visible(e));\n const otherList = others.filter((e) => !e.pinned && visible(e));\n\n const setMode = (mode: GroupMode) => {\n setGroupMode(mode);\n writeLocal(\"coding-sessions.group\", mode);\n };\n\n const selectEntry = (entry: ListEntry) => {\n if (entry.session) props.select({ kind: \"session\", id: entry.session.id });\n else if (entry.providerSessionId) props.select({ kind: \"discovered\", provider: entry.provider, id: entry.providerSessionId });\n };\n\n const isActive = (entry: ListEntry) =>\n entry.session\n ? props.selection.kind === \"session\" && props.selection.id === entry.session.id\n : props.selection.kind === \"discovered\" && props.selection.id === entry.providerSessionId;\n\n const takeover = async (d: DiscoveredSession) => {\n setTakingOver(d.providerSessionId);\n setTakeoverError(null);\n try {\n const taken = await client.takeover(d);\n props.select({ kind: \"session\", id: taken.id });\n } catch (error) {\n setTakeoverError({ id: d.providerSessionId, message: error instanceof Error ? error.message : String(error) });\n } finally {\n setTakingOver(null);\n }\n };\n\n const renderEntry = (entry: ListEntry, extra?: { snippet?: ReactNode; query?: string }) => {\n const live = entry.session ? isLive(entry.session.id) : false;\n const run = entry.session ? state.runs[entry.session.id] : undefined;\n const d = entry.discovered;\n let meta: ReactNode;\n if (live) meta = `${PROVIDER_LABEL[entry.provider]} is working…`;\n else if (d?.activeElsewhere)\n meta = (\n <span className=\"cs-live-elsewhere\">\n <span className=\"cs-live-dot\" aria-hidden=\"true\" />\n Running in {PROVIDER_LABEL[entry.provider]}\n </span>\n );\n else {\n const status = run ? (run.status === \"failed\" ? \"Failed · \" : run.status === \"stopped\" ? \"Stopped · \" : \"\") : \"\";\n const where = entry.cwd ? prettyPath(entry.cwd) : \"unknown folder\";\n meta = `${status}${entry.kind === \"discovered\" ? `${PROVIDER_LABEL[entry.provider]} · ` : \"\"}${\n groupMode === \"folder\" && !extra ? \"\" : `${where} · `\n }${relativeTime(entry.updatedAt, now)}`;\n }\n return (\n <div key={entry.key}>\n <Row\n entry={entry}\n active={isActive(entry)}\n onSelect={() => selectEntry(entry)}\n live={live}\n meta={meta}\n snippet={extra?.snippet}\n takeover={\n d?.cwd ? (\n <button\n type=\"button\"\n className=\"cs-takeover-chip\"\n // A chat live elsewhere opens its preview, where the warning\n // and the confirm live — never a one-click takeover.\n onClick={() => (d.activeElsewhere ? selectEntry(entry) : void takeover(d))}\n title={d.activeElsewhere ? d.activeElsewhere.message : \"Continue this chat here\"}\n disabled={takingOver === d.providerSessionId}\n >\n {takingOver === d.providerSessionId ? <SpinnerIcon size={11} /> : null}\n Take over\n </button>\n ) : null\n }\n />\n {takeoverError && d && takeoverError.id === d.providerSessionId ? (\n <p className=\"mx-4 mb-1 text-[11.5px] text-destructive\">{takeoverError.message}</p>\n ) : null}\n </div>\n );\n };\n\n const renderGroups = (entries: ListEntry[]) =>\n groupEntries(entries, groupMode, now).map((group) => (\n <div key={group.label} role=\"group\" aria-label={group.label}>\n <GroupLabel>{group.label}</GroupLabel>\n {group.entries.map((e) => renderEntry(e))}\n </div>\n ));\n\n /* --- search mode ------------------------------------------------------ */\n const searching = query.trim().length > 0;\n const titleMatches = searching\n ? [...ours, ...others].filter((e) => matchesQuery(e, query)).sort(byNewest)\n : [];\n const titleKeys = new Set(titleMatches.map((e) => e.key));\n const allByKey = new Map([...ours, ...others].map((e) => [e.key, e] as const));\n const contentHits = search.hits.filter((h) => !titleKeys.has(chatKey(h.provider, h.providerSessionId)));\n\n const openHit = (hit: ChatSearchHit) => {\n const known = allByKey.get(chatKey(hit.provider, hit.providerSessionId));\n if (known) {\n selectEntry(known);\n return;\n }\n props.onFound(hitToDiscovered(hit));\n props.select({ kind: \"discovered\", provider: hit.provider, id: hit.providerSessionId });\n };\n\n const searchBody = (\n <>\n <SectionLabel>Chats</SectionLabel>\n {titleMatches.length === 0 ? (\n <p className=\"px-4 py-1 text-[12px] text-muted-foreground\">No listed chat has that in its name or folder.</p>\n ) : (\n titleMatches.map((e) => renderEntry(e, { query }))\n )}\n <SectionLabel>In conversations</SectionLabel>\n {query.trim().length < 2 ? (\n <p className=\"px-4 py-1 text-[12px] text-muted-foreground\">Type at least two letters to search what was said.</p>\n ) : (\n <>\n {contentHits.map((hit) => {\n const known = allByKey.get(chatKey(hit.provider, hit.providerSessionId));\n const entry = known ?? discoveredEntry(hitToDiscovered(hit), prefs);\n return (\n <div key={`hit:${entry.key}`} onClickCapture={known ? undefined : () => props.onFound(hitToDiscovered(hit))}>\n {renderEntry(entry, {\n query,\n snippet: hit.snippet ? <Highlight text={hit.snippet} query={query} /> : undefined,\n })}\n </div>\n );\n })}\n <div className=\"px-4 py-2 text-[11.5px] leading-4 text-muted-foreground\" role=\"status\" aria-live=\"polite\">\n {search.error ? (\n <span className=\"text-destructive\">Search stopped: {search.error}</span>\n ) : search.loading ? (\n <span className=\"inline-flex items-center gap-1.5\">\n <SpinnerIcon size={12} /> Searching your chats…\n </span>\n ) : search.query ? (\n <>\n {contentHits.length === 0 && search.hits.length === 0 ? \"Nothing found. \" : null}\n {search.nextCursor === null\n ? `Searched all ${search.total.toLocaleString()} chats on this computer.`\n : `Searched the ${search.scanned.toLocaleString()} most recent of ${search.total.toLocaleString()} chats.`}\n {search.nextCursor !== null ? (\n <button type=\"button\" className=\"cs-link ml-1\" onClick={searchMore}>\n Search older chats\n </button>\n ) : null}\n </>\n ) : null}\n </div>\n </>\n )}\n </>\n );\n\n /* --- list mode --------------------------------------------------------- */\n const listBody = (\n <>\n {pinned.length > 0 ? (\n <>\n <SectionLabel>Pinned</SectionLabel>\n {pinned.map((e) => renderEntry(e))}\n </>\n ) : null}\n\n {running.length > 0 ? (\n <>\n <SectionLabel>Running</SectionLabel>\n {running.map((e) => renderEntry(e))}\n </>\n ) : null}\n\n <SectionLabel>Recent</SectionLabel>\n {state.sessions.loading && state.sessions.loadedAt === null ? (\n <SidebarSkeleton />\n ) : state.sessions.error ? (\n <p className=\"px-4 py-1 text-[12px] text-destructive\">{state.sessions.error}</p>\n ) : recent.length === 0 ? (\n running.length === 0 ? (\n <p className=\"px-4 py-1 text-[12px] leading-5 text-muted-foreground\">\n Sessions you start or take over here will appear here.\n </p>\n ) : null\n ) : (\n recent.map((e) => renderEntry(e))\n )}\n\n <SectionLabel\n action={\n <span className=\"flex items-center gap-0.5\">\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button type=\"button\" className=\"cs-icon-button cs-icon-button--text\" aria-label=\"How to list your other chats\">\n {groupMode === \"date\" ? \"By date\" : \"By folder\"}\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-52\">\n <DropdownMenuLabel>Group your other chats</DropdownMenuLabel>\n <DropdownMenuRadioGroup value={groupMode} onValueChange={(v) => setMode(v as GroupMode)}>\n <DropdownMenuRadioItem value=\"date\">By date</DropdownMenuRadioItem>\n <DropdownMenuRadioItem value=\"folder\">By folder</DropdownMenuRadioItem>\n </DropdownMenuRadioGroup>\n <DropdownMenuSeparator />\n <DropdownMenuItem onSelect={() => setShowHidden((v) => !v)}>\n {showHidden ? \"Leave hidden chats out\" : `Show hidden chats${hiddenCount ? ` (${hiddenCount})` : \"\"}`}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => void client.refreshDiscovered()}\n aria-label=\"Look again for your other chats\"\n title=\"Look again\"\n >\n {state.discovered.loading ? <SpinnerIcon size={13} /> : <RefreshIcon size={13} />}\n </button>\n </span>\n }\n >\n Your other chats\n </SectionLabel>\n {state.discovered.loading && state.discovered.loadedAt === null ? (\n <SidebarSkeleton />\n ) : state.discovered.error ? (\n <p className=\"px-4 py-1 text-[12px] text-destructive\">{state.discovered.error}</p>\n ) : otherList.length === 0 ? (\n <p className=\"px-4 py-1 text-[12px] leading-5 text-muted-foreground\">\n {others.length > 0\n ? \"Every chat found here is pinned or hidden.\"\n : \"No other Claude Code or Codex chats were found on this computer.\"}\n </p>\n ) : (\n <>\n {renderGroups(otherList)}\n {state.discovered.data.length >= state.discoveredLimit ? (\n <div className=\"px-3 pt-2\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"w-full text-muted-foreground\"\n onClick={() => void client.showMoreDiscovered()}\n disabled={state.discovered.loading}\n >\n {state.discovered.loading ? <SpinnerIcon size={13} /> : null}\n Show older chats\n </Button>\n </div>\n ) : null}\n </>\n )}\n {showHidden ? null : hiddenCount > 0 ? (\n <button type=\"button\" className=\"cs-link mx-4 mt-3 text-[11.5px]\" onClick={() => setShowHidden(true)}>\n {hiddenCount} hidden {hiddenCount === 1 ? \"chat\" : \"chats\"} — show\n </button>\n ) : null}\n </>\n );\n\n return (\n <aside\n className=\"cs-sidebar flex h-full shrink-0 flex-col border-r border-border bg-sidebar-background\"\n style={{ width: props.width }}\n aria-label=\"Sessions\"\n >\n <div className=\"flex items-center justify-between gap-2 px-4 pb-2 pt-3.5\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"cs-app-mark\" aria-hidden=\"true\" />\n <span className=\"truncate text-[14px] font-semibold tracking-[-0.01em]\">Coding sessions</span>\n </div>\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={props.onCollapse}\n aria-label=\"Hide the sidebar (⌘B)\"\n title=\"Hide sidebar ⌘B\"\n >\n <SidebarIcon size={15} />\n </button>\n </div>\n <div className=\"space-y-1.5 px-3 pb-1\">\n <Button className=\"w-full justify-start gap-2\" variant=\"outline\" size=\"sm\" onClick={props.onNew}>\n <PlusIcon size={15} />\n New session\n <kbd className=\"cs-kbd ml-auto\">⌥⌘N</kbd>\n </Button>\n <div className=\"cs-search\">\n <SearchIcon size={14} className=\"cs-search__icon\" />\n <input\n ref={props.searchRef}\n type=\"search\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n if (query) setQuery(\"\");\n else e.currentTarget.blur();\n e.preventDefault();\n }\n if (e.key === \"Enter\") {\n const first = titleMatches[0];\n const hit = contentHits[0];\n if (first) selectEntry(first);\n else if (hit) openHit(hit);\n }\n }}\n placeholder=\"Search chats\"\n aria-label=\"Search chats by name, folder or what was said\"\n spellCheck={false}\n className=\"cs-search__input\"\n />\n {query ? (\n <button type=\"button\" className=\"cs-icon-button cs-search__clear\" onClick={() => setQuery(\"\")} aria-label=\"Clear search\">\n <CloseIcon size={13} />\n </button>\n ) : (\n <kbd className=\"cs-search__kbd\">⌘K</kbd>\n )}\n </div>\n </div>\n\n <nav className=\"min-h-0 flex-1 overflow-y-auto pb-3\">{searching ? searchBody : listBody}</nav>\n\n {props.footer}\n </aside>\n );\n}\n","/**\n * The screen's state, framework-free: one store over a\n * `CodingSessionsTransport`, plus one transcript per open session projected\n * into an `@ai-matrx/chat` thread store. React reads it through\n * `useSyncExternalStore` (see `hooks.ts`); nothing here imports React.\n */\n\nimport { createExternalThreadSource } from \"@ai-matrx/chat/external-store\";\nimport type { ChatMessage, ChatThreadStatus, ChatThreadStore } from \"@ai-matrx/chat\";\n\nimport { friendlyToolName, toolSubtitle } from \"../tool-labels\";\nimport { createTranscriptBuilder, type TranscriptBuilder } from \"../transcript\";\nimport {\n isTerminalRunStatus,\n type ChatPreference,\n type ChatSearchResult,\n type CodingEvent,\n type CodingProvider,\n type StartInput,\n type AgentSelection,\n type CodingSession,\n type CodingSessionsTransport,\n type DiscoveredSession,\n type OpenTarget,\n type RawTranscript,\n type ProviderStatus,\n type RecentFolder,\n type RunRecord,\n type TransportStatus,\n} from \"../types\";\n\nexport interface Loadable<T> {\n data: T;\n loading: boolean;\n error: string | null;\n loadedAt: number | null;\n}\n\nexport interface CodingSessionsState {\n connection: TransportStatus;\n providers: Loadable<ProviderStatus[]>;\n sessions: Loadable<CodingSession[]>;\n discovered: Loadable<DiscoveredSession[]>;\n folders: Loadable<RecentFolder[]>;\n /** Latest run per session id. */\n runs: Record<string, RunRecord>;\n /** The person's renames, pins and hides, by `chatKey()`. */\n preferences: Record<string, ChatPreference>;\n /** How many of \"Your other chats\" to list (grows with \"Show more\"). */\n discoveredLimit: number;\n}\n\n/** A run that just ended — for the tab badge and the desktop notification. */\nexport interface RunFinished {\n run: RunRecord;\n session: CodingSession | null;\n}\n\nconst DISCOVERED_PAGE = 60;\n/** \"Show earlier\" doubles the read, up to the engine's own cap. */\nconst HISTORY_START = 24 * 1024 * 1024;\n\nfunction loadable<T>(data: T): Loadable<T> {\n return { data, loading: false, error: null, loadedAt: null };\n}\n\nfunction message(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** One open conversation: history from the provider's file + the live stream. */\nexport class SessionTranscript {\n readonly thread: ChatThreadStore;\n private builder: TranscriptBuilder = createTranscriptBuilder();\n private messages: readonly ChatMessage[] = [];\n private listeners = new Set<() => void>();\n private seqMark = 0;\n private pending: { seq: number; event: CodingEvent }[] = [];\n private activeRunId: string | null = null;\n /**\n * What the agent is doing right now, in words — the live line under the\n * transcript. Codex's `exec --json` reports only COMPLETED messages (no\n * token deltas), so between them this line is what shows the run is alive.\n */\n activity: string | null = null;\n state: { loading: boolean; unavailable: string | null; truncated: boolean; loadingEarlier?: boolean } = {\n loading: true,\n unavailable: null,\n truncated: false,\n };\n /** How much of the provider's file to read; \"Show earlier\" doubles it. */\n private maxBytes = HISTORY_START;\n\n constructor(\n readonly sessionId: string,\n private readonly client: CodingSessionsClient,\n ) {\n this.thread = createExternalThreadSource({\n getSnapshot: () => ({\n messages: this.messages,\n status: this.status(),\n conversationId: this.sessionId,\n // The transcript lives in the provider's own files, so it IS saved —\n // just not by AI Matrx. Nothing to announce.\n ephemeral: false,\n }),\n // The engine queues a prompt sent during a live run, so the composer\n // may send while an answer is still arriving (Send beside Stop).\n features: { surface: { sendWhileBusy: true } },\n subscribe: (listener) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n },\n onSubmit: async (input) => {\n await this.client.send(this.sessionId, input.text);\n },\n onCancel: async () => {\n const run = this.client.getState().runs[this.sessionId];\n if (run && !isTerminalRunStatus(run.status)) await this.client.stop(run.runId);\n },\n });\n }\n\n private status(): ChatThreadStatus {\n const run = this.client.getState().runs[this.sessionId];\n if (!run) return \"idle\";\n if (run.status === \"starting\") return \"submitted\";\n if (run.status === \"running\") return \"streaming\";\n return \"idle\";\n }\n\n notify(): void {\n this.messages = this.builder.messages();\n for (const listener of this.listeners) listener();\n }\n\n /** Read further back into a long chat. The transcript stays on screen meanwhile. */\n async loadEarlier(): Promise<void> {\n if (!this.state.truncated || this.state.loadingEarlier) return;\n this.maxBytes *= 4;\n this.state = { ...this.state, loadingEarlier: true };\n this.notify();\n await this.load(true);\n }\n\n async load(keepVisible = false): Promise<void> {\n if (!keepVisible) {\n this.state = { loading: true, unavailable: null, truncated: false };\n this.notify();\n }\n try {\n const history = await this.client.transport.call(\"history\", this.sessionId, { maxBytes: this.maxBytes });\n this.builder = createTranscriptBuilder();\n this.builder.applyAll(history.items);\n this.seqMark = history.seq;\n const run = this.client.getState().runs[this.sessionId];\n if (run && !isTerminalRunStatus(run.status)) {\n this.activeRunId = run.runId;\n this.builder.beginTurn();\n } else {\n this.builder.endTurn(\"completed\");\n }\n this.state = { loading: false, unavailable: history.unavailable, truncated: history.truncated };\n const queued = this.pending;\n this.pending = [];\n for (const entry of queued) this.onEvent(entry.event);\n } catch (error) {\n this.state = { loading: false, unavailable: message(error), truncated: false };\n }\n this.notify();\n }\n\n onEvent(event: CodingEvent): void {\n if (this.state.loading) {\n if (event.type === \"item\") this.pending.push({ seq: event.seq, event });\n return;\n }\n if (event.type === \"item\") {\n if (event.seq <= this.seqMark) return;\n this.seqMark = event.seq;\n this.builder.apply(event.item);\n if (event.item.kind === \"user\") {\n // The working bubble opens right under the prompt it answers.\n this.activeRunId = event.runId;\n this.builder.beginTurn();\n }\n this.activity = nextActivity(this.activity, event.item);\n this.notify();\n return;\n }\n if (event.type === \"run\") {\n const run = event.run;\n if (isTerminalRunStatus(run.status)) {\n this.activity = null;\n if (this.activeRunId === run.runId) {\n this.builder.endTurn(run.status, run.error);\n this.activeRunId = null;\n } else if (run.status === \"failed\" && run.error) {\n // A run that failed before producing anything still owes the\n // reader its real error.\n this.builder.endTurn(\"failed\", run.error);\n }\n }\n this.notify();\n }\n }\n}\n\nfunction nextActivity(current: string | null, item: import(\"../types\").TranscriptItem): string | null {\n switch (item.kind) {\n case \"user\":\n return \"Thinking…\";\n case \"text-delta\":\n return \"Writing…\";\n case \"text\":\n case \"reasoning\":\n case \"tool-result\":\n return \"Thinking…\";\n case \"tool-call\": {\n const subtitle = toolSubtitle(item.name, item.input);\n return `${friendlyToolName(item.name)}${subtitle ? ` — ${subtitle}` : \"\"}`;\n }\n default:\n return current;\n }\n}\n\n/** A read-only transcript of a chat found on disk, before taking it over. */\nexport interface PreviewState {\n loading: boolean;\n messages: readonly ChatMessage[];\n unavailable: string | null;\n truncated: boolean;\n}\n\nexport class CodingSessionsClient {\n private state: CodingSessionsState;\n private listeners = new Set<() => void>();\n private transcripts = new Map<string, SessionTranscript>();\n private finishedListeners = new Set<(finished: RunFinished) => void>();\n\n /** Hear about every run that ends (completed, stopped or failed). */\n onRunFinished = (listener: (finished: RunFinished) => void): (() => void) => {\n this.finishedListeners.add(listener);\n return () => {\n this.finishedListeners.delete(listener);\n };\n };\n\n constructor(readonly transport: CodingSessionsTransport) {\n this.state = {\n connection: transport.status(),\n providers: loadable([]),\n sessions: loadable([]),\n discovered: loadable([]),\n folders: loadable([]),\n runs: {},\n preferences: {},\n discoveredLimit: DISCOVERED_PAGE,\n };\n transport.onStatus((connection) => {\n const wasOpen = this.state.connection.state === \"open\";\n this.set({ connection });\n if (connection.state === \"open\" && !wasOpen) void this.refreshAll();\n });\n transport.subscribe((event) => this.onEvent(event));\n }\n\n getState = (): CodingSessionsState => this.state;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n private set(patch: Partial<CodingSessionsState>): void {\n this.state = { ...this.state, ...patch };\n for (const listener of this.listeners) listener();\n }\n\n private onEvent(event: CodingEvent): void {\n if (event.type === \"session\") {\n const list = this.state.sessions.data.filter((s) => s.id !== event.session.id);\n list.unshift(event.session);\n list.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n this.set({ sessions: { ...this.state.sessions, data: list } });\n } else if (event.type === \"run\") {\n const before = this.state.runs[event.run.sessionId];\n this.set({ runs: { ...this.state.runs, [event.run.sessionId]: event.run } });\n const ended =\n isTerminalRunStatus(event.run.status) &&\n (!before || before.runId !== event.run.runId || !isTerminalRunStatus(before.status));\n if (ended) {\n const session = this.state.sessions.data.find((s) => s.id === event.run.sessionId) ?? null;\n for (const listener of this.finishedListeners) listener({ run: event.run, session });\n }\n } else if (event.type === \"preferences\") {\n this.set({ preferences: event.preferences });\n return;\n }\n const sessionId = event.type === \"session\" ? event.session.id : event.type === \"run\" ? event.run.sessionId : event.sessionId;\n this.transcripts.get(sessionId)?.onEvent(event);\n }\n\n private async load<K extends \"providers\" | \"sessions\" | \"discovered\" | \"folders\">(\n key: K,\n fetcher: () => Promise<CodingSessionsState[K][\"data\"]>,\n ): Promise<void> {\n this.set({ [key]: { ...this.state[key], loading: true, error: null } } as Partial<CodingSessionsState>);\n try {\n const data = await fetcher();\n this.set({ [key]: { data, loading: false, error: null, loadedAt: Date.now() } } as Partial<CodingSessionsState>);\n } catch (error) {\n this.set({\n [key]: { ...this.state[key], loading: false, error: message(error) },\n } as Partial<CodingSessionsState>);\n }\n }\n\n refreshProviders = () => this.load(\"providers\", () => this.transport.call(\"providers\"));\n refreshDiscovered = () =>\n this.load(\"discovered\", () => this.transport.call(\"discoverSessions\", { limit: this.state.discoveredLimit }));\n\n /** List more of \"Your other chats\". */\n showMoreDiscovered = async (): Promise<void> => {\n this.set({ discoveredLimit: this.state.discoveredLimit + DISCOVERED_PAGE });\n await this.refreshDiscovered();\n };\n\n refreshPreferences = async (): Promise<void> => {\n try {\n this.set({ preferences: await this.transport.call(\"chatPreferences\") });\n } catch {\n /* the lists still work with no renames or pins */\n }\n };\n\n /** Rename, pin or hide a chat. Applied at once; the host's answer replaces it. */\n setPreference = async (key: string, patch: ChatPreference): Promise<void> => {\n const previous = this.state.preferences;\n const merged = { ...previous[key], ...patch };\n this.set({ preferences: { ...previous, [key]: merged } });\n try {\n this.set({ preferences: await this.transport.call(\"setChatPreference\", key, patch) });\n } catch (error) {\n this.set({ preferences: previous });\n throw error;\n }\n };\n\n search(query: string, cursor = 0): Promise<ChatSearchResult> {\n return this.transport.call(\"searchChats\", query, { cursor, limit: 30 });\n }\n\n /** FULL DOWNLOAD: this chat's complete provider file, from this computer. */\n readRawTranscript(provider: CodingProvider, providerSessionId: string): Promise<RawTranscript> {\n return this.transport.call(\"readRawTranscript\", provider, providerSessionId);\n }\n\n openFolder(path: string, target: OpenTarget): Promise<void> {\n return this.transport.call(\"openFolder\", path, target);\n }\n\n setSessionOptions(sessionId: string, options: { model?: string | null; effort?: string | null }) {\n return this.transport.call(\"setSessionOptions\", sessionId, options);\n }\n refreshFolders = () => this.load(\"folders\", () => this.transport.call(\"recentFolders\"));\n\n refreshSessions = async (): Promise<void> => {\n await this.load(\"sessions\", () => this.transport.call(\"listSessions\"));\n // The latest run of each session, so Running and statuses are right on load.\n const runs: Record<string, RunRecord> = {};\n await Promise.all(\n this.state.sessions.data.map(async (session) => {\n const list = await this.transport.call(\"listRuns\", session.id).catch(() => [] as RunRecord[]);\n const last = list[list.length - 1];\n if (last) runs[session.id] = last;\n }),\n );\n this.set({ runs: { ...runs, ...this.pickLive() } });\n };\n\n private pickLive(): Record<string, RunRecord> {\n const out: Record<string, RunRecord> = {};\n for (const [id, run] of Object.entries(this.state.runs)) {\n if (!isTerminalRunStatus(run.status)) out[id] = run;\n }\n return out;\n }\n\n refreshAll = async (): Promise<void> => {\n await Promise.all([\n this.refreshSessions(),\n this.refreshProviders(),\n this.refreshDiscovered(),\n this.refreshFolders(),\n this.refreshPreferences(),\n ]);\n for (const transcript of this.transcripts.values()) void transcript.load();\n };\n\n transcript(sessionId: string): SessionTranscript {\n let transcript = this.transcripts.get(sessionId);\n if (!transcript) {\n transcript = new SessionTranscript(sessionId, this);\n this.transcripts.set(sessionId, transcript);\n void transcript.load();\n }\n return transcript;\n }\n\n async readPreview(provider: CodingProvider, providerSessionId: string, maxBytes?: number): Promise<PreviewState> {\n try {\n const history = await this.transport.call(\n \"readTranscript\",\n provider,\n providerSessionId,\n maxBytes ? { maxBytes } : undefined,\n );\n const builder = createTranscriptBuilder();\n builder.applyAll(history.items);\n builder.endTurn(\"completed\");\n return {\n loading: false,\n messages: builder.messages(),\n unavailable: history.unavailable,\n truncated: history.truncated,\n };\n } catch (error) {\n return { loading: false, messages: [], unavailable: message(error), truncated: false };\n }\n }\n\n start(input: StartInput) {\n return this.transport.call(\"start\", input);\n }\n\n takeover(session: DiscoveredSession, agent?: AgentSelection | null) {\n return this.transport.call(\"takeover\", {\n provider: session.provider,\n providerSessionId: session.providerSessionId,\n cwd: session.cwd ?? \"\",\n title: session.title,\n ...(agent ? { agent } : {}),\n });\n }\n\n send(sessionId: string, prompt: string) {\n return this.transport.call(\"send\", sessionId, prompt);\n }\n\n stop(runId: string) {\n return this.transport.call(\"stop\", runId);\n }\n}\n","/**\n * `TranscriptItem`s → `@ai-matrx/chat` messages.\n *\n * The transcript is rendered by THE one person ↔ agent chat interface\n * (`@ai-matrx/chat`), not by a second message list: its message/part model\n * already has text, reasoning, tool parts on the industry tool-call state\n * machine, notices and errors, and its React transcript already renders them\n * (markdown, collapsible tool cards, streaming). This module is the only\n * adapter: one assistant message per turn, parts in arrival order.\n *\n * Identity is preserved on purpose: a change rebuilds ONLY the message it\n * touched, so the chat store's per-message subscriptions wake one bubble per\n * token instead of the whole list.\n */\n\nimport {\n createChatMessage,\n type ChatMessage,\n type ChatPart,\n type ChatToolPart,\n} from \"@ai-matrx/chat\";\n\nimport { runErrorLabel } from \"./provider-health\";\nimport { toolSubtitle } from \"./tool-labels\";\nimport type { RunStatus, RunUsage, TranscriptItem } from \"./types\";\n\nexport interface TranscriptBuilder {\n apply(item: TranscriptItem): void;\n applyAll(items: readonly TranscriptItem[]): void;\n /** Close the turn in progress with the run's final status. */\n endTurn(status: RunStatus, error?: string | null): void;\n /** Mark a turn as in progress (the assistant bubble shows it is working). */\n beginTurn(): void;\n messages(): readonly ChatMessage[];\n lastUsage(): { usage: RunUsage; costUsd: number | null } | null;\n}\n\ninterface Working {\n message: ChatMessage;\n /** item id → index in `message.parts`. */\n index: Map<string, number>;\n}\n\nexport function createTranscriptBuilder(): TranscriptBuilder {\n const list: ChatMessage[] = [];\n let current: Working | null = null;\n let turn = 0;\n let usage: { usage: RunUsage; costUsd: number | null } | null = null;\n /** tool call id → [message index, part index] for results that arrive late. */\n const toolHome = new Map<string, { messageIndex: number; partIndex: number }>();\n\n function commit(working: Working, parts: ChatPart[], status?: ChatMessage[\"status\"]): void {\n const next: ChatMessage = {\n ...working.message,\n parts,\n status: status ?? working.message.status,\n };\n working.message = next;\n const at = list.findIndex((m) => m.id === next.id);\n if (at >= 0) list[at] = next;\n }\n\n function ensureAssistant(): Working {\n if (current) return current;\n turn += 1;\n const message = createChatMessage({\n id: `turn-${turn}-${list.length}`,\n role: \"assistant\",\n status: \"streaming\",\n });\n list.push(message);\n current = { message, index: new Map() };\n return current;\n }\n\n function upsertPart(id: string, build: (existing: ChatPart | null) => ChatPart): void {\n const working = ensureAssistant();\n const parts = [...working.message.parts];\n const at = working.index.get(id);\n if (at === undefined) {\n working.index.set(id, parts.length);\n parts.push(build(null));\n } else {\n parts[at] = build(parts[at] ?? null);\n }\n commit(working, parts);\n }\n\n function closeCurrent(status: ChatMessage[\"status\"]): void {\n if (!current) return;\n const working = current;\n const parts = working.message.parts.map((part): ChatPart => {\n if (part.type === \"reasoning\" && part.state === \"streaming\") return { ...part, state: \"done\" };\n if (part.type === \"tool\" && part.state === \"input-available\" && status !== \"streaming\") {\n if (status === \"cancelled\") {\n return { ...part, state: \"output-error\", errorText: \"Stopped before this finished.\" };\n }\n if (status === \"error\") {\n return { ...part, state: \"output-error\", errorText: \"The run ended before this finished.\" };\n }\n }\n return part;\n });\n commit(working, parts, status);\n current = null;\n }\n\n const builder: TranscriptBuilder = {\n apply(item) {\n switch (item.kind) {\n case \"user\": {\n closeCurrent(\"complete\");\n list.push(\n createChatMessage({\n id: `user-${item.id}`,\n role: \"user\",\n parts: [{ type: \"text\", text: item.text }],\n status: \"complete\",\n metadata: item.at ? { createdAt: item.at } : undefined,\n }),\n );\n return;\n }\n case \"text-delta\":\n upsertPart(item.id, (existing) =>\n existing && existing.type === \"text\"\n ? { type: \"text\", text: existing.text + item.text }\n : { type: \"text\", text: item.text },\n );\n return;\n case \"text\":\n upsertPart(item.id, () => ({ type: \"text\", text: item.text }));\n return;\n case \"reasoning\":\n upsertPart(item.id, () => ({ type: \"reasoning\", text: item.text, state: \"done\" }));\n return;\n case \"tool-call\": {\n // The key argument (the command, the file) rides as the card's one\n // progress beat, which the chat card shows beside the tool's name.\n const subtitle = toolSubtitle(item.name, item.input);\n const progress = subtitle ? [{ toolName: item.name, message: subtitle, percent: null, at: null }] : [];\n upsertPart(item.id, (existing) =>\n existing && existing.type === \"tool\"\n ? { ...existing, input: item.input, progress }\n : {\n type: \"tool\",\n toolCallId: item.id,\n toolName: item.name,\n state: \"input-available\",\n input: item.input,\n output: null,\n errorText: null,\n progress,\n delegated: false,\n },\n );\n const working = current;\n if (working) {\n const partIndex = working.index.get(item.id);\n const messageIndex = list.findIndex((m) => m.id === working.message.id);\n if (partIndex !== undefined && messageIndex >= 0) {\n toolHome.set(item.id, { messageIndex, partIndex });\n }\n }\n return;\n }\n case \"tool-result\": {\n const home = toolHome.get(item.id);\n if (!home) {\n // A result whose call we never saw (a history read that started\n // mid-conversation). Show it as its own finished card.\n upsertPart(item.id, () => ({\n type: \"tool\",\n toolCallId: item.id,\n toolName: \"Tool\",\n state: item.isError ? \"output-error\" : \"output-available\",\n input: null,\n output: item.isError ? null : item.output,\n errorText: item.isError ? item.output || \"The tool reported an error.\" : null,\n progress: [],\n delegated: false,\n }));\n return;\n }\n const message = list[home.messageIndex];\n const part = message?.parts[home.partIndex];\n if (!message || !part || part.type !== \"tool\") return;\n const nextPart: ChatToolPart = item.isError\n ? { ...part, state: \"output-error\", errorText: item.output || \"The tool reported an error.\", output: null }\n : { ...part, state: \"output-available\", output: item.output };\n const parts = [...message.parts];\n parts[home.partIndex] = nextPart;\n const next: ChatMessage = { ...message, parts };\n list[home.messageIndex] = next;\n if (current && current.message.id === next.id) current.message = next;\n return;\n }\n case \"usage\":\n usage = { usage: item.usage, costUsd: item.costUsd };\n return;\n case \"notice\":\n upsertPart(item.id, () => ({\n type: \"notice\",\n level: item.level === \"warning\" ? \"medium\" : \"info\",\n code: null,\n userMessage: item.text,\n remedy: null,\n }));\n return;\n case \"error\": {\n // Codex reports one failure up to three ways (a top-level `error`,\n // `turn.failed`, and the run's final error): say it once.\n // A known class (a refused model) shows its short label, never the\n // provider's raw JSON.\n const text = runErrorLabel(item.text);\n const said = current?.message.parts.some((p) => p.type === \"error\" && p.message.trim() === text.trim());\n if (said) return;\n upsertPart(item.id, () => ({\n type: \"error\",\n errorType: \"provider\",\n code: null,\n message: text,\n userMessage: text,\n recoverable: true,\n remedy: null,\n }));\n return;\n }\n }\n },\n applyAll(items) {\n for (const item of items) builder.apply(item);\n },\n beginTurn() {\n ensureAssistant();\n },\n endTurn(status, error) {\n if (status === \"failed\" && error) {\n builder.apply({ kind: \"error\", id: `run-error-${list.length}`, text: error });\n }\n if (status === \"stopped\" && current) {\n builder.apply({\n kind: \"notice\",\n id: `run-stopped-${list.length}`,\n level: \"info\",\n text: \"You stopped this run.\",\n });\n }\n closeCurrent(status === \"stopped\" ? \"cancelled\" : status === \"failed\" ? \"error\" : \"complete\");\n },\n messages() {\n // A fresh array per read: the chat store compares the list by identity\n // to notice appends, and the message objects inside keep theirs.\n return list.slice();\n },\n lastUsage() {\n return usage;\n },\n };\n return builder;\n}\n","/**\n * The New session form's checks, framework-free so they are testable without\n * a DOM. Every refusal names its field and says what to do — a Start button\n * that silently does nothing is the dead control the platform forbids.\n *\n * Validation offers, never blocks: a usage limit or an expired sign-in is a\n * WARNING (the person may have fixed it a minute ago), but a provider that is\n * not installed, a missing folder or an empty request genuinely cannot run.\n */\n\nimport type { FolderCheck, ProviderStatus } from \"../types\";\n\nexport type NewSessionField = \"agent\" | \"folder\" | \"prompt\";\n\nexport interface NewSessionErrors {\n agent?: string;\n folder?: string;\n /** The typed path that does not exist, when creating it is on offer. */\n createFolder?: string;\n prompt?: string;\n}\n\nexport const FIELD_ORDER: readonly NewSessionField[] = [\"agent\", \"folder\", \"prompt\"];\n\nexport async function validateNewSession(input: {\n provider: ProviderStatus | null;\n folder: string;\n prompt: string;\n checkFolder: (path: string) => Promise<FolderCheck>;\n}): Promise<NewSessionErrors> {\n const errors: NewSessionErrors = {};\n const p = input.provider;\n if (p && (!p.installed || !p.loggedIn)) {\n errors.agent = `${p.problem ?? `${p.label} can't run here yet.`} ${p.fix ?? \"\"}`.trim();\n }\n if (!input.folder.trim()) {\n errors.folder = \"Choose a folder, or type one, for it to work in.\";\n } else {\n try {\n const check = await input.checkFolder(input.folder);\n if (!check.exists) {\n errors.folder = \"That folder doesn't exist on this computer.\";\n errors.createFolder = check.path;\n } else if (!check.isDirectory) {\n errors.folder = \"That path is a file, not a folder.\";\n }\n } catch (error) {\n errors.folder = `Couldn't check that folder: ${error instanceof Error ? error.message : String(error)}`;\n }\n }\n if (!input.prompt.trim()) errors.prompt = \"Tell it what to do first.\";\n return errors;\n}\n\nexport function firstInvalidField(errors: NewSessionErrors): NewSessionField | null {\n return FIELD_ORDER.find((field) => errors[field] !== undefined) ?? null;\n}\n"],"mappings":"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","names":["prettyPath","import_react","import_external_store","import_design_system","import_format","import_react","import_design_system","message","import_format","prettyPath","import_react","import_jsx_runtime","import_jsx_runtime","prettyPath","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","prettyPath","message","history","import_jsx_runtime","prettyPath"]}
|
|
1
|
+
{"version":3,"sources":["../../src/react/index.ts","../../src/react/app.tsx","../../src/types.ts","../../src/provider-health.ts","../../src/tool-labels.ts","../../src/react/changes-panel.tsx","../../src/changes.ts","../../src/react/chat-menu.tsx","../../src/react/grouping.ts","../../src/react/hooks.ts","../../src/react/icons.tsx","../../src/react/toast.ts","../../src/react/model-picker.tsx","../../src/react/agent-field.tsx","../../src/react/sidebar.tsx","../../src/react/client.ts","../../src/transcript.ts","../../src/react/new-session.ts"],"sourcesContent":["/**\n * `@ai-matrx/coding-sessions/react` — the screen. `<CodingSessionsApp>` is the\n * whole product; the provider and hooks exist for a host composing its own\n * layout around the same state.\n *\n * Styling: the components use the design system's semantic Tailwind classes\n * plus the package's own `cs-*` rules. The standalone page served by\n * `./server` ships them compiled; a Tailwind host adds this package's `dist`\n * as an `@source` and imports the chat + design-system sheets (see README).\n */\n\nexport { CodingSessionsApp, CodingSessionsProvider } from \"./app\";\nexport type { CodingSessionsAppProps, CodingSessionsProviderProps } from \"./app\";\nexport { CodingSessionsClient, SessionTranscript } from \"./client\";\nexport type { CodingSessionsState, Loadable, PreviewState } from \"./client\";\nexport {\n useCodingSessionsClient,\n useCodingSessionsState,\n useSessionTranscript,\n relativeTime,\n prettyPath,\n} from \"./hooks\";\n","/**\n * THE SCREEN. A three-group list (Running · Recent · Your other chats), a live\n * transcript rendered by `@ai-matrx/chat` (markdown answers, collapsible tool\n * cards, streaming), a composer, and a New session flow. No terminal anywhere:\n * the person never sees a command, a flag or a log line.\n *\n * Every state is honest: loading, empty, host unreachable, provider not\n * installed or not signed in (with the fix in plain English), a run that failed\n * with its real error. A control is present and working, or absent.\n */\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\n\nimport {\n ChatComposer,\n ChatMessageList,\n ChatProvider,\n type ChatNotifierPort,\n} from \"@ai-matrx/chat/react\";\nimport { createExternalThreadSource } from \"@ai-matrx/chat/external-store\";\nimport {\n Button,\n Dialog,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n Textarea,\n cn,\n} from \"@ai-matrx/design-system\";\n\nimport { formatCount, formatUsd } from \"@ai-matrx/kit/format\";\nimport { formatUntil } from \"../provider-health\";\nimport { friendlyToolName } from \"../tool-labels\";\nimport {\n PROVIDER_LABEL,\n isTerminalRunStatus,\n type ActiveElsewhere,\n type AgentDetails,\n type AgentSelection,\n type CodingProvider,\n type CodingSession,\n type CodingSessionsTransport,\n type DiscoveredSession,\n type ProviderStatus,\n type RunRecord,\n} from \"../types\";\nimport { ChangesPanel, useChangedFiles } from \"./changes-panel\";\nimport { ChatMenuItems } from \"./chat-menu\";\nimport { discoveredEntry, sessionEntry, type ListEntry } from \"./grouping\";\nimport { ModelPicker, defaultModelWords, modelLabel, type ModelChoice } from \"./model-picker\";\nimport { AgentField, AgentMenu, ChooseAgentDialog, missingRequiredVariable } from \"./agent-field\";\nimport { MODEL_UNAVAILABLE_LABEL, isModelUnavailable, runErrorLabel } from \"../provider-health\";\nimport { Sidebar, type Selection } from \"./sidebar\";\nimport { ToastContext } from \"./toast\";\nimport { CodingSessionsClient, type PreviewState } from \"./client\";\nimport { firstInvalidField, validateNewSession, type NewSessionErrors, type NewSessionField } from \"./new-session\";\nimport {\n CodingSessionsContext,\n prettyPath,\n relativeTime,\n useCodingSessionsClient,\n useCodingSessionsState,\n useMinuteClock,\n useSessionTranscript,\n} from \"./hooks\";\nimport {\n AlertIcon,\n BellIcon,\n ChatBubbleIcon,\n CheckIcon,\n FileIcon,\n FolderIcon,\n KeyboardIcon,\n MoreIcon,\n SidebarIcon,\n HandoffIcon,\n MonitorIcon,\n MoonIcon,\n PlusIcon,\n ProviderMark,\n RefreshIcon,\n SpinnerIcon,\n StopIcon,\n SunIcon,\n} from \"./icons\";\n\n/* ------------------------------------------------------------------------ */\n/* Provider */\n/* ------------------------------------------------------------------------ */\n\nexport interface CodingSessionsProviderProps {\n transport: CodingSessionsTransport;\n children: ReactNode;\n}\n\nexport function CodingSessionsProvider({ transport, children }: CodingSessionsProviderProps): ReactNode {\n const [client] = useState(() => new CodingSessionsClient(transport));\n useEffect(() => {\n if (transport.status().state === \"open\") void client.refreshAll();\n }, [client, transport]);\n return <CodingSessionsContext.Provider value={client}>{children}</CodingSessionsContext.Provider>;\n}\n\n/* ------------------------------------------------------------------------ */\n/* Selection (kept in the URL hash so a reload lands where you were) */\n/* ------------------------------------------------------------------------ */\n\nfunction readHash(): Selection {\n if (typeof location === \"undefined\") return { kind: \"none\" };\n const [kind, a, b] = location.hash.replace(/^#/, \"\").split(\"/\");\n if (kind === \"s\" && a) return { kind: \"session\", id: a };\n if (kind === \"d\" && (a === \"claude\" || a === \"codex\") && b) return { kind: \"discovered\", provider: a, id: b };\n return { kind: \"none\" };\n}\n\nfunction writeHash(selection: Selection): void {\n if (typeof history === \"undefined\") return;\n const hash =\n selection.kind === \"session\"\n ? `#s/${selection.id}`\n : selection.kind === \"discovered\"\n ? `#d/${selection.provider}/${selection.id}`\n : \"\";\n history.replaceState(null, \"\", `${location.pathname}${location.search}${hash}`);\n}\n\n/* ------------------------------------------------------------------------ */\n/* Theme: system by default, light/dark on demand */\n/* ------------------------------------------------------------------------ */\n\ntype ThemeChoice = \"system\" | \"light\" | \"dark\";\n\nfunction readTheme(): ThemeChoice {\n try {\n const stored = localStorage.getItem(\"coding-sessions.theme\");\n return stored === \"light\" || stored === \"dark\" ? stored : \"system\";\n } catch {\n return \"system\";\n }\n}\n\nfunction useTheme(): [ThemeChoice, (next: ThemeChoice) => void] {\n const [choice, setChoice] = useState<ThemeChoice>(readTheme);\n useEffect(() => {\n // A host without matchMedia (a test DOM, an old webview) follows the choice.\n const media = typeof window.matchMedia === \"function\" ? window.matchMedia(\"(prefers-color-scheme: dark)\") : null;\n const apply = () => {\n const dark = choice === \"dark\" || (choice === \"system\" && media?.matches === true);\n document.documentElement.classList.toggle(\"dark\", dark);\n document.documentElement.setAttribute(\"data-theme\", dark ? \"dark\" : \"light\");\n };\n apply();\n media?.addEventListener(\"change\", apply);\n return () => media?.removeEventListener(\"change\", apply);\n }, [choice]);\n const set = useCallback((next: ThemeChoice) => {\n setChoice(next);\n try {\n localStorage.setItem(\"coding-sessions.theme\", next);\n } catch {\n /* a private window keeps the choice for this visit only */\n }\n }, []);\n return [choice, set];\n}\n\n/* ------------------------------------------------------------------------ */\n/* Small pieces */\n/* ------------------------------------------------------------------------ */\n\nconst RUN_LABEL: Record<RunRecord[\"status\"], string> = {\n starting: \"Starting\",\n running: \"Working\",\n completed: \"Done\",\n stopped: \"Stopped\",\n failed: \"Failed\",\n};\n\nfunction RunPill({ run }: { run: RunRecord | undefined }): ReactNode {\n if (!run) return null;\n const live = !isTerminalRunStatus(run.status);\n return (\n <span className={cn(\"cs-pill\", `cs-pill--${run.status}`)}>\n {live ? <span className=\"cs-pill__dot\" aria-hidden=\"true\" /> : null}\n {RUN_LABEL[run.status]}\n </span>\n );\n}\n\nfunction ConnectionBanner(): ReactNode {\n const { connection } = useCodingSessionsState();\n if (connection.state === \"open\") return null;\n const closed = connection.state === \"closed\";\n return (\n <div\n role=\"status\"\n className={cn(\n \"flex items-center gap-2 border-b px-4 py-2 text-[13px]\",\n closed ? \"border-destructive/30 bg-destructive/10 text-destructive\" : \"border-border bg-muted/60 text-muted-foreground\",\n )}\n >\n {closed ? <AlertIcon size={15} /> : <SpinnerIcon size={14} />}\n <span>{closed ? connection.reason : \"Connecting to the coding sessions host…\"}</span>\n </div>\n );\n}\n\nfunction ProvidersFooter(props: { theme: ThemeChoice; setTheme: (next: ThemeChoice) => void; extra?: ReactNode }): ReactNode {\n const state = useCodingSessionsState();\n const client = useCodingSessionsClient();\n const next: Record<ThemeChoice, ThemeChoice> = { system: \"light\", light: \"dark\", dark: \"system\" };\n const themeLabel: Record<ThemeChoice, string> = { system: \"Match system\", light: \"Light\", dark: \"Dark\" };\n return (\n <div className=\"border-t border-border px-3 py-2.5\">\n <div className=\"flex items-center gap-1.5\">\n <div className=\"flex min-w-0 flex-1 flex-wrap gap-1.5\">\n {state.providers.loading && state.providers.loadedAt === null ? (\n <span className=\"text-[11.5px] text-muted-foreground\">Checking Claude Code and Codex…</span>\n ) : (\n state.providers.data.map((p) => {\n const until = p.lastProblem ? formatUntil(p.lastProblem.until) : null;\n const note = !p.lastProblem ? null : p.lastProblem.kind === \"signed-out\" ? \"· sign in again\" : `· limit${until ? ` until ${until}` : \"\"}`;\n // The note may end in \"…\" on a narrow sidebar; the tooltip always carries it whole.\n const about = p.problem ? `${p.problem} ${p.fix ?? \"\"}`.trim() : [binaryWords(p) ?? p.label, p.plan, newerWords(p)].filter(Boolean).join(\" · \");\n return (\n <span key={p.provider} className={cn(\"cs-provider-chip\", p.ready ? \"\" : \"cs-provider-chip--problem\")} title={note && !p.problem ? `${about} ${note}` : about}>\n <ProviderMark provider={p.provider} size={13} />\n {p.label}\n {note ? <span className=\"cs-provider-chip__note\">{note}</span> : null}\n {p.ready ? <CheckIcon size={12} /> : <AlertIcon size={12} />}\n </span>\n );\n })\n )}\n </div>\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => void client.refreshProviders()}\n aria-label=\"Check Claude Code and Codex again\"\n title=\"Check again\"\n >\n {state.providers.loading ? <SpinnerIcon size={13} /> : <RefreshIcon size={13} />}\n </button>\n {props.extra}\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => props.setTheme(next[props.theme])}\n aria-label={`Theme: ${themeLabel[props.theme]}. Switch to ${themeLabel[next[props.theme]]}.`}\n title={`Theme: ${themeLabel[props.theme]}`}\n >\n {props.theme === \"system\" ? <MonitorIcon size={14} /> : props.theme === \"light\" ? <SunIcon size={14} /> : <MoonIcon size={14} />}\n </button>\n </div>\n </div>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* Session view */\n/* ------------------------------------------------------------------------ */\n\nfunction useNotifier(): ChatNotifierPort {\n const show = useContext(ToastContext);\n return useMemo<ChatNotifierPort>(\n () => ({\n notify(event) {\n // The chat package speaks to developers through remedies that name its\n // components; the reader gets the sentence.\n show(event.message);\n },\n }),\n [show],\n );\n}\n\n/**\n * Is this chat live somewhere else right now? Re-checked every 10 seconds\n * while it is on screen; `provider` null switches the check off.\n */\nfunction useLiveElsewhere(\n provider: CodingProvider | null,\n providerSessionId: string | null,\n initial: ActiveElsewhere | null = null,\n): ActiveElsewhere | null {\n const client = useCodingSessionsClient();\n const [state, setState] = useState<ActiveElsewhere | null>(initial);\n useEffect(() => {\n if (!provider || !providerSessionId) {\n setState(null);\n return;\n }\n let cancelled = false;\n const check = () =>\n client.transport\n .call(\"sessionActivity\", provider, providerSessionId)\n .then((next) => {\n if (!cancelled) setState(next);\n })\n .catch(() => undefined);\n void check();\n const timer = setInterval(check, 10_000);\n return () => {\n cancelled = true;\n clearInterval(timer);\n };\n }, [client, provider, providerSessionId]);\n return state;\n}\n\n/** What this session has used, summed over its runs (refreshed as runs end). */\nfunction useSessionUsage(sessionId: string, lastRunKey: string): { tokens: number; cost: number | null; billing: RunRecord[\"billing\"]; runs: number } | null {\n const client = useCodingSessionsClient();\n const [usage, setUsage] = useState<{ tokens: number; cost: number | null; billing: RunRecord[\"billing\"]; runs: number } | null>(null);\n useEffect(() => {\n let cancelled = false;\n void client.transport\n .call(\"listRuns\", sessionId)\n .then((runs) => {\n if (cancelled) return;\n let tokens = 0;\n let cost: number | null = null;\n let billing: RunRecord[\"billing\"] = null;\n for (const run of runs) {\n if (run.usage) tokens += run.usage.inputTokens + run.usage.outputTokens + run.usage.cachedInputTokens;\n if (run.costUsd !== null) cost = (cost ?? 0) + run.costUsd;\n billing = run.billing ?? billing;\n }\n setUsage(tokens > 0 || cost !== null ? { tokens, cost, billing, runs: runs.length } : null);\n })\n .catch(() => undefined);\n return () => {\n cancelled = true;\n };\n }, [client, sessionId, lastRunKey]);\n return usage;\n}\n\n/**\n * The header's ⋯. Header actions never wrap: at narrow widths the secondary ones hide from the\n * header (container query) and stay reachable here.\n */\nfunction HeaderMenu(props: { entry: ListEntry; onRename: () => void; onChanges?: () => void; changesOpen?: boolean }): ReactNode {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button type=\"button\" className=\"cs-icon-button shrink-0\" aria-label=\"More for this chat\" title=\"More\">\n <MoreIcon size={16} />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-64\" onCloseAutoFocus={(e) => e.preventDefault()}>\n {props.onChanges ? (\n <DropdownMenuItem onSelect={props.onChanges}>\n <FileIcon size={14} />\n {props.changesOpen ? \"Hide changed files\" : \"Files this chat changed\"}\n </DropdownMenuItem>\n ) : null}\n <ChatMenuItems entry={props.entry} variant=\"dropdown\" onRename={props.onRename} />\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\n/** The chat's title in a header, renameable in place. */\nfunction HeaderTitle(props: { entry: ListEntry; renaming: boolean; setRenaming: (on: boolean) => void }): ReactNode {\n const client = useCodingSessionsClient();\n const show = useContext(ToastContext);\n const [value, setValue] = useState(props.entry.title);\n useEffect(() => setValue(props.entry.title), [props.entry.title, props.renaming]);\n // The header menu's focus trap takes focus back from a freshly mounted input and then\n // unmounts, leaving focus on <body> — the next keystrokes went to the composer and were\n // SENT. Focus once the menu has gone, so typing lands in the title.\n const inputRef = useRef<HTMLInputElement>(null);\n useEffect(() => {\n if (!props.renaming) return;\n const timer = setTimeout(() => {\n const input = inputRef.current;\n if (input && document.activeElement !== input) {\n input.focus();\n input.select();\n }\n }, 0);\n return () => clearTimeout(timer);\n }, [props.renaming]);\n if (!props.renaming) {\n return (\n <h1\n className=\"truncate text-[15px] font-semibold leading-5 tracking-[-0.01em]\"\n title={props.entry.title !== props.entry.originalTitle ? `${props.entry.title} (${props.entry.originalTitle})` : props.entry.title}\n onDoubleClick={() => props.setRenaming(true)}\n >\n {props.entry.title}\n </h1>\n );\n }\n const save = () => {\n props.setRenaming(false);\n const title = value.trim();\n if (title === props.entry.title) return;\n const next = title === \"\" || title === props.entry.originalTitle ? null : title;\n client\n .setPreference(props.entry.key, { title: next })\n .catch((error: unknown) => show(`The new name didn't save: ${error instanceof Error ? error.message : String(error)}`));\n };\n return (\n <input\n ref={inputRef}\n autoFocus\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onFocus={(e) => e.currentTarget.select()}\n onBlur={save}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") save();\n if (e.key === \"Escape\") props.setRenaming(false);\n }}\n aria-label=\"New name for this chat\"\n className=\"cs-rename-input !m-0 !h-6 !text-[15px] !font-semibold\"\n />\n );\n}\n\nfunction LongChatNote(props: { onEarlier: () => void; loading: boolean }): ReactNode {\n return (\n <p className=\"mx-auto mt-3 flex items-center gap-2 text-[12px] text-muted-foreground\">\n This chat is very long — showing its most recent part.\n <button type=\"button\" className=\"cs-link\" onClick={props.onEarlier} disabled={props.loading}>\n {props.loading ? \"Reading…\" : \"Show earlier\"}\n </button>\n </p>\n );\n}\n\n/** \"Codex 0.159.2 · from ChatGPT app\" — which CLI runs. */\nfunction binaryWords(p: ProviderStatus): string | null {\n if (!p.version) return null;\n return `${p.label} ${p.version}${p.binary ? ` · ${p.binary.sourceLabel}` : \"\"}`;\n}\n\n/** \"Newer: 0.160.0 from npm\" when a newer copy than the one in use exists. */\nfunction newerWords(p: ProviderStatus): string | null {\n return p.binary?.newer ? `Newer: ${p.binary.newer.version} ${p.binary.newer.sourceLabel}` : null;\n}\n\nfunction SessionView({ session, changesOpen, setChangesOpen }: { session: CodingSession; changesOpen: boolean; setChangesOpen: (open: boolean) => void }): ReactNode {\n const client = useCodingSessionsClient();\n const state = useCodingSessionsState();\n const show = useContext(ToastContext);\n const transcript = useSessionTranscript(session.id);\n const run = state.runs[session.id];\n const live = run !== undefined && !isTerminalRunStatus(run.status);\n const notifier = useNotifier();\n const provider = state.providers.data.find((p) => p.provider === session.provider) ?? null;\n const blocked = provider && (!provider.installed || !provider.loggedIn) ? provider : null;\n // A usage limit or expired sign-in WARNS (the person may have fixed it);\n // only a provider that cannot run at all holds the composer.\n const limited = !blocked && provider?.lastProblem ? provider : null;\n // The last run was refused for its MODEL: offer the picker right here.\n const modelRefused = run?.status === \"failed\" && isModelUnavailable(run.error);\n const [stopping, setStopping] = useState(false);\n const [renaming, setRenaming] = useState(false);\n const elsewhere = useLiveElsewhere(\n session.origin === \"takeover\" && !live ? session.provider : null,\n session.providerSessionId,\n );\n const entry = sessionEntry(session, state.preferences);\n const messages = transcript.thread.getSnapshot().messages;\n const files = useChangedFiles(messages);\n const usage = useSessionUsage(session.id, `${run?.runId ?? \"\"}:${run?.status ?? \"\"}`);\n\n useEffect(() => {\n if (!live) setStopping(false);\n }, [live]);\n\n const stop = async () => {\n if (!run) return;\n setStopping(true);\n await client.stop(run.runId).catch(() => setStopping(false));\n };\n\n const setOptions = (next: ModelChoice) => {\n client\n .setSessionOptions(session.id, { model: next.model, effort: next.effort })\n .then(() => show(`The next message uses ${modelLabel(next, provider)}.`))\n .catch((error: unknown) => show(`That didn't save: ${error instanceof Error ? error.message : String(error)}`));\n };\n\n const usageWords = usage\n ? `${formatCount(usage.tokens, { style: \"compact\" })} tokens${usage.cost !== null ? ` · ${formatUsd(usage.cost)}` : \"\"}`\n : null;\n const usageTitle = usage\n ? `${formatCount(usage.tokens)} tokens over ${usage.runs} ${usage.runs === 1 ? \"message\" : \"messages\"} sent from here.` +\n (usage.cost !== null\n ? usage.billing === \"subscription\"\n ? ` ${formatUsd(usage.cost)} is what this would cost at API prices — it's covered by your ${provider?.plan ?? \"\"} plan.`.replace(\" \", \" \")\n : ` Billed ${formatUsd(usage.cost)} to your API key.`\n : \"\")\n : \"\";\n\n return (\n <div className=\"flex min-w-0 flex-1\">\n <section className=\"flex min-w-0 flex-1 flex-col\" aria-label={entry.title}>\n <header className=\"@container/header flex items-center gap-2 border-b border-border px-5 pt-2.5 pb-2.5\">\n <ProviderMark provider={session.provider} size={22} />\n {/* overflow-hidden: the meta line never runs under the badges beside it. */}\n <div className=\"min-w-0 flex-1 overflow-hidden\">\n <HeaderTitle entry={entry} renaming={renaming} setRenaming={setRenaming} />\n <div className=\"flex min-w-0 items-center gap-1 text-[12px] leading-5 text-muted-foreground\">\n <span className=\"shrink-0\">{PROVIDER_LABEL[session.provider]}</span>\n <span aria-hidden=\"true\">·</span>\n <ModelPicker\n status={provider}\n value={{ model: session.model, effort: session.effort ?? null }}\n onChange={setOptions}\n />\n <span aria-hidden=\"true\">·</span>\n <FolderIcon size={12} className=\"shrink-0\" />\n <span className=\"min-w-[4rem] truncate\" title={session.cwd}>\n {prettyPath(session.cwd)}\n </span>\n {usageWords ? (\n <span className=\"shrink-0\" title={usageTitle}>\n · {usageWords}\n </span>\n ) : null}\n </div>\n </div>\n <AgentMenu transport={client.transport} sessionId={session.id} agent={session.agent ?? null} onChange={() => undefined} />\n <button\n type=\"button\"\n className={cn(\"cs-chip-button shrink-0 @max-[620px]/header:hidden\", changesOpen && \"cs-chip-button--on\")}\n onClick={() => setChangesOpen(!changesOpen)}\n aria-pressed={changesOpen}\n title=\"Files this chat changed\"\n >\n <FileIcon size={13} />\n {files.length > 0 ? `${files.length} ${files.length === 1 ? \"file\" : \"files\"} changed` : \"Changes\"}\n </button>\n <RunPill run={run} />\n {live ? (\n <Button variant=\"outline\" size=\"sm\" onClick={() => void stop()} disabled={stopping} className=\"gap-1.5\" title=\"Stop Esc\">\n {stopping ? <SpinnerIcon size={13} /> : <StopIcon size={13} />}\n {stopping ? \"Stopping…\" : \"Stop\"}\n </Button>\n ) : null}\n <HeaderMenu entry={entry} onRename={() => setRenaming(true)} onChanges={() => setChangesOpen(!changesOpen)} changesOpen={changesOpen} />\n </header>\n\n <div className=\"mx-chat flex min-h-0 flex-1 flex-col\">\n <ChatProvider thread={transcript.thread} ports={{ notifier, toolLabel: friendlyToolName }}>\n <div className=\"min-h-0 flex-1 overflow-hidden\">\n {transcript.state.loading ? (\n <div className=\"flex h-full items-center justify-center gap-2 text-[13px] text-muted-foreground\">\n <SpinnerIcon size={15} /> Loading the conversation…\n </div>\n ) : (\n <div className=\"flex h-full flex-col\">\n {transcript.state.unavailable ? (\n <p className=\"mx-auto mt-4 max-w-[720px] rounded-lg border border-border bg-muted/50 px-4 py-2.5 text-[13px] text-muted-foreground\">\n {transcript.state.unavailable}\n </p>\n ) : null}\n {transcript.state.truncated ? (\n <LongChatNote\n loading={transcript.state.loadingEarlier === true}\n onEarlier={() => void transcript.loadEarlier()}\n />\n ) : null}\n {messages.length === 0 && !live ? (\n <div className=\"flex flex-1 items-center justify-center text-[13px] text-muted-foreground\">\n {session.origin === \"takeover\"\n ? \"You've taken over this chat. Send a message to continue it.\"\n : \"Nothing here yet.\"}\n </div>\n ) : (\n <ChatMessageList className=\"min-h-0 flex-1\" label={`Conversation: ${entry.title}`} />\n )}\n </div>\n )}\n </div>\n <div data-cs-composer className=\"mx-auto w-full max-w-[820px] px-4 pb-4\">\n {limited ? (\n <div className=\"mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]\">\n <AlertIcon size={15} className=\"mt-0.5 shrink-0 text-warning\" />\n <span>\n {limited.problem} {limited.fix}\n </span>\n </div>\n ) : null}\n {modelRefused && !blocked ? (\n <div\n className=\"mb-2 flex items-center gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]\"\n role=\"alert\"\n >\n <AlertIcon size={15} className=\"shrink-0 text-warning\" />\n <span className=\"min-w-0 flex-1 truncate\" title={run?.error ?? undefined}>\n {MODEL_UNAVAILABLE_LABEL}\n </span>\n <ModelPicker\n status={provider}\n value={{ model: session.model, effort: session.effort ?? null }}\n onChange={setOptions}\n />\n </div>\n ) : null}\n {blocked ? (\n <div className=\"mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]\">\n <AlertIcon size={15} className=\"mt-0.5 shrink-0 text-warning\" />\n <span>\n {blocked.problem} {blocked.fix}\n </span>\n </div>\n ) : null}\n {/* ALWAYS in the layout (hidden when idle): a line that came and\n went with each run moved the composer under the pointer. */}\n <div className=\"cs-activity\" role=\"status\" aria-live=\"polite\" data-idle={live ? undefined : true}>\n {live ? (\n <>\n <SpinnerIcon size={13} />\n <span className=\"truncate\">\n {run?.status === \"starting\"\n ? `Starting ${PROVIDER_LABEL[session.provider]}…`\n : (transcript.activity ?? \"Thinking…\")}\n </span>\n <span className=\"ml-auto shrink-0 text-[11px] opacity-70\">Esc to stop</span>\n </>\n ) : null}\n </div>\n {elsewhere ? (\n <div className=\"mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]\">\n <AlertIcon size={15} className=\"mt-0.5 shrink-0 text-warning\" />\n <span>\n {elsewhere.message} A message sent here would put a second agent on the same chat.\n </span>\n </div>\n ) : null}\n {session.queued.length > 0 ? (\n <ul className=\"mb-2 space-y-1.5\" aria-label=\"Queued messages\">\n {session.queued.map((text, index) => (\n <li key={`${index}-${text.slice(0, 16)}`} className=\"cs-queued\">\n <span className=\"cs-queued__label\">Queued · sends when this run finishes</span>\n <span className=\"cs-queued__text\">{text}</span>\n </li>\n ))}\n </ul>\n ) : null}\n <ChatComposer\n placeholder={`Message ${PROVIDER_LABEL[session.provider]}…`}\n autoFocus\n {...(blocked ? { held: { reason: `${blocked.problem} ${blocked.fix ?? \"\"}`.trim() } } : {})}\n />\n </div>\n </ChatProvider>\n </div>\n </section>\n {changesOpen ? (\n <ChangesPanel files={files} cwd={session.cwd} truncated={transcript.state.truncated} onClose={() => setChangesOpen(false)} />\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* Discovered chat preview */\n/* ------------------------------------------------------------------------ */\n\n/**\n * A read-only thread for the preview whose identity never changes, so a\n * refresh (the chat is live elsewhere and growing) updates the list in place\n * instead of remounting it and losing the reader's scroll.\n */\nfunction usePreviewThread(id: string, onSend: () => void) {\n const ref = useRef<{ messages: PreviewState[\"messages\"]; listeners: Set<() => void> }>({ messages: [], listeners: new Set() });\n const send = useRef(onSend);\n send.current = onSend;\n const thread = useMemo(\n () =>\n createExternalThreadSource({\n getSnapshot: () => ({ messages: ref.current.messages, status: \"idle\", conversationId: id }),\n subscribe: (listener) => {\n ref.current.listeners.add(listener);\n return () => {\n ref.current.listeners.delete(listener);\n };\n },\n // Read-only here: \"Ask again\" and \"Edit\" SAY so instead of doing nothing.\n onSubmit: () => send.current(),\n }),\n [id],\n );\n const set = useCallback((messages: PreviewState[\"messages\"]) => {\n ref.current.messages = messages;\n for (const listener of ref.current.listeners) listener();\n }, []);\n return [thread, set] as const;\n}\n\nfunction DiscoveredView(props: {\n session: DiscoveredSession | null;\n provider: CodingProvider;\n id: string;\n onTakenOver: (id: string) => void;\n changesOpen: boolean;\n setChangesOpen: (open: boolean) => void;\n}): ReactNode {\n const client = useCodingSessionsClient();\n const state = useCodingSessionsState();\n const show = useContext(ToastContext);\n const now = useMinuteClock();\n const [preview, setPreview] = useState<PreviewState>({ loading: true, messages: [], unavailable: null, truncated: false });\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [confirming, setConfirming] = useState(false);\n const [renaming, setRenaming] = useState(false);\n const [maxBytes, setMaxBytes] = useState<number | undefined>(undefined);\n const [readingEarlier, setReadingEarlier] = useState(false);\n const elsewhere = useLiveElsewhere(props.provider, props.id, props.session?.activeElsewhere ?? null);\n const files = useChangedFiles(preview.messages);\n const d = props.session;\n const [thread, setThreadMessages] = usePreviewThread(props.id, () =>\n show(\n d?.cwd\n ? `This chat is read-only until you take it over. Press Take over to continue it here.`\n : \"This chat is read-only here: it doesn't record its folder, so it can't be continued.\",\n ),\n );\n\n useEffect(() => {\n let cancelled = false;\n const read = (first: boolean) =>\n client.readPreview(props.provider, props.id, maxBytes).then((next) => {\n if (cancelled) return;\n setThreadMessages(next.messages);\n setPreview(next);\n if (first) setReadingEarlier(false);\n });\n if (maxBytes === undefined) setPreview({ loading: true, messages: [], unavailable: null, truncated: false });\n void read(true);\n // Live elsewhere: follow it, so the preview is not a stale snapshot.\n const timer = elsewhere ? setInterval(() => void read(false), 8000) : null;\n return () => {\n cancelled = true;\n if (timer) clearInterval(timer);\n };\n }, [client, props.provider, props.id, maxBytes, elsewhere !== null, setThreadMessages]);\n\n const notifier = useNotifier();\n const entry = discoveredEntry(\n d ?? { provider: props.provider, providerSessionId: props.id, cwd: null, title: \"Chat\", updatedAt: \"\", source: null, activeElsewhere: null },\n state.preferences,\n );\n\n // Validation offers, never blocks: a live chat asks first, then proceeds.\n const requestTakeover = () => {\n if (elsewhere) setConfirming(true);\n else void takeover();\n };\n const [choosingAgent, setChoosingAgent] = useState(false);\n const takeover = async (agent?: AgentSelection) => {\n if (!d) return;\n setConfirming(false);\n setBusy(true);\n setError(null);\n try {\n const taken = await client.takeover(d, agent);\n props.onTakenOver(taken.id);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <div className=\"flex min-w-0 flex-1\">\n <section className=\"flex min-w-0 flex-1 flex-col\" aria-label={entry.title}>\n <header className=\"@container/header flex items-center gap-2 border-b border-border px-5 pt-2.5 pb-2.5\">\n <ProviderMark provider={props.provider} size={22} />\n <div className=\"min-w-0 flex-1\">\n <HeaderTitle entry={entry} renaming={renaming} setRenaming={setRenaming} />\n <p className=\"flex items-center gap-1.5 truncate text-[12px] leading-4 text-muted-foreground\">\n <span>{PROVIDER_LABEL[props.provider]}</span>\n {d?.cwd ? (\n <>\n <span aria-hidden=\"true\">·</span>\n <FolderIcon size={12} />\n <span className=\"truncate\" title={d.cwd}>\n {prettyPath(d.cwd)}\n </span>\n </>\n ) : null}\n {d ? <span>· last active {relativeTime(d.updatedAt, now)}</span> : null}\n </p>\n </div>\n {files.length > 0 ? (\n <button\n type=\"button\"\n className=\"cs-chip-button\"\n onClick={() => props.setChangesOpen(!props.changesOpen)}\n aria-pressed={props.changesOpen}\n title=\"Files this chat changed\"\n >\n <FileIcon size={13} />\n {`${files.length} ${files.length === 1 ? \"file\" : \"files\"} changed`}\n </button>\n ) : null}\n {d?.cwd ? (\n <Button\n size=\"sm\"\n variant={elsewhere ? \"outline\" : \"default\"}\n onClick={requestTakeover}\n disabled={busy}\n className=\"gap-1.5\"\n title={elsewhere ? elsewhere.message : undefined}\n >\n {busy ? <SpinnerIcon size={13} /> : elsewhere ? <AlertIcon size={14} className=\"text-warning\" /> : <HandoffIcon size={14} />}\n {elsewhere ? \"Take over anyway…\" : \"Take over\"}\n </Button>\n ) : null}\n {d?.cwd && !elsewhere ? (\n <Button size=\"sm\" variant=\"outline\" onClick={() => setChoosingAgent(true)} disabled={busy}>\n Continue with agent…\n </Button>\n ) : null}\n <ChooseAgentDialog\n transport={client.transport}\n open={choosingAgent}\n onOpenChange={setChoosingAgent}\n title=\"Continue with an agent\"\n action=\"Take over with this agent\"\n onConfirm={(agent) => takeover(agent)}\n />\n {d ? <HeaderMenu entry={entry} onRename={() => setRenaming(true)} /> : null}\n </header>\n {elsewhere ? (\n <div role=\"status\" className=\"flex items-start gap-2 border-b border-warning/40 bg-warning/10 px-5 py-2.5 text-[13px]\">\n <AlertIcon size={15} className=\"mt-0.5 shrink-0 text-warning\" />\n <span>\n <span className=\"font-medium\">{elsewhere.message}</span> Taking it over now would put two agents on the same\n chat, and they could overwrite each other's work. Finish or stop it there first if you can. This preview\n follows it as it runs.\n </span>\n </div>\n ) : null}\n <Dialog open={confirming} onOpenChange={setConfirming}>\n <DialogContent className=\"max-w-[460px]\">\n <DialogHeader>\n <DialogTitle>This chat is running right now in {PROVIDER_LABEL[props.provider]}</DialogTitle>\n <DialogDescription>\n {elsewhere?.message} If you take it over, two agents will work in the same conversation at once and may\n overwrite each other's changes.\n </DialogDescription>\n </DialogHeader>\n <DialogFooter>\n <Button variant=\"ghost\" onClick={() => setConfirming(false)}>\n Cancel\n </Button>\n <Button variant=\"destructive\" onClick={() => void takeover()}>\n Take over anyway\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n {error ? (\n <p className=\"border-b border-destructive/30 bg-destructive/10 px-5 py-2 text-[13px] text-destructive\">{error}</p>\n ) : null}\n {d && !d.cwd ? (\n <p className=\"border-b border-border bg-muted/50 px-5 py-2 text-[13px] text-muted-foreground\">\n This chat doesn't record which folder it ran in, so it can't be continued from here.\n </p>\n ) : null}\n <div className=\"mx-chat flex min-h-0 flex-1 flex-col\">\n {preview.loading ? (\n <div className=\"flex flex-1 items-center justify-center gap-2 text-[13px] text-muted-foreground\">\n <SpinnerIcon size={15} /> Reading this chat…\n </div>\n ) : preview.unavailable ? (\n <div className=\"flex flex-1 items-center justify-center px-6 text-center text-[13px] text-muted-foreground\">\n {preview.unavailable}\n </div>\n ) : (\n <ChatProvider thread={thread} ports={{ notifier, toolLabel: friendlyToolName }}>\n {preview.truncated ? (\n <LongChatNote\n loading={readingEarlier}\n onEarlier={() => {\n setReadingEarlier(true);\n setMaxBytes((m) => (m ?? 24 * 1024 * 1024) * 4);\n }}\n />\n ) : null}\n <ChatMessageList className=\"min-h-0 flex-1\" label=\"Chat preview\" />\n </ChatProvider>\n )}\n {d?.cwd ? (\n <div className=\"border-t border-border bg-muted/30 px-5 py-3 text-center text-[13px] text-muted-foreground\">\n This chat was started in {PROVIDER_LABEL[props.provider]}.{\" \"}\n <button type=\"button\" className=\"font-medium text-foreground underline-offset-4 hover:underline\" onClick={requestTakeover}>\n Take it over\n </button>{\" \"}\n to continue it here — it stays in your {PROVIDER_LABEL[props.provider]} history too.\n </div>\n ) : null}\n </div>\n </section>\n {props.changesOpen && files.length > 0 ? (\n <ChangesPanel files={files} cwd={d?.cwd ?? null} truncated={preview.truncated} onClose={() => props.setChangesOpen(false)} />\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* New session */\n/* ------------------------------------------------------------------------ */\n\nfunction ProviderCard(props: { status: ProviderStatus; selected: boolean; onSelect: () => void }): ReactNode {\n const ready = props.status.ready;\n return (\n <button\n type=\"button\"\n onClick={props.onSelect}\n aria-pressed={props.selected}\n className={cn(\n \"flex flex-1 flex-col gap-1.5 rounded-xl border px-3.5 py-3 text-left transition-colors\",\n props.selected ? \"border-primary bg-primary/5 ring-1 ring-primary\" : \"border-border hover:bg-accent/50\",\n )}\n >\n <span className=\"flex items-center gap-2\">\n <ProviderMark provider={props.status.provider} size={18} />\n <span className=\"text-[13.5px] font-semibold\">{props.status.label}</span>\n </span>\n {ready ? (\n <span className=\"flex items-center gap-1 text-[12px] text-success\">\n <CheckIcon size={13} />\n {props.status.billing === \"subscription\"\n ? `Signed in${props.status.plan ? ` · ${props.status.plan} plan` : \"\"}`\n : \"Signed in with an API key (billed per use)\"}\n </span>\n ) : (\n <span className=\"flex items-start gap-1 text-[12px] leading-4 text-warning\">\n <AlertIcon size={13} className=\"mt-px shrink-0\" />\n {props.status.problem}\n </span>\n )}\n {props.status.quota.filter((w) => w.usedPercent !== null).length > 0 ? (\n <span className=\"text-[11.5px] leading-4 text-muted-foreground\">\n {props.status.quota\n .filter((w) => w.usedPercent !== null)\n .map((w) => `${w.label}: ${w.usedPercent}% used`)\n .join(\" · \")}\n </span>\n ) : null}\n </button>\n );\n}\n\nfunction FieldError({ id, children }: { id: string; children: ReactNode }): ReactNode {\n return (\n <p id={id} role=\"alert\" className=\"flex items-start gap-1.5 text-[12.5px] leading-5 text-destructive\">\n <AlertIcon size={14} className=\"mt-0.5 shrink-0\" />\n <span>{children}</span>\n </p>\n );\n}\n\nfunction NewSessionDialog(props: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onStarted: (sessionId: string) => void;\n}): ReactNode {\n const client = useCodingSessionsClient();\n const state = useCodingSessionsState();\n const now = useMinuteClock();\n const [provider, setProvider] = useState<CodingProvider>(\"claude\");\n const [folder, setFolder] = useState(\"\");\n const [choice, setChoice] = useState<ModelChoice>({ model: null, effort: null });\n const [prompt, setPrompt] = useState(\"\");\n const [errors, setErrors] = useState<NewSessionErrors>({});\n const [problem, setProblem] = useState<string | null>(null);\n const [starting, setStarting] = useState(false);\n const [creating, setCreating] = useState(false);\n const [agent, setAgent] = useState<AgentSelection | null>(null);\n const [agentDetails, setAgentDetails] = useState<AgentDetails | null>(null);\n const [agentMissing, setAgentMissing] = useState<string | null>(null);\n const promptRef = useRef<HTMLTextAreaElement | null>(null);\n const folderRef = useRef<HTMLInputElement | null>(null);\n const agentRef = useRef<HTMLFieldSetElement | null>(null);\n\n useEffect(() => {\n if (!props.open) return;\n setProblem(null);\n setErrors({});\n void client.refreshProviders();\n void client.refreshFolders();\n }, [props.open, client]);\n\n useEffect(() => {\n if (!folder && state.folders.data[0]?.exists) setFolder(state.folders.data[0].path);\n }, [state.folders.data, folder]);\n\n useEffect(() => {\n const ready = state.providers.data.filter((p) => p.ready);\n const current = state.providers.data.find((p) => p.provider === provider);\n if (current && !current.ready && ready[0]) setProvider(ready[0].provider);\n // Only when the statuses first arrive.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.providers.loadedAt]);\n\n const selected = state.providers.data.find((p) => p.provider === provider) ?? null;\n\n const focusField = (field: NewSessionField | null) => {\n if (field === \"prompt\") promptRef.current?.focus();\n else if (field === \"folder\") folderRef.current?.focus();\n else if (field === \"agent\") agentRef.current?.querySelector<HTMLButtonElement>(\"button\")?.focus();\n };\n\n const start = async () => {\n if (starting) return;\n setProblem(null);\n const found = await validateNewSession({\n provider: selected,\n folder,\n prompt,\n checkFolder: (path) => client.transport.call(\"checkFolder\", path),\n });\n setErrors(found);\n const first = firstInvalidField(found);\n if (first) {\n focusField(first);\n return;\n }\n const missing = missingRequiredVariable(agentDetails, agent);\n setAgentMissing(missing);\n if (missing) {\n document.getElementById(`cs-agent-var-${missing}`)?.focus();\n return;\n }\n setStarting(true);\n try {\n const result = await client.start({\n provider,\n cwd: folder.trim(),\n prompt,\n model: choice.model,\n effort: choice.effort,\n ...(agent ? { agent } : {}),\n });\n setPrompt(\"\");\n props.onStarted(result.session.id);\n } catch (error) {\n setProblem(error instanceof Error ? error.message : String(error));\n } finally {\n setStarting(false);\n }\n };\n\n const createFolder = async () => {\n if (!errors.createFolder) return;\n setCreating(true);\n try {\n const made = await client.transport.call(\"createFolder\", errors.createFolder);\n setFolder(made.path);\n setErrors((e) => {\n const next = { ...e };\n delete next.folder;\n delete next.createFolder;\n return next;\n });\n void client.refreshFolders();\n folderRef.current?.focus();\n } catch (error) {\n setErrors((e) => ({ ...e, folder: `Couldn't create it: ${error instanceof Error ? error.message : String(error)}` }));\n } finally {\n setCreating(false);\n }\n };\n\n const clear = (field: NewSessionField) =>\n setErrors((e) => {\n if (e[field] === undefined) return e;\n const next = { ...e };\n delete next[field];\n if (field === \"folder\") delete next.createFolder;\n return next;\n });\n\n return (\n <Dialog open={props.open} onOpenChange={props.onOpenChange}>\n <DialogContent className=\"max-w-[560px]\">\n <DialogHeader>\n <DialogTitle>New coding session</DialogTitle>\n <DialogDescription>\n Runs on your own {provider === \"claude\" ? \"Claude\" : \"ChatGPT\"} sign-in, in a folder on this computer.\n </DialogDescription>\n </DialogHeader>\n\n <form\n noValidate\n onSubmit={(e) => {\n e.preventDefault();\n void start();\n }}\n className=\"flex min-h-0 flex-col\"\n >\n {/* The body scrolls; the footer never hides a message below the fold. */}\n <div className=\"cs-dialog-body space-y-5 py-1 pr-1\">\n <fieldset className=\"space-y-2\" ref={agentRef}>\n <legend className=\"mb-2 text-[12.5px] font-medium\">Agent</legend>\n {state.providers.loading && state.providers.loadedAt === null ? (\n <div className=\"flex gap-2\">\n <div className=\"cs-skeleton h-[68px] flex-1 rounded-xl\" />\n <div className=\"cs-skeleton h-[68px] flex-1 rounded-xl\" />\n </div>\n ) : state.providers.error ? (\n <p className=\"text-[12.5px] text-destructive\">{state.providers.error}</p>\n ) : (\n <div className=\"flex gap-2\">\n {state.providers.data.map((p) => (\n <ProviderCard\n key={p.provider}\n status={p}\n selected={p.provider === provider}\n onSelect={() => {\n if (p.provider !== provider) setChoice({ model: null, effort: null });\n setProvider(p.provider);\n clear(\"agent\");\n }}\n />\n ))}\n </div>\n )}\n {errors.agent ? (\n <FieldError id=\"cs-err-agent\">{errors.agent}</FieldError>\n ) : selected && !selected.ready && selected.fix ? (\n <p className=\"text-[12px] leading-4 text-muted-foreground\">\n {selected.fix}\n {selected.installed && selected.loggedIn ? \" You can still try — the run will say if it's still blocked.\" : \"\"}\n </p>\n ) : null}\n </fieldset>\n\n <fieldset className=\"space-y-2\">\n <legend className=\"mb-2 text-[12.5px] font-medium\">AI Matrx agent</legend>\n <AgentField\n transport={client.transport}\n open={props.open}\n value={agent}\n onChange={(next) => {\n setAgent(next);\n setAgentMissing(null);\n }}\n missing={agentMissing}\n onDetails={setAgentDetails}\n />\n </fieldset>\n\n <fieldset className=\"space-y-2\">\n <legend className=\"mb-2 text-[12.5px] font-medium\">Folder</legend>\n {state.folders.data.length > 0 ? (\n <div className=\"max-h-[132px] space-y-0.5 overflow-y-auto rounded-lg border border-border p-1\">\n {state.folders.data.map((f) => (\n <button\n type=\"button\"\n key={f.path}\n onClick={() => {\n setFolder(f.path);\n clear(\"folder\");\n }}\n disabled={!f.exists}\n title={f.exists ? f.path : `${f.path} no longer exists`}\n className={cn(\n \"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-[12.5px]\",\n folder === f.path ? \"bg-accent text-accent-foreground\" : \"hover:bg-accent/50\",\n !f.exists && \"opacity-50\",\n )}\n >\n <FolderIcon size={14} className=\"shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 flex-1 truncate\">{prettyPath(f.path)}</span>\n <span className=\"shrink-0 text-[11px] text-muted-foreground\">\n {f.exists ? relativeTime(f.lastUsedAt, now) : \"missing\"}\n </span>\n </button>\n ))}\n </div>\n ) : state.folders.loading ? (\n <div className=\"cs-skeleton h-10 rounded-lg\" />\n ) : null}\n <Input\n ref={folderRef}\n value={folder}\n onChange={(e) => {\n setFolder(e.target.value);\n clear(\"folder\");\n }}\n placeholder=\"Or type a folder path, like ~/code/my-app\"\n aria-label=\"Folder path\"\n aria-invalid={errors.folder ? true : undefined}\n aria-describedby={errors.folder ? \"cs-err-folder\" : undefined}\n spellCheck={false}\n />\n {errors.folder ? (\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-1\">\n <FieldError id=\"cs-err-folder\">{errors.folder}</FieldError>\n {errors.createFolder ? (\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={() => void createFolder()} disabled={creating} className=\"gap-1.5\">\n {creating ? <SpinnerIcon size={13} /> : <FolderIcon size={13} />}\n Create this folder\n </Button>\n ) : null}\n </div>\n ) : null}\n </fieldset>\n\n <fieldset className=\"space-y-2\">\n <legend className=\"mb-2 text-[12.5px] font-medium\">What should it do?</legend>\n <Textarea\n ref={promptRef}\n value={prompt}\n onChange={(e) => {\n setPrompt(e.target.value);\n clear(\"prompt\");\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n void start();\n }\n }}\n placeholder=\"Describe the change, the bug, or the question…\"\n rows={4}\n aria-label=\"First message\"\n aria-invalid={errors.prompt ? true : undefined}\n aria-describedby={errors.prompt ? \"cs-err-prompt\" : undefined}\n />\n {errors.prompt ? <FieldError id=\"cs-err-prompt\">{errors.prompt}</FieldError> : null}\n </fieldset>\n\n <fieldset className=\"space-y-2\">\n <legend className=\"mb-2 text-[12.5px] font-medium\">Model and thinking effort</legend>\n <ModelPicker status={selected} value={choice} onChange={setChoice} appearance=\"field\" />\n <p className=\"text-[11.5px] leading-4 text-muted-foreground\">\n Default is {defaultModelWords(selected)}. You can change it later from the chat's header.\n </p>\n </fieldset>\n\n {problem ? <FieldError id=\"cs-err-start\">{problem}</FieldError> : null}\n </div>\n\n <DialogFooter className=\"pt-4\">\n <Button type=\"button\" variant=\"ghost\" onClick={() => props.onOpenChange(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={starting} className=\"gap-1.5\">\n {starting ? <SpinnerIcon size={14} /> : null}\n {starting ? \"Starting…\" : \"Start session\"}\n {!starting ? <kbd className=\"cs-kbd\">⌘↵</kbd> : null}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* Home (nothing selected) */\n/* ------------------------------------------------------------------------ */\n\nfunction Home({ onNew }: { onNew: () => void }): ReactNode {\n const state = useCodingSessionsState();\n return (\n <section className=\"flex flex-1 items-center justify-center px-6\">\n <div className=\"w-full max-w-[460px] text-center\">\n <span className=\"mx-auto mb-4 flex h-11 w-11 items-center justify-center rounded-2xl bg-primary/10 text-primary\">\n <ChatBubbleIcon size={22} />\n </span>\n <h1 className=\"text-[15px] font-semibold leading-5 tracking-[-0.01em]\">Drive Claude Code and Codex from here</h1>\n <p className=\"mx-auto mt-2 max-w-[400px] text-[13.5px] leading-6 text-muted-foreground\">\n Start a session in any folder, or pick up a chat you began somewhere else. Everything runs on your own\n subscriptions — no API keys.\n </p>\n <Button className=\"mt-5 gap-1.5\" onClick={onNew}>\n <PlusIcon size={15} />\n New session\n </Button>\n <p className=\"mt-3 text-[12px] text-muted-foreground\">\n <kbd className=\"cs-kbd\">⌥⌘N</kbd> new session · <kbd className=\"cs-kbd\">⌘K</kbd> search your chats ·{\" \"}\n <kbd className=\"cs-kbd\">⌘/</kbd> all shortcuts\n </p>\n <div className=\"mt-6 flex flex-wrap justify-center gap-2 text-left\">\n {state.providers.data.map((p) => (\n <div\n key={p.provider}\n data-provider-card={p.provider}\n title={p.installed && p.version ? [binaryWords(p), newerWords(p) ?? p.binary?.path].filter(Boolean).join(\" · \") : undefined}\n className=\"flex w-[260px] items-start gap-2.5 rounded-lg border border-border bg-card px-3 py-2.5\"\n >\n <ProviderMark provider={p.provider} size={16} />\n <div className=\"min-w-0 flex-1 leading-5\">\n <span className=\"block truncate text-[14px] font-semibold\">{p.label}</span>\n {/* Two lines: the name, then one 12px status line; the version lives in the tooltip. */}\n {p.ready ? (\n <span className=\"block truncate text-[12px] text-muted-foreground\">\n Ready{p.plan ? ` on your ${p.plan} plan` : \"\"}\n {p.billing === \"api\" ? \" (API key, billed per use)\" : \"\"}\n </span>\n ) : (\n <span className=\"block text-[12px] text-muted-foreground\">\n {p.problem} {p.fix}\n </span>\n )}\n </div>\n {p.ready ? (\n <CheckIcon size={15} className=\"mt-0.5 text-success\" />\n ) : (\n <AlertIcon size={15} className=\"mt-0.5 text-warning\" />\n )}\n </div>\n ))}\n </div>\n </div>\n </section>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* The app */\n/* ------------------------------------------------------------------------ */\n\ninterface ToastHandle {\n text: string | null;\n /** The session a run notice is about; null for other notices. */\n sessionId: string | null;\n show: (text: string, sessionId?: string | null) => void;\n dismiss: () => void;\n}\n\nfunction useToast(): ToastHandle {\n const [current, setCurrent] = useState<{ text: string; sessionId: string | null } | null>(null);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(() => () => {\n if (timer.current) clearTimeout(timer.current);\n }, []);\n const show = useCallback((next: string, sessionId: string | null = null) => {\n setCurrent({ text: next, sessionId });\n if (timer.current) clearTimeout(timer.current);\n timer.current = setTimeout(() => setCurrent(null), 6000);\n }, []);\n const dismiss = useCallback(() => {\n if (timer.current) clearTimeout(timer.current);\n setCurrent(null);\n }, []);\n return { text: current?.text ?? null, sessionId: current?.sessionId ?? null, show, dismiss };\n}\n\n/** Bottom-right of the chat pane, above the composer when one is on screen. */\nfunction Toast({ text }: { text: string | null }): ReactNode {\n const ref = useRef<HTMLDivElement | null>(null);\n useLayoutEffect(() => {\n const el = ref.current;\n const pane = el?.parentElement;\n if (!el || !pane) return;\n const composer = pane.querySelector(\"[data-cs-composer]\");\n const gap = composer ? pane.getBoundingClientRect().bottom - composer.getBoundingClientRect().top + 8 : 20;\n el.style.setProperty(\"--cs-toast-bottom\", `${Math.max(20, Math.round(gap))}px`);\n }, [text]);\n if (!text) return null;\n return (\n <div ref={ref} role=\"status\" data-cs-toast className=\"cs-toast\">\n {text}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* Sidebar width, collapse, shortcuts, finished-run notices */\n/* ------------------------------------------------------------------------ */\n\nconst SIDEBAR_DEFAULT = 300;\nconst SIDEBAR_MIN = 220;\nconst SIDEBAR_MAX = 560;\n\nfunction clampWidth(n: number): number {\n return Math.round(Math.min(SIDEBAR_MAX, Math.max(SIDEBAR_MIN, n)));\n}\n\nfunction useSidebarLayout(): {\n width: number;\n setWidth: (n: number) => void;\n collapsed: boolean;\n setCollapsed: (v: boolean) => void;\n} {\n const [width, setWidthState] = useState(() => {\n try {\n const n = Number(localStorage.getItem(\"coding-sessions.sidebar-width\"));\n return Number.isFinite(n) && n > 0 ? clampWidth(n) : SIDEBAR_DEFAULT;\n } catch {\n return SIDEBAR_DEFAULT;\n }\n });\n const [collapsed, setCollapsedState] = useState(() => {\n try {\n return localStorage.getItem(\"coding-sessions.sidebar-collapsed\") === \"1\";\n } catch {\n return false;\n }\n });\n const setWidth = useCallback((n: number) => {\n const next = clampWidth(n);\n setWidthState(next);\n try {\n localStorage.setItem(\"coding-sessions.sidebar-width\", String(next));\n } catch {\n /* this visit only */\n }\n }, []);\n const setCollapsed = useCallback((v: boolean) => {\n setCollapsedState(v);\n try {\n localStorage.setItem(\"coding-sessions.sidebar-collapsed\", v ? \"1\" : \"0\");\n } catch {\n /* this visit only */\n }\n }, []);\n return { width, setWidth, collapsed, setCollapsed };\n}\n\nfunction Resizer(props: { width: number; setWidth: (n: number) => void }): ReactNode {\n const [dragging, setDragging] = useState(false);\n return (\n <div className={cn(\"cs-resizer\", dragging && \"cs-resizer--dragging\")}>\n <button\n type=\"button\"\n className=\"cs-resizer__grip\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label=\"Resize the sidebar\"\n aria-valuenow={props.width}\n aria-valuemin={SIDEBAR_MIN}\n aria-valuemax={SIDEBAR_MAX}\n title=\"Drag to resize · double-click to reset\"\n onDoubleClick={() => props.setWidth(SIDEBAR_DEFAULT)}\n onKeyDown={(e) => {\n if (e.key === \"ArrowLeft\") props.setWidth(props.width - 16);\n if (e.key === \"ArrowRight\") props.setWidth(props.width + 16);\n }}\n onPointerDown={(e) => {\n e.preventDefault();\n const startX = e.clientX;\n const startWidth = props.width;\n setDragging(true);\n document.body.style.cursor = \"col-resize\";\n document.body.style.userSelect = \"none\";\n const move = (ev: PointerEvent) => props.setWidth(startWidth + ev.clientX - startX);\n const up = () => {\n setDragging(false);\n document.body.style.cursor = \"\";\n document.body.style.userSelect = \"\";\n window.removeEventListener(\"pointermove\", move);\n window.removeEventListener(\"pointerup\", up);\n };\n window.addEventListener(\"pointermove\", move);\n window.addEventListener(\"pointerup\", up);\n }}\n />\n </div>\n );\n}\n\nconst SHORTCUTS: { keys: string; what: string }[] = [\n { keys: \"⌘K\", what: \"Search chats\" },\n { keys: \"⌥⌘N\", what: \"New session\" },\n { keys: \"Enter\", what: \"Send (Shift+Enter for a new line)\" },\n { keys: \"Esc\", what: \"Stop the run in the open chat\" },\n { keys: \"⌘B\", what: \"Show or hide the sidebar\" },\n { keys: \"⌥↑ / ⌥↓\", what: \"Previous or next chat in the list\" },\n { keys: \"⌘/\", what: \"These shortcuts\" },\n];\n\nfunction ShortcutsDialog(props: { open: boolean; onOpenChange: (open: boolean) => void }): ReactNode {\n return (\n <Dialog open={props.open} onOpenChange={props.onOpenChange}>\n <DialogContent className=\"max-w-[420px]\">\n <DialogHeader>\n <DialogTitle>Keyboard shortcuts</DialogTitle>\n <DialogDescription>Ctrl works in place of ⌘ on Windows and Linux.</DialogDescription>\n </DialogHeader>\n <dl className=\"divide-y divide-border text-[13px]\">\n {SHORTCUTS.map((s) => (\n <div key={s.keys} className=\"flex items-center justify-between gap-4 py-2\">\n <dt className=\"text-muted-foreground\">{s.what}</dt>\n <dd>\n <kbd className=\"rounded border border-border px-1.5 py-0.5 font-sans text-[12px]\">{s.keys}</kbd>\n </dd>\n </div>\n ))}\n </dl>\n </DialogContent>\n </Dialog>\n );\n}\n\nconst BASE_TITLE = \"Coding sessions\";\n\n/**\n * A run that ends while you are looking elsewhere: a count in the tab's title\n * until you come back, a desktop notification when you allowed them, and a\n * toast when it was a different chat than the one on screen.\n */\nfunction useRunFinishedNotices(openSessionId: string | null, toast: ToastHandle): void {\n const { show, dismiss, sessionId: toastSession } = toast;\n const state = useCodingSessionsState();\n // A notice about a run never outlives what it says: it goes once that chat is opened, or once\n // the chat runs again (the pane would otherwise show \"Starting\" under \"finished\").\n useEffect(() => {\n if (!toastSession) return;\n const run = state.runs[toastSession];\n if (openSessionId === toastSession || (run && (run.status === \"starting\" || run.status === \"running\"))) dismiss();\n }, [toastSession, openSessionId, state.runs, dismiss]);\n const client = useCodingSessionsClient();\n const unseen = useRef(0);\n const openRef = useRef(openSessionId);\n openRef.current = openSessionId;\n useEffect(() => {\n const reset = () => {\n if (document.visibilityState === \"visible\") {\n unseen.current = 0;\n document.title = BASE_TITLE;\n }\n };\n document.addEventListener(\"visibilitychange\", reset);\n const off = client.onRunFinished(({ run, session }) => {\n const title = session?.title ?? \"A session\";\n const outcome = run.status === \"completed\" ? \"finished\" : run.status === \"failed\" ? \"failed\" : \"was stopped\";\n const sentence = `${PROVIDER_LABEL[run.provider]} ${outcome}: ${title}`;\n if (document.visibilityState === \"hidden\") {\n unseen.current += 1;\n document.title = `(${unseen.current}) ${BASE_TITLE}`;\n if (typeof Notification !== \"undefined\" && Notification.permission === \"granted\") {\n const note = new Notification(sentence, run.error ? { tag: run.runId, body: runErrorLabel(run.error) } : { tag: run.runId });\n note.onclick = () => {\n window.focus();\n location.hash = `#s/${run.sessionId}`;\n note.close();\n };\n }\n } else if (openRef.current !== run.sessionId && run.status !== \"stopped\") {\n show(sentence, run.sessionId);\n }\n });\n return () => {\n off();\n document.removeEventListener(\"visibilitychange\", reset);\n };\n }, [client, show]);\n}\n\nfunction NotifyToggle(): ReactNode {\n const supported = typeof Notification !== \"undefined\";\n const [permission, setPermission] = useState(supported ? Notification.permission : \"denied\");\n if (!supported || permission === \"granted\") return null;\n return (\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => void Notification.requestPermission().then(setPermission)}\n aria-label={\n permission === \"denied\"\n ? \"Notifications are blocked for this page in your browser's site settings\"\n : \"Notify me when a run finishes\"\n }\n title={permission === \"denied\" ? \"Notifications are blocked in your browser's site settings\" : \"Notify me when a run finishes\"}\n disabled={permission === \"denied\"}\n >\n <BellIcon size={14} />\n </button>\n );\n}\n\nfunction isTyping(target: EventTarget | null): boolean {\n const el = target as HTMLElement | null;\n if (!el) return false;\n return el.isContentEditable || el.tagName === \"INPUT\" || el.tagName === \"TEXTAREA\" || el.tagName === \"SELECT\";\n}\n\nfunction Shell(): ReactNode {\n const client = useCodingSessionsClient();\n const state = useCodingSessionsState();\n const [selection, setSelection] = useState<Selection>(readHash);\n const [newOpen, setNewOpen] = useState(false);\n const [shortcutsOpen, setShortcutsOpen] = useState(false);\n const [changesOpen, setChangesOpen] = useState(false);\n const [found, setFound] = useState<Record<string, DiscoveredSession>>({});\n const [theme, setTheme] = useTheme();\n const toast = useToast();\n const showToast = toast.show;\n const layout = useSidebarLayout();\n const searchRef = useRef<HTMLInputElement | null>(null);\n\n const select = useCallback((next: Selection) => {\n setSelection(next);\n writeHash(next);\n }, []);\n\n useEffect(() => {\n const onHash = () => setSelection(readHash());\n window.addEventListener(\"hashchange\", onHash);\n return () => window.removeEventListener(\"hashchange\", onHash);\n }, []);\n\n useRunFinishedNotices(selection.kind === \"session\" ? selection.id : null, toast);\n\n const session =\n selection.kind === \"session\" ? (state.sessions.data.find((s) => s.id === selection.id) ?? null) : null;\n const discovered =\n selection.kind === \"discovered\"\n ? (state.discovered.data.find((d) => d.providerSessionId === selection.id) ??\n found[`${selection.provider}:${selection.id}`] ??\n null)\n : null;\n const run = session ? state.runs[session.id] : undefined;\n const live = run !== undefined && !isTerminalRunStatus(run.status);\n\n // The list order the sidebar shows, for ⌥↑ / ⌥↓.\n const order = useMemo((): Selection[] => {\n const known = new Set(state.sessions.data.map((s) => s.providerSessionId).filter(Boolean));\n return [\n ...state.sessions.data.map((s): Selection => ({ kind: \"session\", id: s.id })),\n ...state.discovered.data\n .filter((d) => !known.has(d.providerSessionId))\n .map((d): Selection => ({ kind: \"discovered\", provider: d.provider, id: d.providerSessionId })),\n ];\n }, [state.sessions.data, state.discovered.data]);\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n const mod = e.metaKey || e.ctrlKey;\n const key = e.key.toLowerCase();\n if (mod && !e.shiftKey && !e.altKey && key === \"k\") {\n e.preventDefault();\n layout.setCollapsed(false);\n requestAnimationFrame(() => {\n searchRef.current?.focus();\n searchRef.current?.select();\n });\n return;\n }\n if ((mod && e.altKey && (key === \"n\" || e.code === \"KeyN\")) || (mod && e.shiftKey && key === \"o\")) {\n e.preventDefault();\n setNewOpen(true);\n return;\n }\n if (mod && !e.shiftKey && !e.altKey && key === \"b\") {\n e.preventDefault();\n layout.setCollapsed(!layout.collapsed);\n return;\n }\n if (mod && key === \"/\") {\n e.preventDefault();\n setShortcutsOpen(true);\n return;\n }\n if (e.altKey && !mod && (e.key === \"ArrowUp\" || e.key === \"ArrowDown\")) {\n const at = order.findIndex((o) =>\n o.kind === \"session\" && selection.kind === \"session\"\n ? o.id === selection.id\n : o.kind === \"discovered\" && selection.kind === \"discovered\" && o.id === selection.id,\n );\n const next = order[e.key === \"ArrowUp\" ? Math.max(0, at - 1) : Math.min(order.length - 1, at + 1)];\n if (next) {\n e.preventDefault();\n select(next);\n }\n return;\n }\n if (e.key === \"Escape\" && live && run && !e.defaultPrevented) {\n // Never while a dialog or menu is open (Esc closes those), and never\n // from the search box (Esc clears it).\n if (document.querySelector('[role=\"dialog\"], [role=\"menu\"], [data-radix-popper-content-wrapper]')) return;\n if (e.target === searchRef.current) return;\n e.preventDefault();\n void client.stop(run.runId);\n showToast(\"Stopping…\");\n return;\n }\n if (e.key === \"?\" && !isTyping(e.target)) {\n setShortcutsOpen(true);\n }\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [client, layout, live, run, order, selection, select, showToast]);\n\n let main: ReactNode;\n if (selection.kind === \"session\") {\n main = session ? (\n <SessionView key={session.id} session={session} changesOpen={changesOpen} setChangesOpen={setChangesOpen} />\n ) : state.sessions.loadedAt === null ? (\n <div className=\"flex flex-1 items-center justify-center gap-2 text-[13px] text-muted-foreground\">\n <SpinnerIcon size={15} /> Loading…\n </div>\n ) : (\n <div className=\"flex flex-1 items-center justify-center text-[13px] text-muted-foreground\">\n That session is not in the list anymore.\n </div>\n );\n } else if (selection.kind === \"discovered\") {\n main = (\n <DiscoveredView\n key={`${selection.provider}:${selection.id}`}\n session={discovered}\n provider={selection.provider}\n id={selection.id}\n onTakenOver={(id) => select({ kind: \"session\", id })}\n changesOpen={changesOpen}\n setChangesOpen={setChangesOpen}\n />\n );\n } else {\n main = <Home onNew={() => setNewOpen(true)} />;\n }\n\n return (\n <ToastContext.Provider value={showToast}>\n <div className=\"cs-app flex h-full flex-col bg-background text-foreground\">\n <ConnectionBanner />\n <div className=\"flex min-h-0 flex-1\">\n {layout.collapsed ? (\n <div className=\"flex flex-col items-center gap-1 border-r border-border bg-muted/30 px-1.5 py-3\">\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => layout.setCollapsed(false)}\n aria-label=\"Show the sidebar (⌘B)\"\n title=\"Show sidebar ⌘B\"\n >\n <SidebarIcon size={15} />\n </button>\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => setNewOpen(true)}\n aria-label=\"New session\"\n title=\"New session ⌥⌘N\"\n >\n <PlusIcon size={15} />\n </button>\n </div>\n ) : (\n <>\n <Sidebar\n selection={selection}\n select={select}\n onNew={() => setNewOpen(true)}\n onCollapse={() => layout.setCollapsed(true)}\n width={layout.width}\n searchRef={searchRef}\n onFound={(d) => setFound((f) => ({ ...f, [`${d.provider}:${d.providerSessionId}`]: d }))}\n footer={\n <ProvidersFooter\n theme={theme}\n setTheme={setTheme}\n extra={\n <>\n <NotifyToggle />\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => setShortcutsOpen(true)}\n aria-label=\"Keyboard shortcuts (⌘/)\"\n title=\"Keyboard shortcuts ⌘/\"\n >\n <KeyboardIcon size={14} />\n </button>\n </>\n }\n />\n }\n />\n <Resizer width={layout.width} setWidth={layout.setWidth} />\n </>\n )}\n <main className=\"relative flex min-w-0 flex-1\">\n {main}\n <Toast text={toast.text} />\n </main>\n </div>\n <NewSessionDialog\n open={newOpen}\n onOpenChange={setNewOpen}\n onStarted={(id) => {\n setNewOpen(false);\n select({ kind: \"session\", id });\n }}\n />\n <ShortcutsDialog open={shortcutsOpen} onOpenChange={setShortcutsOpen} />\n </div>\n </ToastContext.Provider>\n );\n}\n\nexport interface CodingSessionsAppProps {\n transport: CodingSessionsTransport;\n}\n\n/** The whole product screen. Mount it full-height. */\nexport function CodingSessionsApp({ transport }: CodingSessionsAppProps): ReactNode {\n return (\n <CodingSessionsProvider transport={transport}>\n <Shell />\n </CodingSessionsProvider>\n );\n}\n","/**\n * The public contract of `@ai-matrx/coding-sessions`, shared by the engine\n * (Node), the local host (Node) and the UI (browser). Pure types — nothing here\n * touches Node or the DOM, and every value is JSON-serializable because it\n * crosses a transport (WebSocket today, desktop IPC later).\n */\n\nimport type { JsonValue } from \"@ai-matrx/agents/portable\";\n\n/** The coding agents this package drives. \"coding session\" is the canonical\n * platform term (chat.coding_session, the Coding Session Bridge). */\nexport type CodingProvider = \"claude\" | \"codex\";\n\nexport const CODING_PROVIDERS: readonly CodingProvider[] = [\"claude\", \"codex\"];\n\nexport const PROVIDER_LABEL: Record<CodingProvider, string> = {\n claude: \"Claude Code\",\n codex: \"Codex\",\n};\n\nexport type Billing = \"subscription\" | \"api\" | \"unknown\";\n\n/** Where the CLI a provider runs came from. */\nexport type BinarySource = \"desktop-app\" | \"path\" | \"npm-global\" | \"configured\";\n\n/** The exact CLI runs use: the newest copy on this computer (or the host's pick). */\nexport interface ProviderBinary {\n path: string;\n version: string | null;\n source: BinarySource;\n /** \"from ChatGPT app\", \"from PATH\", … */\n sourceLabel: string;\n /** A newer copy than the one in use, when one exists. */\n newer: { path: string; version: string; sourceLabel: string } | null;\n}\n\n/** What `providers()` answers for one provider, in plain terms. */\nexport interface ProviderStatus {\n provider: CodingProvider;\n label: string;\n installed: boolean;\n version: string | null;\n loggedIn: boolean;\n billing: Billing;\n /** \"Max\", \"Pro\", \"Plus\", … when the provider reports a plan. */\n plan: string | null;\n /** The signed-in account label, when the provider reports one. */\n account: string | null;\n /** A plain-English sentence for the screen when it is not ready. */\n problem: string | null;\n /** A plain-English fix for `problem`. */\n fix: string | null;\n /** Installed, signed in, and no known usage limit or expired sign-in. */\n ready: boolean;\n /** The last usage-limit or sign-in failure a run reported, until a run succeeds. */\n lastProblem: ProviderProblem | null;\n /** Usage windows, when the provider exposes them (Codex does; see FEATURE.md). */\n quota: QuotaWindow[];\n /** Models the driver knows for this provider (the person may type any other). */\n models?: ModelOption[] | undefined;\n /** Reasoning-effort levels this provider accepts, lowest first. */\n efforts?: string[] | undefined;\n /**\n * The model a run uses when none is picked, and where that comes from: the\n * person's own settings (`~/.claude/settings.json`, `~/.codex/config.toml`)\n * or the driver's built-in default.\n */\n defaultModel?: { id: string; source: \"settings\" | \"driver\" } | null | undefined;\n /** The effort a run uses when none is picked (the person's own settings). */\n defaultEffort?: string | null | undefined;\n /** Which CLI runs use, and its version. */\n binary?: ProviderBinary | null | undefined;\n}\n\nexport interface ModelOption {\n id: string;\n label: string;\n}\n\n/**\n * The person's own organisation of their chats — a rename, a pin, a hide. Kept\n * in this package's data dir, keyed by `chatKey()`; the providers' own files\n * are NEVER touched (a rename here does not rename the chat in Claude Code).\n */\nexport interface ChatPreference {\n /** Shown instead of the chat's own title. */\n title?: string | null | undefined;\n pinned?: boolean | undefined;\n /** Hidden from the lists (still found by search, restorable). */\n hidden?: boolean | undefined;\n updatedAt?: string | undefined;\n}\n\n/** The one key a chat's preference lives under, for ours and discovered alike. */\nexport function chatKey(provider: CodingProvider, providerSessionId: string | null, sessionId?: string | null): string {\n return providerSessionId ? `${provider}:${providerSessionId}` : `session:${sessionId ?? \"\"}`;\n}\n\n/** One chat that matched a search. */\nexport interface ChatSearchHit {\n provider: CodingProvider;\n providerSessionId: string;\n title: string;\n cwd: string | null;\n updatedAt: string;\n /** Where the words were found. */\n where: \"title\" | \"content\";\n /** A short excerpt around the first match in the conversation. */\n snippet: string | null;\n}\n\nexport interface ChatSearchResult {\n query: string;\n hits: ChatSearchHit[];\n /** How many chats were read, newest first, starting from the cursor. */\n scanned: number;\n /** How many chats exist on this computer. */\n total: number;\n /** Pass back to keep searching older chats; null when every chat was read. */\n nextCursor: number | null;\n}\n\n/** Where \"Open folder\" can open a session's folder. */\nexport type OpenTarget = \"finder\" | \"vscode\" | \"cursor\" | \"terminal\";\n\nexport interface ProviderProblem {\n kind: \"usage-limit\" | \"signed-out\";\n /** The provider's own words, verbatim. */\n message: string;\n /** When a usage limit lifts: ISO when parseable, else the provider's phrase. */\n until: string | null;\n at: string;\n}\n\nexport interface QuotaWindow {\n label: string;\n usedPercent: number | null;\n resetsAt: string | null;\n valueLabel: string | null;\n}\n\n/** An existing local Claude Code or Codex chat, found on disk (metadata only). */\nexport interface DiscoveredSession {\n provider: CodingProvider;\n providerSessionId: string;\n cwd: string | null;\n title: string;\n updatedAt: string;\n /** Where it was started, when the provider records it (\"cli\", \"vscode\", \"exec\", …). */\n source: string | null;\n /** Set when the chat looks live somewhere else right now (see `ActiveElsewhere`). */\n activeElsewhere: ActiveElsewhere | null;\n}\n\n/**\n * Evidence that a chat is being driven somewhere else RIGHT NOW. Taking it\n * over then puts two agents on one conversation, so the screen warns and asks —\n * it never blocks (validation offers, never blocks).\n */\nexport interface ActiveElsewhere {\n /** How we know, strongest first. */\n reason: \"process\" | \"recent-write\" | \"open-tool-call\";\n /** One plain sentence for the screen. */\n message: string;\n}\n\nexport type RunStatus = \"starting\" | \"running\" | \"completed\" | \"stopped\" | \"failed\";\n\nexport const TERMINAL_RUN_STATUSES: readonly RunStatus[] = [\"completed\", \"stopped\", \"failed\"];\n\nexport function isTerminalRunStatus(status: RunStatus): boolean {\n return TERMINAL_RUN_STATUSES.includes(status);\n}\n\nexport interface RunUsage {\n inputTokens: number;\n outputTokens: number;\n cachedInputTokens: number;\n}\n\n/** One turn: one prompt sent to one provider process. */\nexport interface RunRecord {\n runId: string;\n /** Our session id (`CodingSession.id`). */\n sessionId: string;\n provider: CodingProvider;\n cwd: string;\n prompt: string;\n model: string | null;\n status: RunStatus;\n startedAt: string;\n endedAt: string | null;\n /** The real error, verbatim from the provider or the driver, when failed. */\n error: string | null;\n usage: RunUsage | null;\n costUsd: number | null;\n billing: Billing | null;\n}\n\n/** How a session came to be listed here. */\nexport type SessionOrigin = \"started\" | \"takeover\";\n\n/** A conversation driven from here. Its transcript lives in the provider's own\n * files; this is only the index row. */\nexport interface CodingSession {\n /** Our stable id. */\n id: string;\n provider: CodingProvider;\n /** The provider's own session/thread id — null until the first run reports it. */\n providerSessionId: string | null;\n cwd: string;\n title: string;\n model: string | null;\n /** Reasoning effort for the next run; null = the provider's own default. */\n effort?: string | null | undefined;\n origin: SessionOrigin;\n createdAt: string;\n updatedAt: string;\n /** The live or most recent run. */\n lastRunId: string | null;\n lastRunStatus: RunStatus | null;\n /** Prompts waiting for the active run to finish, oldest first. */\n queued: string[];\n /** The AI Matrx agent loaded into every run of this session, when one was picked. */\n agent?: SessionAgent | null | undefined;\n /** Codex must be told, in the next prompt, that an earlier agent no longer applies. */\n agentRemovedDue?: boolean | undefined;\n}\n\n/**\n * One normalized transcript item — the same shape from Claude and Codex, from\n * a live stream and from a provider's saved session file.\n */\nexport type TranscriptItem =\n | { kind: \"user\"; id: string; text: string; at: string | null }\n | { kind: \"text\"; id: string; text: string }\n | { kind: \"text-delta\"; id: string; text: string }\n | { kind: \"reasoning\"; id: string; text: string }\n | { kind: \"tool-call\"; id: string; name: string; input: unknown }\n | { kind: \"tool-result\"; id: string; output: string; isError: boolean }\n | { kind: \"usage\"; usage: RunUsage; costUsd: number | null }\n | { kind: \"notice\"; id: string; level: \"info\" | \"warning\"; text: string }\n | { kind: \"error\"; id: string; text: string };\n\n/** Everything the engine pushes to a listener. */\nexport type CodingEvent =\n | { type: \"session\"; session: CodingSession }\n | { type: \"run\"; run: RunRecord }\n | { type: \"preferences\"; preferences: Record<string, ChatPreference> }\n | {\n type: \"item\";\n sessionId: string;\n runId: string;\n /** Monotonic per session; a history read reports the last `seq` it includes. */\n seq: number;\n item: TranscriptItem;\n };\n\n/** A transcript read back from the provider's own file. */\nexport interface SessionHistory {\n items: TranscriptItem[];\n /** True when the file was larger than the read budget and only its end was read. */\n truncated: boolean;\n /** Plain-English reason when history could not be read (never thrown at the UI). */\n unavailable: string | null;\n /** The last live item `seq` this read already contains; apply only newer ones. */\n seq: number;\n}\n\nexport interface StartInput {\n provider: CodingProvider;\n cwd: string;\n prompt: string;\n model?: string | null | undefined;\n effort?: string | null | undefined;\n /** An AI Matrx agent to load into the CLI. Needs the host's `agents` credentials. */\n agent?: AgentSelection | null | undefined;\n}\n\n/** Which AI Matrx agent a new session loads, and the person's variable values. */\nexport interface AgentSelection {\n agentId: string;\n /** Pin one saved version; omitted = the latest, pinned at start. */\n versionId?: string | null | undefined;\n variables?: Record<string, JsonValue> | undefined;\n}\n\n/** One part of an agent and whether this session's CLI carries it. */\nexport interface SessionAgentPart {\n part: \"instructions\" | \"skills\" | \"tools\";\n loaded: number;\n total: number;\n}\n\n/**\n * The agent a session runs with. Recorded at start and never drifts: every\n * later turn reloads the SAME bundle (same version, same hash).\n */\nexport interface SessionAgent {\n agentId: string;\n versionId: string | null;\n versionNumber: number | null;\n name: string;\n definitionHash: string;\n loaded: SessionAgentPart[];\n /** What could not be carried, with the reason. */\n unavailable: { kind: string; name: string; reason: string }[];\n /** The skills it carries (labels) and the tools it serves (names) — the agent's own set. */\n skills?: string[] | undefined;\n tools?: string[] | undefined;\n /** The person's variable values, kept so \"Update to vN\" can reuse them. */\n variables?: Record<string, JsonValue> | undefined;\n /**\n * The CLI must be TOLD in the next prompt (a delimited block): a Codex\n * takeover or agent switch (Codex ignores developer_instructions on resume),\n * or a Codex compaction that dropped the block. Cleared once delivered.\n */\n blockDue?: boolean | undefined;\n /** When the block (or native instructions) last reached the CLI. */\n deliveredAt?: string | null | undefined;\n /** The agent this one replaced mid-chat (\"Code Reviewer v1\"), named in the block. */\n replaces?: string | null | undefined;\n}\n\n/** Whether this host can reach AI Matrx as a signed-in person. */\nexport interface AgentAccess {\n signedIn: boolean;\n userId: string | null;\n organizationId: string | null;\n /** True when the host was started with no AI Matrx connection at all. */\n configured: boolean;\n}\n\n/** A catalogue read the picker asks the host to make (PostgREST RPC shape). */\nexport interface AgentCatalogRpcRequest {\n fn: string;\n args?: Record<string, unknown> | undefined;\n count?: \"exact\" | \"planned\" | \"estimated\" | undefined;\n range?: [number, number] | undefined;\n order?: { column: string; ascending?: boolean | undefined } | undefined;\n}\n\nexport interface AgentCatalogRpcResult {\n data: unknown;\n error: {\n message: string;\n code?: string | undefined;\n details?: string | null | undefined;\n hint?: string | null | undefined;\n } | null;\n count?: number | null;\n}\n\n/** What a picker needs about one agent — the LIGHT read (no skills, no tools). */\nexport interface AgentDetails {\n agentId: string;\n name: string;\n /** Variable declarations as authored (camelCase). */\n variables: Record<string, JsonValue>[];\n /** Newest first. */\n versions: { id: string; versionNumber: number; changedAt: string | null }[];\n /** The version \"Latest\" resolves to right now. */\n latestVersionNumber: number | null;\n latestVersionId: string | null;\n}\n\nexport interface TakeoverInput {\n provider: CodingProvider;\n providerSessionId: string;\n cwd: string;\n title?: string | undefined;\n /** Continue the chat WITH an AI Matrx agent (\"Continue with agent\"). */\n agent?: AgentSelection | null | undefined;\n}\n\nexport interface SendResult {\n session: CodingSession;\n /** The run that started, or null when the prompt was queued behind a live run. */\n run: RunRecord | null;\n queued: boolean;\n}\n\nexport interface FolderCheck {\n /** The absolute path the check resolved. */\n path: string;\n exists: boolean;\n /** False when something that is NOT a folder sits at the path. */\n isDirectory: boolean;\n}\n\n/** A folder the New session flow offers (from discovered and driven sessions). */\nexport interface RecentFolder {\n path: string;\n lastUsedAt: string;\n exists: boolean;\n}\n\n/**\n * THE ENGINE CONTRACT — what the UI can ask for, independent of transport.\n * The WebSocket host implements it over the wire; a desktop app implements it\n * over IPC; the UI never knows which.\n */\nexport interface CodingSessionsApi {\n providers(): Promise<ProviderStatus[]>;\n discoverSessions(options?: { limit?: number }): Promise<DiscoveredSession[]>;\n recentFolders(): Promise<RecentFolder[]>;\n listSessions(): Promise<CodingSession[]>;\n listRuns(sessionId: string): Promise<RunRecord[]>;\n /** `maxBytes` reads more of a long chat's file (\"Show earlier\"). */\n history(sessionId: string, options?: HistoryOptions): Promise<SessionHistory>;\n /** Read-only transcript of a chat found on disk, before taking it over. */\n readTranscript(provider: CodingProvider, providerSessionId: string, options?: HistoryOptions): Promise<SessionHistory>;\n /**\n * FULL DOWNLOAD: the provider's own complete transcript file for this chat,\n * byte for byte (every tool input and output). AI Matrx's cloud keeps only\n * text and tool names, so this computer is the first place the full file\n * lives. `available: false` carries the sentence saying why.\n */\n readRawTranscript(provider: CodingProvider, providerSessionId: string): Promise<RawTranscript>;\n /** Does this folder exist here? `~` is the person's home. */\n checkFolder(path: string): Promise<FolderCheck>;\n /** Create a folder (and any missing parents), then report on it. */\n createFolder(path: string): Promise<FolderCheck>;\n /** Fresh check: is this chat live somewhere else right now? null when not. */\n sessionActivity(provider: CodingProvider, providerSessionId: string): Promise<ActiveElsewhere | null>;\n start(input: StartInput): Promise<SendResult>;\n takeover(input: TakeoverInput): Promise<CodingSession>;\n send(sessionId: string, prompt: string): Promise<SendResult>;\n stop(runId: string): Promise<RunRecord | null>;\n /** The person's renames, pins and hides, by `chatKey()`. */\n chatPreferences(): Promise<Record<string, ChatPreference>>;\n /** Merge a change into one chat's preference; `null` fields clear. Returns them all. */\n setChatPreference(key: string, patch: ChatPreference): Promise<Record<string, ChatPreference>>;\n /** Find chats by title and by what was said in them, newest first, within a time budget. */\n searchChats(query: string, options?: { cursor?: number; limit?: number }): Promise<ChatSearchResult>;\n /** Open a folder in Finder, VS Code, Cursor or Terminal. */\n openFolder(path: string, target: OpenTarget): Promise<void>;\n /** Change the model or effort the NEXT run of a session uses. */\n setSessionOptions(sessionId: string, options: { model?: string | null; effort?: string | null }): Promise<CodingSession>;\n /** Is this host signed in to AI Matrx (so agents can load)? */\n agentAccess(): Promise<AgentAccess>;\n /** One allowlisted agent-catalogue read, made by the host as the signed-in person. */\n agentCatalogRpc(request: AgentCatalogRpcRequest): Promise<AgentCatalogRpcResult>;\n /** An agent's variables and saved versions, for the New session form. */\n agentDetails(agentId: string): Promise<AgentDetails>;\n /**\n * Load a different agent into a session from its next message on (or\n * remove it, with `null`). Claude reads it every turn; Codex is told in the\n * next prompt.\n */\n setAgent(sessionId: string, agent: AgentSelection | null): Promise<CodingSession>;\n}\n\nexport type RawTranscript =\n | { available: true; fileName: string; bytes: number; content: string }\n | { available: false; reason: string };\n\nexport interface HistoryOptions {\n /** Read up to this many bytes from the end of the file (default 24 MB). */\n maxBytes?: number | undefined;\n}\n\nexport type CodingSessionsMethod = keyof CodingSessionsApi;\n\n/** The transport the UI talks through (WebSocket, IPC, in-process). */\nexport interface CodingSessionsTransport {\n call<M extends CodingSessionsMethod>(\n method: M,\n ...args: Parameters<CodingSessionsApi[M]>\n ): ReturnType<CodingSessionsApi[M]>;\n subscribe(listener: (event: CodingEvent) => void): () => void;\n /** Connection state, for an honest banner. */\n status(): TransportStatus;\n onStatus(listener: (status: TransportStatus) => void): () => void;\n}\n\nexport type TransportStatus =\n | { state: \"connecting\" }\n | { state: \"open\" }\n | { state: \"closed\"; reason: string };\n","/**\n * USAGE LIMITS AND EXPIRED SIGN-INS, in plain English.\n *\n * A provider can be installed and signed in and still unable to run: the\n * ChatGPT or Claude plan hit its usage limit, or the saved login expired.\n * Runs report that in the provider's own words; this turns those words into\n * a remembered, honest status. Built from the real texts captured on\n * 2026-09-27 (Codex usage limit, Codex refresh failure).\n */\n\nimport { PROVIDER_LABEL, type CodingProvider, type ProviderProblem, type QuotaWindow } from \"./types\";\n\nconst USAGE_LIMIT = [\n /hit your usage limit/i,\n /usage limit (?:reached|exceeded)/i,\n /\\blimit reached\\b/i,\n /you'?ve hit your limit/i,\n /rate limit/i,\n /quota (?:exceeded|exhausted)/i,\n /purchase more credits/i,\n];\n\nconst SIGNED_OUT = [\n /access token could not be refreshed/i,\n /please sign in again/i,\n /(?:not|no longer) (?:logged|signed) in/i,\n /please run \\/login/i,\n /invalid api key/i,\n /oauth token (?:has )?expired/i,\n /authentication_error/i,\n /401 unauthorized/i,\n];\n\n/** \"Oct 4th, 2026 8:34 AM\" → ISO. null when the phrase is not a date. */\nexport function parseLimitDate(phrase: string): string | null {\n const cleaned = phrase.replace(/(\\d{1,2})(st|nd|rd|th)\\b/gi, \"$1\").replace(/[.,]\\s*$/, \"\").trim();\n const ms = Date.parse(cleaned);\n return Number.isNaN(ms) ? null : new Date(ms).toISOString();\n}\n\nfunction limitPhrase(text: string): string | null {\n const match =\n /try again (?:at|after|on) ([^\\n]+?)(?:\\.\\s|\\.$|$)/i.exec(text) ??\n /resets? (?:at |on )?([^\\n∙·|]+?)(?:\\.\\s|\\.$|$|\\s*[∙·|])/i.exec(text);\n return match?.[1]?.trim() ?? null;\n}\n\nexport function classifyProviderError(text: string, at = new Date().toISOString()): ProviderProblem | null {\n const trimmed = text.trim();\n if (!trimmed) return null;\n if (SIGNED_OUT.some((re) => re.test(trimmed))) {\n return { kind: \"signed-out\", message: trimmed, until: null, at };\n }\n if (USAGE_LIMIT.some((re) => re.test(trimmed))) {\n const phrase = limitPhrase(trimmed);\n return { kind: \"usage-limit\", message: trimmed, until: phrase ? (parseLimitDate(phrase) ?? phrase) : null, at };\n }\n return null;\n}\n\n/** A usage limit whose reset time has passed no longer applies. */\nexport function problemStillApplies(problem: ProviderProblem, now = Date.now()): boolean {\n if (problem.kind !== \"usage-limit\" || !problem.until) return true;\n const ms = Date.parse(problem.until);\n return Number.isNaN(ms) || ms > now;\n}\n\nexport function formatUntil(until: string | null): string | null {\n if (!until) return null;\n const ms = Date.parse(until);\n if (Number.isNaN(ms)) return until;\n return new Date(ms).toLocaleString(undefined, { month: \"short\", day: \"numeric\", hour: \"numeric\", minute: \"2-digit\" });\n}\n\n/** A full quota window (100% used) is a usage limit even before a run hits it. */\nexport function problemFromQuota(windows: readonly QuotaWindow[], at = new Date().toISOString()): ProviderProblem | null {\n const full = windows.find((w) => typeof w.usedPercent === \"number\" && w.usedPercent >= 100);\n if (!full) return null;\n return {\n kind: \"usage-limit\",\n message: `${full.label} is used up.`,\n until: full.resetsAt,\n at,\n };\n}\n\nexport function describeProblem(provider: CodingProvider, problem: ProviderProblem): { problem: string; fix: string } {\n const label = PROVIDER_LABEL[provider];\n if (problem.kind === \"signed-out\") {\n return {\n problem: `${label} — sign-in expired.`,\n fix: `Open ${label} and sign in again, then check again.`,\n };\n }\n const until = formatUntil(problem.until);\n return {\n problem: until ? `${label} — usage limit reached until ${until}.` : `${label} — usage limit reached.`,\n fix: until\n ? `It lifts on its own then, or add more usage in your ${provider === \"codex\" ? \"ChatGPT\" : \"Claude\"} account.`\n : `Wait for it to reset, or add more usage in your ${provider === \"codex\" ? \"ChatGPT\" : \"Claude\"} account.`,\n };\n}\n\n/**\n * A run refused because the CHOSEN MODEL is not available — to this account,\n * or to this version of the CLI. It is about the model, not the provider, so\n * the screen offers the model picker rather than a provider-wide warning.\n * Built from the real Codex text captured 2026-10-01\n * (fixtures/codex-model-unsupported.error.txt) and Claude Code's wording.\n */\nconst MODEL_UNAVAILABLE = [\n /model is not supported when using codex/i,\n /\\bmodel[\\s:'\"`][^.\\n]{0,80}\\b(?:not supported|does not exist|not available|not found)\\b/i,\n /\\bmodel_not_found\\b/i,\n /issue with the selected model/i,\n /may not exist or you may not have access to it/i,\n];\n\nexport const MODEL_UNAVAILABLE_LABEL = \"Model not available on this account\";\n\nexport function isModelUnavailable(text: string | null | undefined): boolean {\n const trimmed = (text ?? \"\").trim();\n return trimmed !== \"\" && MODEL_UNAVAILABLE.some((re) => re.test(trimmed));\n}\n\n/** What the screen says for a failed run: a short label for a known class, else the text itself. */\nexport function runErrorLabel(text: string): string {\n return isModelUnavailable(text) ? MODEL_UNAVAILABLE_LABEL : text;\n}\n","/**\n * What a tool call is CALLED on screen, and the one argument that says what\n * it is doing. `mcp__claude-in-chrome__browser_batch` reads \"Browser batch ·\n * Claude in chrome\"; `Bash {command: \"ls -la\"}` reads \"Run command\" with\n * \"ls -la\" beside it. The machine name stays on the card as `data-tool`.\n */\n\nconst BUILTIN: Record<string, string> = {\n Bash: \"Run command\",\n Shell: \"Run command\",\n BashOutput: \"Read command output\",\n KillShell: \"Stop command\",\n Read: \"Read file\",\n Write: \"Write file\",\n Edit: \"Edit file\",\n MultiEdit: \"Edit file\",\n NotebookEdit: \"Edit notebook\",\n Glob: \"Find files\",\n Grep: \"Search code\",\n LS: \"List folder\",\n WebFetch: \"Fetch page\",\n WebSearch: \"Web search\",\n \"Web search\": \"Web search\",\n Task: \"Sub-agent\",\n Agent: \"Sub-agent\",\n TodoWrite: \"Update plan\",\n Plan: \"Update plan\",\n \"Edit files\": \"Edit files\",\n ExitPlanMode: \"Finish planning\",\n Skill: \"Use skill\",\n ToolSearch: \"Load tools\",\n};\n\nfunction words(identifier: string): string {\n const spaced = identifier\n .replace(/[._-]+/g, \" \")\n .replace(/([a-z\\d])([A-Z])/g, \"$1 $2\")\n .replace(/\\s+/g, \" \")\n .trim()\n .toLowerCase();\n return spaced ? spaced.charAt(0).toUpperCase() + spaced.slice(1) : \"\";\n}\n\n/** `mcp__<server>__<tool>` → { server, tool }, or null. */\nexport function parseMcpToolName(name: string): { server: string; tool: string } | null {\n const match = /^mcp__(.+?)__(.+)$/.exec(name);\n return match?.[1] && match[2] ? { server: match[1], tool: match[2] } : null;\n}\n\nexport function friendlyToolName(name: string): string {\n const builtin = BUILTIN[name];\n if (builtin) return builtin;\n const mcp = parseMcpToolName(name);\n if (mcp) {\n // A server name often repeats in its tool (\"claude_browser\" + \"browser_batch\").\n return `${words(mcp.tool) || \"Tool\"} · ${words(mcp.server)}`;\n }\n // Codex MCP calls arrive as \"<server>.<tool>\".\n const dotted = /^([\\w-]+)\\.([\\w-]+)$/.exec(name);\n if (dotted?.[1] && dotted[2]) return `${words(dotted[2])} · ${words(dotted[1])}`;\n return words(name) || \"Working…\";\n}\n\nfunction prettyPath(value: string): string {\n const home = value.match(/^\\/(?:Users|home)\\/[^/]+/)?.[0];\n return home ? `~${value.slice(home.length)}` : value;\n}\n\nfunction clip(value: string, max = 90): string {\n const flat = value.replace(/\\s+/g, \" \").trim();\n return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;\n}\n\n/** The key argument, for the card's subtitle. null when there is none worth showing. */\nexport function toolSubtitle(name: string, input: unknown): string | null {\n if (typeof input !== \"object\" || input === null) return typeof input === \"string\" && input ? clip(input) : null;\n const args = input as Record<string, unknown>;\n const pick = (...keys: string[]): string | null => {\n for (const key of keys) {\n const value = args[key];\n if (typeof value === \"string\" && value.trim()) return value;\n }\n return null;\n };\n switch (name) {\n case \"Bash\":\n case \"Shell\": {\n const command = pick(\"command\", \"description\");\n return command ? clip(command) : null;\n }\n case \"Read\":\n case \"Write\":\n case \"Edit\":\n case \"MultiEdit\":\n case \"NotebookEdit\": {\n const file = pick(\"file_path\", \"notebook_path\", \"path\");\n return file ? clip(prettyPath(file)) : null;\n }\n case \"Glob\":\n case \"Grep\":\n return pick(\"pattern\") ? clip(pick(\"pattern\") as string) : null;\n case \"WebFetch\":\n return pick(\"url\") ? clip(pick(\"url\") as string) : null;\n case \"WebSearch\":\n case \"Web search\":\n return pick(\"query\") ? clip(pick(\"query\") as string) : null;\n case \"Task\":\n case \"Agent\":\n return pick(\"description\", \"prompt\") ? clip(pick(\"description\", \"prompt\") as string) : null;\n case \"Edit files\": {\n // The live stream lists `{ path, kind }`; a saved rollout maps path → change.\n const raw = args.changes;\n const paths = Array.isArray(raw)\n ? raw\n .map((c) => (typeof c === \"object\" && c !== null ? (c as { path?: unknown }).path : null))\n .filter((p): p is string => typeof p === \"string\")\n : typeof raw === \"object\" && raw !== null\n ? Object.keys(raw)\n : [];\n return paths.length ? clip(paths.map(prettyPath).join(\", \")) : null;\n }\n default: {\n const first = pick(\"url\", \"query\", \"command\", \"path\", \"file_path\", \"name\", \"description\");\n return first ? clip(first) : null;\n }\n }\n}\n","/**\n * THE CHANGES PANEL — every file this chat's agent wrote, with what changed,\n * read from the conversation itself (see `../changes.ts`).\n */\n\nimport { useMemo, useState, type ReactNode } from \"react\";\n\nimport type { ChatMessage } from \"@ai-matrx/chat\";\nimport { cn } from \"@ai-matrx/design-system\";\n\nimport { changedFiles, lineCounts, type ChangedFile, type FileEdit } from \"../changes\";\nimport { copyText } from \"./chat-menu\";\nimport { prettyPath } from \"./hooks\";\nimport { ChevronDownIcon, CloseIcon, FileIcon } from \"./icons\";\nimport { useToastShow } from \"./toast\";\n\nconst MAX_LINES = 400;\n\n/** A file's path inside the chat's folder; macOS's `/tmp` is `/private/tmp`, so both spellings count. */\nexport function relativeTo(file: string, cwd: string | null): string {\n if (cwd) {\n const base = cwd.replace(/\\/+$/, \"\");\n for (const root of [base, `/private${base}`, base.replace(/^\\/private(?=\\/)/, \"\")]) {\n if (file.startsWith(`${root}/`)) return file.slice(root.length + 1);\n }\n }\n return prettyPath(file);\n}\n\nfunction DiffLines({ edit }: { edit: FileEdit }): ReactNode {\n const lines: { kind: \"add\" | \"del\" | \"hunk\" | \"ctx\"; text: string }[] = [];\n if (edit.diff) {\n for (const line of edit.diff.split(\"\\n\")) {\n if (line.startsWith(\"@@\")) lines.push({ kind: \"hunk\", text: line });\n else if (line.startsWith(\"+\")) lines.push({ kind: \"add\", text: line });\n else if (line.startsWith(\"-\")) lines.push({ kind: \"del\", text: line });\n else if (line !== \"\") lines.push({ kind: \"ctx\", text: line });\n }\n } else {\n if (edit.removed) for (const line of edit.removed.split(\"\\n\")) lines.push({ kind: \"del\", text: `-${line}` });\n if (edit.added) for (const line of edit.added.split(\"\\n\")) lines.push({ kind: \"add\", text: `+${line}` });\n }\n if (lines.length === 0) {\n return (\n <p className=\"text-[12px] text-muted-foreground\">\n {edit.failed ? \"This change failed.\" : \"The agent didn't record the text of this change.\"}\n </p>\n );\n }\n const shown = lines.slice(0, MAX_LINES);\n return (\n <>\n {edit.failed ? <p className=\"mb-1 text-[11.5px] text-destructive\">This change failed and was not applied.</p> : null}\n <pre className={cn(\"cs-diff\", edit.failed && \"opacity-60\")}>\n {shown.map((line, i) => (\n <span key={i} className={cn(\"cs-diff__line\", line.kind !== \"ctx\" && `cs-diff__line--${line.kind}`)}>\n {line.text || \" \"}\n </span>\n ))}\n </pre>\n {lines.length > MAX_LINES ? (\n <p className=\"mt-1 text-[11.5px] text-muted-foreground\">\n Showing the first {MAX_LINES} of {lines.length} lines.\n </p>\n ) : null}\n </>\n );\n}\n\nfunction FileRow({ file, cwd }: { file: ChangedFile; cwd: string | null }): ReactNode {\n const [open, setOpen] = useState(false);\n const show = useToastShow();\n const counts = lineCounts(file);\n const shown = relativeTo(file.path, cwd);\n const kind = { created: \"New\", edited: \"Edited\", deleted: \"Deleted\", moved: \"Moved\" }[file.kind];\n return (\n <li className=\"border-b border-border\">\n <div className=\"flex items-center gap-2 px-4 py-2\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n aria-expanded={open}\n className=\"flex min-w-0 flex-1 items-center gap-2 text-left\"\n >\n <ChevronDownIcon size={13} className={cn(\"shrink-0 transition-transform\", !open && \"-rotate-90\")} />\n <FileIcon size={14} className=\"shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 truncate text-[12.5px] font-medium\" title={file.path}>\n {shown}\n </span>\n </button>\n <span className=\"shrink-0 text-[11px] text-muted-foreground\">{kind}</span>\n <span className=\"shrink-0 font-mono text-[11px]\">\n {counts.added ? <span className=\"cs-count-add\">+{counts.added}</span> : null}{\" \"}\n {counts.removed ? <span className=\"cs-count-del\">−{counts.removed}</span> : null}\n </span>\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => void copyText(file.path, show, \"File path\")}\n aria-label={`Copy the path of ${shown}`}\n title=\"Copy path\"\n >\n <FileIcon size={12} />\n </button>\n </div>\n {open ? (\n <div className=\"space-y-3 px-4 pb-3\">\n {file.edits.map((edit, i) => (\n <DiffLines key={`${edit.toolCallId}-${i}`} edit={edit} />\n ))}\n </div>\n ) : null}\n </li>\n );\n}\n\nexport function useChangedFiles(messages: readonly ChatMessage[]): ChangedFile[] {\n return useMemo(() => changedFiles(messages), [messages]);\n}\n\nexport function ChangesPanel(props: {\n files: ChangedFile[];\n cwd: string | null;\n truncated: boolean;\n onClose: () => void;\n}): ReactNode {\n return (\n <aside className=\"cs-changes\" aria-label=\"Files changed in this chat\">\n <div className=\"flex items-center justify-between border-b border-border px-4 py-3\">\n <div>\n <h2 className=\"text-[13.5px] font-semibold\">Files changed</h2>\n <p className=\"text-[11.5px] text-muted-foreground\">\n {props.files.length === 0\n ? \"Nothing yet\"\n : `${props.files.length} ${props.files.length === 1 ? \"file\" : \"files\"}, from this chat's own record`}\n {props.truncated ? \" · only the part of the chat shown here\" : \"\"}\n </p>\n </div>\n <button type=\"button\" className=\"cs-icon-button\" onClick={props.onClose} aria-label=\"Close files changed\">\n <CloseIcon size={14} />\n </button>\n </div>\n {props.files.length === 0 ? (\n <p className=\"px-4 py-6 text-center text-[12.5px] leading-5 text-muted-foreground\">\n The agent hasn't written any files in this chat yet.\n </p>\n ) : (\n <ul className=\"min-h-0 flex-1 overflow-y-auto\">\n {props.files.map((file) => (\n <FileRow key={file.path} file={file} cwd={props.cwd} />\n ))}\n </ul>\n )}\n </aside>\n );\n}\n","/**\n * WHAT CHANGED — the files a session's agent wrote, read straight from the\n * transcript's own tool calls (no git, no second read of the disk):\n *\n * - Claude Code: `Write`, `Edit`, `MultiEdit`, `NotebookEdit` — their inputs\n * carry the text, so each change has a real before/after.\n * - Codex: a completed `FileChange` item — `changes` is a map of path →\n * `{ type, unified_diff }` in saved rollouts, or a list of `{ path, kind }`\n * in the live stream (no diff there; the list says so).\n *\n * Pure: no Node, no DOM. The screen's Changes panel renders the result.\n */\n\nimport type { ChatMessage } from \"@ai-matrx/chat\";\n\nexport type ChangeKind = \"created\" | \"edited\" | \"deleted\" | \"moved\";\n\n/** One edit to one file, with whatever text the provider recorded. */\nexport interface FileEdit {\n /** Lines removed / added, when the provider recorded them. */\n removed: string | null;\n added: string | null;\n /** A unified diff, when that is what the provider recorded. */\n diff: string | null;\n /** The tool call that made it (for \"show in conversation\"). */\n toolCallId: string;\n failed: boolean;\n}\n\nexport interface ChangedFile {\n path: string;\n kind: ChangeKind;\n edits: FileEdit[];\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction str(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction codexKind(value: unknown): ChangeKind {\n const kind = isObject(value) ? str(value.type) : str(value);\n if (kind === \"add\" || kind === \"create\") return \"created\";\n if (kind === \"delete\") return \"deleted\";\n if (kind === \"move\" || kind === \"rename\") return \"moved\";\n return \"edited\";\n}\n\n/** Every file the transcript's tool calls changed, in first-touched order. */\nexport function changedFiles(messages: readonly ChatMessage[]): ChangedFile[] {\n const byPath = new Map<string, ChangedFile>();\n const add = (path: string, kind: ChangeKind, edit: FileEdit) => {\n const existing = byPath.get(path);\n if (existing) {\n existing.edits.push(edit);\n // A file created in this session stays \"created\" however often it is edited after.\n if (kind === \"deleted\") existing.kind = \"deleted\";\n } else {\n byPath.set(path, { path, kind, edits: [edit] });\n }\n };\n\n for (const message of messages) {\n for (const part of message.parts) {\n if (part.type !== \"tool\") continue;\n const input = part.input;\n if (!isObject(input)) continue;\n const failed = part.state === \"output-error\" || Boolean((part as { errorText?: unknown }).errorText);\n const base = { toolCallId: part.toolCallId, failed };\n switch (part.toolName) {\n case \"Write\": {\n const path = str(input.file_path);\n if (path) add(path, \"created\", { ...base, removed: null, added: str(input.content), diff: null });\n break;\n }\n case \"Edit\": {\n const path = str(input.file_path);\n if (path) {\n add(path, \"edited\", { ...base, removed: str(input.old_string), added: str(input.new_string), diff: null });\n }\n break;\n }\n case \"MultiEdit\": {\n const path = str(input.file_path);\n const edits = Array.isArray(input.edits) ? input.edits : [];\n if (path) {\n for (const edit of edits.filter(isObject)) {\n add(path, \"edited\", { ...base, removed: str(edit.old_string), added: str(edit.new_string), diff: null });\n }\n }\n break;\n }\n case \"NotebookEdit\": {\n const path = str(input.notebook_path);\n if (path) add(path, \"edited\", { ...base, removed: null, added: str(input.new_source), diff: null });\n break;\n }\n case \"Edit files\": {\n const changes = input.changes;\n if (Array.isArray(changes)) {\n for (const change of changes.filter(isObject)) {\n const path = str(change.path);\n if (path) add(path, codexKind(change.kind), { ...base, removed: null, added: null, diff: null });\n }\n } else if (isObject(changes)) {\n for (const [path, change] of Object.entries(changes)) {\n const diff = isObject(change) ? str(change.unified_diff) : null;\n add(path, codexKind(change), { ...base, removed: null, added: null, diff });\n }\n }\n break;\n }\n default:\n break;\n }\n }\n }\n return [...byPath.values()];\n}\n\n/** Lines added and removed across a file's edits, for the list's \"+12 −3\". */\nexport function lineCounts(file: ChangedFile): { added: number; removed: number } {\n let added = 0;\n let removed = 0;\n const count = (text: string | null) => (text ? text.split(\"\\n\").length : 0);\n for (const edit of file.edits) {\n if (edit.failed) continue;\n if (edit.diff) {\n for (const line of edit.diff.split(\"\\n\")) {\n if (line.startsWith(\"+\") && !line.startsWith(\"+++\")) added += 1;\n else if (line.startsWith(\"-\") && !line.startsWith(\"---\")) removed += 1;\n }\n } else {\n added += count(edit.added);\n removed += count(edit.removed);\n }\n }\n return { added, removed };\n}\n","/**\n * THE CHAT MENU — one list of actions for a chat, shown from the row's `…`\n * button, a right-click on the row, and the open chat's header: rename, pin,\n * hide, copy its id or the command that reopens it, open its folder.\n *\n * Every action is present and working, or absent: no id yet → no \"Copy chat\n * ID\"; no folder → no \"Open folder\". A failure is said in a toast.\n */\n\nimport type { ReactNode } from \"react\";\n\nimport {\n ContextMenuItem,\n ContextMenuSeparator,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n} from \"@ai-matrx/design-system\";\n\nimport { formatFileSize } from \"@ai-matrx/kit/format\";\nimport type { OpenTarget } from \"../types\";\nimport { resumeCommand, type ListEntry } from \"./grouping\";\nimport { useCodingSessionsClient } from \"./hooks\";\nimport { CopyIcon, EyeOffIcon, FolderIcon, PencilIcon, PinIcon } from \"./icons\";\nimport { useToastShow } from \"./toast\";\n\nconst OPEN_TARGETS: { target: OpenTarget; label: string }[] = [\n { target: \"finder\", label: \"Finder\" },\n { target: \"vscode\", label: \"VS Code\" },\n { target: \"cursor\", label: \"Cursor\" },\n { target: \"terminal\", label: \"Terminal\" },\n];\n\nexport async function copyText(text: string, show: (text: string) => void, what: string): Promise<void> {\n try {\n await navigator.clipboard.writeText(text);\n show(`${what} copied.`);\n } catch {\n show(`This browser didn't allow copying. Select the text and copy it with your keyboard instead: ${text}`);\n }\n}\n\n/**\n * FULL DOWNLOAD — the chat's complete provider file (every tool input and\n * output) saved from THIS computer. AI Matrx's cloud keeps only text and tool\n * names; the web app falls back to the opt-in cloud backup when the computer\n * that ran the chat cannot answer.\n */\nasync function fullDownload(\n client: ReturnType<typeof useCodingSessionsClient>,\n entry: ListEntry,\n show: (text: string) => void,\n): Promise<void> {\n try {\n const raw = await client.readRawTranscript(entry.provider, entry.providerSessionId as string);\n if (!raw.available) {\n show(raw.reason);\n return;\n }\n const url = URL.createObjectURL(new Blob([raw.content], { type: \"application/x-ndjson\" }));\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = raw.fileName;\n anchor.click();\n setTimeout(() => URL.revokeObjectURL(url), 10_000);\n show(`Downloaded ${raw.fileName} (${formatFileSize(raw.bytes)}).`);\n } catch (error) {\n show(`Full Download failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\nexport function ChatMenuItems(props: {\n entry: ListEntry;\n variant: \"dropdown\" | \"context\";\n onRename: () => void;\n}): ReactNode {\n const client = useCodingSessionsClient();\n const show = useToastShow();\n const { entry } = props;\n const P =\n props.variant === \"dropdown\"\n ? {\n Item: DropdownMenuItem,\n Separator: DropdownMenuSeparator,\n Sub: DropdownMenuSub,\n SubTrigger: DropdownMenuSubTrigger,\n SubContent: DropdownMenuSubContent,\n }\n : {\n Item: ContextMenuItem,\n Separator: ContextMenuSeparator,\n Sub: ContextMenuSub,\n SubTrigger: ContextMenuSubTrigger,\n SubContent: ContextMenuSubContent,\n };\n\n const setPref = (patch: { pinned?: boolean; hidden?: boolean }, done: string) => {\n client.setPreference(entry.key, patch).then(\n () => show(done),\n (error: unknown) => show(`That didn't save: ${error instanceof Error ? error.message : String(error)}`),\n );\n };\n const resume = resumeCommand(entry);\n\n return (\n <>\n <P.Item onSelect={props.onRename}>\n <PencilIcon size={14} />\n Rename\n </P.Item>\n <P.Item onSelect={() => setPref({ pinned: !entry.pinned }, entry.pinned ? \"Unpinned.\" : \"Pinned to the top.\")}>\n <PinIcon size={14} />\n {entry.pinned ? \"Unpin\" : \"Pin to top\"}\n </P.Item>\n <P.Item\n onSelect={() =>\n setPref(\n { hidden: !entry.hidden },\n entry.hidden ? \"Back in the list.\" : \"Hidden from the list. Search still finds it.\",\n )\n }\n >\n <EyeOffIcon size={14} />\n {entry.hidden ? \"Show in the list\" : \"Hide from the list\"}\n </P.Item>\n {entry.providerSessionId || entry.cwd ? <P.Separator /> : null}\n {entry.providerSessionId ? (\n <P.Item onSelect={() => void copyText(entry.providerSessionId as string, show, \"Chat ID\")}>\n <CopyIcon size={14} />\n Copy chat ID\n </P.Item>\n ) : null}\n {resume ? (\n <P.Item onSelect={() => void copyText(resume, show, \"Resume command\")}>\n <CopyIcon size={14} />\n Copy resume command\n </P.Item>\n ) : null}\n {entry.providerSessionId ? (\n <P.Item onSelect={() => void fullDownload(client, entry, show)}>\n <CopyIcon size={14} />\n Full Download\n </P.Item>\n ) : null}\n {entry.cwd ? (\n <P.Item onSelect={() => void copyText(entry.cwd as string, show, \"Folder path\")}>\n <CopyIcon size={14} />\n Copy folder path\n </P.Item>\n ) : null}\n {entry.cwd ? (\n <P.Sub>\n <P.SubTrigger className=\"gap-2\">\n <FolderIcon size={14} />\n Open folder in\n </P.SubTrigger>\n <P.SubContent>\n {OPEN_TARGETS.map(({ target, label }) => (\n <P.Item\n key={target}\n onSelect={() =>\n client.openFolder(entry.cwd as string, target).catch((error: unknown) =>\n show(error instanceof Error ? error.message : String(error)),\n )\n }\n >\n {label}\n </P.Item>\n ))}\n </P.SubContent>\n </P.Sub>\n ) : null}\n </>\n );\n}\n","/**\n * The sidebar's lists, as data: one entry shape for chats driven from here and\n * chats found on disk, the person's renames/pins/hides applied, grouped by\n * date (Today, Yesterday, Previous 7 days, …) or by folder. Pure — tested\n * without a DOM.\n */\n\nimport {\n chatKey,\n type ChatPreference,\n type CodingProvider,\n type CodingSession,\n type DiscoveredSession,\n} from \"../types\";\n\nexport interface ListEntry {\n /** `chatKey()` — where this chat's preference lives. */\n key: string;\n kind: \"session\" | \"discovered\";\n provider: CodingProvider;\n providerSessionId: string | null;\n /** The shown title: the person's rename, else the chat's own. */\n title: string;\n /** The chat's own title (shown under a rename, searched too). */\n originalTitle: string;\n cwd: string | null;\n updatedAt: string;\n pinned: boolean;\n hidden: boolean;\n session: CodingSession | null;\n discovered: DiscoveredSession | null;\n}\n\nexport function sessionEntry(session: CodingSession, prefs: Record<string, ChatPreference>): ListEntry {\n const key = chatKey(session.provider, session.providerSessionId, session.id);\n const pref = prefs[key] ?? prefs[chatKey(session.provider, null, session.id)] ?? {};\n return {\n key,\n kind: \"session\",\n provider: session.provider,\n providerSessionId: session.providerSessionId,\n title: pref.title || session.title,\n originalTitle: session.title,\n cwd: session.cwd,\n updatedAt: session.updatedAt,\n pinned: pref.pinned === true,\n hidden: pref.hidden === true,\n session,\n discovered: null,\n };\n}\n\nexport function discoveredEntry(d: DiscoveredSession, prefs: Record<string, ChatPreference>): ListEntry {\n const key = chatKey(d.provider, d.providerSessionId);\n const pref = prefs[key] ?? {};\n return {\n key,\n kind: \"discovered\",\n provider: d.provider,\n providerSessionId: d.providerSessionId,\n title: pref.title || d.title,\n originalTitle: d.title,\n cwd: d.cwd,\n updatedAt: d.updatedAt,\n pinned: pref.pinned === true,\n hidden: pref.hidden === true,\n session: null,\n discovered: d,\n };\n}\n\nexport interface EntryGroup {\n label: string;\n entries: ListEntry[];\n}\n\nconst DAY = 24 * 60 * 60 * 1000;\n\nfunction startOfDay(ms: number): number {\n const d = new Date(ms);\n d.setHours(0, 0, 0, 0);\n return d.getTime();\n}\n\n/** The date bucket a time falls in, as the Claude and ChatGPT apps name them. */\nexport function dateGroup(iso: string, now: number): string {\n const then = Date.parse(iso);\n if (Number.isNaN(then)) return \"Older\";\n const today = startOfDay(now);\n if (then >= today) return \"Today\";\n if (then >= today - DAY) return \"Yesterday\";\n if (then >= today - 7 * DAY) return \"Previous 7 days\";\n if (then >= today - 30 * DAY) return \"Previous 30 days\";\n const date = new Date(then);\n const thisYear = new Date(now).getFullYear();\n return date.getFullYear() === thisYear\n ? date.toLocaleDateString(undefined, { month: \"long\" })\n : String(date.getFullYear());\n}\n\n/** The last folder name, for a folder group's label. */\nexport function folderLabel(cwd: string | null): string {\n if (!cwd) return \"Unknown folder\";\n const parts = cwd.split(\"/\").filter(Boolean);\n return parts[parts.length - 1] ?? cwd;\n}\n\n/**\n * Group entries, keeping their order (newest first) inside each group. Date\n * groups come in time order; folder groups by their newest chat.\n */\nexport function groupEntries(entries: readonly ListEntry[], mode: \"date\" | \"folder\", now: number): EntryGroup[] {\n const groups = new Map<string, EntryGroup>();\n for (const entry of entries) {\n const id = mode === \"date\" ? dateGroup(entry.updatedAt, now) : (entry.cwd ?? \"\");\n let group = groups.get(id);\n if (!group) {\n group = { label: mode === \"date\" ? id : folderLabel(entry.cwd), entries: [] };\n groups.set(id, group);\n }\n group.entries.push(entry);\n }\n if (mode === \"folder\") {\n // Two folders with the same last name get their parent too.\n const byLabel = new Map<string, number>();\n for (const g of groups.values()) byLabel.set(g.label, (byLabel.get(g.label) ?? 0) + 1);\n for (const [cwd, g] of groups) {\n if ((byLabel.get(g.label) ?? 0) > 1 && cwd) {\n const parts = cwd.split(\"/\").filter(Boolean);\n g.label = parts.slice(-2).join(\"/\");\n }\n }\n }\n return [...groups.values()];\n}\n\n/** Does this entry's title, own title or folder contain the query? */\nexport function matchesQuery(entry: ListEntry, query: string): boolean {\n const q = query.trim().toLowerCase();\n if (!q) return true;\n return (\n entry.title.toLowerCase().includes(q) ||\n entry.originalTitle.toLowerCase().includes(q) ||\n (entry.cwd ?? \"\").toLowerCase().includes(q)\n );\n}\n\n/** Sort key: newest first. */\nexport function byNewest(a: ListEntry, b: ListEntry): number {\n return b.updatedAt.localeCompare(a.updatedAt);\n}\n\n/** The shell command that reopens this chat in its own app. */\nexport function resumeCommand(entry: Pick<ListEntry, \"provider\" | \"providerSessionId\" | \"cwd\">): string | null {\n if (!entry.providerSessionId) return null;\n const cli = entry.provider === \"claude\" ? `claude --resume ${entry.providerSessionId}` : `codex resume ${entry.providerSessionId}`;\n if (!entry.cwd) return cli;\n const quoted = /^[A-Za-z0-9_./~-]+$/.test(entry.cwd) ? entry.cwd : `'${entry.cwd.replace(/'/g, `'\\\\''`)}'`;\n return `cd ${quoted} && ${cli}`;\n}\n","import { createContext, useContext, useEffect, useState, useSyncExternalStore } from \"react\";\n\nimport { formatRelativeTime } from \"@ai-matrx/kit/format\";\nimport type { CodingSessionsClient, CodingSessionsState, SessionTranscript } from \"./client\";\n\nexport const CodingSessionsContext = createContext<CodingSessionsClient | null>(null);\n\nexport function useCodingSessionsClient(): CodingSessionsClient {\n const client = useContext(CodingSessionsContext);\n if (!client) {\n throw new Error(\n \"[@ai-matrx/coding-sessions] Render this inside <CodingSessionsProvider transport={…}> (or <CodingSessionsApp>).\",\n );\n }\n return client;\n}\n\nexport function useCodingSessionsState(): CodingSessionsState {\n const client = useCodingSessionsClient();\n return useSyncExternalStore(client.subscribe, client.getState, client.getState);\n}\n\n/** The open transcript for a session, re-rendering when its load state changes. */\nexport function useSessionTranscript(sessionId: string): SessionTranscript {\n const client = useCodingSessionsClient();\n const transcript = client.transcript(sessionId);\n const [, bump] = useState(0);\n useEffect(() => transcript.thread.subscribe(() => bump((n) => n + 1)), [transcript]);\n return transcript;\n}\n\n/** A clock that ticks once a minute, for \"3 min ago\" labels. */\nexport function useMinuteClock(): number {\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), 60_000);\n return () => clearInterval(timer);\n }, []);\n return now;\n}\n\n/** \"5 minutes ago\" — kit's long relative voice, bound to this app's clock tick. */\nexport function relativeTime(iso: string | null | undefined, now: number): string {\n return iso ? formatRelativeTime(iso, { style: \"long\", now, fallback: \"\" }) : \"\";\n}\n\n/** `/Users/me/code/app` → `~/code/app`; long paths keep their last segments. */\nexport function prettyPath(path: string | null | undefined): string {\n if (!path) return \"\";\n const home = path.match(/^\\/(?:Users|home)\\/[^/]+/)?.[0];\n const short = home ? `~${path.slice(home.length)}` : path;\n if (short.length <= 48) return short;\n const parts = short.split(\"/\");\n return `…/${parts.slice(-3).join(\"/\")}`;\n}\n","/**\n * Package-owned glyphs (C19: inlined SVG, no icon-library dependency).\n * Lucide-style 24×24 strokes, `currentColor`, sized by the caller.\n */\n\nimport type { ReactNode, SVGProps } from \"react\";\n\ntype IconProps = SVGProps<SVGSVGElement> & { size?: number };\n\nfunction Svg({ size = 16, children, ...rest }: IconProps & { children: ReactNode }): ReactNode {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.8}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n {...rest}\n >\n {children}\n </svg>\n );\n}\n\nexport const PlusIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M12 5v14M5 12h14\" />\n </Svg>\n);\n\nexport const StopIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" fill=\"currentColor\" stroke=\"none\" />\n </Svg>\n);\n\nexport const FolderIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M3 7.5A2.5 2.5 0 0 1 5.5 5H9l2 2.5h7.5A2.5 2.5 0 0 1 21 10v7.5a2.5 2.5 0 0 1-2.5 2.5h-13A2.5 2.5 0 0 1 3 17.5z\" />\n </Svg>\n);\n\nexport const CheckIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m5 12.5 4.5 4.5L19 7.5\" />\n </Svg>\n);\n\nexport const AlertIcon = (p: IconProps) => (\n <Svg {...p}>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 7.5v5.5M12 16.5h.01\" />\n </Svg>\n);\n\nexport const RefreshIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M20 11a8 8 0 0 0-14.3-4.9L4 8M4 4v4h4M4 13a8 8 0 0 0 14.3 4.9L20 16M20 20v-4h-4\" />\n </Svg>\n);\n\nexport const HandoffIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M5 12h12M13 7l5 5-5 5\" />\n <path d=\"M5 5v14\" />\n </Svg>\n);\n\nexport const SunIcon = (p: IconProps) => (\n <Svg {...p}>\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 2.5v2M12 19.5v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M2.5 12h2M19.5 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4\" />\n </Svg>\n);\n\nexport const MoonIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5z\" />\n </Svg>\n);\n\nexport const MonitorIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"12\" rx=\"2\" />\n <path d=\"M8.5 20h7M12 16.5V20\" />\n </Svg>\n);\n\nexport const ChatBubbleIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M20 12.5a7.5 7.5 0 0 1-10.9 6.7L4 20.5l1.3-4.6A7.5 7.5 0 1 1 20 12.5z\" />\n </Svg>\n);\n\nexport const SpinnerIcon = ({ size = 16, className }: { size?: number; className?: string }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n className={`cs-spin ${className ?? \"\"}`}\n >\n <circle cx=\"12\" cy=\"12\" r=\"9\" fill=\"none\" stroke=\"currentColor\" strokeOpacity=\"0.2\" strokeWidth=\"2.5\" />\n <path d=\"M21 12a9 9 0 0 0-9-9\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" />\n </svg>\n);\n\n/** A small provider mark: a tinted rounded square with the provider's initial. */\n/** The providers' own marks (Claude's, and OpenAI's for Codex), drawn at 16px by default. Paths: simple-icons (CC0). */\nconst CLAUDE_MARK = \"m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z\";\nconst OPENAI_MARK = \"M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z\";\n\nexport function ProviderMark({ provider, size = 16 }: { provider: \"claude\" | \"codex\"; size?: number }): ReactNode {\n return (\n <svg\n className={`cs-provider-mark cs-provider-mark--${provider}`}\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n data-provider-mark={provider}\n >\n <path d={provider === \"claude\" ? CLAUDE_MARK : OPENAI_MARK} />\n </svg>\n );\n}\n\nexport const SearchIcon = (p: IconProps) => (\n <Svg {...p}>\n <circle cx=\"11\" cy=\"11\" r=\"6.5\" />\n <path d=\"m20 20-4.2-4.2\" />\n </Svg>\n);\n\nexport const MoreIcon = (p: IconProps) => (\n <Svg {...p}>\n <circle cx=\"5.5\" cy=\"12\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"12\" cy=\"12\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"18.5\" cy=\"12\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\" />\n </Svg>\n);\n\nexport const PinIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M9 4h6l-1 5 3 3v2H7v-2l3-3z\" />\n <path d=\"M12 14v6\" />\n </Svg>\n);\n\nexport const EyeOffIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M3 3l18 18\" />\n <path d=\"M10.6 5.1A9.8 9.8 0 0 1 12 5c5 0 8.5 4.5 9.5 7a13 13 0 0 1-2.6 3.9M6.4 6.4C4.3 7.8 2.9 9.9 2.5 12c1 2.5 4.5 7 9.5 7 1.8 0 3.4-.6 4.8-1.4\" />\n <path d=\"M9.9 9.9a3 3 0 0 0 4.2 4.2\" />\n </Svg>\n);\n\nexport const CopyIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"8.5\" y=\"8.5\" width=\"11\" height=\"11\" rx=\"2\" />\n <path d=\"M15.5 8.5V6.5a2 2 0 0 0-2-2h-7a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h2\" />\n </Svg>\n);\n\nexport const PencilIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M4 20h4L19 9a2.8 2.8 0 0 0-4-4L4 16z\" />\n <path d=\"m13.5 6.5 4 4\" />\n </Svg>\n);\n\nexport const SidebarIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"3.5\" y=\"4.5\" width=\"17\" height=\"15\" rx=\"2.5\" />\n <path d=\"M9.5 4.5v15\" />\n </Svg>\n);\n\nexport const ChevronDownIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m6.5 9.5 5.5 5.5 5.5-5.5\" />\n </Svg>\n);\n\nexport const FileIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M14 3.5H7.5a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2V8z\" />\n <path d=\"M14 3.5V8h4.5\" />\n </Svg>\n);\n\nexport const CloseIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M6.5 6.5l11 11M17.5 6.5l-11 11\" />\n </Svg>\n);\n\nexport const KeyboardIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"3\" y=\"6.5\" width=\"18\" height=\"11\" rx=\"2\" />\n <path d=\"M7 10.5h.01M11 10.5h.01M15 10.5h.01M8 14h8\" />\n </Svg>\n);\n\nexport const BellIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M6 16.5V11a6 6 0 1 1 12 0v5.5l1.5 1.5h-15z\" />\n <path d=\"M10 20.5a2 2 0 0 0 4 0\" />\n </Svg>\n);\n","import { createContext, useContext } from \"react\";\n\n/** One short sentence at the bottom of the screen (copied, couldn't open, …). */\nexport const ToastContext = createContext<(text: string) => void>(() => undefined);\n\nexport function useToastShow(): (text: string) => void {\n return useContext(ToastContext);\n}\n","/**\n * MODEL AND EFFORT — one small picker used by New session and by an open\n * chat's header (the next message uses the change). \"Default\" says WHICH\n * model that is and where it comes from: the person's own Claude Code or\n * Codex settings, or the driver's built-in default when they set none.\n */\n\nimport { useState, type ReactNode } from \"react\";\n\nimport { Popover, PopoverContent, PopoverTrigger, cn } from \"@ai-matrx/design-system\";\n\nimport type { ProviderStatus } from \"../types\";\nimport { CheckIcon, ChevronDownIcon } from \"./icons\";\n\nexport interface ModelChoice {\n model: string | null;\n effort: string | null;\n}\n\nexport function defaultModelWords(status: ProviderStatus | null): string {\n const d = status?.defaultModel;\n if (!d) return `${status?.label ?? \"the agent\"}'s own default`;\n return d.source === \"settings\" ? `${d.id}, from your settings` : `${d.id}, the built-in default`;\n}\n\nexport function modelLabel(choice: ModelChoice, status: ProviderStatus | null): string {\n const model = choice.model ?? status?.defaultModel?.id ?? \"Default model\";\n const effort = choice.effort ?? status?.defaultEffort ?? null;\n return effort ? `${model} · ${effort}` : model;\n}\n\nexport function ModelPicker(props: {\n status: ProviderStatus | null;\n value: ModelChoice;\n onChange: (next: ModelChoice) => void;\n /** What the chip sits in: a form field or a quiet header chip. */\n appearance?: \"field\" | \"chip\";\n disabled?: boolean;\n}): ReactNode {\n const [open, setOpen] = useState(false);\n const [custom, setCustom] = useState(\"\");\n const models = props.status?.models ?? [];\n const efforts = props.status?.efforts ?? [];\n const known = props.value.model === null || models.some((m) => m.id === props.value.model);\n\n const pick = (patch: Partial<ModelChoice>) => props.onChange({ ...props.value, ...patch });\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n disabled={props.disabled}\n className={cn(props.appearance === \"field\" ? \"cs-model-field\" : \"cs-chip-button\")}\n aria-label={`Model and effort: ${modelLabel(props.value, props.status)}. Change`}\n title=\"Model and effort\"\n >\n <span className=\"truncate\">{modelLabel(props.value, props.status)}</span>\n <ChevronDownIcon size={12} className=\"shrink-0\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-[300px] p-0\">\n <div className=\"max-h-[320px] overflow-y-auto p-1\" role=\"listbox\" aria-label=\"Model\">\n <p className=\"px-2 pb-1 pt-1.5 text-[11px] font-medium uppercase tracking-[0.05em] text-muted-foreground\">Model</p>\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={props.value.model === null}\n className=\"cs-option\"\n onClick={() => pick({ model: null })}\n >\n <span className=\"min-w-0 flex-1\">\n <span className=\"block text-[13px]\">Default</span>\n <span className=\"block truncate text-[11.5px] text-muted-foreground\">{defaultModelWords(props.status)}</span>\n </span>\n {props.value.model === null ? <CheckIcon size={14} /> : null}\n </button>\n {models.map((m) => (\n <button\n key={m.id}\n type=\"button\"\n role=\"option\"\n aria-selected={props.value.model === m.id}\n className=\"cs-option\"\n onClick={() => pick({ model: m.id })}\n >\n <span className=\"min-w-0 flex-1 truncate text-[13px]\">{m.label}</span>\n {props.value.model === m.id ? <CheckIcon size={14} /> : null}\n </button>\n ))}\n {!known ? (\n <div className=\"cs-option\" aria-selected=\"true\" role=\"option\">\n <span className=\"min-w-0 flex-1 truncate text-[13px]\">{props.value.model}</span>\n <CheckIcon size={14} />\n </div>\n ) : null}\n {/* Not a <form>: this popover can sit inside New session's form, and a\n nested Enter would start the session instead of picking the model. */}\n <div className=\"flex gap-1 px-1 pb-1 pt-1.5\">\n <input\n value={custom}\n onChange={(e) => setCustom(e.target.value)}\n onKeyDown={(e) => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n e.stopPropagation();\n if (custom.trim()) {\n pick({ model: custom.trim() });\n setCustom(\"\");\n }\n }}\n placeholder=\"Another model name…\"\n aria-label=\"Another model name\"\n spellCheck={false}\n className=\"cs-option-input\"\n />\n </div>\n </div>\n {efforts.length > 0 ? (\n <div className=\"border-t border-border p-2\">\n <p className=\"px-1 pb-1.5 text-[11px] font-medium uppercase tracking-[0.05em] text-muted-foreground\">\n Thinking effort\n </p>\n <div className=\"flex flex-wrap gap-1\" role=\"radiogroup\" aria-label=\"Thinking effort\">\n {[null, ...efforts].map((level) => (\n <button\n key={level ?? \"default\"}\n type=\"button\"\n role=\"radio\"\n aria-checked={props.value.effort === level}\n className={cn(\"cs-seg\", props.value.effort === level && \"cs-seg--on\")}\n onClick={() => pick({ effort: level })}\n title={level === null ? `Default${props.status?.defaultEffort ? ` (${props.status.defaultEffort}, from your settings)` : \"\"}` : undefined}\n >\n {level === null ? \"Default\" : level}\n </button>\n ))}\n </div>\n </div>\n ) : null}\n </PopoverContent>\n </Popover>\n );\n}\n","/**\n * AI MATRX AGENTS ON THE SCREEN — the New session agent field and the header\n * chip that says what loaded.\n *\n * The picker is THE platform picker (`AgentListDropdown` over\n * `createAgentCatalog`); its catalogue reads go through the host\n * (`agentCatalogRpc`), so the person's token never reaches this page. The\n * variables form is `deriveRunInputs` — the one derivation every run surface\n * uses. Signed out is a state: one line, and plain sessions work as before.\n */\n\nimport { useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\n\nimport { deriveRunInputs, type RunInputVariable } from \"@ai-matrx/agents\";\nimport {\n createAgentCatalog,\n type AgentCatalog,\n type AgentCatalogClient,\n type AgentCatalogRpcCall,\n type PgResultLike,\n} from \"@ai-matrx/agents/catalog\";\nimport { AgentCatalogProvider, AgentListDropdown } from \"@ai-matrx/agents/catalog/react\";\nimport type { JsonValue } from \"@ai-matrx/agents/portable\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Input,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Textarea,\n TooltipProvider,\n cn,\n} from \"@ai-matrx/design-system\";\n\nimport type {\n AgentAccess,\n AgentCatalogRpcRequest,\n AgentDetails,\n AgentSelection,\n CodingSessionsTransport,\n SessionAgent,\n} from \"../types\";\nimport { ChevronDownIcon } from \"./icons\";\nimport { useToastShow } from \"./toast\";\n\nexport const SIGNED_OUT_AGENTS = \"Sign in to AI Matrx to use your agents\";\nconst LATEST = \"latest\";\n\nfunction bridgedClient(transport: CodingSessionsTransport): AgentCatalogClient {\n const call = (request: AgentCatalogRpcRequest): AgentCatalogRpcCall => {\n const run = (): Promise<PgResultLike> =>\n transport.call(\"agentCatalogRpc\", request).then((result) => ({\n data: result.data,\n error: result.error\n ? {\n message: result.error.message,\n ...(result.error.code ? { code: result.error.code } : {}),\n details: result.error.details ?? null,\n hint: result.error.hint ?? null,\n }\n : null,\n count: result.count ?? null,\n }));\n return {\n then: (onOk, onErr) => run().then(onOk, onErr),\n range: (from, to) => call({ ...request, range: [from, to] }),\n order: (column, options) =>\n call({ ...request, order: { column, ascending: options?.ascending !== false } }),\n };\n };\n return {\n rpc: (fn, args, options) =>\n call({ fn, ...(args ? { args } : {}), ...(options?.count ? { count: options.count } : {}) }),\n };\n}\n\n/** Whether the host is signed in to AI Matrx. Re-asks when the dialog opens. */\nexport function useAgentAccess(transport: CodingSessionsTransport, open: boolean): AgentAccess | null {\n const [access, setAccess] = useState<AgentAccess | null>(null);\n useEffect(() => {\n if (!open) return;\n let alive = true;\n transport\n .call(\"agentAccess\")\n .then((next) => alive && setAccess(next))\n .catch(() => alive && setAccess({ signedIn: false, userId: null, organizationId: null, configured: false }));\n return () => {\n alive = false;\n };\n }, [transport, open]);\n return access;\n}\n\nfunction useCatalog(\n transport: CodingSessionsTransport,\n userId: string | null,\n onError: (message: string) => void,\n): AgentCatalog | null {\n const report = useRef(onError);\n report.current = onError;\n return useMemo(() => {\n if (!userId) return null;\n return createAgentCatalog({\n client: bridgedClient(transport),\n identity: { requireUserId: () => userId, getUserId: () => userId },\n catalogId: `coding-sessions:${userId}`,\n // A failed catalogue read shows at the field, never only in the console.\n errorSink: (event) => {\n console.error(`[coding-sessions] agent catalogue: ${event.code}: ${event.message}`);\n if (event.code === \"list_read_failed\") report.current(\"Couldn't load your agents. Reopen to retry.\");\n },\n });\n }, [transport, userId]);\n}\n\nfunction asRunInputVariables(defs: Record<string, JsonValue>[]): RunInputVariable[] {\n return defs.flatMap((def) => (typeof def.name === \"string\" ? [def as unknown as RunInputVariable] : []));\n}\n\nexport interface AgentFieldProps {\n transport: CodingSessionsTransport;\n open: boolean;\n value: AgentSelection | null;\n onChange: (next: AgentSelection | null) => void;\n /** A missing required variable, by name — shown at its input. */\n missing: string | null;\n /** The picked agent's variables and versions, once loaded (null while none). */\n onDetails?: ((details: AgentDetails | null) => void) | undefined;\n}\n\n/** The New session \"AI Matrx agent\" field: picker, version menu, variables. */\nexport function AgentField(props: AgentFieldProps): ReactNode {\n const access = useAgentAccess(props.transport, props.open);\n const [details, setDetails] = useState<AgentDetails | null>(null);\n const [problem, setProblem] = useState<string | null>(null);\n const catalog = useCatalog(props.transport, access?.signedIn ? access.userId : null, setProblem);\n const agentId = props.value?.agentId ?? null;\n\n useEffect(() => {\n setDetails(null);\n setProblem(null);\n if (!agentId) return;\n let alive = true;\n props.transport\n .call(\"agentDetails\", agentId)\n .then((next) => alive && setDetails(next))\n .catch((error: unknown) => alive && setProblem(error instanceof Error ? error.message : String(error)));\n return () => {\n alive = false;\n };\n }, [agentId, props.transport]);\n\n const { onDetails } = props;\n useEffect(() => {\n onDetails?.(details);\n }, [details, onDetails]);\n\n const inputs = useMemo(() => deriveRunInputs(asRunInputVariables(details?.variables ?? [])), [details]);\n\n if (access === null) return <div className=\"cs-skeleton h-9 rounded-lg\" />;\n if (!access.signedIn || !catalog) {\n return <p className=\"text-[12.5px] text-muted-foreground\">{SIGNED_OUT_AGENTS}</p>;\n }\n\n const setVariable = (name: string, value: string) => {\n if (!props.value) return;\n props.onChange({ ...props.value, variables: { ...(props.value.variables ?? {}), [name]: value } });\n };\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n {/* The picker's trigger carries tooltips; this page has no app-wide provider. */}\n <TooltipProvider>\n <AgentCatalogProvider catalog={catalog}>\n <AgentListDropdown\n consumerId=\"coding-sessions-new-session\"\n activeAgentId={agentId}\n label={details?.name ?? (agentId ? \"Loading…\" : \"None\")}\n onSelect={(id) => props.onChange({ agentId: id, versionId: null, variables: {} })}\n />\n </AgentCatalogProvider>\n </TooltipProvider>\n {agentId ? (\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => props.onChange(null)}>\n Remove\n </Button>\n ) : null}\n </div>\n\n {problem ? <p className=\"text-[12px] text-destructive\">{problem}</p> : null}\n\n {details && props.value ? (\n <>\n <div className=\"flex items-center gap-2\">\n <span className=\"w-[72px] shrink-0 text-[12px] text-muted-foreground\">Version</span>\n <Select\n value={props.value.versionId ?? LATEST}\n onValueChange={(next) =>\n props.value && props.onChange({ ...props.value, versionId: next === LATEST ? null : next })\n }\n >\n <SelectTrigger className=\"h-8 w-[200px] text-[12.5px]\" aria-label=\"Agent version\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={LATEST}>\n {details.latestVersionNumber !== null ? `Latest (v${details.latestVersionNumber})` : \"Latest\"}\n </SelectItem>\n {details.versions.map((v) => (\n <SelectItem key={v.id} value={v.id}>\n v{v.versionNumber}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {inputs.map((input) => {\n const raw = props.value?.variables?.[input.name];\n const value = typeof raw === \"string\" ? raw : \"\";\n const id = `cs-agent-var-${input.name}`;\n const invalid = props.missing === input.name;\n return (\n <div key={input.name} className=\"space-y-1\">\n <label htmlFor={id} className=\"text-[12px] font-medium\">\n {input.label}\n {input.required ? <span className=\"text-muted-foreground\"> · required</span> : null}\n </label>\n {input.options && input.options.length > 0 ? (\n <Select value={value} onValueChange={(next) => setVariable(input.name, next)}>\n <SelectTrigger id={id} className=\"h-8 text-[12.5px]\" aria-invalid={invalid || undefined}>\n <SelectValue placeholder=\"Choose…\" />\n </SelectTrigger>\n <SelectContent>\n {input.options.map((option) => (\n <SelectItem key={option} value={option}>\n {option}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : input.variable.customComponent?.type === \"textarea\" ? (\n <Textarea\n id={id}\n rows={2}\n value={value}\n onChange={(e) => setVariable(input.name, e.target.value)}\n placeholder={input.hint ?? \"\"}\n aria-invalid={invalid || undefined}\n />\n ) : (\n <Input\n id={id}\n value={value}\n onChange={(e) => setVariable(input.name, e.target.value)}\n placeholder={input.hint ?? \"\"}\n aria-invalid={invalid || undefined}\n />\n )}\n {invalid ? <p className=\"text-[12px] text-destructive\">Fill this in to use the agent</p> : null}\n </div>\n );\n })}\n </>\n ) : null}\n </div>\n );\n}\n\n/** The first required variable the selection leaves empty, or null. */\nexport function missingRequiredVariable(details: AgentDetails | null, selection: AgentSelection | null): string | null {\n if (!details || !selection) return null;\n for (const input of deriveRunInputs(asRunInputVariables(details.variables))) {\n if (!input.required) continue;\n const value = selection.variables?.[input.name];\n if (typeof value !== \"string\" || !value.trim()) return input.name;\n }\n return null;\n}\n\nconst PART_LABEL: Record<SessionAgent[\"loaded\"][number][\"part\"], string> = {\n instructions: \"Instructions\",\n skills: \"Skills\",\n tools: \"Tools\",\n};\n\n/** `Code Reviewer v7 · Instructions ✓ · Skills 3/3 · Tools 5/6` — the trigger's words. */\nexport function agentChipText(agent: SessionAgent): string {\n const parts = agent.loaded.map((part) =>\n part.part === \"instructions\"\n ? `${PART_LABEL.instructions} ${part.loaded === 1 ? \"✓\" : \"—\"}`\n : `${PART_LABEL[part.part]} ${part.loaded}/${part.total}`,\n );\n return `${agent.name}${agent.versionNumber !== null ? ` v${agent.versionNumber}` : \"\"} · ${parts.join(\" · \")}`;\n}\n\n/**\n * The header's agent control: what loaded (every skill and tool the agent\n * carries, by name — the agent's own resolved set), what did not and why, and\n * the actions: update to the latest version, change the agent, remove it.\n */\nexport function AgentMenu(props: {\n transport: CodingSessionsTransport;\n sessionId: string;\n agent: SessionAgent | null;\n onChange: () => void;\n}): ReactNode {\n const { agent } = props;\n const show = useToastShow();\n const [open, setOpen] = useState(false);\n const [choosing, setChoosing] = useState(false);\n const [latest, setLatest] = useState<{ id: string; number: number } | null>(null);\n const [access, setAccess] = useState<AgentAccess | null>(null);\n\n useEffect(() => {\n if (!open) return;\n let alive = true;\n void props.transport.call(\"agentAccess\").then((next) => alive && setAccess(next)).catch(() => undefined);\n if (agent) {\n props.transport\n .call(\"agentDetails\", agent.agentId)\n .then((d) => {\n if (alive && d.latestVersionId && d.latestVersionNumber !== null) setLatest({ id: d.latestVersionId, number: d.latestVersionNumber });\n })\n .catch(() => undefined);\n }\n return () => {\n alive = false;\n };\n }, [open, agent, props.transport]);\n\n const apply = async (selection: AgentSelection | null, done: string) => {\n try {\n await props.transport.call(\"setAgent\", props.sessionId, selection);\n show(done);\n props.onChange();\n } catch (error) {\n show(`That didn't change: ${error instanceof Error ? error.message : String(error)}`);\n }\n };\n\n const behind = agent && latest && agent.versionNumber !== null && latest.number > agent.versionNumber ? latest : null;\n const complete = agent ? agent.loaded.every((part) => part.loaded === part.total) : true;\n const signedIn = access?.signedIn ?? false;\n\n return (\n <>\n <DropdownMenu open={open} onOpenChange={setOpen}>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className={cn(\"cs-agent-chip\", agent ? \"cs-agent-chip--set\" : \"cs-agent-chip--none\", !complete && \"cs-agent-chip--partial\")}\n data-testid=\"cs-agent-chip\"\n aria-label={agent ? `AI Matrx agent: ${agent.name}` : \"Add an AI Matrx agent\"}\n >\n {agent ? agentChipText(agent) : \"No agent\"}\n {behind ? <span className=\"cs-agent-chip-dot\" aria-label=\"Update available\" /> : null}\n <ChevronDownIcon size={12} className=\"ml-1 inline shrink-0\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-[320px]\">\n {agent ? (\n <>\n <DropdownMenuLabel className=\"truncate\">\n {agent.name}\n {agent.versionNumber !== null ? ` · v${agent.versionNumber}` : \"\"}\n </DropdownMenuLabel>\n <div className=\"cs-agent-parts\">\n {agent.blockDue ? <p className=\"text-[12px] text-muted-foreground\">Sent with your next message</p> : null}\n <AgentPartList title=\"Skills\" items={agent.skills ?? []} />\n <AgentPartList title=\"Tools\" items={agent.tools ?? []} />\n {agent.unavailable.length > 0 ? (\n <AgentPartList\n title=\"Not loaded\"\n items={agent.unavailable.map((u) => `${u.name} — ${u.reason}`)}\n />\n ) : null}\n </div>\n <DropdownMenuSeparator />\n </>\n ) : null}\n {signedIn ? (\n <>\n {behind && agent ? (\n <DropdownMenuItem\n onSelect={() =>\n void apply(\n { agentId: agent.agentId, versionId: behind.id, variables: agent.variables ?? {} },\n `The next message uses ${agent.name} v${behind.number}.`,\n )\n }\n >\n Update to v{behind.number}\n </DropdownMenuItem>\n ) : null}\n <DropdownMenuItem onSelect={() => setChoosing(true)}>{agent ? \"Change agent…\" : \"Choose agent…\"}</DropdownMenuItem>\n {agent ? (\n <DropdownMenuItem onSelect={() => void apply(null, \"The next message runs without an agent.\")}>\n Remove agent\n </DropdownMenuItem>\n ) : null}\n </>\n ) : access ? (\n <p className=\"px-2 py-1.5 text-[12px] text-muted-foreground\">{SIGNED_OUT_AGENTS}</p>\n ) : null}\n </DropdownMenuContent>\n </DropdownMenu>\n <ChooseAgentDialog\n transport={props.transport}\n open={choosing}\n onOpenChange={setChoosing}\n title={agent ? \"Change agent\" : \"Choose an agent\"}\n action=\"Use this agent\"\n onConfirm={(selection) => apply(selection, \"The next message uses the new agent.\")}\n />\n </>\n );\n}\n\nfunction AgentPartList({ title, items }: { title: string; items: string[] }): ReactNode {\n return (\n <div>\n <p className=\"text-[11.5px] font-medium text-muted-foreground\">\n {title} · {items.length}\n </p>\n {items.length > 0 ? (\n <ul className=\"cs-agent-part-list\">\n {items.map((item) => (\n <li key={item} className=\"truncate\" title={item}>\n {item}\n </li>\n ))}\n </ul>\n ) : null}\n </div>\n );\n}\n\n/** Pick an agent (and its version and values) outside New session: a switch, a takeover. */\nexport function ChooseAgentDialog(props: {\n transport: CodingSessionsTransport;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n title: string;\n action: string;\n onConfirm: (selection: AgentSelection) => Promise<void>;\n}): ReactNode {\n const [value, setValue] = useState<AgentSelection | null>(null);\n const [details, setDetails] = useState<AgentDetails | null>(null);\n const [missing, setMissing] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n\n useEffect(() => {\n if (props.open) {\n setValue(null);\n setMissing(null);\n }\n }, [props.open]);\n\n const confirm = async () => {\n if (!value) return;\n const gap = missingRequiredVariable(details, value);\n setMissing(gap);\n if (gap) return;\n setBusy(true);\n try {\n await props.onConfirm(value);\n props.onOpenChange(false);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Dialog open={props.open} onOpenChange={props.onOpenChange}>\n <DialogContent className=\"max-w-[480px]\">\n <DialogHeader>\n <DialogTitle>{props.title}</DialogTitle>\n </DialogHeader>\n <AgentField\n transport={props.transport}\n open={props.open}\n value={value}\n onChange={(next) => {\n setValue(next);\n setMissing(null);\n }}\n missing={missing}\n onDetails={setDetails}\n />\n <DialogFooter>\n <Button type=\"button\" variant=\"ghost\" onClick={() => props.onOpenChange(false)}>\n Cancel\n </Button>\n {/* Absent until there is something to use — never a dead button. */}\n {value ? (\n <Button type=\"button\" disabled={busy} onClick={() => void confirm()}>\n {props.action}\n </Button>\n ) : null}\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n","/**\n * THE SIDEBAR — search, then Pinned · Running · Recent · Your other chats,\n * grouped by date or by folder, each row renameable, pinnable and hideable\n * from its `…` menu or a right-click.\n *\n * A row's title uses the full width: the hover actions take room only while\n * they are showing (an always-reserved invisible button cut every title short).\n * Search is two-speed: titles and folders filter instantly; what was SAID is\n * searched on this computer's files, newest first, and the list says exactly\n * how many chats it read.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\n\nimport {\n Button,\n ContextMenu,\n ContextMenuContent,\n ContextMenuTrigger,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n cn,\n} from \"@ai-matrx/design-system\";\n\nimport { PROVIDER_LABEL, chatKey, isTerminalRunStatus, type ChatSearchHit, type ChatSearchResult, type DiscoveredSession } from \"../types\";\nimport { ChatMenuItems } from \"./chat-menu\";\nimport {\n byNewest,\n discoveredEntry,\n groupEntries,\n matchesQuery,\n sessionEntry,\n type ListEntry,\n} from \"./grouping\";\nimport { prettyPath, relativeTime, useCodingSessionsClient, useCodingSessionsState, useMinuteClock } from \"./hooks\";\nimport {\n CloseIcon,\n MoreIcon,\n PinIcon,\n PlusIcon,\n ProviderMark,\n RefreshIcon,\n SearchIcon,\n SidebarIcon,\n SpinnerIcon,\n} from \"./icons\";\nimport { useToastShow } from \"./toast\";\n\nexport type Selection =\n | { kind: \"none\" }\n | { kind: \"session\"; id: string }\n | { kind: \"discovered\"; provider: \"claude\" | \"codex\"; id: string };\n\ntype GroupMode = \"date\" | \"folder\";\n\nfunction readLocal<T extends string>(key: string, allowed: readonly T[], fallback: T): T {\n try {\n const value = localStorage.getItem(key);\n return (allowed as readonly string[]).includes(value ?? \"\") ? (value as T) : fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction writeLocal(key: string, value: string): void {\n try {\n localStorage.setItem(key, value);\n } catch {\n /* a private window keeps it for this visit only */\n }\n}\n\n/* ------------------------------------------------------------------------ */\n/* Row */\n/* ------------------------------------------------------------------------ */\n\nfunction SectionLabel({ children, action }: { children: ReactNode; action?: ReactNode }): ReactNode {\n return (\n <div data-cs-section-label className=\"flex h-8 items-center justify-between px-3 pt-3\">\n <span className=\"text-[12px] font-medium text-muted-foreground\">{children}</span>\n {action}\n </div>\n );\n}\n\nfunction GroupLabel({ children }: { children: ReactNode }): ReactNode {\n return <div className=\"truncate px-4 pb-0.5 pt-2.5 text-[12px] font-medium text-muted-foreground\">{children}</div>;\n}\n\nfunction RenameInput(props: { initial: string; onDone: (title: string | null) => void }): ReactNode {\n const [value, setValue] = useState(props.initial);\n const done = useRef(false);\n const finish = (title: string | null) => {\n if (done.current) return;\n done.current = true;\n props.onDone(title);\n };\n return (\n <input\n autoFocus\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onFocus={(e) => e.currentTarget.select()}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") finish(value);\n if (e.key === \"Escape\") finish(null);\n }}\n onBlur={() => finish(value)}\n aria-label=\"New name for this chat\"\n className=\"cs-rename-input\"\n />\n );\n}\n\n/** The page's own address for an entry (the same hash the list writes when it is picked). */\nfunction entryTarget(entry: ListEntry): string {\n if (entry.kind === \"session\" && entry.session) return `#s/${entry.session.id}`;\n if (entry.providerSessionId) return `#d/${entry.provider}/${entry.providerSessionId}`;\n return \"\";\n}\n\nfunction Row(props: {\n entry: ListEntry;\n active: boolean;\n onSelect: () => void;\n meta: ReactNode;\n live?: boolean;\n snippet?: ReactNode;\n takeover?: ReactNode;\n}): ReactNode {\n const client = useCodingSessionsClient();\n const show = useToastShow();\n const [renaming, setRenaming] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const { entry } = props;\n\n const rename = (title: string | null) => {\n setRenaming(false);\n if (title === null || title.trim() === entry.title) return;\n // Empty, or back to its own title, clears the rename.\n const next = title.trim() === \"\" || title.trim() === entry.originalTitle ? null : title;\n client.setPreference(entry.key, { title: next }).catch((error: unknown) =>\n show(`The new name didn't save: ${error instanceof Error ? error.message : String(error)}`),\n );\n };\n\n return (\n <ContextMenu>\n <ContextMenuTrigger asChild>\n <div\n className={cn(\"cs-row group\", props.active && \"cs-row--active\", menuOpen && \"cs-row--menu\")}\n data-hidden={entry.hidden || undefined}\n // A host that shows this list in its own chrome (Matrx 2) reads rows by these.\n data-cs-row={entry.key}\n data-cs-target={entryTarget(entry)}\n data-cs-provider={entry.provider}\n data-cs-title={entry.title}\n data-cs-live={props.live ? \"true\" : undefined}\n data-cs-active={props.active ? \"true\" : undefined}\n >\n <button\n type=\"button\"\n onClick={props.onSelect}\n className=\"cs-row__hit\"\n aria-current={props.active ? \"true\" : undefined}\n aria-label={entry.title}\n title={entry.title !== entry.originalTitle ? `${entry.title}\\n(${entry.originalTitle})` : entry.title}\n />\n <span className=\"pointer-events-none mt-0.5 shrink-0\">\n {props.live ? <SpinnerIcon size={16} className=\"text-primary\" /> : <ProviderMark provider={entry.provider} size={16} />}\n </span>\n <span className=\"cs-row__body\">\n {renaming ? (\n <span className=\"pointer-events-auto relative z-10 block\">\n <RenameInput initial={entry.title} onDone={rename} />\n </span>\n ) : (\n <span className=\"flex items-center gap-1\">\n <span className=\"min-w-0 truncate text-[13px] font-medium leading-5\">{entry.title}</span>\n {entry.pinned ? <PinIcon size={11} className=\"shrink-0 text-muted-foreground\" aria-label=\"Pinned\" /> : null}\n </span>\n )}\n <span className=\"block truncate text-[11.5px] leading-4 text-muted-foreground\">{props.meta}</span>\n {props.snippet ? <span className=\"cs-row__snippet\">{props.snippet}</span> : null}\n </span>\n {renaming ? null : (\n <span className=\"cs-row__actions\">\n {props.takeover}\n <DropdownMenu open={menuOpen} onOpenChange={setMenuOpen}>\n <DropdownMenuTrigger asChild>\n <button type=\"button\" className=\"cs-icon-button\" aria-label={`More for ${entry.title}`} title=\"More\">\n <MoreIcon size={15} />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-60\" onCloseAutoFocus={(e) => e.preventDefault()}>\n <ChatMenuItems entry={entry} variant=\"dropdown\" onRename={() => setRenaming(true)} />\n </DropdownMenuContent>\n </DropdownMenu>\n </span>\n )}\n </div>\n </ContextMenuTrigger>\n <ContextMenuContent className=\"w-60\" onCloseAutoFocus={(e) => e.preventDefault()}>\n <ChatMenuItems entry={entry} variant=\"context\" onRename={() => setRenaming(true)} />\n </ContextMenuContent>\n </ContextMenu>\n );\n}\n\nfunction SidebarSkeleton(): ReactNode {\n return (\n <div className=\"space-y-1.5 px-3 py-2\" aria-hidden=\"true\">\n {[0, 1, 2].map((i) => (\n <div key={i} className=\"cs-skeleton h-9 rounded-lg\" />\n ))}\n </div>\n );\n}\n\n/** The query's words, marked where they appear in `text`. */\nexport function Highlight({ text, query }: { text: string; query: string }): ReactNode {\n const q = query.trim().toLowerCase();\n if (!q) return text;\n const at = text.toLowerCase().indexOf(q);\n if (at < 0) return text;\n return (\n <>\n {text.slice(0, at)}\n <mark className=\"cs-mark\">{text.slice(at, at + q.length)}</mark>\n {text.slice(at + q.length)}\n </>\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* Search */\n/* ------------------------------------------------------------------------ */\n\ninterface SearchState {\n query: string;\n loading: boolean;\n error: string | null;\n hits: ChatSearchHit[];\n scanned: number;\n total: number;\n nextCursor: number | null;\n}\n\nconst EMPTY_SEARCH: SearchState = {\n query: \"\",\n loading: false,\n error: null,\n hits: [],\n scanned: 0,\n total: 0,\n nextCursor: null,\n};\n\nfunction useContentSearch(query: string): [SearchState, () => void] {\n const client = useCodingSessionsClient();\n const [state, setState] = useState<SearchState>(EMPTY_SEARCH);\n const latest = useRef(query);\n latest.current = query;\n\n const run = useCallback(\n async (q: string, cursor: number, append: boolean) => {\n setState((s) => ({ ...(append ? s : EMPTY_SEARCH), query: q, loading: true, error: null }));\n try {\n const result: ChatSearchResult = await client.search(q, cursor);\n if (latest.current.trim() !== q) return;\n setState((s) => ({\n query: q,\n loading: false,\n error: null,\n hits: append ? [...s.hits, ...result.hits] : result.hits,\n scanned: (append ? s.scanned : cursor) + result.scanned,\n total: result.total,\n nextCursor: result.nextCursor,\n }));\n } catch (error) {\n if (latest.current.trim() !== q) return;\n setState((s) => ({ ...s, loading: false, error: error instanceof Error ? error.message : String(error) }));\n }\n },\n [client],\n );\n\n useEffect(() => {\n const q = query.trim();\n if (q.length < 2) {\n setState(EMPTY_SEARCH);\n return;\n }\n const timer = setTimeout(() => void run(q, 0, false), 350);\n return () => clearTimeout(timer);\n }, [query, run]);\n\n const more = useCallback(() => {\n if (state.nextCursor !== null && !state.loading) void run(state.query, state.nextCursor, true);\n }, [run, state.nextCursor, state.loading, state.query]);\n\n return [state, more];\n}\n\nfunction hitToDiscovered(hit: ChatSearchHit): DiscoveredSession {\n return {\n provider: hit.provider,\n providerSessionId: hit.providerSessionId,\n cwd: hit.cwd,\n title: hit.title,\n updatedAt: hit.updatedAt,\n source: null,\n activeElsewhere: null,\n };\n}\n\n/* ------------------------------------------------------------------------ */\n/* Sidebar */\n/* ------------------------------------------------------------------------ */\n\nexport interface SidebarHandle {\n focusSearch: () => void;\n}\n\nexport function Sidebar(props: {\n selection: Selection;\n select: (selection: Selection) => void;\n onNew: () => void;\n onCollapse: () => void;\n width: number;\n searchRef: React.RefObject<HTMLInputElement | null>;\n /** A chat opened from search that is older than the listed ones. */\n onFound: (found: DiscoveredSession) => void;\n footer: ReactNode;\n}): ReactNode {\n const client = useCodingSessionsClient();\n const state = useCodingSessionsState();\n const now = useMinuteClock();\n const [query, setQuery] = useState(\"\");\n const [search, searchMore] = useContentSearch(query);\n const [groupMode, setGroupMode] = useState<GroupMode>(() => readLocal(\"coding-sessions.group\", [\"date\", \"folder\"], \"date\"));\n const [showHidden, setShowHidden] = useState(false);\n const [takingOver, setTakingOver] = useState<string | null>(null);\n const [takeoverError, setTakeoverError] = useState<{ id: string; message: string } | null>(null);\n\n const prefs = state.preferences;\n const sessions = state.sessions.data;\n const isLive = (id: string) => {\n const run = state.runs[id];\n return run !== undefined && !isTerminalRunStatus(run.status);\n };\n\n const { ours, others, hiddenCount } = useMemo(() => {\n const oursList = sessions.map((s) => sessionEntry(s, prefs));\n const known = new Set(sessions.map((s) => s.providerSessionId).filter(Boolean));\n const othersList = state.discovered.data\n .filter((d) => !known.has(d.providerSessionId))\n .map((d) => discoveredEntry(d, prefs));\n const hidden = [...oursList, ...othersList].filter((e) => e.hidden).length;\n return { ours: oursList, others: othersList, hiddenCount: hidden };\n }, [sessions, state.discovered.data, prefs]);\n\n const visible = (e: ListEntry) => showHidden || !e.hidden;\n const pinned = [...ours, ...others].filter((e) => e.pinned && visible(e)).sort(byNewest);\n const running = ours.filter((e) => !e.pinned && e.session && isLive(e.session.id) && visible(e));\n const recent = ours.filter((e) => !e.pinned && !(e.session && isLive(e.session.id)) && visible(e));\n const otherList = others.filter((e) => !e.pinned && visible(e));\n\n const setMode = (mode: GroupMode) => {\n setGroupMode(mode);\n writeLocal(\"coding-sessions.group\", mode);\n };\n\n const selectEntry = (entry: ListEntry) => {\n if (entry.session) props.select({ kind: \"session\", id: entry.session.id });\n else if (entry.providerSessionId) props.select({ kind: \"discovered\", provider: entry.provider, id: entry.providerSessionId });\n };\n\n const isActive = (entry: ListEntry) =>\n entry.session\n ? props.selection.kind === \"session\" && props.selection.id === entry.session.id\n : props.selection.kind === \"discovered\" && props.selection.id === entry.providerSessionId;\n\n const takeover = async (d: DiscoveredSession) => {\n setTakingOver(d.providerSessionId);\n setTakeoverError(null);\n try {\n const taken = await client.takeover(d);\n props.select({ kind: \"session\", id: taken.id });\n } catch (error) {\n setTakeoverError({ id: d.providerSessionId, message: error instanceof Error ? error.message : String(error) });\n } finally {\n setTakingOver(null);\n }\n };\n\n const renderEntry = (entry: ListEntry, extra?: { snippet?: ReactNode; query?: string }) => {\n const live = entry.session ? isLive(entry.session.id) : false;\n const run = entry.session ? state.runs[entry.session.id] : undefined;\n const d = entry.discovered;\n let meta: ReactNode;\n if (live) meta = `${PROVIDER_LABEL[entry.provider]} is working…`;\n else if (d?.activeElsewhere)\n meta = (\n <span className=\"cs-live-elsewhere\">\n <span className=\"cs-live-dot\" aria-hidden=\"true\" />\n Running in {PROVIDER_LABEL[entry.provider]}\n </span>\n );\n else {\n const status = run ? (run.status === \"failed\" ? \"Failed · \" : run.status === \"stopped\" ? \"Stopped · \" : \"\") : \"\";\n const where = entry.cwd ? prettyPath(entry.cwd) : \"unknown folder\";\n meta = `${status}${entry.kind === \"discovered\" ? `${PROVIDER_LABEL[entry.provider]} · ` : \"\"}${\n groupMode === \"folder\" && !extra ? \"\" : `${where} · `\n }${relativeTime(entry.updatedAt, now)}`;\n }\n return (\n <div key={entry.key}>\n <Row\n entry={entry}\n active={isActive(entry)}\n onSelect={() => selectEntry(entry)}\n live={live}\n meta={meta}\n snippet={extra?.snippet}\n takeover={\n d?.cwd ? (\n <button\n type=\"button\"\n className=\"cs-takeover-chip\"\n // A chat live elsewhere opens its preview, where the warning\n // and the confirm live — never a one-click takeover.\n onClick={() => (d.activeElsewhere ? selectEntry(entry) : void takeover(d))}\n title={d.activeElsewhere ? d.activeElsewhere.message : \"Continue this chat here\"}\n disabled={takingOver === d.providerSessionId}\n >\n {takingOver === d.providerSessionId ? <SpinnerIcon size={11} /> : null}\n Take over\n </button>\n ) : null\n }\n />\n {takeoverError && d && takeoverError.id === d.providerSessionId ? (\n <p className=\"mx-4 mb-1 text-[11.5px] text-destructive\">{takeoverError.message}</p>\n ) : null}\n </div>\n );\n };\n\n const renderGroups = (entries: ListEntry[]) =>\n groupEntries(entries, groupMode, now).map((group) => (\n <div key={group.label} role=\"group\" aria-label={group.label}>\n <GroupLabel>{group.label}</GroupLabel>\n {group.entries.map((e) => renderEntry(e))}\n </div>\n ));\n\n /* --- search mode ------------------------------------------------------ */\n const searching = query.trim().length > 0;\n const titleMatches = searching\n ? [...ours, ...others].filter((e) => matchesQuery(e, query)).sort(byNewest)\n : [];\n const titleKeys = new Set(titleMatches.map((e) => e.key));\n const allByKey = new Map([...ours, ...others].map((e) => [e.key, e] as const));\n const contentHits = search.hits.filter((h) => !titleKeys.has(chatKey(h.provider, h.providerSessionId)));\n\n const openHit = (hit: ChatSearchHit) => {\n const known = allByKey.get(chatKey(hit.provider, hit.providerSessionId));\n if (known) {\n selectEntry(known);\n return;\n }\n props.onFound(hitToDiscovered(hit));\n props.select({ kind: \"discovered\", provider: hit.provider, id: hit.providerSessionId });\n };\n\n const searchBody = (\n <>\n <SectionLabel>Chats</SectionLabel>\n {titleMatches.length === 0 ? (\n <p className=\"px-4 py-1 text-[12px] text-muted-foreground\">No listed chat has that in its name or folder.</p>\n ) : (\n titleMatches.map((e) => renderEntry(e, { query }))\n )}\n <SectionLabel>In conversations</SectionLabel>\n {query.trim().length < 2 ? (\n <p className=\"px-4 py-1 text-[12px] text-muted-foreground\">Type at least two letters to search what was said.</p>\n ) : (\n <>\n {contentHits.map((hit) => {\n const known = allByKey.get(chatKey(hit.provider, hit.providerSessionId));\n const entry = known ?? discoveredEntry(hitToDiscovered(hit), prefs);\n return (\n <div key={`hit:${entry.key}`} onClickCapture={known ? undefined : () => props.onFound(hitToDiscovered(hit))}>\n {renderEntry(entry, {\n query,\n snippet: hit.snippet ? <Highlight text={hit.snippet} query={query} /> : undefined,\n })}\n </div>\n );\n })}\n <div className=\"px-4 py-2 text-[11.5px] leading-4 text-muted-foreground\" role=\"status\" aria-live=\"polite\">\n {search.error ? (\n <span className=\"text-destructive\">Search stopped: {search.error}</span>\n ) : search.loading ? (\n <span className=\"inline-flex items-center gap-1.5\">\n <SpinnerIcon size={12} /> Searching your chats…\n </span>\n ) : search.query ? (\n <>\n {contentHits.length === 0 && search.hits.length === 0 ? \"Nothing found. \" : null}\n {search.nextCursor === null\n ? `Searched all ${search.total.toLocaleString()} chats on this computer.`\n : `Searched the ${search.scanned.toLocaleString()} most recent of ${search.total.toLocaleString()} chats.`}\n {search.nextCursor !== null ? (\n <button type=\"button\" className=\"cs-link ml-1\" onClick={searchMore}>\n Search older chats\n </button>\n ) : null}\n </>\n ) : null}\n </div>\n </>\n )}\n </>\n );\n\n /* --- list mode --------------------------------------------------------- */\n const listBody = (\n <>\n {pinned.length > 0 ? (\n <>\n <SectionLabel>Pinned</SectionLabel>\n {pinned.map((e) => renderEntry(e))}\n </>\n ) : null}\n\n {running.length > 0 ? (\n <>\n <SectionLabel>Running</SectionLabel>\n {running.map((e) => renderEntry(e))}\n </>\n ) : null}\n\n <SectionLabel>Recent</SectionLabel>\n {state.sessions.loading && state.sessions.loadedAt === null ? (\n <SidebarSkeleton />\n ) : state.sessions.error ? (\n <p className=\"px-4 py-1 text-[12px] text-destructive\">{state.sessions.error}</p>\n ) : recent.length === 0 ? (\n running.length === 0 ? (\n <p className=\"px-4 py-1 text-[12px] leading-5 text-muted-foreground\">\n Sessions you start or take over here will appear here.\n </p>\n ) : null\n ) : (\n recent.map((e) => renderEntry(e))\n )}\n\n <SectionLabel\n action={\n <span className=\"flex items-center gap-0.5\">\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button type=\"button\" className=\"cs-icon-button cs-icon-button--text\" aria-label=\"How to list your other chats\">\n {groupMode === \"date\" ? \"By date\" : \"By folder\"}\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-52\">\n <DropdownMenuLabel>Group your other chats</DropdownMenuLabel>\n <DropdownMenuRadioGroup value={groupMode} onValueChange={(v) => setMode(v as GroupMode)}>\n <DropdownMenuRadioItem value=\"date\">By date</DropdownMenuRadioItem>\n <DropdownMenuRadioItem value=\"folder\">By folder</DropdownMenuRadioItem>\n </DropdownMenuRadioGroup>\n <DropdownMenuSeparator />\n <DropdownMenuItem onSelect={() => setShowHidden((v) => !v)}>\n {showHidden ? \"Leave hidden chats out\" : `Show hidden chats${hiddenCount ? ` (${hiddenCount})` : \"\"}`}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={() => void client.refreshDiscovered()}\n aria-label=\"Look again for your other chats\"\n title=\"Look again\"\n >\n {state.discovered.loading ? <SpinnerIcon size={13} /> : <RefreshIcon size={13} />}\n </button>\n </span>\n }\n >\n Your other chats\n </SectionLabel>\n {state.discovered.loading && state.discovered.loadedAt === null ? (\n <SidebarSkeleton />\n ) : state.discovered.error ? (\n <p className=\"px-4 py-1 text-[12px] text-destructive\">{state.discovered.error}</p>\n ) : otherList.length === 0 ? (\n <p className=\"px-4 py-1 text-[12px] leading-5 text-muted-foreground\">\n {others.length > 0\n ? \"Every chat found here is pinned or hidden.\"\n : \"No other Claude Code or Codex chats were found on this computer.\"}\n </p>\n ) : (\n <>\n {renderGroups(otherList)}\n {state.discovered.data.length >= state.discoveredLimit ? (\n <div className=\"px-3 pt-2\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"w-full text-muted-foreground\"\n onClick={() => void client.showMoreDiscovered()}\n disabled={state.discovered.loading}\n >\n {state.discovered.loading ? <SpinnerIcon size={13} /> : null}\n Show older chats\n </Button>\n </div>\n ) : null}\n </>\n )}\n {showHidden ? null : hiddenCount > 0 ? (\n <button type=\"button\" className=\"cs-link mx-4 mt-3 text-[11.5px]\" onClick={() => setShowHidden(true)}>\n {hiddenCount} hidden {hiddenCount === 1 ? \"chat\" : \"chats\"} — show\n </button>\n ) : null}\n </>\n );\n\n return (\n <aside\n className=\"cs-sidebar flex h-full shrink-0 flex-col border-r border-border bg-sidebar-background\"\n style={{ width: props.width }}\n aria-label=\"Sessions\"\n >\n <div className=\"flex items-center justify-between gap-2 px-4 pb-2 pt-3.5\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"cs-app-mark\" aria-hidden=\"true\" />\n <span className=\"truncate text-[14px] font-semibold tracking-[-0.01em]\">Coding sessions</span>\n </div>\n <button\n type=\"button\"\n className=\"cs-icon-button\"\n onClick={props.onCollapse}\n aria-label=\"Hide the sidebar (⌘B)\"\n title=\"Hide sidebar ⌘B\"\n >\n <SidebarIcon size={15} />\n </button>\n </div>\n <div className=\"space-y-1.5 px-3 pb-1\">\n <Button className=\"w-full justify-start gap-2\" variant=\"outline\" size=\"sm\" onClick={props.onNew}>\n <PlusIcon size={15} />\n New session\n <kbd className=\"cs-kbd ml-auto\">⌥⌘N</kbd>\n </Button>\n <div className=\"cs-search\">\n <SearchIcon size={14} className=\"cs-search__icon\" />\n <input\n ref={props.searchRef}\n type=\"search\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n if (query) setQuery(\"\");\n else e.currentTarget.blur();\n e.preventDefault();\n }\n if (e.key === \"Enter\") {\n const first = titleMatches[0];\n const hit = contentHits[0];\n if (first) selectEntry(first);\n else if (hit) openHit(hit);\n }\n }}\n placeholder=\"Search chats\"\n aria-label=\"Search chats by name, folder or what was said\"\n spellCheck={false}\n className=\"cs-search__input\"\n />\n {query ? (\n <button type=\"button\" className=\"cs-icon-button cs-search__clear\" onClick={() => setQuery(\"\")} aria-label=\"Clear search\">\n <CloseIcon size={13} />\n </button>\n ) : (\n <kbd className=\"cs-search__kbd\">⌘K</kbd>\n )}\n </div>\n </div>\n\n <nav className=\"min-h-0 flex-1 overflow-y-auto pb-3\">{searching ? searchBody : listBody}</nav>\n\n {props.footer}\n </aside>\n );\n}\n","/**\n * The screen's state, framework-free: one store over a\n * `CodingSessionsTransport`, plus one transcript per open session projected\n * into an `@ai-matrx/chat` thread store. React reads it through\n * `useSyncExternalStore` (see `hooks.ts`); nothing here imports React.\n */\n\nimport { createExternalThreadSource } from \"@ai-matrx/chat/external-store\";\nimport type { ChatMessage, ChatThreadStatus, ChatThreadStore } from \"@ai-matrx/chat\";\n\nimport { friendlyToolName, toolSubtitle } from \"../tool-labels\";\nimport { createTranscriptBuilder, type TranscriptBuilder } from \"../transcript\";\nimport {\n isTerminalRunStatus,\n type ChatPreference,\n type ChatSearchResult,\n type CodingEvent,\n type CodingProvider,\n type StartInput,\n type AgentSelection,\n type CodingSession,\n type CodingSessionsTransport,\n type DiscoveredSession,\n type OpenTarget,\n type RawTranscript,\n type ProviderStatus,\n type RecentFolder,\n type RunRecord,\n type TransportStatus,\n} from \"../types\";\n\nexport interface Loadable<T> {\n data: T;\n loading: boolean;\n error: string | null;\n loadedAt: number | null;\n}\n\nexport interface CodingSessionsState {\n connection: TransportStatus;\n providers: Loadable<ProviderStatus[]>;\n sessions: Loadable<CodingSession[]>;\n discovered: Loadable<DiscoveredSession[]>;\n folders: Loadable<RecentFolder[]>;\n /** Latest run per session id. */\n runs: Record<string, RunRecord>;\n /** The person's renames, pins and hides, by `chatKey()`. */\n preferences: Record<string, ChatPreference>;\n /** How many of \"Your other chats\" to list (grows with \"Show more\"). */\n discoveredLimit: number;\n}\n\n/** A run that just ended — for the tab badge and the desktop notification. */\nexport interface RunFinished {\n run: RunRecord;\n session: CodingSession | null;\n}\n\nconst DISCOVERED_PAGE = 60;\n/** \"Show earlier\" doubles the read, up to the engine's own cap. */\nconst HISTORY_START = 24 * 1024 * 1024;\n\nfunction loadable<T>(data: T): Loadable<T> {\n return { data, loading: false, error: null, loadedAt: null };\n}\n\nfunction message(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** One open conversation: history from the provider's file + the live stream. */\nexport class SessionTranscript {\n readonly thread: ChatThreadStore;\n private builder: TranscriptBuilder = createTranscriptBuilder();\n private messages: readonly ChatMessage[] = [];\n private listeners = new Set<() => void>();\n private seqMark = 0;\n private pending: { seq: number; event: CodingEvent }[] = [];\n private activeRunId: string | null = null;\n /**\n * What the agent is doing right now, in words — the live line under the\n * transcript. Codex's `exec --json` reports only COMPLETED messages (no\n * token deltas), so between them this line is what shows the run is alive.\n */\n activity: string | null = null;\n state: { loading: boolean; unavailable: string | null; truncated: boolean; loadingEarlier?: boolean } = {\n loading: true,\n unavailable: null,\n truncated: false,\n };\n /** How much of the provider's file to read; \"Show earlier\" doubles it. */\n private maxBytes = HISTORY_START;\n\n constructor(\n readonly sessionId: string,\n private readonly client: CodingSessionsClient,\n ) {\n this.thread = createExternalThreadSource({\n getSnapshot: () => ({\n messages: this.messages,\n status: this.status(),\n conversationId: this.sessionId,\n // The transcript lives in the provider's own files, so it IS saved —\n // just not by AI Matrx. Nothing to announce.\n ephemeral: false,\n }),\n // The engine queues a prompt sent during a live run, so the composer\n // may send while an answer is still arriving (Send beside Stop).\n features: { surface: { sendWhileBusy: true } },\n subscribe: (listener) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n },\n onSubmit: async (input) => {\n await this.client.send(this.sessionId, input.text);\n },\n onCancel: async () => {\n const run = this.client.getState().runs[this.sessionId];\n if (run && !isTerminalRunStatus(run.status)) await this.client.stop(run.runId);\n },\n });\n }\n\n private status(): ChatThreadStatus {\n const run = this.client.getState().runs[this.sessionId];\n if (!run) return \"idle\";\n if (run.status === \"starting\") return \"submitted\";\n if (run.status === \"running\") return \"streaming\";\n return \"idle\";\n }\n\n notify(): void {\n this.messages = this.builder.messages();\n for (const listener of this.listeners) listener();\n }\n\n /** Read further back into a long chat. The transcript stays on screen meanwhile. */\n async loadEarlier(): Promise<void> {\n if (!this.state.truncated || this.state.loadingEarlier) return;\n this.maxBytes *= 4;\n this.state = { ...this.state, loadingEarlier: true };\n this.notify();\n await this.load(true);\n }\n\n async load(keepVisible = false): Promise<void> {\n if (!keepVisible) {\n this.state = { loading: true, unavailable: null, truncated: false };\n this.notify();\n }\n try {\n const history = await this.client.transport.call(\"history\", this.sessionId, { maxBytes: this.maxBytes });\n this.builder = createTranscriptBuilder();\n this.builder.applyAll(history.items);\n this.seqMark = history.seq;\n const run = this.client.getState().runs[this.sessionId];\n if (run && !isTerminalRunStatus(run.status)) {\n this.activeRunId = run.runId;\n this.builder.beginTurn();\n } else {\n this.builder.endTurn(\"completed\");\n }\n this.state = { loading: false, unavailable: history.unavailable, truncated: history.truncated };\n const queued = this.pending;\n this.pending = [];\n for (const entry of queued) this.onEvent(entry.event);\n } catch (error) {\n this.state = { loading: false, unavailable: message(error), truncated: false };\n }\n this.notify();\n }\n\n onEvent(event: CodingEvent): void {\n if (this.state.loading) {\n if (event.type === \"item\") this.pending.push({ seq: event.seq, event });\n return;\n }\n if (event.type === \"item\") {\n if (event.seq <= this.seqMark) return;\n this.seqMark = event.seq;\n this.builder.apply(event.item);\n if (event.item.kind === \"user\") {\n // The working bubble opens right under the prompt it answers.\n this.activeRunId = event.runId;\n this.builder.beginTurn();\n }\n this.activity = nextActivity(this.activity, event.item);\n this.notify();\n return;\n }\n if (event.type === \"run\") {\n const run = event.run;\n if (isTerminalRunStatus(run.status)) {\n this.activity = null;\n if (this.activeRunId === run.runId) {\n this.builder.endTurn(run.status, run.error);\n this.activeRunId = null;\n } else if (run.status === \"failed\" && run.error) {\n // A run that failed before producing anything still owes the\n // reader its real error.\n this.builder.endTurn(\"failed\", run.error);\n }\n }\n this.notify();\n }\n }\n}\n\nfunction nextActivity(current: string | null, item: import(\"../types\").TranscriptItem): string | null {\n switch (item.kind) {\n case \"user\":\n return \"Thinking…\";\n case \"text-delta\":\n return \"Writing…\";\n case \"text\":\n case \"reasoning\":\n case \"tool-result\":\n return \"Thinking…\";\n case \"tool-call\": {\n const subtitle = toolSubtitle(item.name, item.input);\n return `${friendlyToolName(item.name)}${subtitle ? ` — ${subtitle}` : \"\"}`;\n }\n default:\n return current;\n }\n}\n\n/** A read-only transcript of a chat found on disk, before taking it over. */\nexport interface PreviewState {\n loading: boolean;\n messages: readonly ChatMessage[];\n unavailable: string | null;\n truncated: boolean;\n}\n\nexport class CodingSessionsClient {\n private state: CodingSessionsState;\n private listeners = new Set<() => void>();\n private transcripts = new Map<string, SessionTranscript>();\n private finishedListeners = new Set<(finished: RunFinished) => void>();\n\n /** Hear about every run that ends (completed, stopped or failed). */\n onRunFinished = (listener: (finished: RunFinished) => void): (() => void) => {\n this.finishedListeners.add(listener);\n return () => {\n this.finishedListeners.delete(listener);\n };\n };\n\n constructor(readonly transport: CodingSessionsTransport) {\n this.state = {\n connection: transport.status(),\n providers: loadable([]),\n sessions: loadable([]),\n discovered: loadable([]),\n folders: loadable([]),\n runs: {},\n preferences: {},\n discoveredLimit: DISCOVERED_PAGE,\n };\n transport.onStatus((connection) => {\n const wasOpen = this.state.connection.state === \"open\";\n this.set({ connection });\n if (connection.state === \"open\" && !wasOpen) void this.refreshAll();\n });\n transport.subscribe((event) => this.onEvent(event));\n }\n\n getState = (): CodingSessionsState => this.state;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n private set(patch: Partial<CodingSessionsState>): void {\n this.state = { ...this.state, ...patch };\n for (const listener of this.listeners) listener();\n }\n\n private onEvent(event: CodingEvent): void {\n if (event.type === \"session\") {\n const list = this.state.sessions.data.filter((s) => s.id !== event.session.id);\n list.unshift(event.session);\n list.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n this.set({ sessions: { ...this.state.sessions, data: list } });\n } else if (event.type === \"run\") {\n const before = this.state.runs[event.run.sessionId];\n this.set({ runs: { ...this.state.runs, [event.run.sessionId]: event.run } });\n const ended =\n isTerminalRunStatus(event.run.status) &&\n (!before || before.runId !== event.run.runId || !isTerminalRunStatus(before.status));\n if (ended) {\n const session = this.state.sessions.data.find((s) => s.id === event.run.sessionId) ?? null;\n for (const listener of this.finishedListeners) listener({ run: event.run, session });\n }\n } else if (event.type === \"preferences\") {\n this.set({ preferences: event.preferences });\n return;\n }\n const sessionId = event.type === \"session\" ? event.session.id : event.type === \"run\" ? event.run.sessionId : event.sessionId;\n this.transcripts.get(sessionId)?.onEvent(event);\n }\n\n private async load<K extends \"providers\" | \"sessions\" | \"discovered\" | \"folders\">(\n key: K,\n fetcher: () => Promise<CodingSessionsState[K][\"data\"]>,\n ): Promise<void> {\n this.set({ [key]: { ...this.state[key], loading: true, error: null } } as Partial<CodingSessionsState>);\n try {\n const data = await fetcher();\n this.set({ [key]: { data, loading: false, error: null, loadedAt: Date.now() } } as Partial<CodingSessionsState>);\n } catch (error) {\n this.set({\n [key]: { ...this.state[key], loading: false, error: message(error) },\n } as Partial<CodingSessionsState>);\n }\n }\n\n refreshProviders = () => this.load(\"providers\", () => this.transport.call(\"providers\"));\n refreshDiscovered = () =>\n this.load(\"discovered\", () => this.transport.call(\"discoverSessions\", { limit: this.state.discoveredLimit }));\n\n /** List more of \"Your other chats\". */\n showMoreDiscovered = async (): Promise<void> => {\n this.set({ discoveredLimit: this.state.discoveredLimit + DISCOVERED_PAGE });\n await this.refreshDiscovered();\n };\n\n refreshPreferences = async (): Promise<void> => {\n try {\n this.set({ preferences: await this.transport.call(\"chatPreferences\") });\n } catch {\n /* the lists still work with no renames or pins */\n }\n };\n\n /** Rename, pin or hide a chat. Applied at once; the host's answer replaces it. */\n setPreference = async (key: string, patch: ChatPreference): Promise<void> => {\n const previous = this.state.preferences;\n const merged = { ...previous[key], ...patch };\n this.set({ preferences: { ...previous, [key]: merged } });\n try {\n this.set({ preferences: await this.transport.call(\"setChatPreference\", key, patch) });\n } catch (error) {\n this.set({ preferences: previous });\n throw error;\n }\n };\n\n search(query: string, cursor = 0): Promise<ChatSearchResult> {\n return this.transport.call(\"searchChats\", query, { cursor, limit: 30 });\n }\n\n /** FULL DOWNLOAD: this chat's complete provider file, from this computer. */\n readRawTranscript(provider: CodingProvider, providerSessionId: string): Promise<RawTranscript> {\n return this.transport.call(\"readRawTranscript\", provider, providerSessionId);\n }\n\n openFolder(path: string, target: OpenTarget): Promise<void> {\n return this.transport.call(\"openFolder\", path, target);\n }\n\n setSessionOptions(sessionId: string, options: { model?: string | null; effort?: string | null }) {\n return this.transport.call(\"setSessionOptions\", sessionId, options);\n }\n refreshFolders = () => this.load(\"folders\", () => this.transport.call(\"recentFolders\"));\n\n refreshSessions = async (): Promise<void> => {\n await this.load(\"sessions\", () => this.transport.call(\"listSessions\"));\n // The latest run of each session, so Running and statuses are right on load.\n const runs: Record<string, RunRecord> = {};\n await Promise.all(\n this.state.sessions.data.map(async (session) => {\n const list = await this.transport.call(\"listRuns\", session.id).catch(() => [] as RunRecord[]);\n const last = list[list.length - 1];\n if (last) runs[session.id] = last;\n }),\n );\n this.set({ runs: { ...runs, ...this.pickLive() } });\n };\n\n private pickLive(): Record<string, RunRecord> {\n const out: Record<string, RunRecord> = {};\n for (const [id, run] of Object.entries(this.state.runs)) {\n if (!isTerminalRunStatus(run.status)) out[id] = run;\n }\n return out;\n }\n\n refreshAll = async (): Promise<void> => {\n await Promise.all([\n this.refreshSessions(),\n this.refreshProviders(),\n this.refreshDiscovered(),\n this.refreshFolders(),\n this.refreshPreferences(),\n ]);\n for (const transcript of this.transcripts.values()) void transcript.load();\n };\n\n transcript(sessionId: string): SessionTranscript {\n let transcript = this.transcripts.get(sessionId);\n if (!transcript) {\n transcript = new SessionTranscript(sessionId, this);\n this.transcripts.set(sessionId, transcript);\n void transcript.load();\n }\n return transcript;\n }\n\n async readPreview(provider: CodingProvider, providerSessionId: string, maxBytes?: number): Promise<PreviewState> {\n try {\n const history = await this.transport.call(\n \"readTranscript\",\n provider,\n providerSessionId,\n maxBytes ? { maxBytes } : undefined,\n );\n const builder = createTranscriptBuilder();\n builder.applyAll(history.items);\n builder.endTurn(\"completed\");\n return {\n loading: false,\n messages: builder.messages(),\n unavailable: history.unavailable,\n truncated: history.truncated,\n };\n } catch (error) {\n return { loading: false, messages: [], unavailable: message(error), truncated: false };\n }\n }\n\n start(input: StartInput) {\n return this.transport.call(\"start\", input);\n }\n\n takeover(session: DiscoveredSession, agent?: AgentSelection | null) {\n return this.transport.call(\"takeover\", {\n provider: session.provider,\n providerSessionId: session.providerSessionId,\n cwd: session.cwd ?? \"\",\n title: session.title,\n ...(agent ? { agent } : {}),\n });\n }\n\n send(sessionId: string, prompt: string) {\n return this.transport.call(\"send\", sessionId, prompt);\n }\n\n stop(runId: string) {\n return this.transport.call(\"stop\", runId);\n }\n}\n","/**\n * `TranscriptItem`s → `@ai-matrx/chat` messages.\n *\n * The transcript is rendered by THE one person ↔ agent chat interface\n * (`@ai-matrx/chat`), not by a second message list: its message/part model\n * already has text, reasoning, tool parts on the industry tool-call state\n * machine, notices and errors, and its React transcript already renders them\n * (markdown, collapsible tool cards, streaming). This module is the only\n * adapter: one assistant message per turn, parts in arrival order.\n *\n * Identity is preserved on purpose: a change rebuilds ONLY the message it\n * touched, so the chat store's per-message subscriptions wake one bubble per\n * token instead of the whole list.\n */\n\nimport {\n createChatMessage,\n type ChatMessage,\n type ChatPart,\n type ChatToolPart,\n} from \"@ai-matrx/chat\";\n\nimport { runErrorLabel } from \"./provider-health\";\nimport { toolSubtitle } from \"./tool-labels\";\nimport type { RunStatus, RunUsage, TranscriptItem } from \"./types\";\n\nexport interface TranscriptBuilder {\n apply(item: TranscriptItem): void;\n applyAll(items: readonly TranscriptItem[]): void;\n /** Close the turn in progress with the run's final status. */\n endTurn(status: RunStatus, error?: string | null): void;\n /** Mark a turn as in progress (the assistant bubble shows it is working). */\n beginTurn(): void;\n messages(): readonly ChatMessage[];\n lastUsage(): { usage: RunUsage; costUsd: number | null } | null;\n}\n\ninterface Working {\n message: ChatMessage;\n /** item id → index in `message.parts`. */\n index: Map<string, number>;\n}\n\nexport function createTranscriptBuilder(): TranscriptBuilder {\n const list: ChatMessage[] = [];\n let current: Working | null = null;\n let turn = 0;\n let usage: { usage: RunUsage; costUsd: number | null } | null = null;\n /** tool call id → [message index, part index] for results that arrive late. */\n const toolHome = new Map<string, { messageIndex: number; partIndex: number }>();\n\n function commit(working: Working, parts: ChatPart[], status?: ChatMessage[\"status\"]): void {\n const next: ChatMessage = {\n ...working.message,\n parts,\n status: status ?? working.message.status,\n };\n working.message = next;\n const at = list.findIndex((m) => m.id === next.id);\n if (at >= 0) list[at] = next;\n }\n\n function ensureAssistant(): Working {\n if (current) return current;\n turn += 1;\n const message = createChatMessage({\n id: `turn-${turn}-${list.length}`,\n role: \"assistant\",\n status: \"streaming\",\n });\n list.push(message);\n current = { message, index: new Map() };\n return current;\n }\n\n function upsertPart(id: string, build: (existing: ChatPart | null) => ChatPart): void {\n const working = ensureAssistant();\n const parts = [...working.message.parts];\n const at = working.index.get(id);\n if (at === undefined) {\n working.index.set(id, parts.length);\n parts.push(build(null));\n } else {\n parts[at] = build(parts[at] ?? null);\n }\n commit(working, parts);\n }\n\n function closeCurrent(status: ChatMessage[\"status\"]): void {\n if (!current) return;\n const working = current;\n const parts = working.message.parts.map((part): ChatPart => {\n if (part.type === \"reasoning\" && part.state === \"streaming\") return { ...part, state: \"done\" };\n if (part.type === \"tool\" && part.state === \"input-available\" && status !== \"streaming\") {\n if (status === \"cancelled\") {\n return { ...part, state: \"output-error\", errorText: \"Stopped before this finished.\" };\n }\n if (status === \"error\") {\n return { ...part, state: \"output-error\", errorText: \"The run ended before this finished.\" };\n }\n }\n return part;\n });\n commit(working, parts, status);\n current = null;\n }\n\n const builder: TranscriptBuilder = {\n apply(item) {\n switch (item.kind) {\n case \"user\": {\n closeCurrent(\"complete\");\n list.push(\n createChatMessage({\n id: `user-${item.id}`,\n role: \"user\",\n parts: [{ type: \"text\", text: item.text }],\n status: \"complete\",\n metadata: item.at ? { createdAt: item.at } : undefined,\n }),\n );\n return;\n }\n case \"text-delta\":\n upsertPart(item.id, (existing) =>\n existing && existing.type === \"text\"\n ? { type: \"text\", text: existing.text + item.text }\n : { type: \"text\", text: item.text },\n );\n return;\n case \"text\":\n upsertPart(item.id, () => ({ type: \"text\", text: item.text }));\n return;\n case \"reasoning\":\n upsertPart(item.id, () => ({ type: \"reasoning\", text: item.text, state: \"done\" }));\n return;\n case \"tool-call\": {\n // The key argument (the command, the file) rides as the card's one\n // progress beat, which the chat card shows beside the tool's name.\n const subtitle = toolSubtitle(item.name, item.input);\n const progress = subtitle ? [{ toolName: item.name, message: subtitle, percent: null, at: null }] : [];\n upsertPart(item.id, (existing) =>\n existing && existing.type === \"tool\"\n ? { ...existing, input: item.input, progress }\n : {\n type: \"tool\",\n toolCallId: item.id,\n toolName: item.name,\n state: \"input-available\",\n input: item.input,\n output: null,\n errorText: null,\n progress,\n delegated: false,\n },\n );\n const working = current;\n if (working) {\n const partIndex = working.index.get(item.id);\n const messageIndex = list.findIndex((m) => m.id === working.message.id);\n if (partIndex !== undefined && messageIndex >= 0) {\n toolHome.set(item.id, { messageIndex, partIndex });\n }\n }\n return;\n }\n case \"tool-result\": {\n const home = toolHome.get(item.id);\n if (!home) {\n // A result whose call we never saw (a history read that started\n // mid-conversation). Show it as its own finished card.\n upsertPart(item.id, () => ({\n type: \"tool\",\n toolCallId: item.id,\n toolName: \"Tool\",\n state: item.isError ? \"output-error\" : \"output-available\",\n input: null,\n output: item.isError ? null : item.output,\n errorText: item.isError ? item.output || \"The tool reported an error.\" : null,\n progress: [],\n delegated: false,\n }));\n return;\n }\n const message = list[home.messageIndex];\n const part = message?.parts[home.partIndex];\n if (!message || !part || part.type !== \"tool\") return;\n const nextPart: ChatToolPart = item.isError\n ? { ...part, state: \"output-error\", errorText: item.output || \"The tool reported an error.\", output: null }\n : { ...part, state: \"output-available\", output: item.output };\n const parts = [...message.parts];\n parts[home.partIndex] = nextPart;\n const next: ChatMessage = { ...message, parts };\n list[home.messageIndex] = next;\n if (current && current.message.id === next.id) current.message = next;\n return;\n }\n case \"usage\":\n usage = { usage: item.usage, costUsd: item.costUsd };\n return;\n case \"notice\":\n upsertPart(item.id, () => ({\n type: \"notice\",\n level: item.level === \"warning\" ? \"medium\" : \"info\",\n code: null,\n userMessage: item.text,\n remedy: null,\n }));\n return;\n case \"error\": {\n // Codex reports one failure up to three ways (a top-level `error`,\n // `turn.failed`, and the run's final error): say it once.\n // A known class (a refused model) shows its short label, never the\n // provider's raw JSON.\n const text = runErrorLabel(item.text);\n const said = current?.message.parts.some((p) => p.type === \"error\" && p.message.trim() === text.trim());\n if (said) return;\n upsertPart(item.id, () => ({\n type: \"error\",\n errorType: \"provider\",\n code: null,\n message: text,\n userMessage: text,\n recoverable: true,\n remedy: null,\n }));\n return;\n }\n }\n },\n applyAll(items) {\n for (const item of items) builder.apply(item);\n },\n beginTurn() {\n ensureAssistant();\n },\n endTurn(status, error) {\n if (status === \"failed\" && error) {\n builder.apply({ kind: \"error\", id: `run-error-${list.length}`, text: error });\n }\n if (status === \"stopped\" && current) {\n builder.apply({\n kind: \"notice\",\n id: `run-stopped-${list.length}`,\n level: \"info\",\n text: \"You stopped this run.\",\n });\n }\n closeCurrent(status === \"stopped\" ? \"cancelled\" : status === \"failed\" ? \"error\" : \"complete\");\n },\n messages() {\n // A fresh array per read: the chat store compares the list by identity\n // to notice appends, and the message objects inside keep theirs.\n return list.slice();\n },\n lastUsage() {\n return usage;\n },\n };\n return builder;\n}\n","/**\n * The New session form's checks, framework-free so they are testable without\n * a DOM. Every refusal names its field and says what to do — a Start button\n * that silently does nothing is the dead control the platform forbids.\n *\n * Validation offers, never blocks: a usage limit or an expired sign-in is a\n * WARNING (the person may have fixed it a minute ago), but a provider that is\n * not installed, a missing folder or an empty request genuinely cannot run.\n */\n\nimport type { FolderCheck, ProviderStatus } from \"../types\";\n\nexport type NewSessionField = \"agent\" | \"folder\" | \"prompt\";\n\nexport interface NewSessionErrors {\n agent?: string;\n folder?: string;\n /** The typed path that does not exist, when creating it is on offer. */\n createFolder?: string;\n prompt?: string;\n}\n\nexport const FIELD_ORDER: readonly NewSessionField[] = [\"agent\", \"folder\", \"prompt\"];\n\nexport async function validateNewSession(input: {\n provider: ProviderStatus | null;\n folder: string;\n prompt: string;\n checkFolder: (path: string) => Promise<FolderCheck>;\n}): Promise<NewSessionErrors> {\n const errors: NewSessionErrors = {};\n const p = input.provider;\n if (p && (!p.installed || !p.loggedIn)) {\n errors.agent = `${p.problem ?? `${p.label} can't run here yet.`} ${p.fix ?? \"\"}`.trim();\n }\n if (!input.folder.trim()) {\n errors.folder = \"Choose a folder, or type one, for it to work in.\";\n } else {\n try {\n const check = await input.checkFolder(input.folder);\n if (!check.exists) {\n errors.folder = \"That folder doesn't exist on this computer.\";\n errors.createFolder = check.path;\n } else if (!check.isDirectory) {\n errors.folder = \"That path is a file, not a folder.\";\n }\n } catch (error) {\n errors.folder = `Couldn't check that folder: ${error instanceof Error ? error.message : String(error)}`;\n }\n }\n if (!input.prompt.trim()) errors.prompt = \"Tell it what to do first.\";\n return errors;\n}\n\nexport function firstInvalidField(errors: NewSessionErrors): NewSessionField | null {\n return FIELD_ORDER.find((field) => errors[field] !== undefined) ?? null;\n}\n"],"mappings":"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","names":["prettyPath","import_react","import_external_store","import_design_system","import_format","import_react","import_design_system","message","import_format","prettyPath","import_react","import_jsx_runtime","import_jsx_runtime","prettyPath","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","prettyPath","message","history","import_jsx_runtime","prettyPath"]}
|