@jaypie/llm 1.2.11 → 1.2.13

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.
@@ -1128,17 +1128,24 @@ class AnthropicAdapter extends BaseProviderAdapter {
1128
1128
  //
1129
1129
  // API Execution
1130
1130
  //
1131
- async executeRequest(client, request) {
1131
+ async executeRequest(client, request, signal) {
1132
1132
  const anthropic = client;
1133
- return (await anthropic.messages.create(request));
1133
+ try {
1134
+ return (await anthropic.messages.create(request, signal ? { signal } : undefined));
1135
+ }
1136
+ catch (error) {
1137
+ if (signal?.aborted)
1138
+ return undefined;
1139
+ throw error;
1140
+ }
1134
1141
  }
1135
- async *executeStreamRequest(client, request) {
1142
+ async *executeStreamRequest(client, request, signal) {
1136
1143
  const anthropic = client;
1137
1144
  const streamRequest = {
1138
1145
  ...request,
1139
1146
  stream: true,
1140
1147
  };
1141
- const stream = await anthropic.messages.create(streamRequest);
1148
+ const stream = await anthropic.messages.create(streamRequest, signal ? { signal } : undefined);
1142
1149
  // Track current tool call being built
1143
1150
  let currentToolCall = null;
1144
1151
  // Track usage for final chunk
@@ -1568,19 +1575,26 @@ class GeminiAdapter extends BaseProviderAdapter {
1568
1575
  //
1569
1576
  // API Execution
1570
1577
  //
1571
- async executeRequest(client, request) {
1578
+ async executeRequest(client, request, signal) {
1572
1579
  const genAI = client;
1573
1580
  const geminiRequest = request;
1574
- // Cast config to any to bypass strict type checking between our internal types
1575
- // and the SDK's types. The SDK will validate at runtime.
1576
- const response = await genAI.models.generateContent({
1577
- model: geminiRequest.model,
1578
- contents: geminiRequest.contents,
1579
- config: geminiRequest.config,
1580
- });
1581
- return response;
1581
+ try {
1582
+ // Cast config to any to bypass strict type checking between our internal types
1583
+ // and the SDK's types. The SDK will validate at runtime.
1584
+ const response = await genAI.models.generateContent({
1585
+ model: geminiRequest.model,
1586
+ contents: geminiRequest.contents,
1587
+ config: geminiRequest.config,
1588
+ });
1589
+ return response;
1590
+ }
1591
+ catch (error) {
1592
+ if (signal?.aborted)
1593
+ return undefined;
1594
+ throw error;
1595
+ }
1582
1596
  }
1583
- async *executeStreamRequest(client, request) {
1597
+ async *executeStreamRequest(client, request, signal) {
1584
1598
  const genAI = client;
1585
1599
  const geminiRequest = request;
1586
1600
  // Use generateContentStream for streaming
@@ -2083,7 +2097,17 @@ class GeminiAdapter extends BaseProviderAdapter {
2083
2097
  return JSON.parse(textContent);
2084
2098
  }
2085
2099
  catch {
2086
- // If parsing fails, return the original string
2100
+ // Strip markdown code fences and retry (Gemini sometimes wraps JSON in fences)
2101
+ const jsonMatch = textContent.match(/```(?:json)?\s*([\s\S]*?)\s*```/) ||
2102
+ textContent.match(/\{[\s\S]*\}/);
2103
+ if (jsonMatch) {
2104
+ try {
2105
+ return JSON.parse(jsonMatch[1] || jsonMatch[0]);
2106
+ }
2107
+ catch {
2108
+ // Fall through to return original string
2109
+ }
2110
+ }
2087
2111
  return textContent;
2088
2112
  }
2089
2113
  }
@@ -2230,19 +2254,26 @@ class OpenAiAdapter extends BaseProviderAdapter {
2230
2254
  //
2231
2255
  // API Execution
2232
2256
  //
2233
- async executeRequest(client, request) {
2257
+ async executeRequest(client, request, signal) {
2234
2258
  const openai = client;
2235
- // @ts-expect-error OpenAI SDK types don't match our request format exactly
2236
- return await openai.responses.create(request);
2259
+ try {
2260
+ // @ts-expect-error OpenAI SDK types don't match our request format exactly
2261
+ return await openai.responses.create(request, signal ? { signal } : undefined);
2262
+ }
2263
+ catch (error) {
2264
+ if (signal?.aborted)
2265
+ return undefined;
2266
+ throw error;
2267
+ }
2237
2268
  }
2238
- async *executeStreamRequest(client, request) {
2269
+ async *executeStreamRequest(client, request, signal) {
2239
2270
  const openai = client;
2240
2271
  const baseRequest = request;
2241
2272
  const streamRequest = {
2242
2273
  ...baseRequest,
2243
2274
  stream: true,
2244
2275
  };
2245
- const stream = await openai.responses.create(streamRequest);
2276
+ const stream = await openai.responses.create(streamRequest, signal ? { signal } : undefined);
2246
2277
  // Track current function call being built
2247
2278
  let currentFunctionCall = null;
2248
2279
  // Track usage for final chunk
@@ -2676,14 +2707,21 @@ class OpenRouterAdapter extends BaseProviderAdapter {
2676
2707
  async executeRequest(client, request, signal) {
2677
2708
  const openRouter = client;
2678
2709
  const openRouterRequest = request;
2679
- const response = await openRouter.chat.send({
2680
- model: openRouterRequest.model,
2681
- messages: openRouterRequest.messages,
2682
- tools: openRouterRequest.tools,
2683
- toolChoice: openRouterRequest.tool_choice,
2684
- user: openRouterRequest.user,
2685
- }, signal ? { signal } : undefined);
2686
- return response;
2710
+ try {
2711
+ const response = await openRouter.chat.send({
2712
+ model: openRouterRequest.model,
2713
+ messages: openRouterRequest.messages,
2714
+ tools: openRouterRequest.tools,
2715
+ toolChoice: openRouterRequest.tool_choice,
2716
+ user: openRouterRequest.user,
2717
+ }, signal ? { signal } : undefined);
2718
+ return response;
2719
+ }
2720
+ catch (error) {
2721
+ if (signal?.aborted)
2722
+ return undefined;
2723
+ throw error;
2724
+ }
2687
2725
  }
2688
2726
  async *executeStreamRequest(client, request, signal) {
2689
2727
  const openRouter = client;
@@ -3970,7 +4008,19 @@ class RetryExecutor {
3970
4008
  providerRequest: options.context.providerRequest,
3971
4009
  error,
3972
4010
  });
3973
- await kit.sleep(delay);
4011
+ // Guard against stale socket errors that fire during sleep
4012
+ const staleHandler = (reason) => {
4013
+ if (isTransientNetworkError(reason)) {
4014
+ log$1.trace("Suppressed stale socket error during retry sleep");
4015
+ }
4016
+ };
4017
+ process.on("unhandledRejection", staleHandler);
4018
+ try {
4019
+ await kit.sleep(delay);
4020
+ }
4021
+ finally {
4022
+ process.removeListener("unhandledRejection", staleHandler);
4023
+ }
3974
4024
  attempt++;
3975
4025
  }
3976
4026
  }
@@ -4614,7 +4664,19 @@ class StreamLoop {
4614
4664
  const delay = this.retryPolicy.getDelayForAttempt(attempt);
4615
4665
  log$1.warn(`Stream request failed. Retrying in ${delay}ms...`);
4616
4666
  log$1.var({ error });
4617
- await kit.sleep(delay);
4667
+ // Guard against stale socket errors that fire during sleep
4668
+ const staleHandler = (reason) => {
4669
+ if (isTransientNetworkError(reason)) {
4670
+ log$1.trace("Suppressed stale socket error during retry sleep");
4671
+ }
4672
+ };
4673
+ process.on("unhandledRejection", staleHandler);
4674
+ try {
4675
+ await kit.sleep(delay);
4676
+ }
4677
+ finally {
4678
+ process.removeListener("unhandledRejection", staleHandler);
4679
+ }
4618
4680
  attempt++;
4619
4681
  }
4620
4682
  }
@@ -5091,6 +5153,17 @@ class GeminiProvider {
5091
5153
  return JSON.parse(text);
5092
5154
  }
5093
5155
  catch {
5156
+ // Strip markdown code fences and retry (Gemini sometimes wraps JSON in fences)
5157
+ const jsonMatch = text.match(/```(?:json)?\s*([\s\S]*?)\s*```/) ||
5158
+ text.match(/\{[\s\S]*\}/);
5159
+ if (jsonMatch) {
5160
+ try {
5161
+ return JSON.parse(jsonMatch[1] || jsonMatch[0]);
5162
+ }
5163
+ catch {
5164
+ // Fall through to return original text
5165
+ }
5166
+ }
5094
5167
  return text || "";
5095
5168
  }
5096
5169
  }