@jaypie/llm 1.2.27 → 1.2.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,14 @@
1
+ import { ClassifiedError } from "../types.js";
1
2
  import { OpenAiAdapter } from "./OpenAiAdapter.js";
2
3
  /**
3
4
  * XaiAdapter extends OpenAiAdapter since xAI (Grok) uses an OpenAI-compatible API.
4
- * Only the name and default model are overridden; all request building, response parsing,
5
- * error classification, tool handling, and streaming are inherited.
5
+ * Name, default model, and transient-ingest-error detection are overridden;
6
+ * all request building, response parsing, tool handling, and streaming are
7
+ * inherited.
6
8
  */
7
9
  export declare class XaiAdapter extends OpenAiAdapter {
8
10
  readonly name: "xai";
9
11
  readonly defaultModel: "grok-4.20-0309-reasoning";
12
+ classifyError(error: unknown): ClassifiedError;
10
13
  }
11
14
  export declare const xaiAdapter: XaiAdapter;
package/dist/esm/index.js CHANGED
@@ -1760,8 +1760,6 @@ class GeminiAdapter extends BaseProviderAdapter {
1760
1760
  contents: geminiRequest.contents,
1761
1761
  config: geminiRequest.config,
1762
1762
  });
1763
- // Track current function call being built
1764
- let currentFunctionCall = null;
1765
1763
  // Track usage for final chunk
1766
1764
  let inputTokens = 0;
1767
1765
  let outputTokens = 0;
@@ -1782,7 +1780,7 @@ class GeminiAdapter extends BaseProviderAdapter {
1782
1780
  // Handle function calls
1783
1781
  if (part.functionCall) {
1784
1782
  const functionCall = part.functionCall;
1785
- currentFunctionCall = {
1783
+ const currentFunctionCall = {
1786
1784
  id: functionCall.id || this.generateCallId(),
1787
1785
  name: functionCall.name || "",
1788
1786
  arguments: functionCall.args || {},
@@ -1802,7 +1800,6 @@ class GeminiAdapter extends BaseProviderAdapter {
1802
1800
  metadata,
1803
1801
  },
1804
1802
  };
1805
- currentFunctionCall = null;
1806
1803
  }
1807
1804
  }
1808
1805
  }
@@ -3341,10 +3338,29 @@ class OpenRouterAdapter extends BaseProviderAdapter {
3341
3338
  // Export singleton instance
3342
3339
  const openRouterAdapter = new OpenRouterAdapter();
3343
3340
 
3341
+ /**
3342
+ * Error-message substrings that indicate a transient xAI media-ingest flake.
3343
+ * The xAI ingest service enters a bad state after ~12 consecutive file-bearing
3344
+ * calls and rejects subsequent requests with HTTP 400. The condition is
3345
+ * self-clearing, so these errors should be retried with backoff rather than
3346
+ * surfaced as unrecoverable.
3347
+ *
3348
+ * See: github.com/finlaysonstudio/jaypie issue #301
3349
+ */
3350
+ const TRANSIENT_INGEST_MESSAGE_PATTERNS = [
3351
+ "failed to ingest inline file bytes",
3352
+ ];
3353
+ function isTransientIngestError(error) {
3354
+ if (!(error instanceof BadRequestError))
3355
+ return false;
3356
+ const message = (error.message ?? "").toLowerCase();
3357
+ return TRANSIENT_INGEST_MESSAGE_PATTERNS.some((pattern) => message.includes(pattern));
3358
+ }
3344
3359
  /**
3345
3360
  * XaiAdapter extends OpenAiAdapter since xAI (Grok) uses an OpenAI-compatible API.
3346
- * Only the name and default model are overridden; all request building, response parsing,
3347
- * error classification, tool handling, and streaming are inherited.
3361
+ * Name, default model, and transient-ingest-error detection are overridden;
3362
+ * all request building, response parsing, tool handling, and streaming are
3363
+ * inherited.
3348
3364
  */
3349
3365
  class XaiAdapter extends OpenAiAdapter {
3350
3366
  constructor() {
@@ -3354,6 +3370,16 @@ class XaiAdapter extends OpenAiAdapter {
3354
3370
  // @ts-expect-error Narrowing override: xAI default model differs from parent's literal
3355
3371
  this.defaultModel = PROVIDER.XAI.MODEL.DEFAULT;
3356
3372
  }
3373
+ classifyError(error) {
3374
+ if (isTransientIngestError(error)) {
3375
+ return {
3376
+ error,
3377
+ category: ErrorCategory.Retryable,
3378
+ shouldRetry: true,
3379
+ };
3380
+ }
3381
+ return super.classifyError(error);
3382
+ }
3357
3383
  }
3358
3384
  // Export singleton instance
3359
3385
  const xaiAdapter = new XaiAdapter();
@@ -5392,14 +5418,13 @@ function formatUserMessage$2(message, { data, placeholders: placeholders$1 } = {
5392
5418
  function prepareMessages$2(message, { data, placeholders } = {}) {
5393
5419
  const logger = getLogger$3();
5394
5420
  const messages = [];
5395
- let systemInstruction;
5396
5421
  // Note: Gemini handles system prompts differently via systemInstruction config
5397
5422
  // This function is kept for compatibility but system prompts should be passed
5398
5423
  // via the systemInstruction parameter in generateContent
5399
5424
  const userMessage = formatUserMessage$2(message, { data, placeholders });
5400
5425
  messages.push(userMessage);
5401
5426
  logger.trace(`User message: ${userMessage.content?.length} characters`);
5402
- return { messages, systemInstruction };
5427
+ return { messages, systemInstruction: undefined };
5403
5428
  }
5404
5429
 
5405
5430
  class GeminiProvider {
@@ -6422,8 +6447,10 @@ const weather = {
6422
6447
  }
6423
6448
  catch (error) {
6424
6449
  if (error instanceof Error) {
6450
+ // eslint-disable-next-line preserve-caught-error -- package targets ES2020; Error `cause` option requires ES2022
6425
6451
  throw new Error(`Weather API error: ${error.message}`);
6426
6452
  }
6453
+ // eslint-disable-next-line preserve-caught-error -- package targets ES2020; Error `cause` option requires ES2022
6427
6454
  throw new Error("Unknown error occurred while fetching weather data");
6428
6455
  }
6429
6456
  },