diff --git a/packages/agent-core/src/errors/serialize.ts b/packages/agent-core/src/errors/serialize.ts index bbad58db1..1876f52a3 100644 --- a/packages/agent-core/src/errors/serialize.ts +++ b/packages/agent-core/src/errors/serialize.ts @@ -57,7 +57,7 @@ export function makeErrorPayload( * * Recognized errors: * - `KimiError`: passthrough. - * - `APIStatusError`: 429 -> rate_limit, 401 -> auth_error, otherwise -> api_error. + * - `APIStatusError`: 429 -> rate_limit, 401/403 -> auth_error, otherwise -> api_error. * - `APIConnectionError` / `APITimeoutError`: connection_error. * - `ChatProviderError`: api_error. * @@ -79,7 +79,7 @@ export function toKimiErrorPayload(error: unknown): KimiErrorPayload { const code: KimiErrorCode = error.statusCode === 429 ? ErrorCodes.PROVIDER_RATE_LIMIT - : error.statusCode === 401 + : error.statusCode === 401 || error.statusCode === 403 ? ErrorCodes.PROVIDER_AUTH_ERROR : ErrorCodes.PROVIDER_API_ERROR; return { diff --git a/packages/agent-core/test/errors/serialize.test.ts b/packages/agent-core/test/errors/serialize.test.ts new file mode 100644 index 000000000..9bd125b9b --- /dev/null +++ b/packages/agent-core/test/errors/serialize.test.ts @@ -0,0 +1,23 @@ +import { APIStatusError } from '@moonshot-ai/kosong'; +import { describe, expect, it } from 'vitest'; + +import { ErrorCodes, toKimiErrorPayload } from '../../src/errors'; + +describe('toKimiErrorPayload', () => { + it('classifies provider 403 responses as auth errors', () => { + const payload = toKimiErrorPayload( + new APIStatusError(403, 'access_terminated: Access was terminated', 'req-403'), + ); + + expect(payload).toMatchObject({ + code: ErrorCodes.PROVIDER_AUTH_ERROR, + message: 'access_terminated: Access was terminated', + name: 'APIStatusError', + details: { + statusCode: 403, + requestId: 'req-403', + }, + retryable: false, + }); + }); +});