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/pnpm-lock.yaml b/pnpm-lock.yaml
index 6a18c961..9373bfb5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -17,18 +17,21 @@ 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
- version: 5.9.3
vitest:
specifier: ^4.0.6
version: 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)
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
@@ -1886,6 +1889,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==}
@@ -4473,11 +4515,6 @@ packages:
resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
engines: {node: '>= 0.6'}
- typescript@5.9.3:
- resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
- engines: {node: '>=14.17'}
- hasBin: true
-
ufo@1.6.1:
resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==}
@@ -6448,6 +6485,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': {}
@@ -9555,8 +9623,6 @@ snapshots:
media-typer: 1.1.0
mime-types: 3.0.1
- typescript@5.9.3: {}
-
ufo@1.6.1: {}
undici-types@7.16.0: {}
From 0cd06959c4450177be2bbeb69f18f7be543d9e3c Mon Sep 17 00:00:00 2001
From: 0x5457 <0x5457@protonmail.com>
Date: Mon, 1 Dec 2025 17:19:57 +0800
Subject: [PATCH 3/4] chore: update TypeScript to version 5.9.3 and reintroduce
@vitest/coverage-v8 in package.json; remove unused VSCode extensions
configuration
---
.vscode/extensions.json | 3 ---
.vscode/settings.json | 3 +--
package.json | 3 ++-
pnpm-lock.yaml | 10 ++++++++++
4 files changed, 13 insertions(+), 6 deletions(-)
delete mode 100644 .vscode/extensions.json
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
deleted file mode 100644
index 5b4871d1..00000000
--- a/.vscode/extensions.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "recommendations": ["typescriptteam.native-preview"]
-}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index f49bfc89..efd77936 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,3 @@
{
- "nuxt.isNuxtApp": false,
- "typescript.experimental.useTsgo": true
+ "nuxt.isNuxtApp": false
}
diff --git a/package.json b/package.json
index 03f217f0..6cea64e2 100644
--- a/package.json
+++ b/package.json
@@ -26,8 +26,9 @@
"@biomejs/biome": "^2.3.2",
"@j178/prek": "^0.2.19",
"@types/node": "^24.9.2",
- "@vitest/coverage-v8": "^4.0.6",
"@typescript/native-preview": "^7.0.0-dev.20251201.1",
+ "@vitest/coverage-v8": "^4.0.6",
+ "typescript": "^5.9.3",
"vitest": "^4.0.6"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9373bfb5..5e3dc64f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -23,6 +23,9 @@ importers:
'@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
+ version: 5.9.3
vitest:
specifier: ^4.0.6
version: 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)
@@ -4515,6 +4518,11 @@ packages:
resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
engines: {node: '>= 0.6'}
+ typescript@5.9.3:
+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
ufo@1.6.1:
resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==}
@@ -9623,6 +9631,8 @@ snapshots:
media-typer: 1.1.0
mime-types: 3.0.1
+ typescript@5.9.3: {}
+
ufo@1.6.1: {}
undici-types@7.16.0: {}
From 6975bc3f8ae5795b2de20701b4c122b1037b1f85 Mon Sep 17 00:00:00 2001
From: 0x5457 <0x5457@protonmail.com>
Date: Mon, 1 Dec 2025 17:24:30 +0800
Subject: [PATCH 4/4] chore(browser-ext): add alias for @aipexstudio/aipex-core
in vitest configuration
---
packages/browser-ext/vitest.config.ts | 4 ++++
1 file changed, 4 insertions(+)
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",
+ ),
},
},
});