From 1f3aad6baa4b117238c2431dd1167f30ef62af18 Mon Sep 17 00:00:00 2001 From: langbot-dev Date: Wed, 12 Aug 2026 01:29:07 +0800 Subject: [PATCH] feat(wizard): restructure AI engine selection flow Restructure the wizard's Step 2 (AI Engine) into a two-layer choice: - Orchestrated Agent apps (Dify, n8n, Coze, etc.) - Direct LLM usage (Space service or custom provider) For direct LLM mode, users choose between LangBot Space (OAuth) or adding their own model provider via a dedicated ProviderForm page. Support intra-step back navigation across all layers. Add Vite dev server proxy config for API requests. Add i18n translations for all 8 locales. --- web/src/app/wizard/page.tsx | 408 +++++++++++++++++++++++++------- web/src/i18n/locales/en-US.ts | 35 +++ web/src/i18n/locales/es-ES.ts | 37 +++ web/src/i18n/locales/ja-JP.ts | 36 +++ web/src/i18n/locales/ru-RU.ts | 37 +++ web/src/i18n/locales/th-TH.ts | 35 +++ web/src/i18n/locales/vi-VN.ts | 35 +++ web/src/i18n/locales/zh-Hans.ts | 32 +++ web/src/i18n/locales/zh-Hant.ts | 32 +++ web/vite.config.ts | 6 + 10 files changed, 606 insertions(+), 87 deletions(-) diff --git a/web/src/app/wizard/page.tsx b/web/src/app/wizard/page.tsx index eb533f118..d0e92ec21 100644 --- a/web/src/app/wizard/page.tsx +++ b/web/src/app/wizard/page.tsx @@ -12,6 +12,8 @@ import { Loader2, X, ExternalLink, + Rocket, + Wrench, } from 'lucide-react'; import { httpClient } from '@/app/infra/http/HttpClient'; @@ -38,6 +40,7 @@ import { parseDynamicFormItemType, } from '@/app/home/components/dynamic-form/DynamicFormItemConfig'; import DynamicFormComponent from '@/app/home/components/dynamic-form/DynamicFormComponent'; +import ProviderForm from '@/app/home/components/models-dialog/component/provider-form/ProviderForm'; import { BotLogListComponent } from '@/app/home/bots/components/bot-log/view/BotLogListComponent'; import { extractI18nObject } from '@/i18n/I18nProvider'; import { @@ -67,6 +70,7 @@ import { DialogTitle, } from '@/components/ui/dialog'; + // --------------------------------------------------------------------------- // Types // --------------------------------------------------------------------------- @@ -92,6 +96,13 @@ export default function WizardPage() { {}, ); const [runnerConfig, setRunnerConfig] = useState>({}); + const [aiEngineMode, setAiEngineMode] = useState< + 'orchestrated' | 'llm' | null + >(null); + const [modelSource, setModelSource] = useState<'space' | 'custom' | null>( + null, + ); + const [providerCreated, setProviderCreated] = useState(false); const [createdBotUuid, setCreatedBotUuid] = useState(null); const [webhookUrl, setWebhookUrl] = useState(''); const [extraWebhookUrl, setExtraWebhookUrl] = useState(''); @@ -278,6 +289,16 @@ export default function WizardPage() { [saveProgress], ); + const handleAiEngineModeSelect = useCallback( + (mode: 'orchestrated' | 'llm') => { + setAiEngineMode(mode); + setSelectedRunner(null); + setModelSource(null); + setProviderCreated(false); + }, + [], + ); + // ---- Navigation helpers ---- const canProceed = useCallback((): boolean => { @@ -287,11 +308,29 @@ export default function WizardPage() { case 1: return createdBotUuid !== null && botSaved; case 2: - return selectedRunner !== null; + if (aiEngineMode === 'orchestrated') { + return selectedRunner !== null; + } + if (aiEngineMode === 'llm') { + return ( + modelSource === 'space' || + (modelSource === 'custom' && providerCreated) + ); + } + return false; default: return false; } - }, [currentStep, selectedAdapter, createdBotUuid, botSaved, selectedRunner]); + }, [ + currentStep, + selectedAdapter, + createdBotUuid, + botSaved, + aiEngineMode, + selectedRunner, + modelSource, + providerCreated, + ]); const goNext = useCallback(() => { if (currentStep < TOTAL_STEPS - 1 && canProceed()) { @@ -302,12 +341,35 @@ export default function WizardPage() { }, [currentStep, canProceed, saveProgress]); const goPrev = useCallback(() => { + if (currentStep === 2) { + // Intra-step back navigation for AI Engine step + if (selectedRunner && aiEngineMode === 'orchestrated') { + setSelectedRunner(null); + return; + } + if ( + aiEngineMode === 'llm' && + modelSource === 'custom' && + !providerCreated + ) { + setModelSource(null); + return; + } + if (modelSource) { + setModelSource(null); + return; + } + if (aiEngineMode) { + setAiEngineMode(null); + return; + } + } if (currentStep > 0) { const prevStep = currentStep - 1; setCurrentStep(prevStep); saveProgress({ step: prevStep }); } - }, [currentStep, saveProgress]); + }, [currentStep, saveProgress, aiEngineMode, selectedRunner, modelSource, providerCreated]); // ---- Create Bot (Step 0) ---- // Creates a disabled bot using the adapter label as name. @@ -503,6 +565,16 @@ export default function WizardPage() { } }, [t]); + const handleModelSourceSelect = useCallback( + (source: 'space' | 'custom') => { + setModelSource(source); + if (source === 'space') { + handleSpaceAuth(); + } + }, + [handleSpaceAuth], + ); + // ---- Check if local account ---- // Re-evaluated after remote data fetch (when userInfo is populated) const isLocalAccount = @@ -660,10 +732,17 @@ export default function WizardPage() { {currentStep === 2 && ( setProviderCreated(true)} + onResetModelSource={() => setModelSource(null)} runnerConfigItems={selectedRunnerConfigItems} runnerConfigValues={runnerConfig} onRunnerConfigChange={setRunnerConfig} @@ -1004,19 +1083,33 @@ function StepBotConfig({ function StepAIEngine({ runnerOptions, - selected, - onSelect, + aiEngineMode, + onAiEngineModeSelect, + selectedRunner, + onSelectRunner, isLocalAccount, onSpaceAuth, + modelSource, + onModelSourceSelect, + providerCreated, + onProviderCreated, + onResetModelSource, runnerConfigItems, runnerConfigValues, onRunnerConfigChange, }: { runnerOptions: { name: string; label: { en_US: string; zh_Hans: string } }[]; - selected: string | null; - onSelect: (name: string) => void; + aiEngineMode: 'orchestrated' | 'llm' | null; + onAiEngineModeSelect: (mode: 'orchestrated' | 'llm') => void; + selectedRunner: string | null; + onSelectRunner: (name: string) => void; isLocalAccount: boolean; onSpaceAuth: () => void; + modelSource: 'space' | 'custom' | null; + onModelSourceSelect: (source: 'space' | 'custom') => void; + providerCreated: boolean; + onProviderCreated: () => void; + onResetModelSource: () => void; runnerConfigItems: IDynamicFormItemSchema[]; runnerConfigValues: Record; onRunnerConfigChange: (v: Record) => void; @@ -1032,14 +1125,19 @@ function StepAIEngine({ ); const runnerLabel = useMemo(() => { - const r = runnerOptions.find((o) => o.name === selected); - return r ? extractI18nObject(r.label) : (selected ?? ''); - }, [runnerOptions, selected]); + const r = runnerOptions.find((o) => o.name === selectedRunner); + return r ? extractI18nObject(r.label) : (selectedRunner ?? ''); + }, [runnerOptions, selectedRunner]); - // Before any runner is selected: centered grid layout - if (!selected) { + // Orchestrated runners: everything except local-agent + const orchestratedRunners = runnerOptions.filter( + (o) => o.name !== 'local-agent', + ); + + // ---- Layer 0: Main choice ---- + if (!aiEngineMode) { return ( -
+

{t('wizard.aiEngine.title')} @@ -1048,12 +1146,75 @@ function StepAIEngine({ {t('wizard.aiEngine.description')}

+
+ {/* Orchestrated Agent Apps */} +
onAiEngineModeSelect('orchestrated')} + > +
+
+ +
+
+

+ {t('wizard.aiEngine.orchestrated.title')} +

+

+ {t('wizard.aiEngine.orchestrated.description')} +

+
+ +
+
+ + {/* Direct LLM */} +
onAiEngineModeSelect('llm')} + > +
+
+ +
+
+

+ {t('wizard.aiEngine.llm.title')} +

+

+ {t('wizard.aiEngine.llm.description')} +

+
+ +
+
+
+
+ ); + } + + // ---- Layer 1a: Orchestrated runners ---- + if (aiEngineMode === 'orchestrated' && !selectedRunner) { + return ( +
+
+

+ {t('wizard.aiEngine.orchestrated.selectTitle')} +

+

+ {t('wizard.aiEngine.orchestrated.selectDescription')} +

+
- {runnerOptions.map((opt) => ( + {orchestratedRunners.map((opt) => ( onSelect(opt.name)} + onClick={() => onSelectRunner(opt.name)} >
@@ -1072,9 +1233,96 @@ function StepAIEngine({ ); } - // After a runner is selected: left-right split layout - // On mobile (< lg): single column, normal scroll from parent - // On desktop (>= lg): side-by-side with independent scroll per column + // ---- Layer 1b: LLM model source selection ---- + if (aiEngineMode === 'llm' && !modelSource) { + return ( +
+
+

+ {t('wizard.modelSource.title')} +

+

+ {t('wizard.modelSource.description')} +

+
+
+ {/* LangBot Service */} +
onModelSourceSelect('space')} + > +
+
+ +
+
+

+ {t('wizard.modelSource.space.title')} +

+

+ {t('wizard.modelSource.space.description')} +

+
+ +
+
+ + {/* Custom provider */} +
onModelSourceSelect('custom')} + > +
+
+ +
+
+

+ {t('wizard.modelSource.custom.title')} +

+

+ {t('wizard.modelSource.custom.description')} +

+
+ +
+
+
+
+ ); + } + + // ---- Layer 2: Custom provider creation form ---- + if ( + aiEngineMode === 'llm' && + modelSource === 'custom' && + !providerCreated + ) { + return ( +
+
+

+ {t('wizard.provider.title')} +

+

+ {t('wizard.provider.description')} +

+
+
+ +
+
+ ); + } + + // ---- Layer 3: Runner configuration form ---- return (
@@ -1085,75 +1333,61 @@ function StepAIEngine({
- {/* Left: runner list */} -
- {/* p-1 provides space for ring-2 (4px) to render without clipping */} -
- {runnerOptions.map((opt) => { - const isSelected = selected === opt.name; - return ( - onSelect(opt.name)} - > - -
- - {extractI18nObject(opt.label)} - - - {opt.name} - -
- {isSelected && ( -
-
- -
-
+ {/* Left: runner list (only for orchestrated mode) */} + {aiEngineMode === 'orchestrated' && ( +
+
+ {orchestratedRunners.map((opt) => { + const isSelected = selectedRunner === opt.name; + return ( + - - ); - })} - - {/* Space promotion banner */} - {selected === 'local-agent' && isLocalAccount && ( -
-
-
- -

- {t('wizard.spaceBanner.message')} -

- -
-
-
- )} + onClick={() => onSelectRunner(opt.name)} + > + +
+ + {extractI18nObject(opt.label)} + + + {opt.name} + +
+ {isSelected && ( +
+
+ +
+
+ )} +
+ + ); + })} +
-
+ )} - {/* Right: runner configuration — fixed width on desktop */} -
+ {/* Right: runner configuration */} +
{runnerConfigItems.length > 0 && ( @@ -1164,7 +1398,7 @@ function StepAIEngine({ } onSubmit={stableRunnerConfigCb} diff --git a/web/src/i18n/locales/en-US.ts b/web/src/i18n/locales/en-US.ts index 6603cf560..f3b0b3b56 100644 --- a/web/src/i18n/locales/en-US.ts +++ b/web/src/i18n/locales/en-US.ts @@ -1835,12 +1835,47 @@ const enUS = { title: 'Select an AI Engine', description: "Choose the AI engine that will power your bot's intelligence.", + orchestrated: { + title: 'Use Orchestrated Agent Apps', + description: + 'Use pre-built Agent apps from Dify, n8n, Coze, and more.', + action: 'Select Agent App', + selectTitle: 'Select Agent App', + selectDescription: 'Choose the Agent app platform you want to use.', + }, + llm: { + title: 'Use LLM Directly', + description: + 'Configure a model provider and use LLM to drive your bot directly.', + action: 'Configure LLM', + }, }, spaceBanner: { message: 'Connect to LangBot Space for free trial model credits and zero-config instant setup!', action: 'Authorize with Space', }, + provider: { + title: 'Add Model Provider', + description: + 'Add your own model provider. Configure the API key to get started.', + }, + modelSource: { + title: 'Choose Model Source', + description: 'Select how to provide model capabilities for your AI engine.', + space: { + title: 'LangBot Service', + description: + 'Zero-config ready with free trial model credits. No API key needed — just plug and play.', + action: 'Use LangBot Service', + }, + custom: { + title: 'Custom Model', + description: + 'Bring your own model API key. Supports OpenAI, Claude, Gemini, and more.', + action: 'Add My Own Model', + }, + }, config: { botInfo: 'Bot Information', botNamePlaceholder: 'Enter bot name', diff --git a/web/src/i18n/locales/es-ES.ts b/web/src/i18n/locales/es-ES.ts index 1efa34173..02e467cbc 100644 --- a/web/src/i18n/locales/es-ES.ts +++ b/web/src/i18n/locales/es-ES.ts @@ -1691,12 +1691,49 @@ const esES = { title: 'Selecciona un motor de IA', description: 'Elige el motor de IA que impulsará la inteligencia de tu Bot.', + orchestrated: { + title: 'Usar aplicaciones Agent orquestadas', + description: + 'Usar aplicaciones Agent predefinidas de Dify, n8n, Coze y más.', + action: 'Seleccionar aplicación Agent', + selectTitle: 'Seleccionar aplicación Agent', + selectDescription: + 'Elige la plataforma de aplicación Agent que deseas usar.', + }, + llm: { + title: 'Usar modelo directamente', + description: + 'Configurar un proveedor de modelos y usar el modelo para impulsar tu Bot.', + action: 'Configurar modelo', + }, }, spaceBanner: { message: '¡Conéctate a LangBot Space para obtener créditos de prueba gratuitos y configuración instantánea sin esfuerzo!', action: 'Autorizar con Space', }, + provider: { + title: 'Agregar proveedor de modelos', + description: + 'Agrega tu propio proveedor de modelos. Configura la API key para comenzar.', + }, + modelSource: { + title: 'Elegir fuente del modelo', + description: + 'Selecciona cómo proporcionar capacidades de modelo para tu motor de IA.', + space: { + title: 'Servicio LangBot', + description: + 'Listo para usar sin configuración, con créditos de prueba gratuitos. No se necesita API key.', + action: 'Usar servicio LangBot', + }, + custom: { + title: 'Modelo personalizado', + description: + 'Usa tu propia API key. Compatible con OpenAI, Claude, Gemini y más.', + action: 'Agregar mi propio modelo', + }, + }, config: { botInfo: 'Información del Bot', botNamePlaceholder: 'Introduce el nombre del Bot', diff --git a/web/src/i18n/locales/ja-JP.ts b/web/src/i18n/locales/ja-JP.ts index 7285086c4..5143a262d 100644 --- a/web/src/i18n/locales/ja-JP.ts +++ b/web/src/i18n/locales/ja-JP.ts @@ -1752,12 +1752,48 @@ const jaJP = { title: 'AIエンジンを選択', description: 'ボットのインテリジェンスを駆動するAIエンジンを選択してください。', + orchestrated: { + title: 'オーケストレーション済みAgentアプリを使用', + description: + 'Dify、n8n、Cozeなどのプラットフォームで構築済みのAgentアプリを使用。', + action: 'Agentアプリを選択', + selectTitle: 'Agentアプリを選択', + selectDescription: + '使用するAgentアプリプラットフォームを選択してください。', + }, + llm: { + title: '大規模モデルを直接使用', + description: + 'モデルプロバイダーを設定し、大規模モデルでボットを直接駆動。', + action: '大規模モデルを設定', + }, }, spaceBanner: { message: 'LangBot Spaceに接続して、無料トライアルモデルクレジットとゼロ設定の即時セットアップを入手!', action: 'Spaceで認証', }, + provider: { + title: 'モデルプロバイダーを追加', + description: + '独自のモデルプロバイダーを追加します。APIキーを設定すると使用可能になります。', + }, + modelSource: { + title: 'モデルソースを選択', + description: 'AIエンジンにモデル機能を提供する方法を選択してください。', + space: { + title: 'LangBot サービス', + description: + '設定不要で利用可能。無料トライアルモデルクレジット付き。APIキー不要ですぐに使えます。', + action: 'LangBot サービスを使用', + }, + custom: { + title: 'カスタムモデル', + description: + 'お手持ちのモデルAPIキーを使用。OpenAI、Claude、Geminiなど主要モデルに対応。', + action: '独自のモデルを追加', + }, + }, config: { botInfo: 'ボット情報', botNamePlaceholder: 'ボット名を入力', diff --git a/web/src/i18n/locales/ru-RU.ts b/web/src/i18n/locales/ru-RU.ts index b167c81a1..d94675809 100644 --- a/web/src/i18n/locales/ru-RU.ts +++ b/web/src/i18n/locales/ru-RU.ts @@ -1661,12 +1661,49 @@ const ruRU = { title: 'Выберите ИИ-движок', description: 'Выберите ИИ-движок, который будет управлять интеллектом вашего бота.', + orchestrated: { + title: 'Использовать оркестрированные Agent-приложения', + description: + 'Использовать готовые Agent-приложения из Dify, n8n, Coze и других.', + action: 'Выбрать Agent-приложение', + selectTitle: 'Выбрать Agent-приложение', + selectDescription: + 'Выберите платформу Agent-приложения для использования.', + }, + llm: { + title: 'Использовать LLM напрямую', + description: + 'Настроить провайдера моделей и использовать LLM для управления ботом.', + action: 'Настроить LLM', + }, }, spaceBanner: { message: 'Подключитесь к LangBot Space для бесплатных пробных кредитов и мгновенной настройки!', action: 'Авторизация через Space', }, + provider: { + title: 'Добавить провайдера моделей', + description: + 'Добавьте своего провайдера моделей. Настройте API-ключ для начала работы.', + }, + modelSource: { + title: 'Выберите источник модели', + description: + 'Выберите способ предоставления возможностей модели для вашего AI-движка.', + space: { + title: 'Сервис LangBot', + description: + 'Готов к использованию без настройки, с бесплатными пробными кредитами. API-ключ не требуется.', + action: 'Использовать сервис LangBot', + }, + custom: { + title: 'Пользовательская модель', + description: + 'Используйте свой собственный API-ключ. Поддержка OpenAI, Claude, Gemini и других.', + action: 'Добавить свою модель', + }, + }, config: { botInfo: 'Информация о боте', botNamePlaceholder: 'Введите имя бота', diff --git a/web/src/i18n/locales/th-TH.ts b/web/src/i18n/locales/th-TH.ts index c1afcb48a..3b036ed37 100644 --- a/web/src/i18n/locales/th-TH.ts +++ b/web/src/i18n/locales/th-TH.ts @@ -1626,12 +1626,47 @@ const thTH = { aiEngine: { title: 'เลือกเครื่องมือ AI', description: 'เลือกเครื่องมือ AI ที่จะขับเคลื่อนความฉลาดของ Bot', + orchestrated: { + title: 'ใช้แอป Agent ที่จัดเตรียมไว้', + description: + 'ใช้แอป Agent ที่สร้างไว้จาก Dify, n8n, Coze และอื่นๆ', + action: 'เลือกแอป Agent', + selectTitle: 'เลือกแอป Agent', + selectDescription: 'เลือกแพลตฟอร์มแอป Agent ที่ต้องการใช้', + }, + llm: { + title: 'ใช้โมเดลโดยตรง', + description: + 'กำหนดค่าผู้ให้บริการโมเดลและใช้โมเดลขับเคลื่อน Bot โดยตรง', + action: 'กำหนดค่าโมเดล', + }, }, spaceBanner: { message: 'เชื่อมต่อกับ LangBot Space เพื่อรับเครดิตทดลองใช้โมเดลฟรีและตั้งค่าทันทีโดยไม่ต้องกำหนดค่า!', action: 'ยืนยันสิทธิ์กับ Space', }, + provider: { + title: 'เพิ่มผู้ให้บริการโมเดล', + description: + 'เพิ่มผู้ให้บริการโมเดลของคุณเอง กำหนดค่า API key เพื่อเริ่มต้น', + }, + modelSource: { + title: 'เลือกแหล่งโมเดล', + description: 'เลือกวิธีการให้ความสามารถของโมเดลสำหรับ AI engine ของคุณ', + space: { + title: 'บริการ LangBot', + description: + 'พร้อมใช้งานทันทีไม่ต้องตั้งค่า พร้อมเครดิตทดลองใช้โมเดลฟรี ไม่ต้องใช้ API key', + action: 'ใช้บริการ LangBot', + }, + custom: { + title: 'โมเดลกำหนดเอง', + description: + 'ใช้ API key โมเดลของคุณเอง รองรับ OpenAI, Claude, Gemini และอื่นๆ', + action: 'เพิ่มโมเดลของฉัน', + }, + }, config: { botInfo: 'ข้อมูล Bot', botNamePlaceholder: 'กรอกชื่อ Bot', diff --git a/web/src/i18n/locales/vi-VN.ts b/web/src/i18n/locales/vi-VN.ts index 1a4af1319..e0281d52a 100644 --- a/web/src/i18n/locales/vi-VN.ts +++ b/web/src/i18n/locales/vi-VN.ts @@ -1652,12 +1652,47 @@ const viVN = { aiEngine: { title: 'Chọn công cụ AI', description: 'Chọn công cụ AI sẽ cung cấp trí tuệ cho Bot của bạn.', + orchestrated: { + title: 'Sử dụng ứng dụng Agent đã được phối hợp', + description: + 'Sử dụng các ứng dụng Agent đã được xây dựng từ Dify, n8n, Coze.', + action: 'Chọn ứng dụng Agent', + selectTitle: 'Chọn ứng dụng Agent', + selectDescription: 'Chọn nền tảng ứng dụng Agent bạn muốn sử dụng.', + }, + llm: { + title: 'Sử dụng mô hình trực tiếp', + description: + 'Cấu hình nhà cung cấp mô hình và sử dụng mô hình lớn để điều khiển Bot.', + action: 'Cấu hình mô hình', + }, }, spaceBanner: { message: 'Kết nối với LangBot Space để nhận tín dụng dùng thử mô hình miễn phí và thiết lập tức thì không cần cấu hình!', action: 'Ủy quyền với Space', }, + provider: { + title: 'Thêm nhà cung cấp mô hình', + description: + 'Thêm nhà cung cấp mô hình của bạn. Cấu hình API key để bắt đầu.', + }, + modelSource: { + title: 'Chọn nguồn mô hình', + description: 'Chọn cách cung cấp khả năng mô hình cho AI engine của bạn.', + space: { + title: 'Dịch vụ LangBot', + description: + 'Sẵn sàng sử dụng không cần cấu hình, tặng tín dụng mô hình thử nghiệm miễn phí. Không cần API key.', + action: 'Sử dụng dịch vụ LangBot', + }, + custom: { + title: 'Mô hình tùy chỉnh', + description: + 'Sử dụng API key mô hình của riêng bạn. Hỗ trợ OpenAI, Claude, Gemini và nhiều hơn nữa.', + action: 'Thêm mô hình của tôi', + }, + }, config: { botInfo: 'Thông tin Bot', botNamePlaceholder: 'Nhập tên Bot', diff --git a/web/src/i18n/locales/zh-Hans.ts b/web/src/i18n/locales/zh-Hans.ts index bbece7f35..0a743d4df 100644 --- a/web/src/i18n/locales/zh-Hans.ts +++ b/web/src/i18n/locales/zh-Hans.ts @@ -1755,11 +1755,43 @@ const zhHans = { aiEngine: { title: '选择 AI 引擎', description: '选择驱动机器人智能的 AI 引擎。', + orchestrated: { + title: '使用编排好的 Agent 应用', + description: '使用 Dify、n8n、Coze 等平台编排好的 Agent 应用。', + action: '选择 Agent 应用', + selectTitle: '选择 Agent 应用', + selectDescription: '选择你要使用的 Agent 应用平台。', + }, + llm: { + title: '直接使用大模型', + description: '配置大模型供应商,直接使用大模型驱动机器人。', + action: '配置大模型', + }, }, spaceBanner: { message: '接入 LangBot Space,获取免费试用模型额度,零配置极速开箱!', action: '前往授权登录', }, + provider: { + title: '添加模型供应商', + description: '添加你自己的模型供应商,配置 API Key 后即可使用。', + }, + modelSource: { + title: '选择模型来源', + description: '选择如何为你的 AI 引擎提供模型能力。', + space: { + title: 'LangBot 服务', + description: + '零配置即可使用,提供免费试用模型额度,开箱即用,无需自备 API Key。', + action: '使用 LangBot 服务', + }, + custom: { + title: '自定义模型', + description: + '使用你自己的模型 API Key,支持 OpenAI、Claude、Gemini 等主流模型。', + action: '添加我自己的模型', + }, + }, config: { botInfo: '机器人信息', botNamePlaceholder: '请输入机器人名称', diff --git a/web/src/i18n/locales/zh-Hant.ts b/web/src/i18n/locales/zh-Hant.ts index 707907a32..b1d65ad65 100644 --- a/web/src/i18n/locales/zh-Hant.ts +++ b/web/src/i18n/locales/zh-Hant.ts @@ -1578,11 +1578,43 @@ const zhHant = { aiEngine: { title: '選擇 AI 引擎', description: '選擇驅動機器人智慧的 AI 引擎。', + orchestrated: { + title: '使用編排好的 Agent 應用', + description: '使用 Dify、n8n、Coze 等平台編排好的 Agent 應用。', + action: '選擇 Agent 應用', + selectTitle: '選擇 Agent 應用', + selectDescription: '選擇你要使用的 Agent 應用平台。', + }, + llm: { + title: '直接使用大模型', + description: '配置大模型供應商,直接使用大模型驅動機器人。', + action: '配置大模型', + }, }, spaceBanner: { message: '接入 LangBot Space,取得免費試用模型額度,零配置極速開箱!', action: '前往授權登入', }, + provider: { + title: '新增模型供應商', + description: '新增你自己的模型供應商,配置 API Key 後即可使用。', + }, + modelSource: { + title: '選擇模型來源', + description: '選擇如何為你的 AI 引擎提供模型能力。', + space: { + title: 'LangBot 服務', + description: + '零配置即可使用,提供免費試用模型額度,開箱即用,無需自備 API Key。', + action: '使用 LangBot 服務', + }, + custom: { + title: '自訂模型', + description: + '使用你自己的模型 API Key,支援 OpenAI、Claude、Gemini 等主流模型。', + action: '新增我自己的模型', + }, + }, config: { botInfo: '機器人資訊', botNamePlaceholder: '請輸入機器人名稱', diff --git a/web/vite.config.ts b/web/vite.config.ts index d1023070a..9df5ed61e 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -11,6 +11,12 @@ export default defineConfig({ }, server: { port: 3000, + proxy: { + '/api': { + target: 'http://127.0.0.1:5300', + changeOrigin: true, + }, + }, }, build: { outDir: 'dist',