@neuronection/assistant-ui 0.23.0 → 0.25.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.
Files changed (160) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/README.md +9 -0
  3. package/dist/about.js +1 -1
  4. package/dist/ai-magic-fill.js +1 -1
  5. package/dist/chat-branch-tree.d.ts +45 -0
  6. package/dist/chat-branch-tree.js +3 -0
  7. package/dist/chat-branch-tree.js.map +1 -0
  8. package/dist/chat-composer.d.ts +50 -0
  9. package/dist/chat-composer.js +3 -0
  10. package/dist/chat-composer.js.map +1 -0
  11. package/dist/chat-core.d.ts +154 -0
  12. package/dist/chat-core.js +4 -0
  13. package/dist/chat-core.js.map +1 -0
  14. package/dist/chat-drawer.d.ts +32 -0
  15. package/dist/chat-drawer.js +3 -0
  16. package/dist/chat-drawer.js.map +1 -0
  17. package/dist/chat-launcher.d.ts +28 -0
  18. package/dist/chat-launcher.js +3 -0
  19. package/dist/chat-launcher.js.map +1 -0
  20. package/dist/chat-markdown.d.ts +64 -0
  21. package/dist/chat-markdown.js +3 -0
  22. package/dist/chat-markdown.js.map +1 -0
  23. package/dist/chat-message.d.ts +108 -0
  24. package/dist/chat-message.js +3 -0
  25. package/dist/chat-message.js.map +1 -0
  26. package/dist/chat-panel.d.ts +28 -0
  27. package/dist/chat-panel.js +3 -0
  28. package/dist/chat-panel.js.map +1 -0
  29. package/dist/chat-reasoning.d.ts +27 -0
  30. package/dist/chat-reasoning.js +3 -0
  31. package/dist/chat-reasoning.js.map +1 -0
  32. package/dist/chat-session-list.d.ts +51 -0
  33. package/dist/chat-session-list.js +3 -0
  34. package/dist/chat-session-list.js.map +1 -0
  35. package/dist/chat-tool-card.d.ts +43 -0
  36. package/dist/chat-tool-card.js +3 -0
  37. package/dist/chat-tool-card.js.map +1 -0
  38. package/dist/chat-transcript.d.ts +33 -0
  39. package/dist/chat-transcript.js +3 -0
  40. package/dist/chat-transcript.js.map +1 -0
  41. package/dist/chat-turn-status.d.ts +26 -0
  42. package/dist/chat-turn-status.js +3 -0
  43. package/dist/chat-turn-status.js.map +1 -0
  44. package/dist/{chunk-CZ2BL2ZL.js → chunk-3JJ2WCPN.js} +2 -2
  45. package/dist/{chunk-CZ2BL2ZL.js.map → chunk-3JJ2WCPN.js.map} +1 -1
  46. package/dist/chunk-5IOLDMDY.js +3 -0
  47. package/dist/chunk-5IOLDMDY.js.map +1 -0
  48. package/dist/{chunk-EODV6JK7.js → chunk-5QTHDB3D.js} +3 -3
  49. package/dist/{chunk-EODV6JK7.js.map → chunk-5QTHDB3D.js.map} +1 -1
  50. package/dist/chunk-6E6RRLKU.js +3 -0
  51. package/dist/chunk-6E6RRLKU.js.map +1 -0
  52. package/dist/chunk-6GNLY2EB.js +272 -0
  53. package/dist/chunk-6GNLY2EB.js.map +1 -0
  54. package/dist/chunk-743FJDRA.js +184 -0
  55. package/dist/chunk-743FJDRA.js.map +1 -0
  56. package/dist/chunk-BSIWLVDX.js +217 -0
  57. package/dist/chunk-BSIWLVDX.js.map +1 -0
  58. package/dist/chunk-BVJT67B5.js +134 -0
  59. package/dist/chunk-BVJT67B5.js.map +1 -0
  60. package/dist/chunk-DZBTJZZV.js +201 -0
  61. package/dist/chunk-DZBTJZZV.js.map +1 -0
  62. package/dist/chunk-HQIYSW2D.js +131 -0
  63. package/dist/chunk-HQIYSW2D.js.map +1 -0
  64. package/dist/chunk-LSCWBNG3.js +3 -0
  65. package/dist/chunk-LSCWBNG3.js.map +1 -0
  66. package/dist/chunk-NBT7NLNU.js +120 -0
  67. package/dist/chunk-NBT7NLNU.js.map +1 -0
  68. package/dist/chunk-NKYPNEOX.js +198 -0
  69. package/dist/chunk-NKYPNEOX.js.map +1 -0
  70. package/dist/{chunk-INMAUGBK.js → chunk-OH7AJ3WY.js} +3 -3
  71. package/dist/{chunk-INMAUGBK.js.map → chunk-OH7AJ3WY.js.map} +1 -1
  72. package/dist/chunk-P75QKU5J.js +57 -0
  73. package/dist/chunk-P75QKU5J.js.map +1 -0
  74. package/dist/chunk-PAQ6YQ7Y.js +3 -0
  75. package/dist/chunk-PAQ6YQ7Y.js.map +1 -0
  76. package/dist/chunk-QVDCFZSE.js +72 -0
  77. package/dist/chunk-QVDCFZSE.js.map +1 -0
  78. package/dist/chunk-RPLEI6LQ.js +102 -0
  79. package/dist/chunk-RPLEI6LQ.js.map +1 -0
  80. package/dist/chunk-S62VJVWB.js +36 -0
  81. package/dist/chunk-S62VJVWB.js.map +1 -0
  82. package/dist/chunk-X3C2FBMR.js +141 -0
  83. package/dist/chunk-X3C2FBMR.js.map +1 -0
  84. package/dist/{chunk-7YLR4AGA.js → chunk-XZWLTTHA.js} +2 -2
  85. package/dist/{chunk-7YLR4AGA.js.map → chunk-XZWLTTHA.js.map} +1 -1
  86. package/dist/chunk-Z4IBQ53C.js +75 -0
  87. package/dist/chunk-Z4IBQ53C.js.map +1 -0
  88. package/dist/{chunk-7KD4MG75.js → chunk-ZK2V2LPA.js} +3 -3
  89. package/dist/chunk-ZK2V2LPA.js.map +1 -0
  90. package/dist/copy-button.js +1 -1
  91. package/dist/fonts/KaTeX_AMS-Regular.ttf +0 -0
  92. package/dist/fonts/KaTeX_AMS-Regular.woff +0 -0
  93. package/dist/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  94. package/dist/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  95. package/dist/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  96. package/dist/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  97. package/dist/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  98. package/dist/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  99. package/dist/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  100. package/dist/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  101. package/dist/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  102. package/dist/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  103. package/dist/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  104. package/dist/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  105. package/dist/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  106. package/dist/fonts/KaTeX_Main-Bold.ttf +0 -0
  107. package/dist/fonts/KaTeX_Main-Bold.woff +0 -0
  108. package/dist/fonts/KaTeX_Main-Bold.woff2 +0 -0
  109. package/dist/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  110. package/dist/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  111. package/dist/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  112. package/dist/fonts/KaTeX_Main-Italic.ttf +0 -0
  113. package/dist/fonts/KaTeX_Main-Italic.woff +0 -0
  114. package/dist/fonts/KaTeX_Main-Italic.woff2 +0 -0
  115. package/dist/fonts/KaTeX_Main-Regular.ttf +0 -0
  116. package/dist/fonts/KaTeX_Main-Regular.woff +0 -0
  117. package/dist/fonts/KaTeX_Main-Regular.woff2 +0 -0
  118. package/dist/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  119. package/dist/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  120. package/dist/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  121. package/dist/fonts/KaTeX_Math-Italic.ttf +0 -0
  122. package/dist/fonts/KaTeX_Math-Italic.woff +0 -0
  123. package/dist/fonts/KaTeX_Math-Italic.woff2 +0 -0
  124. package/dist/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  125. package/dist/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  126. package/dist/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  127. package/dist/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  128. package/dist/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  129. package/dist/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  130. package/dist/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  131. package/dist/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  132. package/dist/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  133. package/dist/fonts/KaTeX_Script-Regular.ttf +0 -0
  134. package/dist/fonts/KaTeX_Script-Regular.woff +0 -0
  135. package/dist/fonts/KaTeX_Script-Regular.woff2 +0 -0
  136. package/dist/fonts/KaTeX_Size1-Regular.ttf +0 -0
  137. package/dist/fonts/KaTeX_Size1-Regular.woff +0 -0
  138. package/dist/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  139. package/dist/fonts/KaTeX_Size2-Regular.ttf +0 -0
  140. package/dist/fonts/KaTeX_Size2-Regular.woff +0 -0
  141. package/dist/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  142. package/dist/fonts/KaTeX_Size3-Regular.ttf +0 -0
  143. package/dist/fonts/KaTeX_Size3-Regular.woff +0 -0
  144. package/dist/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  145. package/dist/fonts/KaTeX_Size4-Regular.ttf +0 -0
  146. package/dist/fonts/KaTeX_Size4-Regular.woff +0 -0
  147. package/dist/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  148. package/dist/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  149. package/dist/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  150. package/dist/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  151. package/dist/index.d.ts +16 -0
  152. package/dist/index.js +37 -23
  153. package/dist/index.js.map +1 -1
  154. package/dist/portal.js +1 -1
  155. package/dist/settings-shell.js +1 -1
  156. package/dist/styles.css +1 -1
  157. package/dist/tree-YaIz73vo.d.ts +54 -0
  158. package/dist/types-DZwzmyKE.d.ts +44 -0
  159. package/package.json +60 -2
  160. package/dist/chunk-7KD4MG75.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/chat-markdown/MarkdownCodeBlock.tsx","../src/components/chat-markdown/MermaidDiagram.tsx","../src/components/chat-markdown/MarkdownSurface.tsx"],"names":["React","MarkdownCodeBlock","React2","MermaidDiagram","jsx","MarkdownSurface"],"mappings":"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","file":"chunk-DZBTJZZV.js","sourcesContent":["import * as React from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { CopyButton } from '../copy-button/CopyButton'\n\nexport interface MarkdownCodeBlockLabels {\n copy: string\n code: string\n}\n\nexport interface MarkdownCodeBlockProps {\n code: string\n language?: string\n showLanguage?: boolean\n labels?: Partial<MarkdownCodeBlockLabels>\n className?: string\n}\n\n/**\n * Standalone fenced-code surface: mono block, optional language tag, hover\n * copy. Plain by design — no highlighting engine bundled (apps may wrap or\n * slot their own renderer through `MarkdownSurface.components`).\n */\nexport const MarkdownCodeBlock = React.forwardRef<HTMLDivElement, MarkdownCodeBlockProps>(\n function MarkdownCodeBlock({ code, language, showLanguage = true, labels, className }, ref) {\n const copyLabel = labels?.copy ?? 'Copy code'\n const codeLabel = labels?.code ?? 'Code'\n return (\n <div\n ref={ref}\n data-as=\"markdown-code-block\"\n className={cn(\n 'group/code relative my-3 overflow-hidden rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)]',\n className,\n )}\n >\n {showLanguage && language ? (\n <div className=\"flex items-center justify-between border-b border-[var(--as-border)] px-3 py-1 font-sans text-[10px] font-medium uppercase tracking-wide text-[var(--as-muted-fg)]\">\n <span>{language}</span>\n <CopyButton value={code} label={copyLabel} className=\"opacity-60 transition-opacity group-hover/code:opacity-100\" />\n </div>\n ) : (\n <CopyButton\n value={code}\n label={copyLabel}\n className=\"absolute right-2 top-2 opacity-0 transition-opacity focus-visible:opacity-100 group-hover/code:opacity-100\"\n />\n )}\n <pre className={cn('overflow-x-auto p-3 font-mono text-xs leading-relaxed', !showLanguage && 'pt-3')}>\n <code aria-label={language ? `${language} ${codeLabel}` : codeLabel}>{code}</code>\n </pre>\n </div>\n )\n },\n)\n","import * as React from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { MarkdownCodeBlock } from './MarkdownCodeBlock'\n\nexport interface MermaidDiagramProps {\n code: string\n theme?: 'neutral' | 'default' | 'dark' | 'forest'\n labels?: { diagram?: string }\n className?: string\n}\n\nlet mermaidInitialized = false\n\nasync function renderMermaid(id: string, code: string, theme: NonNullable<MermaidDiagramProps['theme']>): Promise<string> {\n const mermaid = (await import('mermaid')).default\n if (!mermaidInitialized) {\n mermaid.initialize({ startOnLoad: false, securityLevel: 'strict', theme })\n mermaidInitialized = true\n }\n const { svg } = await mermaid.render(id, code)\n return svg\n}\n\nexport function extractText(node: React.ReactNode): string {\n if (node === null || node === undefined || typeof node === 'boolean') {\n return ''\n }\n if (typeof node === 'string' || typeof node === 'number') {\n return String(node)\n }\n if (Array.isArray(node)) {\n return node.map(extractText).join('')\n }\n if (React.isValidElement(node)) {\n return extractText((node.props as { children?: React.ReactNode }).children)\n }\n return ''\n}\n\n/**\n * Lazily-rendered mermaid diagram (dynamic `import('mermaid')`, strict\n * security). Falls back to the plain code block when rendering fails —\n * study-assistant's proven behavior.\n */\nexport const MermaidDiagram = React.forwardRef<HTMLDivElement, MermaidDiagramProps>(\n function MermaidDiagram({ code, theme = 'neutral', labels, className }, ref) {\n const reactId = React.useId().replace(/[^a-zA-Z0-9]/g, '')\n const [svg, setSvg] = React.useState<string | null>(null)\n const [failed, setFailed] = React.useState(false)\n\n React.useEffect(() => {\n let cancelled = false\n setFailed(false)\n setSvg(null)\n renderMermaid(`as-mermaid-${reactId}`, code, theme)\n .then((result) => {\n if (!cancelled) {\n setSvg(result)\n }\n })\n .catch(() => {\n if (!cancelled) {\n setFailed(true)\n }\n })\n return () => {\n cancelled = true\n }\n }, [code, theme, reactId])\n\n if (failed || svg === null) {\n return (\n <MarkdownCodeBlock\n ref={failed ? ref : undefined}\n code={code}\n language=\"mermaid\"\n labels={{ code: labels?.diagram ?? 'Diagram' }}\n className={cn('my-3', svg === null && !failed ? 'opacity-60' : undefined, className)}\n />\n )\n }\n return (\n <div\n ref={ref}\n data-as=\"mermaid-diagram\"\n className={cn(\n 'my-3 flex justify-center overflow-x-auto rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] p-3 [&_svg]:max-w-full',\n className,\n )}\n // mermaid runs with securityLevel 'strict' — no user styles, scripts or links survive\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n )\n },\n)\n","import * as React from 'react'\nimport { defaultUrlTransform, type Components, type Options as ReactMarkdownOptions, type UrlTransform } from 'react-markdown'\nimport ReactMarkdown from 'react-markdown'\nimport rehypeKatex from 'rehype-katex'\nimport remarkGfm from 'remark-gfm'\nimport remarkMath from 'remark-math'\n\nimport { cn } from '../../lib/utils'\nimport { MarkdownCodeBlock, type MarkdownCodeBlockLabels } from './MarkdownCodeBlock'\nimport { extractText, MermaidDiagram } from './MermaidDiagram'\n\nexport type MarkdownComponents = Components\nexport type { MarkdownCodeBlockLabels }\n\nexport interface MarkdownSurfaceProps {\n /** Markdown source (model output is untrusted — raw HTML never renders). */\n value: string\n /** Live turn: defers mermaid to the final render (streaming floods break diagrams). */\n streaming?: boolean\n gfm?: boolean\n math?: boolean\n /** Render ```mermaid fences as diagrams (forced off while `streaming`). */\n mermaid?: boolean\n mermaidTheme?: 'neutral' | 'default' | 'dark' | 'forest'\n /** Per-key overrides of the default renderers (mentions, citations, links…). */\n components?: MarkdownComponents\n urlTransform?: UrlTransform\n showCodeLanguage?: boolean\n labels?: Partial<MarkdownCodeBlockLabels>\n className?: string\n}\n\nconst fenceLanguage = (className: string | undefined): string | undefined =>\n /language-([\\w+-]+)/.exec(className ?? '')?.[1]\n\n/**\n * The family's read-only streaming markdown surface: GFM tables, KaTeX math\n * (error-tolerant while streaming), lazily-imported mermaid diagrams, and\n * copyable code blocks with language tags. Raw HTML is never rendered\n * (no `rehype-raw`) — model output is untrusted input (ai-features §7).\n */\nexport const MarkdownSurface = React.memo(\n React.forwardRef<HTMLDivElement, MarkdownSurfaceProps>(function MarkdownSurface(\n {\n value,\n streaming = false,\n gfm = true,\n math = true,\n mermaid = true,\n mermaidTheme = 'neutral',\n components,\n urlTransform = defaultUrlTransform,\n showCodeLanguage = true,\n labels,\n className,\n },\n ref,\n ) {\n const mermaidEnabled = mermaid && !streaming\n\n const defaultComponents = React.useMemo<MarkdownComponents>(\n () => ({\n pre: ({ children }) => {\n const child = Array.isArray(children) ? children[0] : children\n if (React.isValidElement(child)) {\n const childProps = child.props as { className?: string; children?: React.ReactNode }\n const text = extractText(childProps.children).replace(/\\n$/, '')\n const language = fenceLanguage(childProps.className)\n if (language === 'mermaid' && mermaidEnabled) {\n return <MermaidDiagram code={text} theme={mermaidTheme} labels={{ diagram: labels?.code }} />\n }\n return (\n <MarkdownCodeBlock code={text} language={language} showLanguage={showCodeLanguage} labels={labels} />\n )\n }\n return <pre>{children}</pre>\n },\n code: ({ className: codeClassName, children, ...rest }) => (\n <code\n className={cn(\n 'rounded-[var(--as-radius-sm)] bg-[var(--as-surface-raised)] px-1 py-0.5 font-mono text-[0.85em]',\n codeClassName,\n )}\n {...rest}\n >\n {children}\n </code>\n ),\n a: ({ href, children, ...rest }) => {\n const external =\n typeof href === 'string' && (href.startsWith('http://') || href.startsWith('https://'))\n return (\n <a\n href={href}\n className=\"text-[var(--as-primary)] underline underline-offset-2\"\n {...(external ? { target: '_blank', rel: 'noopener noreferrer' } : {})}\n {...rest}\n >\n {children}\n </a>\n )\n },\n table: ({ children, ...rest }) => (\n <div className=\"my-3 overflow-x-auto rounded-[var(--as-radius)] border border-[var(--as-border)]\">\n <table className=\"w-full border-collapse text-[0.875em]\" {...rest}>\n {children}\n </table>\n </div>\n ),\n img: ({ alt, ...rest }) => (\n <img alt={alt ?? ''} className=\"my-2 max-w-full rounded-[var(--as-radius)]\" loading=\"lazy\" {...rest} />\n ),\n }),\n [labels, mermaidEnabled, mermaidTheme, showCodeLanguage],\n )\n\n const mergedComponents = React.useMemo(\n () => ({ ...defaultComponents, ...components }),\n [defaultComponents, components],\n )\n\n const remarkPlugins = React.useMemo(\n () => [gfm ? remarkGfm : null, math ? remarkMath : null].filter((plugin) => plugin !== null),\n [gfm, math],\n )\n const rehypePlugins = React.useMemo<ReactMarkdownOptions['rehypePlugins']>(\n () =>\n math\n ? [[rehypeKatex, { strict: false, throwOnError: false, output: 'html' }]]\n : [],\n [math],\n )\n\n return (\n <div ref={ref} data-as=\"chat-markdown\" className={cn('min-w-0 text-[var(--as-fg)]', className)}>\n <ReactMarkdown\n remarkPlugins={remarkPlugins}\n rehypePlugins={rehypePlugins}\n components={mergedComponents}\n urlTransform={urlTransform}\n >\n {value}\n </ReactMarkdown>\n </div>\n )\n }),\n)\n\nexport { MarkdownCodeBlock }\n"]}
@@ -0,0 +1,131 @@
1
+ import { activePathSet } from './chunk-Z4IBQ53C.js';
2
+ import { cn } from './chunk-BLJWR4ZV.js';
3
+ import * as React from 'react';
4
+ import { MessageSquare, Sparkles, GitFork } from 'lucide-react';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
7
+ function excerptOf(excerpt, max) {
8
+ if (excerpt === void 0) {
9
+ return "";
10
+ }
11
+ const clean = excerpt.replace(/\s+/g, " ").trim();
12
+ return clean.length > max ? `${clean.slice(0, max - 1)}\u2026` : clean;
13
+ }
14
+ var ChatBranchTree = React.forwardRef(
15
+ function ChatBranchTree2({ tree, activeIds, onSelect, maxExcerpt = 100, icons, labels, className }, ref) {
16
+ const active = React.useMemo(() => activeIds ?? activePathSet(tree), [activeIds, tree]);
17
+ const UserIcon = icons?.user ?? MessageSquare;
18
+ const AssistantIcon = icons?.assistant ?? Sparkles;
19
+ const ForkIcon = icons?.fork ?? GitFork;
20
+ const rootIds = React.useMemo(
21
+ () => Object.values(tree.nodes).filter((node) => node.parentId === null).map((node) => node.id),
22
+ [tree]
23
+ );
24
+ const nodeIds = React.useMemo(() => Object.keys(tree.nodes), [tree]);
25
+ const [tabStopId, setTabStopId] = React.useState(null);
26
+ const effectiveTabStop = tabStopId !== null && nodeIds.includes(tabStopId) ? tabStopId : nodeIds[0];
27
+ const focusNode = (id) => {
28
+ setTabStopId(id);
29
+ document.querySelector(`[data-tree-node="${id}"]`)?.focus();
30
+ };
31
+ const onKeyDown = (event, id) => {
32
+ const index = nodeIds.indexOf(id);
33
+ if (event.key === "ArrowDown" && index < nodeIds.length - 1) {
34
+ event.preventDefault();
35
+ focusNode(nodeIds[index + 1]);
36
+ } else if (event.key === "ArrowUp" && index > 0) {
37
+ event.preventDefault();
38
+ focusNode(nodeIds[index - 1]);
39
+ } else if (event.key === "Home" && nodeIds.length > 0) {
40
+ event.preventDefault();
41
+ focusNode(nodeIds[0]);
42
+ } else if (event.key === "End" && nodeIds.length > 0) {
43
+ event.preventDefault();
44
+ focusNode(nodeIds[nodeIds.length - 1]);
45
+ } else if (event.key === "Enter" || event.key === " ") {
46
+ event.preventDefault();
47
+ onSelect?.(id);
48
+ }
49
+ };
50
+ const renderNode = (id, depth) => {
51
+ const node = tree.nodes[id];
52
+ if (node === void 0) {
53
+ return null;
54
+ }
55
+ const onPath = active.has(id);
56
+ const RoleIcon = node.role === "user" ? UserIcon : AssistantIcon;
57
+ const childCount = node.childIds.length;
58
+ return /* @__PURE__ */ jsxs("div", { role: "none", children: [
59
+ /* @__PURE__ */ jsxs(
60
+ "div",
61
+ {
62
+ role: "treeitem",
63
+ "aria-selected": onPath,
64
+ "aria-level": depth + 1,
65
+ tabIndex: id === effectiveTabStop ? 0 : -1,
66
+ "data-tree-node": id,
67
+ "data-on-path": onPath,
68
+ onKeyDown: (event) => onKeyDown(event, id),
69
+ onClick: () => onSelect?.(id),
70
+ className: cn(
71
+ "flex min-h-7 cursor-pointer select-none items-center gap-2 rounded-[var(--as-radius-sm)] px-1.5 py-1 text-xs transition-colors hover:bg-[var(--as-surface-raised)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
72
+ onPath ? "text-[var(--as-fg)]" : "text-[var(--as-muted-fg)]"
73
+ ),
74
+ style: { paddingInlineStart: depth * 14 + 6 },
75
+ children: [
76
+ /* @__PURE__ */ jsx(
77
+ "span",
78
+ {
79
+ "aria-hidden": true,
80
+ className: cn(
81
+ "size-2 shrink-0 rounded-full border",
82
+ onPath ? "border-[var(--as-primary)] bg-[var(--as-primary)]" : "border-[var(--as-border)] bg-transparent"
83
+ )
84
+ }
85
+ ),
86
+ /* @__PURE__ */ jsx(RoleIcon, { className: "size-3.5 shrink-0", "aria-hidden": true }),
87
+ /* @__PURE__ */ jsx("span", { className: cn("min-w-0 flex-1 truncate", onPath && "font-medium"), children: excerptOf(node.excerpt, maxExcerpt) }),
88
+ childCount > 1 ? /* @__PURE__ */ jsxs(
89
+ "span",
90
+ {
91
+ className: "flex shrink-0 items-center gap-0.5 rounded-full bg-[var(--as-surface-raised)] px-1.5 py-0.5 text-[10px] text-[var(--as-muted-fg)]",
92
+ title: labels?.forked?.(childCount) ?? `${childCount} variants`,
93
+ children: [
94
+ /* @__PURE__ */ jsx(ForkIcon, { className: "size-3", "aria-hidden": true }),
95
+ childCount
96
+ ]
97
+ }
98
+ ) : null
99
+ ]
100
+ }
101
+ ),
102
+ childCount > 0 ? /* @__PURE__ */ jsxs("div", { role: "group", className: "relative", children: [
103
+ /* @__PURE__ */ jsx(
104
+ "span",
105
+ {
106
+ "aria-hidden": true,
107
+ className: "absolute top-0 bottom-0 w-px bg-[var(--as-border)]",
108
+ style: { insetInlineStart: depth * 14 + 12 }
109
+ }
110
+ ),
111
+ node.childIds.map((childId) => renderNode(childId, depth + 1))
112
+ ] }) : null
113
+ ] }, id);
114
+ };
115
+ return /* @__PURE__ */ jsx(
116
+ "div",
117
+ {
118
+ ref,
119
+ role: "tree",
120
+ "aria-label": labels?.tree ?? "Conversation branches",
121
+ "data-as": "chat-branch-tree",
122
+ className: cn("flex max-h-96 flex-col overflow-y-auto p-1 text-xs", className),
123
+ children: rootIds.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-2 py-3 text-[var(--as-muted-fg)]", children: labels?.tree ?? "No messages yet" }) : rootIds.map((id) => renderNode(id, 0))
124
+ }
125
+ );
126
+ }
127
+ );
128
+
129
+ export { ChatBranchTree };
130
+ //# sourceMappingURL=chunk-HQIYSW2D.js.map
131
+ //# sourceMappingURL=chunk-HQIYSW2D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/chat-branch-tree/ChatBranchTree.tsx"],"names":["ChatBranchTree"],"mappings":"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","file":"chunk-HQIYSW2D.js","sourcesContent":["import * as React from 'react'\nimport { GitFork, MessageSquare, Sparkles } from 'lucide-react'\nimport type { LucideIcon } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\nimport { activePathSet, type BranchTree } from '../chat-core/tree'\n\nexport interface ChatBranchTreeIcons {\n user: LucideIcon\n assistant: LucideIcon\n fork: LucideIcon\n}\n\nexport interface ChatBranchTreeLabels {\n tree: string\n user: string\n assistant: string\n forked: (count: number) => string\n}\n\nexport interface ChatBranchTreeNode {\n id: string\n role: 'user' | 'assistant' | 'system'\n excerpt?: string\n parentId: string | null\n activeChildId: string | null\n childIds: string[]\n}\n\nexport interface ChatBranchTreeProps {\n /** From `buildBranchTree` / `linearTree` (chat-core). */\n tree: BranchTree\n /** Override the pointer-walk active set (e.g. while a select is pending). */\n activeIds?: Set<string>\n /** Click = flip one pointer (family `select` endpoint, level-flip semantics). */\n onSelect?: (nodeId: string) => void\n maxExcerpt?: number\n icons?: Partial<ChatBranchTreeIcons>\n labels?: Partial<ChatBranchTreeLabels>\n className?: string\n}\n\nfunction excerptOf(excerpt: string | undefined, max: number): string {\n if (excerpt === undefined) {\n return ''\n }\n const clean = excerpt.replace(/\\s+/g, ' ').trim()\n return clean.length > max ? `${clean.slice(0, max - 1)}…` : clean\n}\n\n/**\n * The OpenWebUI-style conversation tree rail (study's `BranchTreePanel`,\n * family branching contract): recursive commit-graph rows — filled dots on\n * the active path, hollow dots for hidden variants, fork badges, excerpts.\n * `role=\"tree\"` with roving-tabindex keyboard navigation.\n */\nexport const ChatBranchTree = React.forwardRef<HTMLDivElement, ChatBranchTreeProps>(\n function ChatBranchTree({ tree, activeIds, onSelect, maxExcerpt = 100, icons, labels, className }, ref) {\n const active = React.useMemo(() => activeIds ?? activePathSet(tree), [activeIds, tree])\n const UserIcon = icons?.user ?? MessageSquare\n const AssistantIcon = icons?.assistant ?? Sparkles\n const ForkIcon = icons?.fork ?? GitFork\n const rootIds = React.useMemo(\n () => Object.values(tree.nodes).filter((node) => node.parentId === null).map((node) => node.id),\n [tree],\n )\n const nodeIds = React.useMemo(() => Object.keys(tree.nodes), [tree])\n const [tabStopId, setTabStopId] = React.useState<string | null>(null)\n const effectiveTabStop = tabStopId !== null && nodeIds.includes(tabStopId) ? tabStopId : nodeIds[0]\n\n const focusNode = (id: string) => {\n setTabStopId(id)\n document.querySelector<HTMLElement>(`[data-tree-node=\"${id}\"]`)?.focus()\n }\n\n const onKeyDown = (event: React.KeyboardEvent, id: string) => {\n const index = nodeIds.indexOf(id)\n if (event.key === 'ArrowDown' && index < nodeIds.length - 1) {\n event.preventDefault()\n focusNode(nodeIds[index + 1]!)\n } else if (event.key === 'ArrowUp' && index > 0) {\n event.preventDefault()\n focusNode(nodeIds[index - 1]!)\n } else if (event.key === 'Home' && nodeIds.length > 0) {\n event.preventDefault()\n focusNode(nodeIds[0]!)\n } else if (event.key === 'End' && nodeIds.length > 0) {\n event.preventDefault()\n focusNode(nodeIds[nodeIds.length - 1]!)\n } else if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onSelect?.(id)\n }\n }\n\n const renderNode = (id: string, depth: number): React.ReactNode => {\n const node = tree.nodes[id]\n if (node === undefined) {\n return null\n }\n const onPath = active.has(id)\n const RoleIcon = node.role === 'user' ? UserIcon : AssistantIcon\n const childCount = node.childIds.length\n return (\n <div key={id} role=\"none\">\n <div\n role=\"treeitem\"\n aria-selected={onPath}\n aria-level={depth + 1}\n tabIndex={id === effectiveTabStop ? 0 : -1}\n data-tree-node={id}\n data-on-path={onPath}\n onKeyDown={(event) => onKeyDown(event, id)}\n onClick={() => onSelect?.(id)}\n className={cn(\n 'flex min-h-7 cursor-pointer select-none items-center gap-2 rounded-[var(--as-radius-sm)] px-1.5 py-1 text-xs transition-colors hover:bg-[var(--as-surface-raised)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]',\n onPath ? 'text-[var(--as-fg)]' : 'text-[var(--as-muted-fg)]',\n )}\n style={{ paddingInlineStart: depth * 14 + 6 }}\n >\n <span\n aria-hidden\n className={cn(\n 'size-2 shrink-0 rounded-full border',\n onPath\n ? 'border-[var(--as-primary)] bg-[var(--as-primary)]'\n : 'border-[var(--as-border)] bg-transparent',\n )}\n />\n <RoleIcon className=\"size-3.5 shrink-0\" aria-hidden />\n <span className={cn('min-w-0 flex-1 truncate', onPath && 'font-medium')}>\n {excerptOf(node.excerpt, maxExcerpt)}\n </span>\n {childCount > 1 ? (\n <span\n className=\"flex shrink-0 items-center gap-0.5 rounded-full bg-[var(--as-surface-raised)] px-1.5 py-0.5 text-[10px] text-[var(--as-muted-fg)]\"\n title={labels?.forked?.(childCount) ?? `${childCount} variants`}\n >\n <ForkIcon className=\"size-3\" aria-hidden />\n {childCount}\n </span>\n ) : null}\n </div>\n {childCount > 0 ? (\n <div role=\"group\" className=\"relative\">\n <span\n aria-hidden\n className=\"absolute top-0 bottom-0 w-px bg-[var(--as-border)]\"\n style={{ insetInlineStart: depth * 14 + 12 }}\n />\n {node.childIds.map((childId) => renderNode(childId, depth + 1))}\n </div>\n ) : null}\n </div>\n )\n }\n\n return (\n <div\n ref={ref}\n role=\"tree\"\n aria-label={labels?.tree ?? 'Conversation branches'}\n data-as=\"chat-branch-tree\"\n className={cn('flex max-h-96 flex-col overflow-y-auto p-1 text-xs', className)}\n >\n {rootIds.length === 0 ? (\n <p className=\"px-2 py-3 text-[var(--as-muted-fg)]\">{labels?.tree ?? 'No messages yet'}</p>\n ) : (\n rootIds.map((id) => renderNode(id, 0))\n )}\n </div>\n )\n },\n)\n"]}
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-LSCWBNG3.js.map
3
+ //# sourceMappingURL=chunk-LSCWBNG3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-LSCWBNG3.js"}
@@ -0,0 +1,120 @@
1
+ import { Spinner } from './chunk-INTST5VG.js';
2
+ import { cn } from './chunk-BLJWR4ZV.js';
3
+ import * as React from 'react';
4
+ import { Wrench, Check, TriangleAlert, ChevronDown } from 'lucide-react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function formatDuration(ms) {
8
+ if (ms < 1e3) {
9
+ return `${Math.round(ms)} ms`;
10
+ }
11
+ return `${(ms / 1e3).toFixed(1)} s`;
12
+ }
13
+ var ChatToolCard = React.forwardRef(
14
+ function ChatToolCard2({
15
+ name,
16
+ title,
17
+ status,
18
+ args,
19
+ result,
20
+ renderResult,
21
+ durationMs,
22
+ open: openProp,
23
+ defaultOpen = false,
24
+ onOpenChange,
25
+ labels,
26
+ icon: Icon = Wrench,
27
+ className
28
+ }, ref) {
29
+ const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);
30
+ const isControlled = openProp !== void 0;
31
+ const open = isControlled ? openProp : uncontrolledOpen;
32
+ const regionId = React.useId();
33
+ const expandable = Boolean(args || result || renderResult);
34
+ const toggle = () => {
35
+ if (!expandable) {
36
+ return;
37
+ }
38
+ const next = !open;
39
+ if (!isControlled) {
40
+ setUncontrolledOpen(next);
41
+ }
42
+ onOpenChange?.(next);
43
+ };
44
+ const onKeyDown = (event) => {
45
+ if (event.key === "Enter" || event.key === " ") {
46
+ event.preventDefault();
47
+ toggle();
48
+ }
49
+ };
50
+ const statusLabel = status === "running" ? labels?.running ?? "Running" : status === "done" ? labels?.done ?? "Done" : labels?.failed ?? "Failed";
51
+ const Header = expandable ? "button" : "div";
52
+ const headerProps = expandable ? {
53
+ type: "button",
54
+ "aria-expanded": open,
55
+ "aria-controls": regionId,
56
+ onClick: toggle,
57
+ onKeyDown
58
+ } : {};
59
+ return /* @__PURE__ */ jsxs(
60
+ "div",
61
+ {
62
+ ref,
63
+ "data-as": "chat-tool-card",
64
+ "data-status": status,
65
+ className: cn(
66
+ "rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] text-xs",
67
+ className
68
+ ),
69
+ children: [
70
+ /* @__PURE__ */ jsxs(
71
+ Header,
72
+ {
73
+ ...headerProps,
74
+ className: "flex w-full items-center gap-2 px-2.5 py-1.5 text-left focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]",
75
+ children: [
76
+ /* @__PURE__ */ jsx(Icon, { className: "size-3.5 shrink-0 text-[var(--as-muted-fg)]", "aria-hidden": true }),
77
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
78
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-[var(--as-fg)]", children: title ?? name }),
79
+ title ? /* @__PURE__ */ jsx("span", { className: "ml-1.5 font-mono text-[var(--as-muted-fg)]", children: name }) : null
80
+ ] }),
81
+ durationMs !== void 0 ? /* @__PURE__ */ jsx("span", { className: "shrink-0 tabular-nums text-[var(--as-muted-fg)]", children: formatDuration(durationMs) }) : null,
82
+ /* @__PURE__ */ jsxs(
83
+ "span",
84
+ {
85
+ role: status === "running" ? "status" : void 0,
86
+ className: cn(
87
+ "flex shrink-0 items-center gap-1",
88
+ status === "done" && "text-[var(--as-success)]",
89
+ status === "failed" && "text-[var(--as-danger)]",
90
+ status === "running" && "text-[var(--as-muted-fg)]"
91
+ ),
92
+ children: [
93
+ status === "running" ? /* @__PURE__ */ jsx(Spinner, { size: "sm" }) : status === "done" ? /* @__PURE__ */ jsx(Check, { className: "size-3.5", "aria-hidden": true }) : /* @__PURE__ */ jsx(TriangleAlert, { className: "size-3.5", "aria-hidden": true }),
94
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: statusLabel })
95
+ ]
96
+ }
97
+ ),
98
+ expandable ? /* @__PURE__ */ jsx(ChevronDown, { className: cn("size-3.5 shrink-0 text-[var(--as-muted-fg)] transition-transform", open && "rotate-180"), "aria-hidden": true }) : null
99
+ ]
100
+ }
101
+ ),
102
+ expandable && open ? /* @__PURE__ */ jsxs("div", { id: regionId, className: "flex flex-col gap-2 border-t border-[var(--as-border)] px-2.5 py-2", children: [
103
+ args ? /* @__PURE__ */ jsxs("div", { children: [
104
+ /* @__PURE__ */ jsx("p", { className: "mb-1 font-medium uppercase tracking-wide text-[var(--as-muted-fg)]", children: labels?.args ?? "Arguments" }),
105
+ /* @__PURE__ */ jsx("pre", { className: "max-h-40 overflow-auto whitespace-pre-wrap break-words rounded-[var(--as-radius-sm)] bg-[var(--as-surface-raised)] p-2 font-mono text-[11px] leading-relaxed", children: args })
106
+ ] }) : null,
107
+ result || renderResult ? /* @__PURE__ */ jsxs("div", { children: [
108
+ /* @__PURE__ */ jsx("p", { className: "mb-1 font-medium uppercase tracking-wide text-[var(--as-muted-fg)]", children: labels?.result ?? "Result" }),
109
+ renderResult ? renderResult(result ?? "") : /* @__PURE__ */ jsx("pre", { className: "max-h-40 overflow-auto whitespace-pre-wrap break-words rounded-[var(--as-radius-sm)] bg-[var(--as-surface-raised)] p-2 font-mono text-[11px] leading-relaxed", children: result })
110
+ ] }) : null
111
+ ] }) : null
112
+ ]
113
+ }
114
+ );
115
+ }
116
+ );
117
+
118
+ export { ChatToolCard };
119
+ //# sourceMappingURL=chunk-NBT7NLNU.js.map
120
+ //# sourceMappingURL=chunk-NBT7NLNU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/chat-tool-card/ChatToolCard.tsx"],"names":["ChatToolCard"],"mappings":"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","file":"chunk-NBT7NLNU.js","sourcesContent":["import * as React from 'react'\nimport { Check, ChevronDown, TriangleAlert, Wrench } from 'lucide-react'\nimport type { LucideIcon } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\nimport { Spinner } from '../spinner/Spinner'\n\nexport interface ChatToolCardLabels {\n running: string\n done: string\n failed: string\n args: string\n result: string\n details: string\n}\n\nexport interface ChatToolCardProps {\n name: string\n /** Human title, e.g. \"Searching the job catalog\". */\n title?: string\n status: 'running' | 'done' | 'failed'\n /** Serialized arguments (JSON string or formatted text). */\n args?: string\n /** Serialized result. */\n result?: string\n /**\n * Custom result view (study's per-tool views, family plan 12 L2).\n * Called with the result string (possibly empty when the tool has no\n * serialized output); when absent the default `<pre>` pane renders.\n */\n renderResult?: (result: string) => React.ReactNode\n durationMs?: number\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n labels?: Partial<ChatToolCardLabels>\n icon?: LucideIcon\n className?: string\n}\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${Math.round(ms)} ms`\n }\n return `${(ms / 1000).toFixed(1)} s`\n}\n\n/**\n * Inline tool-call observation card (study's `ToolCallCard` + health's tool\n * chips, generalized): status, duration, expandable args/result. The\n * inspector stays app-side (health opens its own modal from `onOpenChange`\n * or wrapping markup).\n */\nexport const ChatToolCard = React.forwardRef<HTMLDivElement, ChatToolCardProps>(\n function ChatToolCard(\n {\n name,\n title,\n status,\n args,\n result,\n renderResult,\n durationMs,\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n labels,\n icon: Icon = Wrench,\n className,\n },\n ref,\n ) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n const isControlled = openProp !== undefined\n const open = isControlled ? openProp : uncontrolledOpen\n const regionId = React.useId()\n const expandable = Boolean(args || result || renderResult)\n\n const toggle = () => {\n if (!expandable) {\n return\n }\n const next = !open\n if (!isControlled) {\n setUncontrolledOpen(next)\n }\n onOpenChange?.(next)\n }\n\n const onKeyDown: React.KeyboardEventHandler<HTMLButtonElement> = (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n toggle()\n }\n }\n\n const statusLabel =\n status === 'running' ? (labels?.running ?? 'Running') : status === 'done' ? (labels?.done ?? 'Done') : (labels?.failed ?? 'Failed')\n\n const Header = (expandable ? 'button' : 'div') as 'button'\n const headerProps: React.ComponentPropsWithoutRef<'button'> = expandable\n ? {\n type: 'button',\n 'aria-expanded': open,\n 'aria-controls': regionId,\n onClick: toggle,\n onKeyDown,\n }\n : {}\n\n return (\n <div\n ref={ref}\n data-as=\"chat-tool-card\"\n data-status={status}\n className={cn(\n 'rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] text-xs',\n className,\n )}\n >\n <Header\n {...headerProps}\n className=\"flex w-full items-center gap-2 px-2.5 py-1.5 text-left focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <Icon className=\"size-3.5 shrink-0 text-[var(--as-muted-fg)]\" aria-hidden />\n <span className=\"min-w-0 flex-1\">\n <span className=\"font-medium text-[var(--as-fg)]\">{title ?? name}</span>\n {title ? <span className=\"ml-1.5 font-mono text-[var(--as-muted-fg)]\">{name}</span> : null}\n </span>\n {durationMs !== undefined ? (\n <span className=\"shrink-0 tabular-nums text-[var(--as-muted-fg)]\">{formatDuration(durationMs)}</span>\n ) : null}\n <span\n role={status === 'running' ? 'status' : undefined}\n className={cn(\n 'flex shrink-0 items-center gap-1',\n status === 'done' && 'text-[var(--as-success)]',\n status === 'failed' && 'text-[var(--as-danger)]',\n status === 'running' && 'text-[var(--as-muted-fg)]',\n )}\n >\n {status === 'running' ? (\n <Spinner size=\"sm\" />\n ) : status === 'done' ? (\n <Check className=\"size-3.5\" aria-hidden />\n ) : (\n <TriangleAlert className=\"size-3.5\" aria-hidden />\n )}\n <span className=\"sr-only\">{statusLabel}</span>\n </span>\n {expandable ? (\n <ChevronDown className={cn('size-3.5 shrink-0 text-[var(--as-muted-fg)] transition-transform', open && 'rotate-180')} aria-hidden />\n ) : null}\n </Header>\n {expandable && open ? (\n <div id={regionId} className=\"flex flex-col gap-2 border-t border-[var(--as-border)] px-2.5 py-2\">\n {args ? (\n <div>\n <p className=\"mb-1 font-medium uppercase tracking-wide text-[var(--as-muted-fg)]\">{labels?.args ?? 'Arguments'}</p>\n <pre className=\"max-h-40 overflow-auto whitespace-pre-wrap break-words rounded-[var(--as-radius-sm)] bg-[var(--as-surface-raised)] p-2 font-mono text-[11px] leading-relaxed\">\n {args}\n </pre>\n </div>\n ) : null}\n {result || renderResult ? (\n <div>\n <p className=\"mb-1 font-medium uppercase tracking-wide text-[var(--as-muted-fg)]\">{labels?.result ?? 'Result'}</p>\n {renderResult ? (\n renderResult(result ?? '')\n ) : (\n <pre className=\"max-h-40 overflow-auto whitespace-pre-wrap break-words rounded-[var(--as-radius-sm)] bg-[var(--as-surface-raised)] p-2 font-mono text-[11px] leading-relaxed\">\n {result}\n </pre>\n )}\n </div>\n ) : null}\n </div>\n ) : null}\n </div>\n )\n },\n)\n"]}
@@ -0,0 +1,198 @@
1
+ import { searchScore } from './chunk-B2G66OSQ.js';
2
+ import { cn } from './chunk-BLJWR4ZV.js';
3
+ import * as React from 'react';
4
+ import { Search, MessageSquarePlus, Pencil, Download, Trash2 } from 'lucide-react';
5
+ import { formatDistanceToNow, parseISO, isToday, isYesterday } from 'date-fns';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ function toDate(value) {
9
+ if (value === void 0) {
10
+ return void 0;
11
+ }
12
+ if (value instanceof Date) {
13
+ return value;
14
+ }
15
+ if (typeof value === "number") {
16
+ return new Date(value);
17
+ }
18
+ return parseISO(value);
19
+ }
20
+ function bucketOf(date) {
21
+ if (date === void 0) {
22
+ return "none";
23
+ }
24
+ if (isToday(date)) {
25
+ return "today";
26
+ }
27
+ if (isYesterday(date)) {
28
+ return "yesterday";
29
+ }
30
+ return "earlier";
31
+ }
32
+ var ChatSessionList = React.forwardRef(
33
+ function ChatSessionList2({
34
+ sessions,
35
+ activeId,
36
+ onSelect,
37
+ onNew,
38
+ onRename,
39
+ onDelete,
40
+ onExport,
41
+ searchable = true,
42
+ groupByDate = true,
43
+ labels,
44
+ icons,
45
+ className
46
+ }, ref) {
47
+ const [query, setQuery] = React.useState("");
48
+ const NewIcon = icons?.newChat ?? MessageSquarePlus;
49
+ const RenameIcon = icons?.rename ?? Pencil;
50
+ const DeleteIcon = icons?.delete ?? Trash2;
51
+ const ExportIcon = icons?.export ?? Download;
52
+ const filtered = React.useMemo(() => {
53
+ const trimmed = query.trim();
54
+ if (trimmed === "") {
55
+ return sessions;
56
+ }
57
+ return sessions.map((session) => ({
58
+ session,
59
+ score: searchScore(trimmed, session.title)
60
+ })).filter((entry) => entry.score !== null).sort((a, b) => (b.score ?? 0) - (a.score ?? 0)).map((entry) => entry.session);
61
+ }, [sessions, query]);
62
+ const groups = React.useMemo(() => {
63
+ if (!groupByDate) {
64
+ return [{ key: "all", label: null, sessions: filtered }];
65
+ }
66
+ const ordered = [...filtered].sort((a, b) => {
67
+ const dateA = toDate(a.updatedAt)?.getTime() ?? 0;
68
+ const dateB = toDate(b.updatedAt)?.getTime() ?? 0;
69
+ return dateB - dateA;
70
+ });
71
+ const byBucket = /* @__PURE__ */ new Map();
72
+ for (const session of ordered) {
73
+ const bucket = bucketOf(toDate(session.updatedAt));
74
+ const list = byBucket.get(bucket) ?? [];
75
+ list.push(session);
76
+ byBucket.set(bucket, list);
77
+ }
78
+ const order = ["today", "yesterday", "earlier", "none"];
79
+ return order.filter((bucket) => byBucket.has(bucket)).map((bucket) => ({
80
+ key: bucket,
81
+ label: bucket === "today" ? labels?.today ?? "Today" : bucket === "yesterday" ? labels?.yesterday ?? "Yesterday" : bucket === "earlier" ? labels?.earlier ?? "Earlier" : null,
82
+ sessions: byBucket.get(bucket) ?? []
83
+ }));
84
+ }, [filtered, groupByDate, labels]);
85
+ return /* @__PURE__ */ jsxs("div", { ref, "data-as": "chat-session-list", className: cn("flex h-full min-h-0 w-full flex-col gap-2", className), children: [
86
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
87
+ searchable ? /* @__PURE__ */ jsxs("div", { className: "relative min-w-0 flex-1", children: [
88
+ /* @__PURE__ */ jsx(Search, { className: "pointer-events-none absolute start-2 top-1/2 size-3.5 -translate-y-1/2 text-[var(--as-muted-fg)]", "aria-hidden": true }),
89
+ /* @__PURE__ */ jsx(
90
+ "input",
91
+ {
92
+ type: "search",
93
+ role: "searchbox",
94
+ value: query,
95
+ "aria-label": labels?.search ?? "Search conversations",
96
+ placeholder: labels?.searchPlaceholder ?? "Search\u2026",
97
+ onChange: (event) => setQuery(event.target.value),
98
+ className: "w-full rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] py-1.5 pe-2 ps-8 text-xs text-[var(--as-fg)] placeholder:text-[var(--as-muted-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]"
99
+ }
100
+ )
101
+ ] }) : null,
102
+ onNew ? /* @__PURE__ */ jsx(
103
+ "button",
104
+ {
105
+ type: "button",
106
+ onClick: onNew,
107
+ "aria-label": labels?.newChat ?? "New conversation",
108
+ title: labels?.newChat ?? "New conversation",
109
+ className: "flex size-7 shrink-0 items-center justify-center rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] text-[var(--as-fg)] transition-colors hover:bg-[var(--as-secondary)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
110
+ children: /* @__PURE__ */ jsx(NewIcon, { className: "size-4", "aria-hidden": true })
111
+ }
112
+ ) : null
113
+ ] }),
114
+ /* @__PURE__ */ jsx("div", { role: "list", "aria-label": labels?.search ?? "Conversations", className: "min-h-0 flex-1 overflow-y-auto", children: sessions.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-2 py-3 text-xs text-[var(--as-muted-fg)]", children: labels?.empty ?? "No conversations yet" }) : filtered.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-2 py-3 text-xs text-[var(--as-muted-fg)]", children: labels?.noResults ?? "No matches" }) : groups.map((group) => /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
115
+ group.label ? /* @__PURE__ */ jsx("p", { className: "px-2 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-[var(--as-muted-fg)]", children: group.label }) : null,
116
+ group.sessions.map((session) => {
117
+ const isActive = session.id === activeId;
118
+ const date = toDate(session.updatedAt);
119
+ const actions = onRename || onDelete || onExport ? [
120
+ onRename ? {
121
+ key: "rename",
122
+ label: labels?.rename ?? "Rename",
123
+ icon: /* @__PURE__ */ jsx(RenameIcon, { className: "size-3.5", "aria-hidden": true }),
124
+ onSelect: () => onRename(session.id)
125
+ } : null,
126
+ onExport ? {
127
+ key: "export",
128
+ label: labels?.export ?? "Export",
129
+ icon: /* @__PURE__ */ jsx(ExportIcon, { className: "size-3.5", "aria-hidden": true }),
130
+ onSelect: () => onExport(session.id)
131
+ } : null,
132
+ onDelete ? {
133
+ key: "delete",
134
+ label: labels?.delete ?? "Delete",
135
+ icon: /* @__PURE__ */ jsx(DeleteIcon, { className: "size-3.5", "aria-hidden": true }),
136
+ onSelect: () => onDelete(session.id),
137
+ danger: true
138
+ } : null
139
+ ].filter((item) => item !== null) : [];
140
+ return /* @__PURE__ */ jsxs(
141
+ "div",
142
+ {
143
+ role: "listitem",
144
+ "aria-current": isActive ? "true" : void 0,
145
+ "data-active": isActive || void 0,
146
+ className: cn(
147
+ "group/session flex cursor-pointer items-center gap-2 rounded-[var(--as-radius)] px-2 py-1.5 text-xs transition-colors hover:bg-[var(--as-surface-raised)]",
148
+ isActive && "bg-[var(--as-surface-raised)] font-medium text-[var(--as-fg)]"
149
+ ),
150
+ onClick: () => onSelect(session.id),
151
+ onKeyDown: (event) => {
152
+ if (event.key === "Enter" || event.key === " ") {
153
+ event.preventDefault();
154
+ onSelect(session.id);
155
+ }
156
+ },
157
+ tabIndex: 0,
158
+ children: [
159
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-[var(--as-fg)]", children: session.title }),
160
+ date ? /* @__PURE__ */ jsx("span", { className: "shrink-0 text-[10px] text-[var(--as-muted-fg)]", children: formatDistanceToNow(date, { addSuffix: true }) }) : null,
161
+ actions.length > 0 ? /* @__PURE__ */ jsx(
162
+ "span",
163
+ {
164
+ role: "group",
165
+ "aria-label": labels?.rename ?? "Conversation actions",
166
+ className: "flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity focus-within:opacity-100 group-hover/session:opacity-100",
167
+ onClick: (event) => event.stopPropagation(),
168
+ onKeyDown: (event) => event.stopPropagation(),
169
+ children: actions.map((action) => /* @__PURE__ */ jsx(
170
+ "button",
171
+ {
172
+ type: "button",
173
+ "aria-label": action.label,
174
+ title: action.label,
175
+ onClick: action.onSelect,
176
+ className: cn(
177
+ "rounded-[var(--as-radius-sm)] p-1 text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-surface)] hover:text-[var(--as-fg)] focus-visible:opacity-100 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
178
+ action.danger && "hover:text-[var(--as-danger)]"
179
+ ),
180
+ children: action.icon
181
+ },
182
+ action.key
183
+ ))
184
+ }
185
+ ) : null
186
+ ]
187
+ },
188
+ session.id
189
+ );
190
+ })
191
+ ] }, group.key)) })
192
+ ] });
193
+ }
194
+ );
195
+
196
+ export { ChatSessionList };
197
+ //# sourceMappingURL=chunk-NKYPNEOX.js.map
198
+ //# sourceMappingURL=chunk-NKYPNEOX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/chat-session-list/ChatSessionList.tsx"],"names":["ChatSessionList"],"mappings":"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","file":"chunk-NKYPNEOX.js","sourcesContent":["import * as React from 'react'\nimport { Download, MessageSquarePlus, Pencil, Search, Trash2 } from 'lucide-react'\nimport type { LucideIcon } from 'lucide-react'\nimport { formatDistanceToNow, isToday, isYesterday, parseISO } from 'date-fns'\n\nimport { cn } from '../../lib/utils'\nimport { searchScore } from '../../lib/fuzzy'\n\nexport interface ChatSessionView {\n id: string\n title: string\n updatedAt?: string | number | Date\n meta?: Record<string, unknown>\n}\n\nexport interface ChatSessionListLabels {\n search: string\n searchPlaceholder: string\n newChat: string\n rename: string\n delete: string\n export: string\n today: string\n yesterday: string\n earlier: string\n empty: string\n noResults: string\n}\n\nexport interface ChatSessionListIcons {\n newChat: LucideIcon\n rename: LucideIcon\n delete: LucideIcon\n export: LucideIcon\n}\n\nexport interface ChatSessionListProps {\n sessions: ChatSessionView[]\n activeId?: string | null\n onSelect: (id: string) => void\n onNew?: () => void\n onRename?: (id: string) => void\n onDelete?: (id: string) => void\n onExport?: (id: string) => void\n searchable?: boolean\n groupByDate?: boolean\n labels?: Partial<ChatSessionListLabels>\n icons?: Partial<ChatSessionListIcons>\n className?: string\n}\n\nfunction toDate(value: string | number | Date | undefined): Date | undefined {\n if (value === undefined) {\n return undefined\n }\n if (value instanceof Date) {\n return value\n }\n if (typeof value === 'number') {\n return new Date(value)\n }\n return parseISO(value)\n}\n\nfunction bucketOf(date: Date | undefined): 'today' | 'yesterday' | 'earlier' | 'none' {\n if (date === undefined) {\n return 'none'\n }\n if (isToday(date)) {\n return 'today'\n }\n if (isYesterday(date)) {\n return 'yesterday'\n }\n return 'earlier'\n}\n\n/**\n * The session list beside a full-page chat (study's `ChatSessionList` +\n * health's history overlay, generalized): fuzzy search, date grouping,\n * active marking, per-session actions (rename/delete/export) via the\n * menu when handlers are provided. All actions stay app-side.\n */\nexport const ChatSessionList = React.forwardRef<HTMLDivElement, ChatSessionListProps>(\n function ChatSessionList(\n {\n sessions,\n activeId,\n onSelect,\n onNew,\n onRename,\n onDelete,\n onExport,\n searchable = true,\n groupByDate = true,\n labels,\n icons,\n className,\n },\n ref,\n ) {\n const [query, setQuery] = React.useState('')\n const NewIcon = icons?.newChat ?? MessageSquarePlus\n const RenameIcon = icons?.rename ?? Pencil\n const DeleteIcon = icons?.delete ?? Trash2\n const ExportIcon = icons?.export ?? Download\n\n const filtered = React.useMemo(() => {\n const trimmed = query.trim()\n if (trimmed === '') {\n return sessions\n }\n return sessions\n .map((session) => ({\n session,\n score: searchScore(trimmed, session.title),\n }))\n .filter((entry) => entry.score !== null)\n .sort((a, b) => (b.score ?? 0) - (a.score ?? 0))\n .map((entry) => entry.session)\n }, [sessions, query])\n\n const groups = React.useMemo(() => {\n if (!groupByDate) {\n return [{ key: 'all', label: null as string | null, sessions: filtered }]\n }\n const ordered = [...filtered].sort((a, b) => {\n const dateA = toDate(a.updatedAt)?.getTime() ?? 0\n const dateB = toDate(b.updatedAt)?.getTime() ?? 0\n return dateB - dateA\n })\n const byBucket = new Map<string, ChatSessionView[]>()\n for (const session of ordered) {\n const bucket = bucketOf(toDate(session.updatedAt))\n const list = byBucket.get(bucket) ?? []\n list.push(session)\n byBucket.set(bucket, list)\n }\n const order = ['today', 'yesterday', 'earlier', 'none']\n return order\n .filter((bucket) => byBucket.has(bucket))\n .map((bucket) => ({\n key: bucket,\n label:\n bucket === 'today'\n ? (labels?.today ?? 'Today')\n : bucket === 'yesterday'\n ? (labels?.yesterday ?? 'Yesterday')\n : bucket === 'earlier'\n ? (labels?.earlier ?? 'Earlier')\n : null,\n sessions: byBucket.get(bucket) ?? [],\n }))\n }, [filtered, groupByDate, labels])\n\n return (\n <div ref={ref} data-as=\"chat-session-list\" className={cn('flex h-full min-h-0 w-full flex-col gap-2', className)}>\n <div className=\"flex items-center gap-2\">\n {searchable ? (\n <div className=\"relative min-w-0 flex-1\">\n <Search className=\"pointer-events-none absolute start-2 top-1/2 size-3.5 -translate-y-1/2 text-[var(--as-muted-fg)]\" aria-hidden />\n <input\n type=\"search\"\n role=\"searchbox\"\n value={query}\n aria-label={labels?.search ?? 'Search conversations'}\n placeholder={labels?.searchPlaceholder ?? 'Search…'}\n onChange={(event) => setQuery(event.target.value)}\n className=\"w-full rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] py-1.5 pe-2 ps-8 text-xs text-[var(--as-fg)] placeholder:text-[var(--as-muted-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]\"\n />\n </div>\n ) : null}\n {onNew ? (\n <button\n type=\"button\"\n onClick={onNew}\n aria-label={labels?.newChat ?? 'New conversation'}\n title={labels?.newChat ?? 'New conversation'}\n className=\"flex size-7 shrink-0 items-center justify-center rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] text-[var(--as-fg)] transition-colors hover:bg-[var(--as-secondary)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <NewIcon className=\"size-4\" aria-hidden />\n </button>\n ) : null}\n </div>\n <div role=\"list\" aria-label={labels?.search ?? 'Conversations'} className=\"min-h-0 flex-1 overflow-y-auto\">\n {sessions.length === 0 ? (\n <p className=\"px-2 py-3 text-xs text-[var(--as-muted-fg)]\">{labels?.empty ?? 'No conversations yet'}</p>\n ) : filtered.length === 0 ? (\n <p className=\"px-2 py-3 text-xs text-[var(--as-muted-fg)]\">{labels?.noResults ?? 'No matches'}</p>\n ) : (\n groups.map((group) => (\n <div key={group.key} className=\"mb-2\">\n {group.label ? (\n <p className=\"px-2 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-[var(--as-muted-fg)]\">\n {group.label}\n </p>\n ) : null}\n {group.sessions.map((session) => {\n const isActive = session.id === activeId\n const date = toDate(session.updatedAt)\n const actions =\n onRename || onDelete || onExport\n ? [\n onRename\n ? {\n key: 'rename',\n label: labels?.rename ?? 'Rename',\n icon: <RenameIcon className=\"size-3.5\" aria-hidden />,\n onSelect: () => onRename(session.id),\n }\n : null,\n onExport\n ? {\n key: 'export',\n label: labels?.export ?? 'Export',\n icon: <ExportIcon className=\"size-3.5\" aria-hidden />,\n onSelect: () => onExport(session.id),\n }\n : null,\n onDelete\n ? {\n key: 'delete',\n label: labels?.delete ?? 'Delete',\n icon: <DeleteIcon className=\"size-3.5\" aria-hidden />,\n onSelect: () => onDelete(session.id),\n danger: true,\n }\n : null,\n ].filter((item): item is NonNullable<typeof item> => item !== null)\n : []\n return (\n <div\n key={session.id}\n role=\"listitem\"\n aria-current={isActive ? 'true' : undefined}\n data-active={isActive || undefined}\n className={cn(\n 'group/session flex cursor-pointer items-center gap-2 rounded-[var(--as-radius)] px-2 py-1.5 text-xs transition-colors hover:bg-[var(--as-surface-raised)]',\n isActive && 'bg-[var(--as-surface-raised)] font-medium text-[var(--as-fg)]',\n )}\n onClick={() => onSelect(session.id)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onSelect(session.id)\n }\n }}\n tabIndex={0}\n >\n <span className=\"min-w-0 flex-1 truncate text-[var(--as-fg)]\">{session.title}</span>\n {date ? (\n <span className=\"shrink-0 text-[10px] text-[var(--as-muted-fg)]\">\n {formatDistanceToNow(date, { addSuffix: true })}\n </span>\n ) : null}\n {actions.length > 0 ? (\n <span\n role=\"group\"\n aria-label={labels?.rename ?? 'Conversation actions'}\n className=\"flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity focus-within:opacity-100 group-hover/session:opacity-100\"\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n >\n {actions.map((action) => (\n <button\n key={action.key}\n type=\"button\"\n aria-label={action.label}\n title={action.label}\n onClick={action.onSelect}\n className={cn(\n 'rounded-[var(--as-radius-sm)] p-1 text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-surface)] hover:text-[var(--as-fg)] focus-visible:opacity-100 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]',\n action.danger && 'hover:text-[var(--as-danger)]',\n )}\n >\n {action.icon}\n </button>\n ))}\n </span>\n ) : null}\n </div>\n )\n })}\n </div>\n ))\n )}\n </div>\n </div>\n )\n },\n)\n"]}
@@ -1,6 +1,6 @@
1
1
  import { NeuronectionMark, NeuronectionWordmark, StudyMark, CareerMark, HealthMark } from './chunk-Q2JMEAKN.js';
2
- import { Card, CardHeader, CardContent } from './chunk-RYE5YCFF.js';
3
2
  import { ChipList } from './chunk-QUPGIPTT.js';
3
+ import { Card, CardHeader, CardContent } from './chunk-RYE5YCFF.js';
4
4
  import { Badge } from './chunk-F4DP4PIM.js';
5
5
  import { cn } from './chunk-BLJWR4ZV.js';
6
6
  import * as React2 from 'react';
@@ -600,5 +600,5 @@ var AboutPanel = React2.forwardRef(
600
600
  );
601
601
 
602
602
  export { AboutCard, AboutFooterLine, AboutLinkList, AboutNote, AboutPanel, FamilyBadge, SponsorCard, TechChips };
603
- //# sourceMappingURL=chunk-INMAUGBK.js.map
604
- //# sourceMappingURL=chunk-INMAUGBK.js.map
603
+ //# sourceMappingURL=chunk-OH7AJ3WY.js.map
604
+ //# sourceMappingURL=chunk-OH7AJ3WY.js.map