fix(web): refresh assistant model state and refine model actions

This commit is contained in:
Hyu
2026-10-09 00:46:51 +08:00
parent fe324fac81
commit 113bb0b773
13 changed files with 57 additions and 21 deletions
@@ -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]);
@@ -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]);
@@ -367,7 +367,7 @@ export default function ProviderCard({
}}
>
<Plus className="h-3 w-3 mr-1" />
{t('models.addModel')}
{t('common.add')}
</Button>
}
onOpen={() => {
@@ -394,14 +394,15 @@ export default function ProviderCard({
trigger={
<Button
variant="ghost"
size="icon"
className="h-6 w-6"
size="sm"
className="h-6 text-xs"
onClick={(e) => {
e.stopPropagation();
setAddModelMode('scan');
}}
>
<Radar className="h-3 w-3" />
<Radar className="h-3 w-3 mr-1" />
{t('models.scanModels')}
</Button>
}
onOpen={() => {
+20 -7
View File
@@ -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<ModelProvider, 'uuid'>,
): 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<ModelProvider>,
): Promise<object> {
return this.put(`/api/v1/provider/providers/${uuid}`, provider);
return notifyAfterModelConfigurationChange(
this.put<object>(`/api/v1/provider/providers/${uuid}`, provider),
);
}
public deleteModelProvider(uuid: string, cascade = false): Promise<object> {
return this.delete(
`/api/v1/provider/providers/${uuid}${cascade ? '?cascade=true' : ''}`,
return notifyAfterModelConfigurationChange(
this.delete<object>(
`/api/v1/provider/providers/${uuid}${cascade ? '?cascade=true' : ''}`,
),
);
}
@@ -229,18 +236,24 @@ export class BackendClient extends BaseHttpClient {
public createProviderLLMModel(
model: Omit<LLMModel, 'uuid'>,
): 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<object> {
return this.delete(`/api/v1/provider/models/llm/${uuid}`);
return notifyAfterModelConfigurationChange(
this.delete<object>(`/api/v1/provider/models/llm/${uuid}`),
);
}
public updateProviderLLMModel(
uuid: string,
model: LLMModel,
): Promise<object> {
return this.put(`/api/v1/provider/models/llm/${uuid}`, model);
return notifyAfterModelConfigurationChange(
this.put<object>(`/api/v1/provider/models/llm/${uuid}`, model),
);
}
public testLLMModel(uuid: string, model: LLMModel): Promise<object> {
@@ -0,0 +1,11 @@
export const MODEL_CONFIGURATION_CHANGED = 'langbot:model-configuration-changed';
export async function notifyAfterModelConfigurationChange<T>(
request: Promise<T>,
): Promise<T> {
const result = await request;
if (typeof window !== 'undefined') {
window.dispatchEvent(new Event(MODEL_CONFIGURATION_CHANGED));
}
return result;
}
+2 -1
View File
@@ -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.',
+1 -1
View File
@@ -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:
+1 -1
View File
@@ -9,7 +9,7 @@ const jaJP = {
stopped:
'停止しました。実行中のツールが反映済みの場合があります。再試行前にリソースを確認してください。',
setupRequired:
'LangBot Account にログインするか、モデルを設定してください。',
'LangBot アカウントにログインするか、モデルを設定すると、ワークスペースアシスタントを利用できます。',
loginAccount: 'LangBot Account にログイン',
configureModels: 'モデルを設定',
providerCheckFailed:
+1 -1
View File
@@ -9,7 +9,7 @@ const ruRU = {
stopped:
'Остановлено. Инструмент мог уже внести изменения. Проверьте ресурс перед повтором.',
setupRequired:
'Войдите в LangBot Account для доступа к LangBot Models или настройте своего провайдера моделей, чтобы начать диалог.',
'Войдите в аккаунт LangBot или настройте модель, чтобы начать пользоваться помощником рабочего пространства.',
loginAccount: 'Войти в LangBot Account',
configureModels: 'Настроить модели',
providerCheckFailed:
+1 -1
View File
@@ -9,7 +9,7 @@ const thTH = {
stopped:
'หยุดแล้ว เครื่องมืออาจดำเนินการไปแล้ว โปรดตรวจสอบทรัพยากรก่อนลองอีกครั้ง',
setupRequired:
'เข้าสู่ระบบ LangBot Account เพื่อใช้ LangBot Models หรือตั้งค่าผู้ให้บริการโมเดลของคุณเพื่อเริ่มสนทนา',
'เข้าสู่ระบบด้วยบัญชี LangBot หรือตั้งค่าโมเดลเพื่อเริ่มใช้ผู้ช่วยพื้นที่ทำงาน',
loginAccount: 'เข้าสู่ระบบ LangBot Account',
configureModels: 'ตั้งค่าโมเดล',
providerCheckFailed: 'ไม่สามารถตรวจสอบผู้ให้บริการโมเดลได้ โปรดลองอีกครั้ง',
+1 -1
View File
@@ -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.',
+1 -1
View File
@@ -7,7 +7,7 @@ const zhHans = {
currentChat: '当前会话',
stop: '停止任务',
stopped: '已停止。执行中的工具可能已经生效,请检查相关资源后再尝试。',
setupRequired: '请使用 LangBot 账户登录或配置模型',
setupRequired: '登录 LangBot 账户或配置模型,即可开始使用工作区助手。',
loginAccount: '登录 LangBot 账户',
configureModels: '配置模型',
providerCheckFailed: '无法检查模型供应商,请重试。',
+1 -1
View File
@@ -8,7 +8,7 @@ const zhHant = {
stop: '停止任務',
stopped: '已停止。執行中的工具可能已經生效,請檢查相關資源後再嘗試。',
setupRequired:
'登入 LangBot Account 使用 LangBot Models,或先設定自己的模型供應商,即可開始對話。',
'登入 LangBot 帳戶或設定模型,即可開始使用工作區助手。',
loginAccount: '登入 LangBot Account',
configureModels: '設定模型',
providerCheckFailed: '無法檢查模型供應商,請重試。',