@sqlrooms/ai-core 0.26.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +9 -0
- package/README.md +488 -0
- package/dist/AiSlice.d.ts +52 -0
- package/dist/AiSlice.d.ts.map +1 -0
- package/dist/AiSlice.js +367 -0
- package/dist/AiSlice.js.map +1 -0
- package/dist/analysis.d.ts +51 -0
- package/dist/analysis.d.ts.map +1 -0
- package/dist/analysis.js +43 -0
- package/dist/analysis.js.map +1 -0
- package/dist/components/AnalysisAnswer.d.ts +15 -0
- package/dist/components/AnalysisAnswer.d.ts.map +1 -0
- package/dist/components/AnalysisAnswer.js +102 -0
- package/dist/components/AnalysisAnswer.js.map +1 -0
- package/dist/components/AnalysisResult.d.ts +22 -0
- package/dist/components/AnalysisResult.d.ts.map +1 -0
- package/dist/components/AnalysisResult.js +39 -0
- package/dist/components/AnalysisResult.js.map +1 -0
- package/dist/components/AnalysisResultsContainer.d.ts +5 -0
- package/dist/components/AnalysisResultsContainer.d.ts.map +1 -0
- package/dist/components/AnalysisResultsContainer.js +26 -0
- package/dist/components/AnalysisResultsContainer.js.map +1 -0
- package/dist/components/ErrorMessage.d.ts +4 -0
- package/dist/components/ErrorMessage.d.ts.map +1 -0
- package/dist/components/ErrorMessage.js +8 -0
- package/dist/components/ErrorMessage.js.map +1 -0
- package/dist/components/MessageContainer.d.ts +10 -0
- package/dist/components/MessageContainer.d.ts.map +1 -0
- package/dist/components/MessageContainer.js +9 -0
- package/dist/components/MessageContainer.js.map +1 -0
- package/dist/components/ModelSelector.d.ts +13 -0
- package/dist/components/ModelSelector.d.ts.map +1 -0
- package/dist/components/ModelSelector.js +34 -0
- package/dist/components/ModelSelector.js.map +1 -0
- package/dist/components/QueryControls.d.ts +10 -0
- package/dist/components/QueryControls.d.ts.map +1 -0
- package/dist/components/QueryControls.js +52 -0
- package/dist/components/QueryControls.js.map +1 -0
- package/dist/components/SessionControls.d.ts +17 -0
- package/dist/components/SessionControls.d.ts.map +1 -0
- package/dist/components/SessionControls.js +20 -0
- package/dist/components/SessionControls.js.map +1 -0
- package/dist/components/session/DeleteSessionButton.d.ts +19 -0
- package/dist/components/session/DeleteSessionButton.d.ts.map +1 -0
- package/dist/components/session/DeleteSessionButton.js +54 -0
- package/dist/components/session/DeleteSessionButton.js.map +1 -0
- package/dist/components/session/DeleteSessionDialog.d.ts +27 -0
- package/dist/components/session/DeleteSessionDialog.d.ts.map +1 -0
- package/dist/components/session/DeleteSessionDialog.js +19 -0
- package/dist/components/session/DeleteSessionDialog.js.map +1 -0
- package/dist/components/session/SessionActions.d.ts +18 -0
- package/dist/components/session/SessionActions.d.ts.map +1 -0
- package/dist/components/session/SessionActions.js +19 -0
- package/dist/components/session/SessionActions.js.map +1 -0
- package/dist/components/session/SessionDropdown.d.ts +18 -0
- package/dist/components/session/SessionDropdown.d.ts.map +1 -0
- package/dist/components/session/SessionDropdown.js +21 -0
- package/dist/components/session/SessionDropdown.js.map +1 -0
- package/dist/components/session/SessionTitle.d.ts +18 -0
- package/dist/components/session/SessionTitle.d.ts.map +1 -0
- package/dist/components/session/SessionTitle.js +22 -0
- package/dist/components/session/SessionTitle.js.map +1 -0
- package/dist/components/session/SessionType.d.ts +24 -0
- package/dist/components/session/SessionType.d.ts.map +1 -0
- package/dist/components/session/SessionType.js +2 -0
- package/dist/components/session/SessionType.js.map +1 -0
- package/dist/components/session/index.d.ts +7 -0
- package/dist/components/session/index.d.ts.map +1 -0
- package/dist/components/session/index.js +7 -0
- package/dist/components/session/index.js.map +1 -0
- package/dist/components/tools/ToolErrorMessage.d.ts +39 -0
- package/dist/components/tools/ToolErrorMessage.d.ts.map +1 -0
- package/dist/components/tools/ToolErrorMessage.js +20 -0
- package/dist/components/tools/ToolErrorMessage.js.map +1 -0
- package/dist/components/tools/ToolResult.d.ts +11 -0
- package/dist/components/tools/ToolResult.d.ts.map +1 -0
- package/dist/components/tools/ToolResult.js +29 -0
- package/dist/components/tools/ToolResult.js.map +1 -0
- package/dist/components/tools/ToolResultErrorBoundary.d.ts +19 -0
- package/dist/components/tools/ToolResultErrorBoundary.d.ts.map +1 -0
- package/dist/components/tools/ToolResultErrorBoundary.js +24 -0
- package/dist/components/tools/ToolResultErrorBoundary.js.map +1 -0
- package/dist/hasAiSettingsConfig.d.ts +13 -0
- package/dist/hasAiSettingsConfig.d.ts.map +1 -0
- package/dist/hasAiSettingsConfig.js +16 -0
- package/dist/hasAiSettingsConfig.js.map +1 -0
- package/dist/hooks/useScrollToBottom.d.ts +82 -0
- package/dist/hooks/useScrollToBottom.d.ts.map +1 -0
- package/dist/hooks/useScrollToBottom.js +142 -0
- package/dist/hooks/useScrollToBottom.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/utils.d.ts +15 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +31 -0
- package/dist/utils.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
interface ScrollToBottomResult<T extends HTMLElement | null> {
|
|
3
|
+
showScrollButton: boolean;
|
|
4
|
+
scrollToBottom: () => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* A React hook that provides automatic scrolling behavior for containers with dynamic content.
|
|
8
|
+
*
|
|
9
|
+
* This hook helps manage scroll behavior in containers where content is being added dynamically,
|
|
10
|
+
* such as chat interfaces or logs. It automatically scrolls to the bottom when new content is added
|
|
11
|
+
* if the user was already at the bottom, and provides a function to manually scroll to the bottom.
|
|
12
|
+
*
|
|
13
|
+
* @template T - The type of HTMLElement for the container and end references
|
|
14
|
+
*
|
|
15
|
+
* @param options - Configuration options
|
|
16
|
+
* @param options.dataToObserve - The data to observe for changes (messages, items, etc.)
|
|
17
|
+
* @param options.containerRef - Reference to the scrollable container element
|
|
18
|
+
* @param options.endRef - Reference to an element at the end of the content
|
|
19
|
+
* @param options.scrollOnInitialLoad - Whether to scroll to bottom on initial load (default: true)
|
|
20
|
+
*
|
|
21
|
+
* @returns An object containing:
|
|
22
|
+
* - showScrollButton: Boolean indicating if the "scroll to bottom" button should be shown
|
|
23
|
+
* - scrollToBottom: Function to programmatically scroll to the bottom
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* import { useRef } from 'react';
|
|
28
|
+
* import { useScrollToBottom } from './use-scroll-to-bottom';
|
|
29
|
+
*
|
|
30
|
+
* function ChatContainer({ messages }) {
|
|
31
|
+
* const containerRef = useRef<HTMLDivElement>(null);
|
|
32
|
+
* const endRef = useRef<HTMLDivElement>(null);
|
|
33
|
+
*
|
|
34
|
+
* const { showScrollButton, scrollToBottom } = useScrollToBottom({
|
|
35
|
+
* dataToObserve: messages,
|
|
36
|
+
* containerRef,
|
|
37
|
+
* endRef,
|
|
38
|
+
* scrollOnInitialLoad: false // Disable scrolling on initial load
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* return (
|
|
42
|
+
* <div className="relative h-[500px]">
|
|
43
|
+
* <div ref={containerRef} className="h-full overflow-y-auto p-4">
|
|
44
|
+
* {messages.map((message) => (
|
|
45
|
+
* <div key={message.id} className="mb-4">
|
|
46
|
+
* {message.text}
|
|
47
|
+
* </div>
|
|
48
|
+
* ))}
|
|
49
|
+
* <div ref={endRef} />
|
|
50
|
+
* </div>
|
|
51
|
+
*
|
|
52
|
+
* {showScrollButton && (
|
|
53
|
+
* <button
|
|
54
|
+
* onClick={scrollToBottom}
|
|
55
|
+
* className="absolute bottom-4 right-4 rounded-full bg-blue-500 p-2"
|
|
56
|
+
* >
|
|
57
|
+
* ↓
|
|
58
|
+
* </button>
|
|
59
|
+
* )}
|
|
60
|
+
* </div>
|
|
61
|
+
* );
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare function useScrollToBottom<T extends HTMLElement | null>({
|
|
66
|
+
/**
|
|
67
|
+
* The data to observe. Can be an array of items or a single item.
|
|
68
|
+
* When the data changes, the hook will scroll to the bottom of the container.
|
|
69
|
+
*/
|
|
70
|
+
dataToObserve, containerRef, endRef,
|
|
71
|
+
/**
|
|
72
|
+
* Whether to scroll to bottom on initial load.
|
|
73
|
+
* @default false
|
|
74
|
+
*/
|
|
75
|
+
scrollOnInitialLoad, }: {
|
|
76
|
+
dataToObserve: unknown;
|
|
77
|
+
containerRef: RefObject<T | null>;
|
|
78
|
+
endRef: RefObject<T | null>;
|
|
79
|
+
scrollOnInitialLoad?: boolean;
|
|
80
|
+
}): ScrollToBottomResult<T>;
|
|
81
|
+
export {};
|
|
82
|
+
//# sourceMappingURL=useScrollToBottom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useScrollToBottom.d.ts","sourceRoot":"","sources":["../../src/hooks/useScrollToBottom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,SAAS,EAAwB,MAAM,OAAO,CAAC;AAE/E,UAAU,oBAAoB,CAAC,CAAC,SAAS,WAAW,GAAG,IAAI;IACzD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,WAAW,GAAG,IAAI,EAAE;AAC9D;;;GAGG;AACH,aAAa,EACb,YAAY,EACZ,MAAM;AACN;;;GAGG;AACH,mBAA2B,GAC5B,EAAE;IACD,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAClC,MAAM,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,GAAG,oBAAoB,CAAC,CAAC,CAAC,CA+E1B"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { useEffect, useRef, useState, useCallback } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Only show button and auto-scroll if we're scrolled up more
|
|
4
|
+
* than {AT_BOTTOM_TOLERANCE}px from the bottom.
|
|
5
|
+
*/
|
|
6
|
+
const AT_BOTTOM_TOLERANCE = 100;
|
|
7
|
+
/**
|
|
8
|
+
* A React hook that provides automatic scrolling behavior for containers with dynamic content.
|
|
9
|
+
*
|
|
10
|
+
* This hook helps manage scroll behavior in containers where content is being added dynamically,
|
|
11
|
+
* such as chat interfaces or logs. It automatically scrolls to the bottom when new content is added
|
|
12
|
+
* if the user was already at the bottom, and provides a function to manually scroll to the bottom.
|
|
13
|
+
*
|
|
14
|
+
* @template T - The type of HTMLElement for the container and end references
|
|
15
|
+
*
|
|
16
|
+
* @param options - Configuration options
|
|
17
|
+
* @param options.dataToObserve - The data to observe for changes (messages, items, etc.)
|
|
18
|
+
* @param options.containerRef - Reference to the scrollable container element
|
|
19
|
+
* @param options.endRef - Reference to an element at the end of the content
|
|
20
|
+
* @param options.scrollOnInitialLoad - Whether to scroll to bottom on initial load (default: true)
|
|
21
|
+
*
|
|
22
|
+
* @returns An object containing:
|
|
23
|
+
* - showScrollButton: Boolean indicating if the "scroll to bottom" button should be shown
|
|
24
|
+
* - scrollToBottom: Function to programmatically scroll to the bottom
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* import { useRef } from 'react';
|
|
29
|
+
* import { useScrollToBottom } from './use-scroll-to-bottom';
|
|
30
|
+
*
|
|
31
|
+
* function ChatContainer({ messages }) {
|
|
32
|
+
* const containerRef = useRef<HTMLDivElement>(null);
|
|
33
|
+
* const endRef = useRef<HTMLDivElement>(null);
|
|
34
|
+
*
|
|
35
|
+
* const { showScrollButton, scrollToBottom } = useScrollToBottom({
|
|
36
|
+
* dataToObserve: messages,
|
|
37
|
+
* containerRef,
|
|
38
|
+
* endRef,
|
|
39
|
+
* scrollOnInitialLoad: false // Disable scrolling on initial load
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* return (
|
|
43
|
+
* <div className="relative h-[500px]">
|
|
44
|
+
* <div ref={containerRef} className="h-full overflow-y-auto p-4">
|
|
45
|
+
* {messages.map((message) => (
|
|
46
|
+
* <div key={message.id} className="mb-4">
|
|
47
|
+
* {message.text}
|
|
48
|
+
* </div>
|
|
49
|
+
* ))}
|
|
50
|
+
* <div ref={endRef} />
|
|
51
|
+
* </div>
|
|
52
|
+
*
|
|
53
|
+
* {showScrollButton && (
|
|
54
|
+
* <button
|
|
55
|
+
* onClick={scrollToBottom}
|
|
56
|
+
* className="absolute bottom-4 right-4 rounded-full bg-blue-500 p-2"
|
|
57
|
+
* >
|
|
58
|
+
* ↓
|
|
59
|
+
* </button>
|
|
60
|
+
* )}
|
|
61
|
+
* </div>
|
|
62
|
+
* );
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export function useScrollToBottom({
|
|
67
|
+
/**
|
|
68
|
+
* The data to observe. Can be an array of items or a single item.
|
|
69
|
+
* When the data changes, the hook will scroll to the bottom of the container.
|
|
70
|
+
*/
|
|
71
|
+
dataToObserve, containerRef, endRef,
|
|
72
|
+
/**
|
|
73
|
+
* Whether to scroll to bottom on initial load.
|
|
74
|
+
* @default false
|
|
75
|
+
*/
|
|
76
|
+
scrollOnInitialLoad = false, }) {
|
|
77
|
+
const [showScrollButton, setShowButton] = useState(false);
|
|
78
|
+
// Track if user was at bottom before content changes
|
|
79
|
+
const wasAtBottomRef = useRef(scrollOnInitialLoad);
|
|
80
|
+
// Track if this is the initial load
|
|
81
|
+
const isInitialLoadRef = useRef(true);
|
|
82
|
+
// Check if the container is scrolled to the bottom
|
|
83
|
+
const checkIfAtBottom = useCallback((container) => {
|
|
84
|
+
if (!container)
|
|
85
|
+
return false;
|
|
86
|
+
const { scrollTop, scrollHeight, clientHeight } = container;
|
|
87
|
+
return scrollHeight - scrollTop - clientHeight <= AT_BOTTOM_TOLERANCE;
|
|
88
|
+
}, []);
|
|
89
|
+
// Extracted reusable handleScroll function
|
|
90
|
+
const onScroll = useCallback(() => {
|
|
91
|
+
const container = containerRef.current;
|
|
92
|
+
if (!container)
|
|
93
|
+
return;
|
|
94
|
+
const isAtBottom = checkIfAtBottom(container);
|
|
95
|
+
// Update wasAtBottom state for next content change
|
|
96
|
+
wasAtBottomRef.current = isAtBottom;
|
|
97
|
+
// Show button only if not at bottom
|
|
98
|
+
setShowButton(!isAtBottom);
|
|
99
|
+
}, [checkIfAtBottom, containerRef]);
|
|
100
|
+
// Handle new content being added
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
if (!dataToObserve)
|
|
103
|
+
return;
|
|
104
|
+
const container = containerRef.current;
|
|
105
|
+
const end = endRef.current;
|
|
106
|
+
if (container && end && wasAtBottomRef.current) {
|
|
107
|
+
// Only scroll if this is not the initial load or if scrollOnInitialLoad is true
|
|
108
|
+
if (!isInitialLoadRef.current || scrollOnInitialLoad) {
|
|
109
|
+
end.scrollIntoView({ behavior: 'instant', block: 'end' });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Mark that initial load is complete
|
|
113
|
+
isInitialLoadRef.current = false;
|
|
114
|
+
// After content change, check scroll position again
|
|
115
|
+
onScroll();
|
|
116
|
+
}, [containerRef, dataToObserve, endRef, onScroll, scrollOnInitialLoad]);
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
const container = containerRef.current;
|
|
119
|
+
if (!container)
|
|
120
|
+
return;
|
|
121
|
+
container.addEventListener('scroll', onScroll);
|
|
122
|
+
// Initial check with a slight delay to ensure proper measurement
|
|
123
|
+
const timeoutId = setTimeout(onScroll, 100);
|
|
124
|
+
return () => {
|
|
125
|
+
container.removeEventListener('scroll', onScroll);
|
|
126
|
+
clearTimeout(timeoutId);
|
|
127
|
+
};
|
|
128
|
+
}, [containerRef, onScroll]);
|
|
129
|
+
const scrollToBottom = () => {
|
|
130
|
+
if (containerRef.current) {
|
|
131
|
+
containerRef.current.scrollTo({
|
|
132
|
+
top: containerRef.current.scrollHeight,
|
|
133
|
+
behavior: 'smooth',
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
return {
|
|
138
|
+
showScrollButton,
|
|
139
|
+
scrollToBottom,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=useScrollToBottom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useScrollToBottom.js","sourceRoot":"","sources":["../../src/hooks/useScrollToBottom.ts"],"names":[],"mappings":"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","sourcesContent":["import {useEffect, useRef, type RefObject, useState, useCallback} from 'react';\n\ninterface ScrollToBottomResult<T extends HTMLElement | null> {\n showScrollButton: boolean;\n scrollToBottom: () => void;\n}\n\n/**\n * Only show button and auto-scroll if we're scrolled up more\n * than {AT_BOTTOM_TOLERANCE}px from the bottom.\n */\nconst AT_BOTTOM_TOLERANCE = 100;\n\n/**\n * A React hook that provides automatic scrolling behavior for containers with dynamic content.\n *\n * This hook helps manage scroll behavior in containers where content is being added dynamically,\n * such as chat interfaces or logs. It automatically scrolls to the bottom when new content is added\n * if the user was already at the bottom, and provides a function to manually scroll to the bottom.\n *\n * @template T - The type of HTMLElement for the container and end references\n *\n * @param options - Configuration options\n * @param options.dataToObserve - The data to observe for changes (messages, items, etc.)\n * @param options.containerRef - Reference to the scrollable container element\n * @param options.endRef - Reference to an element at the end of the content\n * @param options.scrollOnInitialLoad - Whether to scroll to bottom on initial load (default: true)\n *\n * @returns An object containing:\n * - showScrollButton: Boolean indicating if the \"scroll to bottom\" button should be shown\n * - scrollToBottom: Function to programmatically scroll to the bottom\n *\n * @example\n * ```tsx\n * import { useRef } from 'react';\n * import { useScrollToBottom } from './use-scroll-to-bottom';\n *\n * function ChatContainer({ messages }) {\n * const containerRef = useRef<HTMLDivElement>(null);\n * const endRef = useRef<HTMLDivElement>(null);\n *\n * const { showScrollButton, scrollToBottom } = useScrollToBottom({\n * dataToObserve: messages,\n * containerRef,\n * endRef,\n * scrollOnInitialLoad: false // Disable scrolling on initial load\n * });\n *\n * return (\n * <div className=\"relative h-[500px]\">\n * <div ref={containerRef} className=\"h-full overflow-y-auto p-4\">\n * {messages.map((message) => (\n * <div key={message.id} className=\"mb-4\">\n * {message.text}\n * </div>\n * ))}\n * <div ref={endRef} />\n * </div>\n *\n * {showScrollButton && (\n * <button\n * onClick={scrollToBottom}\n * className=\"absolute bottom-4 right-4 rounded-full bg-blue-500 p-2\"\n * >\n * ↓\n * </button>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function useScrollToBottom<T extends HTMLElement | null>({\n /**\n * The data to observe. Can be an array of items or a single item.\n * When the data changes, the hook will scroll to the bottom of the container.\n */\n dataToObserve,\n containerRef,\n endRef,\n /**\n * Whether to scroll to bottom on initial load.\n * @default false\n */\n scrollOnInitialLoad = false,\n}: {\n dataToObserve: unknown;\n containerRef: RefObject<T | null>;\n endRef: RefObject<T | null>;\n scrollOnInitialLoad?: boolean;\n}): ScrollToBottomResult<T> {\n const [showScrollButton, setShowButton] = useState(false);\n\n // Track if user was at bottom before content changes\n const wasAtBottomRef = useRef(scrollOnInitialLoad);\n\n // Track if this is the initial load\n const isInitialLoadRef = useRef(true);\n\n // Check if the container is scrolled to the bottom\n const checkIfAtBottom = useCallback((container: T) => {\n if (!container) return false;\n const {scrollTop, scrollHeight, clientHeight} = container;\n return scrollHeight - scrollTop - clientHeight <= AT_BOTTOM_TOLERANCE;\n }, []);\n\n // Extracted reusable handleScroll function\n const onScroll = useCallback(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const isAtBottom = checkIfAtBottom(container);\n\n // Update wasAtBottom state for next content change\n wasAtBottomRef.current = isAtBottom;\n\n // Show button only if not at bottom\n setShowButton(!isAtBottom);\n }, [checkIfAtBottom, containerRef]);\n\n // Handle new content being added\n useEffect(() => {\n if (!dataToObserve) return;\n\n const container = containerRef.current;\n const end = endRef.current;\n\n if (container && end && wasAtBottomRef.current) {\n // Only scroll if this is not the initial load or if scrollOnInitialLoad is true\n if (!isInitialLoadRef.current || scrollOnInitialLoad) {\n end.scrollIntoView({behavior: 'instant', block: 'end'});\n }\n }\n\n // Mark that initial load is complete\n isInitialLoadRef.current = false;\n\n // After content change, check scroll position again\n onScroll();\n }, [containerRef, dataToObserve, endRef, onScroll, scrollOnInitialLoad]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n container.addEventListener('scroll', onScroll);\n\n // Initial check with a slight delay to ensure proper measurement\n const timeoutId = setTimeout(onScroll, 100);\n\n return () => {\n container.removeEventListener('scroll', onScroll);\n clearTimeout(timeoutId);\n };\n }, [containerRef, onScroll]);\n\n const scrollToBottom = () => {\n if (containerRef.current) {\n containerRef.current.scrollTo({\n top: containerRef.current.scrollHeight,\n behavior: 'smooth',\n });\n }\n };\n\n return {\n showScrollButton,\n scrollToBottom,\n };\n}\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {@include ../README.md}
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
export { createAiSlice, useStoreWithAi } from './AiSlice';
|
|
6
|
+
export type { AiSliceState } from './AiSlice';
|
|
7
|
+
export { AnalysisResultsContainer } from './components/AnalysisResultsContainer';
|
|
8
|
+
export { AnalysisResult } from './components/AnalysisResult';
|
|
9
|
+
export { useScrollToBottom } from './hooks/useScrollToBottom';
|
|
10
|
+
export type { AiSliceTool } from './AiSlice';
|
|
11
|
+
export { ModelSelector } from './components/ModelSelector';
|
|
12
|
+
export { SessionControls } from './components/SessionControls';
|
|
13
|
+
export { QueryControls } from './components/QueryControls';
|
|
14
|
+
export { DeleteSessionDialog } from './components/session/DeleteSessionDialog';
|
|
15
|
+
export { SessionActions } from './components/session/SessionActions';
|
|
16
|
+
export { SessionDropdown } from './components/session/SessionDropdown';
|
|
17
|
+
export { SessionTitle } from './components/session/SessionTitle';
|
|
18
|
+
export type { SessionType } from './components/session/SessionType';
|
|
19
|
+
export { ToolErrorMessage } from './components/tools/ToolErrorMessage';
|
|
20
|
+
export { AiSliceConfig, createDefaultAiConfig } from '@sqlrooms/ai-config';
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,aAAa,EAAE,cAAc,EAAC,MAAM,WAAW,CAAC;AAExD,YAAY,EAAC,YAAY,EAAC,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAC,wBAAwB,EAAC,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAC,iBAAiB,EAAC,MAAM,2BAA2B,CAAC;AAC5D,YAAY,EAAC,WAAW,EAAC,MAAM,WAAW,CAAC;AAE3C,OAAO,EAAC,aAAa,EAAC,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAC,aAAa,EAAC,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAC,mBAAmB,EAAC,MAAM,0CAA0C,CAAC;AAC7E,OAAO,EAAC,cAAc,EAAC,MAAM,qCAAqC,CAAC;AACnE,OAAO,EAAC,eAAe,EAAC,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAC,YAAY,EAAC,MAAM,mCAAmC,CAAC;AAC/D,YAAY,EAAC,WAAW,EAAC,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAC,gBAAgB,EAAC,MAAM,qCAAqC,CAAC;AAErE,OAAO,EAAC,aAAa,EAAE,qBAAqB,EAAC,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {@include ../README.md}
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
export { createAiSlice, useStoreWithAi } from './AiSlice';
|
|
6
|
+
export { AnalysisResultsContainer } from './components/AnalysisResultsContainer';
|
|
7
|
+
export { AnalysisResult } from './components/AnalysisResult';
|
|
8
|
+
export { useScrollToBottom } from './hooks/useScrollToBottom';
|
|
9
|
+
export { ModelSelector } from './components/ModelSelector';
|
|
10
|
+
export { SessionControls } from './components/SessionControls';
|
|
11
|
+
export { QueryControls } from './components/QueryControls';
|
|
12
|
+
export { DeleteSessionDialog } from './components/session/DeleteSessionDialog';
|
|
13
|
+
export { SessionActions } from './components/session/SessionActions';
|
|
14
|
+
export { SessionDropdown } from './components/session/SessionDropdown';
|
|
15
|
+
export { SessionTitle } from './components/session/SessionTitle';
|
|
16
|
+
export { ToolErrorMessage } from './components/tools/ToolErrorMessage';
|
|
17
|
+
export { AiSliceConfig, createDefaultAiConfig } from '@sqlrooms/ai-config';
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,aAAa,EAAE,cAAc,EAAC,MAAM,WAAW,CAAC;AAGxD,OAAO,EAAC,wBAAwB,EAAC,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAC,iBAAiB,EAAC,MAAM,2BAA2B,CAAC;AAG5D,OAAO,EAAC,aAAa,EAAC,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAC,aAAa,EAAC,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAC,mBAAmB,EAAC,MAAM,0CAA0C,CAAC;AAC7E,OAAO,EAAC,cAAc,EAAC,MAAM,qCAAqC,CAAC;AACnE,OAAO,EAAC,eAAe,EAAC,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAC,YAAY,EAAC,MAAM,mCAAmC,CAAC;AAE/D,OAAO,EAAC,gBAAgB,EAAC,MAAM,qCAAqC,CAAC;AAErE,OAAO,EAAC,aAAa,EAAE,qBAAqB,EAAC,MAAM,qBAAqB,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport {createAiSlice, useStoreWithAi} from './AiSlice';\n\nexport type {AiSliceState} from './AiSlice';\nexport {AnalysisResultsContainer} from './components/AnalysisResultsContainer';\nexport {AnalysisResult} from './components/AnalysisResult';\nexport {useScrollToBottom} from './hooks/useScrollToBottom';\nexport type {AiSliceTool} from './AiSlice';\n\nexport {ModelSelector} from './components/ModelSelector';\nexport {SessionControls} from './components/SessionControls';\nexport {QueryControls} from './components/QueryControls';\nexport {DeleteSessionDialog} from './components/session/DeleteSessionDialog';\nexport {SessionActions} from './components/session/SessionActions';\nexport {SessionDropdown} from './components/session/SessionDropdown';\nexport {SessionTitle} from './components/session/SessionTitle';\nexport type {SessionType} from './components/session/SessionType';\nexport {ToolErrorMessage} from './components/tools/ToolErrorMessage';\n\nexport {AiSliceConfig, createDefaultAiConfig} from '@sqlrooms/ai-config';\n"]}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for AI Chat UI configuration
|
|
3
|
+
*/
|
|
4
|
+
import { AiSettingsSliceConfig } from '@sqlrooms/ai-config';
|
|
5
|
+
/**
|
|
6
|
+
* Extract models from aiSettings in the format expected by ModelSelector
|
|
7
|
+
* @param config - The AI model configuration
|
|
8
|
+
* @returns Array of models with provider, label, and value properties
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractModelsFromSettings(config: AiSettingsSliceConfig): Array<{
|
|
11
|
+
provider: string;
|
|
12
|
+
label: string;
|
|
13
|
+
value: string;
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAC,qBAAqB,EAAC,MAAM,qBAAqB,CAAC;AAE1D;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,qBAAqB,GAC5B,KAAK,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CA4BD"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for AI Chat UI configuration
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Extract models from aiSettings in the format expected by ModelSelector
|
|
6
|
+
* @param config - The AI model configuration
|
|
7
|
+
* @returns Array of models with provider, label, and value properties
|
|
8
|
+
*/
|
|
9
|
+
export function extractModelsFromSettings(config) {
|
|
10
|
+
const models = [];
|
|
11
|
+
// Extract models from providers
|
|
12
|
+
Object.entries(config.providers).forEach(([providerKey, provider]) => {
|
|
13
|
+
provider.models.forEach((model) => {
|
|
14
|
+
models.push({
|
|
15
|
+
provider: providerKey,
|
|
16
|
+
label: model.modelName,
|
|
17
|
+
value: model.modelName,
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
// Add custom models
|
|
22
|
+
config.customModels.forEach((customModel) => {
|
|
23
|
+
models.push({
|
|
24
|
+
provider: 'custom',
|
|
25
|
+
label: customModel.modelName,
|
|
26
|
+
value: customModel.modelName,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
return models;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAA6B;IAM7B,MAAM,MAAM,GAIP,EAAE,CAAC;IAER,gCAAgC;IAChC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,EAAE;QACnE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YAChC,MAAM,CAAC,IAAI,CAAC;gBACV,QAAQ,EAAE,WAAW;gBACrB,KAAK,EAAE,KAAK,CAAC,SAAS;gBACtB,KAAK,EAAE,KAAK,CAAC,SAAS;aACvB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,oBAAoB;IACpB,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE;QAC1C,MAAM,CAAC,IAAI,CAAC;YACV,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,WAAW,CAAC,SAAS;YAC5B,KAAK,EAAE,WAAW,CAAC,SAAS;SAC7B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["/**\n * Utility functions for AI Chat UI configuration\n */\n\nimport {AiSettingsSliceConfig} from '@sqlrooms/ai-config';\n\n/**\n * Extract models from aiSettings in the format expected by ModelSelector\n * @param config - The AI model configuration\n * @returns Array of models with provider, label, and value properties\n */\nexport function extractModelsFromSettings(\n config: AiSettingsSliceConfig,\n): Array<{\n provider: string;\n label: string;\n value: string;\n}> {\n const models: Array<{\n provider: string;\n label: string;\n value: string;\n }> = [];\n\n // Extract models from providers\n Object.entries(config.providers).forEach(([providerKey, provider]) => {\n provider.models.forEach((model) => {\n models.push({\n provider: providerKey,\n label: model.modelName,\n value: model.modelName,\n });\n });\n });\n\n // Add custom models\n config.customModels.forEach((customModel) => {\n models.push({\n provider: 'custom',\n label: customModel.modelName,\n value: customModel.modelName,\n });\n });\n\n return models;\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sqlrooms/ai-core",
|
|
3
|
+
"version": "0.26.0-rc.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"author": "Ilya Boyandin <ilya@boyandin.me>",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/sqlrooms/sqlrooms.git"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@ai-sdk/provider": "^1.1.3",
|
|
22
|
+
"@openassistant/core": "0.5.17",
|
|
23
|
+
"@openassistant/utils": "0.5.17",
|
|
24
|
+
"@paralleldrive/cuid2": "^2.2.2",
|
|
25
|
+
"@sqlrooms/ai-config": "0.26.0-rc.0",
|
|
26
|
+
"@sqlrooms/monaco-editor": "0.26.0-rc.0",
|
|
27
|
+
"@sqlrooms/room-config": "0.26.0-rc.0",
|
|
28
|
+
"@sqlrooms/room-store": "0.26.0-rc.0",
|
|
29
|
+
"@sqlrooms/ui": "0.26.0-rc.0",
|
|
30
|
+
"@sqlrooms/utils": "0.26.0-rc.0",
|
|
31
|
+
"ai": "^4.3.19",
|
|
32
|
+
"immer": "^10.1.1",
|
|
33
|
+
"lucide-react": "^0.475.0",
|
|
34
|
+
"react-markdown": "^10.1.0",
|
|
35
|
+
"rehype-raw": "^7.0.0",
|
|
36
|
+
"remark-gfm": "^4.0.0",
|
|
37
|
+
"zod": "^3.25.73"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"react": ">=18",
|
|
41
|
+
"react-dom": ">=18"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"dev": "tsc -w",
|
|
45
|
+
"build": "tsc",
|
|
46
|
+
"lint": "eslint .",
|
|
47
|
+
"typecheck": "tsc --noEmit",
|
|
48
|
+
"typedoc": "typedoc"
|
|
49
|
+
},
|
|
50
|
+
"gitHead": "05d355acee6ea65b33b09c6e49d7746ffacb866e"
|
|
51
|
+
}
|