package com.ankurm.gateway; import java.io.IOException; import com.anthropic.errors.AnthropicIoException; import com.anthropic.errors.AnthropicServiceException; import com.openai.errors.OpenAIIoException; import com.openai.errors.OpenAIServiceException; /** * Decides whether a failed model call is worth sending to another provider. Same idea as the * {@code providers} module: the vendor SDKs throw unrelated exception families, so walk the cause * chain for an HTTP status. */ public final class Failures { private Failures() { } public static int status(Throwable t) { for (Throwable c = t; c != null; c = c.getCause()) { if (c instanceof ProviderFailure e) { return e.status(); } if (c instanceof OpenAIServiceException e) { return e.statusCode(); } if (c instanceof AnthropicServiceException e) { return e.statusCode(); } } return -1; } /** True for overload, rate limit, 5xx and network failures. A 400 or 401 is the caller's problem. */ public static boolean isTransient(Throwable t) { int status = status(t); if (status != -1) { return status == 408 || status == 429 || status >= 500; } for (Throwable c = t; c != null; c = c.getCause()) { if (c instanceof OpenAIIoException || c instanceof AnthropicIoException || c instanceof IOException) { return true; } } return false; } }