@drewswiredin/backstage-plugin-assistants 0.6.0 → 0.7.0
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/dist/AssistantsNavIcon.esm.js +2 -22
- package/dist/AssistantsNavIcon.esm.js.map +1 -1
- package/dist/collapsible/AssistantsList.esm.js +2 -12
- package/dist/collapsible/AssistantsList.esm.js.map +1 -1
- package/dist/collapsible/CollapsiblePage.esm.js +144 -71
- package/dist/collapsible/CollapsiblePage.esm.js.map +1 -1
- package/dist/collapsible/ConversationsPanel.esm.js +4 -12
- package/dist/collapsible/ConversationsPanel.esm.js.map +1 -1
- package/dist/collapsible/StatusDot.esm.js +39 -0
- package/dist/collapsible/StatusDot.esm.js.map +1 -0
- package/dist/collapsible/surface/ConversationSurface.esm.js +2 -1
- package/dist/collapsible/surface/ConversationSurface.esm.js.map +1 -1
- package/dist/collapsible/surface/parts.esm.js +36 -8
- package/dist/collapsible/surface/parts.esm.js.map +1 -1
- package/dist/collapsible/threadListAdapter.esm.js +9 -7
- package/dist/collapsible/threadListAdapter.esm.js.map +1 -1
- package/dist/collapsible/useAssistantRuntime.esm.js +59 -22
- package/dist/collapsible/useAssistantRuntime.esm.js.map +1 -1
- package/dist/collapsible/useThreadStatus.esm.js +61 -78
- package/dist/collapsible/useThreadStatus.esm.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollapsiblePage.esm.js","sources":["../../src/collapsible/CollapsiblePage.tsx"],"sourcesContent":["// Vendored react-ui Thread CSS. Imported at the TOP of this page entry so it\n// bundles into this page's lazy chunk: react-ui ships `sideEffects: false`, so\n// a bare `@assistant-ui/react-ui` CSS import gets tree-shaken and the Thread\n// renders unstyled. These local copies are not subject to that.\nimport './surface/styles/assistant-ui.css';\nimport './surface/styles/assistant-ui-markdown.css';\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport useAsync from 'react-use/lib/useAsync';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { Content, Progress, ResponseErrorPanel } from '@backstage/core-components';\nimport { makeStyles } from '@material-ui/core/styles';\nimport {\n Badge,\n FormControl,\n IconButton,\n ListItemIcon,\n ListSubheader,\n MenuItem,\n Select,\n Tooltip,\n Typography,\n} from '@material-ui/core';\nimport AddIcon from '@material-ui/icons/Add';\nimport ChatBubbleOutlineIcon from '@material-ui/icons/ChatBubbleOutline';\nimport CheckIcon from '@material-ui/icons/Check';\nimport ChevronRightIcon from '@material-ui/icons/ChevronRight';\nimport StarIcon from '@material-ui/icons/Star';\nimport {\n AssistantRuntimeProvider,\n useAssistantRuntime,\n useRemoteThreadListRuntime,\n type ThreadListState,\n} from '@assistant-ui/react';\nimport type {\n AssistantSummary,\n ModelId,\n ModelOption,\n StatusResponse,\n} from '@drewswiredin/backstage-plugin-assistants-common';\nimport { assistantsApiRef, type AssistantsApi } from '../api';\nimport { ConversationSurface } from './surface';\nimport { AssistantAvatar } from './surface/AssistantAvatar';\nimport { SidePane } from './SidePane';\nimport { FullHeightRegion } from './FullHeightRegion';\nimport {\n createThreadListAdapter,\n patchThread,\n type ThreadCustomMetadata,\n type ThreadSummary,\n} from './threadListAdapter';\nimport { makeRuntimeHook } from './useAssistantRuntime';\nimport { useThreadStatus, type ConvStatus } from './useThreadStatus';\n\nconst SIDEPANE_COLLAPSED_KEY = 'ai-chat-sidepane-collapsed';\n\nfunction loadSidePaneCollapsed() {\n try {\n return localStorage.getItem(SIDEPANE_COLLAPSED_KEY) === 'true';\n } catch {\n return false;\n }\n}\n\nconst useStyles = makeStyles(theme => ({\n content: {\n flex: 1,\n minHeight: 0,\n display: 'flex',\n flexDirection: 'column',\n },\n shell: {\n display: 'flex',\n flex: 1,\n minHeight: 0,\n overflow: 'hidden',\n backgroundColor: theme.palette.background.default,\n paddingTop: 0,\n paddingRight: theme.spacing(1),\n paddingBottom: theme.spacing(1),\n paddingLeft: 0,\n gap: theme.spacing(1),\n },\n sidePane: {\n width: 320,\n flexShrink: 0,\n minHeight: 0,\n overflowY: 'auto',\n overflowX: 'hidden',\n },\n sidePaneRail: {\n width: 56,\n flexShrink: 0,\n minHeight: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n paddingBottom: theme.spacing(0.5),\n borderRight: `1px solid ${theme.palette.divider}`,\n overflow: 'hidden',\n },\n sidePaneRailHeader: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '100%',\n minHeight: 44,\n flexShrink: 0,\n borderBottom: `1px solid ${theme.palette.divider}`,\n },\n sidePaneRailAssistants: {\n flexShrink: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n paddingTop: theme.spacing(0.75),\n },\n sidePaneRailDivider: {\n flexShrink: 0,\n width: 24,\n borderTop: `1px solid ${theme.palette.divider}`,\n margin: theme.spacing(0.75, 0),\n },\n sidePaneRailControls: {\n flexShrink: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n paddingBottom: theme.spacing(1),\n },\n sidePaneRailChats: {\n flex: 1,\n minHeight: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n overflowY: 'auto',\n overflowX: 'hidden',\n },\n sidePaneRailButton: {\n color: theme.palette.text.secondary,\n },\n sidePaneRailButtonActive: {\n color: theme.palette.primary.main,\n backgroundColor: theme.palette.action.selected,\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n },\n threadPane: {\n display: 'flex',\n flex: 1,\n flexDirection: 'column',\n minWidth: 0,\n backgroundColor: theme.palette.background.paper,\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: theme.shape.borderRadius,\n boxShadow: theme.shadows[1],\n overflow: 'hidden',\n },\n threadHeader: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: theme.spacing(2),\n minHeight: 36,\n padding: theme.spacing(0, 2),\n backgroundColor: theme.palette.background.paper,\n borderBottom: `1px solid ${theme.palette.divider}`,\n },\n threadIdentity: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n minWidth: 0,\n flex: 1,\n },\n assistantName: {\n fontWeight: 600,\n color: theme.palette.text.primary,\n whiteSpace: 'nowrap',\n flexShrink: 0,\n },\n threadTitle: {\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n color: theme.palette.text.secondary,\n },\n modelSelect: {\n fontSize: theme.typography.caption.fontSize,\n color: theme.palette.text.secondary,\n borderRadius: 999,\n transition: theme.transitions.create('background-color'),\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n '& .MuiSelect-select': {\n display: 'flex',\n alignItems: 'center',\n borderRadius: 999,\n paddingTop: theme.spacing(0.5),\n paddingBottom: theme.spacing(0.5),\n paddingLeft: theme.spacing(1.25),\n paddingRight: theme.spacing(3),\n '&:focus': {\n backgroundColor: 'transparent',\n borderRadius: 999,\n },\n },\n '& .MuiSelect-icon': {\n color: theme.palette.text.secondary,\n right: theme.spacing(0.5),\n },\n },\n modelGroupLabel: {\n lineHeight: 2,\n fontSize: theme.typography.caption.fontSize,\n fontWeight: 600,\n textTransform: 'uppercase',\n letterSpacing: 0.5,\n color: theme.palette.text.secondary,\n backgroundColor: theme.palette.background.paper,\n },\n modelItem: {\n paddingTop: theme.spacing(0.75),\n paddingBottom: theme.spacing(0.75),\n },\n modelItemCheck: {\n minWidth: theme.spacing(3.5),\n color: theme.palette.primary.main,\n },\n modelDefaultStar: {\n fontSize: '1rem',\n color: theme.palette.warning.main,\n marginLeft: theme.spacing(1),\n },\n threadBody: {\n flex: 1,\n minHeight: 0,\n display: 'flex',\n flexDirection: 'column',\n },\n // The \"generating\" indicator: a pulsing dot, distinct from the solid unread dot.\n '@keyframes auiPulse': {\n '0%': { transform: 'scale(1)', opacity: 1 },\n '50%': { transform: 'scale(1.5)', opacity: 0.45 },\n '100%': { transform: 'scale(1)', opacity: 1 },\n },\n pulseDot: {\n animation: '$auiPulse 1.2s ease-in-out infinite',\n },\n}));\n\n/**\n * Split a model id into a display vendor + name. Our models route through one\n * provider (e.g. `openrouter`) but the meaningful family is the vendor prefix in\n * the model name (`google/gemini-2.5-flash`). Falls back to the provider / raw\n * id when there's no `/`.\n */\nfunction splitModel(\n id: ModelId,\n pool: ModelOption[],\n): { vendor: string; name: string } {\n const opt = pool.find(m => m.id === id);\n const raw = opt?.model ?? id;\n const slash = raw.indexOf('/');\n if (slash !== -1) {\n return { vendor: raw.slice(0, slash), name: raw.slice(slash + 1) };\n }\n return { vendor: opt?.provider ?? 'models', name: raw };\n}\n\n/** The short model name (after the vendor prefix), for the selector trigger. */\nfunction modelLabel(id: ModelId, pool: ModelOption[]): string {\n return splitModel(id, pool).name;\n}\n\n// ---------------------------------------------------------------------------\n// Page entry\n// ---------------------------------------------------------------------------\n\n/**\n * The collapsible AI chat page. Reads the target assistant from\n * `?assistant=<id>` (the assistant rail lives in the Backstage nav), loads\n * `/status`, and renders the conversation experience for the chosen assistant.\n * Conversations persist server-side (see ADR-free architecture: docs/architecture.html).\n *\n * @public\n */\nexport function CollapsiblePage() {\n const api = useApi(assistantsApiRef);\n const [searchParams] = useSearchParams();\n const requestedAssistant = searchParams.get('assistant');\n\n const status = useAsync(() => api.getStatus(), [api]);\n\n if (status.loading) {\n return <Progress />;\n }\n if (status.error) {\n return <ResponseErrorPanel error={status.error} />;\n }\n if (!status.value) {\n return null;\n }\n const assistants = status.value.assistants;\n if (assistants.length === 0) {\n return (\n <ResponseErrorPanel\n error={new Error('No assistants are available to you.')}\n />\n );\n }\n const assistant =\n assistants.find(a => a.id === requestedAssistant) ?? assistants[0];\n // Keyed by assistant.id: a fresh server-backed runtime per assistant. Switching\n // never loses an in-flight reply — the backend persists it on finish.\n return (\n <CollapsibleChat key={assistant.id} status={status.value} assistant={assistant} />\n );\n}\n\n// ---------------------------------------------------------------------------\n// Resolve the backend base URL, then build the runtime\n// ---------------------------------------------------------------------------\n\nfunction CollapsibleChat({\n status,\n assistant,\n}: {\n status: StatusResponse;\n assistant: AssistantSummary;\n}) {\n const api = useApi(assistantsApiRef);\n const baseUrl = useAsync(() => api.getBaseUrl(), [api]);\n\n if (baseUrl.loading) {\n return <Progress />;\n }\n if (baseUrl.error || !baseUrl.value) {\n return (\n <ResponseErrorPanel\n error={baseUrl.error ?? new Error('Failed to resolve backend URL')}\n />\n );\n }\n return (\n <ChatRuntime\n status={status}\n assistant={assistant}\n api={api}\n baseUrl={baseUrl.value}\n />\n );\n}\n\nfunction ChatRuntime({\n status,\n assistant,\n api,\n baseUrl,\n}: {\n status: StatusResponse;\n assistant: AssistantSummary;\n api: AssistantsApi;\n baseUrl: string;\n}) {\n const defaultModel = assistant.defaultModel ?? status.defaultModel;\n // Drives the transport body; updated by the model picker + on thread switch.\n const modelIdRef = useRef<ModelId>(defaultModel);\n\n const adapter = useMemo(\n () => createThreadListAdapter(api, assistant.id),\n [api, assistant.id],\n );\n const runtimeHook = useMemo(\n () => makeRuntimeHook({ api, baseUrl, assistantId: assistant.id, modelIdRef }),\n [api, baseUrl, assistant.id],\n );\n const runtime = useRemoteThreadListRuntime({ adapter, runtimeHook });\n\n return (\n <AssistantRuntimeProvider runtime={runtime}>\n <ChatChrome\n status={status}\n assistant={assistant}\n api={api}\n modelIdRef={modelIdRef}\n defaultModel={defaultModel}\n />\n </AssistantRuntimeProvider>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Chrome (inside the runtime provider) — pure view of server thread state\n// ---------------------------------------------------------------------------\n\nfunction ChatChrome({\n status,\n assistant,\n api,\n modelIdRef,\n defaultModel,\n}: {\n status: StatusResponse;\n assistant: AssistantSummary;\n api: AssistantsApi;\n modelIdRef: React.MutableRefObject<ModelId>;\n defaultModel: ModelId;\n}) {\n const classes = useStyles();\n const runtime = useAssistantRuntime();\n const [, setSearchParams] = useSearchParams();\n\n // Reactive snapshot of the server-backed thread list.\n const [threadList, setThreadList] = useState<ThreadListState>(() =>\n runtime.threads.getState(),\n );\n useEffect(() => {\n setThreadList(runtime.threads.getState());\n return runtime.threads.subscribe(() =>\n setThreadList(runtime.threads.getState()),\n );\n }, [runtime]);\n\n const activeId = threadList.mainThreadId;\n const activeItem = threadList.threadItems[activeId];\n const activeRemoteId = activeItem?.remoteId;\n const activeTitle = activeItem?.title ?? '';\n\n // Single source of truth for read/working/unread, derived from server + signals.\n const { statusOf, agentStatus, markRead, finishedTick } = useThreadStatus(\n api,\n activeRemoteId,\n );\n\n // On first load for this agent (the component is keyed by assistant.id), land\n // on the agent's MOST RECENT conversation. The runtime defaults the main thread\n // to a blank \"new thread\"; we switch off it to the latest existing conversation\n // so selecting an agent shows a conversation, never a bare agent. An agent with\n // no conversations stays on the unpersisted draft (the only no-\"+\" empty state).\n // A new conversation is created ONLY via \"+\", never by typing.\n const didSelectInitial = useRef(false);\n useEffect(() => {\n if (didSelectInitial.current || threadList.isLoading) return;\n didSelectInitial.current = true;\n // Only auto-select if we're still on the blank draft (don't override a user pick).\n if (activeId !== threadList.newThreadId) return;\n const mostRecent = [...threadList.threadIds]\n .map(id => ({\n id,\n updatedAt:\n (threadList.threadItems[id]?.custom as Partial<ThreadCustomMetadata>)\n ?.updatedAt ?? '',\n }))\n .sort((a, b) => (a.updatedAt < b.updatedAt ? 1 : -1))[0]?.id;\n if (mostRecent) {\n void runtime.threads.switchToThread(mostRecent);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [threadList.isLoading]);\n\n const conversations = useMemo<ThreadSummary[]>(\n () =>\n threadList.threadIds.map(id => {\n const item = threadList.threadItems[id];\n const custom = item?.custom as Partial<ThreadCustomMetadata> | undefined;\n // Every dot derives from the single status store; the focused\n // conversation shows neither (you're looking at it).\n const st: ConvStatus = id === activeId ? 'read' : statusOf(item?.remoteId);\n return {\n id,\n remoteId: item?.remoteId,\n title: item?.title ?? 'New Chat',\n pinned: custom?.pinned ?? false,\n unread: st === 'unread',\n generating: st === 'working',\n };\n }),\n [threadList, activeId, statusOf],\n );\n\n // A turn finished — refresh the thread list so the sidebar picks up new titles.\n useEffect(() => {\n if (finishedTick > 0) {\n void runtime.threads.reload();\n }\n }, [finishedTick, runtime]);\n\n // Model picker: limited to the assistant's allowlist (else the global pool).\n const allowedModels = useMemo<ModelId[]>(\n () => assistant.models ?? status.models.map(m => m.id),\n [assistant.models, status.models],\n );\n const modelGroups = useMemo<Array<[string, ModelId[]]>>(() => {\n const byVendor = new Map<string, ModelId[]>();\n for (const id of allowedModels) {\n const { vendor } = splitModel(id, status.models);\n const list = byVendor.get(vendor);\n if (list) list.push(id);\n else byVendor.set(vendor, [id]);\n }\n return [...byVendor.entries()];\n }, [allowedModels, status.models]);\n const resolveModel = useCallback(\n (stored: string | null | undefined): ModelId =>\n stored && allowedModels.includes(stored) ? stored : defaultModel,\n [allowedModels, defaultModel],\n );\n\n const [modelId, setModelId] = useState<ModelId>(() =>\n resolveModel((activeItem?.custom as Partial<ThreadCustomMetadata> | undefined)?.model),\n );\n\n // Adopt the active thread's saved model on switch (keyed on the active id only).\n useEffect(() => {\n const stored = (\n threadList.threadItems[activeId]?.custom as\n | Partial<ThreadCustomMetadata>\n | undefined\n )?.model;\n const next = resolveModel(stored);\n setModelId(next);\n modelIdRef.current = next;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeId]);\n\n // Viewing a conversation marks it read — instantly in the store, persisted on\n // the server. The conversation dot and the agent rollup both derive from the\n // store, so they clear together.\n useEffect(() => {\n if (activeRemoteId) markRead(activeRemoteId);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeRemoteId]);\n\n const [sidePaneCollapsed, setSidePaneCollapsed] = useState(loadSidePaneCollapsed);\n useEffect(() => {\n try {\n localStorage.setItem(SIDEPANE_COLLAPSED_KEY, String(sidePaneCollapsed));\n } catch {\n // storage unavailable\n }\n }, [sidePaneCollapsed]);\n\n const handleSelectAssistant = useCallback(\n (id: string) => {\n if (id !== assistant.id) setSearchParams({ assistant: id });\n },\n [assistant.id, setSearchParams],\n );\n\n const handleNew = useCallback(() => {\n void (async () => {\n await runtime.threads.switchToNewThread();\n try {\n await runtime.threads.mainItem.initialize();\n await runtime.threads.reload();\n } catch {\n // already initialized; safe to ignore\n }\n })();\n }, [runtime]);\n\n const handleSelect = useCallback(\n (id: string | null) => {\n if (id) void runtime.threads.switchToThread(id);\n },\n [runtime],\n );\n\n const handleRename = useCallback(\n (id: string, title: string) => {\n void (async () => {\n await runtime.threads.getItemById(id).rename(title);\n await runtime.threads.reload();\n })();\n },\n [runtime],\n );\n\n const handleDelete = useCallback(\n (id: string) => {\n void runtime.threads.getItemById(id).delete();\n },\n [runtime],\n );\n\n const handlePin = useCallback(\n async (id: string) => {\n const item = threadList.threadItems[id];\n if (!item?.remoteId) return;\n const pinned =\n (item.custom as Partial<ThreadCustomMetadata> | undefined)?.pinned ??\n false;\n try {\n await patchThread(api, item.remoteId, { pinned: !pinned });\n await runtime.threads.reload();\n } catch {\n // best-effort\n }\n },\n [api, runtime, threadList],\n );\n\n const handleModelChange = useCallback(\n (next: ModelId) => {\n setModelId(next);\n modelIdRef.current = next;\n if (activeRemoteId) {\n void patchThread(api, activeRemoteId, { model: next });\n }\n },\n [api, activeRemoteId, modelIdRef],\n );\n\n const modelPicker = (\n <FormControl>\n <Select\n value={modelId}\n onChange={e => handleModelChange(e.target.value as ModelId)}\n disableUnderline\n className={classes.modelSelect}\n inputProps={{ 'aria-label': 'Model' }}\n renderValue={value => modelLabel(value as ModelId, status.models)}\n MenuProps={{\n anchorOrigin: { vertical: 'bottom', horizontal: 'right' },\n transformOrigin: { vertical: 'top', horizontal: 'right' },\n getContentAnchorEl: null,\n }}\n >\n {modelGroups.flatMap(([vendor, ids]) => [\n <ListSubheader\n key={`group-${vendor}`}\n disableSticky\n className={classes.modelGroupLabel}\n >\n {vendor}\n </ListSubheader>,\n ...ids.map(id => (\n <MenuItem key={id} value={id} className={classes.modelItem}>\n <ListItemIcon className={classes.modelItemCheck}>\n {id === modelId ? <CheckIcon fontSize=\"small\" /> : null}\n </ListItemIcon>\n <span style={{ flexGrow: 1 }}>{modelLabel(id, status.models)}</span>\n {id === defaultModel && (\n <Tooltip title=\"Assistant default\">\n <StarIcon\n className={classes.modelDefaultStar}\n aria-label=\"Assistant default\"\n />\n </Tooltip>\n )}\n </MenuItem>\n )),\n ])}\n </Select>\n </FormControl>\n );\n\n return (\n <FullHeightRegion>\n <Content noPadding className={classes.content}>\n <div className={classes.shell}>\n {sidePaneCollapsed ? (\n <aside\n className={classes.sidePaneRail}\n aria-label=\"AI chat sidebar collapsed\"\n >\n <div className={classes.sidePaneRailHeader}>\n <Tooltip title=\"Expand\" placement=\"right\">\n <IconButton\n size=\"small\"\n className={classes.sidePaneRailButton}\n aria-label=\"Expand AI chat sidebar\"\n onClick={() => setSidePaneCollapsed(false)}\n >\n <ChevronRightIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </div>\n <nav className={classes.sidePaneRailAssistants} aria-label=\"Assistants\">\n {status.assistants.map(a => (\n <Tooltip key={a.id} title={a.title} placement=\"right\">\n <IconButton\n size=\"small\"\n className={`${classes.sidePaneRailButton} ${\n a.id === assistant.id\n ? classes.sidePaneRailButtonActive\n : ''\n }`}\n aria-label={a.title}\n onClick={() => handleSelectAssistant(a.id)}\n >\n <Badge\n color={\n agentStatus(a.id) === 'working' ? 'primary' : 'error'\n }\n variant=\"dot\"\n overlap=\"circular\"\n invisible={agentStatus(a.id) === 'read'}\n classes={\n agentStatus(a.id) === 'working'\n ? { dot: classes.pulseDot }\n : undefined\n }\n >\n <AssistantAvatar color={a.color} size={24} />\n </Badge>\n </IconButton>\n </Tooltip>\n ))}\n </nav>\n <div className={classes.sidePaneRailDivider} />\n <div className={classes.sidePaneRailControls}>\n <Tooltip title=\"New Chat\" placement=\"right\">\n <IconButton\n size=\"small\"\n className={classes.sidePaneRailButton}\n aria-label=\"New Chat\"\n onClick={handleNew}\n >\n <AddIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </div>\n <nav\n className={classes.sidePaneRailChats}\n aria-label=\"AI chat conversations\"\n >\n {conversations.map(conversation => (\n <Tooltip\n key={conversation.id}\n title={conversation.title}\n placement=\"right\"\n >\n <IconButton\n size=\"small\"\n className={`${classes.sidePaneRailButton} ${\n conversation.id === activeId\n ? classes.sidePaneRailButtonActive\n : ''\n }`}\n aria-label={conversation.title}\n onClick={() => handleSelect(conversation.id)}\n >\n <Badge\n color={conversation.generating ? 'primary' : 'error'}\n variant=\"dot\"\n overlap=\"circular\"\n invisible={\n !conversation.generating && !conversation.unread\n }\n classes={\n conversation.generating\n ? { dot: classes.pulseDot }\n : undefined\n }\n >\n <ChatBubbleOutlineIcon fontSize=\"small\" />\n </Badge>\n </IconButton>\n </Tooltip>\n ))}\n </nav>\n </aside>\n ) : (\n <aside className={classes.sidePane} aria-label=\"AI chat sidepane\">\n <SidePane\n assistants={status.assistants}\n activeAssistantId={assistant.id}\n onSelectAssistant={handleSelectAssistant}\n agentStatus={agentStatus}\n conversations={conversations}\n activeId={activeId}\n onNew={handleNew}\n onSelect={handleSelect}\n onRename={handleRename}\n onPin={handlePin}\n onDelete={handleDelete}\n onCollapse={() => setSidePaneCollapsed(true)}\n />\n </aside>\n )}\n\n <main className={classes.threadPane} aria-label=\"AI chat thread\">\n <div className={classes.threadHeader}>\n <div className={classes.threadIdentity}>\n <AssistantAvatar color={assistant.color} size={22} />\n <Typography variant=\"subtitle2\" className={classes.assistantName}>\n {assistant.title}\n </Typography>\n {activeTitle && (\n <Typography\n variant=\"body2\"\n className={classes.threadTitle}\n title={activeTitle}\n >\n · {activeTitle}\n </Typography>\n )}\n </div>\n {modelPicker}\n </div>\n <div className={classes.threadBody}>\n <ConversationSurface\n composerPlaceholder={assistant.ui?.composer?.placeholder}\n suggestions={assistant.ui?.suggestions}\n assistantColor={assistant.color}\n />\n </div>\n </main>\n </div>\n </Content>\n </FullHeightRegion>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CollapsiblePage.esm.js","sources":["../../src/collapsible/CollapsiblePage.tsx"],"sourcesContent":["// Vendored react-ui Thread CSS. Imported at the TOP of this page entry so it\n// bundles into this page's lazy chunk: react-ui ships `sideEffects: false`, so\n// a bare `@assistant-ui/react-ui` CSS import gets tree-shaken and the Thread\n// renders unstyled. These local copies are not subject to that.\nimport './surface/styles/assistant-ui.css';\nimport './surface/styles/assistant-ui-markdown.css';\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport useAsync from 'react-use/lib/useAsync';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { Content, Progress, ResponseErrorPanel } from '@backstage/core-components';\nimport { makeStyles } from '@material-ui/core/styles';\nimport {\n Button,\n FormControl,\n IconButton,\n ListItemIcon,\n ListSubheader,\n MenuItem,\n Select,\n Tooltip,\n Typography,\n} from '@material-ui/core';\nimport AddIcon from '@material-ui/icons/Add';\nimport ChatBubbleOutlineIcon from '@material-ui/icons/ChatBubbleOutline';\nimport CheckIcon from '@material-ui/icons/Check';\nimport ChevronRightIcon from '@material-ui/icons/ChevronRight';\nimport StarIcon from '@material-ui/icons/Star';\nimport {\n AssistantRuntimeProvider,\n useAssistantRuntime,\n useRemoteThreadListRuntime,\n type ThreadListState,\n} from '@assistant-ui/react';\nimport type {\n AssistantSummary,\n ModelId,\n ModelOption,\n StatusResponse,\n} from '@drewswiredin/backstage-plugin-assistants-common';\nimport { assistantsApiRef, type AssistantsApi } from '../api';\nimport { ConversationSurface } from './surface';\nimport { AssistantAvatar } from './surface/AssistantAvatar';\nimport { SidePane } from './SidePane';\nimport { FullHeightRegion } from './FullHeightRegion';\nimport {\n createThreadListAdapter,\n patchThread,\n type ThreadCustomMetadata,\n type ThreadSummary,\n} from './threadListAdapter';\nimport { signalApiRef } from '@backstage/plugin-signals-react';\nimport type { JsonObject } from '@backstage/types';\nimport { makeRuntimeHook } from './useAssistantRuntime';\nimport { StatusDot } from './StatusDot';\nimport {\n useThreadStatus,\n toConvStatus,\n type ConvStatus,\n} from './useThreadStatus';\n\nconst SIDEPANE_COLLAPSED_KEY = 'ai-chat-sidepane-collapsed';\n\nfunction loadSidePaneCollapsed() {\n try {\n return localStorage.getItem(SIDEPANE_COLLAPSED_KEY) === 'true';\n } catch {\n return false;\n }\n}\n\nconst useStyles = makeStyles(theme => ({\n content: {\n flex: 1,\n minHeight: 0,\n display: 'flex',\n flexDirection: 'column',\n },\n shell: {\n display: 'flex',\n flex: 1,\n minHeight: 0,\n overflow: 'hidden',\n backgroundColor: theme.palette.background.default,\n paddingTop: 0,\n paddingRight: theme.spacing(1),\n paddingBottom: theme.spacing(1),\n paddingLeft: 0,\n gap: theme.spacing(1),\n },\n sidePane: {\n width: 320,\n flexShrink: 0,\n minHeight: 0,\n overflowY: 'auto',\n overflowX: 'hidden',\n },\n sidePaneRail: {\n width: 56,\n flexShrink: 0,\n minHeight: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n paddingBottom: theme.spacing(0.5),\n borderRight: `1px solid ${theme.palette.divider}`,\n overflow: 'hidden',\n },\n sidePaneRailHeader: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '100%',\n minHeight: 44,\n flexShrink: 0,\n borderBottom: `1px solid ${theme.palette.divider}`,\n },\n sidePaneRailAssistants: {\n flexShrink: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n paddingTop: theme.spacing(0.75),\n },\n sidePaneRailDivider: {\n flexShrink: 0,\n width: 24,\n borderTop: `1px solid ${theme.palette.divider}`,\n margin: theme.spacing(0.75, 0),\n },\n sidePaneRailControls: {\n flexShrink: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n paddingBottom: theme.spacing(1),\n },\n sidePaneRailChats: {\n flex: 1,\n minHeight: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n overflowY: 'auto',\n overflowX: 'hidden',\n },\n sidePaneRailButton: {\n color: theme.palette.text.secondary,\n },\n sidePaneRailButtonActive: {\n color: theme.palette.primary.main,\n backgroundColor: theme.palette.action.selected,\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n },\n threadPane: {\n display: 'flex',\n flex: 1,\n flexDirection: 'column',\n minWidth: 0,\n backgroundColor: theme.palette.background.paper,\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: theme.shape.borderRadius,\n boxShadow: theme.shadows[1],\n overflow: 'hidden',\n },\n threadHeader: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: theme.spacing(2),\n minHeight: 36,\n padding: theme.spacing(0, 2),\n backgroundColor: theme.palette.background.paper,\n borderBottom: `1px solid ${theme.palette.divider}`,\n },\n threadIdentity: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n minWidth: 0,\n flex: 1,\n },\n assistantName: {\n fontWeight: 600,\n color: theme.palette.text.primary,\n whiteSpace: 'nowrap',\n flexShrink: 0,\n },\n threadTitle: {\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n color: theme.palette.text.secondary,\n },\n modelSelect: {\n fontSize: theme.typography.caption.fontSize,\n color: theme.palette.text.secondary,\n borderRadius: 999,\n transition: theme.transitions.create('background-color'),\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n '& .MuiSelect-select': {\n display: 'flex',\n alignItems: 'center',\n borderRadius: 999,\n paddingTop: theme.spacing(0.5),\n paddingBottom: theme.spacing(0.5),\n paddingLeft: theme.spacing(1.25),\n paddingRight: theme.spacing(3),\n '&:focus': {\n backgroundColor: 'transparent',\n borderRadius: 999,\n },\n },\n '& .MuiSelect-icon': {\n color: theme.palette.text.secondary,\n right: theme.spacing(0.5),\n },\n },\n modelGroupLabel: {\n lineHeight: 2,\n fontSize: theme.typography.caption.fontSize,\n fontWeight: 600,\n textTransform: 'uppercase',\n letterSpacing: 0.5,\n color: theme.palette.text.secondary,\n backgroundColor: theme.palette.background.paper,\n },\n modelItem: {\n paddingTop: theme.spacing(0.75),\n paddingBottom: theme.spacing(0.75),\n },\n modelItemCheck: {\n minWidth: theme.spacing(3.5),\n color: theme.palette.primary.main,\n },\n modelDefaultStar: {\n fontSize: '1rem',\n color: theme.palette.warning.main,\n marginLeft: theme.spacing(1),\n },\n threadBody: {\n flex: 1,\n minHeight: 0,\n display: 'flex',\n flexDirection: 'column',\n },\n // Bare-agent empty state (no conversation selected; new chats are \"+\"-only).\n emptyState: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: theme.spacing(1),\n height: '100%',\n textAlign: 'center',\n color: theme.palette.text.secondary,\n padding: theme.spacing(3),\n },\n emptyTitle: {\n fontWeight: 600,\n color: theme.palette.text.primary,\n },\n emptyButton: {\n marginTop: theme.spacing(1),\n },\n}));\n\n/**\n * Split a model id into a display vendor + name. Our models route through one\n * provider (e.g. `openrouter`) but the meaningful family is the vendor prefix in\n * the model name (`google/gemini-2.5-flash`). Falls back to the provider / raw\n * id when there's no `/`.\n */\nfunction splitModel(\n id: ModelId,\n pool: ModelOption[],\n): { vendor: string; name: string } {\n const opt = pool.find(m => m.id === id);\n const raw = opt?.model ?? id;\n const slash = raw.indexOf('/');\n if (slash !== -1) {\n return { vendor: raw.slice(0, slash), name: raw.slice(slash + 1) };\n }\n return { vendor: opt?.provider ?? 'models', name: raw };\n}\n\n/** The short model name (after the vendor prefix), for the selector trigger. */\nfunction modelLabel(id: ModelId, pool: ModelOption[]): string {\n return splitModel(id, pool).name;\n}\n\n// ---------------------------------------------------------------------------\n// Page entry\n// ---------------------------------------------------------------------------\n\n/**\n * The collapsible AI chat page. Reads the target assistant from\n * `?assistant=<id>` (the assistant rail lives in the Backstage nav), loads\n * `/status`, and renders the conversation experience for the chosen assistant.\n * Conversations persist server-side (see ADR-free architecture: docs/architecture.html).\n *\n * @public\n */\nexport function CollapsiblePage() {\n const api = useApi(assistantsApiRef);\n const [searchParams] = useSearchParams();\n const requestedAssistant = searchParams.get('assistant');\n\n const status = useAsync(() => api.getStatus(), [api]);\n\n if (status.loading) {\n return <Progress />;\n }\n if (status.error) {\n return <ResponseErrorPanel error={status.error} />;\n }\n if (!status.value) {\n return null;\n }\n const assistants = status.value.assistants;\n if (assistants.length === 0) {\n return (\n <ResponseErrorPanel\n error={new Error('No assistants are available to you.')}\n />\n );\n }\n // The active agent is UI state, NOT a remount key: one runtime carries every\n // conversation across all agents (see ChatRuntime). `?assistant=` only seeds\n // the initially-focused agent.\n const initialAssistantId =\n assistants.find(a => a.id === requestedAssistant)?.id ?? assistants[0].id;\n return (\n <CollapsibleChat\n status={status.value}\n initialAssistantId={initialAssistantId}\n />\n );\n}\n\n/** The id of an agent's most-recently-updated conversation, or undefined if none. */\nfunction mostRecentThreadFor(\n assistantId: string,\n threadList: ThreadListState,\n): string | undefined {\n const updatedAt = (id: string) =>\n (threadList.threadItems[id]?.custom as Partial<ThreadCustomMetadata> | undefined)\n ?.updatedAt ?? '';\n return [...threadList.threadIds]\n .filter(\n id =>\n (threadList.threadItems[id]?.custom as\n | Partial<ThreadCustomMetadata>\n | undefined)?.assistantId === assistantId,\n )\n .sort((a, b) => (updatedAt(a) < updatedAt(b) ? 1 : -1))[0];\n}\n\n// ---------------------------------------------------------------------------\n// Resolve the backend base URL, then build the runtime\n// ---------------------------------------------------------------------------\n\nfunction CollapsibleChat({\n status,\n initialAssistantId,\n}: {\n status: StatusResponse;\n initialAssistantId: string;\n}) {\n const api = useApi(assistantsApiRef);\n const baseUrl = useAsync(() => api.getBaseUrl(), [api]);\n\n if (baseUrl.loading) {\n return <Progress />;\n }\n if (baseUrl.error || !baseUrl.value) {\n return (\n <ResponseErrorPanel\n error={baseUrl.error ?? new Error('Failed to resolve backend URL')}\n />\n );\n }\n return (\n <ChatRuntime\n status={status}\n api={api}\n baseUrl={baseUrl.value}\n initialAssistantId={initialAssistantId}\n />\n );\n}\n\nfunction ChatRuntime({\n status,\n api,\n baseUrl,\n initialAssistantId,\n}: {\n status: StatusResponse;\n api: AssistantsApi;\n baseUrl: string;\n initialAssistantId: string;\n}) {\n // ONE runtime for the whole tab carrying every conversation across all agents.\n // The active agent is a live ref the adapter/runtime read when creating or\n // tagging a new thread — so switching agent or conversation never mounts or\n // unmounts a runtime (no remount churn, no stream loss).\n const activeAssistantIdRef = useRef<string>(initialAssistantId);\n // Drives the transport body; updated by the model picker + on thread switch.\n const modelIdRef = useRef<ModelId>(status.defaultModel);\n\n const adapter = useMemo(\n () => createThreadListAdapter(api, () => activeAssistantIdRef.current),\n [api],\n );\n const runtimeHook = useMemo(\n () =>\n makeRuntimeHook({\n api,\n baseUrl,\n getActiveAssistantId: () => activeAssistantIdRef.current,\n modelIdRef,\n }),\n [api, baseUrl],\n );\n const runtime = useRemoteThreadListRuntime({ adapter, runtimeHook });\n\n return (\n <AssistantRuntimeProvider runtime={runtime}>\n <ChatChrome\n status={status}\n api={api}\n modelIdRef={modelIdRef}\n activeAssistantIdRef={activeAssistantIdRef}\n initialAssistantId={initialAssistantId}\n />\n </AssistantRuntimeProvider>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Chrome (inside the runtime provider) — pure view of server thread state\n// ---------------------------------------------------------------------------\n\nfunction ChatChrome({\n status,\n api,\n modelIdRef,\n activeAssistantIdRef,\n initialAssistantId,\n}: {\n status: StatusResponse;\n api: AssistantsApi;\n modelIdRef: React.MutableRefObject<ModelId>;\n activeAssistantIdRef: React.MutableRefObject<string>;\n initialAssistantId: string;\n}) {\n const classes = useStyles();\n const runtime = useAssistantRuntime();\n const signals = useApi(signalApiRef);\n const [, setSearchParams] = useSearchParams();\n\n // Active agent: UI state, with a ref mirror so the adapter/runtime can tag a\n // brand-new thread synchronously (before React re-renders). The active\n // conversation always belongs to this agent (the list is filtered by it).\n const [activeAssistantId, setActiveAssistantIdState] = useState(\n initialAssistantId,\n );\n const setActiveAssistantId = useCallback(\n (id: string) => {\n activeAssistantIdRef.current = id;\n setActiveAssistantIdState(id);\n },\n [activeAssistantIdRef],\n );\n const assistant = useMemo(\n () =>\n status.assistants.find(a => a.id === activeAssistantId) ??\n status.assistants[0],\n [status.assistants, activeAssistantId],\n );\n const defaultModel = assistant.defaultModel ?? status.defaultModel;\n\n // Reactive snapshot of the server-backed thread list.\n const [threadList, setThreadList] = useState<ThreadListState>(() =>\n runtime.threads.getState(),\n );\n useEffect(() => {\n setThreadList(runtime.threads.getState());\n return runtime.threads.subscribe(() =>\n setThreadList(runtime.threads.getState()),\n );\n }, [runtime]);\n\n const activeId = threadList.mainThreadId;\n const activeItem = threadList.threadItems[activeId];\n const activeRemoteId = activeItem?.remoteId;\n const activeTitle = activeItem?.title ?? '';\n // A bare agent with no conversation: the blank, uninitialized draft slot. New\n // chats are created only via \"+\", so we show an empty state here (no composer)\n // instead of a chat box — removing the ambiguous \"type to start\" path.\n const isBlankDraft = activeId === threadList.newThreadId && !activeRemoteId;\n\n // Single source of truth for read/working/unread, derived from server + signals.\n const { statusOf, agentStatus } = useThreadStatus(api, activeRemoteId);\n\n // On first load for this agent (the component is keyed by assistant.id), land\n // on the agent's MOST RECENT conversation. The runtime defaults the main thread\n // to a blank \"new thread\"; we switch off it to the latest existing conversation\n // so selecting an agent shows a conversation, never a bare agent. An agent with\n // no conversations stays on the unpersisted draft (the only no-\"+\" empty state).\n // A new conversation is created ONLY via \"+\", never by typing.\n const didSelectInitial = useRef(false);\n useEffect(() => {\n if (didSelectInitial.current || threadList.isLoading) return;\n didSelectInitial.current = true;\n // Land on the active agent's most-recent conversation; if it has none, stay\n // on the blank draft (never empty). Don't override a user pick.\n if (activeId !== threadList.newThreadId) return;\n const mostRecent = mostRecentThreadFor(\n activeAssistantIdRef.current,\n threadList,\n );\n if (mostRecent) void runtime.threads.switchToThread(mostRecent);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [threadList.isLoading]);\n\n const conversations = useMemo<ThreadSummary[]>(\n () =>\n threadList.threadIds\n .filter(id => {\n // The conversation you're viewing always shows; other blank drafts\n // don't; the rest are filtered to the active agent. A just-sent thread\n // has no assistantId metadata until the next reload, but it's the\n // active thread, so it stays visible via the first clause.\n if (id === activeId) return true;\n if (id === threadList.newThreadId) return false;\n const aid = (\n threadList.threadItems[id]?.custom as\n | Partial<ThreadCustomMetadata>\n | undefined\n )?.assistantId;\n return aid === activeAssistantId;\n })\n .map(id => {\n const item = threadList.threadItems[id];\n const custom = item?.custom as Partial<ThreadCustomMetadata> | undefined;\n // Every dot derives from the single status snapshot. `working` shows\n // even for the focused conversation; `unread` is suppressed for it.\n const st: ConvStatus = statusOf(item?.remoteId);\n return {\n id,\n remoteId: item?.remoteId,\n title: item?.title ?? 'New Chat',\n pinned: custom?.pinned ?? false,\n unread: st === 'unread',\n working: st === 'working',\n };\n }),\n [threadList, statusOf, activeAssistantId, activeId],\n );\n\n // Refresh the thread list ONLY on metadata changes (a generated title), never\n // mid-turn: reloading re-keys an in-flight new thread (localId → remoteId) and\n // would break its stream. The 'updated' signal fires after a turn completes.\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const sub = signals.subscribe('assistants:threads', (msg: JsonObject) => {\n if ((msg as { type?: string }).type !== 'updated') return;\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => void runtime.threads.reload(), 150);\n });\n return () => {\n if (timer) clearTimeout(timer);\n sub.unsubscribe();\n };\n }, [signals, runtime]);\n\n // Model picker: limited to the assistant's allowlist (else the global pool).\n const allowedModels = useMemo<ModelId[]>(\n () => assistant.models ?? status.models.map(m => m.id),\n [assistant.models, status.models],\n );\n const modelGroups = useMemo<Array<[string, ModelId[]]>>(() => {\n const byVendor = new Map<string, ModelId[]>();\n for (const id of allowedModels) {\n const { vendor } = splitModel(id, status.models);\n const list = byVendor.get(vendor);\n if (list) list.push(id);\n else byVendor.set(vendor, [id]);\n }\n return [...byVendor.entries()];\n }, [allowedModels, status.models]);\n const resolveModel = useCallback(\n (stored: string | null | undefined): ModelId =>\n stored && allowedModels.includes(stored) ? stored : defaultModel,\n [allowedModels, defaultModel],\n );\n\n const [modelId, setModelId] = useState<ModelId>(() =>\n resolveModel((activeItem?.custom as Partial<ThreadCustomMetadata> | undefined)?.model),\n );\n\n // Adopt the active thread's saved model on switch (keyed on the active id only).\n useEffect(() => {\n const stored = (\n threadList.threadItems[activeId]?.custom as\n | Partial<ThreadCustomMetadata>\n | undefined\n )?.model;\n const next = resolveModel(stored);\n setModelId(next);\n modelIdRef.current = next;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeId]);\n\n const [sidePaneCollapsed, setSidePaneCollapsed] = useState(loadSidePaneCollapsed);\n useEffect(() => {\n try {\n localStorage.setItem(SIDEPANE_COLLAPSED_KEY, String(sidePaneCollapsed));\n } catch {\n // storage unavailable\n }\n }, [sidePaneCollapsed]);\n\n const handleSelectAssistant = useCallback(\n (id: string) => {\n if (id === activeAssistantId) return;\n setActiveAssistantId(id);\n setSearchParams({ assistant: id }); // deep-link / survive refresh\n // Land on that agent's most-recent conversation, else a fresh draft.\n const mostRecent = mostRecentThreadFor(id, threadList);\n if (mostRecent) void runtime.threads.switchToThread(mostRecent);\n else void runtime.threads.switchToNewThread();\n },\n [activeAssistantId, setActiveAssistantId, setSearchParams, threadList, runtime],\n );\n\n const handleNew = useCallback(() => {\n void (async () => {\n await runtime.threads.switchToNewThread();\n try {\n await runtime.threads.mainItem.initialize();\n await runtime.threads.reload();\n } catch {\n // already initialized; safe to ignore\n }\n })();\n }, [runtime]);\n\n const handleSelect = useCallback(\n (id: string | null) => {\n if (id) void runtime.threads.switchToThread(id);\n },\n [runtime],\n );\n\n const handleRename = useCallback(\n (id: string, title: string) => {\n void (async () => {\n await runtime.threads.getItemById(id).rename(title);\n await runtime.threads.reload();\n })();\n },\n [runtime],\n );\n\n const handleDelete = useCallback(\n (id: string) => {\n void (async () => {\n const wasActive = id === activeId;\n await runtime.threads.getItemById(id).delete();\n await runtime.threads.reload();\n if (!wasActive) return; // deleting a background chat doesn't move you\n // Land somewhere valid: the agent's most-recent remaining chat, else the\n // empty state (same as a first visit). No conversation is auto-created.\n const remaining = mostRecentThreadFor(\n activeAssistantIdRef.current,\n runtime.threads.getState(),\n );\n if (remaining) await runtime.threads.switchToThread(remaining);\n else await runtime.threads.switchToNewThread();\n })();\n },\n [runtime, activeId, activeAssistantIdRef],\n );\n\n const handlePin = useCallback(\n async (id: string) => {\n const item = threadList.threadItems[id];\n if (!item?.remoteId) return;\n const pinned =\n (item.custom as Partial<ThreadCustomMetadata> | undefined)?.pinned ??\n false;\n try {\n await patchThread(api, item.remoteId, { pinned: !pinned });\n await runtime.threads.reload();\n } catch {\n // best-effort\n }\n },\n [api, runtime, threadList],\n );\n\n const handleModelChange = useCallback(\n (next: ModelId) => {\n setModelId(next);\n modelIdRef.current = next;\n if (activeRemoteId) {\n void patchThread(api, activeRemoteId, { model: next });\n }\n },\n [api, activeRemoteId, modelIdRef],\n );\n\n const modelPicker = (\n <FormControl>\n <Select\n value={modelId}\n onChange={e => handleModelChange(e.target.value as ModelId)}\n disableUnderline\n className={classes.modelSelect}\n inputProps={{ 'aria-label': 'Model' }}\n renderValue={value => modelLabel(value as ModelId, status.models)}\n MenuProps={{\n anchorOrigin: { vertical: 'bottom', horizontal: 'right' },\n transformOrigin: { vertical: 'top', horizontal: 'right' },\n getContentAnchorEl: null,\n }}\n >\n {modelGroups.flatMap(([vendor, ids]) => [\n <ListSubheader\n key={`group-${vendor}`}\n disableSticky\n className={classes.modelGroupLabel}\n >\n {vendor}\n </ListSubheader>,\n ...ids.map(id => (\n <MenuItem key={id} value={id} className={classes.modelItem}>\n <ListItemIcon className={classes.modelItemCheck}>\n {id === modelId ? <CheckIcon fontSize=\"small\" /> : null}\n </ListItemIcon>\n <span style={{ flexGrow: 1 }}>{modelLabel(id, status.models)}</span>\n {id === defaultModel && (\n <Tooltip title=\"Assistant default\">\n <StarIcon\n className={classes.modelDefaultStar}\n aria-label=\"Assistant default\"\n />\n </Tooltip>\n )}\n </MenuItem>\n )),\n ])}\n </Select>\n </FormControl>\n );\n\n return (\n <FullHeightRegion>\n <Content noPadding className={classes.content}>\n <div className={classes.shell}>\n {sidePaneCollapsed ? (\n <aside\n className={classes.sidePaneRail}\n aria-label=\"AI chat sidebar collapsed\"\n >\n <div className={classes.sidePaneRailHeader}>\n <Tooltip title=\"Expand\" placement=\"right\">\n <IconButton\n size=\"small\"\n className={classes.sidePaneRailButton}\n aria-label=\"Expand AI chat sidebar\"\n onClick={() => setSidePaneCollapsed(false)}\n >\n <ChevronRightIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </div>\n <nav className={classes.sidePaneRailAssistants} aria-label=\"Assistants\">\n {status.assistants.map(a => (\n <Tooltip key={a.id} title={a.title} placement=\"right\">\n <IconButton\n size=\"small\"\n className={`${classes.sidePaneRailButton} ${\n a.id === assistant.id\n ? classes.sidePaneRailButtonActive\n : ''\n }`}\n aria-label={a.title}\n onClick={() => handleSelectAssistant(a.id)}\n >\n <StatusDot status={agentStatus(a.id)}>\n <AssistantAvatar color={a.color} size={24} />\n </StatusDot>\n </IconButton>\n </Tooltip>\n ))}\n </nav>\n <div className={classes.sidePaneRailDivider} />\n <div className={classes.sidePaneRailControls}>\n <Tooltip title=\"New Chat\" placement=\"right\">\n <IconButton\n size=\"small\"\n className={classes.sidePaneRailButton}\n aria-label=\"New Chat\"\n onClick={handleNew}\n >\n <AddIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </div>\n <nav\n className={classes.sidePaneRailChats}\n aria-label=\"AI chat conversations\"\n >\n {conversations.map(conversation => (\n <Tooltip\n key={conversation.id}\n title={conversation.title}\n placement=\"right\"\n >\n <IconButton\n size=\"small\"\n className={`${classes.sidePaneRailButton} ${\n conversation.id === activeId\n ? classes.sidePaneRailButtonActive\n : ''\n }`}\n aria-label={conversation.title}\n onClick={() => handleSelect(conversation.id)}\n >\n <StatusDot\n status={toConvStatus(\n conversation.working,\n conversation.unread,\n )}\n >\n <ChatBubbleOutlineIcon fontSize=\"small\" />\n </StatusDot>\n </IconButton>\n </Tooltip>\n ))}\n </nav>\n </aside>\n ) : (\n <aside className={classes.sidePane} aria-label=\"AI chat sidepane\">\n <SidePane\n assistants={status.assistants}\n activeAssistantId={assistant.id}\n onSelectAssistant={handleSelectAssistant}\n agentStatus={agentStatus}\n conversations={conversations}\n activeId={activeId}\n onNew={handleNew}\n onSelect={handleSelect}\n onRename={handleRename}\n onPin={handlePin}\n onDelete={handleDelete}\n onCollapse={() => setSidePaneCollapsed(true)}\n />\n </aside>\n )}\n\n <main className={classes.threadPane} aria-label=\"AI chat thread\">\n <div className={classes.threadHeader}>\n <div className={classes.threadIdentity}>\n <AssistantAvatar color={assistant.color} size={22} />\n <Typography variant=\"subtitle2\" className={classes.assistantName}>\n {assistant.title}\n </Typography>\n {activeTitle && (\n <Typography\n variant=\"body2\"\n className={classes.threadTitle}\n title={activeTitle}\n >\n · {activeTitle}\n </Typography>\n )}\n </div>\n {modelPicker}\n </div>\n <div className={classes.threadBody}>\n {isBlankDraft ? (\n <div className={classes.emptyState}>\n <Typography variant=\"body1\" className={classes.emptyTitle}>\n No conversation yet\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Start a new chat with {assistant.title}.\n </Typography>\n <Button\n variant=\"outlined\"\n size=\"small\"\n startIcon={<AddIcon />}\n onClick={handleNew}\n className={classes.emptyButton}\n >\n New chat\n </Button>\n </div>\n ) : (\n <ConversationSurface\n composerPlaceholder={assistant.ui?.composer?.placeholder}\n suggestions={assistant.ui?.suggestions}\n assistantColor={assistant.color}\n />\n )}\n </div>\n </main>\n </div>\n </Content>\n </FullHeightRegion>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DA,MAAM,sBAAA,GAAyB,4BAAA;AAE/B,SAAS,qBAAA,GAAwB;AAC/B,EAAA,IAAI;AACF,IAAA,OAAO,YAAA,CAAa,OAAA,CAAQ,sBAAsB,CAAA,KAAM,MAAA;AAAA,EAC1D,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,OAAA,EAAS;AAAA,IACP,IAAA,EAAM,CAAA;AAAA,IACN,SAAA,EAAW,CAAA;AAAA,IACX,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe;AAAA,GACjB;AAAA,EACA,KAAA,EAAO;AAAA,IACL,OAAA,EAAS,MAAA;AAAA,IACT,IAAA,EAAM,CAAA;AAAA,IACN,SAAA,EAAW,CAAA;AAAA,IACX,QAAA,EAAU,QAAA;AAAA,IACV,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW,OAAA;AAAA,IAC1C,UAAA,EAAY,CAAA;AAAA,IACZ,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC7B,aAAA,EAAe,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC9B,WAAA,EAAa,CAAA;AAAA,IACb,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA,GACtB;AAAA,EACA,QAAA,EAAU;AAAA,IACR,KAAA,EAAO,GAAA;AAAA,IACP,UAAA,EAAY,CAAA;AAAA,IACZ,SAAA,EAAW,CAAA;AAAA,IACX,SAAA,EAAW,MAAA;AAAA,IACX,SAAA,EAAW;AAAA,GACb;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,KAAA,EAAO,EAAA;AAAA,IACP,UAAA,EAAY,CAAA;AAAA,IACZ,SAAA,EAAW,CAAA;AAAA,IACX,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe,QAAA;AAAA,IACf,UAAA,EAAY,QAAA;AAAA,IACZ,aAAA,EAAe,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAAA,IAChC,WAAA,EAAa,CAAA,UAAA,EAAa,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,CAAA;AAAA,IAC/C,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,kBAAA,EAAoB;AAAA,IAClB,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,cAAA,EAAgB,QAAA;AAAA,IAChB,KAAA,EAAO,MAAA;AAAA,IACP,SAAA,EAAW,EAAA;AAAA,IACX,UAAA,EAAY,CAAA;AAAA,IACZ,YAAA,EAAc,CAAA,UAAA,EAAa,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA;AAAA,GAClD;AAAA,EACA,sBAAA,EAAwB;AAAA,IACtB,UAAA,EAAY,CAAA;AAAA,IACZ,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe,QAAA;AAAA,IACf,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAAA,IACtB,UAAA,EAAY,KAAA,CAAM,OAAA,CAAQ,IAAI;AAAA,GAChC;AAAA,EACA,mBAAA,EAAqB;AAAA,IACnB,UAAA,EAAY,CAAA;AAAA,IACZ,KAAA,EAAO,EAAA;AAAA,IACP,SAAA,EAAW,CAAA,UAAA,EAAa,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,CAAA;AAAA,IAC7C,MAAA,EAAQ,KAAA,CAAM,OAAA,CAAQ,IAAA,EAAM,CAAC;AAAA,GAC/B;AAAA,EACA,oBAAA,EAAsB;AAAA,IACpB,UAAA,EAAY,CAAA;AAAA,IACZ,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe,QAAA;AAAA,IACf,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAAA,IACtB,aAAA,EAAe,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA,GAChC;AAAA,EACA,iBAAA,EAAmB;AAAA,IACjB,IAAA,EAAM,CAAA;AAAA,IACN,SAAA,EAAW,CAAA;AAAA,IACX,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe,QAAA;AAAA,IACf,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAAA,IACtB,SAAA,EAAW,MAAA;AAAA,IACX,SAAA,EAAW;AAAA,GACb;AAAA,EACA,kBAAA,EAAoB;AAAA,IAClB,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK;AAAA,GAC5B;AAAA,EACA,wBAAA,EAA0B;AAAA,IACxB,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,OAAA,CAAQ,IAAA;AAAA,IAC7B,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,QAAA;AAAA,IACtC,SAAA,EAAW;AAAA,MACT,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO;AAAA;AACxC,GACF;AAAA,EACA,UAAA,EAAY;AAAA,IACV,OAAA,EAAS,MAAA;AAAA,IACT,IAAA,EAAM,CAAA;AAAA,IACN,aAAA,EAAe,QAAA;AAAA,IACf,QAAA,EAAU,CAAA;AAAA,IACV,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW,KAAA;AAAA,IAC1C,MAAA,EAAQ,CAAA,UAAA,EAAa,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,CAAA;AAAA,IAC1C,YAAA,EAAc,MAAM,KAAA,CAAM,YAAA;AAAA,IAC1B,SAAA,EAAW,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC1B,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,cAAA,EAAgB,eAAA;AAAA,IAChB,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IACpB,SAAA,EAAW,EAAA;AAAA,IACX,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,CAAA,EAAG,CAAC,CAAA;AAAA,IAC3B,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW,KAAA;AAAA,IAC1C,YAAA,EAAc,CAAA,UAAA,EAAa,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA;AAAA,GAClD;AAAA,EACA,cAAA,EAAgB;AAAA,IACd,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IACpB,QAAA,EAAU,CAAA;AAAA,IACV,IAAA,EAAM;AAAA,GACR;AAAA,EACA,aAAA,EAAe;AAAA,IACb,UAAA,EAAY,GAAA;AAAA,IACZ,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,OAAA;AAAA,IAC1B,UAAA,EAAY,QAAA;AAAA,IACZ,UAAA,EAAY;AAAA,GACd;AAAA,EACA,WAAA,EAAa;AAAA,IACX,QAAA,EAAU,CAAA;AAAA,IACV,QAAA,EAAU,QAAA;AAAA,IACV,YAAA,EAAc,UAAA;AAAA,IACd,UAAA,EAAY,QAAA;AAAA,IACZ,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK;AAAA,GAC5B;AAAA,EACA,WAAA,EAAa;AAAA,IACX,QAAA,EAAU,KAAA,CAAM,UAAA,CAAW,OAAA,CAAQ,QAAA;AAAA,IACnC,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,SAAA;AAAA,IAC1B,YAAA,EAAc,GAAA;AAAA,IACd,UAAA,EAAY,KAAA,CAAM,WAAA,CAAY,MAAA,CAAO,kBAAkB,CAAA;AAAA,IACvD,SAAA,EAAW;AAAA,MACT,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO;AAAA,KACxC;AAAA,IACA,qBAAA,EAAuB;AAAA,MACrB,OAAA,EAAS,MAAA;AAAA,MACT,UAAA,EAAY,QAAA;AAAA,MACZ,YAAA,EAAc,GAAA;AAAA,MACd,UAAA,EAAY,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAAA,MAC7B,aAAA,EAAe,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAAA,MAChC,WAAA,EAAa,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AAAA,MAC/B,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,MAC7B,SAAA,EAAW;AAAA,QACT,eAAA,EAAiB,aAAA;AAAA,QACjB,YAAA,EAAc;AAAA;AAChB,KACF;AAAA,IACA,mBAAA,EAAqB;AAAA,MACnB,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,SAAA;AAAA,MAC1B,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,GAAG;AAAA;AAC1B,GACF;AAAA,EACA,eAAA,EAAiB;AAAA,IACf,UAAA,EAAY,CAAA;AAAA,IACZ,QAAA,EAAU,KAAA,CAAM,UAAA,CAAW,OAAA,CAAQ,QAAA;AAAA,IACnC,UAAA,EAAY,GAAA;AAAA,IACZ,aAAA,EAAe,WAAA;AAAA,IACf,aAAA,EAAe,GAAA;AAAA,IACf,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,SAAA;AAAA,IAC1B,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW;AAAA,GAC5C;AAAA,EACA,SAAA,EAAW;AAAA,IACT,UAAA,EAAY,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AAAA,IAC9B,aAAA,EAAe,KAAA,CAAM,OAAA,CAAQ,IAAI;AAAA,GACnC;AAAA,EACA,cAAA,EAAgB;AAAA,IACd,QAAA,EAAU,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAAA,IAC3B,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,OAAA,CAAQ;AAAA,GAC/B;AAAA,EACA,gBAAA,EAAkB;AAAA,IAChB,QAAA,EAAU,MAAA;AAAA,IACV,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,OAAA,CAAQ,IAAA;AAAA,IAC7B,UAAA,EAAY,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA,GAC7B;AAAA,EACA,UAAA,EAAY;AAAA,IACV,IAAA,EAAM,CAAA;AAAA,IACN,SAAA,EAAW,CAAA;AAAA,IACX,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe;AAAA,GACjB;AAAA;AAAA,EAEA,UAAA,EAAY;AAAA,IACV,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe,QAAA;AAAA,IACf,UAAA,EAAY,QAAA;AAAA,IACZ,cAAA,EAAgB,QAAA;AAAA,IAChB,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IACpB,MAAA,EAAQ,MAAA;AAAA,IACR,SAAA,EAAW,QAAA;AAAA,IACX,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,SAAA;AAAA,IAC1B,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA,GAC1B;AAAA,EACA,UAAA,EAAY;AAAA,IACV,UAAA,EAAY,GAAA;AAAA,IACZ,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK;AAAA,GAC5B;AAAA,EACA,WAAA,EAAa;AAAA,IACX,SAAA,EAAW,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA;AAE9B,CAAA,CAAE,CAAA;AAQF,SAAS,UAAA,CACP,IACA,IAAA,EACkC;AAClC,EAAA,MAAM,MAAM,IAAA,CAAK,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AACtC,EAAA,MAAM,GAAA,GAAM,KAAK,KAAA,IAAS,EAAA;AAC1B,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA;AAC7B,EAAA,IAAI,UAAU,EAAA,EAAI;AAChB,IAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA,EAAG,IAAA,EAAM,GAAA,CAAI,KAAA,CAAM,KAAA,GAAQ,CAAC,CAAA,EAAE;AAAA,EACnE;AACA,EAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,QAAA,IAAY,QAAA,EAAU,MAAM,GAAA,EAAI;AACxD;AAGA,SAAS,UAAA,CAAW,IAAa,IAAA,EAA6B;AAC5D,EAAA,OAAO,UAAA,CAAW,EAAA,EAAI,IAAI,CAAA,CAAE,IAAA;AAC9B;AAcO,SAAS,eAAA,GAAkB;AAChC,EAAA,MAAM,GAAA,GAAM,OAAO,gBAAgB,CAAA;AACnC,EAAA,MAAM,CAAC,YAAY,CAAA,GAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,kBAAA,GAAqB,YAAA,CAAa,GAAA,CAAI,WAAW,CAAA;AAEvD,EAAA,MAAM,MAAA,GAAS,SAAS,MAAM,GAAA,CAAI,WAAU,EAAG,CAAC,GAAG,CAAC,CAAA;AAEpD,EAAA,IAAI,OAAO,OAAA,EAAS;AAClB,IAAA,2BAAQ,QAAA,EAAA,EAAS,CAAA;AAAA,EACnB;AACA,EAAA,IAAI,OAAO,KAAA,EAAO;AAChB,IAAA,uBAAO,GAAA,CAAC,kBAAA,EAAA,EAAmB,KAAA,EAAO,MAAA,CAAO,KAAA,EAAO,CAAA;AAAA,EAClD;AACA,EAAA,IAAI,CAAC,OAAO,KAAA,EAAO;AACjB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,UAAA,GAAa,OAAO,KAAA,CAAM,UAAA;AAChC,EAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,IAAA,uBACE,GAAA;AAAA,MAAC,kBAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,IAAI,KAAA,CAAM,qCAAqC;AAAA;AAAA,KACxD;AAAA,EAEJ;AAIA,EAAA,MAAM,kBAAA,GACJ,UAAA,CAAW,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,EAAA,KAAO,kBAAkB,CAAA,EAAG,EAAA,IAAM,UAAA,CAAW,CAAC,CAAA,CAAE,EAAA;AACzE,EAAA,uBACE,GAAA;AAAA,IAAC,eAAA;AAAA,IAAA;AAAA,MACC,QAAQ,MAAA,CAAO,KAAA;AAAA,MACf;AAAA;AAAA,GACF;AAEJ;AAGA,SAAS,mBAAA,CACP,aACA,UAAA,EACoB;AACpB,EAAA,MAAM,SAAA,GAAY,CAAC,EAAA,KAChB,UAAA,CAAW,YAAY,EAAE,CAAA,EAAG,QACzB,SAAA,IAAa,EAAA;AACnB,EAAA,OAAO,CAAC,GAAG,UAAA,CAAW,SAAS,CAAA,CAC5B,MAAA;AAAA,IACC,QACG,UAAA,CAAW,WAAA,CAAY,EAAE,CAAA,EAAG,QAEb,WAAA,KAAgB;AAAA,GACpC,CACC,IAAA,CAAK,CAAC,CAAA,EAAG,MAAO,SAAA,CAAU,CAAC,CAAA,GAAI,SAAA,CAAU,CAAC,CAAA,GAAI,CAAA,GAAI,EAAG,EAAE,CAAC,CAAA;AAC7D;AAMA,SAAS,eAAA,CAAgB;AAAA,EACvB,MAAA;AAAA,EACA;AACF,CAAA,EAGG;AACD,EAAA,MAAM,GAAA,GAAM,OAAO,gBAAgB,CAAA;AACnC,EAAA,MAAM,OAAA,GAAU,SAAS,MAAM,GAAA,CAAI,YAAW,EAAG,CAAC,GAAG,CAAC,CAAA;AAEtD,EAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,IAAA,2BAAQ,QAAA,EAAA,EAAS,CAAA;AAAA,EACnB;AACA,EAAA,IAAI,OAAA,CAAQ,KAAA,IAAS,CAAC,OAAA,CAAQ,KAAA,EAAO;AACnC,IAAA,uBACE,GAAA;AAAA,MAAC,kBAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,OAAA,CAAQ,KAAA,IAAS,IAAI,MAAM,+BAA+B;AAAA;AAAA,KACnE;AAAA,EAEJ;AACA,EAAA,uBACE,GAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,MAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAS,OAAA,CAAQ,KAAA;AAAA,MACjB;AAAA;AAAA,GACF;AAEJ;AAEA,SAAS,WAAA,CAAY;AAAA,EACnB,MAAA;AAAA,EACA,GAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,EAKG;AAKD,EAAA,MAAM,oBAAA,GAAuB,OAAe,kBAAkB,CAAA;AAE9D,EAAA,MAAM,UAAA,GAAa,MAAA,CAAgB,MAAA,CAAO,YAAY,CAAA;AAEtD,EAAA,MAAM,OAAA,GAAU,OAAA;AAAA,IACd,MAAM,uBAAA,CAAwB,GAAA,EAAK,MAAM,qBAAqB,OAAO,CAAA;AAAA,IACrE,CAAC,GAAG;AAAA,GACN;AACA,EAAA,MAAM,WAAA,GAAc,OAAA;AAAA,IAClB,MACE,eAAA,CAAgB;AAAA,MACd,GAAA;AAAA,MACA,OAAA;AAAA,MACA,oBAAA,EAAsB,MAAM,oBAAA,CAAqB,OAAA;AAAA,MACjD;AAAA,KACD,CAAA;AAAA,IACH,CAAC,KAAK,OAAO;AAAA,GACf;AACA,EAAA,MAAM,OAAA,GAAU,0BAAA,CAA2B,EAAE,OAAA,EAAS,aAAa,CAAA;AAEnE,EAAA,uBACE,GAAA,CAAC,4BAAyB,OAAA,EACxB,QAAA,kBAAA,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,MAAA;AAAA,MACA,GAAA;AAAA,MACA,UAAA;AAAA,MACA,oBAAA;AAAA,MACA;AAAA;AAAA,GACF,EACF,CAAA;AAEJ;AAMA,SAAS,UAAA,CAAW;AAAA,EAClB,MAAA;AAAA,EACA,GAAA;AAAA,EACA,UAAA;AAAA,EACA,oBAAA;AAAA,EACA;AACF,CAAA,EAMG;AACD,EAAA,MAAM,UAAU,SAAA,EAAU;AAC1B,EAAA,MAAM,UAAU,mBAAA,EAAoB;AACpC,EAAA,MAAM,OAAA,GAAU,OAAO,YAAY,CAAA;AACnC,EAAA,MAAM,GAAG,eAAe,CAAA,GAAI,eAAA,EAAgB;AAK5C,EAAA,MAAM,CAAC,iBAAA,EAAmB,yBAAyB,CAAA,GAAI,QAAA;AAAA,IACrD;AAAA,GACF;AACA,EAAA,MAAM,oBAAA,GAAuB,WAAA;AAAA,IAC3B,CAAC,EAAA,KAAe;AACd,MAAA,oBAAA,CAAqB,OAAA,GAAU,EAAA;AAC/B,MAAA,yBAAA,CAA0B,EAAE,CAAA;AAAA,IAC9B,CAAA;AAAA,IACA,CAAC,oBAAoB;AAAA,GACvB;AACA,EAAA,MAAM,SAAA,GAAY,OAAA;AAAA,IAChB,MACE,MAAA,CAAO,UAAA,CAAW,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,EAAA,KAAO,iBAAiB,CAAA,IACtD,MAAA,CAAO,UAAA,CAAW,CAAC,CAAA;AAAA,IACrB,CAAC,MAAA,CAAO,UAAA,EAAY,iBAAiB;AAAA,GACvC;AACA,EAAA,MAAM,YAAA,GAAe,SAAA,CAAU,YAAA,IAAgB,MAAA,CAAO,YAAA;AAGtD,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,QAAA;AAAA,IAA0B,MAC5D,OAAA,CAAQ,OAAA,CAAQ,QAAA;AAAS,GAC3B;AACA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,aAAA,CAAc,OAAA,CAAQ,OAAA,CAAQ,QAAA,EAAU,CAAA;AACxC,IAAA,OAAO,QAAQ,OAAA,CAAQ,SAAA;AAAA,MAAU,MAC/B,aAAA,CAAc,OAAA,CAAQ,OAAA,CAAQ,UAAU;AAAA,KAC1C;AAAA,EACF,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,MAAM,WAAW,UAAA,CAAW,YAAA;AAC5B,EAAA,MAAM,UAAA,GAAa,UAAA,CAAW,WAAA,CAAY,QAAQ,CAAA;AAClD,EAAA,MAAM,iBAAiB,UAAA,EAAY,QAAA;AACnC,EAAA,MAAM,WAAA,GAAc,YAAY,KAAA,IAAS,EAAA;AAIzC,EAAA,MAAM,YAAA,GAAe,QAAA,KAAa,UAAA,CAAW,WAAA,IAAe,CAAC,cAAA;AAG7D,EAAA,MAAM,EAAE,QAAA,EAAU,WAAA,EAAY,GAAI,eAAA,CAAgB,KAAK,cAAc,CAAA;AAQrE,EAAA,MAAM,gBAAA,GAAmB,OAAO,KAAK,CAAA;AACrC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,gBAAA,CAAiB,OAAA,IAAW,UAAA,CAAW,SAAA,EAAW;AACtD,IAAA,gBAAA,CAAiB,OAAA,GAAU,IAAA;AAG3B,IAAA,IAAI,QAAA,KAAa,WAAW,WAAA,EAAa;AACzC,IAAA,MAAM,UAAA,GAAa,mBAAA;AAAA,MACjB,oBAAA,CAAqB,OAAA;AAAA,MACrB;AAAA,KACF;AACA,IAAA,IAAI,UAAA,EAAY,KAAK,OAAA,CAAQ,OAAA,CAAQ,eAAe,UAAU,CAAA;AAAA,EAEhE,CAAA,EAAG,CAAC,UAAA,CAAW,SAAS,CAAC,CAAA;AAEzB,EAAA,MAAM,aAAA,GAAgB,OAAA;AAAA,IACpB,MACE,UAAA,CAAW,SAAA,CACR,MAAA,CAAO,CAAA,EAAA,KAAM;AAKZ,MAAA,IAAI,EAAA,KAAO,UAAU,OAAO,IAAA;AAC5B,MAAA,IAAI,EAAA,KAAO,UAAA,CAAW,WAAA,EAAa,OAAO,KAAA;AAC1C,MAAA,MAAM,GAAA,GACJ,UAAA,CAAW,WAAA,CAAY,EAAE,GAAG,MAAA,EAG3B,WAAA;AACH,MAAA,OAAO,GAAA,KAAQ,iBAAA;AAAA,IACjB,CAAC,CAAA,CACA,GAAA,CAAI,CAAA,EAAA,KAAM;AACT,MAAA,MAAM,IAAA,GAAO,UAAA,CAAW,WAAA,CAAY,EAAE,CAAA;AACtC,MAAA,MAAM,SAAS,IAAA,EAAM,MAAA;AAGrB,MAAA,MAAM,EAAA,GAAiB,QAAA,CAAS,IAAA,EAAM,QAAQ,CAAA;AAC9C,MAAA,OAAO;AAAA,QACL,EAAA;AAAA,QACA,UAAU,IAAA,EAAM,QAAA;AAAA,QAChB,KAAA,EAAO,MAAM,KAAA,IAAS,UAAA;AAAA,QACtB,MAAA,EAAQ,QAAQ,MAAA,IAAU,KAAA;AAAA,QAC1B,QAAQ,EAAA,KAAO,QAAA;AAAA,QACf,SAAS,EAAA,KAAO;AAAA,OAClB;AAAA,IACF,CAAC,CAAA;AAAA,IACL,CAAC,UAAA,EAAY,QAAA,EAAU,iBAAA,EAAmB,QAAQ;AAAA,GACpD;AAKA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,KAAA;AACJ,IAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,SAAA,CAAU,oBAAA,EAAsB,CAAC,GAAA,KAAoB;AACvE,MAAA,IAAK,GAAA,CAA0B,SAAS,SAAA,EAAW;AACnD,MAAA,IAAI,KAAA,eAAoB,KAAK,CAAA;AAC7B,MAAA,KAAA,GAAQ,WAAW,MAAM,KAAK,QAAQ,OAAA,CAAQ,MAAA,IAAU,GAAG,CAAA;AAAA,IAC7D,CAAC,CAAA;AACD,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,KAAA,eAAoB,KAAK,CAAA;AAC7B,MAAA,GAAA,CAAI,WAAA,EAAY;AAAA,IAClB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,OAAA,EAAS,OAAO,CAAC,CAAA;AAGrB,EAAA,MAAM,aAAA,GAAgB,OAAA;AAAA,IACpB,MAAM,UAAU,MAAA,IAAU,MAAA,CAAO,OAAO,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,EAAE,CAAA;AAAA,IACrD,CAAC,SAAA,CAAU,MAAA,EAAQ,MAAA,CAAO,MAAM;AAAA,GAClC;AACA,EAAA,MAAM,WAAA,GAAc,QAAoC,MAAM;AAC5D,IAAA,MAAM,QAAA,uBAAe,GAAA,EAAuB;AAC5C,IAAA,KAAA,MAAW,MAAM,aAAA,EAAe;AAC9B,MAAA,MAAM,EAAE,MAAA,EAAO,GAAI,UAAA,CAAW,EAAA,EAAI,OAAO,MAAM,CAAA;AAC/C,MAAA,MAAM,IAAA,GAAO,QAAA,CAAS,GAAA,CAAI,MAAM,CAAA;AAChC,MAAA,IAAI,IAAA,EAAM,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA;AAAA,WACjB,QAAA,CAAS,GAAA,CAAI,MAAA,EAAQ,CAAC,EAAE,CAAC,CAAA;AAAA,IAChC;AACA,IAAA,OAAO,CAAC,GAAG,QAAA,CAAS,OAAA,EAAS,CAAA;AAAA,EAC/B,CAAA,EAAG,CAAC,aAAA,EAAe,MAAA,CAAO,MAAM,CAAC,CAAA;AACjC,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,CAAC,MAAA,KACC,MAAA,IAAU,cAAc,QAAA,CAAS,MAAM,IAAI,MAAA,GAAS,YAAA;AAAA,IACtD,CAAC,eAAe,YAAY;AAAA,GAC9B;AAEA,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,QAAA;AAAA,IAAkB,MAC9C,YAAA,CAAc,UAAA,EAAY,MAAA,EAAsD,KAAK;AAAA,GACvF;AAGA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,MAAA,GACJ,UAAA,CAAW,WAAA,CAAY,QAAQ,GAAG,MAAA,EAGjC,KAAA;AACH,IAAA,MAAM,IAAA,GAAO,aAAa,MAAM,CAAA;AAChC,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,EAEvB,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAI,SAAS,qBAAqB,CAAA;AAChF,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,OAAA,CAAQ,sBAAA,EAAwB,MAAA,CAAO,iBAAiB,CAAC,CAAA;AAAA,IACxE,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF,CAAA,EAAG,CAAC,iBAAiB,CAAC,CAAA;AAEtB,EAAA,MAAM,qBAAA,GAAwB,WAAA;AAAA,IAC5B,CAAC,EAAA,KAAe;AACd,MAAA,IAAI,OAAO,iBAAA,EAAmB;AAC9B,MAAA,oBAAA,CAAqB,EAAE,CAAA;AACvB,MAAA,eAAA,CAAgB,EAAE,SAAA,EAAW,EAAA,EAAI,CAAA;AAEjC,MAAA,MAAM,UAAA,GAAa,mBAAA,CAAoB,EAAA,EAAI,UAAU,CAAA;AACrD,MAAA,IAAI,UAAA,EAAY,KAAK,OAAA,CAAQ,OAAA,CAAQ,eAAe,UAAU,CAAA;AAAA,WACzD,KAAK,OAAA,CAAQ,OAAA,CAAQ,iBAAA,EAAkB;AAAA,IAC9C,CAAA;AAAA,IACA,CAAC,iBAAA,EAAmB,oBAAA,EAAsB,eAAA,EAAiB,YAAY,OAAO;AAAA,GAChF;AAEA,EAAA,MAAM,SAAA,GAAY,YAAY,MAAM;AAClC,IAAA,KAAA,CAAM,YAAY;AAChB,MAAA,MAAM,OAAA,CAAQ,QAAQ,iBAAA,EAAkB;AACxC,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,CAAQ,OAAA,CAAQ,QAAA,CAAS,UAAA,EAAW;AAC1C,QAAA,MAAM,OAAA,CAAQ,QAAQ,MAAA,EAAO;AAAA,MAC/B,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA,GAAG;AAAA,EACL,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,CAAC,EAAA,KAAsB;AACrB,MAAA,IAAI,EAAA,EAAI,KAAK,OAAA,CAAQ,OAAA,CAAQ,eAAe,EAAE,CAAA;AAAA,IAChD,CAAA;AAAA,IACA,CAAC,OAAO;AAAA,GACV;AAEA,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,CAAC,IAAY,KAAA,KAAkB;AAC7B,MAAA,KAAA,CAAM,YAAY;AAChB,QAAA,MAAM,QAAQ,OAAA,CAAQ,WAAA,CAAY,EAAE,CAAA,CAAE,OAAO,KAAK,CAAA;AAClD,QAAA,MAAM,OAAA,CAAQ,QAAQ,MAAA,EAAO;AAAA,MAC/B,CAAA,GAAG;AAAA,IACL,CAAA;AAAA,IACA,CAAC,OAAO;AAAA,GACV;AAEA,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,CAAC,EAAA,KAAe;AACd,MAAA,KAAA,CAAM,YAAY;AAChB,QAAA,MAAM,YAAY,EAAA,KAAO,QAAA;AACzB,QAAA,MAAM,OAAA,CAAQ,OAAA,CAAQ,WAAA,CAAY,EAAE,EAAE,MAAA,EAAO;AAC7C,QAAA,MAAM,OAAA,CAAQ,QAAQ,MAAA,EAAO;AAC7B,QAAA,IAAI,CAAC,SAAA,EAAW;AAGhB,QAAA,MAAM,SAAA,GAAY,mBAAA;AAAA,UAChB,oBAAA,CAAqB,OAAA;AAAA,UACrB,OAAA,CAAQ,QAAQ,QAAA;AAAS,SAC3B;AACA,QAAA,IAAI,SAAA,EAAW,MAAM,OAAA,CAAQ,OAAA,CAAQ,eAAe,SAAS,CAAA;AAAA,aACxD,MAAM,OAAA,CAAQ,OAAA,CAAQ,iBAAA,EAAkB;AAAA,MAC/C,CAAA,GAAG;AAAA,IACL,CAAA;AAAA,IACA,CAAC,OAAA,EAAS,QAAA,EAAU,oBAAoB;AAAA,GAC1C;AAEA,EAAA,MAAM,SAAA,GAAY,WAAA;AAAA,IAChB,OAAO,EAAA,KAAe;AACpB,MAAA,MAAM,IAAA,GAAO,UAAA,CAAW,WAAA,CAAY,EAAE,CAAA;AACtC,MAAA,IAAI,CAAC,MAAM,QAAA,EAAU;AACrB,MAAA,MAAM,MAAA,GACH,IAAA,CAAK,MAAA,EAAsD,MAAA,IAC5D,KAAA;AACF,MAAA,IAAI;AACF,QAAA,MAAM,WAAA,CAAY,KAAK,IAAA,CAAK,QAAA,EAAU,EAAE,MAAA,EAAQ,CAAC,QAAQ,CAAA;AACzD,QAAA,MAAM,OAAA,CAAQ,QAAQ,MAAA,EAAO;AAAA,MAC/B,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA;AAAA,IACA,CAAC,GAAA,EAAK,OAAA,EAAS,UAAU;AAAA,GAC3B;AAEA,EAAA,MAAM,iBAAA,GAAoB,WAAA;AAAA,IACxB,CAAC,IAAA,KAAkB;AACjB,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AACrB,MAAA,IAAI,cAAA,EAAgB;AAClB,QAAA,KAAK,YAAY,GAAA,EAAK,cAAA,EAAgB,EAAE,KAAA,EAAO,MAAM,CAAA;AAAA,MACvD;AAAA,IACF,CAAA;AAAA,IACA,CAAC,GAAA,EAAK,cAAA,EAAgB,UAAU;AAAA,GAClC;AAEA,EAAA,MAAM,WAAA,uBACH,WAAA,EAAA,EACC,QAAA,kBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,OAAA;AAAA,MACP,QAAA,EAAU,CAAA,CAAA,KAAK,iBAAA,CAAkB,CAAA,CAAE,OAAO,KAAgB,CAAA;AAAA,MAC1D,gBAAA,EAAgB,IAAA;AAAA,MAChB,WAAW,OAAA,CAAQ,WAAA;AAAA,MACnB,UAAA,EAAY,EAAE,YAAA,EAAc,OAAA,EAAQ;AAAA,MACpC,WAAA,EAAa,CAAA,KAAA,KAAS,UAAA,CAAW,KAAA,EAAkB,OAAO,MAAM,CAAA;AAAA,MAChE,SAAA,EAAW;AAAA,QACT,YAAA,EAAc,EAAE,QAAA,EAAU,QAAA,EAAU,YAAY,OAAA,EAAQ;AAAA,QACxD,eAAA,EAAiB,EAAE,QAAA,EAAU,KAAA,EAAO,YAAY,OAAA,EAAQ;AAAA,QACxD,kBAAA,EAAoB;AAAA,OACtB;AAAA,MAEC,sBAAY,OAAA,CAAQ,CAAC,CAAC,MAAA,EAAQ,GAAG,CAAA,KAAM;AAAA,wBACtC,GAAA;AAAA,UAAC,aAAA;AAAA,UAAA;AAAA,YAEC,aAAA,EAAa,IAAA;AAAA,YACb,WAAW,OAAA,CAAQ,eAAA;AAAA,YAElB,QAAA,EAAA;AAAA,WAAA;AAAA,UAJI,SAAS,MAAM,CAAA;AAAA,SAKtB;AAAA,QACA,GAAG,GAAA,CAAI,GAAA,CAAI,CAAA,EAAA,qBACT,IAAA,CAAC,YAAkB,KAAA,EAAO,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,SAAA,EAC/C,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,YAAA,EAAA,EAAa,SAAA,EAAW,OAAA,CAAQ,cAAA,EAC9B,QAAA,EAAA,EAAA,KAAO,OAAA,mBAAU,GAAA,CAAC,SAAA,EAAA,EAAU,QAAA,EAAS,OAAA,EAAQ,CAAA,GAAK,IAAA,EACrD,CAAA;AAAA,0BACA,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,EAAE,QAAA,EAAU,CAAA,EAAE,EAAI,QAAA,EAAA,UAAA,CAAW,EAAA,EAAI,MAAA,CAAO,MAAM,CAAA,EAAE,CAAA;AAAA,UAC5D,EAAA,KAAO,YAAA,oBACN,GAAA,CAAC,OAAA,EAAA,EAAQ,OAAM,mBAAA,EACb,QAAA,kBAAA,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,WAAW,OAAA,CAAQ,gBAAA;AAAA,cACnB,YAAA,EAAW;AAAA;AAAA,WACb,EACF;AAAA,SAAA,EAAA,EAXW,EAaf,CACD;AAAA,OACF;AAAA;AAAA,GACH,EACF,CAAA;AAGF,EAAA,uBACE,GAAA,CAAC,gBAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,OAAA,EAAA,EAAQ,SAAA,EAAS,IAAA,EAAC,SAAA,EAAW,OAAA,CAAQ,OAAA,EACpC,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,QAAQ,KAAA,EACrB,QAAA,EAAA;AAAA,IAAA,iBAAA,mBACC,IAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,WAAW,OAAA,CAAQ,YAAA;AAAA,QACnB,YAAA,EAAW,2BAAA;AAAA,QAEX,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,KAAA,EAAA,EAAI,WAAW,OAAA,CAAQ,kBAAA,EACtB,8BAAC,OAAA,EAAA,EAAQ,KAAA,EAAM,QAAA,EAAS,SAAA,EAAU,OAAA,EAChC,QAAA,kBAAA,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,OAAA;AAAA,cACL,WAAW,OAAA,CAAQ,kBAAA;AAAA,cACnB,YAAA,EAAW,wBAAA;AAAA,cACX,OAAA,EAAS,MAAM,oBAAA,CAAqB,KAAK,CAAA;AAAA,cAEzC,QAAA,kBAAA,GAAA,CAAC,gBAAA,EAAA,EAAiB,QAAA,EAAS,OAAA,EAAQ;AAAA;AAAA,aAEvC,CAAA,EACF,CAAA;AAAA,8BACC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,sBAAA,EAAwB,cAAW,YAAA,EACxD,QAAA,EAAA,MAAA,CAAO,UAAA,CAAW,GAAA,CAAI,uBACrB,GAAA,CAAC,OAAA,EAAA,EAAmB,OAAO,CAAA,CAAE,KAAA,EAAO,WAAU,OAAA,EAC5C,QAAA,kBAAA,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,OAAA;AAAA,cACL,SAAA,EAAW,CAAA,EAAG,OAAA,CAAQ,kBAAkB,CAAA,CAAA,EACtC,CAAA,CAAE,EAAA,KAAO,SAAA,CAAU,EAAA,GACf,OAAA,CAAQ,wBAAA,GACR,EACN,CAAA,CAAA;AAAA,cACA,cAAY,CAAA,CAAE,KAAA;AAAA,cACd,OAAA,EAAS,MAAM,qBAAA,CAAsB,CAAA,CAAE,EAAE,CAAA;AAAA,cAEzC,QAAA,kBAAA,GAAA,CAAC,SAAA,EAAA,EAAU,MAAA,EAAQ,WAAA,CAAY,EAAE,EAAE,CAAA,EACjC,QAAA,kBAAA,GAAA,CAAC,eAAA,EAAA,EAAgB,KAAA,EAAO,CAAA,CAAE,KAAA,EAAO,IAAA,EAAM,IAAI,CAAA,EAC7C;AAAA;AAAA,WACF,EAAA,EAdY,CAAA,CAAE,EAehB,CACD,CAAA,EACH,CAAA;AAAA,0BACA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,mBAAA,EAAqB,CAAA;AAAA,0BAC7C,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,oBAAA,EACtB,8BAAC,OAAA,EAAA,EAAQ,KAAA,EAAM,UAAA,EAAW,SAAA,EAAU,OAAA,EAClC,QAAA,kBAAA,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,OAAA;AAAA,cACL,WAAW,OAAA,CAAQ,kBAAA;AAAA,cACnB,YAAA,EAAW,UAAA;AAAA,cACX,OAAA,EAAS,SAAA;AAAA,cAET,QAAA,kBAAA,GAAA,CAAC,OAAA,EAAA,EAAQ,QAAA,EAAS,OAAA,EAAQ;AAAA;AAAA,aAE9B,CAAA,EACF,CAAA;AAAA,0BACA,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,WAAW,OAAA,CAAQ,iBAAA;AAAA,cACnB,YAAA,EAAW,uBAAA;AAAA,cAEV,QAAA,EAAA,aAAA,CAAc,IAAI,CAAA,YAAA,qBACjB,GAAA;AAAA,gBAAC,OAAA;AAAA,gBAAA;AAAA,kBAEC,OAAO,YAAA,CAAa,KAAA;AAAA,kBACpB,SAAA,EAAU,OAAA;AAAA,kBAEV,QAAA,kBAAA,GAAA;AAAA,oBAAC,UAAA;AAAA,oBAAA;AAAA,sBACC,IAAA,EAAK,OAAA;AAAA,sBACL,SAAA,EAAW,CAAA,EAAG,OAAA,CAAQ,kBAAkB,CAAA,CAAA,EACtC,aAAa,EAAA,KAAO,QAAA,GAChB,OAAA,CAAQ,wBAAA,GACR,EACN,CAAA,CAAA;AAAA,sBACA,cAAY,YAAA,CAAa,KAAA;AAAA,sBACzB,OAAA,EAAS,MAAM,YAAA,CAAa,YAAA,CAAa,EAAE,CAAA;AAAA,sBAE3C,QAAA,kBAAA,GAAA;AAAA,wBAAC,SAAA;AAAA,wBAAA;AAAA,0BACC,MAAA,EAAQ,YAAA;AAAA,4BACN,YAAA,CAAa,OAAA;AAAA,4BACb,YAAA,CAAa;AAAA,2BACf;AAAA,0BAEA,QAAA,kBAAA,GAAA,CAAC,qBAAA,EAAA,EAAsB,QAAA,EAAS,OAAA,EAAQ;AAAA;AAAA;AAC1C;AAAA;AACF,iBAAA;AAAA,gBAtBK,YAAA,CAAa;AAAA,eAwBrB;AAAA;AAAA;AACH;AAAA;AAAA,wBAGF,GAAA,CAAC,OAAA,EAAA,EAAM,WAAW,OAAA,CAAQ,QAAA,EAAU,cAAW,kBAAA,EAC7C,QAAA,kBAAA,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,YAAY,MAAA,CAAO,UAAA;AAAA,QACnB,mBAAmB,SAAA,CAAU,EAAA;AAAA,QAC7B,iBAAA,EAAmB,qBAAA;AAAA,QACnB,WAAA;AAAA,QACA,aAAA;AAAA,QACA,QAAA;AAAA,QACA,KAAA,EAAO,SAAA;AAAA,QACP,QAAA,EAAU,YAAA;AAAA,QACV,QAAA,EAAU,YAAA;AAAA,QACV,KAAA,EAAO,SAAA;AAAA,QACP,QAAA,EAAU,YAAA;AAAA,QACV,UAAA,EAAY,MAAM,oBAAA,CAAqB,IAAI;AAAA;AAAA,KAC7C,EACF,CAAA;AAAA,yBAGD,MAAA,EAAA,EAAK,SAAA,EAAW,OAAA,CAAQ,UAAA,EAAY,cAAW,gBAAA,EAC9C,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,YAAA,EACtB,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,cAAA,EACtB,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,eAAA,EAAA,EAAgB,KAAA,EAAO,SAAA,CAAU,KAAA,EAAO,MAAM,EAAA,EAAI,CAAA;AAAA,0BACnD,GAAA,CAAC,cAAW,OAAA,EAAQ,WAAA,EAAY,WAAW,OAAA,CAAQ,aAAA,EAChD,oBAAU,KAAA,EACb,CAAA;AAAA,UACC,WAAA,oBACC,IAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAQ,OAAA;AAAA,cACR,WAAW,OAAA,CAAQ,WAAA;AAAA,cACnB,KAAA,EAAO,WAAA;AAAA,cACR,QAAA,EAAA;AAAA,gBAAA,OAAA;AAAA,gBACI;AAAA;AAAA;AAAA;AACL,SAAA,EAEJ,CAAA;AAAA,QACC;AAAA,OAAA,EACH,CAAA;AAAA,sBACA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,UAAA,EACrB,yCACC,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,UAAA,EACtB,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,cAAW,OAAA,EAAQ,OAAA,EAAQ,SAAA,EAAW,OAAA,CAAQ,YAAY,QAAA,EAAA,qBAAA,EAE3D,CAAA;AAAA,wBACA,IAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAQ,OAAM,eAAA,EAAgB,QAAA,EAAA;AAAA,UAAA,wBAAA;AAAA,UACzB,SAAA,CAAU,KAAA;AAAA,UAAM;AAAA,SAAA,EACzC,CAAA;AAAA,wBACA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,OAAA,EAAQ,UAAA;AAAA,YACR,IAAA,EAAK,OAAA;AAAA,YACL,SAAA,sBAAY,OAAA,EAAA,EAAQ,CAAA;AAAA,YACpB,OAAA,EAAS,SAAA;AAAA,YACT,WAAW,OAAA,CAAQ,WAAA;AAAA,YACpB,QAAA,EAAA;AAAA;AAAA;AAED,OAAA,EACF,CAAA,mBAEA,GAAA;AAAA,QAAC,mBAAA;AAAA,QAAA;AAAA,UACC,mBAAA,EAAqB,SAAA,CAAU,EAAA,EAAI,QAAA,EAAU,WAAA;AAAA,UAC7C,WAAA,EAAa,UAAU,EAAA,EAAI,WAAA;AAAA,UAC3B,gBAAgB,SAAA,CAAU;AAAA;AAAA,OAC5B,EAEJ;AAAA,KAAA,EACF;AAAA,GAAA,EACF,GACF,CAAA,EACF,CAAA;AAEJ;;;;"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { makeStyles } from '@material-ui/core/styles';
|
|
4
|
-
import { List, ListItem, ListItemIcon,
|
|
4
|
+
import { List, ListItem, ListItemIcon, TextField, Tooltip, ListItemText, ListItemSecondaryAction, IconButton, Menu, MenuItem } from '@material-ui/core';
|
|
5
5
|
import BookmarkIcon from '@material-ui/icons/Bookmark';
|
|
6
6
|
import ChatBubbleOutlineIcon from '@material-ui/icons/ChatBubbleOutline';
|
|
7
7
|
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
|
8
|
+
import { StatusDot } from './StatusDot.esm.js';
|
|
9
|
+
import { toConvStatus } from './useThreadStatus.esm.js';
|
|
8
10
|
|
|
9
11
|
const useStyles = makeStyles((theme) => ({
|
|
10
12
|
root: {
|
|
@@ -103,17 +105,7 @@ function ConversationsPanel({
|
|
|
103
105
|
ContainerProps: { className: classes.container },
|
|
104
106
|
onClick: () => onSelect(conv.id),
|
|
105
107
|
children: [
|
|
106
|
-
/* @__PURE__ */ jsx(ListItemIcon, { style: { minWidth: 32 }, children: /* @__PURE__ */ jsx(
|
|
107
|
-
Badge,
|
|
108
|
-
{
|
|
109
|
-
color: conv.generating ? "primary" : "error",
|
|
110
|
-
variant: "dot",
|
|
111
|
-
overlap: "circular",
|
|
112
|
-
invisible: conv.id === activeId || !conv.generating && !conv.unread,
|
|
113
|
-
classes: conv.generating ? { dot: classes.pulseDot } : void 0,
|
|
114
|
-
children: /* @__PURE__ */ jsx(ChatBubbleOutlineIcon, { fontSize: "small" })
|
|
115
|
-
}
|
|
116
|
-
) }),
|
|
108
|
+
/* @__PURE__ */ jsx(ListItemIcon, { style: { minWidth: 32 }, children: /* @__PURE__ */ jsx(StatusDot, { status: toConvStatus(conv.working, conv.unread), children: /* @__PURE__ */ jsx(ChatBubbleOutlineIcon, { fontSize: "small" }) }) }),
|
|
117
109
|
renamingId === conv.id ? /* @__PURE__ */ jsx(
|
|
118
110
|
TextField,
|
|
119
111
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationsPanel.esm.js","sources":["../../src/collapsible/ConversationsPanel.tsx"],"sourcesContent":["/* eslint-disable jsx-a11y/no-autofocus -- the inline rename field appears on a\n deliberate user action (Rename) and should take focus immediately. */\nimport { MouseEvent, useState } from 'react';\nimport { makeStyles } from '@material-ui/core/styles';\nimport {\n Badge,\n IconButton,\n List,\n ListItem,\n ListItemIcon,\n ListItemSecondaryAction,\n ListItemText,\n Menu,\n MenuItem,\n TextField,\n Tooltip,\n} from '@material-ui/core';\nimport BookmarkIcon from '@material-ui/icons/Bookmark';\nimport ChatBubbleOutlineIcon from '@material-ui/icons/ChatBubbleOutline';\nimport MoreVertIcon from '@material-ui/icons/MoreVert';\nimport type { ThreadSummary } from './threadListAdapter';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n display: 'flex',\n flexDirection: 'column',\n padding: theme.spacing(0.5, 1.5, 1),\n gap: theme.spacing(1),\n },\n activeItem: {\n borderRadius: theme.shape.borderRadius,\n backgroundColor: theme.palette.action.selected,\n },\n listItem: {\n borderRadius: theme.shape.borderRadius,\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n },\n // Reveal the row's ⋮ only on hover so the title gets the full width otherwise.\n // Must live on the container <li> (ContainerProps): the secondary action is a\n // sibling of the ListItem root, so a :hover on the row can't reach it.\n container: {\n '&:hover $action': {\n opacity: 1,\n pointerEvents: 'auto',\n },\n },\n action: {\n opacity: 0,\n pointerEvents: 'none',\n transition: theme.transitions.create('opacity'),\n },\n // Keep the ⋮ visible while its menu is open (even if the row isn't hovered).\n actionVisible: {\n opacity: 1,\n pointerEvents: 'auto',\n },\n pinnedIcon: {\n color: theme.palette.warning.main,\n fontSize: '0.875rem',\n marginRight: theme.spacing(0.5),\n },\n renameInput: {\n '& input': {\n fontSize: '0.875rem',\n padding: theme.spacing(0.5, 1),\n },\n },\n emptyState: {\n padding: theme.spacing(3, 2),\n textAlign: 'center',\n },\n '@keyframes auiPulse': {\n '0%': { transform: 'scale(1)', opacity: 1 },\n '50%': { transform: 'scale(1.5)', opacity: 0.45 },\n '100%': { transform: 'scale(1)', opacity: 1 },\n },\n pulseDot: {\n animation: '$auiPulse 1.2s ease-in-out infinite',\n },\n}));\n\n/**\n * Props for {@link ConversationsPanel}.\n *\n * @public\n */\nexport interface ConversationsPanelProps {\n conversations: ThreadSummary[];\n activeId: string | null;\n onSelect: (id: string | null) => void;\n onRename: (id: string, title: string) => void;\n onPin: (id: string) => void;\n onDelete: (id: string) => void;\n}\n\n/**\n * The expanded sidebar's conversation list (ported from Implementation 1): a\n * \"New Chat\" button, the conversation rows (active highlight, pinned bookmark\n * icon, inline rename), and a per-row overflow (⋮) menu with Rename / Pin /\n * Delete.\n *\n * @public\n */\nexport function ConversationsPanel({\n conversations,\n activeId,\n onSelect,\n onRename,\n onPin,\n onDelete,\n}: ConversationsPanelProps) {\n const classes = useStyles();\n const [menuAnchor, setMenuAnchor] = useState<{\n el: HTMLElement;\n id: string;\n } | null>(null);\n const [renamingId, setRenamingId] = useState<string | null>(null);\n const [renameValue, setRenameValue] = useState('');\n\n const handleMenuOpen = (e: MouseEvent<HTMLElement>, id: string) => {\n e.stopPropagation();\n setMenuAnchor({ el: e.currentTarget, id });\n };\n\n const handleMenuClose = () => setMenuAnchor(null);\n\n const handleRenameStart = (conv: ThreadSummary) => {\n setRenamingId(conv.id);\n setRenameValue(conv.title);\n handleMenuClose();\n };\n\n const handleRenameSubmit = () => {\n if (renamingId && renameValue.trim()) {\n onRename(renamingId, renameValue.trim());\n }\n setRenamingId(null);\n };\n\n return (\n <div className={classes.root}>\n {conversations.length === 0 ? null : (\n <List disablePadding dense>\n {conversations.map(conv => (\n <ListItem\n key={conv.id}\n button\n className={\n conv.id === activeId ? classes.activeItem : classes.listItem\n }\n ContainerProps={{ className: classes.container }}\n onClick={() => onSelect(conv.id)}\n >\n <ListItemIcon style={{ minWidth: 32 }}>\n <Badge\n color={conv.generating ? 'primary' : 'error'}\n variant=\"dot\"\n overlap=\"circular\"\n invisible={\n conv.id === activeId || (!conv.generating && !conv.unread)\n }\n classes={conv.generating ? { dot: classes.pulseDot } : undefined}\n >\n <ChatBubbleOutlineIcon fontSize=\"small\" />\n </Badge>\n </ListItemIcon>\n {renamingId === conv.id ? (\n <TextField\n className={classes.renameInput}\n value={renameValue}\n onChange={e => setRenameValue(e.target.value)}\n onBlur={handleRenameSubmit}\n onKeyDown={e => {\n if (e.key === 'Enter') handleRenameSubmit();\n if (e.key === 'Escape') setRenamingId(null);\n }}\n autoFocus\n fullWidth\n size=\"small\"\n variant=\"standard\"\n />\n ) : (\n <Tooltip title={conv.title} placement=\"right\" arrow>\n <ListItemText\n primary={\n <>\n {conv.pinned && (\n <BookmarkIcon className={classes.pinnedIcon} />\n )}\n {conv.title}\n </>\n }\n primaryTypographyProps={{ variant: 'body2', noWrap: true }}\n />\n </Tooltip>\n )}\n <ListItemSecondaryAction\n className={`${classes.action}${\n menuAnchor?.id === conv.id ? ` ${classes.actionVisible}` : ''\n }`}\n >\n <IconButton\n edge=\"end\"\n size=\"small\"\n aria-label=\"Conversation options\"\n onClick={e => handleMenuOpen(e, conv.id)}\n >\n <MoreVertIcon fontSize=\"small\" />\n </IconButton>\n </ListItemSecondaryAction>\n </ListItem>\n ))}\n </List>\n )}\n\n <Menu\n anchorEl={menuAnchor?.el}\n open={Boolean(menuAnchor)}\n onClose={handleMenuClose}\n >\n {menuAnchor &&\n (() => {\n const conv = conversations.find(c => c.id === menuAnchor.id);\n if (!conv) return null;\n return [\n <MenuItem key=\"rename\" onClick={() => handleRenameStart(conv)}>\n Rename\n </MenuItem>,\n <MenuItem\n key=\"pin\"\n onClick={() => {\n onPin(conv.id);\n handleMenuClose();\n }}\n >\n {conv.pinned ? 'Unpin' : 'Pin'}\n </MenuItem>,\n <MenuItem\n key=\"delete\"\n onClick={() => {\n onDelete(conv.id);\n handleMenuClose();\n }}\n >\n Delete\n </MenuItem>,\n ];\n })()}\n </Menu>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ConversationsPanel.esm.js","sources":["../../src/collapsible/ConversationsPanel.tsx"],"sourcesContent":["/* eslint-disable jsx-a11y/no-autofocus -- the inline rename field appears on a\n deliberate user action (Rename) and should take focus immediately. */\nimport { MouseEvent, useState } from 'react';\nimport { makeStyles } from '@material-ui/core/styles';\nimport {\n IconButton,\n List,\n ListItem,\n ListItemIcon,\n ListItemSecondaryAction,\n ListItemText,\n Menu,\n MenuItem,\n TextField,\n Tooltip,\n} from '@material-ui/core';\nimport BookmarkIcon from '@material-ui/icons/Bookmark';\nimport ChatBubbleOutlineIcon from '@material-ui/icons/ChatBubbleOutline';\nimport MoreVertIcon from '@material-ui/icons/MoreVert';\nimport { StatusDot } from './StatusDot';\nimport { toConvStatus } from './useThreadStatus';\nimport type { ThreadSummary } from './threadListAdapter';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n display: 'flex',\n flexDirection: 'column',\n padding: theme.spacing(0.5, 1.5, 1),\n gap: theme.spacing(1),\n },\n activeItem: {\n borderRadius: theme.shape.borderRadius,\n backgroundColor: theme.palette.action.selected,\n },\n listItem: {\n borderRadius: theme.shape.borderRadius,\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n },\n // Reveal the row's ⋮ only on hover so the title gets the full width otherwise.\n // Must live on the container <li> (ContainerProps): the secondary action is a\n // sibling of the ListItem root, so a :hover on the row can't reach it.\n container: {\n '&:hover $action': {\n opacity: 1,\n pointerEvents: 'auto',\n },\n },\n action: {\n opacity: 0,\n pointerEvents: 'none',\n transition: theme.transitions.create('opacity'),\n },\n // Keep the ⋮ visible while its menu is open (even if the row isn't hovered).\n actionVisible: {\n opacity: 1,\n pointerEvents: 'auto',\n },\n pinnedIcon: {\n color: theme.palette.warning.main,\n fontSize: '0.875rem',\n marginRight: theme.spacing(0.5),\n },\n renameInput: {\n '& input': {\n fontSize: '0.875rem',\n padding: theme.spacing(0.5, 1),\n },\n },\n emptyState: {\n padding: theme.spacing(3, 2),\n textAlign: 'center',\n },\n '@keyframes auiPulse': {\n '0%': { transform: 'scale(1)', opacity: 1 },\n '50%': { transform: 'scale(1.5)', opacity: 0.45 },\n '100%': { transform: 'scale(1)', opacity: 1 },\n },\n pulseDot: {\n animation: '$auiPulse 1.2s ease-in-out infinite',\n },\n}));\n\n/**\n * Props for {@link ConversationsPanel}.\n *\n * @public\n */\nexport interface ConversationsPanelProps {\n conversations: ThreadSummary[];\n activeId: string | null;\n onSelect: (id: string | null) => void;\n onRename: (id: string, title: string) => void;\n onPin: (id: string) => void;\n onDelete: (id: string) => void;\n}\n\n/**\n * The expanded sidebar's conversation list (ported from Implementation 1): a\n * \"New Chat\" button, the conversation rows (active highlight, pinned bookmark\n * icon, inline rename), and a per-row overflow (⋮) menu with Rename / Pin /\n * Delete.\n *\n * @public\n */\nexport function ConversationsPanel({\n conversations,\n activeId,\n onSelect,\n onRename,\n onPin,\n onDelete,\n}: ConversationsPanelProps) {\n const classes = useStyles();\n const [menuAnchor, setMenuAnchor] = useState<{\n el: HTMLElement;\n id: string;\n } | null>(null);\n const [renamingId, setRenamingId] = useState<string | null>(null);\n const [renameValue, setRenameValue] = useState('');\n\n const handleMenuOpen = (e: MouseEvent<HTMLElement>, id: string) => {\n e.stopPropagation();\n setMenuAnchor({ el: e.currentTarget, id });\n };\n\n const handleMenuClose = () => setMenuAnchor(null);\n\n const handleRenameStart = (conv: ThreadSummary) => {\n setRenamingId(conv.id);\n setRenameValue(conv.title);\n handleMenuClose();\n };\n\n const handleRenameSubmit = () => {\n if (renamingId && renameValue.trim()) {\n onRename(renamingId, renameValue.trim());\n }\n setRenamingId(null);\n };\n\n return (\n <div className={classes.root}>\n {conversations.length === 0 ? null : (\n <List disablePadding dense>\n {conversations.map(conv => (\n <ListItem\n key={conv.id}\n button\n className={\n conv.id === activeId ? classes.activeItem : classes.listItem\n }\n ContainerProps={{ className: classes.container }}\n onClick={() => onSelect(conv.id)}\n >\n <ListItemIcon style={{ minWidth: 32 }}>\n <StatusDot status={toConvStatus(conv.working, conv.unread)}>\n <ChatBubbleOutlineIcon fontSize=\"small\" />\n </StatusDot>\n </ListItemIcon>\n {renamingId === conv.id ? (\n <TextField\n className={classes.renameInput}\n value={renameValue}\n onChange={e => setRenameValue(e.target.value)}\n onBlur={handleRenameSubmit}\n onKeyDown={e => {\n if (e.key === 'Enter') handleRenameSubmit();\n if (e.key === 'Escape') setRenamingId(null);\n }}\n autoFocus\n fullWidth\n size=\"small\"\n variant=\"standard\"\n />\n ) : (\n <Tooltip title={conv.title} placement=\"right\" arrow>\n <ListItemText\n primary={\n <>\n {conv.pinned && (\n <BookmarkIcon className={classes.pinnedIcon} />\n )}\n {conv.title}\n </>\n }\n primaryTypographyProps={{ variant: 'body2', noWrap: true }}\n />\n </Tooltip>\n )}\n <ListItemSecondaryAction\n className={`${classes.action}${\n menuAnchor?.id === conv.id ? ` ${classes.actionVisible}` : ''\n }`}\n >\n <IconButton\n edge=\"end\"\n size=\"small\"\n aria-label=\"Conversation options\"\n onClick={e => handleMenuOpen(e, conv.id)}\n >\n <MoreVertIcon fontSize=\"small\" />\n </IconButton>\n </ListItemSecondaryAction>\n </ListItem>\n ))}\n </List>\n )}\n\n <Menu\n anchorEl={menuAnchor?.el}\n open={Boolean(menuAnchor)}\n onClose={handleMenuClose}\n >\n {menuAnchor &&\n (() => {\n const conv = conversations.find(c => c.id === menuAnchor.id);\n if (!conv) return null;\n return [\n <MenuItem key=\"rename\" onClick={() => handleRenameStart(conv)}>\n Rename\n </MenuItem>,\n <MenuItem\n key=\"pin\"\n onClick={() => {\n onPin(conv.id);\n handleMenuClose();\n }}\n >\n {conv.pinned ? 'Unpin' : 'Pin'}\n </MenuItem>,\n <MenuItem\n key=\"delete\"\n onClick={() => {\n onDelete(conv.id);\n handleMenuClose();\n }}\n >\n Delete\n </MenuItem>,\n ];\n })()}\n </Menu>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import Badge from '@material-ui/core/Badge';
|
|
3
|
+
import { makeStyles } from '@material-ui/core/styles';
|
|
4
|
+
|
|
5
|
+
const WORKING_COLOR = "#e3a008";
|
|
6
|
+
const UNREAD_COLOR = "#f44336";
|
|
7
|
+
const useStyles = makeStyles({
|
|
8
|
+
"@keyframes auiStatusPulse": {
|
|
9
|
+
"0%": { transform: "scale(1)", opacity: 1 },
|
|
10
|
+
"50%": { transform: "scale(1.6)", opacity: 0.4 },
|
|
11
|
+
"100%": { transform: "scale(1)", opacity: 1 }
|
|
12
|
+
},
|
|
13
|
+
working: {
|
|
14
|
+
backgroundColor: WORKING_COLOR,
|
|
15
|
+
color: WORKING_COLOR,
|
|
16
|
+
animation: "$auiStatusPulse 1.2s ease-in-out infinite"
|
|
17
|
+
},
|
|
18
|
+
unread: { backgroundColor: UNREAD_COLOR, color: UNREAD_COLOR }
|
|
19
|
+
});
|
|
20
|
+
function StatusDot({
|
|
21
|
+
status,
|
|
22
|
+
overlap = "circular",
|
|
23
|
+
children
|
|
24
|
+
}) {
|
|
25
|
+
const classes = useStyles();
|
|
26
|
+
return /* @__PURE__ */ jsx(
|
|
27
|
+
Badge,
|
|
28
|
+
{
|
|
29
|
+
variant: "dot",
|
|
30
|
+
overlap,
|
|
31
|
+
invisible: status === "read",
|
|
32
|
+
classes: { badge: status === "working" ? classes.working : classes.unread },
|
|
33
|
+
children
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { StatusDot };
|
|
39
|
+
//# sourceMappingURL=StatusDot.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatusDot.esm.js","sources":["../../src/collapsible/StatusDot.tsx"],"sourcesContent":["/**\n * The single rendering of conversation status as a badge dot — used by the\n * conversation rows, the agent rail, and the nav icon so they can never disagree\n * on look or meaning:\n * - working (in-flight) → amber, pulsing\n * - unread → solid red\n * - read → nothing\n */\nimport Badge from '@material-ui/core/Badge';\nimport { makeStyles } from '@material-ui/core/styles';\nimport type { PropsWithChildren } from 'react';\nimport type { ConvStatus } from './useThreadStatus';\n\nconst WORKING_COLOR = '#e3a008'; // amber / \"warning\"\nconst UNREAD_COLOR = '#f44336'; // red\n\nconst useStyles = makeStyles({\n '@keyframes auiStatusPulse': {\n '0%': { transform: 'scale(1)', opacity: 1 },\n '50%': { transform: 'scale(1.6)', opacity: 0.4 },\n '100%': { transform: 'scale(1)', opacity: 1 },\n },\n working: {\n backgroundColor: WORKING_COLOR,\n color: WORKING_COLOR,\n animation: '$auiStatusPulse 1.2s ease-in-out infinite',\n },\n unread: { backgroundColor: UNREAD_COLOR, color: UNREAD_COLOR },\n});\n\nexport interface StatusDotProps {\n status: ConvStatus;\n /** Badge overlap shape around the wrapped element. Defaults to circular. */\n overlap?: 'circular' | 'rectangular';\n}\n\nexport function StatusDot({\n status,\n overlap = 'circular',\n children,\n}: PropsWithChildren<StatusDotProps>) {\n const classes = useStyles();\n return (\n <Badge\n variant=\"dot\"\n overlap={overlap}\n invisible={status === 'read'}\n classes={{ badge: status === 'working' ? classes.working : classes.unread }}\n >\n {children}\n </Badge>\n );\n}\n"],"names":[],"mappings":";;;;AAaA,MAAM,aAAA,GAAgB,SAAA;AACtB,MAAM,YAAA,GAAe,SAAA;AAErB,MAAM,YAAY,UAAA,CAAW;AAAA,EAC3B,2BAAA,EAA6B;AAAA,IAC3B,IAAA,EAAM,EAAE,SAAA,EAAW,UAAA,EAAY,SAAS,CAAA,EAAE;AAAA,IAC1C,KAAA,EAAO,EAAE,SAAA,EAAW,YAAA,EAAc,SAAS,GAAA,EAAI;AAAA,IAC/C,MAAA,EAAQ,EAAE,SAAA,EAAW,UAAA,EAAY,SAAS,CAAA;AAAE,GAC9C;AAAA,EACA,OAAA,EAAS;AAAA,IACP,eAAA,EAAiB,aAAA;AAAA,IACjB,KAAA,EAAO,aAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,MAAA,EAAQ,EAAE,eAAA,EAAiB,YAAA,EAAc,OAAO,YAAA;AAClD,CAAC,CAAA;AAQM,SAAS,SAAA,CAAU;AAAA,EACxB,MAAA;AAAA,EACA,OAAA,GAAU,UAAA;AAAA,EACV;AACF,CAAA,EAAsC;AACpC,EAAA,MAAM,UAAU,SAAA,EAAU;AAC1B,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAQ,KAAA;AAAA,MACR,OAAA;AAAA,MACA,WAAW,MAAA,KAAW,MAAA;AAAA,MACtB,OAAA,EAAS,EAAE,KAAA,EAAO,MAAA,KAAW,YAAY,OAAA,CAAQ,OAAA,GAAU,QAAQ,MAAA,EAAO;AAAA,MAEzE;AAAA;AAAA,GACH;AAEJ;;;;"}
|
|
@@ -9,7 +9,7 @@ import { resolveAssistantColor, DEFAULT_AVATAR_COLOR } from './AssistantAvatar.e
|
|
|
9
9
|
import { ThreadPrimitive } from '@assistant-ui/react';
|
|
10
10
|
import { Thread, UserMessage, ThreadWelcome, AssistantMessage, BranchPicker, AssistantActionBar } from '@assistant-ui/react-ui';
|
|
11
11
|
import { MarkdownText } from './MarkdownText.esm.js';
|
|
12
|
-
import { ToolFallback, ThinkingMessage, ReasoningPart } from './parts.esm.js';
|
|
12
|
+
import { ToolFallback, ThinkingMessage, ReasoningPart, MessageError } from './parts.esm.js';
|
|
13
13
|
|
|
14
14
|
const DEFAULT_WELCOME_SUBTITLE = "Ask me about services, APIs, teams, TechDocs, or anything in the catalog.";
|
|
15
15
|
const AvatarColorContext = createContext(void 0);
|
|
@@ -147,6 +147,7 @@ function AssistantMessageWithAvatar() {
|
|
|
147
147
|
return /* @__PURE__ */ jsxs(AssistantMessage.Root, { children: [
|
|
148
148
|
/* @__PURE__ */ jsx(AssistantBotAvatar, {}),
|
|
149
149
|
/* @__PURE__ */ jsx(AssistantMessage.Content, { components: { Reasoning: ReasoningPart } }),
|
|
150
|
+
/* @__PURE__ */ jsx(MessageError, {}),
|
|
150
151
|
/* @__PURE__ */ jsx(BranchPicker, {}),
|
|
151
152
|
/* @__PURE__ */ jsx(AssistantActionBar, {})
|
|
152
153
|
] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationSurface.esm.js","sources":["../../../src/collapsible/surface/ConversationSurface.tsx"],"sourcesContent":["// The prebuilt react-ui `<Thread>` stylesheet is vendored locally under\n// `styles/` and imported once at the top of `CollapsiblePage.tsx`. It is NOT\n// imported here: react-ui's `sideEffects: false` lets bundlers tree-shake a\n// bare CSS import from inside a lazily-loaded component, which left the Thread\n// unstyled.\nimport {\n createContext,\n useContext,\n useEffect,\n useState,\n type CSSProperties,\n} from 'react';\nimport type { ProfileInfo } from '@backstage/core-plugin-api';\nimport { identityApiRef, useApi } from '@backstage/core-plugin-api';\nimport { Avatar as BackstageAvatar } from '@backstage/core-components';\nimport { makeStyles, useTheme } from '@material-ui/core/styles';\nimport { Button, Typography } from '@material-ui/core';\nimport { BackstageLogo } from './BackstageLogo';\nimport { DEFAULT_AVATAR_COLOR, resolveAssistantColor } from './AssistantAvatar';\nimport { ThreadPrimitive } from '@assistant-ui/react';\nimport {\n AssistantActionBar,\n AssistantMessage,\n BranchPicker,\n Thread,\n ThreadWelcome,\n UserMessage,\n} from '@assistant-ui/react-ui';\nimport { MarkdownText } from './MarkdownText';\nimport { ReasoningPart, ThinkingMessage, ToolFallback } from './parts';\n\nconst DEFAULT_WELCOME_SUBTITLE =\n 'Ask me about services, APIs, teams, TechDocs, or anything in the catalog.';\n\n// The active assistant's avatar color. ConversationSurface provides it; the\n// message components (passed to <Thread> by reference, so they can't take props)\n// read it from context. Falls back to DEFAULT_AVATAR_COLOR.\nconst AvatarColorContext = createContext<string | undefined>(undefined);\n\nconst useStyles = makeStyles(theme => ({\n threadHost: {\n flex: 1,\n minHeight: 0,\n '& .aui-thread-root': {\n // Wide conversation pane to maximize room for diagrams / visual artifacts.\n // (The composer is narrowed independently via the footer max-width below.)\n '--aui-thread-max-width': '90%',\n '--aui-background':\n theme.palette.type === 'dark' ? '0 0% 18%' : '0 0% 100%',\n '--aui-foreground':\n theme.palette.type === 'dark' ? '0 0% 98%' : '240 10% 3.9%',\n '--aui-muted':\n theme.palette.type === 'dark' ? '0 0% 24%' : '240 4.8% 95.9%',\n '--aui-muted-foreground':\n theme.palette.type === 'dark' ? '0 0% 70%' : '240 3.8% 46.1%',\n '--aui-accent':\n theme.palette.type === 'dark' ? '0 0% 24%' : '240 4.8% 95.9%',\n '--aui-accent-foreground':\n theme.palette.type === 'dark' ? '0 0% 98%' : '240 5.9% 10%',\n '--aui-border':\n theme.palette.type === 'dark' ? '0 0% 40%' : '240 5.9% 90%',\n '--aui-input':\n theme.palette.type === 'dark' ? '0 0% 40%' : '240 5.9% 90%',\n '--aui-ring':\n theme.palette.type === 'dark' ? '207 90% 68%' : '210 90% 45%',\n '--aui-primary':\n theme.palette.type === 'dark' ? '0 0% 98%' : '240 5.9% 10%',\n '--aui-primary-foreground':\n theme.palette.type === 'dark' ? '240 5.9% 10%' : '0 0% 98%',\n },\n // Active composer border tinted to the agent color (set as --aui-composer-focus\n // on the host below); falls back to the theme primary if unset.\n '& .aui-composer-root:focus-within': {\n borderColor: 'var(--aui-composer-focus)',\n boxShadow: '0 0 0 1px var(--aui-composer-focus)',\n },\n '& .aui-assistant-message-content': {\n maxWidth: '100%',\n width: '100%',\n },\n // The composer is narrower than the conversation: cap the footer (which holds\n // the composer and is centered in the viewport) below the 90% thread width.\n // Bottom padding is left at the react-ui stock value (1rem) — overriding it\n // larger left a too-tall solid footer band beneath the composer.\n '& .aui-thread-viewport-footer': {\n maxWidth: '48rem',\n },\n },\n botAvatar: {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n // Transparent so the tinted logo floats (overrides react-ui's aui-avatar-root).\n backgroundColor: 'transparent',\n // Bumped to ~match the user avatar (which has an encircling disc); the\n // floating logo looked small by comparison.\n width: 32,\n height: 32,\n },\n botLogo: {\n height: '100%',\n width: 'auto',\n },\n userMessageWithAvatar: {\n display: 'flex',\n width: '100%',\n maxWidth: 'var(--aui-thread-max-width)',\n flexDirection: 'column',\n alignItems: 'flex-end',\n gap: theme.spacing(0.5),\n paddingTop: theme.spacing(1),\n paddingBottom: theme.spacing(1),\n },\n userMessageBody: {\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'flex-end',\n gap: theme.spacing(1),\n '& .aui-user-message-content': {\n maxWidth: '100%',\n },\n },\n userAvatar: {\n width: theme.spacing(5),\n height: theme.spacing(5),\n marginTop: theme.spacing(0.25),\n flexShrink: 0,\n },\n welcomeRoot: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: theme.spacing(2),\n maxWidth: '28rem',\n textAlign: 'center',\n },\n welcomeLogo: {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 56,\n height: 56,\n },\n welcomeLogoIcon: {\n width: 30,\n height: 'auto',\n },\n welcomeGreeting: {\n fontWeight: 500,\n color: theme.palette.text.primary,\n },\n welcomeSubtitle: {\n color: theme.palette.text.secondary,\n },\n suggestions: {\n display: 'flex',\n flexWrap: 'wrap',\n justifyContent: 'center',\n gap: theme.spacing(1),\n marginTop: theme.spacing(1),\n },\n suggestionButton: {\n textTransform: 'none',\n borderRadius: 999,\n },\n}));\n\n/** A circular MUI-styled bot avatar (no host asset dependency). */\nfunction AssistantBotAvatar() {\n const classes = useStyles();\n const color = useContext(AvatarColorContext) ?? DEFAULT_AVATAR_COLOR;\n\n return (\n <span\n className={`aui-avatar-root ${classes.botAvatar}`}\n style={{ color, backgroundColor: 'transparent' }}\n aria-label=\"Backstage assistant\"\n role=\"img\"\n >\n <BackstageLogo className={classes.botLogo} />\n </span>\n );\n}\n\nfunction AssistantMessageWithAvatar() {\n return (\n <AssistantMessage.Root>\n <AssistantBotAvatar />\n <AssistantMessage.Content components={{ Reasoning: ReasoningPart }} />\n <BranchPicker />\n <AssistantActionBar />\n </AssistantMessage.Root>\n );\n}\n\n/** Read the signed-in user's profile (display name, picture) once. */\nfunction useProfile() {\n const identityApi = useApi(identityApiRef);\n const [profile, setProfile] = useState<ProfileInfo>();\n\n useEffect(() => {\n let mounted = true;\n\n identityApi.getProfileInfo().then(value => {\n if (mounted) {\n setProfile(value);\n }\n });\n\n return () => {\n mounted = false;\n };\n }, [identityApi]);\n\n return profile;\n}\n\nfunction UserChatAvatar() {\n const classes = useStyles();\n const profile = useProfile();\n\n return (\n <BackstageAvatar\n classes={{ avatar: classes.userAvatar }}\n displayName={profile?.displayName ?? profile?.email ?? 'You'}\n picture={profile?.picture}\n />\n );\n}\n\nfunction UserMessageWithAvatar() {\n const classes = useStyles();\n\n return (\n <UserMessage.Root className={classes.userMessageWithAvatar}>\n <UserMessage.Attachments />\n <div className={classes.userMessageBody}>\n <UserMessage.Content />\n <UserChatAvatar />\n </div>\n </UserMessage.Root>\n );\n}\n\n/**\n * Props for {@link ConversationSurface}.\n *\n * @public\n */\nexport interface ConversationSurfaceProps {\n /** Placeholder text for the composer input (from the assistant's ui config). */\n composerPlaceholder?: string;\n /** Starter prompts shown as clickable chips on the empty thread. */\n suggestions?: Array<{ title: string; prompt: string }>;\n /** Overrides for the default empty-thread greeting. */\n welcome?: { title?: string; subtitle?: string };\n /** The active assistant's avatar tint (hex); defaults to Backstage teal. */\n assistantColor?: string;\n /** Host layout escape hatch (applied alongside the themed thread host). */\n className?: string;\n}\n\n/**\n * The react-ui `<Thread>` rendered with Implementation 1's custom message\n * components: a bot-avatar assistant message, an avatar'd user message,\n * Markdown (with streaming-safe Mermaid), a tool-call fallback, a thinking /\n * error empty-state, and a personalized empty-thread welcome with optional\n * starter-prompt chips.\n *\n * This is a \"bring your own runtime\" surface — it expects an\n * `AssistantRuntimeProvider` higher in the tree.\n *\n * @public\n */\nexport function ConversationSurface(props: ConversationSurfaceProps) {\n const { composerPlaceholder, suggestions, welcome, assistantColor, className } =\n props;\n const classes = useStyles();\n const theme = useTheme();\n // One mode-appropriate shade for every place the agent color appears here\n // (chat bot avatar via context, welcome logo, composer focus border).\n const resolvedColor = resolveAssistantColor(assistantColor, theme.palette.type);\n\n function EmptyThreadWelcome() {\n const profile = useProfile();\n const firstName = profile?.displayName?.split(' ')[0] ?? 'there';\n\n const title = welcome?.title ?? `Hi ${firstName}, welcome to Backstage`;\n const subtitle = welcome?.subtitle ?? DEFAULT_WELCOME_SUBTITLE;\n\n return (\n <ThreadWelcome.Root>\n <ThreadWelcome.Center>\n <div className={classes.welcomeRoot}>\n <span\n className={classes.welcomeLogo}\n style={{ color: resolvedColor }}\n aria-hidden=\"true\"\n >\n <BackstageLogo className={classes.welcomeLogoIcon} />\n </span>\n <Typography variant=\"h5\" className={classes.welcomeGreeting}>\n {title}\n </Typography>\n <Typography variant=\"body2\" className={classes.welcomeSubtitle}>\n {subtitle}\n </Typography>\n {suggestions && suggestions.length > 0 && (\n <div className={classes.suggestions}>\n {suggestions.map(suggestion => (\n <ThreadPrimitive.Suggestion\n key={suggestion.prompt}\n prompt={suggestion.prompt}\n send\n asChild\n >\n <Button\n variant=\"outlined\"\n size=\"small\"\n className={classes.suggestionButton}\n >\n {suggestion.title}\n </Button>\n </ThreadPrimitive.Suggestion>\n ))}\n </div>\n )}\n </div>\n </ThreadWelcome.Center>\n </ThreadWelcome.Root>\n );\n }\n\n return (\n <AvatarColorContext.Provider value={resolvedColor}>\n <div\n className={`${classes.threadHost} ${className ?? ''}`}\n style={\n {\n '--aui-composer-focus': resolvedColor,\n } as CSSProperties\n }\n >\n <Thread\n strings={\n composerPlaceholder\n ? { composer: { input: { placeholder: composerPlaceholder } } }\n : undefined\n }\n components={{\n AssistantMessage: AssistantMessageWithAvatar,\n ThreadWelcome: EmptyThreadWelcome,\n UserMessage: UserMessageWithAvatar,\n }}\n assistantMessage={{\n components: {\n Text: MarkdownText,\n Empty: ThinkingMessage,\n ToolFallback,\n },\n }}\n />\n </div>\n </AvatarColorContext.Provider>\n );\n}\n"],"names":["BackstageAvatar"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ConversationSurface.esm.js","sources":["../../../src/collapsible/surface/ConversationSurface.tsx"],"sourcesContent":["// The prebuilt react-ui `<Thread>` stylesheet is vendored locally under\n// `styles/` and imported once at the top of `CollapsiblePage.tsx`. It is NOT\n// imported here: react-ui's `sideEffects: false` lets bundlers tree-shake a\n// bare CSS import from inside a lazily-loaded component, which left the Thread\n// unstyled.\nimport {\n createContext,\n useContext,\n useEffect,\n useState,\n type CSSProperties,\n} from 'react';\nimport type { ProfileInfo } from '@backstage/core-plugin-api';\nimport { identityApiRef, useApi } from '@backstage/core-plugin-api';\nimport { Avatar as BackstageAvatar } from '@backstage/core-components';\nimport { makeStyles, useTheme } from '@material-ui/core/styles';\nimport { Button, Typography } from '@material-ui/core';\nimport { BackstageLogo } from './BackstageLogo';\nimport { DEFAULT_AVATAR_COLOR, resolveAssistantColor } from './AssistantAvatar';\nimport { ThreadPrimitive } from '@assistant-ui/react';\nimport {\n AssistantActionBar,\n AssistantMessage,\n BranchPicker,\n Thread,\n ThreadWelcome,\n UserMessage,\n} from '@assistant-ui/react-ui';\nimport { MarkdownText } from './MarkdownText';\nimport {\n MessageError,\n ReasoningPart,\n ThinkingMessage,\n ToolFallback,\n} from './parts';\n\nconst DEFAULT_WELCOME_SUBTITLE =\n 'Ask me about services, APIs, teams, TechDocs, or anything in the catalog.';\n\n// The active assistant's avatar color. ConversationSurface provides it; the\n// message components (passed to <Thread> by reference, so they can't take props)\n// read it from context. Falls back to DEFAULT_AVATAR_COLOR.\nconst AvatarColorContext = createContext<string | undefined>(undefined);\n\nconst useStyles = makeStyles(theme => ({\n threadHost: {\n flex: 1,\n minHeight: 0,\n '& .aui-thread-root': {\n // Wide conversation pane to maximize room for diagrams / visual artifacts.\n // (The composer is narrowed independently via the footer max-width below.)\n '--aui-thread-max-width': '90%',\n '--aui-background':\n theme.palette.type === 'dark' ? '0 0% 18%' : '0 0% 100%',\n '--aui-foreground':\n theme.palette.type === 'dark' ? '0 0% 98%' : '240 10% 3.9%',\n '--aui-muted':\n theme.palette.type === 'dark' ? '0 0% 24%' : '240 4.8% 95.9%',\n '--aui-muted-foreground':\n theme.palette.type === 'dark' ? '0 0% 70%' : '240 3.8% 46.1%',\n '--aui-accent':\n theme.palette.type === 'dark' ? '0 0% 24%' : '240 4.8% 95.9%',\n '--aui-accent-foreground':\n theme.palette.type === 'dark' ? '0 0% 98%' : '240 5.9% 10%',\n '--aui-border':\n theme.palette.type === 'dark' ? '0 0% 40%' : '240 5.9% 90%',\n '--aui-input':\n theme.palette.type === 'dark' ? '0 0% 40%' : '240 5.9% 90%',\n '--aui-ring':\n theme.palette.type === 'dark' ? '207 90% 68%' : '210 90% 45%',\n '--aui-primary':\n theme.palette.type === 'dark' ? '0 0% 98%' : '240 5.9% 10%',\n '--aui-primary-foreground':\n theme.palette.type === 'dark' ? '240 5.9% 10%' : '0 0% 98%',\n },\n // Active composer border tinted to the agent color (set as --aui-composer-focus\n // on the host below); falls back to the theme primary if unset.\n '& .aui-composer-root:focus-within': {\n borderColor: 'var(--aui-composer-focus)',\n boxShadow: '0 0 0 1px var(--aui-composer-focus)',\n },\n '& .aui-assistant-message-content': {\n maxWidth: '100%',\n width: '100%',\n },\n // The composer is narrower than the conversation: cap the footer (which holds\n // the composer and is centered in the viewport) below the 90% thread width.\n // Bottom padding is left at the react-ui stock value (1rem) — overriding it\n // larger left a too-tall solid footer band beneath the composer.\n '& .aui-thread-viewport-footer': {\n maxWidth: '48rem',\n },\n },\n botAvatar: {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n // Transparent so the tinted logo floats (overrides react-ui's aui-avatar-root).\n backgroundColor: 'transparent',\n // Bumped to ~match the user avatar (which has an encircling disc); the\n // floating logo looked small by comparison.\n width: 32,\n height: 32,\n },\n botLogo: {\n height: '100%',\n width: 'auto',\n },\n userMessageWithAvatar: {\n display: 'flex',\n width: '100%',\n maxWidth: 'var(--aui-thread-max-width)',\n flexDirection: 'column',\n alignItems: 'flex-end',\n gap: theme.spacing(0.5),\n paddingTop: theme.spacing(1),\n paddingBottom: theme.spacing(1),\n },\n userMessageBody: {\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'flex-end',\n gap: theme.spacing(1),\n '& .aui-user-message-content': {\n maxWidth: '100%',\n },\n },\n userAvatar: {\n width: theme.spacing(5),\n height: theme.spacing(5),\n marginTop: theme.spacing(0.25),\n flexShrink: 0,\n },\n welcomeRoot: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: theme.spacing(2),\n maxWidth: '28rem',\n textAlign: 'center',\n },\n welcomeLogo: {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 56,\n height: 56,\n },\n welcomeLogoIcon: {\n width: 30,\n height: 'auto',\n },\n welcomeGreeting: {\n fontWeight: 500,\n color: theme.palette.text.primary,\n },\n welcomeSubtitle: {\n color: theme.palette.text.secondary,\n },\n suggestions: {\n display: 'flex',\n flexWrap: 'wrap',\n justifyContent: 'center',\n gap: theme.spacing(1),\n marginTop: theme.spacing(1),\n },\n suggestionButton: {\n textTransform: 'none',\n borderRadius: 999,\n },\n}));\n\n/** A circular MUI-styled bot avatar (no host asset dependency). */\nfunction AssistantBotAvatar() {\n const classes = useStyles();\n const color = useContext(AvatarColorContext) ?? DEFAULT_AVATAR_COLOR;\n\n return (\n <span\n className={`aui-avatar-root ${classes.botAvatar}`}\n style={{ color, backgroundColor: 'transparent' }}\n aria-label=\"Backstage assistant\"\n role=\"img\"\n >\n <BackstageLogo className={classes.botLogo} />\n </span>\n );\n}\n\nfunction AssistantMessageWithAvatar() {\n return (\n <AssistantMessage.Root>\n <AssistantBotAvatar />\n <AssistantMessage.Content components={{ Reasoning: ReasoningPart }} />\n <MessageError />\n <BranchPicker />\n <AssistantActionBar />\n </AssistantMessage.Root>\n );\n}\n\n/** Read the signed-in user's profile (display name, picture) once. */\nfunction useProfile() {\n const identityApi = useApi(identityApiRef);\n const [profile, setProfile] = useState<ProfileInfo>();\n\n useEffect(() => {\n let mounted = true;\n\n identityApi.getProfileInfo().then(value => {\n if (mounted) {\n setProfile(value);\n }\n });\n\n return () => {\n mounted = false;\n };\n }, [identityApi]);\n\n return profile;\n}\n\nfunction UserChatAvatar() {\n const classes = useStyles();\n const profile = useProfile();\n\n return (\n <BackstageAvatar\n classes={{ avatar: classes.userAvatar }}\n displayName={profile?.displayName ?? profile?.email ?? 'You'}\n picture={profile?.picture}\n />\n );\n}\n\nfunction UserMessageWithAvatar() {\n const classes = useStyles();\n\n return (\n <UserMessage.Root className={classes.userMessageWithAvatar}>\n <UserMessage.Attachments />\n <div className={classes.userMessageBody}>\n <UserMessage.Content />\n <UserChatAvatar />\n </div>\n </UserMessage.Root>\n );\n}\n\n/**\n * Props for {@link ConversationSurface}.\n *\n * @public\n */\nexport interface ConversationSurfaceProps {\n /** Placeholder text for the composer input (from the assistant's ui config). */\n composerPlaceholder?: string;\n /** Starter prompts shown as clickable chips on the empty thread. */\n suggestions?: Array<{ title: string; prompt: string }>;\n /** Overrides for the default empty-thread greeting. */\n welcome?: { title?: string; subtitle?: string };\n /** The active assistant's avatar tint (hex); defaults to Backstage teal. */\n assistantColor?: string;\n /** Host layout escape hatch (applied alongside the themed thread host). */\n className?: string;\n}\n\n/**\n * The react-ui `<Thread>` rendered with Implementation 1's custom message\n * components: a bot-avatar assistant message, an avatar'd user message,\n * Markdown (with streaming-safe Mermaid), a tool-call fallback, a thinking /\n * error empty-state, and a personalized empty-thread welcome with optional\n * starter-prompt chips.\n *\n * This is a \"bring your own runtime\" surface — it expects an\n * `AssistantRuntimeProvider` higher in the tree.\n *\n * @public\n */\nexport function ConversationSurface(props: ConversationSurfaceProps) {\n const { composerPlaceholder, suggestions, welcome, assistantColor, className } =\n props;\n const classes = useStyles();\n const theme = useTheme();\n // One mode-appropriate shade for every place the agent color appears here\n // (chat bot avatar via context, welcome logo, composer focus border).\n const resolvedColor = resolveAssistantColor(assistantColor, theme.palette.type);\n\n function EmptyThreadWelcome() {\n const profile = useProfile();\n const firstName = profile?.displayName?.split(' ')[0] ?? 'there';\n\n const title = welcome?.title ?? `Hi ${firstName}, welcome to Backstage`;\n const subtitle = welcome?.subtitle ?? DEFAULT_WELCOME_SUBTITLE;\n\n return (\n <ThreadWelcome.Root>\n <ThreadWelcome.Center>\n <div className={classes.welcomeRoot}>\n <span\n className={classes.welcomeLogo}\n style={{ color: resolvedColor }}\n aria-hidden=\"true\"\n >\n <BackstageLogo className={classes.welcomeLogoIcon} />\n </span>\n <Typography variant=\"h5\" className={classes.welcomeGreeting}>\n {title}\n </Typography>\n <Typography variant=\"body2\" className={classes.welcomeSubtitle}>\n {subtitle}\n </Typography>\n {suggestions && suggestions.length > 0 && (\n <div className={classes.suggestions}>\n {suggestions.map(suggestion => (\n <ThreadPrimitive.Suggestion\n key={suggestion.prompt}\n prompt={suggestion.prompt}\n send\n asChild\n >\n <Button\n variant=\"outlined\"\n size=\"small\"\n className={classes.suggestionButton}\n >\n {suggestion.title}\n </Button>\n </ThreadPrimitive.Suggestion>\n ))}\n </div>\n )}\n </div>\n </ThreadWelcome.Center>\n </ThreadWelcome.Root>\n );\n }\n\n return (\n <AvatarColorContext.Provider value={resolvedColor}>\n <div\n className={`${classes.threadHost} ${className ?? ''}`}\n style={\n {\n '--aui-composer-focus': resolvedColor,\n } as CSSProperties\n }\n >\n <Thread\n strings={\n composerPlaceholder\n ? { composer: { input: { placeholder: composerPlaceholder } } }\n : undefined\n }\n components={{\n AssistantMessage: AssistantMessageWithAvatar,\n ThreadWelcome: EmptyThreadWelcome,\n UserMessage: UserMessageWithAvatar,\n }}\n assistantMessage={{\n components: {\n Text: MarkdownText,\n Empty: ThinkingMessage,\n ToolFallback,\n },\n }}\n />\n </div>\n </AvatarColorContext.Provider>\n );\n}\n"],"names":["BackstageAvatar"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { useState } from 'react';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
3
|
import { useTheme, makeStyles } from '@material-ui/core/styles';
|
|
4
4
|
import { Collapse, Box, Typography, CircularProgress } from '@material-ui/core';
|
|
5
5
|
import CheckCircleOutlineIcon from '@material-ui/icons/CheckCircleOutline';
|
|
@@ -7,6 +7,7 @@ import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
|
|
|
7
7
|
import ExpandLessIcon from '@material-ui/icons/ExpandLess';
|
|
8
8
|
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
|
9
9
|
import HourglassEmptyIcon from '@material-ui/icons/HourglassEmpty';
|
|
10
|
+
import { useAuiState } from '@assistant-ui/react';
|
|
10
11
|
|
|
11
12
|
const useStyles = makeStyles((theme) => ({
|
|
12
13
|
thinkingMessage: {
|
|
@@ -144,6 +145,7 @@ function getToolStatus(status, theme, result) {
|
|
|
144
145
|
}
|
|
145
146
|
}
|
|
146
147
|
function ToolFallback({
|
|
148
|
+
toolCallId,
|
|
147
149
|
toolName,
|
|
148
150
|
args,
|
|
149
151
|
result,
|
|
@@ -152,6 +154,9 @@ function ToolFallback({
|
|
|
152
154
|
const classes = useStyles();
|
|
153
155
|
const theme = useTheme();
|
|
154
156
|
const [open, setOpen] = useState(false);
|
|
157
|
+
useEffect(() => {
|
|
158
|
+
setOpen(false);
|
|
159
|
+
}, [toolCallId]);
|
|
155
160
|
const { icon } = getToolStatus(status, theme, result);
|
|
156
161
|
const hasArgs = args !== void 0 && args !== null;
|
|
157
162
|
const hasResult = result !== void 0 && result !== null;
|
|
@@ -210,14 +215,37 @@ function ThinkingMessage({ status }) {
|
|
|
210
215
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", component: "span", children: "Reasoning\u2026" })
|
|
211
216
|
] });
|
|
212
217
|
}
|
|
213
|
-
if (status.type === "complete" || status.type === "incomplete") {
|
|
214
|
-
return /* @__PURE__ */ jsxs(Box, { className: classes.errorMessage, "aria-live": "polite", children: [
|
|
215
|
-
/* @__PURE__ */ jsx(ErrorOutlineIcon, { fontSize: "small" }),
|
|
216
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", component: "span", children: "Something went wrong. Please try again." })
|
|
217
|
-
] });
|
|
218
|
-
}
|
|
219
218
|
return null;
|
|
220
219
|
}
|
|
220
|
+
function errorToText(error) {
|
|
221
|
+
if (typeof error === "string") {
|
|
222
|
+
return error;
|
|
223
|
+
}
|
|
224
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
225
|
+
const message = error.message;
|
|
226
|
+
if (typeof message === "string") {
|
|
227
|
+
return message;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
return JSON.stringify(error);
|
|
232
|
+
} catch {
|
|
233
|
+
return String(error);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
function MessageError() {
|
|
237
|
+
const classes = useStyles();
|
|
238
|
+
const error = useAuiState(
|
|
239
|
+
(s) => s.message.status?.type === "incomplete" && s.message.status.reason === "error" ? errorToText(s.message.status.error ?? "An error occurred") : void 0
|
|
240
|
+
);
|
|
241
|
+
if (!error) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
return /* @__PURE__ */ jsxs(Box, { className: classes.errorMessage, role: "alert", children: [
|
|
245
|
+
/* @__PURE__ */ jsx(ErrorOutlineIcon, { fontSize: "small" }),
|
|
246
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", component: "span", children: error })
|
|
247
|
+
] });
|
|
248
|
+
}
|
|
221
249
|
function ReasoningPart({ text, status }) {
|
|
222
250
|
const classes = useStyles();
|
|
223
251
|
const [open, setOpen] = useState(false);
|
|
@@ -239,5 +267,5 @@ function ReasoningPart({ text, status }) {
|
|
|
239
267
|
] });
|
|
240
268
|
}
|
|
241
269
|
|
|
242
|
-
export { ReasoningPart, ThinkingMessage, ToolFallback, formatPayload, getToolStatus };
|
|
270
|
+
export { MessageError, ReasoningPart, ThinkingMessage, ToolFallback, formatPayload, getToolStatus };
|
|
243
271
|
//# sourceMappingURL=parts.esm.js.map
|