@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.
@@ -17,8 +17,8 @@ export declare class AnthropicAdapter extends BaseProviderAdapter {
17
17
  buildRequest(request: OperateRequest): Anthropic.MessageCreateParams;
18
18
  formatTools(toolkit: Toolkit, outputSchema?: JsonObject): ProviderToolDefinition[];
19
19
  formatOutputSchema(schema: JsonObject | NaturalSchema | z.ZodType): JsonObject;
20
- executeRequest(client: unknown, request: unknown): Promise<Anthropic.Message>;
21
- executeStreamRequest(client: unknown, request: unknown): AsyncIterable<LlmStreamChunk>;
20
+ executeRequest(client: unknown, request: unknown, signal?: AbortSignal): Promise<Anthropic.Message>;
21
+ executeStreamRequest(client: unknown, request: unknown, signal?: AbortSignal): AsyncIterable<LlmStreamChunk>;
22
22
  parseResponse(response: unknown, _options?: LlmOperateOptions): ParsedResponse;
23
23
  extractToolCalls(response: unknown): StandardToolCall[];
24
24
  extractUsage(response: unknown, model: string): LlmUsageItem;
@@ -17,8 +17,8 @@ export declare class GeminiAdapter extends BaseProviderAdapter {
17
17
  buildRequest(request: OperateRequest): GeminiRequest;
18
18
  formatTools(toolkit: Toolkit, outputSchema?: JsonObject): ProviderToolDefinition[];
19
19
  formatOutputSchema(schema: JsonObject | NaturalSchema | z.ZodType): JsonObject;
20
- executeRequest(client: unknown, request: unknown): Promise<GeminiRawResponse>;
21
- executeStreamRequest(client: unknown, request: unknown): AsyncIterable<LlmStreamChunk>;
20
+ executeRequest(client: unknown, request: unknown, signal?: AbortSignal): Promise<GeminiRawResponse>;
21
+ executeStreamRequest(client: unknown, request: unknown, signal?: AbortSignal): AsyncIterable<LlmStreamChunk>;
22
22
  parseResponse(response: unknown, options?: LlmOperateOptions): ParsedResponse;
23
23
  extractToolCalls(response: unknown): StandardToolCall[];
24
24
  extractUsage(response: unknown, model: string): LlmUsageItem;
@@ -16,8 +16,8 @@ export declare class OpenAiAdapter extends BaseProviderAdapter {
16
16
  buildRequest(request: OperateRequest): unknown;
17
17
  formatTools(toolkit: Toolkit, _outputSchema?: JsonObject): ProviderToolDefinition[];
18
18
  formatOutputSchema(schema: JsonObject | NaturalSchema | z.ZodType): JsonObject;
19
- executeRequest(client: unknown, request: unknown): Promise<unknown>;
20
- executeStreamRequest(client: unknown, request: unknown): AsyncIterable<LlmStreamChunk>;
19
+ executeRequest(client: unknown, request: unknown, signal?: AbortSignal): Promise<unknown>;
20
+ executeStreamRequest(client: unknown, request: unknown, signal?: AbortSignal): AsyncIterable<LlmStreamChunk>;
21
21
  parseResponse(response: unknown, options?: LlmOperateOptions): ParsedResponse;
22
22
  extractToolCalls(response: unknown): StandardToolCall[];
23
23
  extractUsage(response: unknown, model: string): LlmUsageItem;
package/dist/esm/index.js CHANGED
@@ -1126,17 +1126,24 @@ class AnthropicAdapter extends BaseProviderAdapter {
1126
1126
  //
1127
1127
  // API Execution
1128
1128
  //
1129
- async executeRequest(client, request) {
1129
+ async executeRequest(client, request, signal) {
1130
1130
  const anthropic = client;
1131
- return (await anthropic.messages.create(request));
1131
+ try {
1132
+ return (await anthropic.messages.create(request, signal ? { signal } : undefined));
1133
+ }
1134
+ catch (error) {
1135
+ if (signal?.aborted)
1136
+ return undefined;
1137
+ throw error;
1138
+ }
1132
1139
  }
1133
- async *executeStreamRequest(client, request) {
1140
+ async *executeStreamRequest(client, request, signal) {
1134
1141
  const anthropic = client;
1135
1142
  const streamRequest = {
1136
1143
  ...request,
1137
1144
  stream: true,
1138
1145
  };
1139
- const stream = await anthropic.messages.create(streamRequest);
1146
+ const stream = await anthropic.messages.create(streamRequest, signal ? { signal } : undefined);
1140
1147
  // Track current tool call being built
1141
1148
  let currentToolCall = null;
1142
1149
  // Track usage for final chunk
@@ -1566,19 +1573,26 @@ class GeminiAdapter extends BaseProviderAdapter {
1566
1573
  //
1567
1574
  // API Execution
1568
1575
  //
1569
- async executeRequest(client, request) {
1576
+ async executeRequest(client, request, signal) {
1570
1577
  const genAI = client;
1571
1578
  const geminiRequest = request;
1572
- // Cast config to any to bypass strict type checking between our internal types
1573
- // and the SDK's types. The SDK will validate at runtime.
1574
- const response = await genAI.models.generateContent({
1575
- model: geminiRequest.model,
1576
- contents: geminiRequest.contents,
1577
- config: geminiRequest.config,
1578
- });
1579
- return response;
1579
+ try {
1580
+ // Cast config to any to bypass strict type checking between our internal types
1581
+ // and the SDK's types. The SDK will validate at runtime.
1582
+ const response = await genAI.models.generateContent({
1583
+ model: geminiRequest.model,
1584
+ contents: geminiRequest.contents,
1585
+ config: geminiRequest.config,
1586
+ });
1587
+ return response;
1588
+ }
1589
+ catch (error) {
1590
+ if (signal?.aborted)
1591
+ return undefined;
1592
+ throw error;
1593
+ }
1580
1594
  }
1581
- async *executeStreamRequest(client, request) {
1595
+ async *executeStreamRequest(client, request, signal) {
1582
1596
  const genAI = client;
1583
1597
  const geminiRequest = request;
1584
1598
  // Use generateContentStream for streaming
@@ -2081,7 +2095,17 @@ class GeminiAdapter extends BaseProviderAdapter {
2081
2095
  return JSON.parse(textContent);
2082
2096
  }
2083
2097
  catch {
2084
- // If parsing fails, return the original string
2098
+ // Strip markdown code fences and retry (Gemini sometimes wraps JSON in fences)
2099
+ const jsonMatch = textContent.match(/```(?:json)?\s*([\s\S]*?)\s*```/) ||
2100
+ textContent.match(/\{[\s\S]*\}/);
2101
+ if (jsonMatch) {
2102
+ try {
2103
+ return JSON.parse(jsonMatch[1] || jsonMatch[0]);
2104
+ }
2105
+ catch {
2106
+ // Fall through to return original string
2107
+ }
2108
+ }
2085
2109
  return textContent;
2086
2110
  }
2087
2111
  }
@@ -2228,19 +2252,26 @@ class OpenAiAdapter extends BaseProviderAdapter {
2228
2252
  //
2229
2253
  // API Execution
2230
2254
  //
2231
- async executeRequest(client, request) {
2255
+ async executeRequest(client, request, signal) {
2232
2256
  const openai = client;
2233
- // @ts-expect-error OpenAI SDK types don't match our request format exactly
2234
- return await openai.responses.create(request);
2257
+ try {
2258
+ // @ts-expect-error OpenAI SDK types don't match our request format exactly
2259
+ return await openai.responses.create(request, signal ? { signal } : undefined);
2260
+ }
2261
+ catch (error) {
2262
+ if (signal?.aborted)
2263
+ return undefined;
2264
+ throw error;
2265
+ }
2235
2266
  }
2236
- async *executeStreamRequest(client, request) {
2267
+ async *executeStreamRequest(client, request, signal) {
2237
2268
  const openai = client;
2238
2269
  const baseRequest = request;
2239
2270
  const streamRequest = {
2240
2271
  ...baseRequest,
2241
2272
  stream: true,
2242
2273
  };
2243
- const stream = await openai.responses.create(streamRequest);
2274
+ const stream = await openai.responses.create(streamRequest, signal ? { signal } : undefined);
2244
2275
  // Track current function call being built
2245
2276
  let currentFunctionCall = null;
2246
2277
  // Track usage for final chunk
@@ -2674,14 +2705,21 @@ class OpenRouterAdapter extends BaseProviderAdapter {
2674
2705
  async executeRequest(client, request, signal) {
2675
2706
  const openRouter = client;
2676
2707
  const openRouterRequest = request;
2677
- const response = await openRouter.chat.send({
2678
- model: openRouterRequest.model,
2679
- messages: openRouterRequest.messages,
2680
- tools: openRouterRequest.tools,
2681
- toolChoice: openRouterRequest.tool_choice,
2682
- user: openRouterRequest.user,
2683
- }, signal ? { signal } : undefined);
2684
- return response;
2708
+ try {
2709
+ const response = await openRouter.chat.send({
2710
+ model: openRouterRequest.model,
2711
+ messages: openRouterRequest.messages,
2712
+ tools: openRouterRequest.tools,
2713
+ toolChoice: openRouterRequest.tool_choice,
2714
+ user: openRouterRequest.user,
2715
+ }, signal ? { signal } : undefined);
2716
+ return response;
2717
+ }
2718
+ catch (error) {
2719
+ if (signal?.aborted)
2720
+ return undefined;
2721
+ throw error;
2722
+ }
2685
2723
  }
2686
2724
  async *executeStreamRequest(client, request, signal) {
2687
2725
  const openRouter = client;
@@ -3968,7 +4006,19 @@ class RetryExecutor {
3968
4006
  providerRequest: options.context.providerRequest,
3969
4007
  error,
3970
4008
  });
3971
- await sleep(delay);
4009
+ // Guard against stale socket errors that fire during sleep
4010
+ const staleHandler = (reason) => {
4011
+ if (isTransientNetworkError(reason)) {
4012
+ log$1.trace("Suppressed stale socket error during retry sleep");
4013
+ }
4014
+ };
4015
+ process.on("unhandledRejection", staleHandler);
4016
+ try {
4017
+ await sleep(delay);
4018
+ }
4019
+ finally {
4020
+ process.removeListener("unhandledRejection", staleHandler);
4021
+ }
3972
4022
  attempt++;
3973
4023
  }
3974
4024
  }
@@ -4612,7 +4662,19 @@ class StreamLoop {
4612
4662
  const delay = this.retryPolicy.getDelayForAttempt(attempt);
4613
4663
  log$1.warn(`Stream request failed. Retrying in ${delay}ms...`);
4614
4664
  log$1.var({ error });
4615
- await sleep(delay);
4665
+ // Guard against stale socket errors that fire during sleep
4666
+ const staleHandler = (reason) => {
4667
+ if (isTransientNetworkError(reason)) {
4668
+ log$1.trace("Suppressed stale socket error during retry sleep");
4669
+ }
4670
+ };
4671
+ process.on("unhandledRejection", staleHandler);
4672
+ try {
4673
+ await sleep(delay);
4674
+ }
4675
+ finally {
4676
+ process.removeListener("unhandledRejection", staleHandler);
4677
+ }
4616
4678
  attempt++;
4617
4679
  }
4618
4680
  }
@@ -5089,6 +5151,17 @@ class GeminiProvider {
5089
5151
  return JSON.parse(text);
5090
5152
  }
5091
5153
  catch {
5154
+ // Strip markdown code fences and retry (Gemini sometimes wraps JSON in fences)
5155
+ const jsonMatch = text.match(/```(?:json)?\s*([\s\S]*?)\s*```/) ||
5156
+ text.match(/\{[\s\S]*\}/);
5157
+ if (jsonMatch) {
5158
+ try {
5159
+ return JSON.parse(jsonMatch[1] || jsonMatch[0]);
5160
+ }
5161
+ catch {
5162
+ // Fall through to return original text
5163
+ }
5164
+ }
5092
5165
  return text || "";
5093
5166
  }
5094
5167
  }