@jaypie/llm 1.2.21 → 1.2.22

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.
@@ -10,6 +10,7 @@ export interface OperateLoopConfig {
10
10
  inputProcessor?: InputProcessor;
11
11
  retryPolicy?: RetryPolicy;
12
12
  }
13
+ export declare const MAX_CONSECUTIVE_TOOL_ERRORS = 6;
13
14
  /**
14
15
  * OperateLoop implements the core multi-turn conversation loop.
15
16
  * It orchestrates provider adapters, retry logic, hook execution, and tool calling.
@@ -117,6 +117,8 @@ import type { ResponseBuilder } from "./response/ResponseBuilder.js";
117
117
  * Internal state of the operate loop
118
118
  */
119
119
  export interface OperateLoopState {
120
+ /** Count of consecutive tool errors (resets on success) */
121
+ consecutiveToolErrors: number;
120
122
  /** Current conversation input/messages */
121
123
  currentInput: LlmHistory;
122
124
  /** Current turn number (0-indexed, incremented at start of each turn) */
@@ -3,7 +3,7 @@ import { LlmMessageOptions } from "../../types/LlmProvider.interface.js";
3
3
  import { z } from "zod/v4";
4
4
  import { JsonObject, NaturalSchema } from "@jaypie/types";
5
5
  export declare function loadSdk(): Promise<typeof import("@anthropic-ai/sdk")>;
6
- export declare const getLogger: () => any;
6
+ export declare const getLogger: () => import("@jaypie/logger/dist/esm/JaypieLogger.js").default;
7
7
  export declare function initializeClient({ apiKey, }?: {
8
8
  apiKey?: string;
9
9
  }): Promise<Anthropic>;
@@ -1,7 +1,7 @@
1
1
  import type { GoogleGenAI } from "@google/genai";
2
2
  import { LlmMessageOptions } from "../../types/LlmProvider.interface.js";
3
3
  export declare function loadSdk(): Promise<typeof import("@google/genai")>;
4
- export declare const getLogger: () => any;
4
+ export declare const getLogger: () => import("@jaypie/logger/dist/esm/JaypieLogger.js").default;
5
5
  export declare function initializeClient({ apiKey, }?: {
6
6
  apiKey?: string;
7
7
  }): Promise<GoogleGenAI>;
@@ -2,7 +2,7 @@ import { JsonObject, NaturalSchema } from "@jaypie/types";
2
2
  import { OpenAI } from "openai";
3
3
  import { z } from "zod/v4";
4
4
  import { LlmMessageOptions } from "../../types/LlmProvider.interface.js";
5
- export declare const getLogger: () => any;
5
+ export declare const getLogger: () => import("@jaypie/logger/dist/esm/JaypieLogger.js").default;
6
6
  export declare function initializeClient({ apiKey, }?: {
7
7
  apiKey?: string;
8
8
  }): Promise<OpenAI>;
@@ -1,7 +1,7 @@
1
1
  import type { OpenRouter } from "@openrouter/sdk";
2
2
  import { LlmMessageOptions } from "../../types/LlmProvider.interface.js";
3
3
  export declare function loadSdk(): Promise<typeof import("@openrouter/sdk")>;
4
- export declare const getLogger: () => any;
4
+ export declare const getLogger: () => import("@jaypie/logger/dist/esm/JaypieLogger.js").default;
5
5
  export declare function initializeClient({ apiKey, }?: {
6
6
  apiKey?: string;
7
7
  }): Promise<OpenRouter>;
@@ -1,5 +1,5 @@
1
1
  import { OpenAI } from "openai";
2
- export declare const getLogger: () => any;
2
+ export declare const getLogger: () => import("@jaypie/logger/dist/esm/JaypieLogger.js").default;
3
3
  export declare function initializeClient({ apiKey, }?: {
4
4
  apiKey?: string;
5
5
  }): Promise<OpenAI>;
@@ -1,2 +1,2 @@
1
- export declare const getLogger: () => any;
2
- export declare const log: any;
1
+ export declare const getLogger: () => import("@jaypie/logger/dist/esm/JaypieLogger").default;
2
+ export declare const log: import("@jaypie/logger/dist/esm/JaypieLogger").default;
@@ -1,6 +1,6 @@
1
1
  import { LlmOperateOptions } from "../types/LlmProvider.interface.js";
2
2
  export declare const MAX_TURNS_ABSOLUTE_LIMIT = 72;
3
- export declare const MAX_TURNS_DEFAULT_LIMIT = 12;
3
+ export declare const MAX_TURNS_DEFAULT_LIMIT = 24;
4
4
  /**
5
5
  * Determines the maximum number of turns based on the provided options
6
6
  *
package/dist/esm/index.js CHANGED
@@ -555,7 +555,7 @@ const log$1 = getLogger$5();
555
555
 
556
556
  // Turn policy constants
557
557
  const MAX_TURNS_ABSOLUTE_LIMIT = 72;
558
- const MAX_TURNS_DEFAULT_LIMIT = 12;
558
+ const MAX_TURNS_DEFAULT_LIMIT = 24;
559
559
  /**
560
560
  * Determines the maximum number of turns based on the provided options
561
561
  *
@@ -4147,6 +4147,7 @@ class RetryExecutor {
4147
4147
  const ERROR$1 = {
4148
4148
  BAD_FUNCTION_CALL: "Bad Function Call",
4149
4149
  };
4150
+ const MAX_CONSECUTIVE_TOOL_ERRORS = 6;
4150
4151
  //
4151
4152
  //
4152
4153
  // Helpers
@@ -4269,6 +4270,7 @@ class OperateLoop {
4269
4270
  }
4270
4271
  }
4271
4272
  return {
4273
+ consecutiveToolErrors: 0,
4272
4274
  currentInput: processedInput.history,
4273
4275
  currentTurn: 0,
4274
4276
  formattedFormat,
@@ -4393,6 +4395,8 @@ class OperateLoop {
4393
4395
  output: JSON.stringify(result),
4394
4396
  success: true,
4395
4397
  };
4398
+ // Reset consecutive error counter on success
4399
+ state.consecutiveToolErrors = 0;
4396
4400
  // Update provider request with tool result
4397
4401
  currentProviderRequest = this.adapter.appendToolResult(currentProviderRequest, toolCall, formattedResult);
4398
4402
  // Sync state from updated request
@@ -4434,6 +4438,19 @@ class OperateLoop {
4434
4438
  state.responseBuilder.appendToHistory(toolResultFormatted);
4435
4439
  log$1.error(`Error executing function call ${toolCall.name}`);
4436
4440
  log$1.var({ error });
4441
+ // Track consecutive errors and stop if threshold reached
4442
+ state.consecutiveToolErrors++;
4443
+ if (state.consecutiveToolErrors >= MAX_CONSECUTIVE_TOOL_ERRORS) {
4444
+ const detail = `Stopped after ${MAX_CONSECUTIVE_TOOL_ERRORS} consecutive tool errors`;
4445
+ log$1.warn(detail);
4446
+ state.responseBuilder.setError({
4447
+ detail,
4448
+ status: 502,
4449
+ title: ERROR$1.BAD_FUNCTION_CALL,
4450
+ });
4451
+ state.responseBuilder.incomplete();
4452
+ return false; // Stop loop
4453
+ }
4437
4454
  }
4438
4455
  }
4439
4456
  // Check if we've reached max turns
@@ -4681,6 +4698,7 @@ class StreamLoop {
4681
4698
  ? this.adapter.formatTools(toolkit, formattedFormat)
4682
4699
  : undefined;
4683
4700
  return {
4701
+ consecutiveToolErrors: 0,
4684
4702
  currentInput: processedInput.history,
4685
4703
  currentTurn: 0,
4686
4704
  formattedFormat,
@@ -4874,6 +4892,8 @@ class StreamLoop {
4874
4892
  result,
4875
4893
  toolName: toolCall.name,
4876
4894
  });
4895
+ // Reset consecutive error counter on success
4896
+ state.consecutiveToolErrors = 0;
4877
4897
  // Yield tool result chunk
4878
4898
  yield {
4879
4899
  type: LlmStreamChunkType.ToolResult,
@@ -4926,6 +4946,21 @@ class StreamLoop {
4926
4946
  });
4927
4947
  log$1.error(`Error executing function call ${toolCall.name}`);
4928
4948
  log$1.var({ error });
4949
+ // Track consecutive errors and stop if threshold reached
4950
+ state.consecutiveToolErrors++;
4951
+ if (state.consecutiveToolErrors >= MAX_CONSECUTIVE_TOOL_ERRORS) {
4952
+ const stopDetail = `Stopped after ${MAX_CONSECUTIVE_TOOL_ERRORS} consecutive tool errors`;
4953
+ log$1.warn(stopDetail);
4954
+ yield {
4955
+ type: LlmStreamChunkType.Error,
4956
+ error: {
4957
+ detail: stopDetail,
4958
+ status: 502,
4959
+ title: ERROR.BAD_FUNCTION_CALL,
4960
+ },
4961
+ };
4962
+ return; // Stop processing tools
4963
+ }
4929
4964
  }
4930
4965
  }
4931
4966
  }