@sqlrooms/ai 0.24.11 → 0.24.13

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.
@@ -1 +1 @@
1
- {"version":3,"file":"AnalysisAnswer.d.ts","sourceRoot":"","sources":["../../src/components/AnalysisAnswer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAM5D,KAAK,mBAAmB,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAoGF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,iDAwEzB,CAAC"}
1
+ {"version":3,"file":"AnalysisAnswer.d.ts","sourceRoot":"","sources":["../../src/components/AnalysisAnswer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAS5D,KAAK,mBAAmB,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AA6GF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,iDAyEzB,CAAC"}
@@ -1,9 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useState, useCallback, useMemo } from 'react';
3
3
  import Markdown from 'react-markdown';
4
+ import remarkGfm from 'remark-gfm';
4
5
  import rehypeRaw from 'rehype-raw';
5
6
  import { truncate } from '@sqlrooms/utils';
6
7
  import { MessageContainer } from './MessageContainer';
8
+ import { BrainIcon } from 'lucide-react';
9
+ import { cn } from '@sqlrooms/ui';
7
10
  // Constants moved outside component to prevent recreation
8
11
  const THINK_WORD_LIMIT = 10;
9
12
  const COMPLETE_THINK_REGEX = /<think>([\s\S]*?)<\/think>/g;
@@ -44,11 +47,11 @@ const processContent = (originalContent) => {
44
47
  /**
45
48
  * ThinkBlock component for rendering individual think blocks
46
49
  */
47
- const ThinkBlock = React.memo(({ thinkContent, isExpanded, onToggleExpansion }) => {
50
+ const ThinkBlock = React.memo(({ thinkContent, isExpanded, onToggleExpansion, className }) => {
48
51
  const { content, isComplete, index } = thinkContent;
49
52
  const displayText = isComplete && !isExpanded ? truncate(content, THINK_WORD_LIMIT) : content;
50
53
  const needsTruncation = isComplete && content.split(' ').length > THINK_WORD_LIMIT;
51
- return (_jsx("div", { className: "inline-block", children: _jsxs("span", { className: "rounded-lg bg-gray-50 px-3 py-2 text-sm font-normal text-gray-100 dark:bg-gray-800/50 dark:text-gray-400", children: [_jsx("span", { className: "inline-flex items-start gap-2", children: _jsxs("span", { className: "text-gray-400", children: [_jsx("span", { className: "inline-block opacity-60 grayscale", children: "\uD83D\uDCAD" }), ' ', displayText] }) }), needsTruncation && (_jsx("button", { onClick: () => onToggleExpansion(content), className: "ml-2 text-xs text-gray-500 underline hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300", children: isExpanded ? 'Show less' : 'Show more' }))] }) }, `think-${index}`));
54
+ return (_jsxs("span", { className: cn('inline-block rounded-lg px-3 py-2 text-xs font-normal text-gray-100 dark:text-gray-400', isExpanded && 'bg-gray-50 dark:bg-gray-800/50', className), children: [_jsx("span", { className: "inline-flex items-start gap-2", children: _jsxs("span", { className: "text-gray-400", children: [_jsx(BrainIcon, { className: "mb-1 inline-block opacity-60 grayscale", size: 12 }), ' ', displayText] }) }), ' ', needsTruncation && (_jsx("button", { onClick: () => onToggleExpansion(content), className: "text-xs text-gray-500 underline hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300", children: isExpanded ? 'Show less' : 'Show more thinking' }))] }, `think-${index}`));
52
55
  });
53
56
  ThinkBlock.displayName = 'ThinkBlock';
54
57
  /**
@@ -91,7 +94,7 @@ export const AnalysisAnswer = React.memo(function AnalysisAnswer(props) {
91
94
  return null;
92
95
  }
93
96
  }, [thinkContents, expandedThink, toggleThinkExpansion]);
94
- return (_jsx("div", { className: "flex flex-col gap-5", children: _jsx(MessageContainer, { isSuccess: true, type: props.isAnswer ? 'answer' : 'thinking', content: props, children: _jsx(Markdown, { className: "prose dark:prose-invert max-w-none text-sm", rehypePlugins: [rehypeRaw], components: {
97
+ return (_jsx("div", { className: "flex flex-col gap-5", children: _jsx(MessageContainer, { isSuccess: true, type: props.isAnswer ? 'answer' : 'thinking', content: props, children: _jsx(Markdown, { className: "prose dark:prose-invert max-w-none text-sm", remarkPlugins: [remarkGfm], rehypePlugins: [rehypeRaw], components: {
95
98
  // @ts-expect-error - Custom HTML element not in react-markdown types
96
99
  'think-block': thinkBlockComponent,
97
100
  }, children: processedContent }) }) }));
@@ -1 +1 @@
1
- {"version":3,"file":"AnalysisAnswer.js","sourceRoot":"","sources":["../../src/components/AnalysisAnswer.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {useState, useCallback, useMemo} from 'react';\nimport Markdown from 'react-markdown';\nimport rehypeRaw from 'rehype-raw';\nimport {truncate} from '@sqlrooms/utils';\nimport {MessageContainer} from './MessageContainer';\n\ntype AnalysisAnswerProps = {\n content: string;\n isAnswer: boolean;\n};\n\ntype ThinkContent = {\n content: string;\n isComplete: boolean;\n index: number;\n};\n\n// Constants moved outside component to prevent recreation\nconst THINK_WORD_LIMIT = 10;\nconst COMPLETE_THINK_REGEX = /<think>([\\s\\S]*?)<\\/think>/g;\nconst INCOMPLETE_THINK_REGEX = /<think>([\\s\\S]*)$/;\n\n/**\n * Processes content and extracts think content in one pass\n */\nconst processContent = (\n originalContent: string,\n): {\n processedContent: string;\n thinkContents: ThinkContent[];\n} => {\n const thinkContents: ThinkContent[] = [];\n let processedContent = originalContent;\n let index = 0;\n\n // Replace complete think tags\n processedContent = processedContent.replace(\n COMPLETE_THINK_REGEX,\n (match, content) => {\n if (content) {\n thinkContents.push({\n content: content.trim(),\n isComplete: true,\n index: index++,\n });\n return `\\n\\n<think-block data-index=\"${index - 1}\"></think-block>\\n\\n`;\n }\n return match;\n },\n );\n\n // Replace incomplete think tags (no closing tag)\n processedContent = processedContent.replace(\n INCOMPLETE_THINK_REGEX,\n (match, content) => {\n if (content) {\n thinkContents.push({\n content: content.trim(),\n isComplete: false,\n index: index++,\n });\n return `\\n\\n<think-block data-index=\"${index - 1}\"></think-block>\\n\\n`;\n }\n return match;\n },\n );\n\n return {processedContent, thinkContents};\n};\n\n/**\n * ThinkBlock component for rendering individual think blocks\n */\nconst ThinkBlock = React.memo<{\n thinkContent: ThinkContent;\n isExpanded: boolean;\n onToggleExpansion: (content: string) => void;\n}>(({thinkContent, isExpanded, onToggleExpansion}) => {\n const {content, isComplete, index} = thinkContent;\n\n const displayText =\n isComplete && !isExpanded ? truncate(content, THINK_WORD_LIMIT) : content;\n const needsTruncation =\n isComplete && content.split(' ').length > THINK_WORD_LIMIT;\n\n return (\n <div key={`think-${index}`} className=\"inline-block\">\n <span className=\"rounded-lg bg-gray-50 px-3 py-2 text-sm font-normal text-gray-100 dark:bg-gray-800/50 dark:text-gray-400\">\n <span className=\"inline-flex items-start gap-2\">\n <span className=\"text-gray-400\">\n <span className=\"inline-block opacity-60 grayscale\">💭</span>{' '}\n {displayText}\n </span>\n </span>\n {needsTruncation && (\n <button\n onClick={() => onToggleExpansion(content)}\n className=\"ml-2 text-xs text-gray-500 underline hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300\"\n >\n {isExpanded ? 'Show less' : 'Show more'}\n </button>\n )}\n </span>\n </div>\n );\n});\n\nThinkBlock.displayName = 'ThinkBlock';\n\n/**\n * Renders an analysis answer with markdown content of the final streaming response.\n * Supports streaming think content that may arrive in chunks (e.g., \"<think>Hello\" before \"</think>\").\n *\n * @param {AnalysisAnswerProps} props - The component props. See {@link AnalysisAnswerProps} for more details.\n * @returns {JSX.Element} The rendered answer tool call\n */\nexport const AnalysisAnswer = React.memo(function AnalysisAnswer(\n props: AnalysisAnswerProps,\n) {\n const [expandedThink, setExpandedThink] = useState<Set<string>>(new Set());\n\n const toggleThinkExpansion = useCallback((content: string) => {\n setExpandedThink((prev) => {\n const newExpanded = new Set(prev);\n if (newExpanded.has(content)) {\n newExpanded.delete(content);\n } else {\n newExpanded.add(content);\n }\n return newExpanded;\n });\n }, []);\n\n // Memoize content processing to avoid recalculation on every render\n const {processedContent, thinkContents} = useMemo(\n () => processContent(props.content),\n [props.content],\n );\n\n // Memoize the think-block component to prevent unnecessary re-renders\n const thinkBlockComponent = useCallback(\n (thinkBlock: any) => {\n try {\n const index = parseInt(thinkBlock.props?.['data-index'] || '0', 10);\n const thinkContent = thinkContents[index];\n\n if (!thinkContent) {\n console.warn(`Think content not found for index: ${index}`);\n return null;\n }\n\n const isExpanded = expandedThink.has(thinkContent.content);\n\n return (\n <ThinkBlock\n thinkContent={thinkContent}\n isExpanded={isExpanded}\n onToggleExpansion={toggleThinkExpansion}\n />\n );\n } catch (error) {\n console.error('Error rendering think block:', error);\n return null;\n }\n },\n [thinkContents, expandedThink, toggleThinkExpansion],\n );\n\n return (\n <div className=\"flex flex-col gap-5\">\n <MessageContainer\n isSuccess={true}\n type={props.isAnswer ? 'answer' : 'thinking'}\n content={props}\n >\n <Markdown\n className=\"prose dark:prose-invert max-w-none text-sm\"\n rehypePlugins={[rehypeRaw]}\n components={{\n // @ts-expect-error - Custom HTML element not in react-markdown types\n 'think-block': thinkBlockComponent,\n }}\n >\n {processedContent}\n </Markdown>\n </MessageContainer>\n </div>\n );\n});\n"]}
1
+ {"version":3,"file":"AnalysisAnswer.js","sourceRoot":"","sources":["../../src/components/AnalysisAnswer.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAC,MAAM,OAAO,CAAC;AAC5D,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,EAAC,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AACvC,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAahC,0DAA0D;AAC1D,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,oBAAoB,GAAG,6BAA6B,CAAC;AAC3D,MAAM,sBAAsB,GAAG,mBAAmB,CAAC;AAEnD;;GAEG;AACH,MAAM,cAAc,GAAG,CACrB,eAAuB,EAIvB,EAAE;IACF,MAAM,aAAa,GAAmB,EAAE,CAAC;IACzC,IAAI,gBAAgB,GAAG,eAAe,CAAC;IACvC,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,8BAA8B;IAC9B,gBAAgB,GAAG,gBAAgB,CAAC,OAAO,CACzC,oBAAoB,EACpB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACjB,IAAI,OAAO,EAAE,CAAC;YACZ,aAAa,CAAC,IAAI,CAAC;gBACjB,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE;gBACvB,UAAU,EAAE,IAAI;gBAChB,KAAK,EAAE,KAAK,EAAE;aACf,CAAC,CAAC;YACH,OAAO,gCAAgC,KAAK,GAAG,CAAC,sBAAsB,CAAC;QACzE,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CACF,CAAC;IAEF,iDAAiD;IACjD,gBAAgB,GAAG,gBAAgB,CAAC,OAAO,CACzC,sBAAsB,EACtB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACjB,IAAI,OAAO,EAAE,CAAC;YACZ,aAAa,CAAC,IAAI,CAAC;gBACjB,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE;gBACvB,UAAU,EAAE,KAAK;gBACjB,KAAK,EAAE,KAAK,EAAE;aACf,CAAC,CAAC;YACH,OAAO,gCAAgC,KAAK,GAAG,CAAC,sBAAsB,CAAC;QACzE,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CACF,CAAC;IAEF,OAAO,EAAC,gBAAgB,EAAE,aAAa,EAAC,CAAC;AAC3C,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAK1B,CAAC,EAAC,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,SAAS,EAAC,EAAE,EAAE;IAC9D,MAAM,EAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAC,GAAG,YAAY,CAAC;IAElD,MAAM,WAAW,GACf,UAAU,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC5E,MAAM,eAAe,GACnB,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,gBAAgB,CAAC;IAE7D,OAAO,CACL,gBAEE,SAAS,EAAE,EAAE,CACX,wFAAwF,EACxF,UAAU,IAAI,gCAAgC,EAC9C,SAAS,CACV,aAED,eAAM,SAAS,EAAC,+BAA+B,YAC7C,gBAAM,SAAS,EAAC,eAAe,aAC7B,KAAC,SAAS,IACR,SAAS,EAAC,wCAAwC,EAClD,IAAI,EAAE,EAAE,GACR,EAAC,GAAG,EACL,WAAW,IACP,GACF,EAAC,GAAG,EACV,eAAe,IAAI,CAClB,iBACE,OAAO,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,OAAO,CAAC,EACzC,SAAS,EAAC,iGAAiG,YAE1G,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,oBAAoB,GACzC,CACV,KAvBI,SAAS,KAAK,EAAE,CAwBhB,CACR,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,UAAU,CAAC,WAAW,GAAG,YAAY,CAAC;AAEtC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,cAAc,CAC9D,KAA0B;IAE1B,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAc,IAAI,GAAG,EAAE,CAAC,CAAC;IAE3E,MAAM,oBAAoB,GAAG,WAAW,CAAC,CAAC,OAAe,EAAE,EAAE;QAC3D,gBAAgB,CAAC,CAAC,IAAI,EAAE,EAAE;YACxB,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7B,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC;YACD,OAAO,WAAW,CAAC;QACrB,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,oEAAoE;IACpE,MAAM,EAAC,gBAAgB,EAAE,aAAa,EAAC,GAAG,OAAO,CAC/C,GAAG,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,EACnC,CAAC,KAAK,CAAC,OAAO,CAAC,CAChB,CAAC;IAEF,sEAAsE;IACtE,MAAM,mBAAmB,GAAG,WAAW,CACrC,CAAC,UAAe,EAAE,EAAE;QAClB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,QAAQ,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,YAAY,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;YACpE,MAAM,YAAY,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;YAE1C,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CAAC,sCAAsC,KAAK,EAAE,CAAC,CAAC;gBAC5D,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAE3D,OAAO,CACL,KAAC,UAAU,IACT,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,oBAAoB,GACvC,CACH,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;YACrD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC,EACD,CAAC,aAAa,EAAE,aAAa,EAAE,oBAAoB,CAAC,CACrD,CAAC;IAEF,OAAO,CACL,cAAK,SAAS,EAAC,qBAAqB,YAClC,KAAC,gBAAgB,IACf,SAAS,EAAE,IAAI,EACf,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,EAC5C,OAAO,EAAE,KAAK,YAEd,KAAC,QAAQ,IACP,SAAS,EAAC,4CAA4C,EACtD,aAAa,EAAE,CAAC,SAAS,CAAC,EAC1B,aAAa,EAAE,CAAC,SAAS,CAAC,EAC1B,UAAU,EAAE;oBACV,qEAAqE;oBACrE,aAAa,EAAE,mBAAmB;iBACnC,YAEA,gBAAgB,GACR,GACM,GACf,CACP,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["import React, {useState, useCallback, useMemo} from 'react';\nimport Markdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport rehypeRaw from 'rehype-raw';\nimport {truncate} from '@sqlrooms/utils';\nimport {MessageContainer} from './MessageContainer';\nimport {BrainIcon} from 'lucide-react';\nimport {cn} from '@sqlrooms/ui';\n\ntype AnalysisAnswerProps = {\n content: string;\n isAnswer: boolean;\n};\n\ntype ThinkContent = {\n content: string;\n isComplete: boolean;\n index: number;\n};\n\n// Constants moved outside component to prevent recreation\nconst THINK_WORD_LIMIT = 10;\nconst COMPLETE_THINK_REGEX = /<think>([\\s\\S]*?)<\\/think>/g;\nconst INCOMPLETE_THINK_REGEX = /<think>([\\s\\S]*)$/;\n\n/**\n * Processes content and extracts think content in one pass\n */\nconst processContent = (\n originalContent: string,\n): {\n processedContent: string;\n thinkContents: ThinkContent[];\n} => {\n const thinkContents: ThinkContent[] = [];\n let processedContent = originalContent;\n let index = 0;\n\n // Replace complete think tags\n processedContent = processedContent.replace(\n COMPLETE_THINK_REGEX,\n (match, content) => {\n if (content) {\n thinkContents.push({\n content: content.trim(),\n isComplete: true,\n index: index++,\n });\n return `\\n\\n<think-block data-index=\"${index - 1}\"></think-block>\\n\\n`;\n }\n return match;\n },\n );\n\n // Replace incomplete think tags (no closing tag)\n processedContent = processedContent.replace(\n INCOMPLETE_THINK_REGEX,\n (match, content) => {\n if (content) {\n thinkContents.push({\n content: content.trim(),\n isComplete: false,\n index: index++,\n });\n return `\\n\\n<think-block data-index=\"${index - 1}\"></think-block>\\n\\n`;\n }\n return match;\n },\n );\n\n return {processedContent, thinkContents};\n};\n\n/**\n * ThinkBlock component for rendering individual think blocks\n */\nconst ThinkBlock = React.memo<{\n className?: string;\n thinkContent: ThinkContent;\n isExpanded: boolean;\n onToggleExpansion: (content: string) => void;\n}>(({thinkContent, isExpanded, onToggleExpansion, className}) => {\n const {content, isComplete, index} = thinkContent;\n\n const displayText =\n isComplete && !isExpanded ? truncate(content, THINK_WORD_LIMIT) : content;\n const needsTruncation =\n isComplete && content.split(' ').length > THINK_WORD_LIMIT;\n\n return (\n <span\n key={`think-${index}`}\n className={cn(\n 'inline-block rounded-lg px-3 py-2 text-xs font-normal text-gray-100 dark:text-gray-400',\n isExpanded && 'bg-gray-50 dark:bg-gray-800/50',\n className,\n )}\n >\n <span className=\"inline-flex items-start gap-2\">\n <span className=\"text-gray-400\">\n <BrainIcon\n className=\"mb-1 inline-block opacity-60 grayscale\"\n size={12}\n />{' '}\n {displayText}\n </span>\n </span>{' '}\n {needsTruncation && (\n <button\n onClick={() => onToggleExpansion(content)}\n className=\"text-xs text-gray-500 underline hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300\"\n >\n {isExpanded ? 'Show less' : 'Show more thinking'}\n </button>\n )}\n </span>\n );\n});\n\nThinkBlock.displayName = 'ThinkBlock';\n\n/**\n * Renders an analysis answer with markdown content of the final streaming response.\n * Supports streaming think content that may arrive in chunks (e.g., \"<think>Hello\" before \"</think>\").\n *\n * @param {AnalysisAnswerProps} props - The component props. See {@link AnalysisAnswerProps} for more details.\n * @returns {JSX.Element} The rendered answer tool call\n */\nexport const AnalysisAnswer = React.memo(function AnalysisAnswer(\n props: AnalysisAnswerProps,\n) {\n const [expandedThink, setExpandedThink] = useState<Set<string>>(new Set());\n\n const toggleThinkExpansion = useCallback((content: string) => {\n setExpandedThink((prev) => {\n const newExpanded = new Set(prev);\n if (newExpanded.has(content)) {\n newExpanded.delete(content);\n } else {\n newExpanded.add(content);\n }\n return newExpanded;\n });\n }, []);\n\n // Memoize content processing to avoid recalculation on every render\n const {processedContent, thinkContents} = useMemo(\n () => processContent(props.content),\n [props.content],\n );\n\n // Memoize the think-block component to prevent unnecessary re-renders\n const thinkBlockComponent = useCallback(\n (thinkBlock: any) => {\n try {\n const index = parseInt(thinkBlock.props?.['data-index'] || '0', 10);\n const thinkContent = thinkContents[index];\n\n if (!thinkContent) {\n console.warn(`Think content not found for index: ${index}`);\n return null;\n }\n\n const isExpanded = expandedThink.has(thinkContent.content);\n\n return (\n <ThinkBlock\n thinkContent={thinkContent}\n isExpanded={isExpanded}\n onToggleExpansion={toggleThinkExpansion}\n />\n );\n } catch (error) {\n console.error('Error rendering think block:', error);\n return null;\n }\n },\n [thinkContents, expandedThink, toggleThinkExpansion],\n );\n\n return (\n <div className=\"flex flex-col gap-5\">\n <MessageContainer\n isSuccess={true}\n type={props.isAnswer ? 'answer' : 'thinking'}\n content={props}\n >\n <Markdown\n className=\"prose dark:prose-invert max-w-none text-sm\"\n remarkPlugins={[remarkGfm]}\n rehypePlugins={[rehypeRaw]}\n components={{\n // @ts-expect-error - Custom HTML element not in react-markdown types\n 'think-block': thinkBlockComponent,\n }}\n >\n {processedContent}\n </Markdown>\n </MessageContainer>\n </div>\n );\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AnalysisResult.d.ts","sourceRoot":"","sources":["../../src/components/AnalysisResult.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAC,oBAAoB,EAAC,MAAM,YAAY,CAAC;AAKhD;;;GAGG;AACH,KAAK,mBAAmB,GAAG;IACzB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,sBAAsB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,CAAC;AAaF;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAiHxD,CAAC"}
1
+ {"version":3,"file":"AnalysisResult.d.ts","sourceRoot":"","sources":["../../src/components/AnalysisResult.tsx"],"names":[],"mappings":"AAuBA,OAAO,EAAC,oBAAoB,EAAC,MAAM,YAAY,CAAC;AAKhD;;;GAGG;AACH,KAAK,mBAAmB,GAAG;IACzB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,sBAAsB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,CAAC;AAaF;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA8FxD,CAAC"}
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { JsonMonacoEditor } from '@sqlrooms/monaco-editor';
3
- import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Popover, PopoverContent, PopoverTrigger, } from '@sqlrooms/ui';
4
- import { CodeIcon, SquareTerminalIcon, TrashIcon } from 'lucide-react';
2
+ import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, CopyButton, } from '@sqlrooms/ui';
3
+ import { SquareTerminalIcon, TrashIcon, } from 'lucide-react';
5
4
  import { useState } from 'react';
6
5
  import { AnalysisAnswer } from './AnalysisAnswer';
7
6
  import { ErrorMessage } from './ErrorMessage';
@@ -32,14 +31,7 @@ export const AnalysisResult = ({ result, onDeleteAnalysisResult, }) => {
32
31
  const { id, prompt, errorMessage, streamMessage } = result;
33
32
  const parts = streamMessage.parts;
34
33
  const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false);
35
- return (_jsxs("div", { className: "group flex w-full flex-col gap-2 text-sm", children: [_jsx("div", { className: "mb-2 flex items-center gap-2 rounded-md text-gray-700 dark:text-gray-100", children: _jsxs("div", { className: "flex w-full items-center gap-2 rounded-md border p-4 text-sm", children: [_jsx(SquareTerminalIcon, { className: "h-4 w-4" }), _jsx("div", { className: "flex-1", children: prompt }), _jsxs("div", { className: "flex gap-2 opacity-0 transition-opacity group-hover:opacity-100", children: [_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6", children: _jsx(CodeIcon, { className: "h-4 w-4" }) }) }), _jsx(PopoverContent, { className: "max-h-[400px] w-[400px] overflow-auto", align: "end", side: "right", children: _jsx(JsonMonacoEditor, { value: stringifyResult(result), readOnly: true, className: "h-[300px]", options: {
36
- minimap: { enabled: false },
37
- scrollBeyondLastLine: false,
38
- automaticLayout: true,
39
- folding: true,
40
- lineNumbers: false,
41
- wordWrap: 'on',
42
- } }) })] }), _jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6", onClick: () => setShowDeleteConfirmation(true), children: _jsx(TrashIcon, { className: "h-4 w-4" }) }), _jsx(Dialog, { open: showDeleteConfirmation, onOpenChange: setShowDeleteConfirmation, children: _jsxs(DialogContent, { className: "sm:max-w-[425px]", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Confirm Deletion" }), _jsx(DialogDescription, { children: "Are you sure you want to delete this analysis result? This action cannot be undone." })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { variant: "outline", onClick: () => setShowDeleteConfirmation(false), children: "Cancel" }), _jsx(Button, { variant: "destructive", onClick: () => {
34
+ return (_jsxs("div", { className: "group flex w-full flex-col gap-2 text-sm", children: [_jsx("div", { className: "mb-2 flex items-center gap-2 rounded-md text-gray-700 dark:text-gray-100", children: _jsxs("div", { className: "bg-muted flex w-full items-center gap-2 rounded-md border p-2 text-sm", children: [_jsx(SquareTerminalIcon, { className: "h-4 w-4" }), _jsx("div", { className: "flex-1", children: prompt }), _jsxs("div", { className: "flex gap-2 opacity-0 transition-opacity group-hover:opacity-100", children: [_jsx(CopyButton, { text: prompt, variant: "ghost", size: "icon", className: "h-6 w-6", ariaLabel: "Copy prompt" }), _jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6", onClick: () => setShowDeleteConfirmation(true), children: _jsx(TrashIcon, { className: "h-4 w-4" }) }), _jsx(Dialog, { open: showDeleteConfirmation, onOpenChange: setShowDeleteConfirmation, children: _jsxs(DialogContent, { className: "sm:max-w-[425px]", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Confirm Deletion" }), _jsx(DialogDescription, { children: "Are you sure you want to delete this analysis result? This action cannot be undone." })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { variant: "outline", onClick: () => setShowDeleteConfirmation(false), children: "Cancel" }), _jsx(Button, { variant: "destructive", onClick: () => {
43
35
  onDeleteAnalysisResult(id);
44
36
  setShowDeleteConfirmation(false);
45
37
  }, children: "Delete" })] })] }) })] })] }) }), parts?.map((part, index) => (_jsxs("div", { children: [part.type === 'text' && (_jsx(AnalysisAnswer, { content: part.text, isAnswer: index === (streamMessage.parts?.length || 0) - 1 })), part.type === 'tool-invocation' && (_jsx("div", { children: _jsx(ToolResult, { toolInvocation: part.toolInvocation, additionalData: part.additionalData, isCompleted: result.isCompleted }, part.toolInvocation.toolCallId) }))] }, index))), errorMessage && _jsx(ErrorMessage, { errorMessage: errorMessage.error })] }));
@@ -1 +1 @@
1
- {"version":3,"file":"AnalysisResult.js","sourceRoot":"","sources":["../../src/components/AnalysisResult.tsx"],"names":[],"mappings":"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","sourcesContent":["import {JsonMonacoEditor} from '@sqlrooms/monaco-editor';\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@sqlrooms/ui';\nimport {StreamMessagePart} from '@openassistant/core';\nimport {CodeIcon, SquareTerminalIcon, TrashIcon} from 'lucide-react';\nimport {useState} from 'react';\nimport {AnalysisResultSchema} from '../schemas';\nimport {AnalysisAnswer} from './AnalysisAnswer';\nimport {ErrorMessage} from './ErrorMessage';\nimport {ToolResult} from './tools/ToolResult';\n\n/**\n * Props for the AnalysisResult component\n * @property {AnalysisResultSchema} result - The result of the analysis containing prompt, tool calls, and analysis data\n */\ntype AnalysisResultProps = {\n result: AnalysisResultSchema;\n onDeleteAnalysisResult: (id: string) => void;\n};\n\n/**\n * Stringify the result of the analysis, excluding toolCallMessages.\n * Used to display raw result data in a code view.\n *\n * @param result - The complete analysis result\n * @returns A JSON string representation of the result without toolCallMessages\n */\nconst stringifyResult = (result: AnalysisResultSchema) => {\n return JSON.stringify(result, null, 2);\n};\n\n/**\n * Component that displays the results of an AI analysis.\n * Shows the original prompt, intermediate tool calls, final analysis text,\n * and any tool results.\n *\n * @component\n * @param props - Component props\n * @param props.result - The analysis result data to display\n * @returns A React component displaying the analysis results\n */\nexport const AnalysisResult: React.FC<AnalysisResultProps> = ({\n result,\n onDeleteAnalysisResult,\n}) => {\n // the toolResults are reasoning steps that the LLM took to achieve the final result\n // by calling function tools to answer the prompt\n const {id, prompt, errorMessage, streamMessage} = result;\n const parts = streamMessage.parts as StreamMessagePart[];\n const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false);\n\n return (\n <div className=\"group flex w-full flex-col gap-2 text-sm\">\n <div className=\"mb-2 flex items-center gap-2 rounded-md text-gray-700 dark:text-gray-100\">\n <div className=\"flex w-full items-center gap-2 rounded-md border p-4 text-sm\">\n <SquareTerminalIcon className=\"h-4 w-4\" />\n {/** render prompt */}\n <div className=\"flex-1\">{prompt}</div>\n <div className=\"flex gap-2 opacity-0 transition-opacity group-hover:opacity-100\">\n <Popover>\n <PopoverTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\">\n <CodeIcon className=\"h-4 w-4\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className=\"max-h-[400px] w-[400px] overflow-auto\"\n align=\"end\"\n side=\"right\"\n >\n <JsonMonacoEditor\n value={stringifyResult(result)}\n readOnly={true}\n className=\"h-[300px]\"\n options={{\n minimap: {enabled: false},\n scrollBeyondLastLine: false,\n automaticLayout: true,\n folding: true,\n lineNumbers: false,\n wordWrap: 'on',\n }}\n />\n </PopoverContent>\n </Popover>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n onClick={() => setShowDeleteConfirmation(true)}\n >\n <TrashIcon className=\"h-4 w-4\" />\n </Button>\n\n {/* Delete Confirmation Dialog */}\n <Dialog\n open={showDeleteConfirmation}\n onOpenChange={setShowDeleteConfirmation}\n >\n <DialogContent className=\"sm:max-w-[425px]\">\n <DialogHeader>\n <DialogTitle>Confirm Deletion</DialogTitle>\n <DialogDescription>\n Are you sure you want to delete this analysis result? This\n action cannot be undone.\n </DialogDescription>\n </DialogHeader>\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => setShowDeleteConfirmation(false)}\n >\n Cancel\n </Button>\n <Button\n variant=\"destructive\"\n onClick={() => {\n onDeleteAnalysisResult(id);\n setShowDeleteConfirmation(false);\n }}\n >\n Delete\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n </div>\n </div>\n {/** render parts */}\n {parts?.map((part, index) => (\n <div key={index}>\n {part.type === 'text' && (\n <AnalysisAnswer\n content={part.text}\n isAnswer={index === (streamMessage.parts?.length || 0) - 1}\n />\n )}\n {part.type === 'tool-invocation' && (\n <div>\n <ToolResult\n key={part.toolInvocation.toolCallId}\n toolInvocation={part.toolInvocation}\n additionalData={part.additionalData}\n isCompleted={result.isCompleted}\n />\n </div>\n )}\n </div>\n ))}\n {/** render error message */}\n {errorMessage && <ErrorMessage errorMessage={errorMessage.error} />}\n </div>\n );\n};\n"]}
1
+ {"version":3,"file":"AnalysisResult.js","sourceRoot":"","sources":["../../src/components/AnalysisResult.tsx"],"names":[],"mappings":"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","sourcesContent":["import {JsonMonacoEditor} from '@sqlrooms/monaco-editor';\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Popover,\n PopoverContent,\n PopoverTrigger,\n CopyButton,\n} from '@sqlrooms/ui';\nimport {StreamMessagePart} from '@openassistant/core';\nimport {\n ClipboardIcon,\n CodeIcon,\n SquareTerminalIcon,\n TrashIcon,\n CheckIcon,\n} from 'lucide-react';\nimport {useState} from 'react';\nimport {AnalysisResultSchema} from '../schemas';\nimport {AnalysisAnswer} from './AnalysisAnswer';\nimport {ErrorMessage} from './ErrorMessage';\nimport {ToolResult} from './tools/ToolResult';\n\n/**\n * Props for the AnalysisResult component\n * @property {AnalysisResultSchema} result - The result of the analysis containing prompt, tool calls, and analysis data\n */\ntype AnalysisResultProps = {\n result: AnalysisResultSchema;\n onDeleteAnalysisResult: (id: string) => void;\n};\n\n/**\n * Stringify the result of the analysis, excluding toolCallMessages.\n * Used to display raw result data in a code view.\n *\n * @param result - The complete analysis result\n * @returns A JSON string representation of the result without toolCallMessages\n */\nconst stringifyResult = (result: AnalysisResultSchema) => {\n return JSON.stringify(result, null, 2);\n};\n\n/**\n * Component that displays the results of an AI analysis.\n * Shows the original prompt, intermediate tool calls, final analysis text,\n * and any tool results.\n *\n * @component\n * @param props - Component props\n * @param props.result - The analysis result data to display\n * @returns A React component displaying the analysis results\n */\nexport const AnalysisResult: React.FC<AnalysisResultProps> = ({\n result,\n onDeleteAnalysisResult,\n}) => {\n // the toolResults are reasoning steps that the LLM took to achieve the final result\n // by calling function tools to answer the prompt\n const {id, prompt, errorMessage, streamMessage} = result;\n const parts = streamMessage.parts as StreamMessagePart[];\n const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false);\n\n return (\n <div className=\"group flex w-full flex-col gap-2 text-sm\">\n <div className=\"mb-2 flex items-center gap-2 rounded-md text-gray-700 dark:text-gray-100\">\n <div className=\"bg-muted flex w-full items-center gap-2 rounded-md border p-2 text-sm\">\n <SquareTerminalIcon className=\"h-4 w-4\" />\n {/** render prompt */}\n <div className=\"flex-1\">{prompt}</div>\n <div className=\"flex gap-2 opacity-0 transition-opacity group-hover:opacity-100\">\n <CopyButton\n text={prompt}\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n ariaLabel=\"Copy prompt\"\n />\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n onClick={() => setShowDeleteConfirmation(true)}\n >\n <TrashIcon className=\"h-4 w-4\" />\n </Button>\n\n {/* Delete Confirmation Dialog */}\n <Dialog\n open={showDeleteConfirmation}\n onOpenChange={setShowDeleteConfirmation}\n >\n <DialogContent className=\"sm:max-w-[425px]\">\n <DialogHeader>\n <DialogTitle>Confirm Deletion</DialogTitle>\n <DialogDescription>\n Are you sure you want to delete this analysis result? This\n action cannot be undone.\n </DialogDescription>\n </DialogHeader>\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => setShowDeleteConfirmation(false)}\n >\n Cancel\n </Button>\n <Button\n variant=\"destructive\"\n onClick={() => {\n onDeleteAnalysisResult(id);\n setShowDeleteConfirmation(false);\n }}\n >\n Delete\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n </div>\n </div>\n {/** render parts */}\n {parts?.map((part, index) => (\n <div key={index}>\n {part.type === 'text' && (\n <AnalysisAnswer\n content={part.text}\n isAnswer={index === (streamMessage.parts?.length || 0) - 1}\n />\n )}\n {part.type === 'tool-invocation' && (\n <div>\n <ToolResult\n key={part.toolInvocation.toolCallId}\n toolInvocation={part.toolInvocation}\n additionalData={part.additionalData}\n isCompleted={result.isCompleted}\n />\n </div>\n )}\n </div>\n ))}\n {/** render error message */}\n {errorMessage && <ErrorMessage errorMessage={errorMessage.error} />}\n </div>\n );\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorMessage.d.ts","sourceRoot":"","sources":["../../src/components/ErrorMessage.tsx"],"names":[],"mappings":"AAGA,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAAC,YAAY,EAAE,MAAM,CAAA;CAAC,2CAQzD"}
1
+ {"version":3,"file":"ErrorMessage.d.ts","sourceRoot":"","sources":["../../src/components/ErrorMessage.tsx"],"names":[],"mappings":"AAIA,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAAC,YAAY,EAAE,MAAM,CAAA;CAAC,2CAWzD"}
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import Markdown from 'react-markdown';
3
+ import remarkGfm from 'remark-gfm';
3
4
  import { MessageContainer } from './MessageContainer';
4
5
  export function ErrorMessage(props) {
5
- return (_jsx(MessageContainer, { isSuccess: false, type: "error", content: props, children: _jsx(Markdown, { className: "prose dark:prose-invert max-w-none text-sm", children: props.errorMessage }) }));
6
+ return (_jsx(MessageContainer, { isSuccess: false, type: "error", content: props, children: _jsx(Markdown, { className: "prose dark:prose-invert max-w-none text-sm", remarkPlugins: [remarkGfm], children: props.errorMessage }) }));
6
7
  }
7
8
  //# sourceMappingURL=ErrorMessage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorMessage.js","sourceRoot":"","sources":["../../src/components/ErrorMessage.tsx"],"names":[],"mappings":";AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAEpD,MAAM,UAAU,YAAY,CAAC,KAA6B;IACxD,OAAO,CACL,KAAC,gBAAgB,IAAC,SAAS,EAAE,KAAK,EAAE,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,KAAK,YAC7D,KAAC,QAAQ,IAAC,SAAS,EAAC,4CAA4C,YAC7D,KAAK,CAAC,YAAY,GACV,GACM,CACpB,CAAC;AACJ,CAAC","sourcesContent":["import Markdown from 'react-markdown';\nimport {MessageContainer} from './MessageContainer';\n\nexport function ErrorMessage(props: {errorMessage: string}) {\n return (\n <MessageContainer isSuccess={false} type=\"error\" content={props}>\n <Markdown className=\"prose dark:prose-invert max-w-none text-sm\">\n {props.errorMessage}\n </Markdown>\n </MessageContainer>\n );\n}\n"]}
1
+ {"version":3,"file":"ErrorMessage.js","sourceRoot":"","sources":["../../src/components/ErrorMessage.tsx"],"names":[],"mappings":";AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAEpD,MAAM,UAAU,YAAY,CAAC,KAA6B;IACxD,OAAO,CACL,KAAC,gBAAgB,IAAC,SAAS,EAAE,KAAK,EAAE,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,KAAK,YAC7D,KAAC,QAAQ,IACP,SAAS,EAAC,4CAA4C,EACtD,aAAa,EAAE,CAAC,SAAS,CAAC,YAEzB,KAAK,CAAC,YAAY,GACV,GACM,CACpB,CAAC;AACJ,CAAC","sourcesContent":["import Markdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport {MessageContainer} from './MessageContainer';\n\nexport function ErrorMessage(props: {errorMessage: string}) {\n return (\n <MessageContainer isSuccess={false} type=\"error\" content={props}>\n <Markdown\n className=\"prose dark:prose-invert max-w-none text-sm\"\n remarkPlugins={[remarkGfm]}\n >\n {props.errorMessage}\n </Markdown>\n </MessageContainer>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"MessageContainer.d.ts","sourceRoot":"","sources":["../../src/components/MessageContainer.tsx"],"names":[],"mappings":"AAWA,KAAK,qBAAqB,GAAG;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IAEnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAmE5D,CAAC"}
1
+ {"version":3,"file":"MessageContainer.d.ts","sourceRoot":"","sources":["../../src/components/MessageContainer.tsx"],"names":[],"mappings":"AAWA,KAAK,qBAAqB,GAAG;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IAEnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAsC5D,CAAC"}
@@ -1,17 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { JsonMonacoEditor } from '@sqlrooms/monaco-editor';
3
- import { Badge, Button, cn, Popover, PopoverContent, PopoverTrigger, } from '@sqlrooms/ui';
4
- import { CodeIcon, XCircleIcon } from 'lucide-react';
2
+ import { Badge, cn, } from '@sqlrooms/ui';
3
+ import { XCircleIcon } from 'lucide-react';
5
4
  export const MessageContainer = ({ className, type,
6
5
  // borderColor,
7
6
  content, children, }) => {
8
- return (_jsxs("div", { className: cn('group relative px-5 py-2 text-xs', className, type === 'error' && 'border-destructive rounded-md border py-4'), children: [type === 'error' && (_jsxs(Badge, { variant: "secondary", className: cn('absolute left-2 top-[-12px] flex items-center gap-1 border text-xs', 'border-destructive bg-background'), children: [_jsx(XCircleIcon, { className: "h-3 w-3 text-red-500" }), type] })), _jsx("div", { className: "absolute right-2 top-2 opacity-0 transition-opacity duration-200 group-hover:opacity-100", children: _jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6", children: _jsx(CodeIcon, { className: "h-4 w-4" }) }) }), _jsx(PopoverContent, { className: "max-h-[300px] w-[400px] overflow-auto p-4", side: "right", align: "start", children: _jsx(JsonMonacoEditor, { value: JSON.stringify(content, null, 2), readOnly: true, className: "h-[250px]", options: {
9
- minimap: { enabled: false },
10
- scrollBeyondLastLine: false,
11
- automaticLayout: true,
12
- folding: true,
13
- lineNumbers: false,
14
- wordWrap: 'on',
15
- } }) })] }) }), _jsx("div", { className: "flex flex-col gap-5", children: children })] }));
7
+ return (_jsxs("div", { className: cn('group relative px-5 py-2 text-xs', className, type === 'error' && 'border-destructive rounded-md border py-4'), children: [type === 'error' && (_jsxs(Badge, { variant: "secondary", className: cn('absolute left-2 top-[-12px] flex items-center gap-1 border text-xs', 'border-destructive bg-background'), children: [_jsx(XCircleIcon, { className: "h-3 w-3 text-red-500" }), type] })), _jsx("div", { className: "flex flex-col gap-5", children: children })] }));
16
8
  };
17
9
  //# sourceMappingURL=MessageContainer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MessageContainer.js","sourceRoot":"","sources":["../../src/components/MessageContainer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AACzD,OAAO,EACL,KAAK,EACL,MAAM,EACN,EAAE,EACF,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,QAAQ,EAAE,WAAW,EAAC,MAAM,cAAc,CAAC;AAWnD,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAChE,SAAS,EACT,IAAI;AACJ,eAAe;AACf,OAAO,EACP,QAAQ,GACT,EAAE,EAAE;IACH,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,kCAAkC,EAClC,SAAS,EACT,IAAI,KAAK,OAAO,IAAI,2CAA2C,CAGhE,aAEA,IAAI,KAAK,OAAO,IAAI,CACnB,MAAC,KAAK,IACJ,OAAO,EAAC,WAAW,EACnB,SAAS,EAAE,EAAE,CACX,oEAAoE,EACpE,kCAAkC,CAEnC,aAKD,KAAC,WAAW,IAAC,SAAS,EAAC,sBAAsB,GAAG,EAE/C,IAAI,IACC,CACT,EAED,cAAK,SAAS,EAAC,0FAA0F,YACvG,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBACrB,KAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,IAAI,EAAC,MAAM,EAAC,SAAS,EAAC,SAAS,YACrD,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,GACzB,GACM,EACjB,KAAC,cAAc,IACb,SAAS,EAAC,2CAA2C,EACrD,IAAI,EAAC,OAAO,EACZ,KAAK,EAAC,OAAO,YAEb,KAAC,gBAAgB,IACf,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EACvC,QAAQ,EAAE,IAAI,EACd,SAAS,EAAC,WAAW,EACrB,OAAO,EAAE;oCACP,OAAO,EAAE,EAAC,OAAO,EAAE,KAAK,EAAC;oCACzB,oBAAoB,EAAE,KAAK;oCAC3B,eAAe,EAAE,IAAI;oCACrB,OAAO,EAAE,IAAI;oCACb,WAAW,EAAE,KAAK;oCAClB,QAAQ,EAAE,IAAI;iCACf,GACD,GACa,IACT,GACN,EAEN,cAAK,SAAS,EAAC,qBAAqB,YAAE,QAAQ,GAAO,IACjD,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {JsonMonacoEditor} from '@sqlrooms/monaco-editor';\nimport {\n Badge,\n Button,\n cn,\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@sqlrooms/ui';\nimport {CodeIcon, XCircleIcon} from 'lucide-react';\n\ntype MessageContainerProps = {\n className?: string;\n isSuccess: boolean;\n // borderColor: string;\n type: string;\n content: object;\n children: React.ReactNode;\n};\n\nexport const MessageContainer: React.FC<MessageContainerProps> = ({\n className,\n type,\n // borderColor,\n content,\n children,\n}) => {\n return (\n <div\n className={cn(\n 'group relative px-5 py-2 text-xs',\n className,\n type === 'error' && 'border-destructive rounded-md border py-4',\n // borderColor,\n // isSuccess ? borderColor : 'border-red-500',\n )}\n >\n {type === 'error' && (\n <Badge\n variant=\"secondary\"\n className={cn(\n 'absolute left-2 top-[-12px] flex items-center gap-1 border text-xs',\n 'border-destructive bg-background',\n // isSuccess ? borderColor : 'border-red-500',\n )}\n >\n {/* {isSuccess ? ( */}\n {/* <CheckCircle2Icon className=\"h-3 w-3 text-green-500\" /> */}\n {/* ) : ( */}\n <XCircleIcon className=\"h-3 w-3 text-red-500\" />\n {/* )} */}\n {type}\n </Badge>\n )}\n\n <div className=\"absolute right-2 top-2 opacity-0 transition-opacity duration-200 group-hover:opacity-100\">\n <Popover>\n <PopoverTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\">\n <CodeIcon className=\"h-4 w-4\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className=\"max-h-[300px] w-[400px] overflow-auto p-4\"\n side=\"right\"\n align=\"start\"\n >\n <JsonMonacoEditor\n value={JSON.stringify(content, null, 2)}\n readOnly={true}\n className=\"h-[250px]\"\n options={{\n minimap: {enabled: false},\n scrollBeyondLastLine: false,\n automaticLayout: true,\n folding: true,\n lineNumbers: false,\n wordWrap: 'on',\n }}\n />\n </PopoverContent>\n </Popover>\n </div>\n\n <div className=\"flex flex-col gap-5\">{children}</div>\n </div>\n );\n};\n"]}
1
+ {"version":3,"file":"MessageContainer.js","sourceRoot":"","sources":["../../src/components/MessageContainer.tsx"],"names":[],"mappings":";AACA,OAAO,EACL,KAAK,EAEL,EAAE,GAIH,MAAM,cAAc,CAAC;AACtB,OAAO,EAAW,WAAW,EAAC,MAAM,cAAc,CAAC;AAWnD,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAChE,SAAS,EACT,IAAI;AACJ,eAAe;AACf,OAAO,EACP,QAAQ,GACT,EAAE,EAAE;IACH,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,kCAAkC,EAClC,SAAS,EACT,IAAI,KAAK,OAAO,IAAI,2CAA2C,CAGhE,aAEA,IAAI,KAAK,OAAO,IAAI,CACnB,MAAC,KAAK,IACJ,OAAO,EAAC,WAAW,EACnB,SAAS,EAAE,EAAE,CACX,oEAAoE,EACpE,kCAAkC,CAEnC,aAKD,KAAC,WAAW,IAAC,SAAS,EAAC,sBAAsB,GAAG,EAE/C,IAAI,IACC,CACT,EAED,cAAK,SAAS,EAAC,qBAAqB,YAAE,QAAQ,GAAO,IACjD,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {JsonMonacoEditor} from '@sqlrooms/monaco-editor';\nimport {\n Badge,\n Button,\n cn,\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@sqlrooms/ui';\nimport {CodeIcon, XCircleIcon} from 'lucide-react';\n\ntype MessageContainerProps = {\n className?: string;\n isSuccess: boolean;\n // borderColor: string;\n type: string;\n content: object;\n children: React.ReactNode;\n};\n\nexport const MessageContainer: React.FC<MessageContainerProps> = ({\n className,\n type,\n // borderColor,\n content,\n children,\n}) => {\n return (\n <div\n className={cn(\n 'group relative px-5 py-2 text-xs',\n className,\n type === 'error' && 'border-destructive rounded-md border py-4',\n // borderColor,\n // isSuccess ? borderColor : 'border-red-500',\n )}\n >\n {type === 'error' && (\n <Badge\n variant=\"secondary\"\n className={cn(\n 'absolute left-2 top-[-12px] flex items-center gap-1 border text-xs',\n 'border-destructive bg-background',\n // isSuccess ? borderColor : 'border-red-500',\n )}\n >\n {/* {isSuccess ? ( */}\n {/* <CheckCircle2Icon className=\"h-3 w-3 text-green-500\" /> */}\n {/* ) : ( */}\n <XCircleIcon className=\"h-3 w-3 text-red-500\" />\n {/* )} */}\n {type}\n </Badge>\n )}\n\n <div className=\"flex flex-col gap-5\">{children}</div>\n </div>\n );\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryControls.d.ts","sourceRoot":"","sources":["../../src/components/QueryControls.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAC,iBAAiB,EAAiC,MAAM,OAAO,CAAC;AAGxE,KAAK,kBAAkB,GAAG,iBAAiB,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC,CAAC;AAEH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAyGtD,CAAC"}
1
+ {"version":3,"file":"QueryControls.d.ts","sourceRoot":"","sources":["../../src/components/QueryControls.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAC,iBAAiB,EAAiC,MAAM,OAAO,CAAC;AAGxE,KAAK,kBAAkB,GAAG,iBAAiB,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC,CAAC;AAEH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA6FtD,CAAC"}
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Button, cn, Spinner, Textarea } from '@sqlrooms/ui';
2
+ import { Button, cn, Textarea } from '@sqlrooms/ui';
3
3
  import { ArrowUpIcon, OctagonXIcon } from 'lucide-react';
4
4
  import { useCallback, useRef, useEffect } from 'react';
5
5
  import { useStoreWithAi } from '../AiSlice';
6
- export const QueryControls = ({ className, placeholder = 'Type here what would you like to learn about the data?', children, }) => {
6
+ export const QueryControls = ({ className, placeholder = 'What would you like to learn about the data?', children, }) => {
7
7
  const textareaRef = useRef(null);
8
8
  const isRunningAnalysis = useStoreWithAi((s) => s.ai.isRunningAnalysis);
9
9
  const runAnalysis = useStoreWithAi((s) => s.ai.startAnalysis);
@@ -39,7 +39,7 @@ export const QueryControls = ({ className, placeholder = 'Type here what would y
39
39
  }
40
40
  }
41
41
  }, [isRunningAnalysis, model, analysisPrompt, runAnalysis]);
42
- const canStart = Boolean(!isRunningAnalysis && model && analysisPrompt.trim().length);
43
- return (_jsx("div", { className: cn('flex w-full flex-col items-center justify-center gap-4', className), children: _jsx("div", { className: "relative w-full overflow-hidden p-[1px]", children: _jsxs("div", { className: "flex flex-col", children: [_jsx(Textarea, { ref: textareaRef, disabled: isRunningAnalysis, className: "bg-muted/50 h-[100px] resize-none", value: analysisPrompt, onChange: (e) => setAnalysisPrompt(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, autoFocus: true }), _jsxs("div", { className: "bg-muted/30 flex w-full items-center justify-between gap-2 p-2", children: [_jsx("div", { children: children }), _jsx("div", { className: "flex-1" }), _jsxs("div", { children: [isRunningAnalysis && (_jsxs(Button, { variant: "outline", className: "rounded-full", onClick: cancelAnalysis, children: [_jsx(OctagonXIcon, { className: "h-4 w-4" }), "Stop"] })), _jsx(Button, { className: "h-10 w-10 rounded-full", variant: "default", size: "icon", onClick: runAnalysis, disabled: !canStart, children: isRunningAnalysis ? (_jsx("div", { className: "flex items-center gap-2", children: _jsx(Spinner, { className: "h-4 w-4" }) })) : (_jsx(ArrowUpIcon, {})) })] })] })] }) }) }));
42
+ const canStart = Boolean(model && analysisPrompt.trim().length);
43
+ return (_jsx("div", { className: cn('flex w-full flex-col items-center justify-center gap-4', className), children: _jsx("div", { className: "bg-muted/50 flex h-full w-full flex-row items-center gap-2 rounded-md border", children: _jsxs("div", { className: "flex w-full flex-col gap-1 overflow-hidden", children: [_jsx(Textarea, { ref: textareaRef, disabled: isRunningAnalysis, className: "min-h-[30px] resize-none border-none p-2 text-sm outline-none focus-visible:ring-0", autoResize: true, value: analysisPrompt, onChange: (e) => setAnalysisPrompt(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, autoFocus: true }), _jsx("div", { className: "align-stretch flex w-full items-center gap-2 overflow-hidden", children: _jsxs("div", { className: "flex h-full w-full min-w-0 items-center gap-2 overflow-hidden", children: [_jsx("div", { className: "min-w-0 flex-1 overflow-hidden pl-2", children: _jsx("div", { className: "flex flex-nowrap items-center gap-2 overflow-x-auto py-1", children: children }) }), _jsx("div", { className: "ml-auto shrink-0 pr-2", children: _jsx(Button, { className: "h-8 w-8 rounded-full", variant: "default", size: "icon", onClick: isRunningAnalysis ? cancelAnalysis : runAnalysis, disabled: !canStart, children: isRunningAnalysis ? _jsx(OctagonXIcon, {}) : _jsx(ArrowUpIcon, {}) }) })] }) })] }) }) }));
44
44
  };
45
45
  //# sourceMappingURL=QueryControls.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"QueryControls.js","sourceRoot":"","sources":["../../src/components/QueryControls.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAC,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAC,WAAW,EAAE,YAAY,EAAC,MAAM,cAAc,CAAC;AACvD,OAAO,EAAoB,WAAW,EAAE,MAAM,EAAE,SAAS,EAAC,MAAM,OAAO,CAAC;AACxE,OAAO,EAAC,cAAc,EAAC,MAAM,YAAY,CAAC;AAO1C,MAAM,CAAC,MAAM,aAAa,GAAiC,CAAC,EAC1D,SAAS,EACT,WAAW,GAAG,wDAAwD,EACtE,QAAQ,GACT,EAAE,EAAE;IACH,MAAM,WAAW,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAC;IACtD,MAAM,iBAAiB,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC;IACxE,MAAM,WAAW,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC;IAClE,MAAM,cAAc,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC;IAClE,MAAM,eAAe,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACtE,MAAM,iBAAiB,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC;IACxE,MAAM,cAAc,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACvE,MAAM,KAAK,GAAG,cAAc,EAAE,KAAK,CAAC;IAEpC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,eAAe;YAAE,OAAO;QAC7B,+CAA+C;QAC/C,uDAAuD;QACvD,2DAA2D;QAC3D,2CAA2C;QAC3C,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;gBACxB,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC9B,CAAC;QACH,CAAC,EAAE,GAAG,CAAC,CAAC;QAER,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IAEtB,MAAM,aAAa,GAAG,WAAW,CAC/B,CAAC,CAA2C,EAAE,EAAE;QAC9C,IACE,CAAC,CAAC,GAAG,KAAK,OAAO;YACjB,CAAC,CAAC,CAAC,QAAQ;YACX,CAAC,CAAC,CAAC,OAAO;YACV,CAAC,CAAC,CAAC,MAAM;YACT,CAAC,CAAC,CAAC,OAAO,EACV,CAAC;YACD,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,IAAI,CAAC,iBAAiB,IAAI,KAAK,IAAI,cAAc,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;gBAChE,WAAW,EAAE,CAAC;YAChB,CAAC;QACH,CAAC;IACH,CAAC,EACD,CAAC,iBAAiB,EAAE,KAAK,EAAE,cAAc,EAAE,WAAW,CAAC,CACxD,CAAC;IAEF,MAAM,QAAQ,GAAG,OAAO,CACtB,CAAC,iBAAiB,IAAI,KAAK,IAAI,cAAc,CAAC,IAAI,EAAE,CAAC,MAAM,CAC5D,CAAC;IACF,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,wDAAwD,EACxD,SAAS,CACV,YAED,cAAK,SAAS,EAAC,yCAAyC,YACtD,eAAK,SAAS,EAAC,eAAe,aAC5B,KAAC,QAAQ,IACP,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAC,mCAAmC,EAC7C,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAClD,SAAS,EAAE,aAAa,EACxB,WAAW,EAAE,WAAW,EACxB,SAAS,SACT,EACF,eAAK,SAAS,EAAC,gEAAgE,aAC7E,wBAAM,QAAQ,GAAO,EACrB,cAAK,SAAS,EAAC,QAAQ,GAAG,EAC1B,0BACG,iBAAiB,IAAI,CACpB,MAAC,MAAM,IACL,OAAO,EAAC,SAAS,EACjB,SAAS,EAAC,cAAc,EACxB,OAAO,EAAE,cAAc,aAEvB,KAAC,YAAY,IAAC,SAAS,EAAC,SAAS,GAAG,YAE7B,CACV,EACD,KAAC,MAAM,IACL,SAAS,EAAC,wBAAwB,EAClC,OAAO,EAAC,SAAS,EACjB,IAAI,EAAC,MAAM,EACX,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,CAAC,QAAQ,YAElB,iBAAiB,CAAC,CAAC,CAAC,CACnB,cAAK,SAAS,EAAC,yBAAyB,YACtC,KAAC,OAAO,IAAC,SAAS,EAAC,SAAS,GAAG,GAC3B,CACP,CAAC,CAAC,CAAC,CACF,KAAC,WAAW,KAAG,CAChB,GACM,IACL,IACF,IACF,GACF,GACF,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {Button, cn, Spinner, Textarea} from '@sqlrooms/ui';\nimport {ArrowUpIcon, OctagonXIcon} from 'lucide-react';\nimport {PropsWithChildren, useCallback, useRef, useEffect} from 'react';\nimport {useStoreWithAi} from '../AiSlice';\n\ntype QueryControlsProps = PropsWithChildren<{\n className?: string;\n placeholder?: string;\n}>;\n\nexport const QueryControls: React.FC<QueryControlsProps> = ({\n className,\n placeholder = 'Type here what would you like to learn about the data?',\n children,\n}) => {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const isRunningAnalysis = useStoreWithAi((s) => s.ai.isRunningAnalysis);\n const runAnalysis = useStoreWithAi((s) => s.ai.startAnalysis);\n const cancelAnalysis = useStoreWithAi((s) => s.ai.cancelAnalysis);\n const analysisPrompt = useStoreWithAi((s) => s.ai.analysisPrompt);\n const isDataAvailable = useStoreWithAi((s) => s.room.isDataAvailable);\n const setAnalysisPrompt = useStoreWithAi((s) => s.ai.setAnalysisPrompt);\n const currentSession = useStoreWithAi((s) => s.ai.getCurrentSession());\n const model = currentSession?.model;\n\n useEffect(() => {\n if (!isDataAvailable) return;\n // Focus the textarea when the component mounts\n // Using a small timeout ensures the data is loaded and\n // add timeout to prevent aria hidden warning caused by the\n // loading progress dialog being still open\n const timer = setTimeout(() => {\n if (textareaRef.current) {\n textareaRef.current.focus();\n }\n }, 500);\n\n return () => clearTimeout(timer);\n }, [isDataAvailable]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (\n e.key === 'Enter' &&\n !e.shiftKey &&\n !e.ctrlKey &&\n !e.altKey &&\n !e.metaKey\n ) {\n e.preventDefault();\n if (!isRunningAnalysis && model && analysisPrompt.trim().length) {\n runAnalysis();\n }\n }\n },\n [isRunningAnalysis, model, analysisPrompt, runAnalysis],\n );\n\n const canStart = Boolean(\n !isRunningAnalysis && model && analysisPrompt.trim().length,\n );\n return (\n <div\n className={cn(\n 'flex w-full flex-col items-center justify-center gap-4',\n className,\n )}\n >\n <div className=\"relative w-full overflow-hidden p-[1px]\">\n <div className=\"flex flex-col\">\n <Textarea\n ref={textareaRef}\n disabled={isRunningAnalysis}\n className=\"bg-muted/50 h-[100px] resize-none\"\n value={analysisPrompt}\n onChange={(e) => setAnalysisPrompt(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n autoFocus\n />\n <div className=\"bg-muted/30 flex w-full items-center justify-between gap-2 p-2\">\n <div>{children}</div>\n <div className=\"flex-1\" />\n <div>\n {isRunningAnalysis && (\n <Button\n variant=\"outline\"\n className=\"rounded-full\"\n onClick={cancelAnalysis}\n >\n <OctagonXIcon className=\"h-4 w-4\" />\n Stop\n </Button>\n )}\n <Button\n className=\"h-10 w-10 rounded-full\"\n variant=\"default\"\n size=\"icon\"\n onClick={runAnalysis}\n disabled={!canStart}\n >\n {isRunningAnalysis ? (\n <div className=\"flex items-center gap-2\">\n <Spinner className=\"h-4 w-4\" />\n </div>\n ) : (\n <ArrowUpIcon />\n )}\n </Button>\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n};\n"]}
1
+ {"version":3,"file":"QueryControls.js","sourceRoot":"","sources":["../../src/components/QueryControls.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,MAAM,EAAE,EAAE,EAAW,QAAQ,EAAC,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAC,WAAW,EAAE,YAAY,EAAC,MAAM,cAAc,CAAC;AACvD,OAAO,EAAoB,WAAW,EAAE,MAAM,EAAE,SAAS,EAAC,MAAM,OAAO,CAAC;AACxE,OAAO,EAAC,cAAc,EAAC,MAAM,YAAY,CAAC;AAO1C,MAAM,CAAC,MAAM,aAAa,GAAiC,CAAC,EAC1D,SAAS,EACT,WAAW,GAAG,8CAA8C,EAC5D,QAAQ,GACT,EAAE,EAAE;IACH,MAAM,WAAW,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAC;IACtD,MAAM,iBAAiB,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC;IACxE,MAAM,WAAW,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC;IAClE,MAAM,cAAc,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC;IAClE,MAAM,eAAe,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACtE,MAAM,iBAAiB,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC;IACxE,MAAM,cAAc,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACvE,MAAM,KAAK,GAAG,cAAc,EAAE,KAAK,CAAC;IAEpC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,eAAe;YAAE,OAAO;QAC7B,+CAA+C;QAC/C,uDAAuD;QACvD,2DAA2D;QAC3D,2CAA2C;QAC3C,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;gBACxB,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC9B,CAAC;QACH,CAAC,EAAE,GAAG,CAAC,CAAC;QAER,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IAEtB,MAAM,aAAa,GAAG,WAAW,CAC/B,CAAC,CAA2C,EAAE,EAAE;QAC9C,IACE,CAAC,CAAC,GAAG,KAAK,OAAO;YACjB,CAAC,CAAC,CAAC,QAAQ;YACX,CAAC,CAAC,CAAC,OAAO;YACV,CAAC,CAAC,CAAC,MAAM;YACT,CAAC,CAAC,CAAC,OAAO,EACV,CAAC;YACD,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,IAAI,CAAC,iBAAiB,IAAI,KAAK,IAAI,cAAc,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;gBAChE,WAAW,EAAE,CAAC;YAChB,CAAC;QACH,CAAC;IACH,CAAC,EACD,CAAC,iBAAiB,EAAE,KAAK,EAAE,cAAc,EAAE,WAAW,CAAC,CACxD,CAAC;IAEF,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,IAAI,cAAc,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC;IAChE,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,wDAAwD,EACxD,SAAS,CACV,YAED,cAAK,SAAS,EAAC,8EAA8E,YAC3F,eAAK,SAAS,EAAC,4CAA4C,aACzD,KAAC,QAAQ,IACP,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAC,oFAAoF,EAC9F,UAAU,QACV,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAClD,SAAS,EAAE,aAAa,EACxB,WAAW,EAAE,WAAW,EACxB,SAAS,SACT,EACF,cAAK,SAAS,EAAC,8DAA8D,YAC3E,eAAK,SAAS,EAAC,+DAA+D,aAC5E,cAAK,SAAS,EAAC,qCAAqC,YAClD,cAAK,SAAS,EAAC,0DAA0D,YACtE,QAAQ,GACL,GACF,EACN,cAAK,SAAS,EAAC,uBAAuB,YACpC,KAAC,MAAM,IACL,SAAS,EAAC,sBAAsB,EAChC,OAAO,EAAC,SAAS,EACjB,IAAI,EAAC,MAAM,EACX,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,WAAW,EACzD,QAAQ,EAAE,CAAC,QAAQ,YAElB,iBAAiB,CAAC,CAAC,CAAC,KAAC,YAAY,KAAG,CAAC,CAAC,CAAC,KAAC,WAAW,KAAG,GAChD,GACL,IACF,GACF,IACF,GACF,GACF,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {Button, cn, Spinner, Textarea} from '@sqlrooms/ui';\nimport {ArrowUpIcon, OctagonXIcon} from 'lucide-react';\nimport {PropsWithChildren, useCallback, useRef, useEffect} from 'react';\nimport {useStoreWithAi} from '../AiSlice';\n\ntype QueryControlsProps = PropsWithChildren<{\n className?: string;\n placeholder?: string;\n}>;\n\nexport const QueryControls: React.FC<QueryControlsProps> = ({\n className,\n placeholder = 'What would you like to learn about the data?',\n children,\n}) => {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const isRunningAnalysis = useStoreWithAi((s) => s.ai.isRunningAnalysis);\n const runAnalysis = useStoreWithAi((s) => s.ai.startAnalysis);\n const cancelAnalysis = useStoreWithAi((s) => s.ai.cancelAnalysis);\n const analysisPrompt = useStoreWithAi((s) => s.ai.analysisPrompt);\n const isDataAvailable = useStoreWithAi((s) => s.room.isDataAvailable);\n const setAnalysisPrompt = useStoreWithAi((s) => s.ai.setAnalysisPrompt);\n const currentSession = useStoreWithAi((s) => s.ai.getCurrentSession());\n const model = currentSession?.model;\n\n useEffect(() => {\n if (!isDataAvailable) return;\n // Focus the textarea when the component mounts\n // Using a small timeout ensures the data is loaded and\n // add timeout to prevent aria hidden warning caused by the\n // loading progress dialog being still open\n const timer = setTimeout(() => {\n if (textareaRef.current) {\n textareaRef.current.focus();\n }\n }, 500);\n\n return () => clearTimeout(timer);\n }, [isDataAvailable]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (\n e.key === 'Enter' &&\n !e.shiftKey &&\n !e.ctrlKey &&\n !e.altKey &&\n !e.metaKey\n ) {\n e.preventDefault();\n if (!isRunningAnalysis && model && analysisPrompt.trim().length) {\n runAnalysis();\n }\n }\n },\n [isRunningAnalysis, model, analysisPrompt, runAnalysis],\n );\n\n const canStart = Boolean(model && analysisPrompt.trim().length);\n return (\n <div\n className={cn(\n 'flex w-full flex-col items-center justify-center gap-4',\n className,\n )}\n >\n <div className=\"bg-muted/50 flex h-full w-full flex-row items-center gap-2 rounded-md border\">\n <div className=\"flex w-full flex-col gap-1 overflow-hidden\">\n <Textarea\n ref={textareaRef}\n disabled={isRunningAnalysis}\n className=\"min-h-[30px] resize-none border-none p-2 text-sm outline-none focus-visible:ring-0\"\n autoResize\n value={analysisPrompt}\n onChange={(e) => setAnalysisPrompt(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n autoFocus\n />\n <div className=\"align-stretch flex w-full items-center gap-2 overflow-hidden\">\n <div className=\"flex h-full w-full min-w-0 items-center gap-2 overflow-hidden\">\n <div className=\"min-w-0 flex-1 overflow-hidden pl-2\">\n <div className=\"flex flex-nowrap items-center gap-2 overflow-x-auto py-1\">\n {children}\n </div>\n </div>\n <div className=\"ml-auto shrink-0 pr-2\">\n <Button\n className=\"h-8 w-8 rounded-full\"\n variant=\"default\"\n size=\"icon\"\n onClick={isRunningAnalysis ? cancelAnalysis : runAnalysis}\n disabled={!canStart}\n >\n {isRunningAnalysis ? <OctagonXIcon /> : <ArrowUpIcon />}\n </Button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryToolResult.d.ts","sourceRoot":"","sources":["../../../src/components/tools/QueryToolResult.tsx"],"names":[],"mappings":"AAIA,KAAK,oBAAoB,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,eAAe,CAAC,EAAC,KAAK,EAAE,QAAQ,EAAC,EAAE,oBAAoB,2CAiBtE"}
1
+ {"version":3,"file":"QueryToolResult.d.ts","sourceRoot":"","sources":["../../../src/components/tools/QueryToolResult.tsx"],"names":[],"mappings":"AAIA,KAAK,oBAAoB,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,eAAe,CAAC,EAAC,KAAK,EAAE,QAAQ,EAAC,EAAE,oBAAoB,2CA0BtE"}
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { DataTableModal } from '@sqlrooms/data-table';
3
- import { Button, useDisclosure } from '@sqlrooms/ui';
3
+ import { Button, CopyButton, useDisclosure } from '@sqlrooms/ui';
4
4
  import { TableIcon } from 'lucide-react';
5
5
  export function QueryToolResult({ title, sqlQuery }) {
6
6
  const tableModal = useDisclosure();
7
- return (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground bg-muted max-h-20 w-full overflow-auto whitespace-pre-wrap rounded-md p-2 font-mono text-xs", children: sqlQuery }), _jsx("div", { children: _jsxs(Button, { variant: "ghost", size: "sm", onClick: tableModal.onOpen, children: [_jsx(TableIcon, { className: "h-4 w-4" }), _jsx("h3", { className: "ml-1 text-xs", children: "Show Query Result" })] }) }), _jsx(DataTableModal, { title: title, query: sqlQuery, tableModal: tableModal })] }));
7
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "text-muted-foreground bg-muted relative max-h-[150px] w-full overflow-auto rounded-md p-2 font-mono text-xs", children: [_jsx("pre", { className: "whitespace-pre-wrap break-words pr-8", children: sqlQuery }), _jsx("div", { className: "absolute right-1 top-1", children: _jsx(CopyButton, { text: sqlQuery, variant: "ghost", size: "icon", className: "h-6 w-6", ariaLabel: "Copy SQL" }) })] }), _jsx("div", { className: "flex items-center gap-2", children: _jsxs(Button, { variant: "ghost", size: "sm", onClick: tableModal.onOpen, children: [_jsx(TableIcon, { className: "h-4 w-4" }), _jsx("h3", { className: "ml-1 text-xs", children: "Show Query Result" })] }) }), _jsx(DataTableModal, { title: title, query: sqlQuery, tableModal: tableModal })] }));
8
8
  }
9
9
  //# sourceMappingURL=QueryToolResult.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"QueryToolResult.js","sourceRoot":"","sources":["../../../src/components/tools/QueryToolResult.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAC,MAAM,EAAE,aAAa,EAAC,MAAM,cAAc,CAAC;AACnD,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAOvC,MAAM,UAAU,eAAe,CAAC,EAAC,KAAK,EAAE,QAAQ,EAAuB;IACrE,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,OAAO,CACL,8BACE,cAAK,SAAS,EAAC,mHAAmH,YAC/H,QAAQ,GACL,EACN,wBACE,MAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,UAAU,CAAC,MAAM,aAC1D,KAAC,SAAS,IAAC,SAAS,EAAC,SAAS,GAAG,EACjC,aAAI,SAAS,EAAC,cAAc,kCAAuB,IAC5C,GACL,EAEN,KAAC,cAAc,IAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,GAAI,IACxE,CACJ,CAAC;AACJ,CAAC","sourcesContent":["import {DataTableModal} from '@sqlrooms/data-table';\nimport {Button, useDisclosure} from '@sqlrooms/ui';\nimport {TableIcon} from 'lucide-react';\n\ntype QueryToolResultProps = {\n title: string;\n sqlQuery: string;\n};\n\nexport function QueryToolResult({title, sqlQuery}: QueryToolResultProps) {\n const tableModal = useDisclosure();\n return (\n <>\n <div className=\"text-muted-foreground bg-muted max-h-20 w-full overflow-auto whitespace-pre-wrap rounded-md p-2 font-mono text-xs\">\n {sqlQuery}\n </div>\n <div>\n <Button variant=\"ghost\" size=\"sm\" onClick={tableModal.onOpen}>\n <TableIcon className=\"h-4 w-4\" />\n <h3 className=\"ml-1 text-xs\">Show Query Result</h3>\n </Button>\n </div>\n\n <DataTableModal title={title} query={sqlQuery} tableModal={tableModal} />\n </>\n );\n}\n"]}
1
+ {"version":3,"file":"QueryToolResult.js","sourceRoot":"","sources":["../../../src/components/tools/QueryToolResult.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAC,MAAM,EAAE,UAAU,EAAE,aAAa,EAAC,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAOvC,MAAM,UAAU,eAAe,CAAC,EAAC,KAAK,EAAE,QAAQ,EAAuB;IACrE,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,OAAO,CACL,8BACE,eAAK,SAAS,EAAC,6GAA6G,aAC1H,cAAK,SAAS,EAAC,sCAAsC,YAAE,QAAQ,GAAO,EACtE,cAAK,SAAS,EAAC,wBAAwB,YACrC,KAAC,UAAU,IACT,IAAI,EAAE,QAAQ,EACd,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,MAAM,EACX,SAAS,EAAC,SAAS,EACnB,SAAS,EAAC,UAAU,GACpB,GACE,IACF,EACN,cAAK,SAAS,EAAC,yBAAyB,YACtC,MAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,UAAU,CAAC,MAAM,aAC1D,KAAC,SAAS,IAAC,SAAS,EAAC,SAAS,GAAG,EACjC,aAAI,SAAS,EAAC,cAAc,kCAAuB,IAC5C,GACL,EAEN,KAAC,cAAc,IAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,GAAI,IACxE,CACJ,CAAC;AACJ,CAAC","sourcesContent":["import {DataTableModal} from '@sqlrooms/data-table';\nimport {Button, CopyButton, useDisclosure} from '@sqlrooms/ui';\nimport {TableIcon} from 'lucide-react';\n\ntype QueryToolResultProps = {\n title: string;\n sqlQuery: string;\n};\n\nexport function QueryToolResult({title, sqlQuery}: QueryToolResultProps) {\n const tableModal = useDisclosure();\n return (\n <>\n <div className=\"text-muted-foreground bg-muted relative max-h-[150px] w-full overflow-auto rounded-md p-2 font-mono text-xs\">\n <pre className=\"whitespace-pre-wrap break-words pr-8\">{sqlQuery}</pre>\n <div className=\"absolute right-1 top-1\">\n <CopyButton\n text={sqlQuery}\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n ariaLabel=\"Copy SQL\"\n />\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={tableModal.onOpen}>\n <TableIcon className=\"h-4 w-4\" />\n <h3 className=\"ml-1 text-xs\">Show Query Result</h3>\n </Button>\n </div>\n\n <DataTableModal title={title} query={sqlQuery} tableModal={tableModal} />\n </>\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqlrooms/ai",
3
- "version": "0.24.11",
3
+ "version": "0.24.13",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "module": "dist/index.js",
@@ -22,18 +22,19 @@
22
22
  "@openassistant/core": "0.5.14-alpha.2",
23
23
  "@openassistant/utils": "0.5.14-alpha.2",
24
24
  "@paralleldrive/cuid2": "^2.2.2",
25
- "@sqlrooms/data-table": "0.24.11",
26
- "@sqlrooms/duckdb": "0.24.11",
27
- "@sqlrooms/monaco-editor": "0.24.11",
28
- "@sqlrooms/room-config": "0.24.11",
29
- "@sqlrooms/room-shell": "0.24.11",
30
- "@sqlrooms/ui": "0.24.11",
31
- "@sqlrooms/utils": "0.24.11",
25
+ "@sqlrooms/data-table": "0.24.13",
26
+ "@sqlrooms/duckdb": "0.24.13",
27
+ "@sqlrooms/monaco-editor": "0.24.13",
28
+ "@sqlrooms/room-config": "0.24.13",
29
+ "@sqlrooms/room-shell": "0.24.13",
30
+ "@sqlrooms/ui": "0.24.13",
31
+ "@sqlrooms/utils": "0.24.13",
32
32
  "ai": "^4.3.19",
33
33
  "immer": "^10.1.1",
34
34
  "lucide-react": "^0.475.0",
35
35
  "react-markdown": "^9.1.0",
36
36
  "rehype-raw": "^7.0.0",
37
+ "remark-gfm": "^4.0.0",
37
38
  "zod": "^3.25.73"
38
39
  },
39
40
  "peerDependencies": {
@@ -47,5 +48,5 @@
47
48
  "typecheck": "tsc --noEmit",
48
49
  "typedoc": "typedoc"
49
50
  },
50
- "gitHead": "91b8ede86a0ab35d10267e6f414cd430d3632661"
51
+ "gitHead": "24b90fcf3302fe94164268ab901f5784c99ffb32"
51
52
  }