fix(ApiService): properly handle and throw stream errors in API check (#11577)

* fix(ApiService): handle stream errors properly in checkApi

Ensure stream errors are properly caught and thrown when checking API availability

* docs(types): add type safety comment for ResponseError

Add FIXME comment highlighting weak type safety in ResponseError type
This commit is contained in:
Phantom 2025-11-30 18:34:56 +08:00 committed by GitHub
parent 2bd680361a
commit d968df4612
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 6 additions and 6 deletions

View File

@ -12,7 +12,7 @@ import type { FetchChatCompletionParams } from '@renderer/types'
import type { Assistant, MCPServer, MCPTool, Model, Provider } from '@renderer/types' import type { Assistant, MCPServer, MCPTool, Model, Provider } from '@renderer/types'
import type { StreamTextParams } from '@renderer/types/aiCoreTypes' import type { StreamTextParams } from '@renderer/types/aiCoreTypes'
import { type Chunk, ChunkType } from '@renderer/types/chunk' import { type Chunk, ChunkType } from '@renderer/types/chunk'
import type { Message } from '@renderer/types/newMessage' import type { Message, ResponseError } from '@renderer/types/newMessage'
import type { SdkModel } from '@renderer/types/sdk' import type { SdkModel } from '@renderer/types/sdk'
import { removeSpecialCharactersForTopicName, uuid } from '@renderer/utils' import { removeSpecialCharactersForTopicName, uuid } from '@renderer/utils'
import { abortCompletion, readyToAbort } from '@renderer/utils/abortController' import { abortCompletion, readyToAbort } from '@renderer/utils/abortController'
@ -476,7 +476,7 @@ export async function checkApi(provider: Provider, model: Model, timeout = 15000
} else { } else {
const abortId = uuid() const abortId = uuid()
const signal = readyToAbort(abortId) const signal = readyToAbort(abortId)
let chunkError let streamError: ResponseError | undefined
const params: StreamTextParams = { const params: StreamTextParams = {
system: assistant.prompt, system: assistant.prompt,
prompt: 'hi', prompt: 'hi',
@ -495,19 +495,18 @@ export async function checkApi(provider: Provider, model: Model, timeout = 15000
callType: 'check', callType: 'check',
onChunk: (chunk: Chunk) => { onChunk: (chunk: Chunk) => {
if (chunk.type === ChunkType.ERROR) { if (chunk.type === ChunkType.ERROR) {
chunkError = chunk.error streamError = chunk.error
} else { } else {
abortCompletion(abortId) abortCompletion(abortId)
} }
} }
} }
// Try streaming check
try { try {
await ai.completions(model.id, params, config) await ai.completions(model.id, params, config)
} catch (e) { } catch (e) {
if (!isAbortError(e) && !isAbortError(chunkError)) { if (!isAbortError(e) && !isAbortError(streamError)) {
throw e throw streamError ?? e
} }
} }
} }

View File

@ -234,6 +234,7 @@ export interface Response {
error?: ResponseError error?: ResponseError
} }
// FIXME: Weak type safety. It may be a specific class instance which inherits Error in runtime.
export type ResponseError = Record<string, any> export type ResponseError = Record<string, any>
export interface MessageInputBaseParams { export interface MessageInputBaseParams {