mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-10-21 07:55:18 +08:00
fix(web): refresh assistant model state and refine model actions
This commit is contained in:
@@ -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={() => {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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.',
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -9,7 +9,7 @@ const jaJP = {
|
||||
stopped:
|
||||
'停止しました。実行中のツールが反映済みの場合があります。再試行前にリソースを確認してください。',
|
||||
setupRequired:
|
||||
'LangBot Account にログインするか、モデルを設定してください。',
|
||||
'LangBot アカウントにログインするか、モデルを設定すると、ワークスペースアシスタントを利用できます。',
|
||||
loginAccount: 'LangBot Account にログイン',
|
||||
configureModels: 'モデルを設定',
|
||||
providerCheckFailed:
|
||||
|
||||
@@ -9,7 +9,7 @@ const ruRU = {
|
||||
stopped:
|
||||
'Остановлено. Инструмент мог уже внести изменения. Проверьте ресурс перед повтором.',
|
||||
setupRequired:
|
||||
'Войдите в LangBot Account для доступа к LangBot Models или настройте своего провайдера моделей, чтобы начать диалог.',
|
||||
'Войдите в аккаунт LangBot или настройте модель, чтобы начать пользоваться помощником рабочего пространства.',
|
||||
loginAccount: 'Войти в LangBot Account',
|
||||
configureModels: 'Настроить модели',
|
||||
providerCheckFailed:
|
||||
|
||||
@@ -9,7 +9,7 @@ const thTH = {
|
||||
stopped:
|
||||
'หยุดแล้ว เครื่องมืออาจดำเนินการไปแล้ว โปรดตรวจสอบทรัพยากรก่อนลองอีกครั้ง',
|
||||
setupRequired:
|
||||
'เข้าสู่ระบบ LangBot Account เพื่อใช้ LangBot Models หรือตั้งค่าผู้ให้บริการโมเดลของคุณเพื่อเริ่มสนทนา',
|
||||
'เข้าสู่ระบบด้วยบัญชี LangBot หรือตั้งค่าโมเดลเพื่อเริ่มใช้ผู้ช่วยพื้นที่ทำงาน',
|
||||
loginAccount: 'เข้าสู่ระบบ LangBot Account',
|
||||
configureModels: 'ตั้งค่าโมเดล',
|
||||
providerCheckFailed: 'ไม่สามารถตรวจสอบผู้ให้บริการโมเดลได้ โปรดลองอีกครั้ง',
|
||||
|
||||
@@ -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.',
|
||||
|
||||
@@ -7,7 +7,7 @@ const zhHans = {
|
||||
currentChat: '当前会话',
|
||||
stop: '停止任务',
|
||||
stopped: '已停止。执行中的工具可能已经生效,请检查相关资源后再尝试。',
|
||||
setupRequired: '请使用 LangBot 账户登录或配置模型',
|
||||
setupRequired: '登录 LangBot 账户或配置模型,即可开始使用工作区助手。',
|
||||
loginAccount: '登录 LangBot 账户',
|
||||
configureModels: '配置模型',
|
||||
providerCheckFailed: '无法检查模型供应商,请重试。',
|
||||
|
||||
@@ -8,7 +8,7 @@ const zhHant = {
|
||||
stop: '停止任務',
|
||||
stopped: '已停止。執行中的工具可能已經生效,請檢查相關資源後再嘗試。',
|
||||
setupRequired:
|
||||
'登入 LangBot Account 使用 LangBot Models,或先設定自己的模型供應商,即可開始對話。',
|
||||
'登入 LangBot 帳戶或設定模型,即可開始使用工作區助手。',
|
||||
loginAccount: '登入 LangBot Account',
|
||||
configureModels: '設定模型',
|
||||
providerCheckFailed: '無法檢查模型供應商,請重試。',
|
||||
|
||||
Reference in New Issue
Block a user