@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.
@@ -1762,8 +1762,6 @@ class GeminiAdapter extends BaseProviderAdapter {
1762
1762
  contents: geminiRequest.contents,
1763
1763
  config: geminiRequest.config,
1764
1764
  });
1765
- // Track current function call being built
1766
- let currentFunctionCall = null;
1767
1765
  // Track usage for final chunk
1768
1766
  let inputTokens = 0;
1769
1767
  let outputTokens = 0;
@@ -1784,7 +1782,7 @@ class GeminiAdapter extends BaseProviderAdapter {
1784
1782
  // Handle function calls
1785
1783
  if (part.functionCall) {
1786
1784
  const functionCall = part.functionCall;
1787
- currentFunctionCall = {
1785
+ const currentFunctionCall = {
1788
1786
  id: functionCall.id || this.generateCallId(),
1789
1787
  name: functionCall.name || "",
1790
1788
  arguments: functionCall.args || {},
@@ -1804,7 +1802,6 @@ class GeminiAdapter extends BaseProviderAdapter {
1804
1802
  metadata,
1805
1803
  },
1806
1804
  };
1807
- currentFunctionCall = null;
1808
1805
  }
1809
1806
  }
1810
1807
  }
@@ -3343,10 +3340,29 @@ class OpenRouterAdapter extends BaseProviderAdapter {
3343
3340
  // Export singleton instance
3344
3341
  const openRouterAdapter = new OpenRouterAdapter();
3345
3342
 
3343
+ /**
3344
+ * Error-message substrings that indicate a transient xAI media-ingest flake.
3345
+ * The xAI ingest service enters a bad state after ~12 consecutive file-bearing
3346
+ * calls and rejects subsequent requests with HTTP 400. The condition is
3347
+ * self-clearing, so these errors should be retried with backoff rather than
3348
+ * surfaced as unrecoverable.
3349
+ *
3350
+ * See: github.com/finlaysonstudio/jaypie issue #301
3351
+ */
3352
+ const TRANSIENT_INGEST_MESSAGE_PATTERNS = [
3353
+ "failed to ingest inline file bytes",
3354
+ ];
3355
+ function isTransientIngestError(error) {
3356
+ if (!(error instanceof openai.BadRequestError))
3357
+ return false;
3358
+ const message = (error.message ?? "").toLowerCase();
3359
+ return TRANSIENT_INGEST_MESSAGE_PATTERNS.some((pattern) => message.includes(pattern));
3360
+ }
3346
3361
  /**
3347
3362
  * XaiAdapter extends OpenAiAdapter since xAI (Grok) uses an OpenAI-compatible API.
3348
- * Only the name and default model are overridden; all request building, response parsing,
3349
- * error classification, tool handling, and streaming are inherited.
3363
+ * Name, default model, and transient-ingest-error detection are overridden;
3364
+ * all request building, response parsing, tool handling, and streaming are
3365
+ * inherited.
3350
3366
  */
3351
3367
  class XaiAdapter extends OpenAiAdapter {
3352
3368
  constructor() {
@@ -3356,6 +3372,16 @@ class XaiAdapter extends OpenAiAdapter {
3356
3372
  // @ts-expect-error Narrowing override: xAI default model differs from parent's literal
3357
3373
  this.defaultModel = PROVIDER.XAI.MODEL.DEFAULT;
3358
3374
  }
3375
+ classifyError(error) {
3376
+ if (isTransientIngestError(error)) {
3377
+ return {
3378
+ error,
3379
+ category: ErrorCategory.Retryable,
3380
+ shouldRetry: true,
3381
+ };
3382
+ }
3383
+ return super.classifyError(error);
3384
+ }
3359
3385
  }
3360
3386
  // Export singleton instance
3361
3387
  const xaiAdapter = new XaiAdapter();
@@ -5394,14 +5420,13 @@ function formatUserMessage$2(message, { data, placeholders } = {}) {
5394
5420
  function prepareMessages$2(message, { data, placeholders } = {}) {
5395
5421
  const logger = getLogger$3();
5396
5422
  const messages = [];
5397
- let systemInstruction;
5398
5423
  // Note: Gemini handles system prompts differently via systemInstruction config
5399
5424
  // This function is kept for compatibility but system prompts should be passed
5400
5425
  // via the systemInstruction parameter in generateContent
5401
5426
  const userMessage = formatUserMessage$2(message, { data, placeholders });
5402
5427
  messages.push(userMessage);
5403
5428
  logger.trace(`User message: ${userMessage.content?.length} characters`);
5404
- return { messages, systemInstruction };
5429
+ return { messages, systemInstruction: undefined };
5405
5430
  }
5406
5431
 
5407
5432
  class GeminiProvider {
@@ -6424,8 +6449,10 @@ const weather = {
6424
6449
  }
6425
6450
  catch (error) {
6426
6451
  if (error instanceof Error) {
6452
+ // eslint-disable-next-line preserve-caught-error -- package targets ES2020; Error `cause` option requires ES2022
6427
6453
  throw new Error(`Weather API error: ${error.message}`);
6428
6454
  }
6455
+ // eslint-disable-next-line preserve-caught-error -- package targets ES2020; Error `cause` option requires ES2022
6429
6456
  throw new Error("Unknown error occurred while fetching weather data");
6430
6457
  }
6431
6458
  },