Spaces:
Running
Running
Commit
·
8c61b89
1
Parent(s):
51105d0
feat: add back grok 3 mini and API key management functionality
Browse files- Integrated the XAI provider into the application, allowing for model interactions.
- Implemented an API Key Manager component for managing API keys for OpenAI, Anthropic, Groq, and XAI.
- Updated the Chat Sidebar to include an option for accessing the API Key Manager.
- Enhanced the providers.ts file to utilize the new XAI client and manage API keys securely.
- ai/providers.ts +64 -16
- components/api-key-manager.tsx +163 -0
- components/chat-sidebar.tsx +15 -1
- components/model-picker.tsx +2 -2
- package.json +1 -0
- pnpm-lock.yaml +28 -0
ai/providers.ts
CHANGED
@@ -1,8 +1,14 @@
|
|
1 |
-
import {
|
2 |
-
import {
|
3 |
-
import {
|
4 |
-
import {
|
5 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
export interface ModelInfo {
|
7 |
provider: string;
|
8 |
name: string;
|
@@ -15,26 +21,51 @@ const middleware = extractReasoningMiddleware({
|
|
15 |
tagName: 'think',
|
16 |
});
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
const languageModels = {
|
19 |
-
"
|
20 |
-
"
|
21 |
-
"claude-3-7-sonnet": anthropic('claude-3-7-sonnet-20250219'),
|
22 |
"qwen-qwq": wrapLanguageModel(
|
23 |
{
|
24 |
-
model:
|
25 |
middleware
|
26 |
}
|
27 |
),
|
|
|
28 |
};
|
29 |
|
30 |
export const modelDetails: Record<keyof typeof languageModels, ModelInfo> = {
|
31 |
-
"gemini-2.5-flash": {
|
32 |
-
provider: "Google",
|
33 |
-
name: "Gemini 2.5 Flash",
|
34 |
-
description: "Latest version of Google's Gemini 2.5 Flash with strong reasoning and coding capabilities.",
|
35 |
-
apiVersion: "gemini-2.5-flash-preview-04-17",
|
36 |
-
capabilities: ["Balance", "Efficient", "Agentic"]
|
37 |
-
},
|
38 |
"gpt-4.1-mini": {
|
39 |
provider: "OpenAI",
|
40 |
name: "GPT-4.1 Mini",
|
@@ -56,8 +87,25 @@ export const modelDetails: Record<keyof typeof languageModels, ModelInfo> = {
|
|
56 |
apiVersion: "qwen-qwq",
|
57 |
capabilities: ["Reasoning", "Efficient", "Agentic"]
|
58 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
};
|
60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
export const model = customProvider({
|
62 |
languageModels,
|
63 |
});
|
|
|
1 |
+
import { createOpenAI } from "@ai-sdk/openai";
|
2 |
+
import { createGroq } from "@ai-sdk/groq";
|
3 |
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
4 |
+
import { createXai } from "@ai-sdk/xai";
|
5 |
+
|
6 |
+
import {
|
7 |
+
customProvider,
|
8 |
+
wrapLanguageModel,
|
9 |
+
extractReasoningMiddleware
|
10 |
+
} from "ai";
|
11 |
+
|
12 |
export interface ModelInfo {
|
13 |
provider: string;
|
14 |
name: string;
|
|
|
21 |
tagName: 'think',
|
22 |
});
|
23 |
|
24 |
+
// Helper to get API keys from environment variables first, then localStorage
|
25 |
+
const getApiKey = (key: string): string | undefined => {
|
26 |
+
// Check for environment variables first
|
27 |
+
if (process.env[key]) {
|
28 |
+
return process.env[key] || undefined;
|
29 |
+
}
|
30 |
+
|
31 |
+
// Fall back to localStorage if available
|
32 |
+
if (typeof window !== 'undefined') {
|
33 |
+
return window.localStorage.getItem(key) || undefined;
|
34 |
+
}
|
35 |
+
|
36 |
+
return undefined;
|
37 |
+
};
|
38 |
+
|
39 |
+
// Create provider instances with API keys from localStorage
|
40 |
+
const openaiClient = createOpenAI({
|
41 |
+
apiKey: getApiKey('OPENAI_API_KEY'),
|
42 |
+
});
|
43 |
+
|
44 |
+
const anthropicClient = createAnthropic({
|
45 |
+
apiKey: getApiKey('ANTHROPIC_API_KEY'),
|
46 |
+
});
|
47 |
+
|
48 |
+
const groqClient = createGroq({
|
49 |
+
apiKey: getApiKey('GROQ_API_KEY'),
|
50 |
+
});
|
51 |
+
|
52 |
+
const xaiClient = createXai({
|
53 |
+
apiKey: getApiKey('XAI_API_KEY'),
|
54 |
+
});
|
55 |
+
|
56 |
const languageModels = {
|
57 |
+
"gpt-4.1-mini": openaiClient("gpt-4.1-mini"),
|
58 |
+
"claude-3-7-sonnet": anthropicClient('claude-3-7-sonnet-20250219'),
|
|
|
59 |
"qwen-qwq": wrapLanguageModel(
|
60 |
{
|
61 |
+
model: groqClient("qwen-qwq-32b"),
|
62 |
middleware
|
63 |
}
|
64 |
),
|
65 |
+
"grok-3-mini": xaiClient("grok-3-mini-latest"),
|
66 |
};
|
67 |
|
68 |
export const modelDetails: Record<keyof typeof languageModels, ModelInfo> = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
"gpt-4.1-mini": {
|
70 |
provider: "OpenAI",
|
71 |
name: "GPT-4.1 Mini",
|
|
|
87 |
apiVersion: "qwen-qwq",
|
88 |
capabilities: ["Reasoning", "Efficient", "Agentic"]
|
89 |
},
|
90 |
+
"grok-3-mini": {
|
91 |
+
provider: "XAI",
|
92 |
+
name: "Grok 3 Mini",
|
93 |
+
description: "Latest version of XAI's Grok 3 Mini with strong reasoning and coding capabilities.",
|
94 |
+
apiVersion: "grok-3-mini-latest",
|
95 |
+
capabilities: ["Reasoning", "Efficient", "Agentic"]
|
96 |
+
},
|
97 |
};
|
98 |
|
99 |
+
// Update API keys when localStorage changes (for runtime updates)
|
100 |
+
if (typeof window !== 'undefined') {
|
101 |
+
window.addEventListener('storage', (event) => {
|
102 |
+
// Reload the page if any API key changed to refresh the providers
|
103 |
+
if (event.key?.includes('API_KEY')) {
|
104 |
+
window.location.reload();
|
105 |
+
}
|
106 |
+
});
|
107 |
+
}
|
108 |
+
|
109 |
export const model = customProvider({
|
110 |
languageModels,
|
111 |
});
|
components/api-key-manager.tsx
ADDED
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { useState, useEffect } from "react";
|
2 |
+
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
3 |
+
import { Button } from "@/components/ui/button";
|
4 |
+
import { Input } from "@/components/ui/input";
|
5 |
+
import { Label } from "@/components/ui/label";
|
6 |
+
import { toast } from "sonner";
|
7 |
+
|
8 |
+
// API key configuration
|
9 |
+
interface ApiKeyConfig {
|
10 |
+
name: string;
|
11 |
+
key: string;
|
12 |
+
storageKey: string;
|
13 |
+
label: string;
|
14 |
+
placeholder: string;
|
15 |
+
}
|
16 |
+
|
17 |
+
// Available API keys configuration
|
18 |
+
const API_KEYS_CONFIG: ApiKeyConfig[] = [
|
19 |
+
{
|
20 |
+
name: "OpenAI",
|
21 |
+
key: "openai",
|
22 |
+
storageKey: "OPENAI_API_KEY",
|
23 |
+
label: "OpenAI API Key",
|
24 |
+
placeholder: "sk-..."
|
25 |
+
},
|
26 |
+
{
|
27 |
+
name: "Anthropic",
|
28 |
+
key: "anthropic",
|
29 |
+
storageKey: "ANTHROPIC_API_KEY",
|
30 |
+
label: "Anthropic API Key",
|
31 |
+
placeholder: "sk-ant-..."
|
32 |
+
},
|
33 |
+
{
|
34 |
+
name: "Groq",
|
35 |
+
key: "groq",
|
36 |
+
storageKey: "GROQ_API_KEY",
|
37 |
+
label: "Groq API Key",
|
38 |
+
placeholder: "gsk_..."
|
39 |
+
},
|
40 |
+
{
|
41 |
+
name: "XAI",
|
42 |
+
key: "xai",
|
43 |
+
storageKey: "XAI_API_KEY",
|
44 |
+
label: "XAI API Key",
|
45 |
+
placeholder: "xai-..."
|
46 |
+
}
|
47 |
+
];
|
48 |
+
|
49 |
+
interface ApiKeyManagerProps {
|
50 |
+
open: boolean;
|
51 |
+
onOpenChange: (open: boolean) => void;
|
52 |
+
}
|
53 |
+
|
54 |
+
export function ApiKeyManager({ open, onOpenChange }: ApiKeyManagerProps) {
|
55 |
+
// State to store API keys
|
56 |
+
const [apiKeys, setApiKeys] = useState<Record<string, string>>({});
|
57 |
+
|
58 |
+
// Load API keys from localStorage on initial mount
|
59 |
+
useEffect(() => {
|
60 |
+
const storedKeys: Record<string, string> = {};
|
61 |
+
|
62 |
+
API_KEYS_CONFIG.forEach(config => {
|
63 |
+
const value = localStorage.getItem(config.storageKey);
|
64 |
+
if (value) {
|
65 |
+
storedKeys[config.key] = value;
|
66 |
+
}
|
67 |
+
});
|
68 |
+
|
69 |
+
setApiKeys(storedKeys);
|
70 |
+
}, []);
|
71 |
+
|
72 |
+
// Update API key in state
|
73 |
+
const handleApiKeyChange = (key: string, value: string) => {
|
74 |
+
setApiKeys(prev => ({
|
75 |
+
...prev,
|
76 |
+
[key]: value
|
77 |
+
}));
|
78 |
+
};
|
79 |
+
|
80 |
+
// Save API keys to localStorage
|
81 |
+
const handleSaveApiKeys = () => {
|
82 |
+
try {
|
83 |
+
API_KEYS_CONFIG.forEach(config => {
|
84 |
+
const value = apiKeys[config.key];
|
85 |
+
|
86 |
+
if (value && value.trim()) {
|
87 |
+
localStorage.setItem(config.storageKey, value.trim());
|
88 |
+
} else {
|
89 |
+
localStorage.removeItem(config.storageKey);
|
90 |
+
}
|
91 |
+
});
|
92 |
+
|
93 |
+
toast.success("API keys saved successfully");
|
94 |
+
onOpenChange(false);
|
95 |
+
} catch (error) {
|
96 |
+
console.error("Error saving API keys:", error);
|
97 |
+
toast.error("Failed to save API keys");
|
98 |
+
}
|
99 |
+
};
|
100 |
+
|
101 |
+
// Clear all API keys
|
102 |
+
const handleClearApiKeys = () => {
|
103 |
+
try {
|
104 |
+
API_KEYS_CONFIG.forEach(config => {
|
105 |
+
localStorage.removeItem(config.storageKey);
|
106 |
+
});
|
107 |
+
|
108 |
+
setApiKeys({});
|
109 |
+
toast.success("All API keys cleared");
|
110 |
+
} catch (error) {
|
111 |
+
console.error("Error clearing API keys:", error);
|
112 |
+
toast.error("Failed to clear API keys");
|
113 |
+
}
|
114 |
+
};
|
115 |
+
|
116 |
+
return (
|
117 |
+
<Dialog open={open} onOpenChange={onOpenChange}>
|
118 |
+
<DialogContent className="sm:max-w-[500px]">
|
119 |
+
<DialogHeader>
|
120 |
+
<DialogTitle>API Key Settings</DialogTitle>
|
121 |
+
<DialogDescription>
|
122 |
+
Enter your own API keys for different AI providers. Keys are stored securely in your browser's local storage.
|
123 |
+
</DialogDescription>
|
124 |
+
</DialogHeader>
|
125 |
+
|
126 |
+
<div className="grid gap-4 py-4">
|
127 |
+
{API_KEYS_CONFIG.map(config => (
|
128 |
+
<div key={config.key} className="grid gap-2">
|
129 |
+
<Label htmlFor={config.key}>{config.label}</Label>
|
130 |
+
<Input
|
131 |
+
id={config.key}
|
132 |
+
type="password"
|
133 |
+
value={apiKeys[config.key] || ""}
|
134 |
+
onChange={(e) => handleApiKeyChange(config.key, e.target.value)}
|
135 |
+
placeholder={config.placeholder}
|
136 |
+
/>
|
137 |
+
</div>
|
138 |
+
))}
|
139 |
+
</div>
|
140 |
+
|
141 |
+
<DialogFooter className="flex justify-between sm:justify-between">
|
142 |
+
<Button
|
143 |
+
variant="destructive"
|
144 |
+
onClick={handleClearApiKeys}
|
145 |
+
>
|
146 |
+
Clear All Keys
|
147 |
+
</Button>
|
148 |
+
<div className="flex gap-2">
|
149 |
+
<Button
|
150 |
+
variant="outline"
|
151 |
+
onClick={() => onOpenChange(false)}
|
152 |
+
>
|
153 |
+
Cancel
|
154 |
+
</Button>
|
155 |
+
<Button onClick={handleSaveApiKeys}>
|
156 |
+
Save Keys
|
157 |
+
</Button>
|
158 |
+
</div>
|
159 |
+
</DialogFooter>
|
160 |
+
</DialogContent>
|
161 |
+
</Dialog>
|
162 |
+
);
|
163 |
+
}
|
components/chat-sidebar.tsx
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
import { useState, useEffect } from "react";
|
4 |
import { useRouter, usePathname } from "next/navigation";
|
5 |
-
import { MessageSquare, PlusCircle, Trash2, ServerIcon, Settings, Sparkles, ChevronsUpDown, Copy, Pencil, Github } from "lucide-react";
|
6 |
import {
|
7 |
Sidebar,
|
8 |
SidebarContent,
|
@@ -23,6 +23,7 @@ import { Badge } from "@/components/ui/badge";
|
|
23 |
import { toast } from "sonner";
|
24 |
import Image from "next/image";
|
25 |
import { MCPServerManager } from "./mcp-server-manager";
|
|
|
26 |
import { ThemeToggle } from "./theme-toggle";
|
27 |
import { getUserId, updateUserId } from "@/lib/user-id";
|
28 |
import { useChats } from "@/lib/hooks/use-chats";
|
@@ -57,6 +58,7 @@ export function ChatSidebar() {
|
|
57 |
const pathname = usePathname();
|
58 |
const [userId, setUserId] = useState<string>('');
|
59 |
const [mcpSettingsOpen, setMcpSettingsOpen] = useState(false);
|
|
|
60 |
const { state } = useSidebar();
|
61 |
const isCollapsed = state === "collapsed";
|
62 |
const [editUserIdOpen, setEditUserIdOpen] = useState(false);
|
@@ -384,6 +386,13 @@ export function ChatSidebar() {
|
|
384 |
<Settings className="mr-2 h-4 w-4 hover:text-sidebar-accent" />
|
385 |
MCP Settings
|
386 |
</DropdownMenuItem>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
387 |
<DropdownMenuItem onSelect={(e) => {
|
388 |
e.preventDefault();
|
389 |
window.open("https://git.new/s-mcp", "_blank");
|
@@ -413,6 +422,11 @@ export function ChatSidebar() {
|
|
413 |
open={mcpSettingsOpen}
|
414 |
onOpenChange={setMcpSettingsOpen}
|
415 |
/>
|
|
|
|
|
|
|
|
|
|
|
416 |
</SidebarFooter>
|
417 |
|
418 |
<Dialog open={editUserIdOpen} onOpenChange={(open) => {
|
|
|
2 |
|
3 |
import { useState, useEffect } from "react";
|
4 |
import { useRouter, usePathname } from "next/navigation";
|
5 |
+
import { MessageSquare, PlusCircle, Trash2, ServerIcon, Settings, Sparkles, ChevronsUpDown, Copy, Pencil, Github, Key } from "lucide-react";
|
6 |
import {
|
7 |
Sidebar,
|
8 |
SidebarContent,
|
|
|
23 |
import { toast } from "sonner";
|
24 |
import Image from "next/image";
|
25 |
import { MCPServerManager } from "./mcp-server-manager";
|
26 |
+
import { ApiKeyManager } from "./api-key-manager";
|
27 |
import { ThemeToggle } from "./theme-toggle";
|
28 |
import { getUserId, updateUserId } from "@/lib/user-id";
|
29 |
import { useChats } from "@/lib/hooks/use-chats";
|
|
|
58 |
const pathname = usePathname();
|
59 |
const [userId, setUserId] = useState<string>('');
|
60 |
const [mcpSettingsOpen, setMcpSettingsOpen] = useState(false);
|
61 |
+
const [apiKeySettingsOpen, setApiKeySettingsOpen] = useState(false);
|
62 |
const { state } = useSidebar();
|
63 |
const isCollapsed = state === "collapsed";
|
64 |
const [editUserIdOpen, setEditUserIdOpen] = useState(false);
|
|
|
386 |
<Settings className="mr-2 h-4 w-4 hover:text-sidebar-accent" />
|
387 |
MCP Settings
|
388 |
</DropdownMenuItem>
|
389 |
+
<DropdownMenuItem onSelect={(e) => {
|
390 |
+
e.preventDefault();
|
391 |
+
setApiKeySettingsOpen(true);
|
392 |
+
}}>
|
393 |
+
<Key className="mr-2 h-4 w-4 hover:text-sidebar-accent" />
|
394 |
+
API Keys
|
395 |
+
</DropdownMenuItem>
|
396 |
<DropdownMenuItem onSelect={(e) => {
|
397 |
e.preventDefault();
|
398 |
window.open("https://git.new/s-mcp", "_blank");
|
|
|
422 |
open={mcpSettingsOpen}
|
423 |
onOpenChange={setMcpSettingsOpen}
|
424 |
/>
|
425 |
+
|
426 |
+
<ApiKeyManager
|
427 |
+
open={apiKeySettingsOpen}
|
428 |
+
onOpenChange={setApiKeySettingsOpen}
|
429 |
+
/>
|
430 |
</SidebarFooter>
|
431 |
|
432 |
<Dialog open={editUserIdOpen} onOpenChange={(open) => {
|
components/model-picker.tsx
CHANGED
@@ -35,14 +35,14 @@ export const ModelPicker = ({ selectedModel, setSelectedModel }: ModelPickerProp
|
|
35 |
const getProviderIcon = (provider: string) => {
|
36 |
switch (provider.toLowerCase()) {
|
37 |
case 'anthropic':
|
38 |
-
return <Sparkles className="h-3 w-3 text-
|
39 |
case 'openai':
|
40 |
return <Zap className="h-3 w-3 text-green-500" />;
|
41 |
case 'google':
|
42 |
return <Zap className="h-3 w-3 text-red-500" />;
|
43 |
case 'groq':
|
44 |
return <Sparkles className="h-3 w-3 text-blue-500" />;
|
45 |
-
case '
|
46 |
return <Sparkles className="h-3 w-3 text-yellow-500" />;
|
47 |
default:
|
48 |
return <Info className="h-3 w-3 text-blue-500" />;
|
|
|
35 |
const getProviderIcon = (provider: string) => {
|
36 |
switch (provider.toLowerCase()) {
|
37 |
case 'anthropic':
|
38 |
+
return <Sparkles className="h-3 w-3 text-orange-600" />;
|
39 |
case 'openai':
|
40 |
return <Zap className="h-3 w-3 text-green-500" />;
|
41 |
case 'google':
|
42 |
return <Zap className="h-3 w-3 text-red-500" />;
|
43 |
case 'groq':
|
44 |
return <Sparkles className="h-3 w-3 text-blue-500" />;
|
45 |
+
case 'xai':
|
46 |
return <Sparkles className="h-3 w-3 text-yellow-500" />;
|
47 |
default:
|
48 |
return <Info className="h-3 w-3 text-blue-500" />;
|
package.json
CHANGED
@@ -19,6 +19,7 @@
|
|
19 |
"@ai-sdk/groq": "^1.2.8",
|
20 |
"@ai-sdk/openai": "^1.3.16",
|
21 |
"@ai-sdk/react": "^1.2.9",
|
|
|
22 |
"@neondatabase/serverless": "^1.0.0",
|
23 |
"@radix-ui/react-accordion": "^1.2.7",
|
24 |
"@radix-ui/react-avatar": "^1.1.6",
|
|
|
19 |
"@ai-sdk/groq": "^1.2.8",
|
20 |
"@ai-sdk/openai": "^1.3.16",
|
21 |
"@ai-sdk/react": "^1.2.9",
|
22 |
+
"@ai-sdk/xai": "^1.2.14",
|
23 |
"@neondatabase/serverless": "^1.0.0",
|
24 |
"@radix-ui/react-accordion": "^1.2.7",
|
25 |
"@radix-ui/react-avatar": "^1.1.6",
|
pnpm-lock.yaml
CHANGED
@@ -26,6 +26,9 @@ importers:
|
|
26 |
'@ai-sdk/react':
|
27 |
specifier: ^1.2.9
|
28 |
version: 1.2.9([email protected])([email protected])
|
|
|
|
|
|
|
29 |
'@neondatabase/serverless':
|
30 |
specifier: ^1.0.0
|
31 |
version: 1.0.0
|
@@ -207,6 +210,12 @@ packages:
|
|
207 |
peerDependencies:
|
208 |
zod: ^3.0.0
|
209 |
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
'@ai-sdk/[email protected]':
|
211 |
resolution: {integrity: sha512-pjtiBKt1GgaSKZryTbM3tqgoegJwgAUlp1+X5uN6T+VPnI4FLSymV65tyloWzDlyqZmi9HXnnSRPu76VoL5D5g==}
|
212 |
engines: {node: '>=18'}
|
@@ -239,6 +248,12 @@ packages:
|
|
239 |
peerDependencies:
|
240 |
zod: ^3.23.8
|
241 |
|
|
|
|
|
|
|
|
|
|
|
|
|
242 |
'@alloc/[email protected]':
|
243 |
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
|
244 |
engines: {node: '>=10'}
|
@@ -3698,6 +3713,12 @@ snapshots:
|
|
3698 |
'@ai-sdk/provider-utils': 2.2.7([email protected])
|
3699 |
zod: 3.24.2
|
3700 |
|
|
|
|
|
|
|
|
|
|
|
|
|
3701 |
'@ai-sdk/[email protected]([email protected])':
|
3702 |
dependencies:
|
3703 |
'@ai-sdk/provider': 1.1.3
|
@@ -3732,6 +3753,13 @@ snapshots:
|
|
3732 |
zod: 3.24.2
|
3733 |
zod-to-json-schema: 3.24.5([email protected])
|
3734 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3735 |
'@alloc/[email protected]': {}
|
3736 |
|
3737 |
'@babel/[email protected]':
|
|
|
26 |
'@ai-sdk/react':
|
27 |
specifier: ^1.2.9
|
28 |
version: 1.2.9([email protected])([email protected])
|
29 |
+
'@ai-sdk/xai':
|
30 |
+
specifier: ^1.2.14
|
31 |
+
version: 1.2.14([email protected])
|
32 |
'@neondatabase/serverless':
|
33 |
specifier: ^1.0.0
|
34 |
version: 1.0.0
|
|
|
210 |
peerDependencies:
|
211 |
zod: ^3.0.0
|
212 |
|
213 |
+
'@ai-sdk/[email protected]':
|
214 |
+
resolution: {integrity: sha512-WGk3hTYMOkExgKqBZPWgow/2lp8JLYeJiiO/T/SxBa1NolxNcV+fPaZVvIyqeHGV0/AIXHqNtqI95CFblM47iA==}
|
215 |
+
engines: {node: '>=18'}
|
216 |
+
peerDependencies:
|
217 |
+
zod: ^3.0.0
|
218 |
+
|
219 |
'@ai-sdk/[email protected]':
|
220 |
resolution: {integrity: sha512-pjtiBKt1GgaSKZryTbM3tqgoegJwgAUlp1+X5uN6T+VPnI4FLSymV65tyloWzDlyqZmi9HXnnSRPu76VoL5D5g==}
|
221 |
engines: {node: '>=18'}
|
|
|
248 |
peerDependencies:
|
249 |
zod: ^3.23.8
|
250 |
|
251 |
+
'@ai-sdk/[email protected]':
|
252 |
+
resolution: {integrity: sha512-ZxGjI/D1heIOX6XqyAwrqyBSkICP2mge2La7qHmr5RRcqw9+vWU+2cAg2y1FqCw8FpN/pGFZI81Dm473cYwlpg==}
|
253 |
+
engines: {node: '>=18'}
|
254 |
+
peerDependencies:
|
255 |
+
zod: ^3.0.0
|
256 |
+
|
257 |
'@alloc/[email protected]':
|
258 |
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
|
259 |
engines: {node: '>=10'}
|
|
|
3713 |
'@ai-sdk/provider-utils': 2.2.7([email protected])
|
3714 |
zod: 3.24.2
|
3715 |
|
3716 |
+
'@ai-sdk/[email protected]([email protected])':
|
3717 |
+
dependencies:
|
3718 |
+
'@ai-sdk/provider': 1.1.3
|
3719 |
+
'@ai-sdk/provider-utils': 2.2.7([email protected])
|
3720 |
+
zod: 3.24.2
|
3721 |
+
|
3722 |
'@ai-sdk/[email protected]([email protected])':
|
3723 |
dependencies:
|
3724 |
'@ai-sdk/provider': 1.1.3
|
|
|
3753 |
zod: 3.24.2
|
3754 |
zod-to-json-schema: 3.24.5([email protected])
|
3755 |
|
3756 |
+
'@ai-sdk/[email protected]([email protected])':
|
3757 |
+
dependencies:
|
3758 |
+
'@ai-sdk/openai-compatible': 0.2.12([email protected])
|
3759 |
+
'@ai-sdk/provider': 1.1.3
|
3760 |
+
'@ai-sdk/provider-utils': 2.2.7([email protected])
|
3761 |
+
zod: 3.24.2
|
3762 |
+
|
3763 |
'@alloc/[email protected]': {}
|
3764 |
|
3765 |
'@babel/[email protected]':
|