feat: unify InvokeError; add rawResponse to historical ErrorEvent

This commit is contained in:
Simon
2026-01-20 20:16:34 +08:00
parent 1f8953c450
commit 22516dec74
5 changed files with 34 additions and 13 deletions

View File

@@ -107,14 +107,23 @@ export class OpenAIClient implements LLMClient {
case 'length':
throw new InvokeError(
InvokeErrorType.CONTEXT_LENGTH,
'Response truncated: max tokens reached'
'Response truncated: max tokens reached',
undefined,
data
)
case 'content_filter':
throw new InvokeError(InvokeErrorType.CONTENT_FILTER, 'Content filtered by safety system')
throw new InvokeError(
InvokeErrorType.CONTENT_FILTER,
'Content filtered by safety system',
undefined,
data
)
default:
throw new InvokeError(
InvokeErrorType.UNKNOWN,
`Unexpected finish_reason: ${choice.finish_reason}`
`Unexpected finish_reason: ${choice.finish_reason}`,
undefined,
data
)
}
@@ -128,7 +137,8 @@ export class OpenAIClient implements LLMClient {
throw new InvokeError(
InvokeErrorType.NO_TOOL_CALL,
'No tool call found in response',
normalizedData
undefined,
data
)
}
@@ -137,7 +147,8 @@ export class OpenAIClient implements LLMClient {
throw new InvokeError(
InvokeErrorType.UNKNOWN,
`Tool "${toolCallName}" not found in tools`,
normalizedData
undefined,
data
)
}
@@ -147,7 +158,8 @@ export class OpenAIClient implements LLMClient {
throw new InvokeError(
InvokeErrorType.INVALID_TOOL_ARGS,
'No tool call arguments found',
normalizedData
undefined,
data
)
}
@@ -158,7 +170,8 @@ export class OpenAIClient implements LLMClient {
throw new InvokeError(
InvokeErrorType.INVALID_TOOL_ARGS,
'Failed to parse tool arguments as JSON',
error
error,
data
)
}
@@ -169,7 +182,8 @@ export class OpenAIClient implements LLMClient {
throw new InvokeError(
InvokeErrorType.INVALID_TOOL_ARGS,
'Tool arguments validation failed',
validation.error
validation.error,
data
)
}
const toolInput = validation.data
@@ -182,7 +196,8 @@ export class OpenAIClient implements LLMClient {
throw new InvokeError(
InvokeErrorType.TOOL_EXECUTION_ERROR,
`Tool execution failed: ${(e as Error).message}`,
e
e,
data
)
}

View File

@@ -25,14 +25,18 @@ export class InvokeError extends Error {
type: InvokeErrorType
retryable: boolean
statusCode?: number
/* raw error (provided if this error is caused by another error) */
rawError?: unknown
/* raw response from the API (provided if this error is caused by an API calling) */
rawResponse?: unknown
constructor(type: InvokeErrorType, message: string, rawError?: unknown) {
constructor(type: InvokeErrorType, message: string, rawError?: unknown, rawResponse?: unknown) {
super(message)
this.name = 'InvokeError'
this.type = type
this.retryable = this.isRetryable(type)
this.rawError = rawError
this.rawResponse = rawResponse
}
private isRetryable(type: InvokeErrorType): boolean {

View File

@@ -3,7 +3,7 @@ import { DEFAULT_TEMPERATURE, LLM_MAX_RETRIES } from './constants'
import { InvokeError } from './errors'
import type { InvokeOptions, InvokeResult, LLMClient, LLMConfig, Message, Tool } from './types'
export type { InvokeOptions, InvokeResult, LLMClient, LLMConfig, Message, Tool }
export type { InvokeError, InvokeOptions, InvokeResult, LLMClient, LLMConfig, Message, Tool }
export function parseLLMConfig(config: LLMConfig): Required<LLMConfig> {
// Runtime validation as defensive programming (types already guarantee these)