mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-13 18:32:12 +03:00
fix(resilience): surface Responses failed.error.message in 502s (#12472)
Validado em lote numa worktree combinada com os 10 PRs desta leva sobre o tip de `release/v3.8.51`: `typecheck:core` limpo, `check-file-size` OK e **241/242** nos 29 arquivos de teste que os PRs tocam. A única "falha" não é falha: `tests/unit/autoCombo/strict-zero-cost-filter.test.ts` é um teste em estilo Vitest que eu incluí por engano na invocação do runner nativo do Node — ele quebra no import (`@vitest/runner`), não numa asserção. Ao investigar, descobri que esse arquivo não roda em nenhum dos dois runners hoje (o glob do `test:unit` não lista `autoCombo` e o `include` do Vitest só pega `.tsx` nessa pasta); é um problema pré-existente do repositório, sem relação com esta leva, e vou registrá-lo separadamente. O #12636 conflitava apenas na lista de testes do `@omniroute/opencode-plugin/package.json`, de forma aditiva: o tip já tinha `models-fetcher.test.ts` (do #12607, irmão desta mesma leva) e o #12636 acrescenta `telemetry.test.ts`. Fiz a união dos dois lados (25 arquivos contra 24 de cada) em vez de escolher um, o que teria removido um arquivo da suíte do plugin em silêncio. Obrigado, @RaviTharuma.
This commit is contained in:
@@ -323,8 +323,14 @@ export function describeMalformedNonStream(
|
||||
): { message: string; code: string; type: string } {
|
||||
const body = resp && typeof resp === "object" ? (resp as Record<string, unknown>) : null;
|
||||
if (body?.object === "response" && body.status === "failed") {
|
||||
const err = body.error && typeof body.error === "object" ? (body.error as Record<string, unknown>) : null;
|
||||
const rawMessage =
|
||||
typeof err?.message === "string" && err.message.trim().length > 0 ? err.message.trim() : null;
|
||||
return {
|
||||
message: "upstream reported a failed response without usable output",
|
||||
// Trim only here; buildErrorBody (chatCore) does the single sanitization pass.
|
||||
message: rawMessage
|
||||
? `upstream reported a failed response: ${rawMessage}`
|
||||
: "upstream reported a failed response without usable output",
|
||||
code: "upstream_response_failed",
|
||||
type: "upstream_response_error",
|
||||
};
|
||||
|
||||
@@ -105,6 +105,22 @@ test("failed Responses API body gets a request-scoped machine-readable classific
|
||||
});
|
||||
});
|
||||
|
||||
test("failed Responses API body surfaces the upstream error message when present", () => {
|
||||
const failed = {
|
||||
object: "response",
|
||||
status: "failed",
|
||||
output: [],
|
||||
error: { code: "server_error", message: " Gemini 503: overloaded " },
|
||||
};
|
||||
const reason = detectMalformedNonStream(failed);
|
||||
assert.equal(reason, "empty_choices");
|
||||
assert.deepEqual(describeMalformedNonStream(failed, reason), {
|
||||
message: "upstream reported a failed response: Gemini 503: overloaded",
|
||||
code: "upstream_response_failed",
|
||||
type: "upstream_response_error",
|
||||
});
|
||||
});
|
||||
|
||||
test("detectMalformedNonStream returns 'empty_choices' when choice message has no content", () => {
|
||||
const body = {
|
||||
choices: [{ message: { content: "", tool_calls: null }, finish_reason: "stop" }],
|
||||
|
||||
Reference in New Issue
Block a user