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 (
+
+ );
+ }
+
+ // 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: {}