@sqlrooms/ai 0.7.0 → 0.8.1

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 (121) hide show
  1. package/README.md +377 -25
  2. package/dist/AiSlice.d.ts +489 -307
  3. package/dist/AiSlice.d.ts.map +1 -1
  4. package/dist/AiSlice.js +267 -177
  5. package/dist/AiSlice.js.map +1 -1
  6. package/dist/analysis.d.ts +25 -19
  7. package/dist/analysis.d.ts.map +1 -1
  8. package/dist/analysis.js +86 -145
  9. package/dist/analysis.js.map +1 -1
  10. package/dist/components/AnalysisAnswer.d.ts +14 -0
  11. package/dist/components/AnalysisAnswer.d.ts.map +1 -0
  12. package/dist/components/AnalysisAnswer.js +14 -0
  13. package/dist/components/AnalysisAnswer.js.map +1 -0
  14. package/dist/{AnalysisResult.d.ts → components/AnalysisResult.d.ts} +2 -1
  15. package/dist/components/AnalysisResult.d.ts.map +1 -0
  16. package/dist/components/AnalysisResult.js +46 -0
  17. package/dist/components/AnalysisResult.js.map +1 -0
  18. package/dist/components/AnalysisResultsContainer.d.ts +5 -0
  19. package/dist/components/AnalysisResultsContainer.d.ts.map +1 -0
  20. package/dist/components/AnalysisResultsContainer.js +27 -0
  21. package/dist/components/AnalysisResultsContainer.js.map +1 -0
  22. package/dist/components/ErrorMessage.d.ts +4 -0
  23. package/dist/components/ErrorMessage.d.ts.map +1 -0
  24. package/dist/components/ErrorMessage.js +7 -0
  25. package/dist/components/ErrorMessage.js.map +1 -0
  26. package/dist/components/MessageContainer.d.ts +10 -0
  27. package/dist/components/MessageContainer.d.ts.map +1 -0
  28. package/dist/components/MessageContainer.js +17 -0
  29. package/dist/components/MessageContainer.js.map +1 -0
  30. package/dist/components/ModelSelector.d.ts +13 -0
  31. package/dist/components/ModelSelector.d.ts.map +1 -0
  32. package/dist/components/ModelSelector.js +29 -0
  33. package/dist/components/ModelSelector.js.map +1 -0
  34. package/dist/components/QueryControls.d.ts +8 -0
  35. package/dist/components/QueryControls.d.ts.map +1 -0
  36. package/dist/components/QueryControls.js +45 -0
  37. package/dist/components/QueryControls.js.map +1 -0
  38. package/dist/components/SessionControls.d.ts +17 -0
  39. package/dist/components/SessionControls.d.ts.map +1 -0
  40. package/dist/components/SessionControls.js +20 -0
  41. package/dist/components/SessionControls.js.map +1 -0
  42. package/dist/components/session/DeleteSessionButton.d.ts +19 -0
  43. package/dist/components/session/DeleteSessionButton.d.ts.map +1 -0
  44. package/dist/components/session/DeleteSessionButton.js +54 -0
  45. package/dist/components/session/DeleteSessionButton.js.map +1 -0
  46. package/dist/components/session/DeleteSessionDialog.d.ts +27 -0
  47. package/dist/components/session/DeleteSessionDialog.d.ts.map +1 -0
  48. package/dist/components/session/DeleteSessionDialog.js +19 -0
  49. package/dist/components/session/DeleteSessionDialog.js.map +1 -0
  50. package/dist/components/session/SessionActions.d.ts +18 -0
  51. package/dist/components/session/SessionActions.d.ts.map +1 -0
  52. package/dist/components/session/SessionActions.js +19 -0
  53. package/dist/components/session/SessionActions.js.map +1 -0
  54. package/dist/components/session/SessionDropdown.d.ts +18 -0
  55. package/dist/components/session/SessionDropdown.d.ts.map +1 -0
  56. package/dist/components/session/SessionDropdown.js +21 -0
  57. package/dist/components/session/SessionDropdown.js.map +1 -0
  58. package/dist/components/session/SessionTitle.d.ts +18 -0
  59. package/dist/components/session/SessionTitle.d.ts.map +1 -0
  60. package/dist/components/session/SessionTitle.js +22 -0
  61. package/dist/components/session/SessionTitle.js.map +1 -0
  62. package/dist/components/session/SessionType.d.ts +24 -0
  63. package/dist/components/session/SessionType.d.ts.map +1 -0
  64. package/dist/components/session/SessionType.js +2 -0
  65. package/dist/components/session/SessionType.js.map +1 -0
  66. package/dist/components/session/index.d.ts +7 -0
  67. package/dist/components/session/index.d.ts.map +1 -0
  68. package/dist/components/session/index.js +7 -0
  69. package/dist/components/session/index.js.map +1 -0
  70. package/dist/components/tools/QueryToolResult.d.ts +7 -0
  71. package/dist/components/tools/QueryToolResult.d.ts.map +1 -0
  72. package/dist/components/tools/QueryToolResult.js +9 -0
  73. package/dist/components/tools/QueryToolResult.js.map +1 -0
  74. package/dist/components/tools/ToolResult.d.ts +9 -0
  75. package/dist/components/tools/ToolResult.d.ts.map +1 -0
  76. package/dist/components/tools/ToolResult.js +32 -0
  77. package/dist/components/tools/ToolResult.js.map +1 -0
  78. package/dist/components/tools/ToolResultErrorBoundary.d.ts +19 -0
  79. package/dist/components/tools/ToolResultErrorBoundary.d.ts.map +1 -0
  80. package/dist/components/tools/ToolResultErrorBoundary.js +23 -0
  81. package/dist/components/tools/ToolResultErrorBoundary.js.map +1 -0
  82. package/dist/hooks/useScrollToBottom.d.ts +82 -0
  83. package/dist/hooks/useScrollToBottom.d.ts.map +1 -0
  84. package/dist/hooks/useScrollToBottom.js +140 -0
  85. package/dist/hooks/useScrollToBottom.js.map +1 -0
  86. package/dist/index.d.ts +16 -5
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +15 -5
  89. package/dist/index.js.map +1 -1
  90. package/dist/schemas.d.ts +592 -201
  91. package/dist/schemas.d.ts.map +1 -1
  92. package/dist/schemas.js +36 -11
  93. package/dist/schemas.js.map +1 -1
  94. package/package.json +11 -10
  95. package/dist/AnalysisResult.d.ts.map +0 -1
  96. package/dist/AnalysisResult.js +0 -56
  97. package/dist/AnalysisResult.js.map +0 -1
  98. package/dist/AnalysisResultsContainer.d.ts +0 -2
  99. package/dist/AnalysisResultsContainer.d.ts.map +0 -1
  100. package/dist/AnalysisResultsContainer.js +0 -15
  101. package/dist/AnalysisResultsContainer.js.map +0 -1
  102. package/dist/QueryControls.d.ts +0 -6
  103. package/dist/QueryControls.d.ts.map +0 -1
  104. package/dist/QueryControls.js +0 -28
  105. package/dist/QueryControls.js.map +0 -1
  106. package/dist/QueryResult.d.ts +0 -9
  107. package/dist/QueryResult.d.ts.map +0 -1
  108. package/dist/QueryResult.js +0 -46
  109. package/dist/QueryResult.js.map +0 -1
  110. package/dist/ToolCall.d.ts +0 -66
  111. package/dist/ToolCall.d.ts.map +0 -1
  112. package/dist/ToolCall.js +0 -59
  113. package/dist/ToolCall.js.map +0 -1
  114. package/dist/ToolResult.d.ts +0 -10
  115. package/dist/ToolResult.d.ts.map +0 -1
  116. package/dist/ToolResult.js +0 -39
  117. package/dist/ToolResult.js.map +0 -1
  118. package/dist/hooks/use-scroll-to-bottom.d.ts +0 -7
  119. package/dist/hooks/use-scroll-to-bottom.d.ts.map +0 -1
  120. package/dist/hooks/use-scroll-to-bottom.js +0 -51
  121. package/dist/hooks/use-scroll-to-bottom.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"ToolResult.js","sourceRoot":"","sources":["../src/ToolResult.tsx"],"names":[],"mappings":"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","sourcesContent":["import {ToolResultSchema} from './schemas';\nimport {\n Badge,\n Button,\n Popover,\n PopoverContent,\n PopoverTrigger,\n cn,\n} from '@sqlrooms/ui';\nimport {CheckCircle2Icon, CodeIcon, XCircleIcon} from 'lucide-react';\nimport {ReactNode} from 'react';\nimport {\n AnalysisAnswer,\n ChartToolCall,\n isAnalysisAnswer,\n isChartToolParameters,\n} from './ToolCall';\nimport {isQueryToolParameters, QueryToolCall} from './ToolCall';\nimport React from 'react';\nimport {JsonMonacoEditor} from '@sqlrooms/monaco-editor';\n\ninterface ToolResultProps {\n toolResult: ToolResultSchema;\n customMessage?: ReactNode;\n}\n\nfunction getBorderColor(isSuccess: boolean, toolName: string) {\n if (!isSuccess) {\n return 'border-red-500';\n }\n switch (toolName) {\n case 'query':\n return 'border-green-500';\n case 'chart':\n return 'border-blue-500';\n case 'answer':\n return 'border-gray-500';\n default:\n return 'border-gray-500';\n }\n}\n\nexport const ToolResult: React.FC<ToolResultProps> = ({\n toolResult,\n customMessage,\n}) => {\n const {toolName, args, result} = toolResult;\n const isSuccess = result.success;\n\n return (\n <div\n className={cn(\n 'border-2 relative bg-gray-100 dark:bg-gray-900 px-5 py-6 rounded-md text-gray-700 dark:text-gray-300 text-xs',\n getBorderColor(isSuccess, toolName),\n )}\n >\n <Badge\n variant=\"secondary\"\n className={cn(\n 'text-xs absolute top-[-12px] left-2 dark:text-gray-100 text-gray-700 flex items-center gap-1 border',\n getBorderColor(isSuccess, toolName),\n )}\n >\n {isSuccess ? (\n <CheckCircle2Icon className=\"w-3 h-3 text-green-500\" />\n ) : (\n <XCircleIcon className=\"w-3 h-3 text-red-500\" />\n )}\n {toolName}\n </Badge>\n\n <div className=\"absolute top-2 right-2\">\n <Popover>\n <PopoverTrigger asChild>\n <Button variant=\"outline\" size=\"icon\" className=\"w-6 h-6\">\n <CodeIcon className=\"w-4 h-4\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className=\"w-[400px] max-h-[300px] overflow-auto p-4\"\n side=\"right\"\n align=\"start\"\n >\n <JsonMonacoEditor\n value={JSON.stringify(toolResult, 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 }}\n />\n </PopoverContent>\n </Popover>\n </div>\n\n <div className=\"flex flex-col gap-5\">\n {toolName === 'query' && isQueryToolParameters(args) ? (\n <QueryToolCall {...args} customMessage={customMessage} />\n ) : toolName === 'chart' && isChartToolParameters(args) ? (\n <ChartToolCall {...args} />\n ) : toolName === 'answer' && isAnalysisAnswer(result) ? (\n <AnalysisAnswer {...result} />\n ) : (\n Object.keys(args).length > 0 && (\n <JsonMonacoEditor\n value={JSON.stringify(args, null, 2)}\n readOnly={true}\n className=\"h-[150px]\"\n options={{\n minimap: {enabled: false},\n scrollBeyondLastLine: false,\n automaticLayout: true,\n folding: true,\n lineNumbers: false,\n }}\n />\n )\n )}\n {!result.success && (\n <div className=\"text-red-500 gap-2 flex flex-col\">\n <p className=\"text-sm font-bold\">Oops! Something went wrong...</p>\n <p className=\"text-xs\">{result.error}</p>\n </div>\n )}\n </div>\n </div>\n );\n};\n"]}
@@ -1,7 +0,0 @@
1
- import { type RefObject } from 'react';
2
- export declare function useScrollToBottom<T extends HTMLElement>(options?: MutationObserverInit): [RefObject<T>, RefObject<T>];
3
- export declare function useScrollToBottomButton(containerRef: RefObject<HTMLElement>): {
4
- showButton: boolean;
5
- scrollToBottom: () => void;
6
- };
7
- //# sourceMappingURL=use-scroll-to-bottom.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-scroll-to-bottom.d.ts","sourceRoot":"","sources":["../../src/hooks/use-scroll-to-bottom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,SAAS,EAAW,MAAM,OAAO,CAAC;AAElE,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,WAAW,EACrD,OAAO,GAAE,oBAKR,GACA,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAoB9B;AAED,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,SAAS,CAAC,WAAW,CAAC;;;EAiC3E"}
@@ -1,51 +0,0 @@
1
- import { useEffect, useRef, useState } from 'react';
2
- export function useScrollToBottom(options = {
3
- childList: true,
4
- subtree: true,
5
- characterData: true,
6
- // attributes: true,
7
- }) {
8
- const containerRef = useRef(null);
9
- const endRef = useRef(null);
10
- useEffect(() => {
11
- const container = containerRef.current;
12
- const end = endRef.current;
13
- if (container && end) {
14
- const observer = new MutationObserver(() => {
15
- end.scrollIntoView({ behavior: 'instant', block: 'end' });
16
- });
17
- observer.observe(container, options);
18
- return () => observer.disconnect();
19
- }
20
- }, [options]);
21
- return [containerRef, endRef];
22
- }
23
- export function useScrollToBottomButton(containerRef) {
24
- const [showButton, setShowButton] = useState(false);
25
- useEffect(() => {
26
- const container = containerRef.current;
27
- if (!container)
28
- return;
29
- const handleScroll = () => {
30
- const { scrollTop, scrollHeight, clientHeight } = container;
31
- // Only show if we're scrolled up more than 200px from the bottom
32
- const isNotAtBottom = scrollHeight - scrollTop - clientHeight > 200;
33
- setShowButton(isNotAtBottom);
34
- };
35
- container.addEventListener('scroll', handleScroll);
36
- // Initial check with a slight delay to ensure proper measurement
37
- const timeoutId = setTimeout(handleScroll, 100);
38
- return () => {
39
- container.removeEventListener('scroll', handleScroll);
40
- clearTimeout(timeoutId);
41
- };
42
- }, [containerRef]);
43
- const scrollToBottom = () => {
44
- containerRef.current?.scrollTo({
45
- top: containerRef.current.scrollHeight,
46
- behavior: 'smooth',
47
- });
48
- };
49
- return { showButton, scrollToBottom };
50
- }
51
- //# sourceMappingURL=use-scroll-to-bottom.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-scroll-to-bottom.js","sourceRoot":"","sources":["../../src/hooks/use-scroll-to-bottom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,MAAM,EAAkB,QAAQ,EAAC,MAAM,OAAO,CAAC;AAElE,MAAM,UAAU,iBAAiB,CAC/B,UAAgC;IAC9B,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,IAAI;IACb,aAAa,EAAE,IAAI;IACnB,oBAAoB;CACrB;IAED,MAAM,YAAY,GAAG,MAAM,CAAI,IAAI,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,MAAM,CAAI,IAAI,CAAC,CAAC;IAE/B,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC;QAE3B,IAAI,SAAS,IAAI,GAAG,EAAE,CAAC;YACrB,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,GAAG,EAAE;gBACzC,GAAG,CAAC,cAAc,CAAC,EAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAC,CAAC,CAAC;YAC1D,CAAC,CAAC,CAAC;YAEH,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAErC,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QACrC,CAAC;IACH,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,YAAoC;IAC1E,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEpD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC;QACvC,IAAI,CAAC,SAAS;YAAE,OAAO;QAEvB,MAAM,YAAY,GAAG,GAAG,EAAE;YACxB,MAAM,EAAC,SAAS,EAAE,YAAY,EAAE,YAAY,EAAC,GAAG,SAAS,CAAC;YAC1D,iEAAiE;YACjE,MAAM,aAAa,GAAG,YAAY,GAAG,SAAS,GAAG,YAAY,GAAG,GAAG,CAAC;YACpE,aAAa,CAAC,aAAa,CAAC,CAAC;QAC/B,CAAC,CAAC;QAEF,SAAS,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QAEnD,iEAAiE;QACjE,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;QAEhD,OAAO,GAAG,EAAE;YACV,SAAS,CAAC,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YACtD,YAAY,CAAC,SAAS,CAAC,CAAC;QAC1B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAEnB,MAAM,cAAc,GAAG,GAAG,EAAE;QAC1B,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC;YAC7B,GAAG,EAAE,YAAY,CAAC,OAAO,CAAC,YAAY;YACtC,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,EAAC,UAAU,EAAE,cAAc,EAAC,CAAC;AACtC,CAAC","sourcesContent":["import {useEffect, useRef, type RefObject, useState} from 'react';\n\nexport function useScrollToBottom<T extends HTMLElement>(\n options: MutationObserverInit = {\n childList: true,\n subtree: true,\n characterData: true,\n // attributes: true,\n },\n): [RefObject<T>, RefObject<T>] {\n const containerRef = useRef<T>(null);\n const endRef = useRef<T>(null);\n\n useEffect(() => {\n const container = containerRef.current;\n const end = endRef.current;\n\n if (container && end) {\n const observer = new MutationObserver(() => {\n end.scrollIntoView({behavior: 'instant', block: 'end'});\n });\n\n observer.observe(container, options);\n\n return () => observer.disconnect();\n }\n }, [options]);\n\n return [containerRef, endRef];\n}\n\nexport function useScrollToBottomButton(containerRef: RefObject<HTMLElement>) {\n const [showButton, setShowButton] = useState(false);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const handleScroll = () => {\n const {scrollTop, scrollHeight, clientHeight} = container;\n // Only show if we're scrolled up more than 200px from the bottom\n const isNotAtBottom = scrollHeight - scrollTop - clientHeight > 200;\n setShowButton(isNotAtBottom);\n };\n\n container.addEventListener('scroll', handleScroll);\n\n // Initial check with a slight delay to ensure proper measurement\n const timeoutId = setTimeout(handleScroll, 100);\n\n return () => {\n container.removeEventListener('scroll', handleScroll);\n clearTimeout(timeoutId);\n };\n }, [containerRef]);\n\n const scrollToBottom = () => {\n containerRef.current?.scrollTo({\n top: containerRef.current.scrollHeight,\n behavior: 'smooth',\n });\n };\n\n return {showButton, scrollToBottom};\n}\n"]}