{"version":3,"file":"callLimit.cjs","names":["z","exceededHint: string[]","middlewareOptions?: ModelCallLimitMiddlewareConfig","createMiddleware","AIMessage"],"sources":["../../../src/agents/middleware/callLimit.ts"],"sourcesContent":["import { z } from \"zod/v3\";\nimport { AIMessage } from \"@langchain/core/messages\";\nimport { InferInteropZodInput } from \"@langchain/core/utils/types\";\n\nimport { createMiddleware } from \"../middleware.js\";\n\nconst DEFAULT_EXIT_BEHAVIOR = \"end\";\n\nconst contextSchema = z.object({\n  /**\n   * The maximum number of model calls allowed per thread.\n   */\n  threadLimit: z.number().optional(),\n  /**\n   * The maximum number of model calls allowed per run.\n   */\n  runLimit: z.number().optional(),\n  /**\n   * The behavior to take when the limit is exceeded.\n   * - \"throw\" will throw an error and stop the agent.\n   * - \"end\" will end the agent.\n   * @default \"end\"\n   */\n  exitBehavior: z.enum([\"throw\", \"end\"]).optional(),\n});\nexport type ModelCallLimitMiddlewareConfig = Partial<\n  InferInteropZodInput<typeof contextSchema>\n>;\n\n/**\n * Error thrown when the model call limit is exceeded.\n *\n * @param threadLimit - The maximum number of model calls allowed per thread.\n * @param runLimit - The maximum number of model calls allowed per run.\n * @param threadCount - The number of model calls made at the thread level.\n * @param runCount - The number of model calls made at the run level.\n */\nclass ModelCallLimitMiddlewareError extends Error {\n  constructor({\n    threadLimit,\n    runLimit,\n    threadCount,\n    runCount,\n  }: {\n    threadLimit?: number;\n    runLimit?: number;\n    threadCount?: number;\n    runCount?: number;\n  }) {\n    const exceededHint: string[] = [];\n    if (typeof threadLimit === \"number\" && typeof threadCount === \"number\") {\n      exceededHint.push(\n        `thread level call limit reached with ${threadCount} model calls`\n      );\n    }\n    if (typeof runLimit === \"number\" && typeof runCount === \"number\") {\n      exceededHint.push(\n        `run level call limit reached with ${runCount} model calls`\n      );\n    }\n    super(\n      `Model call limits exceeded${\n        exceededHint.length > 0 ? `: ${exceededHint.join(\", \")}` : \"\"\n      }`\n    );\n    this.name = \"ModelCallLimitMiddlewareError\";\n  }\n}\n\n/**\n * Creates a middleware to limit the number of model calls at both thread and run levels.\n *\n * This middleware helps prevent excessive model API calls by enforcing limits on how many\n * times the model can be invoked. It supports two types of limits:\n *\n * - **Thread-level limit**: Restricts the total number of model calls across an entire conversation thread\n * - **Run-level limit**: Restricts the number of model calls within a single agent run/invocation\n *\n * ## How It Works\n *\n * The middleware intercepts model requests before they are sent and checks the current call counts\n * against the configured limits. If either limit is exceeded, it throws a `ModelCallLimitMiddlewareError`\n * to stop execution and prevent further API calls.\n *\n * ## Use Cases\n *\n * - **Cost Control**: Prevent runaway costs from excessive model calls in production\n * - **Testing**: Ensure agents don't make too many calls during development/testing\n * - **Safety**: Limit potential infinite loops or recursive agent behaviors\n * - **Rate Limiting**: Enforce organizational policies on model usage per conversation\n *\n * @param middlewareOptions - Configuration options for the call limits\n * @param middlewareOptions.threadLimit - Maximum number of model calls allowed per thread (optional)\n * @param middlewareOptions.runLimit - Maximum number of model calls allowed per run (optional)\n *\n * @returns A middleware instance that can be passed to `createAgent`\n *\n * @throws {ModelCallLimitMiddlewareError} When either the thread or run limit is exceeded\n *\n * @example\n * ```typescript\n * import { createAgent, modelCallLimitMiddleware } from \"langchain\";\n *\n * // Limit to 10 calls per thread and 3 calls per run\n * const agent = createAgent({\n *   model: \"openai:gpt-4o-mini\",\n *   tools: [myTool],\n *   middleware: [\n *     modelCallLimitMiddleware({\n *       threadLimit: 10,\n *       runLimit: 3\n *     })\n *   ]\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Limits can also be configured at runtime via context\n * const result = await agent.invoke(\n *   { messages: [\"Hello\"] },\n *   {\n *     configurable: {\n *       threadLimit: 5  // Override the default limit for this run\n *     }\n *   }\n * );\n * ```\n */\nexport function modelCallLimitMiddleware(\n  middlewareOptions?: ModelCallLimitMiddlewareConfig\n) {\n  return createMiddleware({\n    name: \"ModelCallLimitMiddleware\",\n    contextSchema,\n    beforeModel: {\n      canJumpTo: [\"end\"],\n      hook: (state, runtime) => {\n        const exitBehavior =\n          runtime.context.exitBehavior ??\n          middlewareOptions?.exitBehavior ??\n          DEFAULT_EXIT_BEHAVIOR;\n        const threadLimit =\n          runtime.context.threadLimit ?? middlewareOptions?.threadLimit;\n        const runLimit =\n          runtime.context.runLimit ?? middlewareOptions?.runLimit;\n\n        if (\n          typeof threadLimit === \"number\" &&\n          threadLimit <= runtime.threadLevelCallCount\n        ) {\n          const error = new ModelCallLimitMiddlewareError({\n            threadLimit,\n            threadCount: runtime.threadLevelCallCount,\n          });\n          if (exitBehavior === \"end\") {\n            return {\n              jumpTo: \"end\",\n              messages: [new AIMessage(error.message)],\n            };\n          }\n\n          throw error;\n        }\n        if (\n          typeof runLimit === \"number\" &&\n          runLimit <= runtime.runModelCallCount\n        ) {\n          const error = new ModelCallLimitMiddlewareError({\n            runLimit,\n            runCount: runtime.runModelCallCount,\n          });\n          if (exitBehavior === \"end\") {\n            return {\n              jumpTo: \"end\",\n              messages: [new AIMessage(error.message)],\n            };\n          }\n\n          throw error;\n        }\n\n        return state;\n      },\n    },\n  });\n}\n"],"mappings":";;;;;;AAMA,MAAM,wBAAwB;AAE9B,MAAM,gBAAgBA,SAAE,OAAO;CAI7B,aAAaA,SAAE,QAAQ,CAAC,UAAU;CAIlC,UAAUA,SAAE,QAAQ,CAAC,UAAU;CAO/B,cAAcA,SAAE,KAAK,CAAC,SAAS,KAAM,EAAC,CAAC,UAAU;AAClD,EAAC;;;;;;;;;AAaF,IAAM,gCAAN,cAA4C,MAAM;CAChD,YAAY,EACV,aACA,UACA,aACA,UAMD,EAAE;EACD,MAAMC,eAAyB,CAAE;AACjC,MAAI,OAAO,gBAAgB,YAAY,OAAO,gBAAgB,UAC5D,aAAa,KACX,CAAC,qCAAqC,EAAE,YAAY,YAAY,CAAC,CAClE;AAEH,MAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UACtD,aAAa,KACX,CAAC,kCAAkC,EAAE,SAAS,YAAY,CAAC,CAC5D;EAEH,MACE,CAAC,0BAA0B,EACzB,aAAa,SAAS,IAAI,CAAC,EAAE,EAAE,aAAa,KAAK,KAAK,EAAE,GAAG,IAC3D,CACH;EACD,KAAK,OAAO;CACb;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DD,SAAgB,yBACdC,mBACA;AACA,QAAOC,oCAAiB;EACtB,MAAM;EACN;EACA,aAAa;GACX,WAAW,CAAC,KAAM;GAClB,MAAM,CAAC,OAAO,YAAY;IACxB,MAAM,eACJ,QAAQ,QAAQ,gBAChB,mBAAmB,gBACnB;IACF,MAAM,cACJ,QAAQ,QAAQ,eAAe,mBAAmB;IACpD,MAAM,WACJ,QAAQ,QAAQ,YAAY,mBAAmB;AAEjD,QACE,OAAO,gBAAgB,YACvB,eAAe,QAAQ,sBACvB;KACA,MAAM,QAAQ,IAAI,8BAA8B;MAC9C;MACA,aAAa,QAAQ;KACtB;AACD,SAAI,iBAAiB,MACnB,QAAO;MACL,QAAQ;MACR,UAAU,CAAC,IAAIC,oCAAU,MAAM,QAAS;KACzC;AAGH,WAAM;IACP;AACD,QACE,OAAO,aAAa,YACpB,YAAY,QAAQ,mBACpB;KACA,MAAM,QAAQ,IAAI,8BAA8B;MAC9C;MACA,UAAU,QAAQ;KACnB;AACD,SAAI,iBAAiB,MACnB,QAAO;MACL,QAAQ;MACR,UAAU,CAAC,IAAIA,oCAAU,MAAM,QAAS;KACzC;AAGH,WAAM;IACP;AAED,WAAO;GACR;EACF;CACF,EAAC;AACH"}