diff --git a/api/db/joint_services/tenant_model_service.py b/api/db/joint_services/tenant_model_service.py index 785312032e..425ff459ce 100644 --- a/api/db/joint_services/tenant_model_service.py +++ b/api/db/joint_services/tenant_model_service.py @@ -435,6 +435,37 @@ def ensure_tenant_model_ids_for_params(tenant_id: str, params: dict) -> dict: def get_api_key(tenant_id: str, model_name: str): + # Try direct model ID (UUID) lookup first + exist, model_obj = TenantModelService.get_by_id(model_name) + if exist: + # Verify tenant ownership through the provider chain + ok, provider_obj = TenantModelProviderService.get_by_id(model_obj.provider_id) + if not ok: + raise LookupError(f"Provider id={model_obj.provider_id} not found for model {model_name}.") + if tenant_id != provider_obj.tenant_id: + joined_tenants = TenantService.get_joined_tenants_by_user_id(tenant_id) + joined_tenant_ids = [t["tenant_id"] for t in joined_tenants] + if provider_obj.tenant_id not in joined_tenant_ids: + raise LookupError(f"Tenant {tenant_id} has no access to provider owned by tenant {provider_obj.tenant_id}.") + + exist_inst, instance_obj = TenantModelInstanceService.get_by_id(model_obj.instance_id) + if not exist_inst: + logger.warning( + "Direct-ID resolution: instance not found | tenant_id=%s model_id=%s instance_id=%s", + tenant_id, + model_name, + model_obj.instance_id, + ) + raise LookupError(f"Instance {model_obj.instance_id} not found for model {model_name}.") + logger.debug( + "Direct-ID resolution: resolved | tenant_id=%s model_id=%s instance_id=%s", + tenant_id, + model_name, + model_obj.instance_id, + ) + return instance_obj.api_key + + # Fall back to name-based resolution: model[@instance]@provider _, instance_name, provider_name = split_model_name(model_name) if not provider_name: diff --git a/web/src/pages/next-chats/chat/chat-box/next-multiple-chat-box.tsx b/web/src/pages/next-chats/chat/chat-box/next-multiple-chat-box.tsx index c8a83ca7f1..0d73c8bda0 100644 --- a/web/src/pages/next-chats/chat/chat-box/next-multiple-chat-box.tsx +++ b/web/src/pages/next-chats/chat/chat-box/next-multiple-chat-box.tsx @@ -39,6 +39,7 @@ import { useCallback, useEffect, useImperativeHandle, + useLayoutEffect, useRef, useState, } from 'react'; @@ -60,7 +61,6 @@ import { useUploadFile } from '../../hooks/use-upload-file'; import { buildMessageItemReference } from '../../utils'; import { useAddChatBox } from '../use-add-box'; import { useShowInternet } from '../use-show-internet'; -import { useSetDefaultModel } from './use-set-default-model'; type MultipleChatBoxProps = { controller: AbortController; @@ -153,7 +153,9 @@ const ChatCard = forwardRef(function ChatCard( const { data: currentDialog } = useFetchChat(); const findLlmByUuid = useFindLlmByUuid(); - useSetDefaultModel(form); + useLayoutEffect(() => { + form.setValue('llm_id', currentDialog?.llm_id || ''); + }, [currentDialog?.llm_id, form]); const isLatestChat = idx === chatBoxIds.length - 1; diff --git a/web/src/pages/next-chats/chat/chat-box/use-set-default-model.ts b/web/src/pages/next-chats/chat/chat-box/use-set-default-model.ts deleted file mode 100644 index 6ea8807ae0..0000000000 --- a/web/src/pages/next-chats/chat/chat-box/use-set-default-model.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ModelTypeMap } from '@/components/model-tree-select'; -import { useFetchAllAddedModels } from '@/hooks/use-llm-request'; -import { getRealModelName } from '@/utils/llm-util'; -import { useEffect, useRef } from 'react'; -import { UseFormReturn } from 'react-hook-form'; - -export function useSetDefaultModel(form: UseFormReturn) { - const { data: allAddedModels } = useFetchAllAddedModels(); - const hasSet = useRef(false); - - useEffect(() => { - if (hasSet.current || !allAddedModels.length) return; - const chatModels = allAddedModels.filter((m) => - m.model_type?.some((t) => ModelTypeMap.llm_id.includes(t)), - ); - const first = chatModels[0]; - if (first) { - const modelName = getRealModelName(first.name); - form.setValue( - 'llm_id', - `${modelName}@${first.instance_name}@${first.provider_name}`, - ); - hasSet.current = true; - } - }, [allAddedModels, form]); -}