diff --git a/web/src/app/home/components/WorkspaceAssistant.tsx b/web/src/app/home/components/WorkspaceAssistant.tsx index 82d8ff235..dd2dbad38 100644 --- a/web/src/app/home/components/WorkspaceAssistant.tsx +++ b/web/src/app/home/components/WorkspaceAssistant.tsx @@ -22,6 +22,7 @@ import { } from '@/app/infra/http'; import { toast } from 'sonner'; import { httpClient } from '@/app/infra/http/HttpClient'; +import { MODEL_CONFIGURATION_CHANGED } from '@/app/infra/http/modelConfigEvents'; import SettingsDialog, { SettingsSection, } from './settings-dialog/SettingsDialog'; @@ -85,10 +86,12 @@ function AssistantEntry({ storageKey }: { storageKey: string }) { useEffect(() => { let active = true; + let latestCheck = 0; async function check() { + const currentCheck = ++latestCheck; try { const { models } = await backendClient.getProviderLLMModels(); - if (active) { + if (active && currentCheck === latestCheck) { const usableModels = models.filter( (model) => !!model.uuid?.trim() && @@ -109,14 +112,16 @@ function AssistantEntry({ storageKey }: { storageKey: string }) { setFailed(false); } } catch { - if (active) setFailed(true); + if (active && currentCheck === latestCheck) setFailed(true); } } if (!settingsOpen) void check(); window.addEventListener('focus', check); + window.addEventListener(MODEL_CONFIGURATION_CHANGED, check); return () => { active = false; window.removeEventListener('focus', check); + window.removeEventListener(MODEL_CONFIGURATION_CHANGED, check); }; }, [settingsOpen, retry]); diff --git a/web/src/app/home/components/dynamic-form/DynamicFormItemComponent.tsx b/web/src/app/home/components/dynamic-form/DynamicFormItemComponent.tsx index 054120395..3f14128c8 100644 --- a/web/src/app/home/components/dynamic-form/DynamicFormItemComponent.tsx +++ b/web/src/app/home/components/dynamic-form/DynamicFormItemComponent.tsx @@ -22,6 +22,7 @@ import { ControllerRenderProps } from 'react-hook-form'; import { Button } from '@/components/ui/button'; import { useEffect, useState } from 'react'; import { httpClient, systemInfo, userInfo } from '@/app/infra/http'; +import { MODEL_CONFIGURATION_CHANGED } from '@/app/infra/http/modelConfigEvents'; import { useInstalledPluginIcon } from '@/app/infra/hooks/useInstalledPluginIcon'; import { LLMModel, @@ -306,6 +307,10 @@ export default function DynamicFormItemComponent({ useEffect(() => { if (config.type === DynamicFormItemType.LLM_MODEL_SELECTOR) { fetchLlmModels(); + window.addEventListener(MODEL_CONFIGURATION_CHANGED, fetchLlmModels); + return () => { + window.removeEventListener(MODEL_CONFIGURATION_CHANGED, fetchLlmModels); + }; } }, [config.type]); diff --git a/web/src/app/home/components/models-dialog/components/ProviderCard.tsx b/web/src/app/home/components/models-dialog/components/ProviderCard.tsx index 0d29151d4..a0b49612e 100644 --- a/web/src/app/home/components/models-dialog/components/ProviderCard.tsx +++ b/web/src/app/home/components/models-dialog/components/ProviderCard.tsx @@ -367,7 +367,7 @@ export default function ProviderCard({ }} > - {t('models.addModel')} + {t('common.add')} } onOpen={() => { @@ -394,14 +394,15 @@ export default function ProviderCard({ trigger={ } onOpen={() => { diff --git a/web/src/app/infra/http/BackendClient.ts b/web/src/app/infra/http/BackendClient.ts index 27eb93657..b8591c4c4 100644 --- a/web/src/app/infra/http/BackendClient.ts +++ b/web/src/app/infra/http/BackendClient.ts @@ -1,4 +1,5 @@ import { BaseHttpClient, type RequestConfig } from './BaseHttpClient'; +import { notifyAfterModelConfigurationChange } from './modelConfigEvents'; import type { PipelineMigrationPreview, PipelineMigrationRequest, @@ -148,19 +149,25 @@ export class BackendClient extends BaseHttpClient { public createModelProvider( provider: Omit, ): Promise<{ uuid: string }> { - return this.post('/api/v1/provider/providers', provider); + return notifyAfterModelConfigurationChange( + this.post<{ uuid: string }>('/api/v1/provider/providers', provider), + ); } public updateModelProvider( uuid: string, provider: Partial, ): Promise { - return this.put(`/api/v1/provider/providers/${uuid}`, provider); + return notifyAfterModelConfigurationChange( + this.put(`/api/v1/provider/providers/${uuid}`, provider), + ); } public deleteModelProvider(uuid: string, cascade = false): Promise { - return this.delete( - `/api/v1/provider/providers/${uuid}${cascade ? '?cascade=true' : ''}`, + return notifyAfterModelConfigurationChange( + this.delete( + `/api/v1/provider/providers/${uuid}${cascade ? '?cascade=true' : ''}`, + ), ); } @@ -229,18 +236,24 @@ export class BackendClient extends BaseHttpClient { public createProviderLLMModel( model: Omit, ): Promise<{ uuid: string }> { - return this.post('/api/v1/provider/models/llm', model); + return notifyAfterModelConfigurationChange( + this.post<{ uuid: string }>('/api/v1/provider/models/llm', model), + ); } public deleteProviderLLMModel(uuid: string): Promise { - return this.delete(`/api/v1/provider/models/llm/${uuid}`); + return notifyAfterModelConfigurationChange( + this.delete(`/api/v1/provider/models/llm/${uuid}`), + ); } public updateProviderLLMModel( uuid: string, model: LLMModel, ): Promise { - return this.put(`/api/v1/provider/models/llm/${uuid}`, model); + return notifyAfterModelConfigurationChange( + this.put(`/api/v1/provider/models/llm/${uuid}`, model), + ); } public testLLMModel(uuid: string, model: LLMModel): Promise { diff --git a/web/src/app/infra/http/modelConfigEvents.ts b/web/src/app/infra/http/modelConfigEvents.ts new file mode 100644 index 000000000..989ccb368 --- /dev/null +++ b/web/src/app/infra/http/modelConfigEvents.ts @@ -0,0 +1,11 @@ +export const MODEL_CONFIGURATION_CHANGED = 'langbot:model-configuration-changed'; + +export async function notifyAfterModelConfigurationChange( + request: Promise, +): Promise { + const result = await request; + if (typeof window !== 'undefined') { + window.dispatchEvent(new Event(MODEL_CONFIGURATION_CHANGED)); + } + return result; +} diff --git a/web/src/i18n/locales/en-US.ts b/web/src/i18n/locales/en-US.ts index 4de72d3bb..e712f633e 100644 --- a/web/src/i18n/locales/en-US.ts +++ b/web/src/i18n/locales/en-US.ts @@ -8,7 +8,8 @@ const enUS = { stop: 'Stop task', stopped: 'Stopped. An in-progress tool may already have taken effect. Check its resource before retrying.', - setupRequired: 'Sign in to LangBot Account or configure a model.', + setupRequired: + 'Sign in to LangBot Account or configure a model to start using the workspace assistant.', loginAccount: 'Sign in to LangBot Account', configureModels: 'Configure models', providerCheckFailed: 'Could not check model providers. Please try again.', diff --git a/web/src/i18n/locales/es-ES.ts b/web/src/i18n/locales/es-ES.ts index 93fb07ffc..485270053 100644 --- a/web/src/i18n/locales/es-ES.ts +++ b/web/src/i18n/locales/es-ES.ts @@ -9,7 +9,7 @@ const esES = { stopped: 'Detenido. Una herramienta en curso puede haber surtido efecto. Comprueba el recurso antes de reintentar.', setupRequired: - 'Inicia sesión en LangBot Account para usar LangBot Models o configura tu proveedor de modelos para empezar a conversar.', + 'Inicia sesión con tu cuenta de LangBot o configura un modelo para empezar a usar el asistente del espacio de trabajo.', loginAccount: 'Iniciar sesión en LangBot Account', configureModels: 'Configurar modelos', providerCheckFailed: diff --git a/web/src/i18n/locales/ja-JP.ts b/web/src/i18n/locales/ja-JP.ts index 75afb225f..8091523c1 100644 --- a/web/src/i18n/locales/ja-JP.ts +++ b/web/src/i18n/locales/ja-JP.ts @@ -9,7 +9,7 @@ const jaJP = { stopped: '停止しました。実行中のツールが反映済みの場合があります。再試行前にリソースを確認してください。', setupRequired: - 'LangBot Account にログインするか、モデルを設定してください。', + 'LangBot アカウントにログインするか、モデルを設定すると、ワークスペースアシスタントを利用できます。', loginAccount: 'LangBot Account にログイン', configureModels: 'モデルを設定', providerCheckFailed: diff --git a/web/src/i18n/locales/ru-RU.ts b/web/src/i18n/locales/ru-RU.ts index 95aedc522..c479ef5e8 100644 --- a/web/src/i18n/locales/ru-RU.ts +++ b/web/src/i18n/locales/ru-RU.ts @@ -9,7 +9,7 @@ const ruRU = { stopped: 'Остановлено. Инструмент мог уже внести изменения. Проверьте ресурс перед повтором.', setupRequired: - 'Войдите в LangBot Account для доступа к LangBot Models или настройте своего провайдера моделей, чтобы начать диалог.', + 'Войдите в аккаунт LangBot или настройте модель, чтобы начать пользоваться помощником рабочего пространства.', loginAccount: 'Войти в LangBot Account', configureModels: 'Настроить модели', providerCheckFailed: diff --git a/web/src/i18n/locales/th-TH.ts b/web/src/i18n/locales/th-TH.ts index 5b65bb85c..b5978a76b 100644 --- a/web/src/i18n/locales/th-TH.ts +++ b/web/src/i18n/locales/th-TH.ts @@ -9,7 +9,7 @@ const thTH = { stopped: 'หยุดแล้ว เครื่องมืออาจดำเนินการไปแล้ว โปรดตรวจสอบทรัพยากรก่อนลองอีกครั้ง', setupRequired: - 'เข้าสู่ระบบ LangBot Account เพื่อใช้ LangBot Models หรือตั้งค่าผู้ให้บริการโมเดลของคุณเพื่อเริ่มสนทนา', + 'เข้าสู่ระบบด้วยบัญชี LangBot หรือตั้งค่าโมเดลเพื่อเริ่มใช้ผู้ช่วยพื้นที่ทำงาน', loginAccount: 'เข้าสู่ระบบ LangBot Account', configureModels: 'ตั้งค่าโมเดล', providerCheckFailed: 'ไม่สามารถตรวจสอบผู้ให้บริการโมเดลได้ โปรดลองอีกครั้ง', diff --git a/web/src/i18n/locales/vi-VN.ts b/web/src/i18n/locales/vi-VN.ts index 05a78e34c..cefa3d4ce 100644 --- a/web/src/i18n/locales/vi-VN.ts +++ b/web/src/i18n/locales/vi-VN.ts @@ -9,7 +9,7 @@ const viVN = { stopped: 'Đã dừng. Công cụ có thể đã thực hiện thay đổi. Kiểm tra tài nguyên trước khi thử lại.', setupRequired: - 'Đăng nhập LangBot Account để dùng LangBot Models hoặc cấu hình nhà cung cấp mô hình riêng để bắt đầu trò chuyện.', + 'Đăng nhập bằng tài khoản LangBot hoặc cấu hình mô hình để bắt đầu sử dụng trợ lý không gian làm việc.', loginAccount: 'Đăng nhập LangBot Account', configureModels: 'Cấu hình mô hình', providerCheckFailed: 'Không thể kiểm tra nhà cung cấp. Vui lòng thử lại.', diff --git a/web/src/i18n/locales/zh-Hans.ts b/web/src/i18n/locales/zh-Hans.ts index 76b031ae1..7eb045d19 100644 --- a/web/src/i18n/locales/zh-Hans.ts +++ b/web/src/i18n/locales/zh-Hans.ts @@ -7,7 +7,7 @@ const zhHans = { currentChat: '当前会话', stop: '停止任务', stopped: '已停止。执行中的工具可能已经生效,请检查相关资源后再尝试。', - setupRequired: '请使用 LangBot 账户登录或配置模型', + setupRequired: '登录 LangBot 账户或配置模型,即可开始使用工作区助手。', loginAccount: '登录 LangBot 账户', configureModels: '配置模型', providerCheckFailed: '无法检查模型供应商,请重试。', diff --git a/web/src/i18n/locales/zh-Hant.ts b/web/src/i18n/locales/zh-Hant.ts index 144aabb96..121154728 100644 --- a/web/src/i18n/locales/zh-Hant.ts +++ b/web/src/i18n/locales/zh-Hant.ts @@ -8,7 +8,7 @@ const zhHant = { stop: '停止任務', stopped: '已停止。執行中的工具可能已經生效,請檢查相關資源後再嘗試。', setupRequired: - '登入 LangBot Account 使用 LangBot Models,或先設定自己的模型供應商,即可開始對話。', + '登入 LangBot 帳戶或設定模型,即可開始使用工作區助手。', loginAccount: '登入 LangBot Account', configureModels: '設定模型', providerCheckFailed: '無法檢查模型供應商,請重試。',