@sqlrooms/ai-settings 0.29.0-rc.1 → 0.29.0-rc.2
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/README.md +1 -3
- package/dist/components/AiModelParameters.d.ts.map +1 -1
- package/dist/components/AiModelParameters.js +5 -13
- package/dist/components/AiModelParameters.js.map +1 -1
- package/dist/components/AiModelsSettings.d.ts.map +1 -1
- package/dist/components/AiModelsSettings.js +16 -37
- package/dist/components/AiModelsSettings.js.map +1 -1
- package/dist/components/AiProvidersSettings.d.ts.map +1 -1
- package/dist/components/AiProvidersSettings.js +4 -9
- package/dist/components/AiProvidersSettings.js.map +1 -1
- package/dist/components/AiSettingsPanel.js +1 -1
- package/dist/components/AiSettingsPanel.js.map +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -86,9 +86,7 @@ function MaxStepsControl() {
|
|
|
86
86
|
const maxSteps = useRoomStore(
|
|
87
87
|
(state) => state.aiSettings.config.modelParameters.maxSteps,
|
|
88
88
|
);
|
|
89
|
-
const setMaxSteps = useRoomStore(
|
|
90
|
-
(state) => state.aiSettings.setMaxSteps,
|
|
91
|
-
);
|
|
89
|
+
const setMaxSteps = useRoomStore((state) => state.aiSettings.setMaxSteps);
|
|
92
90
|
|
|
93
91
|
return (
|
|
94
92
|
<Button onClick={() => setMaxSteps(maxSteps + 5)}>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiModelParameters.d.ts","sourceRoot":"","sources":["../../src/components/AiModelParameters.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,EAAE,EAAS,MAAM,OAAO,CAAC;AAgBjC,MAAM,WAAW,sBAAsB;IACrC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,sBAAsB,
|
|
1
|
+
{"version":3,"file":"AiModelParameters.d.ts","sourceRoot":"","sources":["../../src/components/AiModelParameters.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,EAAE,EAAS,MAAM,OAAO,CAAC;AAgBjC,MAAM,WAAW,sBAAsB;IACrC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,sBAAsB,CA2LxD,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useRef } from 'react';
|
|
3
3
|
import { Sliders, Wrench, FileText, Upload, Eye } from 'lucide-react';
|
|
4
|
-
import { Textarea, Input, Button, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, useDisclosure,
|
|
4
|
+
import { Textarea, Input, Button, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, useDisclosure, toast, } from '@sqlrooms/ui';
|
|
5
5
|
import { useStoreWithAiSettings } from '../AiSettingsSlice';
|
|
6
6
|
export const AiModelParameters = ({ showViewInstructions = false, }) => {
|
|
7
7
|
const maxSteps = useStoreWithAiSettings((s) => s.aiSettings.config.modelParameters.maxSteps);
|
|
@@ -9,7 +9,6 @@ export const AiModelParameters = ({ showViewInstructions = false, }) => {
|
|
|
9
9
|
const additionalInstruction = useStoreWithAiSettings((s) => s.aiSettings.config.modelParameters.additionalInstruction);
|
|
10
10
|
const setAdditionalInstruction = useStoreWithAiSettings((s) => s.aiSettings.setAdditionalInstruction);
|
|
11
11
|
const fileInputRef = useRef(null);
|
|
12
|
-
const { toast } = useToast();
|
|
13
12
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
|
14
13
|
const handleMaxStepsChange = (value) => {
|
|
15
14
|
setMaxStepsAiChatUi(value);
|
|
@@ -30,37 +29,30 @@ export const AiModelParameters = ({ showViewInstructions = false, }) => {
|
|
|
30
29
|
.slice(file.name.lastIndexOf('.'));
|
|
31
30
|
if (!allowedTypes.includes(file.type) &&
|
|
32
31
|
!allowedExtensions.includes(fileExtension)) {
|
|
33
|
-
toast({
|
|
34
|
-
title: 'Invalid file type',
|
|
32
|
+
toast.error('Invalid file type', {
|
|
35
33
|
description: 'Please select a text file (.txt, .md, .json)',
|
|
36
|
-
variant: 'destructive',
|
|
37
34
|
});
|
|
38
35
|
return;
|
|
39
36
|
}
|
|
40
37
|
// Validate file size (max 1MB)
|
|
41
38
|
const maxSize = 1024 * 1024; // 1MB
|
|
42
39
|
if (file.size > maxSize) {
|
|
43
|
-
toast({
|
|
44
|
-
title: 'File too large',
|
|
40
|
+
toast.error('File too large', {
|
|
45
41
|
description: 'File size must be less than 1MB',
|
|
46
|
-
variant: 'destructive',
|
|
47
42
|
});
|
|
48
43
|
return;
|
|
49
44
|
}
|
|
50
45
|
try {
|
|
51
46
|
const text = await file.text();
|
|
52
47
|
setAdditionalInstruction(text);
|
|
53
|
-
toast({
|
|
54
|
-
title: 'File uploaded successfully',
|
|
48
|
+
toast.success('File uploaded successfully', {
|
|
55
49
|
description: 'System instructions have been updated from the uploaded file.',
|
|
56
50
|
});
|
|
57
51
|
}
|
|
58
52
|
catch (error) {
|
|
59
53
|
console.error('Error reading file:', error);
|
|
60
|
-
toast({
|
|
61
|
-
title: 'Error reading file',
|
|
54
|
+
toast.error('Error reading file', {
|
|
62
55
|
description: 'Please try again.',
|
|
63
|
-
variant: 'destructive',
|
|
64
56
|
});
|
|
65
57
|
}
|
|
66
58
|
// Reset the input so the same file can be selected again
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiModelParameters.js","sourceRoot":"","sources":["../../src/components/AiModelParameters.tsx"],"names":[],"mappings":"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","sourcesContent":["import {FC, useRef} from 'react';\nimport {Sliders, Wrench, FileText, Upload, Eye} from 'lucide-react';\nimport {\n Textarea,\n Input,\n Button,\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n useDisclosure,\n useToast,\n} from '@sqlrooms/ui';\nimport {useStoreWithAiSettings} from '../AiSettingsSlice';\n\nexport interface AiModelParametersProps {\n showViewInstructions?: boolean;\n}\n\nexport const AiModelParameters: FC<AiModelParametersProps> = ({\n showViewInstructions = false,\n}) => {\n const maxSteps = useStoreWithAiSettings(\n (s) => s.aiSettings.config.modelParameters.maxSteps,\n );\n const setMaxStepsAiChatUi = useStoreWithAiSettings(\n (s) => s.aiSettings.setMaxSteps,\n );\n\n const additionalInstruction = useStoreWithAiSettings(\n (s) => s.aiSettings.config.modelParameters.additionalInstruction,\n );\n const setAdditionalInstruction = useStoreWithAiSettings(\n (s) => s.aiSettings.setAdditionalInstruction,\n );\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const {toast} = useToast();\n\n const {isOpen, onOpen, onClose} = useDisclosure();\n\n const handleMaxStepsChange = (value: number) => {\n setMaxStepsAiChatUi(value);\n };\n\n const handleAdditionalInstructionChange = (value: string) => {\n setAdditionalInstruction(value);\n };\n\n const getFullInstructions = useStoreWithAiSettings(\n (s) => s.ai.getFullInstructions,\n );\n\n const handleFileUpload = async (\n event: React.ChangeEvent<HTMLInputElement>,\n ) => {\n const file = event.target.files?.[0];\n if (!file) return;\n\n // Validate file type\n const allowedTypes = ['text/plain', 'text/markdown', 'application/json'];\n const allowedExtensions = ['.txt', '.md', '.json', '.text'];\n const fileExtension = file.name\n .toLowerCase()\n .slice(file.name.lastIndexOf('.'));\n\n if (\n !allowedTypes.includes(file.type) &&\n !allowedExtensions.includes(fileExtension)\n ) {\n toast({\n title: 'Invalid file type',\n description: 'Please select a text file (.txt, .md, .json)',\n variant: 'destructive',\n });\n return;\n }\n\n // Validate file size (max 1MB)\n const maxSize = 1024 * 1024; // 1MB\n if (file.size > maxSize) {\n toast({\n title: 'File too large',\n description: 'File size must be less than 1MB',\n variant: 'destructive',\n });\n return;\n }\n\n try {\n const text = await file.text();\n setAdditionalInstruction(text);\n toast({\n title: 'File uploaded successfully',\n description:\n 'System instructions have been updated from the uploaded file.',\n });\n } catch (error) {\n console.error('Error reading file:', error);\n toast({\n title: 'Error reading file',\n description: 'Please try again.',\n variant: 'destructive',\n });\n }\n\n // Reset the input so the same file can be selected again\n if (fileInputRef.current) {\n fileInputRef.current.value = '';\n }\n };\n\n const handleUploadButtonClick = () => {\n fileInputRef.current?.click();\n };\n\n const handleViewFullInstructions = () => {\n onOpen();\n };\n\n return (\n <div className=\"space-y-2\">\n <label className=\"text-md flex items-center gap-2 pb-6 font-medium\">\n <Sliders className=\"h-4 w-4\" />\n Model Parameters\n </label>\n <div className=\"grid grid-cols-1 gap-4\">\n {/* Max Steps */}\n <div className=\"space-y-2\">\n <label className=\"flex items-center gap-2 text-sm font-medium\">\n <Wrench className=\"h-4 w-4\" />\n Max Tool Steps\n </label>\n <div className=\"flex items-center gap-2\">\n <Input\n type=\"number\"\n min=\"1\"\n max=\"20\"\n step=\"1\"\n value={maxSteps}\n onChange={(e) =>\n handleMaxStepsChange(parseInt(e.target.value) || 1)\n }\n className=\"flex-1\"\n />\n </div>\n </div>\n\n {/* Additional Instruction */}\n <div className=\"space-y-2\">\n <label className=\"flex items-center gap-2 text-sm font-medium\">\n <FileText className=\"h-4 w-4\" />\n Additional Instructions\n </label>\n <Textarea\n value={additionalInstruction}\n onChange={(e) => handleAdditionalInstructionChange(e.target.value)}\n placeholder=\"Enter custom system instructions for the AI model...\"\n className=\"min-h-[80px] resize-y\"\n autoResize={false}\n />\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleUploadButtonClick}\n className=\"flex items-center gap-2\"\n >\n <Upload className=\"h-4 w-4\" />\n Upload File\n </Button>\n {showViewInstructions && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleViewFullInstructions}\n className=\"flex items-center gap-2\"\n >\n <Eye className=\"h-4 w-4\" />\n View Instructions\n </Button>\n )}\n </div>\n <Input\n ref={fileInputRef}\n type=\"file\"\n accept=\".txt,.md,.json,.text,text/plain,text/markdown,application/json\"\n onChange={handleFileUpload}\n style={{display: 'none'}}\n />\n </div>\n </div>\n\n {/* Full Instructions Modal */}\n <Dialog open={isOpen} onOpenChange={onClose}>\n <DialogContent className=\"flex h-[80vh] max-w-4xl flex-col\">\n <DialogHeader className=\"shrink-0\">\n <DialogTitle>Full System Instructions</DialogTitle>\n <DialogDescription>\n Complete system instructions that will be sent to the AI model,\n including default instructions and your additional custom\n instructions.\n </DialogDescription>\n </DialogHeader>\n <div className=\"mt-4 min-h-0 flex-1 overflow-hidden\">\n <div className=\"bg-muted/50 h-full overflow-auto rounded-lg p-4\">\n <pre className=\"overflow-wrap-anywhere w-full max-w-full font-mono text-sm leading-relaxed wrap-break-word\">\n {getFullInstructions()}\n </pre>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"AiModelParameters.js","sourceRoot":"","sources":["../../src/components/AiModelParameters.tsx"],"names":[],"mappings":"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","sourcesContent":["import {FC, useRef} from 'react';\nimport {Sliders, Wrench, FileText, Upload, Eye} from 'lucide-react';\nimport {\n Textarea,\n Input,\n Button,\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n useDisclosure,\n toast,\n} from '@sqlrooms/ui';\nimport {useStoreWithAiSettings} from '../AiSettingsSlice';\n\nexport interface AiModelParametersProps {\n showViewInstructions?: boolean;\n}\n\nexport const AiModelParameters: FC<AiModelParametersProps> = ({\n showViewInstructions = false,\n}) => {\n const maxSteps = useStoreWithAiSettings(\n (s) => s.aiSettings.config.modelParameters.maxSteps,\n );\n const setMaxStepsAiChatUi = useStoreWithAiSettings(\n (s) => s.aiSettings.setMaxSteps,\n );\n\n const additionalInstruction = useStoreWithAiSettings(\n (s) => s.aiSettings.config.modelParameters.additionalInstruction,\n );\n const setAdditionalInstruction = useStoreWithAiSettings(\n (s) => s.aiSettings.setAdditionalInstruction,\n );\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const {isOpen, onOpen, onClose} = useDisclosure();\n\n const handleMaxStepsChange = (value: number) => {\n setMaxStepsAiChatUi(value);\n };\n\n const handleAdditionalInstructionChange = (value: string) => {\n setAdditionalInstruction(value);\n };\n\n const getFullInstructions = useStoreWithAiSettings(\n (s) => s.ai.getFullInstructions,\n );\n\n const handleFileUpload = async (\n event: React.ChangeEvent<HTMLInputElement>,\n ) => {\n const file = event.target.files?.[0];\n if (!file) return;\n\n // Validate file type\n const allowedTypes = ['text/plain', 'text/markdown', 'application/json'];\n const allowedExtensions = ['.txt', '.md', '.json', '.text'];\n const fileExtension = file.name\n .toLowerCase()\n .slice(file.name.lastIndexOf('.'));\n\n if (\n !allowedTypes.includes(file.type) &&\n !allowedExtensions.includes(fileExtension)\n ) {\n toast.error('Invalid file type', {\n description: 'Please select a text file (.txt, .md, .json)',\n });\n return;\n }\n\n // Validate file size (max 1MB)\n const maxSize = 1024 * 1024; // 1MB\n if (file.size > maxSize) {\n toast.error('File too large', {\n description: 'File size must be less than 1MB',\n });\n return;\n }\n\n try {\n const text = await file.text();\n setAdditionalInstruction(text);\n toast.success('File uploaded successfully', {\n description:\n 'System instructions have been updated from the uploaded file.',\n });\n } catch (error) {\n console.error('Error reading file:', error);\n toast.error('Error reading file', {\n description: 'Please try again.',\n });\n }\n\n // Reset the input so the same file can be selected again\n if (fileInputRef.current) {\n fileInputRef.current.value = '';\n }\n };\n\n const handleUploadButtonClick = () => {\n fileInputRef.current?.click();\n };\n\n const handleViewFullInstructions = () => {\n onOpen();\n };\n\n return (\n <div className=\"space-y-2\">\n <label className=\"text-md flex items-center gap-2 pb-6 font-medium\">\n <Sliders className=\"h-4 w-4\" />\n Model Parameters\n </label>\n <div className=\"grid grid-cols-1 gap-4\">\n {/* Max Steps */}\n <div className=\"space-y-2\">\n <label className=\"flex items-center gap-2 text-sm font-medium\">\n <Wrench className=\"h-4 w-4\" />\n Max Tool Steps\n </label>\n <div className=\"flex items-center gap-2\">\n <Input\n type=\"number\"\n min=\"1\"\n max=\"20\"\n step=\"1\"\n value={maxSteps}\n onChange={(e) =>\n handleMaxStepsChange(parseInt(e.target.value) || 1)\n }\n className=\"flex-1\"\n />\n </div>\n </div>\n\n {/* Additional Instruction */}\n <div className=\"space-y-2\">\n <label className=\"flex items-center gap-2 text-sm font-medium\">\n <FileText className=\"h-4 w-4\" />\n Additional Instructions\n </label>\n <Textarea\n value={additionalInstruction}\n onChange={(e) => handleAdditionalInstructionChange(e.target.value)}\n placeholder=\"Enter custom system instructions for the AI model...\"\n className=\"min-h-[80px] resize-y\"\n autoResize={false}\n />\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleUploadButtonClick}\n className=\"flex items-center gap-2\"\n >\n <Upload className=\"h-4 w-4\" />\n Upload File\n </Button>\n {showViewInstructions && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleViewFullInstructions}\n className=\"flex items-center gap-2\"\n >\n <Eye className=\"h-4 w-4\" />\n View Instructions\n </Button>\n )}\n </div>\n <Input\n ref={fileInputRef}\n type=\"file\"\n accept=\".txt,.md,.json,.text,text/plain,text/markdown,application/json\"\n onChange={handleFileUpload}\n style={{display: 'none'}}\n />\n </div>\n </div>\n\n {/* Full Instructions Modal */}\n <Dialog open={isOpen} onOpenChange={onClose}>\n <DialogContent className=\"flex h-[80vh] max-w-4xl flex-col\">\n <DialogHeader className=\"shrink-0\">\n <DialogTitle>Full System Instructions</DialogTitle>\n <DialogDescription>\n Complete system instructions that will be sent to the AI model,\n including default instructions and your additional custom\n instructions.\n </DialogDescription>\n </DialogHeader>\n <div className=\"mt-4 min-h-0 flex-1 overflow-hidden\">\n <div className=\"bg-muted/50 h-full overflow-auto rounded-lg p-4\">\n <pre className=\"overflow-wrap-anywhere w-full max-w-full font-mono text-sm leading-relaxed wrap-break-word\">\n {getFullInstructions()}\n </pre>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n </div>\n );\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiModelsSettings.d.ts","sourceRoot":"","sources":["../../src/components/AiModelsSettings.tsx"],"names":[],"mappings":"AAwBA,OAAO,EAAC,EAAE,EAAoB,MAAM,OAAO,CAAC;AAG5C,MAAM,WAAW,qBAAqB;IACpC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,
|
|
1
|
+
{"version":3,"file":"AiModelsSettings.d.ts","sourceRoot":"","sources":["../../src/components/AiModelsSettings.tsx"],"names":[],"mappings":"AAwBA,OAAO,EAAC,EAAE,EAAoB,MAAM,OAAO,CAAC;AAG5C,MAAM,WAAW,qBAAqB;IACpC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CA+oBtD,CAAC"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useStoreWithAi } from '@sqlrooms/ai-core';
|
|
3
|
-
import { Button, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, Input, Label, useDisclosure,
|
|
3
|
+
import { Button, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, Input, Label, useDisclosure, toast, } from '@sqlrooms/ui';
|
|
4
4
|
import { Blocks, CirclePlus, Cpu, Key, Plus, Server, Settings, Trash2, } from 'lucide-react';
|
|
5
5
|
import { useMemo, useState } from 'react';
|
|
6
6
|
import { useStoreWithAiSettings } from '../AiSettingsSlice';
|
|
7
7
|
export const AiModelsSettings = ({ className = '', allowEditProviderModels = true, allowCustomModels = true, }) => {
|
|
8
|
-
const { toast } = useToast();
|
|
9
8
|
const aiConfig = useStoreWithAiSettings((s) => s.aiSettings.config);
|
|
10
9
|
const setAiModel = useStoreWithAi((s) => s.ai.setAiModel);
|
|
11
10
|
const addModelToProvider = useStoreWithAiSettings((s) => s.aiSettings.addModelToProvider);
|
|
@@ -37,19 +36,15 @@ export const AiModelsSettings = ({ className = '', allowEditProviderModels = tru
|
|
|
37
36
|
setBaseUrlError(false);
|
|
38
37
|
// Validate required fields
|
|
39
38
|
if (!customName.trim()) {
|
|
40
|
-
toast({
|
|
41
|
-
title: 'Model Name Required',
|
|
39
|
+
toast.error('Model Name Required', {
|
|
42
40
|
description: 'Please enter a model name.',
|
|
43
|
-
variant: 'destructive',
|
|
44
41
|
});
|
|
45
42
|
return;
|
|
46
43
|
}
|
|
47
44
|
if (!customBaseUrl.trim()) {
|
|
48
45
|
setBaseUrlError(true);
|
|
49
|
-
toast({
|
|
50
|
-
title: 'Base URL Required',
|
|
46
|
+
toast.error('Base URL Required', {
|
|
51
47
|
description: 'Please enter a base URL for the model.',
|
|
52
|
-
variant: 'destructive',
|
|
53
48
|
});
|
|
54
49
|
return;
|
|
55
50
|
}
|
|
@@ -59,10 +54,8 @@ export const AiModelsSettings = ({ className = '', allowEditProviderModels = tru
|
|
|
59
54
|
// Update the current session to use this custom model
|
|
60
55
|
setAiModel('custom', trimmedName);
|
|
61
56
|
// Show success message
|
|
62
|
-
toast({
|
|
63
|
-
title: 'Custom Model Added',
|
|
57
|
+
toast.success('Custom Model Added', {
|
|
64
58
|
description: `Successfully added "${trimmedName}" to your custom models.`,
|
|
65
|
-
variant: 'default',
|
|
66
59
|
});
|
|
67
60
|
// Reset form
|
|
68
61
|
setCustomName('');
|
|
@@ -91,19 +84,15 @@ export const AiModelsSettings = ({ className = '', allowEditProviderModels = tru
|
|
|
91
84
|
setEditBaseUrlError(false);
|
|
92
85
|
// Validate required fields
|
|
93
86
|
if (!editingModel.modelName.trim()) {
|
|
94
|
-
toast({
|
|
95
|
-
title: 'Model Name Required',
|
|
87
|
+
toast.error('Model Name Required', {
|
|
96
88
|
description: 'Please enter a model name.',
|
|
97
|
-
variant: 'destructive',
|
|
98
89
|
});
|
|
99
90
|
return;
|
|
100
91
|
}
|
|
101
92
|
if (!editingModel.baseUrl.trim()) {
|
|
102
93
|
setEditBaseUrlError(true);
|
|
103
|
-
toast({
|
|
104
|
-
title: 'Base URL Required',
|
|
94
|
+
toast.error('Base URL Required', {
|
|
105
95
|
description: 'Please enter a base URL for the model.',
|
|
106
|
-
variant: 'destructive',
|
|
107
96
|
});
|
|
108
97
|
return;
|
|
109
98
|
}
|
|
@@ -114,20 +103,16 @@ export const AiModelsSettings = ({ className = '', allowEditProviderModels = tru
|
|
|
114
103
|
const duplicateModel = customModels.find((cm) => cm.modelName.toLowerCase() === trimmedName.toLowerCase() &&
|
|
115
104
|
cm.modelName !== editingModel.oldModelName);
|
|
116
105
|
if (duplicateModel) {
|
|
117
|
-
toast({
|
|
118
|
-
title: 'Model Name Already Exists',
|
|
106
|
+
toast.error('Model Name Already Exists', {
|
|
119
107
|
description: `A custom model with the name "${trimmedName}" already exists.`,
|
|
120
|
-
variant: 'destructive',
|
|
121
108
|
});
|
|
122
109
|
return;
|
|
123
110
|
}
|
|
124
111
|
// Update the custom model
|
|
125
112
|
updateCustomModel(editingModel.oldModelName, trimmedBaseUrl, trimmedApiKey, trimmedName);
|
|
126
113
|
// Show success message
|
|
127
|
-
toast({
|
|
128
|
-
title: 'Custom Model Updated',
|
|
114
|
+
toast.success('Custom Model Updated', {
|
|
129
115
|
description: `Successfully updated "${trimmedName}".`,
|
|
130
|
-
variant: 'default',
|
|
131
116
|
});
|
|
132
117
|
// Reset form and close dialog
|
|
133
118
|
setEditingModel(null);
|
|
@@ -146,10 +131,8 @@ export const AiModelsSettings = ({ className = '', allowEditProviderModels = tru
|
|
|
146
131
|
const provider = aiConfig.providers[selectedProviderKey];
|
|
147
132
|
const modelExists = provider?.models.some((model) => model.modelName.toLowerCase() === newModelName.trim().toLowerCase());
|
|
148
133
|
if (modelExists) {
|
|
149
|
-
toast({
|
|
150
|
-
title: 'Model Already Exists',
|
|
134
|
+
toast.error('Model Already Exists', {
|
|
151
135
|
description: `The model "${newModelName.trim()}" already exists in this provider.`,
|
|
152
|
-
variant: 'destructive',
|
|
153
136
|
});
|
|
154
137
|
return;
|
|
155
138
|
}
|
|
@@ -166,18 +149,14 @@ export const AiModelsSettings = ({ className = '', allowEditProviderModels = tru
|
|
|
166
149
|
return;
|
|
167
150
|
if (modelToDelete.type === 'provider' && modelToDelete.providerKey) {
|
|
168
151
|
removeModelFromProvider(modelToDelete.providerKey, modelToDelete.modelName);
|
|
169
|
-
toast({
|
|
170
|
-
title: 'Model Deleted',
|
|
152
|
+
toast.success('Model Deleted', {
|
|
171
153
|
description: `Successfully removed "${modelToDelete.modelName}" from the provider.`,
|
|
172
|
-
variant: 'default',
|
|
173
154
|
});
|
|
174
155
|
}
|
|
175
156
|
else if (modelToDelete.type === 'custom') {
|
|
176
157
|
removeCustomModel(modelToDelete.modelName);
|
|
177
|
-
toast({
|
|
178
|
-
title: 'Custom Model Deleted',
|
|
158
|
+
toast.success('Custom Model Deleted', {
|
|
179
159
|
description: `Successfully removed "${modelToDelete.modelName}" from custom models.`,
|
|
180
|
-
variant: 'default',
|
|
181
160
|
});
|
|
182
161
|
}
|
|
183
162
|
setModelToDelete(null);
|
|
@@ -197,14 +176,14 @@ export const AiModelsSettings = ({ className = '', allowEditProviderModels = tru
|
|
|
197
176
|
setBaseUrlError(false);
|
|
198
177
|
closeCustomModelDialog();
|
|
199
178
|
}
|
|
200
|
-
}, children: [_jsx(DialogTrigger, { asChild: true }), _jsxs(DialogContent, { className: "border-0 p-5", children: [_jsxs(DialogHeader, { className: "mb-1", children: [_jsxs(DialogTitle, { className: "flex items-center gap-2 text-base", children: [_jsx(Blocks, { className: "h-4 w-4" }), " Add Custom Model"] }), _jsx(DialogDescription, { className: "text-xs", children: "Provide connection details for your model provider." })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Label, { htmlFor: "custom-name", className: "w-20 text-sm", children: "Name" }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Cpu, { className: "absolute
|
|
179
|
+
}, children: [_jsx(DialogTrigger, { asChild: true }), _jsxs(DialogContent, { className: "border-0 p-5", children: [_jsxs(DialogHeader, { className: "mb-1", children: [_jsxs(DialogTitle, { className: "flex items-center gap-2 text-base", children: [_jsx(Blocks, { className: "h-4 w-4" }), " Add Custom Model"] }), _jsx(DialogDescription, { className: "text-xs", children: "Provide connection details for your model provider." })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Label, { htmlFor: "custom-name", className: "w-20 text-sm", children: "Name" }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Cpu, { className: "absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2" }), _jsx(Input, { id: "custom-name", value: customName, onChange: (e) => setCustomName(e.target.value), placeholder: "e.g., My cool model", className: "pl-8" })] })] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Label, { htmlFor: "custom-baseUrl", className: "w-20 text-sm", children: "baseUrl" }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Server, { className: "absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2" }), _jsx(Input, { id: "custom-baseUrl", value: customBaseUrl, onChange: (e) => {
|
|
201
180
|
setCustomBaseUrl(e.target.value);
|
|
202
181
|
if (baseUrlError && e.target.value.trim()) {
|
|
203
182
|
setBaseUrlError(false);
|
|
204
183
|
}
|
|
205
|
-
}, placeholder: "https://api.example.com", className: `pl-8 ${baseUrlError ? 'border-red-500 focus:border-red-500' : ''}` })] })] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Label, { htmlFor: "custom-apiKey", className: "w-20 text-sm", children: "API key" }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Key, { className: "absolute
|
|
184
|
+
}, placeholder: "https://api.example.com", className: `pl-8 ${baseUrlError ? 'border-red-500 focus:border-red-500' : ''}` })] })] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Label, { htmlFor: "custom-apiKey", className: "w-20 text-sm", children: "API key" }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Key, { className: "absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2" }), _jsx(Input, { id: "custom-apiKey", type: "password", value: customApiKey, onChange: (e) => setCustomApiKey(e.target.value), placeholder: "Optional", className: "pl-8" })] })] }), _jsx("div", { className: "flex justify-end pt-1", children: _jsxs(Button, { size: "sm", onClick: handleAddCustomToSession, children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), " Add"] }) })] })] })] })), _jsxs(Dialog, { open: isAddProviderModelDialogOpen, onOpenChange: (open) => open ? openAddProviderModelDialog() : closeAddProviderModelDialog(), children: [_jsx(DialogTrigger, { asChild: true }), _jsxs(DialogContent, { className: "border-0 p-5", children: [_jsxs(DialogHeader, { className: "mb-1", children: [_jsxs(DialogTitle, { className: "flex items-center gap-2 text-base", children: [_jsx(Blocks, { className: "h-4 w-4" }), " Add Model to Provider"] }), _jsxs(DialogDescription, { className: "text-xs", children: ["Add a new model to", ' ', selectedProviderKey &&
|
|
206
185
|
selectedProviderKey.charAt(0).toUpperCase() +
|
|
207
|
-
selectedProviderKey.slice(1)] })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Label, { htmlFor: "new-model-name", className: "w-24 text-sm", children: "Model Name" }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Cpu, { className: "absolute
|
|
186
|
+
selectedProviderKey.slice(1)] })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Label, { htmlFor: "new-model-name", className: "w-24 text-sm", children: "Model Name" }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Cpu, { className: "absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2" }), _jsx(Input, { id: "new-model-name", value: newModelName, onChange: (e) => setNewModelName(e.target.value), placeholder: "e.g., gpt-4-turbo", className: "pl-8" })] })] }), _jsx("div", { className: "flex justify-end pt-1", children: _jsxs(Button, { size: "sm", onClick: handleAddModelToProvider, children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), " Add Model"] }) })] })] })] }), allowCustomModels && (_jsxs(Dialog, { open: isEditCustomModelDialogOpen, onOpenChange: (open) => {
|
|
208
187
|
if (open) {
|
|
209
188
|
openEditCustomModelDialog();
|
|
210
189
|
}
|
|
@@ -212,12 +191,12 @@ export const AiModelsSettings = ({ className = '', allowEditProviderModels = tru
|
|
|
212
191
|
setEditBaseUrlError(false);
|
|
213
192
|
closeEditCustomModelDialog();
|
|
214
193
|
}
|
|
215
|
-
}, children: [_jsx(DialogTrigger, { asChild: true }), _jsxs(DialogContent, { className: "border-0 p-5", children: [_jsxs(DialogHeader, { className: "mb-1", children: [_jsxs(DialogTitle, { className: "flex items-center gap-2 text-base", children: [_jsx(Settings, { className: "h-4 w-4" }), " Edit Custom Model"] }), _jsx(DialogDescription, { className: "text-xs", children: "Update the connection details for your custom model." })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Label, { htmlFor: "edit-model-name", className: "w-20 text-sm", children: "Name" }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Cpu, { className: "absolute
|
|
194
|
+
}, children: [_jsx(DialogTrigger, { asChild: true }), _jsxs(DialogContent, { className: "border-0 p-5", children: [_jsxs(DialogHeader, { className: "mb-1", children: [_jsxs(DialogTitle, { className: "flex items-center gap-2 text-base", children: [_jsx(Settings, { className: "h-4 w-4" }), " Edit Custom Model"] }), _jsx(DialogDescription, { className: "text-xs", children: "Update the connection details for your custom model." })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Label, { htmlFor: "edit-model-name", className: "w-20 text-sm", children: "Name" }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Cpu, { className: "absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2" }), _jsx(Input, { id: "edit-model-name", value: editingModel?.modelName || '', onChange: (e) => setEditingModel((prev) => prev ? { ...prev, modelName: e.target.value } : null), placeholder: "e.g., My cool model", className: "pl-8" })] })] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Label, { htmlFor: "edit-model-baseUrl", className: "w-20 text-sm", children: "baseUrl" }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Server, { className: "absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2" }), _jsx(Input, { id: "edit-model-baseUrl", value: editingModel?.baseUrl || '', onChange: (e) => {
|
|
216
195
|
setEditingModel((prev) => prev ? { ...prev, baseUrl: e.target.value } : null);
|
|
217
196
|
if (editBaseUrlError && e.target.value.trim()) {
|
|
218
197
|
setEditBaseUrlError(false);
|
|
219
198
|
}
|
|
220
|
-
}, placeholder: "https://api.example.com", className: `pl-8 ${editBaseUrlError ? 'border-red-500 focus:border-red-500' : ''}` })] })] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Label, { htmlFor: "edit-model-apiKey", className: "w-20 text-sm", children: "API key" }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Key, { className: "absolute
|
|
199
|
+
}, placeholder: "https://api.example.com", className: `pl-8 ${editBaseUrlError ? 'border-red-500 focus:border-red-500' : ''}` })] })] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Label, { htmlFor: "edit-model-apiKey", className: "w-20 text-sm", children: "API key" }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Key, { className: "absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2" }), _jsx(Input, { id: "edit-model-apiKey", type: "password", value: editingModel?.apiKey || '', onChange: (e) => setEditingModel((prev) => prev ? { ...prev, apiKey: e.target.value } : null), placeholder: "Optional", className: "pl-8" })] })] }), _jsxs("div", { className: "flex justify-end gap-2 pt-1", children: [_jsx(Button, { size: "sm", variant: "outline", onClick: () => {
|
|
221
200
|
setEditingModel(null);
|
|
222
201
|
setEditBaseUrlError(false);
|
|
223
202
|
closeEditCustomModelDialog();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiModelsSettings.js","sourceRoot":"","sources":["../../src/components/AiModelsSettings.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useStoreWithAi} from '@sqlrooms/ai-core';\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n Input,\n Label,\n useDisclosure,\n useToast,\n} from '@sqlrooms/ui';\nimport {\n Blocks,\n CirclePlus,\n Cpu,\n Key,\n Plus,\n Server,\n Settings,\n Trash2,\n} from 'lucide-react';\nimport {FC, useMemo, useState} from 'react';\nimport {useStoreWithAiSettings} from '../AiSettingsSlice';\n\nexport interface AiModelsSettingsProps {\n showProviderModels?: boolean;\n showCustomModels?: boolean;\n allowEditProviderModels?: boolean;\n allowCustomModels?: boolean;\n className?: string;\n}\n\nexport const AiModelsSettings: FC<AiModelsSettingsProps> = ({\n className = '',\n allowEditProviderModels = true,\n allowCustomModels = true,\n}) => {\n const {toast} = useToast();\n const aiConfig = useStoreWithAiSettings((s) => s.aiSettings.config);\n const setAiModel = useStoreWithAi((s) => s.ai.setAiModel);\n const addModelToProvider = useStoreWithAiSettings(\n (s) => s.aiSettings.addModelToProvider,\n );\n const removeModelFromProvider = useStoreWithAiSettings(\n (s) => s.aiSettings.removeModelFromProvider,\n );\n const addCustomModel = useStoreWithAiSettings(\n (s) => s.aiSettings.addCustomModel,\n );\n const updateCustomModel = useStoreWithAiSettings(\n (s) => s.aiSettings.updateCustomModel,\n );\n const removeCustomModel = useStoreWithAiSettings(\n (s) => s.aiSettings.removeCustomModel,\n );\n\n const providers = useMemo(\n () => Object.entries(aiConfig.providers),\n [aiConfig.providers],\n );\n const customModels = aiConfig.customModels || [];\n\n // Dialog state for adding a custom model\n const {\n isOpen: isCustomModelDialogOpen,\n onOpen: openCustomModelDialog,\n onClose: closeCustomModelDialog,\n } = useDisclosure();\n const [customName, setCustomName] = useState('');\n const [customBaseUrl, setCustomBaseUrl] = useState('');\n const [customApiKey, setCustomApiKey] = useState('');\n const [baseUrlError, setBaseUrlError] = useState(false);\n\n // Dialog state for editing a custom model\n const {\n isOpen: isEditCustomModelDialogOpen,\n onOpen: openEditCustomModelDialog,\n onClose: closeEditCustomModelDialog,\n } = useDisclosure();\n const [editingModel, setEditingModel] = useState<{\n oldModelName: string;\n modelName: string;\n baseUrl: string;\n apiKey: string;\n } | null>(null);\n const [editBaseUrlError, setEditBaseUrlError] = useState(false);\n\n // Dialog state for adding a model to a provider\n const {\n isOpen: isAddProviderModelDialogOpen,\n onOpen: openAddProviderModelDialog,\n onClose: closeAddProviderModelDialog,\n } = useDisclosure();\n const [selectedProviderKey, setSelectedProviderKey] = useState('');\n const [newModelName, setNewModelName] = useState('');\n\n // Dialog state for deleting a model\n const {\n isOpen: isDeleteModelDialogOpen,\n onOpen: openDeleteModelDialog,\n onClose: closeDeleteModelDialog,\n } = useDisclosure();\n const [modelToDelete, setModelToDelete] = useState<{\n type: 'provider' | 'custom';\n providerKey?: string;\n modelName: string;\n } | null>(null);\n\n const handleAddCustomToSession = () => {\n // Reset error states\n setBaseUrlError(false);\n\n // Validate required fields\n if (!customName.trim()) {\n toast({\n title: 'Model Name Required',\n description: 'Please enter a model name.',\n variant: 'destructive',\n });\n return;\n }\n\n if (!customBaseUrl.trim()) {\n setBaseUrlError(true);\n toast({\n title: 'Base URL Required',\n description: 'Please enter a base URL for the model.',\n variant: 'destructive',\n });\n return;\n }\n\n const trimmedName = customName.trim();\n\n // Add the custom model to the config\n addCustomModel(customBaseUrl.trim(), customApiKey.trim(), trimmedName);\n\n // Update the current session to use this custom model\n setAiModel('custom', trimmedName);\n\n // Show success message\n toast({\n title: 'Custom Model Added',\n description: `Successfully added \"${trimmedName}\" to your custom models.`,\n variant: 'default',\n });\n\n // Reset form\n setCustomName('');\n setCustomBaseUrl('');\n setCustomApiKey('');\n setBaseUrlError(false);\n closeCustomModelDialog();\n };\n\n const handleEditCustomModel = (modelName: string) => {\n const customModel = customModels.find((cm) => cm.modelName === modelName);\n if (customModel) {\n setEditingModel({\n oldModelName: modelName,\n modelName: modelName,\n baseUrl: customModel.baseUrl,\n apiKey: customModel.apiKey,\n });\n setEditBaseUrlError(false);\n openEditCustomModelDialog();\n }\n };\n\n const handleUpdateCustomModel = () => {\n if (!editingModel) return;\n\n // Reset error states\n setEditBaseUrlError(false);\n\n // Validate required fields\n if (!editingModel.modelName.trim()) {\n toast({\n title: 'Model Name Required',\n description: 'Please enter a model name.',\n variant: 'destructive',\n });\n return;\n }\n\n if (!editingModel.baseUrl.trim()) {\n setEditBaseUrlError(true);\n toast({\n title: 'Base URL Required',\n description: 'Please enter a base URL for the model.',\n variant: 'destructive',\n });\n return;\n }\n\n const trimmedName = editingModel.modelName.trim();\n const trimmedBaseUrl = editingModel.baseUrl.trim();\n const trimmedApiKey = editingModel.apiKey.trim();\n\n // Check for duplicate model names (excluding the current model being edited)\n const duplicateModel = customModels.find(\n (cm) =>\n cm.modelName.toLowerCase() === trimmedName.toLowerCase() &&\n cm.modelName !== editingModel.oldModelName,\n );\n\n if (duplicateModel) {\n toast({\n title: 'Model Name Already Exists',\n description: `A custom model with the name \"${trimmedName}\" already exists.`,\n variant: 'destructive',\n });\n return;\n }\n\n // Update the custom model\n updateCustomModel(\n editingModel.oldModelName,\n trimmedBaseUrl,\n trimmedApiKey,\n trimmedName,\n );\n\n // Show success message\n toast({\n title: 'Custom Model Updated',\n description: `Successfully updated \"${trimmedName}\".`,\n variant: 'default',\n });\n\n // Reset form and close dialog\n setEditingModel(null);\n setEditBaseUrlError(false);\n closeEditCustomModelDialog();\n };\n\n const handleOpenAddProviderModelDialog = (providerKey: string) => {\n setSelectedProviderKey(providerKey);\n setNewModelName('');\n openAddProviderModelDialog();\n };\n\n const handleAddModelToProvider = () => {\n if (!selectedProviderKey || !newModelName.trim()) return;\n\n // Check for duplicates\n const provider = aiConfig.providers[selectedProviderKey];\n const modelExists = provider?.models.some(\n (model) =>\n model.modelName.toLowerCase() === newModelName.trim().toLowerCase(),\n );\n\n if (modelExists) {\n toast({\n title: 'Model Already Exists',\n description: `The model \"${newModelName.trim()}\" already exists in this provider.`,\n variant: 'destructive',\n });\n return;\n }\n\n addModelToProvider(selectedProviderKey, newModelName.trim());\n setNewModelName('');\n closeAddProviderModelDialog();\n };\n\n const handleDeleteModel = (\n type: 'provider' | 'custom',\n providerKey: string | undefined,\n modelName: string,\n ) => {\n setModelToDelete({type, providerKey, modelName});\n openDeleteModelDialog();\n };\n\n const confirmDeleteModel = () => {\n if (!modelToDelete) return;\n\n if (modelToDelete.type === 'provider' && modelToDelete.providerKey) {\n removeModelFromProvider(\n modelToDelete.providerKey,\n modelToDelete.modelName,\n );\n toast({\n title: 'Model Deleted',\n description: `Successfully removed \"${modelToDelete.modelName}\" from the provider.`,\n variant: 'default',\n });\n } else if (modelToDelete.type === 'custom') {\n removeCustomModel(modelToDelete.modelName);\n toast({\n title: 'Custom Model Deleted',\n description: `Successfully removed \"${modelToDelete.modelName}\" from custom models.`,\n variant: 'default',\n });\n }\n\n setModelToDelete(null);\n closeDeleteModelDialog();\n };\n\n return (\n <div className={`space-y-2 ${className}`}>\n <label className=\"text-md flex items-center gap-2 pb-4 font-medium\">\n <Blocks className=\"h-4 w-4\" />\n Models\n </label>\n\n {/* Providers and their models */}\n <div className=\"w-full space-y-4\">\n {providers.map(([providerKey, provider]) => (\n <div key={providerKey} className=\"flex w-full items-start gap-4\">\n {/* Provider name column - 30% */}\n <div className=\"flex w-20 items-start justify-start text-sm font-medium\">\n {providerKey.charAt(0).toUpperCase() + providerKey.slice(1)}\n </div>\n\n {/* Models column - 65% (fills the rest) */}\n <div className=\"flex flex-1 flex-col items-start gap-2\">\n {provider.models.map((m) => (\n <div\n key={m.modelName}\n className=\"flex w-full items-center justify-between gap-2 border-b p-1 text-xs\"\n >\n <span className=\"text-foreground/90\">{m.modelName}</span>\n {allowEditProviderModels && (\n <Button\n size=\"xs\"\n variant=\"ghost\"\n onClick={() =>\n handleDeleteModel('provider', providerKey, m.modelName)\n }\n className=\"h-6 w-6 p-0 text-gray-500 hover:bg-gray-100 hover:text-gray-700\"\n >\n <Trash2 className=\"h-3 w-3\" />\n </Button>\n )}\n </div>\n ))}\n {allowEditProviderModels && (\n <Button\n size=\"xs\"\n variant=\"secondary\"\n onClick={() => handleOpenAddProviderModelDialog(providerKey)}\n >\n <CirclePlus className=\"h-3 w-3\" />\n Add\n </Button>\n )}\n </div>\n\n {/* add model button column - 5% */}\n <div className=\"flex w-12 items-start justify-end\"></div>\n </div>\n ))}\n\n {/* Custom models */}\n {allowCustomModels && (\n <div className=\"flex w-full items-start gap-4\">\n <div className=\"flex w-20 items-start justify-start text-sm font-medium\">\n Custom\n </div>\n <div className=\"flex flex-1 flex-col items-start gap-2\">\n {customModels.map((cm) => (\n <div\n key={cm.modelName}\n className=\"flex w-full items-center justify-between gap-2 border-b p-1 text-xs\"\n >\n <span className=\"text-foreground/90\">{cm.modelName}</span>\n <div className=\"flex w-full items-center justify-end\">\n <Button\n size=\"xs\"\n variant=\"ghost\"\n onClick={() =>\n handleDeleteModel('custom', undefined, cm.modelName)\n }\n className=\"h-6 w-6 p-0 text-gray-500 hover:bg-gray-100 hover:text-gray-700\"\n >\n <Trash2 className=\"h-3 w-3\" />\n </Button>\n <Button\n size=\"xs\"\n variant=\"ghost\"\n onClick={() => handleEditCustomModel(cm.modelName)}\n >\n <Settings className=\"h-3 w-3\" />\n </Button>\n </div>\n </div>\n ))}\n <Button\n size=\"xs\"\n variant=\"secondary\"\n onClick={() => {\n setCustomName('');\n setCustomBaseUrl('');\n setCustomApiKey('');\n setBaseUrlError(false);\n openCustomModelDialog();\n }}\n >\n <CirclePlus className=\"h-3 w-3\" />\n Add\n </Button>\n </div>\n <div className=\"flex w-12 items-start justify-end\"></div>\n </div>\n )}\n </div>\n\n {/* Add Custom Model Dialog */}\n {allowCustomModels && (\n <Dialog\n open={isCustomModelDialogOpen}\n onOpenChange={(open) => {\n if (open) {\n openCustomModelDialog();\n } else {\n setBaseUrlError(false);\n closeCustomModelDialog();\n }\n }}\n >\n <DialogTrigger asChild>\n {/* handled via onOpen button above */}\n </DialogTrigger>\n <DialogContent className=\"border-0 p-5\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"flex items-center gap-2 text-base\">\n <Blocks className=\"h-4 w-4\" /> Add Custom Model\n </DialogTitle>\n <DialogDescription className=\"text-xs\">\n Provide connection details for your model provider.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"custom-name\" className=\"w-20 text-sm\">\n Name\n </Label>\n <div className=\"relative flex-1\">\n <Cpu className=\"absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"custom-name\"\n value={customName}\n onChange={(e) => setCustomName(e.target.value)}\n placeholder=\"e.g., My cool model\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"custom-baseUrl\" className=\"w-20 text-sm\">\n baseUrl\n </Label>\n <div className=\"relative flex-1\">\n <Server className=\"absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"custom-baseUrl\"\n value={customBaseUrl}\n onChange={(e) => {\n setCustomBaseUrl(e.target.value);\n if (baseUrlError && e.target.value.trim()) {\n setBaseUrlError(false);\n }\n }}\n placeholder=\"https://api.example.com\"\n className={`pl-8 ${baseUrlError ? 'border-red-500 focus:border-red-500' : ''}`}\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"custom-apiKey\" className=\"w-20 text-sm\">\n API key\n </Label>\n <div className=\"relative flex-1\">\n <Key className=\"absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"custom-apiKey\"\n type=\"password\"\n value={customApiKey}\n onChange={(e) => setCustomApiKey(e.target.value)}\n placeholder=\"Optional\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex justify-end pt-1\">\n <Button size=\"sm\" onClick={handleAddCustomToSession}>\n <Plus className=\"mr-2 h-4 w-4\" /> Add\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n )}\n\n {/* Add Model to Provider Dialog */}\n <Dialog\n open={isAddProviderModelDialogOpen}\n onOpenChange={(open) =>\n open ? openAddProviderModelDialog() : closeAddProviderModelDialog()\n }\n >\n <DialogTrigger asChild>\n {/* handled via onOpen button above */}\n </DialogTrigger>\n <DialogContent className=\"border-0 p-5\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"flex items-center gap-2 text-base\">\n <Blocks className=\"h-4 w-4\" /> Add Model to Provider\n </DialogTitle>\n <DialogDescription className=\"text-xs\">\n Add a new model to{' '}\n {selectedProviderKey &&\n selectedProviderKey.charAt(0).toUpperCase() +\n selectedProviderKey.slice(1)}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"new-model-name\" className=\"w-24 text-sm\">\n Model Name\n </Label>\n <div className=\"relative flex-1\">\n <Cpu className=\"absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"new-model-name\"\n value={newModelName}\n onChange={(e) => setNewModelName(e.target.value)}\n placeholder=\"e.g., gpt-4-turbo\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex justify-end pt-1\">\n <Button size=\"sm\" onClick={handleAddModelToProvider}>\n <Plus className=\"mr-2 h-4 w-4\" /> Add Model\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n\n {/* Edit Custom Model Dialog */}\n {allowCustomModels && (\n <Dialog\n open={isEditCustomModelDialogOpen}\n onOpenChange={(open) => {\n if (open) {\n openEditCustomModelDialog();\n } else {\n setEditBaseUrlError(false);\n closeEditCustomModelDialog();\n }\n }}\n >\n <DialogTrigger asChild>\n {/* handled via onOpen button above */}\n </DialogTrigger>\n <DialogContent className=\"border-0 p-5\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"flex items-center gap-2 text-base\">\n <Settings className=\"h-4 w-4\" /> Edit Custom Model\n </DialogTitle>\n <DialogDescription className=\"text-xs\">\n Update the connection details for your custom model.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"edit-model-name\" className=\"w-20 text-sm\">\n Name\n </Label>\n <div className=\"relative flex-1\">\n <Cpu className=\"absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"edit-model-name\"\n value={editingModel?.modelName || ''}\n onChange={(e) =>\n setEditingModel((prev) =>\n prev ? {...prev, modelName: e.target.value} : null,\n )\n }\n placeholder=\"e.g., My cool model\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"edit-model-baseUrl\" className=\"w-20 text-sm\">\n baseUrl\n </Label>\n <div className=\"relative flex-1\">\n <Server className=\"absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"edit-model-baseUrl\"\n value={editingModel?.baseUrl || ''}\n onChange={(e) => {\n setEditingModel((prev) =>\n prev ? {...prev, baseUrl: e.target.value} : null,\n );\n if (editBaseUrlError && e.target.value.trim()) {\n setEditBaseUrlError(false);\n }\n }}\n placeholder=\"https://api.example.com\"\n className={`pl-8 ${editBaseUrlError ? 'border-red-500 focus:border-red-500' : ''}`}\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"edit-model-apiKey\" className=\"w-20 text-sm\">\n API key\n </Label>\n <div className=\"relative flex-1\">\n <Key className=\"absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"edit-model-apiKey\"\n type=\"password\"\n value={editingModel?.apiKey || ''}\n onChange={(e) =>\n setEditingModel((prev) =>\n prev ? {...prev, apiKey: e.target.value} : null,\n )\n }\n placeholder=\"Optional\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex justify-end gap-2 pt-1\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n setEditingModel(null);\n setEditBaseUrlError(false);\n closeEditCustomModelDialog();\n }}\n >\n Cancel\n </Button>\n <Button size=\"sm\" onClick={handleUpdateCustomModel}>\n <Settings className=\"mr-2 h-4 w-4\" /> Update\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n )}\n\n {/* Delete Model Confirmation Dialog */}\n {(allowEditProviderModels || allowCustomModels) && (\n <Dialog\n open={isDeleteModelDialogOpen}\n onOpenChange={(open) =>\n open ? openDeleteModelDialog() : closeDeleteModelDialog()\n }\n >\n <DialogTrigger asChild>\n {/* handled via onOpen button above */}\n </DialogTrigger>\n <DialogContent className=\"border-0 p-5\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"flex items-center gap-2 text-base\">\n <Trash2 className=\"h-4 w-4 text-red-500\" /> Delete Model\n </DialogTitle>\n <DialogDescription className=\"text-xs\">\n Are you sure you want to delete "{modelToDelete?.modelName}\n "? This action cannot be undone.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"flex justify-end gap-2 pt-1\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n setModelToDelete(null);\n closeDeleteModelDialog();\n }}\n >\n Cancel\n </Button>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={confirmDeleteModel}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" /> Delete\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n )}\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"AiModelsSettings.js","sourceRoot":"","sources":["../../src/components/AiModelsSettings.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useStoreWithAi} from '@sqlrooms/ai-core';\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n Input,\n Label,\n useDisclosure,\n toast,\n} from '@sqlrooms/ui';\nimport {\n Blocks,\n CirclePlus,\n Cpu,\n Key,\n Plus,\n Server,\n Settings,\n Trash2,\n} from 'lucide-react';\nimport {FC, useMemo, useState} from 'react';\nimport {useStoreWithAiSettings} from '../AiSettingsSlice';\n\nexport interface AiModelsSettingsProps {\n showProviderModels?: boolean;\n showCustomModels?: boolean;\n allowEditProviderModels?: boolean;\n allowCustomModels?: boolean;\n className?: string;\n}\n\nexport const AiModelsSettings: FC<AiModelsSettingsProps> = ({\n className = '',\n allowEditProviderModels = true,\n allowCustomModels = true,\n}) => {\n const aiConfig = useStoreWithAiSettings((s) => s.aiSettings.config);\n const setAiModel = useStoreWithAi((s) => s.ai.setAiModel);\n const addModelToProvider = useStoreWithAiSettings(\n (s) => s.aiSettings.addModelToProvider,\n );\n const removeModelFromProvider = useStoreWithAiSettings(\n (s) => s.aiSettings.removeModelFromProvider,\n );\n const addCustomModel = useStoreWithAiSettings(\n (s) => s.aiSettings.addCustomModel,\n );\n const updateCustomModel = useStoreWithAiSettings(\n (s) => s.aiSettings.updateCustomModel,\n );\n const removeCustomModel = useStoreWithAiSettings(\n (s) => s.aiSettings.removeCustomModel,\n );\n\n const providers = useMemo(\n () => Object.entries(aiConfig.providers),\n [aiConfig.providers],\n );\n const customModels = aiConfig.customModels || [];\n\n // Dialog state for adding a custom model\n const {\n isOpen: isCustomModelDialogOpen,\n onOpen: openCustomModelDialog,\n onClose: closeCustomModelDialog,\n } = useDisclosure();\n const [customName, setCustomName] = useState('');\n const [customBaseUrl, setCustomBaseUrl] = useState('');\n const [customApiKey, setCustomApiKey] = useState('');\n const [baseUrlError, setBaseUrlError] = useState(false);\n\n // Dialog state for editing a custom model\n const {\n isOpen: isEditCustomModelDialogOpen,\n onOpen: openEditCustomModelDialog,\n onClose: closeEditCustomModelDialog,\n } = useDisclosure();\n const [editingModel, setEditingModel] = useState<{\n oldModelName: string;\n modelName: string;\n baseUrl: string;\n apiKey: string;\n } | null>(null);\n const [editBaseUrlError, setEditBaseUrlError] = useState(false);\n\n // Dialog state for adding a model to a provider\n const {\n isOpen: isAddProviderModelDialogOpen,\n onOpen: openAddProviderModelDialog,\n onClose: closeAddProviderModelDialog,\n } = useDisclosure();\n const [selectedProviderKey, setSelectedProviderKey] = useState('');\n const [newModelName, setNewModelName] = useState('');\n\n // Dialog state for deleting a model\n const {\n isOpen: isDeleteModelDialogOpen,\n onOpen: openDeleteModelDialog,\n onClose: closeDeleteModelDialog,\n } = useDisclosure();\n const [modelToDelete, setModelToDelete] = useState<{\n type: 'provider' | 'custom';\n providerKey?: string;\n modelName: string;\n } | null>(null);\n\n const handleAddCustomToSession = () => {\n // Reset error states\n setBaseUrlError(false);\n\n // Validate required fields\n if (!customName.trim()) {\n toast.error('Model Name Required', {\n description: 'Please enter a model name.',\n });\n return;\n }\n\n if (!customBaseUrl.trim()) {\n setBaseUrlError(true);\n toast.error('Base URL Required', {\n description: 'Please enter a base URL for the model.',\n });\n return;\n }\n\n const trimmedName = customName.trim();\n\n // Add the custom model to the config\n addCustomModel(customBaseUrl.trim(), customApiKey.trim(), trimmedName);\n\n // Update the current session to use this custom model\n setAiModel('custom', trimmedName);\n\n // Show success message\n toast.success('Custom Model Added', {\n description: `Successfully added \"${trimmedName}\" to your custom models.`,\n });\n\n // Reset form\n setCustomName('');\n setCustomBaseUrl('');\n setCustomApiKey('');\n setBaseUrlError(false);\n closeCustomModelDialog();\n };\n\n const handleEditCustomModel = (modelName: string) => {\n const customModel = customModels.find((cm) => cm.modelName === modelName);\n if (customModel) {\n setEditingModel({\n oldModelName: modelName,\n modelName: modelName,\n baseUrl: customModel.baseUrl,\n apiKey: customModel.apiKey,\n });\n setEditBaseUrlError(false);\n openEditCustomModelDialog();\n }\n };\n\n const handleUpdateCustomModel = () => {\n if (!editingModel) return;\n\n // Reset error states\n setEditBaseUrlError(false);\n\n // Validate required fields\n if (!editingModel.modelName.trim()) {\n toast.error('Model Name Required', {\n description: 'Please enter a model name.',\n });\n return;\n }\n\n if (!editingModel.baseUrl.trim()) {\n setEditBaseUrlError(true);\n toast.error('Base URL Required', {\n description: 'Please enter a base URL for the model.',\n });\n return;\n }\n\n const trimmedName = editingModel.modelName.trim();\n const trimmedBaseUrl = editingModel.baseUrl.trim();\n const trimmedApiKey = editingModel.apiKey.trim();\n\n // Check for duplicate model names (excluding the current model being edited)\n const duplicateModel = customModels.find(\n (cm) =>\n cm.modelName.toLowerCase() === trimmedName.toLowerCase() &&\n cm.modelName !== editingModel.oldModelName,\n );\n\n if (duplicateModel) {\n toast.error('Model Name Already Exists', {\n description: `A custom model with the name \"${trimmedName}\" already exists.`,\n });\n return;\n }\n\n // Update the custom model\n updateCustomModel(\n editingModel.oldModelName,\n trimmedBaseUrl,\n trimmedApiKey,\n trimmedName,\n );\n\n // Show success message\n toast.success('Custom Model Updated', {\n description: `Successfully updated \"${trimmedName}\".`,\n });\n\n // Reset form and close dialog\n setEditingModel(null);\n setEditBaseUrlError(false);\n closeEditCustomModelDialog();\n };\n\n const handleOpenAddProviderModelDialog = (providerKey: string) => {\n setSelectedProviderKey(providerKey);\n setNewModelName('');\n openAddProviderModelDialog();\n };\n\n const handleAddModelToProvider = () => {\n if (!selectedProviderKey || !newModelName.trim()) return;\n\n // Check for duplicates\n const provider = aiConfig.providers[selectedProviderKey];\n const modelExists = provider?.models.some(\n (model) =>\n model.modelName.toLowerCase() === newModelName.trim().toLowerCase(),\n );\n\n if (modelExists) {\n toast.error('Model Already Exists', {\n description: `The model \"${newModelName.trim()}\" already exists in this provider.`,\n });\n return;\n }\n\n addModelToProvider(selectedProviderKey, newModelName.trim());\n setNewModelName('');\n closeAddProviderModelDialog();\n };\n\n const handleDeleteModel = (\n type: 'provider' | 'custom',\n providerKey: string | undefined,\n modelName: string,\n ) => {\n setModelToDelete({type, providerKey, modelName});\n openDeleteModelDialog();\n };\n\n const confirmDeleteModel = () => {\n if (!modelToDelete) return;\n\n if (modelToDelete.type === 'provider' && modelToDelete.providerKey) {\n removeModelFromProvider(\n modelToDelete.providerKey,\n modelToDelete.modelName,\n );\n toast.success('Model Deleted', {\n description: `Successfully removed \"${modelToDelete.modelName}\" from the provider.`,\n });\n } else if (modelToDelete.type === 'custom') {\n removeCustomModel(modelToDelete.modelName);\n toast.success('Custom Model Deleted', {\n description: `Successfully removed \"${modelToDelete.modelName}\" from custom models.`,\n });\n }\n\n setModelToDelete(null);\n closeDeleteModelDialog();\n };\n\n return (\n <div className={`space-y-2 ${className}`}>\n <label className=\"text-md flex items-center gap-2 pb-4 font-medium\">\n <Blocks className=\"h-4 w-4\" />\n Models\n </label>\n\n {/* Providers and their models */}\n <div className=\"w-full space-y-4\">\n {providers.map(([providerKey, provider]) => (\n <div key={providerKey} className=\"flex w-full items-start gap-4\">\n {/* Provider name column - 30% */}\n <div className=\"flex w-20 items-start justify-start text-sm font-medium\">\n {providerKey.charAt(0).toUpperCase() + providerKey.slice(1)}\n </div>\n\n {/* Models column - 65% (fills the rest) */}\n <div className=\"flex flex-1 flex-col items-start gap-2\">\n {provider.models.map((m) => (\n <div\n key={m.modelName}\n className=\"flex w-full items-center justify-between gap-2 border-b p-1 text-xs\"\n >\n <span className=\"text-foreground/90\">{m.modelName}</span>\n {allowEditProviderModels && (\n <Button\n size=\"xs\"\n variant=\"ghost\"\n onClick={() =>\n handleDeleteModel('provider', providerKey, m.modelName)\n }\n className=\"h-6 w-6 p-0 text-gray-500 hover:bg-gray-100 hover:text-gray-700\"\n >\n <Trash2 className=\"h-3 w-3\" />\n </Button>\n )}\n </div>\n ))}\n {allowEditProviderModels && (\n <Button\n size=\"xs\"\n variant=\"secondary\"\n onClick={() => handleOpenAddProviderModelDialog(providerKey)}\n >\n <CirclePlus className=\"h-3 w-3\" />\n Add\n </Button>\n )}\n </div>\n\n {/* add model button column - 5% */}\n <div className=\"flex w-12 items-start justify-end\"></div>\n </div>\n ))}\n\n {/* Custom models */}\n {allowCustomModels && (\n <div className=\"flex w-full items-start gap-4\">\n <div className=\"flex w-20 items-start justify-start text-sm font-medium\">\n Custom\n </div>\n <div className=\"flex flex-1 flex-col items-start gap-2\">\n {customModels.map((cm) => (\n <div\n key={cm.modelName}\n className=\"flex w-full items-center justify-between gap-2 border-b p-1 text-xs\"\n >\n <span className=\"text-foreground/90\">{cm.modelName}</span>\n <div className=\"flex w-full items-center justify-end\">\n <Button\n size=\"xs\"\n variant=\"ghost\"\n onClick={() =>\n handleDeleteModel('custom', undefined, cm.modelName)\n }\n className=\"h-6 w-6 p-0 text-gray-500 hover:bg-gray-100 hover:text-gray-700\"\n >\n <Trash2 className=\"h-3 w-3\" />\n </Button>\n <Button\n size=\"xs\"\n variant=\"ghost\"\n onClick={() => handleEditCustomModel(cm.modelName)}\n >\n <Settings className=\"h-3 w-3\" />\n </Button>\n </div>\n </div>\n ))}\n <Button\n size=\"xs\"\n variant=\"secondary\"\n onClick={() => {\n setCustomName('');\n setCustomBaseUrl('');\n setCustomApiKey('');\n setBaseUrlError(false);\n openCustomModelDialog();\n }}\n >\n <CirclePlus className=\"h-3 w-3\" />\n Add\n </Button>\n </div>\n <div className=\"flex w-12 items-start justify-end\"></div>\n </div>\n )}\n </div>\n\n {/* Add Custom Model Dialog */}\n {allowCustomModels && (\n <Dialog\n open={isCustomModelDialogOpen}\n onOpenChange={(open) => {\n if (open) {\n openCustomModelDialog();\n } else {\n setBaseUrlError(false);\n closeCustomModelDialog();\n }\n }}\n >\n <DialogTrigger asChild>\n {/* handled via onOpen button above */}\n </DialogTrigger>\n <DialogContent className=\"border-0 p-5\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"flex items-center gap-2 text-base\">\n <Blocks className=\"h-4 w-4\" /> Add Custom Model\n </DialogTitle>\n <DialogDescription className=\"text-xs\">\n Provide connection details for your model provider.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"custom-name\" className=\"w-20 text-sm\">\n Name\n </Label>\n <div className=\"relative flex-1\">\n <Cpu className=\"absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"custom-name\"\n value={customName}\n onChange={(e) => setCustomName(e.target.value)}\n placeholder=\"e.g., My cool model\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"custom-baseUrl\" className=\"w-20 text-sm\">\n baseUrl\n </Label>\n <div className=\"relative flex-1\">\n <Server className=\"absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"custom-baseUrl\"\n value={customBaseUrl}\n onChange={(e) => {\n setCustomBaseUrl(e.target.value);\n if (baseUrlError && e.target.value.trim()) {\n setBaseUrlError(false);\n }\n }}\n placeholder=\"https://api.example.com\"\n className={`pl-8 ${baseUrlError ? 'border-red-500 focus:border-red-500' : ''}`}\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"custom-apiKey\" className=\"w-20 text-sm\">\n API key\n </Label>\n <div className=\"relative flex-1\">\n <Key className=\"absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"custom-apiKey\"\n type=\"password\"\n value={customApiKey}\n onChange={(e) => setCustomApiKey(e.target.value)}\n placeholder=\"Optional\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex justify-end pt-1\">\n <Button size=\"sm\" onClick={handleAddCustomToSession}>\n <Plus className=\"mr-2 h-4 w-4\" /> Add\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n )}\n\n {/* Add Model to Provider Dialog */}\n <Dialog\n open={isAddProviderModelDialogOpen}\n onOpenChange={(open) =>\n open ? openAddProviderModelDialog() : closeAddProviderModelDialog()\n }\n >\n <DialogTrigger asChild>\n {/* handled via onOpen button above */}\n </DialogTrigger>\n <DialogContent className=\"border-0 p-5\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"flex items-center gap-2 text-base\">\n <Blocks className=\"h-4 w-4\" /> Add Model to Provider\n </DialogTitle>\n <DialogDescription className=\"text-xs\">\n Add a new model to{' '}\n {selectedProviderKey &&\n selectedProviderKey.charAt(0).toUpperCase() +\n selectedProviderKey.slice(1)}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"new-model-name\" className=\"w-24 text-sm\">\n Model Name\n </Label>\n <div className=\"relative flex-1\">\n <Cpu className=\"absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"new-model-name\"\n value={newModelName}\n onChange={(e) => setNewModelName(e.target.value)}\n placeholder=\"e.g., gpt-4-turbo\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex justify-end pt-1\">\n <Button size=\"sm\" onClick={handleAddModelToProvider}>\n <Plus className=\"mr-2 h-4 w-4\" /> Add Model\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n\n {/* Edit Custom Model Dialog */}\n {allowCustomModels && (\n <Dialog\n open={isEditCustomModelDialogOpen}\n onOpenChange={(open) => {\n if (open) {\n openEditCustomModelDialog();\n } else {\n setEditBaseUrlError(false);\n closeEditCustomModelDialog();\n }\n }}\n >\n <DialogTrigger asChild>\n {/* handled via onOpen button above */}\n </DialogTrigger>\n <DialogContent className=\"border-0 p-5\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"flex items-center gap-2 text-base\">\n <Settings className=\"h-4 w-4\" /> Edit Custom Model\n </DialogTitle>\n <DialogDescription className=\"text-xs\">\n Update the connection details for your custom model.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"edit-model-name\" className=\"w-20 text-sm\">\n Name\n </Label>\n <div className=\"relative flex-1\">\n <Cpu className=\"absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"edit-model-name\"\n value={editingModel?.modelName || ''}\n onChange={(e) =>\n setEditingModel((prev) =>\n prev ? {...prev, modelName: e.target.value} : null,\n )\n }\n placeholder=\"e.g., My cool model\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"edit-model-baseUrl\" className=\"w-20 text-sm\">\n baseUrl\n </Label>\n <div className=\"relative flex-1\">\n <Server className=\"absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"edit-model-baseUrl\"\n value={editingModel?.baseUrl || ''}\n onChange={(e) => {\n setEditingModel((prev) =>\n prev ? {...prev, baseUrl: e.target.value} : null,\n );\n if (editBaseUrlError && e.target.value.trim()) {\n setEditBaseUrlError(false);\n }\n }}\n placeholder=\"https://api.example.com\"\n className={`pl-8 ${editBaseUrlError ? 'border-red-500 focus:border-red-500' : ''}`}\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"edit-model-apiKey\" className=\"w-20 text-sm\">\n API key\n </Label>\n <div className=\"relative flex-1\">\n <Key className=\"absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"edit-model-apiKey\"\n type=\"password\"\n value={editingModel?.apiKey || ''}\n onChange={(e) =>\n setEditingModel((prev) =>\n prev ? {...prev, apiKey: e.target.value} : null,\n )\n }\n placeholder=\"Optional\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex justify-end gap-2 pt-1\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n setEditingModel(null);\n setEditBaseUrlError(false);\n closeEditCustomModelDialog();\n }}\n >\n Cancel\n </Button>\n <Button size=\"sm\" onClick={handleUpdateCustomModel}>\n <Settings className=\"mr-2 h-4 w-4\" /> Update\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n )}\n\n {/* Delete Model Confirmation Dialog */}\n {(allowEditProviderModels || allowCustomModels) && (\n <Dialog\n open={isDeleteModelDialogOpen}\n onOpenChange={(open) =>\n open ? openDeleteModelDialog() : closeDeleteModelDialog()\n }\n >\n <DialogTrigger asChild>\n {/* handled via onOpen button above */}\n </DialogTrigger>\n <DialogContent className=\"border-0 p-5\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"flex items-center gap-2 text-base\">\n <Trash2 className=\"h-4 w-4 text-red-500\" /> Delete Model\n </DialogTitle>\n <DialogDescription className=\"text-xs\">\n Are you sure you want to delete "{modelToDelete?.modelName}\n "? This action cannot be undone.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"flex justify-end gap-2 pt-1\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n setModelToDelete(null);\n closeDeleteModelDialog();\n }}\n >\n Cancel\n </Button>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={confirmDeleteModel}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" /> Delete\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n )}\n </div>\n );\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiProvidersSettings.d.ts","sourceRoot":"","sources":["../../src/components/AiProvidersSettings.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAC,EAAE,EAAW,MAAM,OAAO,CAAC;AA0B1C,eAAO,MAAM,mBAAmB,EAAE,
|
|
1
|
+
{"version":3,"file":"AiProvidersSettings.d.ts","sourceRoot":"","sources":["../../src/components/AiProvidersSettings.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAC,EAAE,EAAW,MAAM,OAAO,CAAC;AA0B1C,eAAO,MAAM,mBAAmB,EAAE,EA2TjC,CAAC"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React, { useState } from 'react';
|
|
3
|
-
import { Button, Input, Label, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogTrigger, DialogFooter, useDisclosure,
|
|
3
|
+
import { Button, Input, Label, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogTrigger, DialogFooter, useDisclosure, toast, } from '@sqlrooms/ui';
|
|
4
4
|
import { Cone, Settings, Plus, Server, Key, Trash2, CirclePlus, } from 'lucide-react';
|
|
5
5
|
import { useStoreWithAiSettings } from '../AiSettingsSlice';
|
|
6
6
|
export const AiProvidersSettings = () => {
|
|
7
|
-
const { toast } = useToast();
|
|
8
7
|
const updateProvider = useStoreWithAiSettings((state) => state.aiSettings.updateProvider);
|
|
9
8
|
const addProvider = useStoreWithAiSettings((state) => state.aiSettings.addProvider);
|
|
10
9
|
const removeProvider = useStoreWithAiSettings((state) => state.aiSettings.removeProvider);
|
|
@@ -32,10 +31,8 @@ export const AiProvidersSettings = () => {
|
|
|
32
31
|
if (newProviderKey) {
|
|
33
32
|
// Check if provider already exists
|
|
34
33
|
if (providers[newProviderKey]) {
|
|
35
|
-
toast({
|
|
36
|
-
title: 'Provider already exists',
|
|
34
|
+
toast.error('Provider already exists', {
|
|
37
35
|
description: `A provider with the key "${newProviderKey}" already exists. Please choose a different key.`,
|
|
38
|
-
variant: 'destructive',
|
|
39
36
|
});
|
|
40
37
|
return;
|
|
41
38
|
}
|
|
@@ -44,8 +41,7 @@ export const AiProvidersSettings = () => {
|
|
|
44
41
|
setNewProviderApiKey('');
|
|
45
42
|
setNewProviderBaseUrl('');
|
|
46
43
|
onClose();
|
|
47
|
-
toast({
|
|
48
|
-
title: 'Provider added successfully',
|
|
44
|
+
toast.success('Provider added successfully', {
|
|
49
45
|
description: `Provider "${newProviderKey}" has been added.`,
|
|
50
46
|
});
|
|
51
47
|
}
|
|
@@ -62,8 +58,7 @@ export const AiProvidersSettings = () => {
|
|
|
62
58
|
removeProvider(providerToDelete.key);
|
|
63
59
|
onDeleteClose();
|
|
64
60
|
setProviderToDelete(null);
|
|
65
|
-
toast({
|
|
66
|
-
title: 'Provider deleted successfully',
|
|
61
|
+
toast.success('Provider deleted successfully', {
|
|
67
62
|
description: `Provider "${providerToDelete.key}" and its associated models have been removed.`,
|
|
68
63
|
});
|
|
69
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiProvidersSettings.js","sourceRoot":"","sources":["../../src/components/AiProvidersSettings.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EAAK,QAAQ,EAAC,MAAM,OAAO,CAAC;AAC1C,OAAO,EACL,MAAM,EACN,KAAK,EACL,KAAK,EACL,MAAM,EACN,aAAa,EACb,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,aAAa,EACb,QAAQ,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,GAAG,EACH,MAAM,EACN,UAAU,GACX,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,sBAAsB,EAAC,MAAM,oBAAoB,CAAC;AAE1D,MAAM,CAAC,MAAM,mBAAmB,GAAO,GAAG,EAAE;IAC1C,MAAM,EAAC,KAAK,EAAC,GAAG,QAAQ,EAAE,CAAC;IAC3B,MAAM,cAAc,GAAG,sBAAsB,CAC3C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,cAAc,CAC3C,CAAC;IACF,MAAM,WAAW,GAAG,sBAAsB,CACxC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CACxC,CAAC;IACF,MAAM,cAAc,GAAG,sBAAsB,CAC3C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,cAAc,CAC3C,CAAC;IACF,MAAM,SAAS,GAAG,sBAAsB,CACtC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAC7C,CAAC;IACF,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACxC,MAAM,MAAM,GAAsD,EAAE,CAAC;QACrE,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,EAAE;YACpD,MAAM,CAAC,GAAG,CAAC,GAAG;gBACZ,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,OAAO,EAAE,QAAQ,CAAC,OAAO;aAC1B,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;IAEhB,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CACxD,IAAI,GAAG,EAAE,CACV,CAAC;IAEF,yCAAyC;IACzC,MAAM,EAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAC,GAAG,aAAa,EAAE,CAAC;IAClD,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzD,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC/D,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEjE,uCAAuC;IACvC,MAAM,EACJ,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,aAAa,GACvB,GAAG,aAAa,EAAE,CAAC;IACpB,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAE9C,IAAI,CAAC,CAAC;IAEhB,MAAM,iBAAiB,GAAG,GAAG,EAAE;QAC7B,IAAI,cAAc,EAAE,CAAC;YACnB,mCAAmC;YACnC,IAAI,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC;gBAC9B,KAAK,CAAC;oBACJ,KAAK,EAAE,yBAAyB;oBAChC,WAAW,EAAE,4BAA4B,cAAc,kDAAkD;oBACzG,OAAO,EAAE,aAAa;iBACvB,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,WAAW,CAAC,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,CAAC,CAAC;YACnE,iBAAiB,CAAC,EAAE,CAAC,CAAC;YACtB,oBAAoB,CAAC,EAAE,CAAC,CAAC;YACzB,qBAAqB,CAAC,EAAE,CAAC,CAAC;YAC1B,OAAO,EAAE,CAAC;YAEV,KAAK,CAAC;gBACJ,KAAK,EAAE,6BAA6B;gBACpC,WAAW,EAAE,aAAa,cAAc,mBAAmB;aAC5D,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,CAC3B,WAAmB,EACnB,KAA2B,EAC3B,KAAa,EACb,EAAE;QACF,cAAc,CAAC,WAAW,EAAE,EAAC,CAAC,KAAK,CAAC,EAAE,KAAK,EAAC,CAAC,CAAC;IAChD,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,CAAC,WAAmB,EAAE,EAAE;QACnD,mBAAmB,CAAC,EAAC,GAAG,EAAE,WAAW,EAAC,CAAC,CAAC;QACxC,YAAY,EAAE,CAAC;IACjB,CAAC,CAAC;IAEF,MAAM,qBAAqB,GAAG,GAAG,EAAE;QACjC,IAAI,gBAAgB,EAAE,CAAC;YACrB,cAAc,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACrC,aAAa,EAAE,CAAC;YAChB,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAE1B,KAAK,CAAC;gBACJ,KAAK,EAAE,+BAA+B;gBACtC,WAAW,EAAE,aAAa,gBAAgB,CAAC,GAAG,gDAAgD;aAC/F,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,sBAAsB,GAAG,CAAC,WAAmB,EAAE,EAAE;QACrD,oBAAoB,CAAC,CAAC,IAAI,EAAE,EAAE;YAC5B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC5B,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YAC1B,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,WAAW,aACxB,iBAAO,SAAS,EAAC,kDAAkD,aACjE,KAAC,IAAI,IAAC,SAAS,EAAC,SAAS,GAAG,iBAEtB,EAGR,cAAK,SAAS,EAAC,WAAW,YACvB,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,EAAE;oBAC9D,MAAM,UAAU,GAAG,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;oBAEtD,OAAO,CACL,eAAuB,SAAS,EAAC,0BAA0B,aAEzD,eAAK,SAAS,EAAC,yBAAyB,aACtC,KAAC,KAAK,IAAC,SAAS,EAAC,uBAAuB,YACrC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,GACrD,EACR,KAAC,KAAK,IACJ,EAAE,EAAE,GAAG,WAAW,SAAS,EAC3B,IAAI,EAAC,UAAU,EACf,KAAK,EAAE,QAAQ,CAAC,MAAM,EACtB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CACd,oBAAoB,CAAC,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAE7D,WAAW,EAAC,eAAe,EAC3B,SAAS,EAAC,QAAQ,GAClB,EACF,KAAC,MAAM,IACL,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,MAAM,EACX,OAAO,EAAE,GAAG,EAAE,CAAC,oBAAoB,CAAC,WAAW,CAAC,EAChD,SAAS,EAAC,yEAAyE,YAEnF,KAAC,MAAM,IAAC,SAAS,EAAC,SAAS,GAAG,GACvB,EACT,KAAC,MAAM,IACL,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,MAAM,EACX,OAAO,EAAE,GAAG,EAAE,CAAC,sBAAsB,CAAC,WAAW,CAAC,EAClD,SAAS,EAAC,kBAAkB,YAE5B,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,GACzB,IACL,EAGL,UAAU,IAAI,CACb,eAAK,SAAS,EAAC,8BAA8B,aAC3C,cAAK,SAAS,EAAC,eAAe,GAAG,EAAC,GAAG,EAErC,eAAK,SAAS,EAAC,gCAAgC,aAC7C,KAAC,KAAK,IACJ,OAAO,EAAE,GAAG,WAAW,UAAU,EACjC,SAAS,EAAC,wCAAwC,yBAG5C,EACR,KAAC,KAAK,IACJ,EAAE,EAAE,GAAG,WAAW,UAAU,EAC5B,IAAI,EAAC,KAAK,EACV,KAAK,EAAE,QAAQ,CAAC,OAAO,EACvB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CACd,oBAAoB,CAClB,WAAW,EACX,SAAS,EACT,CAAC,CAAC,MAAM,CAAC,KAAK,CACf,EAEH,WAAW,EAAC,gBAAgB,EAC5B,SAAS,EAAC,QAAQ,GAClB,IACE,EACN,cAAK,SAAS,EAAC,eAAe,GAAG,EAAC,GAAG,IAEjC,CACP,KAhEO,WAAW,CAiEf,CACP,CAAC;gBACJ,CAAC,CAAC,GACE,EAGN,cAAK,SAAS,EAAC,iBAAiB,YAC9B,MAAC,MAAM,IAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,IAAI,aACpD,KAAC,UAAU,IAAC,SAAS,EAAC,SAAS,GAAG,WAE3B,GACL,EAGN,MAAC,MAAM,IACL,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,aAErD,KAAC,aAAa,IAAC,OAAO,SAEN,EAChB,MAAC,aAAa,IAAC,SAAS,EAAC,cAAc,aACrC,MAAC,YAAY,IAAC,SAAS,EAAC,MAAM,aAC5B,MAAC,WAAW,IAAC,SAAS,EAAC,mCAAmC,aACxD,KAAC,IAAI,IAAC,SAAS,EAAC,SAAS,GAAG,yBAChB,EACd,KAAC,iBAAiB,IAAC,SAAS,EAAC,SAAS,qEAElB,IACP,EAEf,eAAK,SAAS,EAAC,WAAW,aACxB,eAAK,SAAS,EAAC,yBAAyB,aACtC,KAAC,KAAK,IAAC,OAAO,EAAC,kBAAkB,EAAC,SAAS,EAAC,cAAc,oBAElD,EACR,eAAK,SAAS,EAAC,iBAAiB,aAC9B,KAAC,IAAI,IAAC,SAAS,EAAC,kDAAkD,GAAG,EACrE,KAAC,KAAK,IACJ,EAAE,EAAC,kBAAkB,EACrB,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAClD,WAAW,EAAC,iBAAiB,EAC7B,SAAS,EAAC,MAAM,GAChB,IACE,IACF,EAEN,eAAK,SAAS,EAAC,yBAAyB,aACtC,KAAC,KAAK,IAAC,OAAO,EAAC,sBAAsB,EAAC,SAAS,EAAC,cAAc,wBAEtD,EACR,eAAK,SAAS,EAAC,iBAAiB,aAC9B,KAAC,GAAG,IAAC,SAAS,EAAC,kDAAkD,GAAG,EACpE,KAAC,KAAK,IACJ,EAAE,EAAC,sBAAsB,EACzB,IAAI,EAAC,UAAU,EACf,KAAK,EAAE,iBAAiB,EACxB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACrD,WAAW,EAAC,eAAe,EAC3B,SAAS,EAAC,MAAM,GAChB,IACE,IACF,EAEN,eAAK,SAAS,EAAC,yBAAyB,aACtC,KAAC,KAAK,IAAC,OAAO,EAAC,kBAAkB,EAAC,SAAS,EAAC,cAAc,wBAElD,EACR,eAAK,SAAS,EAAC,iBAAiB,aAC9B,KAAC,MAAM,IAAC,SAAS,EAAC,kDAAkD,GAAG,EACvE,KAAC,KAAK,IACJ,EAAE,EAAC,kBAAkB,EACrB,IAAI,EAAC,KAAK,EACV,KAAK,EAAE,kBAAkB,EACzB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACtD,WAAW,EAAC,gBAAgB,EAC5B,SAAS,EAAC,MAAM,GAChB,IACE,IACF,EAEN,cAAK,SAAS,EAAC,uBAAuB,YACpC,MAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,iBAAiB,aAC1C,KAAC,IAAI,IAAC,SAAS,EAAC,cAAc,GAAG,qBAC1B,GACL,IACF,IACQ,IACT,EAGT,KAAC,MAAM,IACL,IAAI,EAAE,YAAY,EAClB,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,YAEjE,MAAC,aAAa,IAAC,SAAS,EAAC,cAAc,aACrC,MAAC,YAAY,IAAC,SAAS,EAAC,MAAM,aAC5B,MAAC,WAAW,IAAC,SAAS,EAAC,oDAAoD,aACzE,KAAC,MAAM,IAAC,SAAS,EAAC,SAAS,GAAG,wBAClB,EACd,KAAC,iBAAiB,IAAC,SAAS,EAAC,SAAS,uHAGlB,IACP,EAEf,eAAK,SAAS,EAAC,MAAM,aACnB,aAAG,SAAS,EAAC,SAAS,6DACyB,GAAG,EAChD,uCAAgB,gBAAgB,EAAE,GAAG,cAAiB,SACpD,EACJ,YAAG,SAAS,EAAC,oCAAoC,+EAE7C,IACA,EAEN,MAAC,YAAY,IAAC,SAAS,EAAC,OAAO,aAC7B,KAAC,MAAM,IAAC,OAAO,EAAC,SAAS,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,aAAa,uBAEjD,EACT,MAAC,MAAM,IACL,OAAO,EAAC,aAAa,EACrB,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,qBAAqB,aAE9B,KAAC,MAAM,IAAC,SAAS,EAAC,cAAc,GAAG,uBAE5B,IACI,IACD,GACT,IACL,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import React, {FC, useState} from 'react';\nimport {\n Button,\n Input,\n Label,\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogTrigger,\n DialogFooter,\n useDisclosure,\n useToast,\n} from '@sqlrooms/ui';\nimport {\n Cone,\n Settings,\n Plus,\n Server,\n Key,\n Trash2,\n CirclePlus,\n} from 'lucide-react';\nimport {useStoreWithAiSettings} from '../AiSettingsSlice';\n\nexport const AiProvidersSettings: FC = () => {\n const {toast} = useToast();\n const updateProvider = useStoreWithAiSettings(\n (state) => state.aiSettings.updateProvider,\n );\n const addProvider = useStoreWithAiSettings(\n (state) => state.aiSettings.addProvider,\n );\n const removeProvider = useStoreWithAiSettings(\n (state) => state.aiSettings.removeProvider,\n );\n const providers = useStoreWithAiSettings(\n (state) => state.aiSettings.config.providers,\n );\n const modelProviders = React.useMemo(() => {\n const result: Record<string, {apiKey: string; baseUrl: string}> = {};\n Object.entries(providers).forEach(([key, provider]) => {\n result[key] = {\n apiKey: provider.apiKey,\n baseUrl: provider.baseUrl,\n };\n });\n return result;\n }, [providers]);\n\n const [expandedProviders, setExpandedProviders] = useState<Set<string>>(\n new Set(),\n );\n\n // Dialog state for adding a new provider\n const {isOpen, onOpen, onClose} = useDisclosure();\n const [newProviderKey, setNewProviderKey] = useState('');\n const [newProviderApiKey, setNewProviderApiKey] = useState('');\n const [newProviderBaseUrl, setNewProviderBaseUrl] = useState('');\n\n // Dialog state for delete confirmation\n const {\n isOpen: isDeleteOpen,\n onOpen: onDeleteOpen,\n onClose: onDeleteClose,\n } = useDisclosure();\n const [providerToDelete, setProviderToDelete] = useState<{\n key: string;\n } | null>(null);\n\n const handleAddProvider = () => {\n if (newProviderKey) {\n // Check if provider already exists\n if (providers[newProviderKey]) {\n toast({\n title: 'Provider already exists',\n description: `A provider with the key \"${newProviderKey}\" already exists. Please choose a different key.`,\n variant: 'destructive',\n });\n return;\n }\n\n addProvider(newProviderKey, newProviderBaseUrl, newProviderApiKey);\n setNewProviderKey('');\n setNewProviderApiKey('');\n setNewProviderBaseUrl('');\n onClose();\n\n toast({\n title: 'Provider added successfully',\n description: `Provider \"${newProviderKey}\" has been added.`,\n });\n }\n };\n\n const handleUpdateProvider = (\n providerKey: string,\n field: 'apiKey' | 'baseUrl',\n value: string,\n ) => {\n updateProvider(providerKey, {[field]: value});\n };\n\n const handleDeleteProvider = (providerKey: string) => {\n setProviderToDelete({key: providerKey});\n onDeleteOpen();\n };\n\n const confirmDeleteProvider = () => {\n if (providerToDelete) {\n removeProvider(providerToDelete.key);\n onDeleteClose();\n setProviderToDelete(null);\n\n toast({\n title: 'Provider deleted successfully',\n description: `Provider \"${providerToDelete.key}\" and its associated models have been removed.`,\n });\n }\n };\n\n const toggleProviderExpanded = (providerKey: string) => {\n setExpandedProviders((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(providerKey)) {\n newSet.delete(providerKey);\n } else {\n newSet.add(providerKey);\n }\n return newSet;\n });\n };\n\n return (\n <div className=\"space-y-2\">\n <label className=\"text-md flex items-center gap-2 pb-6 font-medium\">\n <Cone className=\"h-4 w-4\" />\n Providers\n </label>\n\n {/* Existing Providers */}\n <div className=\"space-y-1\">\n {Object.entries(modelProviders).map(([providerKey, provider]) => {\n const isExpanded = expandedProviders.has(providerKey);\n\n return (\n <div key={providerKey} className=\"space-y-0 rounded-lg p-0\">\n {/* First row: Provider name, API key input, delete button, and cogwheel button */}\n <div className=\"flex items-center gap-3\">\n <Label className=\"w-20 shrink-0 text-sm\">\n {providerKey.charAt(0).toUpperCase() + providerKey.slice(1)}\n </Label>\n <Input\n id={`${providerKey}-apiKey`}\n type=\"password\"\n value={provider.apiKey}\n onChange={(e) =>\n handleUpdateProvider(providerKey, 'apiKey', e.target.value)\n }\n placeholder=\"Enter API key\"\n className=\"flex-1\"\n />\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => handleDeleteProvider(providerKey)}\n className=\"h-6 h-8 w-6 w-8 p-0 text-gray-500 hover:bg-gray-100 hover:text-gray-700\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => toggleProviderExpanded(providerKey)}\n className=\"h-8 w-8 shrink-0\"\n >\n <Settings className=\"h-4 w-4\" />\n </Button>\n </div>\n\n {/* Second row: baseUrl input (toggleable) */}\n {isExpanded && (\n <div className=\"flex items-center gap-3 pt-1\">\n <div className=\"w-20 shrink-0\" />{' '}\n {/* Spacer to align with provider name above */}\n <div className=\"flex flex-1 items-center gap-3\">\n <Label\n htmlFor={`${providerKey}-baseUrl`}\n className=\"text-muted-foreground shrink-0 text-xs\"\n >\n baseUrl:\n </Label>\n <Input\n id={`${providerKey}-baseUrl`}\n type=\"url\"\n value={provider.baseUrl}\n onChange={(e) =>\n handleUpdateProvider(\n providerKey,\n 'baseUrl',\n e.target.value,\n )\n }\n placeholder=\"Enter base URL\"\n className=\"flex-1\"\n />\n </div>\n <div className=\"w-16 shrink-0\" />{' '}\n {/* Spacer to align with delete and cogwheel buttons above */}\n </div>\n )}\n </div>\n );\n })}\n </div>\n\n {/* Add New Provider */}\n <div className=\"flex w-full p-2\">\n <Button onClick={onOpen} variant=\"secondary\" size=\"sm\">\n <CirclePlus className=\"h-3 w-3\" />\n Add\n </Button>\n </div>\n\n {/* Add New Provider Dialog */}\n <Dialog\n open={isOpen}\n onOpenChange={(open) => (open ? onOpen() : onClose())}\n >\n <DialogTrigger asChild>\n {/* handled via onOpen button above */}\n </DialogTrigger>\n <DialogContent className=\"border-0 p-5\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"flex items-center gap-2 text-base\">\n <Cone className=\"h-4 w-4\" /> Add New Provider\n </DialogTitle>\n <DialogDescription className=\"text-xs\">\n Configure a new model provider with API credentials.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"new-provider-key\" className=\"w-20 text-sm\">\n Key\n </Label>\n <div className=\"relative flex-1\">\n <Cone className=\"absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"new-provider-key\"\n value={newProviderKey}\n onChange={(e) => setNewProviderKey(e.target.value)}\n placeholder=\"e.g., anthropic\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"new-provider-api-key\" className=\"w-20 text-sm\">\n API Key\n </Label>\n <div className=\"relative flex-1\">\n <Key className=\"absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"new-provider-api-key\"\n type=\"password\"\n value={newProviderApiKey}\n onChange={(e) => setNewProviderApiKey(e.target.value)}\n placeholder=\"Enter API key\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"new-provider-url\" className=\"w-20 text-sm\">\n baseUrl\n </Label>\n <div className=\"relative flex-1\">\n <Server className=\"absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"new-provider-url\"\n type=\"url\"\n value={newProviderBaseUrl}\n onChange={(e) => setNewProviderBaseUrl(e.target.value)}\n placeholder=\"Enter base URL\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex justify-end pt-1\">\n <Button size=\"sm\" onClick={handleAddProvider}>\n <Plus className=\"mr-2 h-4 w-4\" /> Add Provider\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n\n {/* Delete Confirmation Dialog */}\n <Dialog\n open={isDeleteOpen}\n onOpenChange={(open) => (open ? onDeleteOpen() : onDeleteClose())}\n >\n <DialogContent className=\"border-0 p-5\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"text-destructive flex items-center gap-2 text-base\">\n <Trash2 className=\"h-4 w-4\" /> Delete Provider\n </DialogTitle>\n <DialogDescription className=\"text-xs\">\n This action cannot be undone. This will permanently delete the\n provider and all its associated models.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"py-2\">\n <p className=\"text-sm\">\n Are you sure you want to delete the provider{' '}\n <strong>“{providerToDelete?.key}”</strong>?\n </p>\n <p className=\"text-muted-foreground mt-1 text-xs\">\n All models associated with this provider will also be removed.\n </p>\n </div>\n\n <DialogFooter className=\"gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={onDeleteClose}>\n Cancel\n </Button>\n <Button\n variant=\"destructive\"\n size=\"sm\"\n onClick={confirmDeleteProvider}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n Delete Provider\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"AiProvidersSettings.js","sourceRoot":"","sources":["../../src/components/AiProvidersSettings.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {FC, useState} from 'react';\nimport {\n Button,\n Input,\n Label,\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogTrigger,\n DialogFooter,\n useDisclosure,\n toast,\n} from '@sqlrooms/ui';\nimport {\n Cone,\n Settings,\n Plus,\n Server,\n Key,\n Trash2,\n CirclePlus,\n} from 'lucide-react';\nimport {useStoreWithAiSettings} from '../AiSettingsSlice';\n\nexport const AiProvidersSettings: FC = () => {\n const updateProvider = useStoreWithAiSettings(\n (state) => state.aiSettings.updateProvider,\n );\n const addProvider = useStoreWithAiSettings(\n (state) => state.aiSettings.addProvider,\n );\n const removeProvider = useStoreWithAiSettings(\n (state) => state.aiSettings.removeProvider,\n );\n const providers = useStoreWithAiSettings(\n (state) => state.aiSettings.config.providers,\n );\n const modelProviders = React.useMemo(() => {\n const result: Record<string, {apiKey: string; baseUrl: string}> = {};\n Object.entries(providers).forEach(([key, provider]) => {\n result[key] = {\n apiKey: provider.apiKey,\n baseUrl: provider.baseUrl,\n };\n });\n return result;\n }, [providers]);\n\n const [expandedProviders, setExpandedProviders] = useState<Set<string>>(\n new Set(),\n );\n\n // Dialog state for adding a new provider\n const {isOpen, onOpen, onClose} = useDisclosure();\n const [newProviderKey, setNewProviderKey] = useState('');\n const [newProviderApiKey, setNewProviderApiKey] = useState('');\n const [newProviderBaseUrl, setNewProviderBaseUrl] = useState('');\n\n // Dialog state for delete confirmation\n const {\n isOpen: isDeleteOpen,\n onOpen: onDeleteOpen,\n onClose: onDeleteClose,\n } = useDisclosure();\n const [providerToDelete, setProviderToDelete] = useState<{\n key: string;\n } | null>(null);\n\n const handleAddProvider = () => {\n if (newProviderKey) {\n // Check if provider already exists\n if (providers[newProviderKey]) {\n toast.error('Provider already exists', {\n description: `A provider with the key \"${newProviderKey}\" already exists. Please choose a different key.`,\n });\n return;\n }\n\n addProvider(newProviderKey, newProviderBaseUrl, newProviderApiKey);\n setNewProviderKey('');\n setNewProviderApiKey('');\n setNewProviderBaseUrl('');\n onClose();\n\n toast.success('Provider added successfully', {\n description: `Provider \"${newProviderKey}\" has been added.`,\n });\n }\n };\n\n const handleUpdateProvider = (\n providerKey: string,\n field: 'apiKey' | 'baseUrl',\n value: string,\n ) => {\n updateProvider(providerKey, {[field]: value});\n };\n\n const handleDeleteProvider = (providerKey: string) => {\n setProviderToDelete({key: providerKey});\n onDeleteOpen();\n };\n\n const confirmDeleteProvider = () => {\n if (providerToDelete) {\n removeProvider(providerToDelete.key);\n onDeleteClose();\n setProviderToDelete(null);\n\n toast.success('Provider deleted successfully', {\n description: `Provider \"${providerToDelete.key}\" and its associated models have been removed.`,\n });\n }\n };\n\n const toggleProviderExpanded = (providerKey: string) => {\n setExpandedProviders((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(providerKey)) {\n newSet.delete(providerKey);\n } else {\n newSet.add(providerKey);\n }\n return newSet;\n });\n };\n\n return (\n <div className=\"space-y-2\">\n <label className=\"text-md flex items-center gap-2 pb-6 font-medium\">\n <Cone className=\"h-4 w-4\" />\n Providers\n </label>\n\n {/* Existing Providers */}\n <div className=\"space-y-1\">\n {Object.entries(modelProviders).map(([providerKey, provider]) => {\n const isExpanded = expandedProviders.has(providerKey);\n\n return (\n <div key={providerKey} className=\"space-y-0 rounded-lg p-0\">\n {/* First row: Provider name, API key input, delete button, and cogwheel button */}\n <div className=\"flex items-center gap-3\">\n <Label className=\"w-20 shrink-0 text-sm\">\n {providerKey.charAt(0).toUpperCase() + providerKey.slice(1)}\n </Label>\n <Input\n id={`${providerKey}-apiKey`}\n type=\"password\"\n value={provider.apiKey}\n onChange={(e) =>\n handleUpdateProvider(providerKey, 'apiKey', e.target.value)\n }\n placeholder=\"Enter API key\"\n className=\"flex-1\"\n />\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => handleDeleteProvider(providerKey)}\n className=\"h-6 h-8 w-6 w-8 p-0 text-gray-500 hover:bg-gray-100 hover:text-gray-700\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => toggleProviderExpanded(providerKey)}\n className=\"h-8 w-8 shrink-0\"\n >\n <Settings className=\"h-4 w-4\" />\n </Button>\n </div>\n\n {/* Second row: baseUrl input (toggleable) */}\n {isExpanded && (\n <div className=\"flex items-center gap-3 pt-1\">\n <div className=\"w-20 shrink-0\" />{' '}\n {/* Spacer to align with provider name above */}\n <div className=\"flex flex-1 items-center gap-3\">\n <Label\n htmlFor={`${providerKey}-baseUrl`}\n className=\"text-muted-foreground shrink-0 text-xs\"\n >\n baseUrl:\n </Label>\n <Input\n id={`${providerKey}-baseUrl`}\n type=\"url\"\n value={provider.baseUrl}\n onChange={(e) =>\n handleUpdateProvider(\n providerKey,\n 'baseUrl',\n e.target.value,\n )\n }\n placeholder=\"Enter base URL\"\n className=\"flex-1\"\n />\n </div>\n <div className=\"w-16 shrink-0\" />{' '}\n {/* Spacer to align with delete and cogwheel buttons above */}\n </div>\n )}\n </div>\n );\n })}\n </div>\n\n {/* Add New Provider */}\n <div className=\"flex w-full p-2\">\n <Button onClick={onOpen} variant=\"secondary\" size=\"sm\">\n <CirclePlus className=\"h-3 w-3\" />\n Add\n </Button>\n </div>\n\n {/* Add New Provider Dialog */}\n <Dialog\n open={isOpen}\n onOpenChange={(open) => (open ? onOpen() : onClose())}\n >\n <DialogTrigger asChild>\n {/* handled via onOpen button above */}\n </DialogTrigger>\n <DialogContent className=\"border-0 p-5\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"flex items-center gap-2 text-base\">\n <Cone className=\"h-4 w-4\" /> Add New Provider\n </DialogTitle>\n <DialogDescription className=\"text-xs\">\n Configure a new model provider with API credentials.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"new-provider-key\" className=\"w-20 text-sm\">\n Key\n </Label>\n <div className=\"relative flex-1\">\n <Cone className=\"absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"new-provider-key\"\n value={newProviderKey}\n onChange={(e) => setNewProviderKey(e.target.value)}\n placeholder=\"e.g., anthropic\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"new-provider-api-key\" className=\"w-20 text-sm\">\n API Key\n </Label>\n <div className=\"relative flex-1\">\n <Key className=\"absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"new-provider-api-key\"\n type=\"password\"\n value={newProviderApiKey}\n onChange={(e) => setNewProviderApiKey(e.target.value)}\n placeholder=\"Enter API key\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <Label htmlFor=\"new-provider-url\" className=\"w-20 text-sm\">\n baseUrl\n </Label>\n <div className=\"relative flex-1\">\n <Server className=\"absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2\" />\n <Input\n id=\"new-provider-url\"\n type=\"url\"\n value={newProviderBaseUrl}\n onChange={(e) => setNewProviderBaseUrl(e.target.value)}\n placeholder=\"Enter base URL\"\n className=\"pl-8\"\n />\n </div>\n </div>\n\n <div className=\"flex justify-end pt-1\">\n <Button size=\"sm\" onClick={handleAddProvider}>\n <Plus className=\"mr-2 h-4 w-4\" /> Add Provider\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n\n {/* Delete Confirmation Dialog */}\n <Dialog\n open={isDeleteOpen}\n onOpenChange={(open) => (open ? onDeleteOpen() : onDeleteClose())}\n >\n <DialogContent className=\"border-0 p-5\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"text-destructive flex items-center gap-2 text-base\">\n <Trash2 className=\"h-4 w-4\" /> Delete Provider\n </DialogTitle>\n <DialogDescription className=\"text-xs\">\n This action cannot be undone. This will permanently delete the\n provider and all its associated models.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"py-2\">\n <p className=\"text-sm\">\n Are you sure you want to delete the provider{' '}\n <strong>“{providerToDelete?.key}”</strong>?\n </p>\n <p className=\"text-muted-foreground mt-1 text-xs\">\n All models associated with this provider will also be removed.\n </p>\n </div>\n\n <DialogFooter className=\"gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={onDeleteClose}>\n Cancel\n </Button>\n <Button\n variant=\"destructive\"\n size=\"sm\"\n onClick={confirmDeleteProvider}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n Delete Provider\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n );\n};\n"]}
|
|
@@ -9,7 +9,7 @@ export const AiSettingsPanelBase = ({ disclosure, children }) => {
|
|
|
9
9
|
const { isOpen, onClose } = disclosure;
|
|
10
10
|
if (!isOpen)
|
|
11
11
|
return null;
|
|
12
|
-
return (_jsx("div", { className: "bg-background border-border w-full rounded-lg border shadow-sm", children: _jsxs("div", { className: "relative flex flex-col gap-12 overflow-y-auto p-6", children: [_jsx(Button, { variant: "ghost", size: "icon", onClick: onClose, className: "absolute
|
|
12
|
+
return (_jsx("div", { className: "bg-background border-border w-full rounded-lg border shadow-sm", children: _jsxs("div", { className: "relative flex flex-col gap-12 overflow-y-auto p-6", children: [_jsx(Button, { variant: "ghost", size: "icon", onClick: onClose, className: "absolute top-2 right-2 z-10", children: _jsx(X, { className: "h-4 w-4" }) }), children] }) }));
|
|
13
13
|
};
|
|
14
14
|
export const AiSettingsPanel = Object.assign(AiSettingsPanelBase, {
|
|
15
15
|
ProvidersSettings: AiProvidersSettings,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiSettingsPanel.js","sourceRoot":"","sources":["../../src/components/AiSettingsPanel.tsx"],"names":[],"mappings":";AACA,OAAO,EAAC,MAAM,EAA2B,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAC,CAAC,EAAC,MAAM,cAAc,CAAC;AAE/B,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAC,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAMpD,MAAM,CAAC,MAAM,mBAAmB,GAE5B,CAAC,EAAC,UAAU,EAAE,QAAQ,EAAC,EAAE,EAAE;IAC7B,MAAM,EAAC,MAAM,EAAE,OAAO,EAAC,GAAG,UAAU,CAAC;IACrC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,OAAO,CACL,cAAK,SAAS,EAAC,gEAAgE,YAC7E,eAAK,SAAS,EAAC,mDAAmD,aAChE,KAAC,MAAM,IACL,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,SAAS,EAAC,6BAA6B,YAEvC,KAAC,CAAC,IAAC,SAAS,EAAC,SAAS,GAAG,GAClB,EACR,QAAQ,IACL,GACF,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE;IAChE,iBAAiB,EAAE,mBAAmB;IACtC,cAAc,EAAE,gBAAgB;IAChC,UAAU,EAAE,YAAY;IACxB,uBAAuB,EAAE,iBAAiB;CAC3C,CAAC,CAAC","sourcesContent":["import {FC, PropsWithChildren} from 'react';\nimport {Button, UseDisclosureReturnValue} from '@sqlrooms/ui';\nimport {X} from 'lucide-react';\n\nimport {AiModelParameters} from './AiModelParameters';\nimport {AiModelUsage} from './AiModelUsage';\nimport {AiProvidersSettings} from './AiProvidersSettings';\nimport {AiModelsSettings} from './AiModelsSettings';\n\ninterface AiSettingsPanelProps {\n disclosure: UseDisclosureReturnValue;\n}\n\nexport const AiSettingsPanelBase: FC<\n PropsWithChildren<AiSettingsPanelProps>\n> = ({disclosure, children}) => {\n const {isOpen, onClose} = disclosure;\n if (!isOpen) return null;\n\n return (\n <div className=\"bg-background border-border w-full rounded-lg border shadow-sm\">\n <div className=\"relative flex flex-col gap-12 overflow-y-auto p-6\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={onClose}\n className=\"absolute
|
|
1
|
+
{"version":3,"file":"AiSettingsPanel.js","sourceRoot":"","sources":["../../src/components/AiSettingsPanel.tsx"],"names":[],"mappings":";AACA,OAAO,EAAC,MAAM,EAA2B,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAC,CAAC,EAAC,MAAM,cAAc,CAAC;AAE/B,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAC,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAMpD,MAAM,CAAC,MAAM,mBAAmB,GAE5B,CAAC,EAAC,UAAU,EAAE,QAAQ,EAAC,EAAE,EAAE;IAC7B,MAAM,EAAC,MAAM,EAAE,OAAO,EAAC,GAAG,UAAU,CAAC;IACrC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,OAAO,CACL,cAAK,SAAS,EAAC,gEAAgE,YAC7E,eAAK,SAAS,EAAC,mDAAmD,aAChE,KAAC,MAAM,IACL,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,SAAS,EAAC,6BAA6B,YAEvC,KAAC,CAAC,IAAC,SAAS,EAAC,SAAS,GAAG,GAClB,EACR,QAAQ,IACL,GACF,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE;IAChE,iBAAiB,EAAE,mBAAmB;IACtC,cAAc,EAAE,gBAAgB;IAChC,UAAU,EAAE,YAAY;IACxB,uBAAuB,EAAE,iBAAiB;CAC3C,CAAC,CAAC","sourcesContent":["import {FC, PropsWithChildren} from 'react';\nimport {Button, UseDisclosureReturnValue} from '@sqlrooms/ui';\nimport {X} from 'lucide-react';\n\nimport {AiModelParameters} from './AiModelParameters';\nimport {AiModelUsage} from './AiModelUsage';\nimport {AiProvidersSettings} from './AiProvidersSettings';\nimport {AiModelsSettings} from './AiModelsSettings';\n\ninterface AiSettingsPanelProps {\n disclosure: UseDisclosureReturnValue;\n}\n\nexport const AiSettingsPanelBase: FC<\n PropsWithChildren<AiSettingsPanelProps>\n> = ({disclosure, children}) => {\n const {isOpen, onClose} = disclosure;\n if (!isOpen) return null;\n\n return (\n <div className=\"bg-background border-border w-full rounded-lg border shadow-sm\">\n <div className=\"relative flex flex-col gap-12 overflow-y-auto p-6\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={onClose}\n className=\"absolute top-2 right-2 z-10\"\n >\n <X className=\"h-4 w-4\" />\n </Button>\n {children}\n </div>\n </div>\n );\n};\n\nexport const AiSettingsPanel = Object.assign(AiSettingsPanelBase, {\n ProvidersSettings: AiProvidersSettings,\n ModelsSettings: AiModelsSettings,\n ModelUsage: AiModelUsage,\n ModelParametersSettings: AiModelParameters,\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqlrooms/ai-settings",
|
|
3
|
-
"version": "0.29.0-rc.
|
|
3
|
+
"version": "0.29.0-rc.2",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
13
|
-
"url": "https://github.com/sqlrooms/sqlrooms.git"
|
|
13
|
+
"url": "git+https://github.com/sqlrooms/sqlrooms.git"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist"
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
"access": "public"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@sqlrooms/ai-config": "0.29.0-rc.
|
|
23
|
-
"@sqlrooms/ai-core": "0.29.0-rc.
|
|
24
|
-
"@sqlrooms/recharts": "0.29.0-rc.
|
|
25
|
-
"@sqlrooms/room-store": "0.29.0-rc.
|
|
26
|
-
"@sqlrooms/ui": "0.29.0-rc.
|
|
22
|
+
"@sqlrooms/ai-config": "0.29.0-rc.2",
|
|
23
|
+
"@sqlrooms/ai-core": "0.29.0-rc.2",
|
|
24
|
+
"@sqlrooms/recharts": "0.29.0-rc.2",
|
|
25
|
+
"@sqlrooms/room-store": "0.29.0-rc.2",
|
|
26
|
+
"@sqlrooms/ui": "0.29.0-rc.2",
|
|
27
27
|
"immer": "^11.0.1",
|
|
28
28
|
"lucide-react": "^0.556.0",
|
|
29
29
|
"recharts": "^2.12.7"
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"typecheck": "tsc --noEmit",
|
|
40
40
|
"typedoc": "typedoc"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "5d511631992c1af8852ea79ced488867aad4a555"
|
|
43
43
|
}
|