UNPKG

@mastra/core

Version:
1 lines 3.98 kB
{"version":3,"file":"collect-tool-mocks-6LRmTDZn.cjs","names":[],"sources":["../src/evals/collect-tool-mocks.ts"],"sourcesContent":["import type { DatasetItemToolMock } from '../storage/types';\nimport type { TrajectoryStep } from './types';\n\n/**\n * Sub-agent delegation is exposed to the parent as a tool named `agent-<name>`\n * (see `Agent.listAgentTools`). Its `args.prompt` is free LLM-authored text plus\n * runtime-injected fields (threadId, resourceId, suspendedToolRunId), so strict\n * deep-equality almost never matches on replay. Derive these as `ignore` mocks\n * so the saved mock works out of the box; the user can tighten it to `strict`.\n */\nfunction isSubAgentDelegation(toolName: string): boolean {\n return toolName.startsWith('agent-');\n}\n\n/**\n * Tool-call trajectory steps carry a display label as their `name`, not the bare\n * tool name. Tool spans are named `tool: '<name>'` and MCP tool spans are named\n * `mcp_tool: '<name>' on '<server>'` (see tool-builder). The tool-mock matcher\n * keys on the registered tool name, so we recover `<name>` from the label.\n */\nfunction extractToolName(label: string): string {\n const match = label.match(/^(?:mcp_)?tool:\\s*'(.*?)'/);\n return match?.[1] ?? label;\n}\n\n/**\n * Walk trajectory steps in order, collecting tool/MCP-tool calls as item-level\n * tool mocks. Nested children of non-tool container steps (e.g. workflow steps)\n * are walked depth-first so the mock order mirrors the recorded call order.\n *\n * A tool-call step's OWN children are NOT collected: for a delegated sub-agent,\n * those children are the sub-agent's internal tool calls (e.g. `lookupBalance`\n * under `agent-balanceAgent`). Those run inside the sub-agent and never reach\n * the target agent's tool-mock matcher, so a mock for them can never be served.\n * We only collect top-level calls the target agent itself makes — including the\n * sub-agent delegation call, which mocks the sub-agent's whole response.\n */\nexport function collectToolMocks(steps: TrajectoryStep[] | undefined): DatasetItemToolMock[] {\n return collectToolMocksInto(steps, []);\n}\n\nfunction collectToolMocksInto(steps: TrajectoryStep[] | undefined, acc: DatasetItemToolMock[]): DatasetItemToolMock[] {\n if (!steps) return acc;\n for (const step of steps) {\n const isToolCall = step.stepType === 'tool_call' || step.stepType === 'mcp_tool_call';\n if (isToolCall && step.name) {\n const toolName = extractToolName(step.name);\n const toolArgs = 'toolArgs' in step ? step.toolArgs : undefined;\n const toolResult = 'toolResult' in step ? step.toolResult : undefined;\n acc.push({\n toolName,\n args: toolArgs ?? {},\n output: toolResult,\n // Sub-agent delegation args are LLM-authored + runtime-injected; default\n // to ignore-args matching so the saved mock matches on replay.\n ...(isSubAgentDelegation(toolName) ? { matchArgs: 'ignore' as const } : {}),\n });\n }\n // Skip a tool call's own children (sub-agent internals); only recurse into\n // non-tool container steps to preserve nested top-level call order.\n if (!isToolCall && step.children?.length) {\n collectToolMocksInto(step.children, acc);\n }\n }\n return acc;\n}\n"],"mappings":";;;;;;;;AAUA,SAAS,qBAAqB,UAA2B;CACvD,OAAO,SAAS,WAAW,QAAQ;AACrC;;;;;;;AAQA,SAAS,gBAAgB,OAAuB;CAE9C,OADc,MAAM,MAAM,2BACf,CAAC,GAAG,MAAM;AACvB;;;;;;;;;;;;;AAcA,SAAgB,iBAAiB,OAA4D;CAC3F,OAAO,qBAAqB,OAAO,CAAC,CAAC;AACvC;AAEA,SAAS,qBAAqB,OAAqC,KAAmD;CACpH,IAAI,CAAC,OAAO,OAAO;CACnB,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,aAAa,KAAK,aAAa,eAAe,KAAK,aAAa;EACtE,IAAI,cAAc,KAAK,MAAM;GAC3B,MAAM,WAAW,gBAAgB,KAAK,IAAI;GAC1C,MAAM,WAAW,cAAc,OAAO,KAAK,WAAW,KAAA;GACtD,MAAM,aAAa,gBAAgB,OAAO,KAAK,aAAa,KAAA;GAC5D,IAAI,KAAK;IACP;IACA,MAAM,YAAY,CAAC;IACnB,QAAQ;IAGR,GAAI,qBAAqB,QAAQ,IAAI,EAAE,WAAW,SAAkB,IAAI,CAAC;GAC3E,CAAC;EACH;EAGA,IAAI,CAAC,cAAc,KAAK,UAAU,QAChC,qBAAqB,KAAK,UAAU,GAAG;CAE3C;CACA,OAAO;AACT"}