Skip to content

Commit 90605e0

Browse files
authored
feat(new-api): add endpoint debug selection (#1836)
* feat(new-api): add endpoint debug selection * fix(new-api): harden endpoint debug selection
1 parent 44810b1 commit 90605e0

8 files changed

Lines changed: 1120 additions & 202 deletions

File tree

src/main/presenter/configPresenter/providerModelHelper.ts

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import logger from '@shared/logger'
22
import { ModelConfig, MODEL_META } from '@shared/presenter'
3-
import { ModelType, resolveNewApiSelectableEndpointTypes } from '@shared/model'
3+
import {
4+
isNewApiEndpointType,
5+
ModelType,
6+
resolveNewApiModelTypeFromMetadata,
7+
resolveNewApiSelectableEndpointTypes
8+
} from '@shared/model'
49
import { resolveVideoGenerationCompatType } from '@shared/videoGenerationSettings'
510
import ElectronStore from 'electron-store'
611
import path from 'path'
@@ -30,6 +35,16 @@ interface ProviderModelHelperOptions {
3035

3136
type ProviderModelStore = StoreLike<IModelStore & Record<string, unknown>>
3237

38+
const MODEL_TYPE_VALUES = new Set<string>(Object.values(ModelType))
39+
40+
function isModelType(value: unknown): value is ModelType {
41+
return typeof value === 'string' && MODEL_TYPE_VALUES.has(value)
42+
}
43+
44+
function isNonChatModelType(type: ModelType | undefined): type is ModelType {
45+
return type !== undefined && type !== ModelType.Chat
46+
}
47+
3348
export class ProviderModelHelper {
3449
private readonly userDataPath: string
3550
private readonly getModelConfig: ModelConfigResolver
@@ -127,6 +142,38 @@ export class ProviderModelHelper {
127142
return normalizedModel
128143
}
129144

145+
private resolveNewApiEffectiveModelType(model: MODEL_META, config?: ModelConfig): ModelType {
146+
const userConfigType =
147+
config?.isUserDefined === true && isModelType(config.type) ? config.type : undefined
148+
if (userConfigType) {
149+
return userConfigType
150+
}
151+
152+
if (isModelType(model.type)) {
153+
return model.type
154+
}
155+
156+
const supportedEndpointTypes = (model.supportedEndpointTypes ?? []).filter(isNewApiEndpointType)
157+
const routeEndpointTypes =
158+
supportedEndpointTypes.length > 0
159+
? supportedEndpointTypes
160+
: isNewApiEndpointType(model.endpointType)
161+
? [model.endpointType]
162+
: []
163+
const metadataType = resolveNewApiModelTypeFromMetadata(routeEndpointTypes, model.id, undefined)
164+
if (metadataType) {
165+
return metadataType
166+
}
167+
168+
const providerConfigType =
169+
config?.isUserDefined !== true && isModelType(config?.type) ? config.type : undefined
170+
if (isNonChatModelType(providerConfigType)) {
171+
return providerConfigType
172+
}
173+
174+
return ModelType.Chat
175+
}
176+
130177
private applyResolvedModelConfig(model: MODEL_META, providerId: string): MODEL_META {
131178
const normalizedModel = this.cloneModel(model)
132179
const config = this.getModelConfig(normalizedModel.id, providerId)
@@ -146,6 +193,11 @@ export class ProviderModelHelper {
146193
: config.reasoning || false
147194
normalizedModel.endpointType = config.endpointType ?? normalizedModel.endpointType
148195
normalizedModel.ownedBy = normalizedModel.ownedBy ?? config.ownedBy
196+
if (providerId === 'new-api') {
197+
normalizedModel.type = this.resolveNewApiEffectiveModelType(normalizedModel, config)
198+
return normalizedModel
199+
}
200+
149201
normalizedModel.type =
150202
resolveVideoGenerationCompatType({
151203
modelId: normalizedModel.id,
@@ -161,6 +213,11 @@ export class ProviderModelHelper {
161213
normalizedModel.vision = normalizedModel.vision || false
162214
normalizedModel.functionCall = normalizedModel.functionCall || false
163215
normalizedModel.reasoning = normalizedModel.reasoning || false
216+
if (providerId === 'new-api') {
217+
normalizedModel.type = this.resolveNewApiEffectiveModelType(normalizedModel)
218+
return normalizedModel
219+
}
220+
164221
normalizedModel.type =
165222
resolveVideoGenerationCompatType({
166223
modelId: normalizedModel.id,
@@ -173,16 +230,15 @@ export class ProviderModelHelper {
173230
}
174231

175232
private applyNewApiEndpointCompatibility(model: MODEL_META, providerId: string): MODEL_META {
176-
if (providerId !== 'new-api' || model.selectableEndpointTypes?.length) {
233+
if (providerId !== 'new-api') {
177234
return model
178235
}
179236

180237
const selectableEndpointTypes = resolveNewApiSelectableEndpointTypes(
181238
model.supportedEndpointTypes,
182239
model.id,
183240
{
184-
type: model.type,
185-
ownedBy: model.ownedBy
241+
type: model.type
186242
}
187243
)
188244
return selectableEndpointTypes ? { ...model, selectableEndpointTypes } : model
@@ -217,8 +273,8 @@ export class ProviderModelHelper {
217273
}
218274

219275
const result = normalizedStoredModels.map((model) =>
220-
this.applyResolvedModelConfig(
221-
this.applyNewApiEndpointCompatibility(model, providerId),
276+
this.applyNewApiEndpointCompatibility(
277+
this.applyResolvedModelConfig(model, providerId),
222278
providerId
223279
)
224280
)

src/main/presenter/llmProviderPresenter/providers/aiSdkProvider.ts

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
isDeepSeekSeriesModelId,
77
isGeminiFamilyModelId,
88
isNewApiEndpointType,
9+
resolveNewApiModelTypeFromMetadata,
910
resolveNewApiSelectableEndpointTypes,
1011
resolveNewApiEndpointTypeFromRoute,
1112
resolveProviderCapabilityProviderId,
@@ -1905,37 +1906,18 @@ export class AiSdkProvider extends BaseLLMProvider {
19051906

19061907
const normalizedRawType =
19071908
typeof rawModel.type === 'string' ? rawModel.type.trim().toLowerCase() : ''
1908-
const normalizedModelId = rawModel.id.toLowerCase()
1909-
const type =
1910-
normalizedRawType === 'imagegeneration' ||
1911-
normalizedRawType === 'image-generation' ||
1912-
normalizedRawType === 'image' ||
1913-
rawSupportedEndpointTypes.includes('image-generation')
1914-
? ModelType.ImageGeneration
1915-
: normalizedRawType === 'videogeneration' ||
1916-
normalizedRawType === 'video-generation' ||
1917-
normalizedRawType === 'video' ||
1918-
rawSupportedEndpointTypes.includes('video-generation')
1919-
? ModelType.VideoGeneration
1920-
: normalizedRawType === 'tts' ||
1921-
normalizedRawType === 'audio-speech' ||
1922-
normalizedRawType === 'audiospeech'
1923-
? ModelType.TTS
1924-
: normalizedRawType === 'embedding' ||
1925-
normalizedRawType === 'embeddings' ||
1926-
normalizedModelId.includes('embedding')
1927-
? ModelType.Embedding
1928-
: normalizedRawType === 'rerank' || normalizedModelId.includes('rerank')
1929-
? ModelType.Rerank
1930-
: undefined
1909+
const type = resolveNewApiModelTypeFromMetadata(
1910+
rawSupportedEndpointTypes,
1911+
rawModel.id,
1912+
normalizedRawType
1913+
)
19311914
const supportedEndpointTypes = rawSupportedEndpointTypes
19321915
const selectableEndpointTypes = resolveNewApiSelectableEndpointTypes(
19331916
rawSupportedEndpointTypes,
19341917
rawModel.id,
19351918
{
19361919
type,
1937-
rawType: normalizedRawType,
1938-
ownedBy
1920+
rawType: normalizedRawType
19391921
}
19401922
)
19411923

0 commit comments

Comments
 (0)