diff --git a/package.json b/package.json index 16cb68bf..6cea64e2 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ }, "scripts": { "postinstall": "prek install", + "dev": "pnpm --filter @aipexstudio/cool-aipex dev", "preflight": "npm run format && npm run lint:fix && npm run typecheck && npm run test", "format": "biome format . --write", "format:check": "biome format .", @@ -25,8 +26,9 @@ "@biomejs/biome": "^2.3.2", "@j178/prek": "^0.2.19", "@types/node": "^24.9.2", + "@typescript/native-preview": "^7.0.0-dev.20251201.1", "@vitest/coverage-v8": "^4.0.6", - "typescript": "5.9.3", + "typescript": "^5.9.3", "vitest": "^4.0.6" } } diff --git a/packages/browser-ext/package.json b/packages/browser-ext/package.json index ec204d1c..a540361d 100644 --- a/packages/browser-ext/package.json +++ b/packages/browser-ext/package.json @@ -19,7 +19,7 @@ "build": "vite build", "preview": "vite preview", "build:css": "npx tailwindcss -i ./src/tailwind.css -o ./src/style.css --minify", - "test": "pnpm --filter @aipexstudio/aipex-core build && vitest run", + "test": "vitest run", "test:watch": "vitest" }, "files": [ @@ -29,6 +29,7 @@ "host-access-config.json" ], "dependencies": { + "@ai-sdk/openai": "^2.0.72", "@aipexstudio/aipex-core": "workspace:*", "@modelcontextprotocol/sdk": "^1.17.4", "@radix-ui/react-avatar": "^1.1.10", @@ -62,7 +63,8 @@ "tailwindcss": "4.1.13", "tokenlens": "^1.3.1", "tw-animate-css": "^1.4.0", - "use-stick-to-bottom": "^1.1.1" + "use-stick-to-bottom": "^1.1.1", + "zod": "^3.25.40" }, "devDependencies": { "@crxjs/vite-plugin": "^2.2.0", diff --git a/packages/browser-ext/src/components/chatbot/components/chatbot.tsx b/packages/browser-ext/src/components/chatbot/components/chatbot.tsx index 29868107..368e521a 100644 --- a/packages/browser-ext/src/components/chatbot/components/chatbot.tsx +++ b/packages/browser-ext/src/components/chatbot/components/chatbot.tsx @@ -4,12 +4,14 @@ import { cn } from "~/lib/utils"; import type { ChatbotThemeVariables, ContextItem } from "~/types"; import { DEFAULT_MODELS } from "../constants"; import { + AgentContext, type ChatbotProviderProps, ChatContext, ComponentsContext, ConfigContext, ThemeContext, } from "../core/context"; +import { ConfigurationGuide } from "./configuration-guide"; import { Header } from "./header"; import { InputArea } from "./input-area"; import { MessageList } from "./message-list"; @@ -37,6 +39,7 @@ function themeToStyle( */ export function ChatbotProvider({ agent, + configError, config, handlers, components = {}, @@ -64,6 +67,15 @@ export function ChatbotProvider({ [theme.className, className], ); + // Agent context value + const agentContextValue = useMemo( + () => ({ + isReady: Boolean(agent), + configError, + }), + [agent, configError], + ); + // Context values const chatContextValue = useMemo( () => ({ @@ -108,9 +120,11 @@ export function ChatbotProvider({ - - {children} - + + + {children} + + @@ -150,6 +164,7 @@ export interface ChatbotProps extends Omit { */ export function Chatbot({ agent, + configError, config, handlers, components, @@ -164,6 +179,7 @@ export function Chatbot({ return ( { + setShowSettings(true); + }, []); + return (
setShowSettings(true)} + onSettingsClick={handleOpenSettings} onNewChat={handleNewChat} /> - {/* Message List */} - + {/* Show configuration guide when agent is not ready */} + {!isAgentReady ? ( + + ) : ( + <> + {/* Message List */} + - {/* Input Area */} - + {/* Input Area */} + + + )} {/* Settings Dialog */} diff --git a/packages/browser-ext/src/components/chatbot/components/configuration-guide.tsx b/packages/browser-ext/src/components/chatbot/components/configuration-guide.tsx new file mode 100644 index 00000000..9f876023 --- /dev/null +++ b/packages/browser-ext/src/components/chatbot/components/configuration-guide.tsx @@ -0,0 +1,55 @@ +import { SettingsIcon } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { useTranslation } from "~/i18n/context"; +import { cn } from "~/lib/utils"; + +export interface ConfigurationGuideProps { + onOpenSettings: () => void; + className?: string; +} + +export function ConfigurationGuide({ + onOpenSettings, + className, +}: ConfigurationGuideProps) { + const { t } = useTranslation(); + + return ( +
+
+
+
+ +
+
+ +

+ {t("config.title")} +

+ +

+ {t("config.description")} +

+ +

+ {t("config.apiTokenRequired")} +

+ + +
+
+ ); +} diff --git a/packages/browser-ext/src/components/chatbot/components/index.ts b/packages/browser-ext/src/components/chatbot/components/index.ts index bea0a053..41ba1d6d 100644 --- a/packages/browser-ext/src/components/chatbot/components/index.ts +++ b/packages/browser-ext/src/components/chatbot/components/index.ts @@ -2,6 +2,10 @@ export { Chatbot, type ChatbotProps, ChatbotProvider } from "./chatbot"; // Individual components +export { + ConfigurationGuide, + type ConfigurationGuideProps, +} from "./configuration-guide"; export { DefaultHeader, Header } from "./header"; export { DefaultInputArea, diff --git a/packages/browser-ext/src/components/chatbot/core/context.ts b/packages/browser-ext/src/components/chatbot/core/context.ts index e566fde1..114f8832 100644 --- a/packages/browser-ext/src/components/chatbot/core/context.ts +++ b/packages/browser-ext/src/components/chatbot/core/context.ts @@ -134,11 +134,36 @@ export function useThemeContext(): ThemeContextValue { export { ThemeContext }; +// ============ Agent Context ============ + +export interface AgentContextValue { + /** Whether the agent is configured and ready */ + isReady: boolean; + /** Configuration error if agent creation failed */ + configError?: Error; +} + +const AgentContext = createContext({ + isReady: false, + configError: undefined, +}); + +/** + * Hook to access agent state + */ +export function useAgentContext(): AgentContextValue { + return useContext(AgentContext); +} + +export { AgentContext }; + // ============ Provider Props ============ export interface ChatbotProviderProps { - /** The AIPex instance from @aipexstudio/aipex-core */ - agent: AIPex; + /** The AIPex instance from @aipexstudio/aipex-core (undefined when not configured) */ + agent: AIPex | undefined; + /** Configuration error message */ + configError?: Error; /** Chat configuration */ config?: ChatConfig; /** Event handlers */ diff --git a/packages/browser-ext/src/components/chatbot/index.ts b/packages/browser-ext/src/components/chatbot/index.ts index abc6d53f..e0c2c413 100644 --- a/packages/browser-ext/src/components/chatbot/index.ts +++ b/packages/browser-ext/src/components/chatbot/index.ts @@ -49,6 +49,8 @@ export type { } from "../../types"; // Individual component exports export { + ConfigurationGuide, + type ConfigurationGuideProps, DefaultHeader, DefaultInputArea, DefaultMessageItem, @@ -90,6 +92,8 @@ export { export { models, SYSTEM_PROMPT } from "./constants"; // Context exports export { + AgentContext, + type AgentContextValue, type ChatbotProviderProps, ChatContext, type ChatContextValue, @@ -99,6 +103,7 @@ export { type ConfigContextValue, ThemeContext, type ThemeContextValue, + useAgentContext, useChatContext, useComponentsContext, useConfigContext, diff --git a/packages/browser-ext/src/hooks/index.ts b/packages/browser-ext/src/hooks/index.ts index eb11c43c..d9dfd9b2 100644 --- a/packages/browser-ext/src/hooks/index.ts +++ b/packages/browser-ext/src/hooks/index.ts @@ -1,3 +1,8 @@ +export { + type UseAgentOptions, + type UseAgentReturn, + useAgent, +} from "./use-agent"; export { type ChatbotEventHandlers, type UseChatOptions, diff --git a/packages/browser-ext/src/hooks/use-agent.ts b/packages/browser-ext/src/hooks/use-agent.ts new file mode 100644 index 00000000..890dbe67 --- /dev/null +++ b/packages/browser-ext/src/hooks/use-agent.ts @@ -0,0 +1,100 @@ +import { createOpenAI } from "@ai-sdk/openai"; +import { + AIPex, + aisdk, + IndexedDBStorage, + SessionStorage, +} from "@aipexstudio/aipex-core"; +import { useEffect, useMemo, useState } from "react"; +import { SYSTEM_PROMPT } from "~/components/chatbot/constants"; +import { allBrowserTools } from "~/tools"; +import type { ChatSettings } from "~/types"; + +export interface UseAgentOptions { + settings: ChatSettings; + isLoading: boolean; +} + +export interface UseAgentReturn { + agent: AIPex | undefined; + isReady: boolean; + error: Error | undefined; +} + +/** + * useAgent - Hook for creating and managing the AIPex agent instance + * + * Creates an agent based on the provided settings (aiHost, aiToken, aiModel). + * The agent is recreated when settings change. + */ +export function useAgent({ + settings, + isLoading, +}: UseAgentOptions): UseAgentReturn { + const [agent, setAgent] = useState(undefined); + const [error, setError] = useState(undefined); + + const isConfigured = useMemo(() => { + return Boolean(settings.aiToken && settings.aiModel); + }, [settings.aiToken, settings.aiModel]); + + useEffect(() => { + if (isLoading) { + return; + } + + if (!isConfigured) { + setAgent(undefined); + setError(new Error("API token or model not configured")); + return; + } + + try { + // Create OpenAI compatible provider with custom baseURL + const openai = createOpenAI({ + baseURL: settings.aiHost || "https://api.openai.com/v1", + apiKey: settings.aiToken, + }); + + // Create the model using aisdk + const model = aisdk(openai(settings.aiModel)); + + // Create storage for conversation persistence + const storage = new SessionStorage( + new IndexedDBStorage("aipex-sessions"), + ); + + // Get all available tools + const tools = [...allBrowserTools]; + + // Create the agent + const newAgent = AIPex.create({ + name: "AIPex Assistant", + instructions: SYSTEM_PROMPT, + model, + tools, + storage, + maxTurns: 10, + }); + + setAgent(newAgent); + setError(undefined); + } catch (err) { + console.error("Failed to create agent:", err); + setAgent(undefined); + setError(err instanceof Error ? err : new Error(String(err))); + } + }, [ + isLoading, + isConfigured, + settings.aiHost, + settings.aiToken, + settings.aiModel, + ]); + + return { + agent, + isReady: Boolean(agent) && !isLoading, + error, + }; +} diff --git a/packages/browser-ext/src/hooks/use-chat.ts b/packages/browser-ext/src/hooks/use-chat.ts index 1769902c..71744ebe 100644 --- a/packages/browser-ext/src/hooks/use-chat.ts +++ b/packages/browser-ext/src/hooks/use-chat.ts @@ -80,7 +80,7 @@ export interface UseChatReturn { * ``` */ export function useChat( - agent: AIPex, + agent: AIPex | undefined, options: UseChatOptions = {}, ): UseChatReturn { const { config, handlers } = options; @@ -176,6 +176,11 @@ export function useChat( files?: File[], contexts?: ContextItem[], ): Promise => { + if (!agent) { + console.warn("useChat: agent is not initialized"); + return; + } + if (!text.trim() && !files?.length && !contexts?.length) { return; } @@ -206,6 +211,11 @@ export function useChat( // Continue conversation (for multi-turn without creating new user message) const continueConversation = useCallback( async (text: string): Promise => { + if (!agent) { + console.warn("useChat: agent is not initialized"); + return; + } + if (!sessionId) { // No session, start new await sendMessage(text); @@ -237,7 +247,7 @@ export function useChat( // Reset chat const reset = useCallback((): void => { - if (sessionId) { + if (sessionId && agent) { void agent.getConversationManager()?.deleteSession(sessionId); } activeGeneratorRef.current = null; @@ -247,6 +257,11 @@ export function useChat( // Regenerate last response const regenerate = useCallback(async (): Promise => { + if (!agent) { + console.warn("useChat: agent is not initialized"); + return; + } + // Remove last assistant message const removed = adapter.removeLastAssistantMessage(); if (!removed) return; diff --git a/packages/browser-ext/src/i18n/index.ts b/packages/browser-ext/src/i18n/index.ts index 73247c00..db75e661 100644 --- a/packages/browser-ext/src/i18n/index.ts +++ b/packages/browser-ext/src/i18n/index.ts @@ -79,11 +79,11 @@ export const getTranslation = ( // Navigate through nested object using dot notation const keys = key.split("."); - let value: unknown = resource; + let value: any = resource; for (const k of keys) { if (value && typeof value === "object" && k in value) { - value = value[k]; + value = value[k] as any; } else { console.warn( `Translation key not found: ${key} for language: ${language}`, diff --git a/packages/browser-ext/src/i18n/locales/en.json b/packages/browser-ext/src/i18n/locales/en.json index e2ef3c37..f0db7a88 100644 --- a/packages/browser-ext/src/i18n/locales/en.json +++ b/packages/browser-ext/src/i18n/locales/en.json @@ -68,6 +68,12 @@ "research": "Please use Google to research topic 'MCP'", "comparePrice": "Compare the price of iPhone 17" }, + "config": { + "title": "Setup Required", + "description": "To start using AIPex, please configure your AI settings.", + "apiTokenRequired": "API token is required to connect to the AI service.", + "openSettings": "Open Settings" + }, "tools": { "get_all_tabs": "Get All Tabs", "get_current_tab": "Get Current Tab", diff --git a/packages/browser-ext/src/i18n/locales/zh.json b/packages/browser-ext/src/i18n/locales/zh.json index f6e3dbab..231a7f14 100644 --- a/packages/browser-ext/src/i18n/locales/zh.json +++ b/packages/browser-ext/src/i18n/locales/zh.json @@ -68,6 +68,12 @@ "research": "请使用 Google 研究主题 'MCP'", "comparePrice": "比较 iPhone 17 的价格" }, + "config": { + "title": "需要配置", + "description": "使用 AIPex 前,请先配置您的 AI 设置。", + "apiTokenRequired": "需要 API 令牌来连接 AI 服务。", + "openSettings": "打开设置" + }, "tools": { "get_all_tabs": "获取所有标签页", "get_current_tab": "获取当前标签页", diff --git a/packages/browser-ext/src/i18n/types.ts b/packages/browser-ext/src/i18n/types.ts index 714799c5..4dd48b5e 100644 --- a/packages/browser-ext/src/i18n/types.ts +++ b/packages/browser-ext/src/i18n/types.ts @@ -64,6 +64,12 @@ export interface TranslationResources { research: string; comparePrice: string; }; + config: { + title: string; + description: string; + apiTokenRequired: string; + openSettings: string; + }; tools: { [key: string]: string; }; @@ -116,7 +122,11 @@ export type TranslationKey = | "welcome.organizeTabs" | "welcome.analyzePage" | "welcome.research" - | "welcome.comparePrice"; + | "welcome.comparePrice" + | "config.title" + | "config.description" + | "config.apiTokenRequired" + | "config.openSettings"; export interface I18nContextValue { language: Language; diff --git a/packages/browser-ext/src/pages/common/app-root.tsx b/packages/browser-ext/src/pages/common/app-root.tsx index 1d0ed9cc..028b33b8 100644 --- a/packages/browser-ext/src/pages/common/app-root.tsx +++ b/packages/browser-ext/src/pages/common/app-root.tsx @@ -1,8 +1,29 @@ import React from "react"; import ReactDOM from "react-dom/client"; import ChatBot from "~/components/chatbot"; +import { chromeStorageAdapter, useAgent, useChatConfig } from "~/hooks"; import { I18nProvider } from "~/i18n/context"; +function ChatApp() { + const { settings, isLoading } = useChatConfig({ + storageAdapter: chromeStorageAdapter, + autoLoad: true, + }); + + const { agent, error } = useAgent({ settings, isLoading }); + + if (isLoading) { + return ( +
+
Loading...
+
+ ); + } + + // Pass agent and configError to ChatBot - it will show configuration guide if needed + return ; +} + export function renderChatApp() { const rootElement = document.getElementById("root"); if (!rootElement) { @@ -11,7 +32,7 @@ export function renderChatApp() { const App = () => ( - + ); diff --git a/packages/browser-ext/src/sidepanel.html b/packages/browser-ext/src/sidepanel.html index 01b8ebe3..d463c7a2 100644 --- a/packages/browser-ext/src/sidepanel.html +++ b/packages/browser-ext/src/sidepanel.html @@ -4,6 +4,7 @@ AIPex Side Panel +
diff --git a/packages/browser-ext/vite.config.ts b/packages/browser-ext/vite.config.ts index 905a4d56..6598ecb5 100644 --- a/packages/browser-ext/vite.config.ts +++ b/packages/browser-ext/vite.config.ts @@ -27,6 +27,11 @@ export default defineConfig({ alias: { "~": path.resolve(__dirname, "./src"), "@": path.resolve(__dirname, "./"), + // Point to core source code directly for better dev experience + "@aipexstudio/aipex-core": path.resolve( + __dirname, + "../core/src/index.ts", + ), }, }, css: { @@ -37,7 +42,6 @@ export default defineConfig({ rollupOptions: { input: { sidepanel: path.resolve(__dirname, "src/pages/sidepanel/index.html"), - content: path.resolve(__dirname, "src/pages/content/index.tsx"), options: path.resolve(__dirname, "src/pages/options/index.html"), }, }, diff --git a/packages/browser-ext/vitest.config.ts b/packages/browser-ext/vitest.config.ts index 538f98a7..9a7de7d2 100644 --- a/packages/browser-ext/vitest.config.ts +++ b/packages/browser-ext/vitest.config.ts @@ -30,6 +30,10 @@ export default defineConfig({ alias: { "~": path.resolve(__dirname, "./src"), "@": path.resolve(__dirname, "./"), + "@aipexstudio/aipex-core": path.resolve( + __dirname, + "../core/src/index.ts", + ), }, }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b9109f94..5e3dc64f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,11 +17,14 @@ importers: '@types/node': specifier: ^24.9.2 version: 24.9.2 + '@typescript/native-preview': + specifier: ^7.0.0-dev.20251201.1 + version: 7.0.0-dev.20251201.1 '@vitest/coverage-v8': specifier: ^4.0.6 version: 4.0.6(vitest@4.0.6(@types/debug@4.1.12)(@types/node@24.9.2)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.20.6)) typescript: - specifier: 5.9.3 + specifier: ^5.9.3 version: 5.9.3 vitest: specifier: ^4.0.6 @@ -29,6 +32,9 @@ importers: packages/browser-ext: dependencies: + '@ai-sdk/openai': + specifier: ^2.0.72 + version: 2.0.72(zod@3.25.76) '@aipexstudio/aipex-core': specifier: workspace:* version: link:../core @@ -73,7 +79,7 @@ importers: version: 3.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) ai: specifier: ^5.0.59 - version: 5.0.86(zod@4.1.13) + version: 5.0.86(zod@3.25.76) assistant-ui: specifier: ^0.0.56 version: 0.0.56 @@ -131,6 +137,9 @@ importers: use-stick-to-bottom: specifier: ^1.1.1 version: 1.1.1(react@19.2.0) + zod: + specifier: ^3.25.40 + version: 3.25.76 devDependencies: '@crxjs/vite-plugin': specifier: ^2.2.0 @@ -1883,6 +1892,45 @@ packages: '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@typescript/native-preview-darwin-arm64@7.0.0-dev.20251201.1': + resolution: {integrity: sha512-PY0BrlRF3YCZEMxzuk79IFSgpGqUErkdrW7Aq+/mF8DEET5uaDypTMb8Vz4CLYJ7Xvvxz8eZsLimPbv6hYDIvA==} + cpu: [arm64] + os: [darwin] + + '@typescript/native-preview-darwin-x64@7.0.0-dev.20251201.1': + resolution: {integrity: sha512-YeDrjnsvXwm/MNG8aURT3J+cmHQIhpiElBKOVOy/H6ky4S2Ro9ufG+Bj9CqS3etbTCLhV5btk+QNh86DZ4VDkQ==} + cpu: [x64] + os: [darwin] + + '@typescript/native-preview-linux-arm64@7.0.0-dev.20251201.1': + resolution: {integrity: sha512-HbEn+SBTDZEtwN/VUxA2To+6vEr7x++SCRc6yGp5y4onpBL2xnH17UoxWiqN9J4Bu1DbQ9jZv3D5CzwBlofPQA==} + cpu: [arm64] + os: [linux] + + '@typescript/native-preview-linux-arm@7.0.0-dev.20251201.1': + resolution: {integrity: sha512-gr2EQYK888YdGROMc7l3N3MeKY1V3QVImKIQZNgqprV+N2rXaFnxGAZ+gql3LqZgRGel4a12vCUJeP7Pjl2gww==} + cpu: [arm] + os: [linux] + + '@typescript/native-preview-linux-x64@7.0.0-dev.20251201.1': + resolution: {integrity: sha512-q94K/LZ3Ab/SbUBMBsf37VdsumeZ1dZmymJYlhGBqk/fdXBayL0diLR3RdzyeQWbCXAxWL5KFKLIiIc3cI/fcA==} + cpu: [x64] + os: [linux] + + '@typescript/native-preview-win32-arm64@7.0.0-dev.20251201.1': + resolution: {integrity: sha512-/AFwpsX/G05bBsfVURfg4+/JC6gfvqj9jfFe/7oe1Y1J42koN5C8TH+eSmMOOEcPYpFjR1e+NWckqBJKaCXJ4A==} + cpu: [arm64] + os: [win32] + + '@typescript/native-preview-win32-x64@7.0.0-dev.20251201.1': + resolution: {integrity: sha512-vTUCDEuSP4ifLHqb8aljuj44v6+M1HDKo1WLnboTDpwU7IIrTux/0jzkPfEHd9xd5FU4EhSA8ZrYDwKI0BcRcg==} + cpu: [x64] + os: [win32] + + '@typescript/native-preview@7.0.0-dev.20251201.1': + resolution: {integrity: sha512-EiPEgGwNa2uHyyKgeoWTL6wWHKUBmF3xsfZ3OHofk7TxUuxb2mpLG5igEuaBe8iUwkCUl9uZgJvOu6o0wE5NSA==} + hasBin: true + '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} @@ -4803,9 +4851,6 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.1.13: - resolution: {integrity: sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==} - zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -4819,12 +4864,12 @@ snapshots: '@ai-sdk/provider-utils': 3.0.17(zod@3.25.76) zod: 3.25.76 - '@ai-sdk/gateway@2.0.5(zod@4.1.13)': + '@ai-sdk/gateway@2.0.5(zod@3.25.76)': dependencies: '@ai-sdk/provider': 2.0.0 - '@ai-sdk/provider-utils': 3.0.15(zod@4.1.13) + '@ai-sdk/provider-utils': 3.0.15(zod@3.25.76) '@vercel/oidc': 3.0.3 - zod: 4.1.13 + zod: 3.25.76 '@ai-sdk/google@2.0.43(zod@3.25.76)': dependencies: @@ -4847,12 +4892,12 @@ snapshots: optionalDependencies: zod: 3.25.76 - '@ai-sdk/provider-utils@3.0.15(zod@4.1.13)': + '@ai-sdk/provider-utils@3.0.15(zod@3.25.76)': dependencies: '@ai-sdk/provider': 2.0.0 '@standard-schema/spec': 1.0.0 eventsource-parser: 3.0.6 - zod: 4.1.13 + zod: 3.25.76 '@ai-sdk/provider-utils@3.0.17(zod@3.25.76)': dependencies: @@ -6448,6 +6493,37 @@ snapshots: dependencies: '@types/node': 24.10.1 + '@typescript/native-preview-darwin-arm64@7.0.0-dev.20251201.1': + optional: true + + '@typescript/native-preview-darwin-x64@7.0.0-dev.20251201.1': + optional: true + + '@typescript/native-preview-linux-arm64@7.0.0-dev.20251201.1': + optional: true + + '@typescript/native-preview-linux-arm@7.0.0-dev.20251201.1': + optional: true + + '@typescript/native-preview-linux-x64@7.0.0-dev.20251201.1': + optional: true + + '@typescript/native-preview-win32-arm64@7.0.0-dev.20251201.1': + optional: true + + '@typescript/native-preview-win32-x64@7.0.0-dev.20251201.1': + optional: true + + '@typescript/native-preview@7.0.0-dev.20251201.1': + optionalDependencies: + '@typescript/native-preview-darwin-arm64': 7.0.0-dev.20251201.1 + '@typescript/native-preview-darwin-x64': 7.0.0-dev.20251201.1 + '@typescript/native-preview-linux-arm': 7.0.0-dev.20251201.1 + '@typescript/native-preview-linux-arm64': 7.0.0-dev.20251201.1 + '@typescript/native-preview-linux-x64': 7.0.0-dev.20251201.1 + '@typescript/native-preview-win32-arm64': 7.0.0-dev.20251201.1 + '@typescript/native-preview-win32-x64': 7.0.0-dev.20251201.1 + '@ungap/structured-clone@1.3.0': {} '@vercel/oidc@3.0.3': {} @@ -6602,13 +6678,13 @@ snapshots: screenfull: 5.2.0 tslib: 2.8.1 - ai@5.0.86(zod@4.1.13): + ai@5.0.86(zod@3.25.76): dependencies: - '@ai-sdk/gateway': 2.0.5(zod@4.1.13) + '@ai-sdk/gateway': 2.0.5(zod@3.25.76) '@ai-sdk/provider': 2.0.0 - '@ai-sdk/provider-utils': 3.0.15(zod@4.1.13) + '@ai-sdk/provider-utils': 3.0.15(zod@3.25.76) '@opentelemetry/api': 1.9.0 - zod: 4.1.13 + zod: 3.25.76 ajv-formats@3.0.1(ajv@8.17.1): optionalDependencies: @@ -9898,6 +9974,4 @@ snapshots: zod@3.25.76: {} - zod@4.1.13: {} - zwitch@2.0.4: {}