mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-17 04:12:17 +03:00
Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
59 lines
2.8 KiB
TypeScript
59 lines
2.8 KiB
TypeScript
/**
|
|
* Build a sanitized OpenAI-style error body for a non-ok Antigravity/agy upstream
|
|
* response (#3229).
|
|
*
|
|
* The non-streaming executor path previously fed 4xx/5xx responses into the SSE
|
|
* collector, which produced a synthetic `{"object":"chat.completion","content":""}`
|
|
* success envelope — masking the real error. Route non-ok responses through
|
|
* `buildErrorBody` instead so the client sees a proper error (hard rule #12).
|
|
*/
|
|
import { buildErrorBody } from "../utils/error.ts";
|
|
import { isGeoBlockedError } from "../services/errorClassifier.ts";
|
|
|
|
// The dashboard "Test Connection" for antigravity only probes the OAuth userinfo
|
|
// endpoint (https://www.googleapis.com/oauth2/v1/userinfo), which is NOT
|
|
// geo-restricted — so a green tick does not prove the model path works. Spell
|
|
// this out in the geo-block message so operators stop chasing accounts.
|
|
const GEO_BLOCKED_HINT =
|
|
"The Cloud Code API is not offered from this server's current egress location " +
|
|
'("User location is not supported for the API use."). This is not an account ' +
|
|
"problem: the connection test only validates the Google OAuth token and does not " +
|
|
"call the model API. Route antigravity/agy egress through a proxy in a " +
|
|
"supported region (e.g. US/EU) or use a different provider.";
|
|
|
|
/**
|
|
* Extract the real upstream error message (e.g. Google's Gemini-dialect field-path
|
|
* rejection) from a parsed Antigravity `upstream_details`-shaped body, so callers can
|
|
* surface it directly in `error.message` instead of only nesting it under
|
|
* `upstream_details` — the generic `parseUpstreamError()` re-parser used by the shared
|
|
* chatCore failure path only reads the outer `error.message` (#13591).
|
|
*/
|
|
function extractUpstreamMessage(details: unknown): string | null {
|
|
if (!details || typeof details !== "object") return null;
|
|
const err = (details as { error?: { message?: unknown } }).error;
|
|
const msg = err && typeof err.message === "string" ? err.message : null;
|
|
return msg && msg.trim() ? msg.trim() : null;
|
|
}
|
|
|
|
export function buildAntigravityUpstreamError(status: number, statusText: string, rawBody: string) {
|
|
let upstreamDetails: unknown;
|
|
try {
|
|
upstreamDetails = JSON.parse(rawBody);
|
|
} catch {
|
|
// upstream body is not JSON (e.g. HTML error page) — omit structured details
|
|
}
|
|
const suffix = statusText ? `: ${statusText}` : "";
|
|
if (isGeoBlockedError(rawBody)) {
|
|
return buildErrorBody(
|
|
status,
|
|
`Antigravity upstream error (${status})${suffix}. ${GEO_BLOCKED_HINT}`,
|
|
upstreamDetails
|
|
);
|
|
}
|
|
const upstreamMessage = extractUpstreamMessage(upstreamDetails);
|
|
const message = upstreamMessage
|
|
? `Antigravity upstream error (${status}): ${upstreamMessage}`
|
|
: `Antigravity upstream error (${status})${suffix}`;
|
|
return buildErrorBody(status, message, upstreamDetails);
|
|
}
|