{"version":3,"file":"utils.cjs","names":["AIMessage","ToolMessage"],"sources":["../../../src/agents/middleware/utils.ts"],"sourcesContent":["import {\n  AIMessage,\n  ToolMessage,\n  type BaseMessage,\n} from \"@langchain/core/messages\";\nimport { isLangChainTool } from \"@langchain/core/tools\";\nimport { convertToOpenAITool } from \"@langchain/core/utils/function_calling\";\nimport {\n  AfterModelHook,\n  AfterAgentHook,\n  BeforeAgentHook,\n  BeforeModelHook,\n} from \"./types.js\";\nimport { JumpToTarget } from \"../constants.js\";\n\n/**\n * Default token counter that approximates based on character count.\n *\n * If tools are provided, the token count also includes stringified tool schemas.\n *\n * @param messages Messages to count tokens for\n * @param tools Optional list of tools to include in the token count. Each tool\n *   can be either a LangChain tool instance or a dict representing a tool schema.\n *   LangChain tool instances are converted to OpenAI tool format before counting.\n * @returns Approximate token count\n */\nexport function countTokensApproximately(\n  messages: BaseMessage[],\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  tools?: Array<Record<string, any>> | null\n): number {\n  const charsPerToken = 4;\n  let totalChars = 0;\n\n  // Count tokens for tools if provided\n  if (tools && tools.length > 0) {\n    let toolsChars = 0;\n    for (const tool of tools) {\n      const toolDict = isLangChainTool(tool) ? convertToOpenAITool(tool) : tool;\n      toolsChars += JSON.stringify(toolDict).length;\n    }\n    totalChars += toolsChars;\n  }\n\n  for (const msg of messages) {\n    let textContent: string;\n    if (typeof msg.content === \"string\") {\n      textContent = msg.content;\n    } else if (Array.isArray(msg.content)) {\n      textContent = msg.content\n        .map((item) => {\n          if (typeof item === \"string\") return item;\n          if (item.type === \"text\" && \"text\" in item) return item.text;\n          return \"\";\n        })\n        .join(\"\");\n    } else {\n      textContent = \"\";\n    }\n\n    if (\n      AIMessage.isInstance(msg) &&\n      Array.isArray(msg.tool_calls) &&\n      msg.tool_calls.length > 0\n    ) {\n      textContent += JSON.stringify(msg.tool_calls);\n    }\n\n    if (ToolMessage.isInstance(msg)) {\n      textContent += msg.tool_call_id ?? \"\";\n    }\n\n    totalChars += textContent.length;\n  }\n  // Approximate 1 token = 4 characters\n  return Math.ceil(totalChars / charsPerToken);\n}\n\nexport function getHookConstraint(\n  hook:\n    | BeforeAgentHook\n    | BeforeModelHook\n    | AfterAgentHook\n    | AfterModelHook\n    | undefined\n): JumpToTarget[] | undefined {\n  if (!hook || typeof hook === \"function\") {\n    return undefined;\n  }\n  return hook.canJumpTo;\n}\n\nexport function getHookFunction(\n  arg: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook\n) {\n  if (typeof arg === \"function\") {\n    return arg;\n  }\n  return arg.hook;\n}\n\n/**\n * Sleep for the specified number of milliseconds.\n */\nexport function sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Calculate delay for a retry attempt with exponential backoff and jitter.\n *\n * @param retryNumber - The retry attempt number (0-indexed)\n * @param config - Configuration for backoff calculation\n * @returns Delay in milliseconds before next retry\n *\n * @internal Exported for testing purposes\n */\nexport function calculateRetryDelay(\n  config: {\n    backoffFactor: number;\n    initialDelayMs: number;\n    maxDelayMs: number;\n    jitter: boolean;\n  },\n  retryNumber: number\n): number {\n  const { backoffFactor, initialDelayMs, maxDelayMs, jitter } = config;\n\n  let delay: number;\n  if (backoffFactor === 0.0) {\n    delay = initialDelayMs;\n  } else {\n    delay = initialDelayMs * backoffFactor ** retryNumber;\n  }\n\n  // Cap at maxDelayMs\n  delay = Math.min(delay, maxDelayMs);\n\n  if (jitter && delay > 0) {\n    const jitterAmount = delay * 0.25;\n    delay = delay + (Math.random() * 2 - 1) * jitterAmount;\n    // Ensure delay is not negative after jitter\n    delay = Math.max(0, delay);\n  }\n\n  return delay;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA0BA,SAAgB,yBACd,UAEA,OACQ;CACR,MAAM,gBAAgB;CACtB,IAAI,aAAa;AAGjB,KAAI,SAAS,MAAM,SAAS,GAAG;EAC7B,IAAI,aAAa;AACjB,OAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,YAAA,GAAA,sBAAA,iBAA2B,KAAK,IAAA,GAAA,uCAAA,qBAAuB,KAAK,GAAG;AACrE,iBAAc,KAAK,UAAU,SAAS,CAAC;;AAEzC,gBAAc;;AAGhB,MAAK,MAAM,OAAO,UAAU;EAC1B,IAAI;AACJ,MAAI,OAAO,IAAI,YAAY,SACzB,eAAc,IAAI;WACT,MAAM,QAAQ,IAAI,QAAQ,CACnC,eAAc,IAAI,QACf,KAAK,SAAS;AACb,OAAI,OAAO,SAAS,SAAU,QAAO;AACrC,OAAI,KAAK,SAAS,UAAU,UAAU,KAAM,QAAO,KAAK;AACxD,UAAO;IACP,CACD,KAAK,GAAG;MAEX,eAAc;AAGhB,MACEA,yBAAAA,UAAU,WAAW,IAAI,IACzB,MAAM,QAAQ,IAAI,WAAW,IAC7B,IAAI,WAAW,SAAS,EAExB,gBAAe,KAAK,UAAU,IAAI,WAAW;AAG/C,MAAIC,yBAAAA,YAAY,WAAW,IAAI,CAC7B,gBAAe,IAAI,gBAAgB;AAGrC,gBAAc,YAAY;;AAG5B,QAAO,KAAK,KAAK,aAAa,cAAc;;AAG9C,SAAgB,kBACd,MAM4B;AAC5B,KAAI,CAAC,QAAQ,OAAO,SAAS,WAC3B;AAEF,QAAO,KAAK;;AAGd,SAAgB,gBACd,KACA;AACA,KAAI,OAAO,QAAQ,WACjB,QAAO;AAET,QAAO,IAAI;;;;;AAMb,SAAgB,MAAM,IAA2B;AAC/C,QAAO,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC;;;;;;;;;;;AAY1D,SAAgB,oBACd,QAMA,aACQ;CACR,MAAM,EAAE,eAAe,gBAAgB,YAAY,WAAW;CAE9D,IAAI;AACJ,KAAI,kBAAkB,EACpB,SAAQ;KAER,SAAQ,iBAAiB,iBAAiB;AAI5C,SAAQ,KAAK,IAAI,OAAO,WAAW;AAEnC,KAAI,UAAU,QAAQ,GAAG;EACvB,MAAM,eAAe,QAAQ;AAC7B,UAAQ,SAAS,KAAK,QAAQ,GAAG,IAAI,KAAK;AAE1C,UAAQ,KAAK,IAAI,GAAG,MAAM;;AAG5B,QAAO"}