mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-21 16:01:35 +08:00
fix: make anthropic model provided by cherryin visible to agent (#10695)
This commit is contained in:
parent
004d6d8201
commit
7b3b73d390
@ -1,3 +1,5 @@
|
|||||||
|
import { isEmpty } from 'lodash'
|
||||||
|
|
||||||
import { ApiModel, ApiModelsFilter, ApiModelsResponse } from '../../../renderer/src/types/apiModels'
|
import { ApiModel, ApiModelsFilter, ApiModelsResponse } from '../../../renderer/src/types/apiModels'
|
||||||
import { loggerService } from '../../services/LoggerService'
|
import { loggerService } from '../../services/LoggerService'
|
||||||
import { getAvailableProviders, listAllAvailableModels, transformModelToOpenAI } from '../utils'
|
import { getAvailableProviders, listAllAvailableModels, transformModelToOpenAI } from '../utils'
|
||||||
@ -8,6 +10,10 @@ const logger = loggerService.withContext('ModelsService')
|
|||||||
|
|
||||||
export type ModelsFilter = ApiModelsFilter
|
export type ModelsFilter = ApiModelsFilter
|
||||||
|
|
||||||
|
const isAnthropicProvider = (provider: { type: string; anthropicApiHost?: string }) => {
|
||||||
|
return provider.type === 'anthropic' || !isEmpty(provider.anthropicApiHost?.trim())
|
||||||
|
}
|
||||||
|
|
||||||
export class ModelsService {
|
export class ModelsService {
|
||||||
async getModels(filter: ModelsFilter): Promise<ApiModelsResponse> {
|
async getModels(filter: ModelsFilter): Promise<ApiModelsResponse> {
|
||||||
try {
|
try {
|
||||||
@ -16,9 +22,7 @@ export class ModelsService {
|
|||||||
let providers = await getAvailableProviders()
|
let providers = await getAvailableProviders()
|
||||||
|
|
||||||
if (filter.providerType === 'anthropic') {
|
if (filter.providerType === 'anthropic') {
|
||||||
providers = providers.filter(
|
providers = providers.filter(isAnthropicProvider)
|
||||||
(p) => p.type === 'anthropic' || (p.anthropicApiHost !== undefined && p.anthropicApiHost.trim() !== '')
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const models = await listAllAvailableModels(providers)
|
const models = await listAllAvailableModels(providers)
|
||||||
@ -41,6 +45,10 @@ export class ModelsService {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter.supportAnthropic && model.endpoint_type !== 'anthropic' && !isAnthropicProvider(provider)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
const openAIModel = transformModelToOpenAI(model, provider)
|
const openAIModel = transformModelToOpenAI(model, provider)
|
||||||
const fullModelId = openAIModel.id // This is already in format "provider:model_id"
|
const fullModelId = openAIModel.id // This is already in format "provider:model_id"
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { CacheService } from '@main/services/CacheService'
|
import { CacheService } from '@main/services/CacheService'
|
||||||
import { loggerService } from '@main/services/LoggerService'
|
import { loggerService } from '@main/services/LoggerService'
|
||||||
import { reduxService } from '@main/services/ReduxService'
|
import { reduxService } from '@main/services/ReduxService'
|
||||||
import { ApiModel, Model, Provider } from '@types'
|
import { ApiModel, EndpointType, Model, Provider } from '@types'
|
||||||
|
|
||||||
const logger = loggerService.withContext('ApiServerUtils')
|
const logger = loggerService.withContext('ApiServerUtils')
|
||||||
|
|
||||||
@ -114,6 +114,7 @@ export async function validateModelId(model: string): Promise<{
|
|||||||
error?: ModelValidationError
|
error?: ModelValidationError
|
||||||
provider?: Provider
|
provider?: Provider
|
||||||
modelId?: string
|
modelId?: string
|
||||||
|
modelEndpointType?: EndpointType
|
||||||
}> {
|
}> {
|
||||||
try {
|
try {
|
||||||
if (!model || typeof model !== 'string') {
|
if (!model || typeof model !== 'string') {
|
||||||
@ -166,7 +167,8 @@ export async function validateModelId(model: string): Promise<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if model exists in provider
|
// Check if model exists in provider
|
||||||
const modelExists = provider.models?.some((m) => m.id === modelId)
|
const modelInProvider = provider.models?.find((m) => m.id === modelId)
|
||||||
|
const modelExists = !!modelInProvider
|
||||||
if (!modelExists) {
|
if (!modelExists) {
|
||||||
const availableModels = provider.models?.map((m) => m.id).join(', ') || 'none'
|
const availableModels = provider.models?.map((m) => m.id).join(', ') || 'none'
|
||||||
return {
|
return {
|
||||||
@ -179,10 +181,13 @@ export async function validateModelId(model: string): Promise<{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const modelEndpointType = modelInProvider?.endpoint_type
|
||||||
|
|
||||||
return {
|
return {
|
||||||
valid: true,
|
valid: true,
|
||||||
provider,
|
provider,
|
||||||
modelId
|
modelId,
|
||||||
|
modelEndpointType
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
logger.error('Error validating model ID', { error, model })
|
logger.error('Error validating model ID', { error, model })
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { config as apiConfigService } from '@main/apiServer/config'
|
|||||||
import { validateModelId } from '@main/apiServer/utils'
|
import { validateModelId } from '@main/apiServer/utils'
|
||||||
import getLoginShellEnvironment from '@main/utils/shell-env'
|
import getLoginShellEnvironment from '@main/utils/shell-env'
|
||||||
import { app } from 'electron'
|
import { app } from 'electron'
|
||||||
|
import { isEmpty } from 'lodash'
|
||||||
|
|
||||||
import { GetAgentSessionResponse } from '../..'
|
import { GetAgentSessionResponse } from '../..'
|
||||||
import { AgentServiceInterface, AgentStream, AgentStreamEvent } from '../../interfaces/AgentStreamInterface'
|
import { AgentServiceInterface, AgentStream, AgentStreamEvent } from '../../interfaces/AgentStreamInterface'
|
||||||
@ -60,11 +61,20 @@ class ClaudeCodeService implements AgentServiceInterface {
|
|||||||
})
|
})
|
||||||
return aiStream
|
return aiStream
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
(modelInfo.provider?.type !== 'anthropic' &&
|
const validateModelInfo: (m: typeof modelInfo) => boolean = (m) => {
|
||||||
(modelInfo.provider?.anthropicApiHost === undefined || modelInfo.provider.anthropicApiHost.trim() === '')) ||
|
const { provider, modelEndpointType } = m
|
||||||
modelInfo.provider.apiKey === ''
|
if (!provider) return false
|
||||||
) {
|
if (isEmpty(provider.apiKey?.trim())) return false
|
||||||
|
|
||||||
|
const isAnthropicType = provider.type === 'anthropic'
|
||||||
|
const isAnthropicEndpoint = modelEndpointType === 'anthropic'
|
||||||
|
const hasValidApiHost = !isEmpty(provider.anthropicApiHost?.trim())
|
||||||
|
|
||||||
|
return !(!isAnthropicType && !isAnthropicEndpoint && !hasValidApiHost)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!modelInfo.provider || !validateModelInfo(modelInfo)) {
|
||||||
logger.error('Anthropic provider configuration is missing', {
|
logger.error('Anthropic provider configuration is missing', {
|
||||||
modelInfo
|
modelInfo
|
||||||
})
|
})
|
||||||
|
|||||||
@ -100,7 +100,7 @@ export const AgentModal: React.FC<Props> = ({ agent, trigger, isOpen: _isOpen, o
|
|||||||
const { addAgent } = useAgents()
|
const { addAgent } = useAgents()
|
||||||
const { updateAgent } = useUpdateAgent()
|
const { updateAgent } = useUpdateAgent()
|
||||||
// hard-coded. We only support anthropic for now.
|
// hard-coded. We only support anthropic for now.
|
||||||
const { models } = useApiModels({ providerType: 'anthropic' })
|
const { models } = useApiModels({ supportAnthropic: true })
|
||||||
const isEditing = (agent?: AgentWithTools) => agent !== undefined
|
const isEditing = (agent?: AgentWithTools) => agent !== undefined
|
||||||
|
|
||||||
const [form, setForm] = useState<BaseAgentForm>(() => buildAgentForm(agent))
|
const [form, setForm] = useState<BaseAgentForm>(() => buildAgentForm(agent))
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { ProviderTypeSchema } from './provider'
|
|||||||
// Request schema for /v1/models
|
// Request schema for /v1/models
|
||||||
export const ApiModelsFilterSchema = z.object({
|
export const ApiModelsFilterSchema = z.object({
|
||||||
providerType: ProviderTypeSchema.optional(),
|
providerType: ProviderTypeSchema.optional(),
|
||||||
|
supportAnthropic: z.coerce.boolean().optional(),
|
||||||
offset: z.coerce.number().min(0).default(0).optional(),
|
offset: z.coerce.number().min(0).default(0).optional(),
|
||||||
limit: z.coerce.number().min(1).default(20).optional()
|
limit: z.coerce.number().min(1).default(20).optional()
|
||||||
})
|
})
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export const getModelFilterByAgentType = (type: AgentType): ApiModelsFilter => {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case 'claude-code':
|
case 'claude-code':
|
||||||
return {
|
return {
|
||||||
providerType: 'anthropic'
|
supportAnthropic: true
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return {}
|
return {}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user