{"version":3,"file":"for-tool.mjs","names":[],"sources":["../../../../../../../../ai/src/middleware/helpers/for-tool.ts"],"sourcesContent":["import type { AgentMiddleware } from \"../../contracts/middleware\";\n\n/**\n * Scope a middleware's `tool`-level hooks to only fire for a\n * specific tool name (or a set of names). `execute` and `trip`\n * hooks pass through unchanged.\n *\n * **Role.** Tool-specific concerns — \"rate-limit `search_web`\",\n * \"cache results for `fetch_faq`\" — are common. Rather than adding\n * a `middleware` field to `ai.tool()` (see decisions §27), the\n * framework keeps one contract (`AgentMiddleware`) and offers this\n * helper for the locality problem. The middleware body stays agnostic\n * of the tool name; `forTool` handles the filtering.\n *\n * **What gets filtered.** Only `tool.before` / `tool.after` /\n * `tool.onError`. Each hook is wrapped so that `ctx.tool.name`\n * must be in the allowed set or the wrapped hook is a no-op.\n * `execute` and `trip` hooks are NOT touched — they run normally.\n *\n * **Why not filter execute/trip too?** Because a middleware that\n * reaches across levels (a tool-specific budget that initializes a\n * counter in `execute.before` and checks it in `tool.before`) still\n * needs `execute.before` to fire unconditionally. Scoping all hooks\n * would break cross-level middleware; scoping only `tool` hooks\n * matches the mental model of \"this middleware cares about these\n * tools.\"\n *\n * **Single-name vs multi-name.** A string matches one tool; a string\n * array matches any of the listed tools. No wildcards, no regex —\n * keep it boring.\n *\n * @example\n * // Single tool\n * const scoped = ai.middleware.forTool(\n *   \"search_web\",\n *   toolRateLimit({ maxCalls: 3 }),\n * );\n *\n * @example\n * // Multiple tools sharing a rule\n * const scoped = ai.middleware.forTool(\n *   [\"paid_api\", \"expensive_db\"],\n *   toolRateLimit({ maxCalls: 5 }),\n * );\n *\n * ai.agent({\n *   model,\n *   tools: [webTool, paidApiTool, expensiveDbTool],\n *   middleware: [scoped],\n * });\n */\nexport function forTool(\n  toolNames: string | ReadonlyArray<string>,\n  middleware: AgentMiddleware,\n): AgentMiddleware {\n  const allowed = new Set(\n    typeof toolNames === \"string\" ? [toolNames] : toolNames,\n  );\n  const scope =\n    allowed.size === 1 ? Array.from(allowed)[0] : Array.from(allowed).join(\"+\");\n\n  if (!middleware.tool) {\n    return middleware;\n  }\n\n  const innerBefore = middleware.tool.before;\n  const innerAfter = middleware.tool.after;\n  const innerOnError = middleware.tool.onError;\n\n  return {\n    ...middleware,\n    name: `${middleware.name}[for:${scope}]`,\n    tool: {\n      before: innerBefore\n        ? async ctx => {\n            if (!allowed.has(ctx.tool.name)) {\n              return;\n            }\n\n            return innerBefore(ctx);\n          }\n        : undefined,\n      after: innerAfter\n        ? async (ctx, result) => {\n            if (!allowed.has(ctx.tool.name)) {\n              return;\n            }\n\n            return innerAfter(ctx, result);\n          }\n        : undefined,\n      onError: innerOnError\n        ? async (ctx, error) => {\n            if (!allowed.has(ctx.tool.name)) {\n              return;\n            }\n\n            return innerOnError(ctx, error);\n          }\n        : undefined,\n    },\n  };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDA,SAAgB,QACd,WACA,YACiB;CACjB,MAAM,UAAU,IAAI,IAClB,OAAO,cAAc,WAAW,CAAC,SAAS,IAAI,SAChD;CACA,MAAM,QACJ,QAAQ,SAAS,IAAI,MAAM,KAAK,OAAO,CAAC,CAAC,KAAK,MAAM,KAAK,OAAO,CAAC,CAAC,KAAK,GAAG;CAE5E,IAAI,CAAC,WAAW,MACd,OAAO;CAGT,MAAM,cAAc,WAAW,KAAK;CACpC,MAAM,aAAa,WAAW,KAAK;CACnC,MAAM,eAAe,WAAW,KAAK;CAErC,OAAO;EACL,GAAG;EACH,MAAM,GAAG,WAAW,KAAK,OAAO,MAAM;EACtC,MAAM;GACJ,QAAQ,cACJ,OAAM,QAAO;IACX,IAAI,CAAC,QAAQ,IAAI,IAAI,KAAK,IAAI,GAC5B;IAGF,OAAO,YAAY,GAAG;GACxB,IACA;GACJ,OAAO,aACH,OAAO,KAAK,WAAW;IACrB,IAAI,CAAC,QAAQ,IAAI,IAAI,KAAK,IAAI,GAC5B;IAGF,OAAO,WAAW,KAAK,MAAM;GAC/B,IACA;GACJ,SAAS,eACL,OAAO,KAAK,UAAU;IACpB,IAAI,CAAC,QAAQ,IAAI,IAAI,KAAK,IAAI,GAC5B;IAGF,OAAO,aAAa,KAAK,KAAK;GAChC,IACA;EACN;CACF;AACF"}