graphlit-client
Version:
Graphlit API Client for TypeScript
82 lines (81 loc) • 2.81 kB
JavaScript
/**
* Internal types used by the streaming implementation
* These are not exported to consumers of the library
*/
/**
* Normalized error from an LLM provider. Carries structured metadata
* so the retry layer can make decisions without parsing error messages.
*/
export class ProviderError extends Error {
provider;
statusCode;
retryable;
requestId;
constructor(message, opts) {
super(message, { cause: opts.cause });
this.name = "ProviderError";
this.provider = opts.provider;
this.statusCode = opts.statusCode;
this.retryable = opts.retryable;
this.requestId = opts.requestId;
}
}
/**
* Detect common retryable server errors across providers.
* Used as a catch-all after provider-specific error classification.
*/
export function isRetryableServerError(error) {
const status = error.status ?? error.statusCode;
if (typeof status === "number" && status >= 500)
return true;
const msg = (error.message || "").toLowerCase();
const type = (error.type || "").toLowerCase();
if (type === "api_error" || type === "server_error")
return true;
return (msg.includes("internal server error") ||
msg.includes("service unavailable") ||
msg.includes("bad gateway") ||
msg.includes("gateway timeout"));
}
/**
* Detect rate-limit / overloaded errors across providers.
*/
export function isRateLimitError(error) {
const status = error.status ?? error.statusCode;
if (status === 429)
return true;
const type = (error.type || "").toLowerCase();
if (type === "rate_limit_error" || type === "overloaded_error")
return true;
if (error.code === "rate_limit_exceeded")
return true;
const msg = (error.message || "").toLowerCase();
return msg.includes("rate limit") || msg.includes("overloaded");
}
/**
* Detect transient network errors.
*
* Node's undici (built-in fetch) wraps TCP resets as:
* TypeError: terminated
* [cause]: Error: read ECONNRESET { code: 'ECONNRESET' }
*
* The ECONNRESET code lives on the nested `cause`, not the top-level error,
* so we check both levels.
*/
export function isNetworkError(error) {
const msg = error.message || "";
const code = error.code || "";
const causeCode = error.cause?.code || "";
return (msg.includes("fetch failed") ||
msg === "terminated" ||
code === "ECONNRESET" ||
code === "ETIMEDOUT" ||
code === "ECONNREFUSED" ||
causeCode === "ECONNRESET" ||
causeCode === "ETIMEDOUT" ||
causeCode === "ECONNREFUSED");
}
/** Extract a request ID from a provider error, if present. */
export function extractRequestId(error) {
return error.request_id ?? error.requestId ?? error.headers?.["x-request-id"];
}