UNPKG

@juspay/neurolink

Version:

The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002

119 lines (118 loc) • 4.67 kB
/** * Error classes surfaced by the generation pipeline. * * These used to be re-exported from the `ai` package. They are now declared * here, because every path that threw them upstream is gone: generation is * native end to end, and the only one this repo still constructs is * NoOutputGeneratedError. * * The marker symbols are deliberately identical to the upstream ones * (`Symbol.for("vercel.ai.error.<name>")`). `isInstance` is a marker check, not * an `instanceof`, precisely so it survives across duplicate module copies — * and keeping the same symbol means an error raised by any remaining upstream * code is still recognised by these classes, and vice versa. Switching to a * private symbol would have silently broken that recognition at exactly the * points that matter: retry classification and the no-output sentinel. */ const markerSymbolFor = (name) => Symbol.for(`vercel.ai.error.${name}`); const hasMarker = (error, name) => { const marker = markerSymbolFor(name); return (error !== null && typeof error === "object" && marker in error && error[marker] === true); }; /** Base for the generation errors; stamps the upstream-compatible marker. */ class GenerationError extends Error { cause; constructor(markerName, message, cause) { super(message); this.name = markerName; if (cause !== undefined) { this.cause = cause; } Object.defineProperty(this, markerSymbolFor(markerName), { value: true, enumerable: false, writable: false, }); } } export class NoOutputGeneratedError extends GenerationError { constructor(options = {}) { super("AI_NoOutputGeneratedError", options.message ?? "No output generated.", options.cause); } static isInstance(error) { return hasMarker(error, "AI_NoOutputGeneratedError"); } } export class NoObjectGeneratedError extends GenerationError { text; finishReason; constructor(options = {}) { super("AI_NoObjectGeneratedError", options.message ?? "No object generated.", options.cause); this.text = options.text; this.finishReason = options.finishReason; } static isInstance(error) { return hasMarker(error, "AI_NoObjectGeneratedError"); } } export class NoSuchToolError extends GenerationError { toolName; constructor(options = {}) { super("AI_NoSuchToolError", options.message ?? `Model tried to call unavailable tool '${options.toolName ?? "unknown"}'.`); this.toolName = options.toolName; } static isInstance(error) { return hasMarker(error, "AI_NoSuchToolError"); } } export class InvalidToolInputError extends GenerationError { toolName; constructor(options = {}) { super("AI_InvalidToolInputError", options.message ?? `Invalid input for tool '${options.toolName ?? "unknown"}'.`, options.cause); this.toolName = options.toolName; } static isInstance(error) { return hasMarker(error, "AI_InvalidToolInputError"); } } /** * Transport-level failure. This repo only ever CATCHES and classifies these — * `providerRetry` and the error classifier duck-type `.statusCode` — so the * class exists to keep those `isInstance` checks working for errors raised by * the provider clients, which stamp the same marker. */ export class APICallError extends GenerationError { url; statusCode; responseBody; responseHeaders; isRetryable; requestBodyValues; constructor(options = {}) { super("AI_APICallError", options.message ?? "API call error.", options.cause); this.url = options.url; this.statusCode = options.statusCode; this.responseBody = options.responseBody; this.responseHeaders = options.responseHeaders; // Upstream derives this from the status code when the caller does not say, // and `providerRetry` reads it as a plain boolean — leaving it undefined // would make every classified APICallError non-retryable by accident. this.isRetryable = options.isRetryable ?? (options.statusCode !== null && options.statusCode !== undefined && (options.statusCode === 408 || options.statusCode === 409 || options.statusCode === 429 || options.statusCode >= 500)); this.requestBodyValues = options.requestBodyValues; } static isInstance(error) { return hasMarker(error, "AI_APICallError"); } }