{"version":3,"file":"mastra-CSCQQcep.mjs","names":[],"sources":["../src/utils.ts","../src/mastra.ts"],"sourcesContent":["import type {\n  InputContent,\n  InputContentDataSource,\n  InputContentUrlSource,\n  Message,\n} from \"@ag-ui/client\";\nimport { AbstractAgent } from \"@ag-ui/client\";\nimport { MastraClient } from \"@mastra/client-js\";\nimport type { Mastra } from \"@mastra/core\";\nimport type { CoreMessage } from \"@mastra/core/llm\";\nimport { Agent as LocalMastraAgent } from \"@mastra/core/agent\";\nimport { RequestContext } from \"@mastra/core/request-context\";\nimport { MastraAgent, MastraTracingOptions } from \"./mastra\";\n\n/**\n * CoreMessage extended with an optional `id` field.\n * Mastra's `inputToMastraDBMessage` checks `\"id\" in message` at runtime\n * and preserves it when present, but the upstream AI SDK type doesn't\n * declare the field. This type makes the pass-through explicit.\n * Ref: https://github.com/mastra-ai/mastra/blob/13f46064564fc4aee14aa11878f9352d79f4efc4/packages/core/src/agent/message-list/conversion/input-converter.ts#L79\n */\ntype CoreMessageWithId = CoreMessage & { id?: string };\n\nfunction mediaSourceToUrl(\n  source: InputContentDataSource | InputContentUrlSource,\n): string {\n  if (source.type === \"data\") {\n    return `data:${source.mimeType};base64,${source.value}`;\n  }\n  return source.value;\n}\n\nconst toMastraTextContent = (content: Message[\"content\"]): string => {\n  if (!content) {\n    return \"\";\n  }\n\n  if (typeof content === \"string\") {\n    return content;\n  }\n\n  if (!Array.isArray(content)) {\n    return \"\";\n  }\n\n  type TextInput = Extract<InputContent, { type: \"text\" }>;\n\n  const textParts = content\n    .filter((part): part is TextInput => part.type === \"text\")\n    .map((part: TextInput) => part.text.trim())\n    .filter(Boolean);\n\n  return textParts.join(\"\\n\");\n};\n\nconst toMastraContent = (content: Message[\"content\"]): string | any[] => {\n  if (!content) {\n    return \"\";\n  }\n\n  if (typeof content === \"string\") {\n    return content;\n  }\n\n  if (!Array.isArray(content)) {\n    return \"\";\n  }\n\n  // Convert content parts to Mastra format\n  const parts: any[] = [];\n  for (const part of content) {\n    switch (part.type) {\n      case \"text\":\n        parts.push({ type: \"text\", text: part.text });\n        break;\n      case \"image\":\n        parts.push({ type: \"image\", image: mediaSourceToUrl(part.source) });\n        break;\n      case \"audio\":\n      case \"video\":\n      case \"document\":\n        parts.push({\n          type: \"file\",\n          data: mediaSourceToUrl(part.source),\n          mimeType: part.source.mimeType ?? \"application/octet-stream\",\n        });\n        break;\n      case \"binary\": {\n        // Deprecated BinaryInputContent\n        const binaryPart = part as Extract<InputContent, { type: \"binary\" }>;\n        if (binaryPart.url) {\n          parts.push({ type: \"image\", image: binaryPart.url });\n        } else if (binaryPart.data && binaryPart.mimeType) {\n          parts.push({\n            type: \"image\",\n            image: `data:${binaryPart.mimeType};base64,${binaryPart.data}`,\n          });\n        } else {\n          console.warn(\n            \"[toMastraContent] Dropping BinaryInputContent: no url or data provided\",\n          );\n        }\n        break;\n      }\n      default:\n        console.warn(\n          `[toMastraContent] Unknown content type \"${part.type}\"; skipping`,\n        );\n        break;\n    }\n  }\n  return parts;\n};\n\nexport function convertAGUIMessagesToMastra(\n  messages: Message[],\n  // Messages to resolve a tool message's toolName against. Defaults to\n  // `messages`, but callers that send only a diff (the new turn) must pass the\n  // full incoming history here: a tool-result's matching assistant tool-call\n  // may have been filtered out of `messages`, and resolving toolName to\n  // \"unknown\" makes Mastra store a broken tool result (the model then re-calls).\n  lookupMessages: Message[] = messages,\n): CoreMessageWithId[] {\n  // Preserve AG-UI message IDs on the CoreMessage objects (see CoreMessageWithId).\n  // Mastra's AIV4Adapter.fromCoreMessage reads `id` when present, which enables\n  // Mastra's MessageHistory processor to deduplicate re-sent history:\n  //   - processInput filters historical messages whose IDs match the input IDs\n  //   - storage.saveMessages upserts by ID, so re-sent history won't duplicate\n  // The `id` key is omitted when undefined so it doesn't defeat Mastra's\n  // `\"id\" in message` check.\n  const result: CoreMessageWithId[] = [];\n\n  for (const message of messages) {\n    if (message.role === \"assistant\") {\n      const assistantContent = toMastraTextContent(message.content);\n      const parts: any[] = [];\n      if (assistantContent) {\n        parts.push({ type: \"text\", text: assistantContent });\n      }\n      for (const toolCall of message.toolCalls ?? []) {\n        parts.push({\n          type: \"tool-call\",\n          toolCallId: toolCall.id,\n          toolName: toolCall.function.name,\n          args: JSON.parse(toolCall.function.arguments),\n        });\n      }\n      result.push({\n        ...(message.id !== undefined ? { id: message.id } : {}),\n        role: \"assistant\",\n        content: parts,\n      } as CoreMessage);\n    } else if (message.role === \"user\") {\n      const userContent = toMastraContent(message.content);\n      result.push({\n        ...(message.id !== undefined ? { id: message.id } : {}),\n        role: \"user\",\n        content: userContent,\n      } as CoreMessage);\n    } else if (message.role === \"tool\") {\n      let toolName = \"unknown\";\n      for (const msg of lookupMessages) {\n        if (msg.role === \"assistant\") {\n          for (const toolCall of msg.toolCalls ?? []) {\n            if (toolCall.id === message.toolCallId) {\n              toolName = toolCall.function.name;\n              break;\n            }\n          }\n        }\n      }\n      result.push({\n        ...(message.id !== undefined ? { id: message.id } : {}),\n        role: \"tool\",\n        content: [\n          {\n            type: \"tool-result\",\n            toolCallId: message.toolCallId,\n            toolName: toolName,\n            result: message.content,\n          },\n        ],\n      } as CoreMessage);\n    }\n  }\n\n  return result;\n}\n\nexport interface GetRemoteAgentsOptions {\n  mastraClient: MastraClient;\n  resourceId: string;\n  /**\n   * Surface Mastra Observational Memory (OM) background work as AG-UI activity\n   * events (activityType `mastra-observational-memory`). `true` enables it for\n   * every agent; pass an array of agent ids to enable it only for those.\n   * Default OFF. The remote agent must have OM enabled on its Memory server-side\n   * — this only controls whether the bridge surfaces the `data-om-*` chunks it\n   * streams. See `MastraAgentConfig.observationalMemory`.\n   */\n  observationalMemory?: boolean | string[];\n  /** Mastra tracing options forwarded to each run. See MastraAgentConfig.tracingOptions. */\n  tracingOptions?: MastraTracingOptions;\n}\n\nexport async function getRemoteAgents({\n  mastraClient,\n  resourceId,\n  observationalMemory,\n  tracingOptions,\n}: GetRemoteAgentsOptions): Promise<Record<string, AbstractAgent>> {\n  const agents = await mastraClient.listAgents();\n\n  const wantsObservationalMemory = (agentId: string): boolean =>\n    observationalMemory === true ||\n    (Array.isArray(observationalMemory) &&\n      observationalMemory.includes(agentId));\n\n  return Object.entries(agents).reduce(\n    (acc, [agentId]) => {\n      const agent = mastraClient.getAgent(agentId);\n\n      acc[agentId] = new MastraAgent({\n        agentId,\n        agent,\n        resourceId,\n        // Enables syncing input.state into the remote server's working memory\n        // (client -> agent shared state), mirroring the local path.\n        remoteClient: mastraClient,\n        observationalMemory: wantsObservationalMemory(agentId)\n          ? true\n          : undefined,\n        tracingOptions,\n      });\n\n      return acc;\n    },\n    {} as Record<string, AbstractAgent>,\n  );\n}\n\nexport interface GetLocalAgentsOptions {\n  mastra: Mastra;\n  resourceId: string;\n  requestContext?: RequestContext;\n  /**\n   * Enable Mastra's `untilIdle` run mode (background-task lifecycle piped into\n   * the run's fullStream). `true` enables it for every agent; pass an array of\n   * agent ids to enable it only for those. See `MastraAgentConfig.untilIdle`.\n   */\n  untilIdle?: boolean | string[];\n  /**\n   * Surface Mastra Observational Memory (OM) background work as AG-UI activity\n   * events (activityType `mastra-observational-memory`). `true` enables it for\n   * every agent; pass an array of agent ids to enable it only for those.\n   * Default OFF. See `MastraAgentConfig.observationalMemory`.\n   */\n  observationalMemory?: boolean | string[];\n  /** Mastra tracing options forwarded to each run. See MastraAgentConfig.tracingOptions. */\n  tracingOptions?: MastraTracingOptions;\n}\n\nexport function getLocalAgents({\n  mastra,\n  resourceId,\n  requestContext,\n  untilIdle,\n  observationalMemory,\n  tracingOptions,\n}: GetLocalAgentsOptions): Record<string, AbstractAgent> {\n  const agents = mastra.listAgents() || {};\n\n  const wantsUntilIdle = (agentId: string): boolean =>\n    untilIdle === true ||\n    (Array.isArray(untilIdle) && untilIdle.includes(agentId));\n\n  const wantsObservationalMemory = (agentId: string): boolean =>\n    observationalMemory === true ||\n    (Array.isArray(observationalMemory) &&\n      observationalMemory.includes(agentId));\n\n  const agentAGUI = Object.entries(agents).reduce(\n    (acc, [agentId, agent]) => {\n      acc[agentId] = new MastraAgent({\n        agentId,\n        agent,\n        resourceId,\n        requestContext,\n        untilIdle: wantsUntilIdle(agentId) ? true : undefined,\n        observationalMemory: wantsObservationalMemory(agentId)\n          ? true\n          : undefined,\n        tracingOptions,\n      });\n      return acc;\n    },\n    {} as Record<string, AbstractAgent>,\n  );\n\n  return agentAGUI;\n}\n\nexport interface GetLocalAgentOptions {\n  mastra: Mastra;\n  agentId: string;\n  resourceId: string;\n  requestContext?: RequestContext;\n  /** Mastra tracing options forwarded to the run. See MastraAgentConfig.tracingOptions. */\n  tracingOptions?: MastraTracingOptions;\n}\n\nexport function getLocalAgent({\n  mastra,\n  agentId,\n  resourceId,\n  requestContext,\n  tracingOptions,\n}: GetLocalAgentOptions) {\n  const agent = mastra.getAgent(agentId);\n  if (!agent) {\n    throw new Error(`Agent ${agentId} not found`);\n  }\n  return new MastraAgent({\n    agentId,\n    agent,\n    resourceId,\n    requestContext,\n    tracingOptions,\n  }) as AbstractAgent;\n}\n\nexport interface GetNetworkOptions {\n  mastra: Mastra;\n  networkId: string;\n  resourceId: string;\n  requestContext?: RequestContext;\n  /** Mastra tracing options forwarded to the run. See MastraAgentConfig.tracingOptions. */\n  tracingOptions?: MastraTracingOptions;\n}\n\nexport function getNetwork({\n  mastra,\n  networkId,\n  resourceId,\n  requestContext,\n  tracingOptions,\n}: GetNetworkOptions) {\n  const network = mastra.getAgent(networkId);\n  if (!network) {\n    throw new Error(`Network ${networkId} not found`);\n  }\n  return new MastraAgent({\n    agentId: network.name!,\n    agent: network as unknown as LocalMastraAgent,\n    resourceId,\n    requestContext,\n    tracingOptions,\n  }) as AbstractAgent;\n}\n","import type {\n  ActivityDeltaEvent,\n  ActivitySnapshotEvent,\n  AgentConfig,\n  BaseEvent,\n  CustomEvent,\n  Interrupt,\n  Message,\n  ReasoningStartEvent,\n  ReasoningMessageStartEvent,\n  ReasoningMessageContentEvent,\n  ReasoningMessageEndEvent,\n  ReasoningEndEvent,\n  RunAgentInput,\n  RunFinishedEvent,\n  RunFinishedInterruptOutcome,\n  RunStartedEvent,\n  StateDeltaEvent,\n  StateSnapshotEvent,\n  TextMessageChunkEvent,\n  ToolCallArgsEvent,\n  ToolCallEndEvent,\n  ToolCallResultEvent,\n  ToolCallStartEvent,\n} from \"@ag-ui/client\";\nimport { AbstractAgent, EventType } from \"@ag-ui/client\";\nimport type { Agent as LocalMastraAgent } from \"@mastra/core/agent\";\nimport { RequestContext } from \"@mastra/core/request-context\";\nimport { randomUUID } from \"@ag-ui/client\";\nimport jsonpatch from \"fast-json-patch\";\nimport { parsePartialJson } from \"@ai-sdk/ui-utils\";\nimport { Observable } from \"rxjs\";\nimport type { MastraClient } from \"@mastra/client-js\";\nimport {\n  convertAGUIMessagesToMastra,\n  GetLocalAgentsOptions,\n  getLocalAgents,\n  getRemoteAgents,\n  GetRemoteAgentsOptions,\n  GetLocalAgentOptions,\n  getLocalAgent,\n  GetNetworkOptions,\n  getNetwork,\n} from \"./utils\";\nimport { planA2UIInjection, type A2UIInjectConfig } from \"./a2ui-tool\";\n\nconst { compare } = jsonpatch;\n\ntype RemoteMastraAgent = ReturnType<MastraClient[\"getAgent\"]>;\n\n/**\n * AG-UI `activityType` used for Mastra Background Tasks. Background work\n * (a tool with `background: { enabled: true }`) runs out-of-band while the\n * agent conversation continues; the bridge surfaces its lifecycle as AG-UI\n * ACTIVITY_SNAPSHOT / ACTIVITY_DELTA events so the UI can render it distinctly\n * from normal streamed responses. Renderers register against this string via\n * CopilotKit's `renderActivityMessages` prop.\n *\n * The activity `content` shape (one activity per Mastra task; `messageId` is\n * the Mastra `taskId`):\n *\n *   {\n *     taskId: string;        // Mastra background task id (== activity messageId)\n *     toolName: string;      // the backgrounded tool\n *     toolCallId: string;    // originating tool call\n *     status: \"started\" | \"running\" | \"suspended\" | \"resumed\"\n *           | \"completed\" | \"failed\" | \"cancelled\";\n *     args?: Record<string, unknown>;  // tool args, once running\n *     outputs: unknown[];    // streamed tool-output chunks, appended in order\n *     elapsedMs?: number;    // wall-clock since dispatch, ticked by progress\n *     result?: unknown;      // final result on completion\n *     error?: string;        // message on failure\n *     suspendPayload?: unknown; // data passed to suspend(), when suspended\n *     startedAt?: string;    // ISO timestamp\n *     completedAt?: string;  // ISO timestamp\n *   }\n *\n * This shape is a sensible default proposed by the AG-UI bridge; it is intended\n * to be co-designed with Mastra (see OSS-93) and may evolve.\n */\nexport const MASTRA_BACKGROUND_TASK_ACTIVITY_TYPE = \"mastra-background-task\";\n\n/**\n * Tool name(s) Mastra uses for the built-in working-memory update tool. When an\n * agent has working memory enabled, Mastra injects this tool; the model calls\n * it mid-run with the new working-memory content. The bridge maps those calls\n * to AG-UI STATE_DELTA (see createChunkProcessor). Mastra registers it under\n * the key `updateWorkingMemory` (the name that appears on the stream chunk;\n * `UPDATE_WORKING_MEMORY_TOOL_NAME` in @mastra/core) with tool id\n * `update-working-memory` — match both so the mapping is robust to either.\n */\nconst WORKING_MEMORY_TOOL_NAMES = new Set([\n  \"updateWorkingMemory\",\n  \"update-working-memory\",\n]);\n\n/**\n * Deep-merges a working-memory update onto the existing state, mirroring\n * @mastra/core's `deepMergeWorkingMemory` (the semantics schema/json working\n * memory applies to partial updates): nested objects recurse, arrays are\n * replaced wholesale, an explicit `null` deletes the key, scalars overwrite.\n * Replicated here so the bridge can compute the post-update state — and thus an\n * accurate RFC-6902 delta — synchronously, without a mid-stream memory re-read.\n */\nfunction deepMergeWorkingMemory(\n  existing: Record<string, any> | undefined,\n  update: Record<string, any>,\n): Record<string, any> {\n  if (\n    !update ||\n    typeof update !== \"object\" ||\n    Object.keys(update).length === 0\n  ) {\n    return existing && typeof existing === \"object\" ? { ...existing } : {};\n  }\n  if (!existing || typeof existing !== \"object\") {\n    return update;\n  }\n  const result: Record<string, any> = { ...existing };\n  for (const key of Object.keys(update)) {\n    const updateValue = update[key];\n    const existingValue = result[key];\n    if (updateValue === null) {\n      delete result[key];\n    } else if (Array.isArray(updateValue)) {\n      result[key] = updateValue;\n    } else if (\n      typeof updateValue === \"object\" &&\n      updateValue !== null &&\n      typeof existingValue === \"object\" &&\n      existingValue !== null &&\n      !Array.isArray(existingValue)\n    ) {\n      result[key] = deepMergeWorkingMemory(existingValue, updateValue);\n    } else {\n      result[key] = updateValue;\n    }\n  }\n  return result;\n}\n\n/**\n * Parses the `memory` argument of an `updateWorkingMemory` tool call into a\n * plain object suitable for structured state diffing. The arg is a JSON string\n * for schema/json working memory (the state-rendering case). Returns `undefined`\n * for markdown-template working memory (non-JSON string) or any non-object\n * payload — the caller then skips STATE_DELTA and relies on the run-end\n * STATE_SNAPSHOT.\n */\nfunction parseWorkingMemoryUpdate(\n  args: Record<string, any> | undefined,\n): Record<string, any> | undefined {\n  const raw = args?.memory ?? args;\n  let value: unknown = raw;\n  if (typeof raw === \"string\") {\n    try {\n      value = JSON.parse(raw);\n    } catch {\n      return undefined;\n    }\n  }\n  if (value && typeof value === \"object\" && !Array.isArray(value)) {\n    return value as Record<string, any>;\n  }\n  return undefined;\n}\n\n/**\n * Best-effort parse of the PARTIAL, still-streaming raw tool-input text of an\n * `updateWorkingMemory` call — the accumulated `tool-call-delta` fragments, e.g.\n * `{\"memory\":\"{\\\"recipe\\\":{\\\"title\\\":\\\"Sp`. Uses `parsePartialJson` (repairs\n * truncated JSON) twice: once for the outer `{ memory }` envelope, then for the\n * inner `memory` payload (a nested JSON string for schema/json working memory).\n * Returns the parseable prefix as an object so the bridge can emit an\n * incremental STATE_DELTA as the model writes the update; `undefined` while the\n * text is not yet a usable object (or is markdown-template working memory).\n */\nfunction parseStreamingWorkingMemoryUpdate(\n  argsText: string,\n): Record<string, any> | undefined {\n  if (!argsText) return undefined;\n  const outer = parsePartialJson(argsText);\n  const outerVal = outer.value;\n  if (!outerVal || typeof outerVal !== \"object\" || Array.isArray(outerVal)) {\n    return undefined;\n  }\n  const mem = (outerVal as Record<string, any>).memory;\n  if (mem == null) return undefined;\n  if (typeof mem === \"object\" && !Array.isArray(mem)) {\n    return mem as Record<string, any>;\n  }\n  if (typeof mem === \"string\") {\n    const inner = parsePartialJson(mem);\n    const innerVal = inner.value;\n    if (innerVal && typeof innerVal === \"object\" && !Array.isArray(innerVal)) {\n      return innerVal as Record<string, any>;\n    }\n  }\n  return undefined;\n}\n\n// Shape of a remote resume response. Newer @mastra/client-js (>= the release\n// that added agent suspend/resume) exposes `resumeStream` on the remote Agent\n// resource; it returns a Response augmented with `processDataStream` — the same\n// callback-based stream the remote `.stream()` path consumes. We type it\n// structurally (not against the installed client-js) so the bridge compiles\n// against older client-js builds that predate `resumeStream`; the capability is\n// probed at runtime via `hasRemoteResume` before use.\ntype RemoteResumeResponse = {\n  processDataStream?: (args: {\n    onChunk: (chunk: any) => void | Promise<void>;\n  }) => Promise<void>;\n};\n\ninterface RemoteResumableAgent {\n  resumeStream(\n    resumeData: unknown,\n    options: Record<string, unknown>,\n  ): Promise<RemoteResumeResponse | null | undefined>;\n}\n\n/**\n * Walks `finish.payload.response.uiMessages` to pull the final assistant text\n * after Mastra's output processors have run.\n *\n * Returns `undefined` when:\n *   - `uiMessages` is absent (older Mastra, or a non-finish chunk),\n *   - no assistant message is present,\n *   - the assistant message contains no text parts (tool-only response),\n * so callers can fall back to the buffered raw text.\n *\n * Accepts both string content and array-of-parts content shapes (Mastra's\n * UIMessage tolerates either depending on how the agent assembled its\n * response).\n */\nfunction extractLastAssistantText(uiMessages: unknown): string | undefined {\n  if (!Array.isArray(uiMessages)) return undefined;\n  for (let i = uiMessages.length - 1; i >= 0; i--) {\n    const message = uiMessages[i];\n    if (!message || (message as { role?: string }).role !== \"assistant\") {\n      continue;\n    }\n    const content = (message as { content?: unknown }).content;\n    if (typeof content === \"string\") {\n      return content.length > 0 ? content : undefined;\n    }\n    if (Array.isArray(content)) {\n      const text = content\n        .filter(\n          (part: any): part is { type: \"text\"; text: string } =>\n            part?.type === \"text\" && typeof part.text === \"string\",\n        )\n        .map((part) => part.text)\n        .join(\"\");\n      return text.length > 0 ? text : undefined;\n    }\n    // Some UIMessage shapes expose pre-joined text via a `text` field.\n    const text = (message as { text?: unknown }).text;\n    if (typeof text === \"string\" && text.length > 0) return text;\n    return undefined;\n  }\n  return undefined;\n}\n\n/**\n * AG-UI `activityType` used for Mastra Observational Memory (OM). OM is a\n * Mastra memory feature the developer enables on THEIR agent\n * (`new Memory({ options: { observationalMemory: true } })`). When enabled,\n * Mastra runs Observer/Reflector agents out of band that read the conversation,\n * compress it into observations, and activate them into the context window. OM\n * surfaces this background work on the agent's `fullStream` as typed\n * `data-om-*` chunks (see `@mastra/core/channels/om` + the `@mastra/memory` OM\n * processor). The bridge maps the substantive lifecycle of those chunks to\n * AG-UI ACTIVITY_SNAPSHOT / ACTIVITY_DELTA events so the UI can render the\n * \"agent is observing / reflecting / compressing memory\" activity distinctly\n * from the streamed response. Renderers register against this string via\n * CopilotKit's `renderActivityMessages` prop.\n *\n * Surfacing is OPT-IN per agent (`MastraAgentConfig.observationalMemory`,\n * default OFF) — OM is the developer's own opt-in, so the bridge does not\n * announce it unless asked. With the toggle OFF the `data-om-*` chunks are\n * swallowed silently (they carry no assistant output), so an OM-enabled agent\n * still streams cleanly through the bridge and emits no activity.\n *\n * The activity `content` shape (one activity per OM cycle; `messageId` is the\n * Mastra `cycleId`). In the async path the buffering cycle and its activation\n * share one `cycleId`, so they advance a single activity\n * running -> completed -> activated:\n *\n *   {\n *     cycleId: string;        // Mastra OM cycle id (== activity messageId)\n *     operationType: \"observation\" | \"reflection\";\n *     phase: \"observation\" | \"buffering\" | \"activation\";\n *     status: \"running\" | \"completed\" | \"failed\" | \"activated\";\n *     threadId?: string;\n *     recordId?: string;\n *     observations?: string;  // the observation/reflection summary text\n *     currentTask?: string;       // task the Observer extracted\n *     suggestedResponse?: string; // suggestion the Observer extracted\n *     tokensToObserve?: number;   // observation/buffering: tokens in this batch\n *     tokensObserved?: number;    // observation: tokens observed\n *     bufferedTokens?: number;    // buffering: resulting tokens after compress\n *     observationTokens?: number; // resulting observation tokens\n *     tokensActivated?: number;   // activation: message tokens activated\n *     chunksActivated?: number;   // activation: buffered chunks activated\n *     messagesActivated?: number; // activation: messages observed via activation\n *     generationCount?: number;   // activation: reflection generation count\n *     triggeredBy?: \"threshold\" | \"ttl\" | \"provider_change\";\n *     durationMs?: number;\n *     startedAt?: string;     // ISO timestamp\n *     completedAt?: string;   // ISO timestamp\n *     error?: string;         // message on failure\n *   }\n *\n * This shape is a sensible default proposed by the AG-UI bridge; it mirrors the\n * background-task activity shape and may evolve alongside Mastra's OM data\n * parts (see OSS-92).\n */\nexport const MASTRA_OBSERVATIONAL_MEMORY_ACTIVITY_TYPE =\n  \"mastra-observational-memory\";\n\n/**\n * Mastra tracing options threaded into the underlying `agent.stream(...)` /\n * `agent.resumeStream(...)` call. Typed structurally (not against\n * `@mastra/core`) so the bridge compiles on any supported core in the peer\n * range — cores predating observability v-next simply ignore an unknown\n * `tracingOptions` key. Mirrors Mastra's `TracingOptions`:\n *   - `traceId`: a caller-chosen trace id to anchor the run under (lets a client\n *     self-assign a trace it already knows, e.g. to attach feedback later).\n *   - `metadata`: arbitrary key/values attached to the run's root trace span.\n */\nexport interface MastraTracingOptions {\n  traceId?: string;\n  metadata?: Record<string, unknown>;\n}\n\nexport interface MastraAgentConfig extends AgentConfig {\n  agent: LocalMastraAgent | RemoteMastraAgent;\n  resourceId?: string;\n  requestContext?: RequestContext;\n  /**\n   * Forward Mastra tracing options into the run's `agent.stream(...)` (and the\n   * resume path). Chiefly lets a caller inject a self-chosen `traceId` so the\n   * Mastra execution trace is anchored to an id the client already knows,\n   * enabling trace-centric feedback/scores (`createFeedback({ traceId })`).\n   *\n   * NOT per-run: this config (and any `traceId` in it) is stored once on the\n   * agent instance and reused verbatim for EVERY run of that instance. So a\n   * config-level `tracingOptions.traceId` is applied to every run, not to a\n   * single run, meaning a caller who sets a fixed `traceId` here and reuses one\n   * `MastraAgent` across many runs collapses all those runs onto a single trace.\n   * Callers who want a distinct traceId per run should construct a fresh agent\n   * per run (the `registerCopilotKit` / `getLocalAgents` path already does this,\n   * since agents are constructed inside the per-request route handler).\n   *\n   * The OUTBOUND execution traceId surfaced on `RUN_FINISHED.result` IS per-run:\n   * when no inbound `traceId` is set, Mastra generates one for that run, which\n   * the bridge surfaces back to the client (see {@link makeRunFinishedEvent}).\n   * Inert on cores that predate Mastra observability v-next.\n   */\n  tracingOptions?: MastraTracingOptions;\n  /**\n   * Opt into Mastra's `untilIdle` run mode (local agents only). When set, the\n   * bridge passes `untilIdle` to `agent.stream(...)`, which subscribes to the\n   * background-task manager for the run's memory scope and pipes the task\n   * lifecycle chunks (`background-task-running` / `-output` / `-completed` /\n   * `-failed` / …) into the SAME `fullStream`, re-entering the agentic loop so\n   * the model reacts to the result in the same run. Without it, only\n   * `background-task-started` reaches the run stream and completion is\n   * delivered out of band. Requires a configured storage backend + a memory\n   * scope (Mastra falls through to the default stream otherwise). `true` uses\n   * Mastra's default idle timeout; pass `{ maxIdleMs }` to override.\n   *\n   * CAVEAT (verified against @mastra/core 1.47.0): in practice only\n   * `background-task-started` + `-running` reach the piped stream;\n   * `background-task-completed` does NOT arrive, so the run idles out without a\n   * completion and the activity stays \"running\". Treat this as the forward-\n   * looking hook for when Mastra delivers terminal lifecycle on the stream;\n   * leave it OFF until then (its only effect today is an idle hold with no\n   * completion payload).\n   */\n  untilIdle?: boolean | { maxIdleMs?: number };\n  /**\n   * Terminate interrupted runs with the AG-UI structured outcome\n   * `RUN_FINISHED.outcome={ type: \"interrupt\", interrupts: [...] }`, mapping each\n   * Mastra tool suspend to an `Interrupt`.\n   *\n   * Default **true** (opt-out). The structured outcome is the canonical AG-UI\n   * interrupt path; clients on the canonical resume protocol drive resume via\n   * `RunAgentInput.resume`, which the bridge consumes here.\n   *\n   * REQUIRES a CopilotKit client **>= 1.61.2** (the release that reads\n   * `outcome:\"interrupt\"` and resumes via `RunAgentInput.resume`). On older\n   * clients (<= 1.61.1, incl. 1.60.1/1.61.0) the client records the structured\n   * interrupt but never addresses it on resume, stranding the run with\n   * `Thread has N pending interrupt(s) not addressed by resume`. **If you target\n   * a client below 1.61.2, set this to `false`** to fall back to the legacy\n   * `on_interrupt`-only path. (The bridge can't detect the client version — the\n   * CopilotKit client is the consumer app's dependency, not this package's —\n   * so the floor is a documented requirement, not an enforced one.)\n   *\n   * Independent of the legacy `CUSTOM(name=\"on_interrupt\")` event, which is\n   * always emitted (backward compat). When on, BOTH the legacy event and the\n   * structured outcome are emitted; when off, only the legacy event plus a plain\n   * `RUN_FINISHED` — exactly as before this flag existed. Resume itself consumes\n   * BOTH the legacy `forwardedProps.command.resume` and the standard\n   * `RunAgentInput.resume` channels regardless of this flag.\n   */\n  emitInterruptOutcome?: boolean;\n  /**\n   * A2UI auto-injection config (local agents). When the runtime/middleware\n   * forwards `injectA2UITool`, the bridge injects a backend-owned `generate_a2ui`\n   * tool (recovery + subagent) per run so the developer wires nothing — the\n   * easy-devex path. Set `injectA2UITool:false` here to force it off; set\n   * `model`/`defaultCatalogId`/`guidelines`/`recovery` to customize. A `model` is\n   * required for auto-inject unless one can be inferred from the wrapped agent.\n   */\n  a2ui?: A2UIInjectConfig;\n  /**\n   * For REMOTE agents only: the `MastraClient` used to reach the agent. When\n   * set, the bridge syncs `input.state` into the remote server's working memory\n   * (via `client.updateWorkingMemory`) before streaming, so a client-side edit\n   * to shared state reaches a remote agent the same way it does a local one.\n   * Set by `getRemoteAgents`; unused for local agents (which sync through their\n   * own `Memory` instance).\n   */\n  remoteClient?: MastraClient;\n  /**\n   * When the configured agent uses `outputProcessors` that rewrite assistant\n   * text (e.g. character-voice transforms, redaction, format normalization),\n   * the processor-modified text is available only on the `finish` /\n   * `step-finish` chunk's `payload.response.uiMessages` — surfaced upstream in\n   * https://github.com/mastra-ai/mastra/pull/11549 to expose processor output\n   * through streaming.\n   *\n   * Set to `true` to buffer intermediate `text-delta` chunks and emit only the\n   * processor-modified text extracted from that boundary's `uiMessages`. When a\n   * boundary has no usable `uiMessages` (older Mastra, or processors that did\n   * not modify text), the buffered raw text is emitted on the terminal `finish`\n   * as a fallback so no text is ever dropped.\n   *\n   * Default: `false` (current behavior — text-delta chunks stream to the client\n   * in real time, processor rewrites are not surfaced).\n   *\n   * Trade-off: enabling this loses real-time text streaming — the final\n   * assistant text appears at once after the agent's last step. Required when\n   * downstream consumers (e.g. CopilotKit chat UI) must render the\n   * post-processor text rather than the raw LLM output.\n   *\n   * Tracking: https://github.com/ag-ui-protocol/ag-ui/issues/1726\n   */\n  useProcessedFinalText?: boolean;\n  /**\n   * Surface Mastra Observational Memory (OM) background work as AG-UI activity\n   * events (activityType `mastra-observational-memory`). Default OFF.\n   *\n   * OM is the developer's own opt-in (enabled on their Mastra `Memory`), so the\n   * bridge stays silent about it unless explicitly asked. When `true`, the\n   * bridge maps the OM lifecycle chunks Mastra streams on `fullStream`\n   * (`data-om-observation-*`, `data-om-buffering-*`, `data-om-activation`) to\n   * ACTIVITY_SNAPSHOT / ACTIVITY_DELTA events. When `false`/unset, those chunks\n   * are swallowed (no activity emitted) but the stream still flows cleanly.\n   *\n   * Note: this toggle does NOT enable OM — that is configured on the agent's\n   * Memory. It only controls whether the bridge surfaces OM's activity.\n   */\n  observationalMemory?: boolean;\n}\n\ninterface MastraAgentStreamOptions {\n  /**\n   * Called when Mastra announces the persisted message id for the upcoming\n   * step (the `start` / `step-start` chunk's `messageId`). The bridge adopts\n   * this id for the assistant message it streams, so the id the client sees\n   * equals the id Mastra stores. Without this the bridge would mint its own\n   * id, and re-sent history on the next turn would not match storage, causing\n   * Mastra to persist the assistant message again (duplicate history).\n   */\n  onMessageId?: (messageId: string) => void;\n  onTextPart?: (text: string) => void;\n  onReasoningStart?: () => void;\n  onReasoningPart?: (text: string) => void;\n  onReasoningEnd?: () => void;\n  onFinishMessagePart?: () => void;\n  /** Emit TOOL_CALL_START. Fired once per tool call, before any args. */\n  onToolCallStart?: (streamPart: {\n    toolCallId: string;\n    toolName: string;\n  }) => void;\n  /**\n   * Emit a TOOL_CALL_ARGS delta. The bridge streams these incrementally as\n   * Mastra emits `tool-call-delta` chunks (raw JSON-text fragments), or emits\n   * a single full-args delta on the fall-back path (older @mastra/core that\n   * only emits the final `tool-call` chunk).\n   */\n  onToolCallArgs?: (streamPart: {\n    toolCallId: string;\n    argsTextDelta: string;\n  }) => void;\n  /** Emit TOOL_CALL_END. Fired once per tool call, after all args. */\n  onToolCallEnd?: (streamPart: { toolCallId: string }) => void;\n  onToolResultPart?: (streamPart: { toolCallId: string; result: any }) => void;\n  onError: (error: Error) => void;\n  /**\n   * Terminate the run with RUN_FINISHED. Receives the Mastra execution traceId\n   * (Mastra observability v-next) when the consumed stream exposed one, so the\n   * bridge can surface it on `RUN_FINISHED.result` (see makeRunFinishedEvent).\n   * traceId is undefined on cores/streams that don't expose one.\n   */\n  onRunFinished?: (traceId?: string) => Promise<void>;\n  onToolSuspended: (payload: {\n    toolCallId: string;\n    toolName: string;\n    suspendPayload: any;\n    args: Record<string, any>;\n    resumeSchema: string;\n    // The runId Mastra associated with the suspended run, taken from the\n    // suspend chunk. Mastra keys the suspended workflow snapshot by this id —\n    // which is NOT necessarily the AG-UI RunAgentInput.runId — so resume must\n    // round-trip THIS value back to `resumeStream({ runId })`. Optional so the\n    // bridge can fall back to the AG-UI runId when a chunk omits it.\n    runId?: string;\n  }) => void;\n  /**\n   * Emit an ACTIVITY_SNAPSHOT for a background task (full initial content).\n   * Called once per task, when the task starts.\n   */\n  onActivitySnapshot?: (snapshot: {\n    messageId: string;\n    activityType: string;\n    content: Record<string, any>;\n  }) => void;\n  /**\n   * Emit an ACTIVITY_DELTA for a background task (RFC 6902 JSON patch against\n   * the prior snapshot/delta content). Called on each subsequent lifecycle\n   * chunk (running, output, progress, completed, failed, cancelled, …).\n   */\n  onActivityDelta?: (delta: {\n    messageId: string;\n    activityType: string;\n    patch: Array<Record<string, any>>;\n  }) => void;\n  /**\n   * Emit a STATE_SNAPSHOT (full shared state). Emitted once per run as the FIRST\n   * working-memory state event, to establish the base the client/runtime patch\n   * against — the AG-UI runtime applies STATE_DELTA from an empty document at\n   * run start, so a leading snapshot is required or the first delta's paths are\n   * unresolvable. Subsequent changes ride STATE_DELTA.\n   */\n  onStateSnapshot?: (snapshot: Record<string, any>) => void;\n  /**\n   * Emit a STATE_DELTA (RFC 6902 JSON patch) when the agent updates its working\n   * memory mid-run. Emitted for every working-memory change AFTER the initial\n   * snapshot, with the patch from the previously-known state to the post-update\n   * state, so shared state renders live as it changes (the run-end\n   * STATE_SNAPSHOT still follows).\n   */\n  onStateDelta?: (delta: Array<Record<string, any>>) => void;\n}\n\nexport class MastraAgent extends AbstractAgent {\n  agent: LocalMastraAgent | RemoteMastraAgent;\n  resourceId?: string;\n  requestContext?: RequestContext;\n  untilIdle?: boolean | { maxIdleMs?: number };\n  observationalMemory?: boolean;\n  tracingOptions?: MastraTracingOptions;\n  public headers?: Record<string, string>;\n  /** See MastraAgentConfig.emitInterruptOutcome. Default true. */\n  emitInterruptOutcome: boolean;\n  /** See MastraAgentConfig.a2ui — A2UI auto-injection config. */\n  a2ui?: A2UIInjectConfig;\n  /** See MastraAgentConfig.remoteClient. Set for remote agents only. */\n  remoteClient?: MastraClient;\n  /** See MastraAgentConfig.useProcessedFinalText. Default false. */\n  useProcessedFinalText: boolean;\n\n  /**\n   * Suffix appended to a turn's base (Mastra-stored) messageId to key the\n   * SEPARATE AG-UI message that carries assistant text streamed AFTER a tool\n   * call in the same turn. See {@link continuationMessageId} and the ordering\n   * note in {@link makeStreamCallbacks}.\n   */\n  private static readonly ASSISTANT_TEXT_CONTINUATION_SUFFIX = \"-agui-text\";\n\n  /**\n   * Deterministic id for the \"trailing text\" continuation message split off a\n   * turn whose tool call already rendered under `baseId`. Deterministic (a pure\n   * function of the stored turn id) so re-sent history dedups: `selectNewMessages`\n   * recomputes it from each stored id and filters the continuation message out,\n   * so the split text is never re-forwarded (and duplicated) on later turns.\n   */\n  private static continuationMessageId(baseId: string): string {\n    return `${baseId}${MastraAgent.ASSISTANT_TEXT_CONTINUATION_SUFFIX}`;\n  }\n\n  constructor(private config: MastraAgentConfig) {\n    const {\n      agent,\n      resourceId,\n      requestContext,\n      untilIdle,\n      tracingOptions,\n      emitInterruptOutcome,\n      a2ui,\n      remoteClient,\n      useProcessedFinalText,\n      observationalMemory,\n      ...rest\n    } = config;\n    super(rest);\n    this.emitInterruptOutcome = emitInterruptOutcome ?? true;\n    this.agent = agent;\n    this.resourceId = resourceId;\n    this.requestContext = requestContext ?? new RequestContext();\n    this.untilIdle = untilIdle;\n    this.a2ui = a2ui;\n    this.remoteClient = remoteClient;\n    this.useProcessedFinalText = useProcessedFinalText ?? false;\n    this.observationalMemory = observationalMemory;\n    this.tracingOptions = tracingOptions;\n  }\n\n  public clone() {\n    const cloned = new MastraAgent(this.config);\n    if (this.headers) {\n      cloned.headers = { ...this.headers };\n    }\n    return cloned;\n  }\n\n  /**\n   * Forwards `input.context` onto the Mastra RequestContext under \"ag-ui\", so a\n   * tool reads it via `requestContext.get(\"ag-ui\").context`. Called on every\n   * entry path (initial stream + both resume paths) so a resumed run forwards\n   * its own context instead of reusing the prior turn's.\n   */\n  private applyInputContext(context: RunAgentInput[\"context\"]): RequestContext {\n    this.requestContext ??= new RequestContext();\n    this.requestContext.set(\"ag-ui\", { context });\n    return this.requestContext;\n  }\n\n  run(input: RunAgentInput): Observable<BaseEvent> {\n    // Fallback id used only until Mastra announces the persisted message id on\n    // the start / step-start chunk (see onMessageId). Adopting Mastra's id\n    // keeps the streamed assistant id equal to the stored id so re-sent history\n    // dedupes instead of duplicating. Remote agents / older Mastra streams that\n    // omit the start messageId keep using this fallback (and the rotation below).\n    let messageId = randomUUID();\n\n    // Tool suspends collected this run, mapped to AG-UI Interrupts. Only\n    // populated when emitInterruptOutcome is on; the terminating RUN_FINISHED\n    // carries them as a structured `outcome` (see makeRunFinishedEvent). The\n    // legacy CUSTOM(on_interrupt) event is emitted regardless (see\n    // onToolSuspended).\n    const pendingInterrupts: Interrupt[] = [];\n\n    return new Observable<BaseEvent>((subscriber) => {\n      const run = async () => {\n        const runStartedEvent: RunStartedEvent = {\n          type: EventType.RUN_STARTED,\n          threadId: input.threadId,\n          runId: input.runId,\n        };\n\n        subscriber.next(runStartedEvent);\n\n        // CopilotKit passes resume data via forwardedProps.command (convention\n        // shared with LangGraph's interrupt bridge). forwardedProps is untyped\n        // (any) — the caller is responsible for shape validation.\n        let forwardedCommand = input.forwardedProps?.command;\n\n        // Standard AG-UI resume channel: clients on the canonical interrupt path\n        // (CopilotKit >= 1.61.2) drive resume through `RunAgentInput.resume`\n        // (an array of { interruptId, status, payload }) instead of the legacy\n        // `forwardedProps.command`. Mastra fully overrides run(), so the base\n        // AbstractAgent reconcile of `input.resume` is bypassed — we consume it\n        // here. We normalize the first entry into the same internal command shape\n        // the legacy path uses, so a single resume block serves both channels.\n        //\n        // The Mastra snapshot runId (the resumeStream key) is NOT carried by a\n        // ResumeEntry — only `interruptId` round-trips. So we encode the runId\n        // into the emitted Interrupt id as `${runId}::${toolCallId}` (see\n        // suspendToInterrupt) and decode it back here.\n        if (!forwardedCommand?.interruptEvent && Array.isArray(input.resume)) {\n          const entry = input.resume.find(\n            (r) => r?.status === \"resolved\" || r?.status === \"cancelled\",\n          );\n          if (entry?.interruptId) {\n            const sep = entry.interruptId.indexOf(\"::\");\n            const runId =\n              sep >= 0 ? entry.interruptId.slice(0, sep) : input.runId;\n            const toolCallId =\n              sep >= 0 ? entry.interruptId.slice(sep + 2) : entry.interruptId;\n            forwardedCommand = {\n              resume: entry.status === \"cancelled\" ? false : entry.payload,\n              interruptEvent: { toolCallId, runId },\n            };\n          }\n        }\n\n        // resume: false means the user explicitly declined the tool call.\n        // Close the run cleanly without calling resumeStream.\n        if (\n          forwardedCommand?.resume === false &&\n          forwardedCommand?.interruptEvent\n        ) {\n          await this.emitWorkingMemorySnapshot(subscriber, input.threadId);\n          subscriber.next({\n            type: EventType.RUN_FINISHED,\n            threadId: input.threadId,\n            runId: input.runId,\n          } as RunFinishedEvent);\n          subscriber.complete();\n          return;\n        }\n\n        if (\n          forwardedCommand?.resume != null &&\n          forwardedCommand?.interruptEvent\n        ) {\n          // Safely parse interruptEvent — client-supplied data\n          let interruptEvent: any;\n          try {\n            interruptEvent =\n              typeof forwardedCommand.interruptEvent === \"string\"\n                ? JSON.parse(forwardedCommand.interruptEvent)\n                : forwardedCommand.interruptEvent;\n          } catch (err) {\n            subscriber.error(\n              new Error(\"Invalid interruptEvent: malformed JSON\", {\n                cause: err,\n              }),\n            );\n            return;\n          }\n\n          // Validate required fields for resume\n          if (!interruptEvent?.toolCallId || !interruptEvent?.runId) {\n            subscriber.error(\n              new Error(\"Invalid interruptEvent: missing toolCallId or runId\"),\n            );\n            return;\n          }\n\n          // Re-set this run's context so resume forwards it, not the prior turn's.\n          const resumeRequestContext = this.applyInputContext(input.context);\n\n          // Resume options are shared verbatim by the local and remote paths.\n          // Mastra keys the suspended snapshot by the runId surfaced on the\n          // suspend chunk (round-tripped here as interruptEvent.runId), NOT the\n          // AG-UI RunAgentInput.runId — passing the latter fails remote resume\n          // with \"No snapshot found for this workflow run\". The remote instance\n          // loads that snapshot from configured storage, so `memory` must point\n          // at the same thread/resource the suspended run used.\n          const resumeOptions: Record<string, unknown> = {\n            toolCallId: interruptEvent.toolCallId,\n            runId: interruptEvent.runId,\n            memory: {\n              thread: input.threadId,\n              resource: this.resourceId ?? input.threadId,\n            },\n            requestContext: resumeRequestContext,\n          };\n          if (this.tracingOptions) {\n            resumeOptions.tracingOptions = this.tracingOptions;\n          }\n          if (this.headers && Object.keys(this.headers).length > 0) {\n            resumeOptions.modelSettings = {\n              ...((resumeOptions.modelSettings as\n                | Record<string, unknown>\n                | undefined) ?? {}),\n              headers: this.headers,\n            };\n          }\n\n          const callbacks = this.makeStreamCallbacks(\n            subscriber,\n            () => messageId,\n            (id) => {\n              messageId = id;\n            },\n            input.runId,\n            pendingInterrupts,\n          );\n\n          // Shared completion: emit a best-effort working-memory snapshot\n          // (no-op for remote agents, which have no local memory) then\n          // RUN_FINISHED. makeRunFinishedEvent attaches the structured\n          // interrupt outcome when emitInterruptOutcome is on (e.g. a chained\n          // interrupt in the resumed stream), so the resumed-run tail is\n          // identical for local and remote.\n          const finishResume = async (traceId?: string) => {\n            await this.emitWorkingMemorySnapshot(subscriber, input.threadId);\n            subscriber.next(\n              this.makeRunFinishedEvent(\n                input.threadId,\n                input.runId,\n                pendingInterrupts,\n                traceId,\n              ),\n            );\n            subscriber.complete();\n          };\n\n          try {\n            if (this.isLocalMastraAgent(this.agent)) {\n              const response = await this.agent.resumeStream(\n                forwardedCommand.resume,\n                resumeOptions,\n              );\n\n              // Null/invalid response from resumeStream is an error\n              if (\n                !response ||\n                typeof response !== \"object\" ||\n                !response.fullStream\n              ) {\n                subscriber.error(\n                  new Error(\n                    \"resumeStream returned no valid response (missing fullStream)\",\n                  ),\n                );\n                return;\n              }\n\n              const hadError = await this.processFullStream(\n                response.fullStream,\n                {\n                  ...callbacks,\n                  onError: (error) => {\n                    subscriber.error(error);\n                  },\n                },\n              );\n\n              if (!hadError) {\n                await finishResume(await this.resolveTraceId(response));\n              }\n            } else {\n              // Remote resume round-trips the suspend state + resume command\n              // over @mastra/client-js. The remote Agent's resumeStream returns\n              // a processDataStream response (callback-based), so we drive it\n              // through the same createChunkProcessor used by the remote\n              // .stream() path — single source of truth for chunk handling.\n              const remoteAgent = this\n                .agent as unknown as Partial<RemoteResumableAgent>;\n              if (typeof remoteAgent.resumeStream !== \"function\") {\n                subscriber.error(\n                  new Error(\n                    \"Resume from interrupt requires a @mastra/client-js version that supports agent.resumeStream(); please upgrade @mastra/client-js\",\n                  ),\n                );\n                return;\n              }\n\n              const response = await remoteAgent.resumeStream(\n                forwardedCommand.resume,\n                resumeOptions,\n              );\n\n              if (\n                !response ||\n                typeof response.processDataStream !== \"function\"\n              ) {\n                subscriber.error(\n                  new Error(\n                    \"resumeStream returned no valid response (missing processDataStream)\",\n                  ),\n                );\n                return;\n              }\n\n              let stopped = false;\n              const { handleChunk, flush } = this.createChunkProcessor({\n                ...callbacks,\n                onError: (error) => {\n                  subscriber.error(error);\n                },\n              });\n\n              await response.processDataStream({\n                onChunk: async (chunk: any) => {\n                  if (stopped) return;\n                  if (handleChunk(chunk)) stopped = true;\n                },\n              });\n\n              if (!stopped) {\n                flush();\n                await finishResume(await this.resolveTraceId(response));\n              }\n            }\n          } catch (error) {\n            subscriber.error(error);\n          }\n          return;\n        }\n\n        // Sync AG-UI input state into Mastra's working memory before streaming,\n        // so a client-side edit to shared state (e.g. unchecking a dietary\n        // preference in the recipe UI, then hitting \"Improve\") is what the agent\n        // reads on the next run. Works for both local and remote agents (see\n        // syncInputStateToWorkingMemory).\n        try {\n          await this.syncInputStateToWorkingMemory(input);\n        } catch (error) {\n          subscriber.error(error);\n          return;\n        }\n\n        try {\n          const streamCallbacks = this.makeStreamCallbacks(\n            subscriber,\n            () => messageId,\n            (id) => {\n              messageId = id;\n            },\n            input.runId,\n            pendingInterrupts,\n          );\n\n          await this.streamMastraAgent(input, {\n            ...streamCallbacks,\n            onError: (error) => {\n              subscriber.error(error);\n            },\n            onRunFinished: async (traceId) => {\n              await this.emitWorkingMemorySnapshot(subscriber, input.threadId);\n              subscriber.next(\n                this.makeRunFinishedEvent(\n                  input.threadId,\n                  input.runId,\n                  pendingInterrupts,\n                  traceId,\n                ),\n              );\n              subscriber.complete();\n            },\n          });\n        } catch (error) {\n          subscriber.error(error);\n        }\n      };\n\n      run().catch((err) => {\n        if (subscriber.closed) return;\n        subscriber.error(err);\n      });\n\n      return () => {};\n    });\n  }\n\n  isLocalMastraAgent(\n    agent: LocalMastraAgent | RemoteMastraAgent,\n  ): agent is LocalMastraAgent {\n    return \"getMemory\" in agent;\n  }\n\n  /**\n   * Maps a Mastra tool suspend to an AG-UI {@link Interrupt}.\n   *\n   * `id` is the suspended tool call id — the correlation key resume sends back\n   * (alongside `runId`) via `resumeStream`. `responseSchema` is the parsed\n   * `resumeSchema` (Mastra hands it over as a JSON string). Everything the\n   * resume round-trip needs that has no first-class Interrupt field\n   * (`toolName`, `suspendPayload`, `args`, the snapshot-keying `runId`) is\n   * preserved under `metadata.mastra`, shaped like the legacy on_interrupt\n   * value so a standard-path client can reconstruct the resume directive.\n   */\n  private suspendToInterrupt(\n    payload: {\n      toolCallId: string;\n      toolName: string;\n      suspendPayload: any;\n      args: Record<string, any>;\n      resumeSchema: string;\n      runId?: string;\n    },\n    runId: string,\n  ): Interrupt {\n    let responseSchema: Record<string, any> | undefined;\n    const rawSchema = payload.resumeSchema as unknown;\n    if (typeof rawSchema === \"string\" && rawSchema.trim().length > 0) {\n      try {\n        const parsed = JSON.parse(rawSchema);\n        if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n          responseSchema = parsed;\n        }\n      } catch {\n        // resumeSchema is not valid JSON — omit responseSchema; the raw value\n        // is still carried in metadata.mastra below.\n      }\n    } else if (\n      rawSchema &&\n      typeof rawSchema === \"object\" &&\n      !Array.isArray(rawSchema)\n    ) {\n      responseSchema = rawSchema as Record<string, any>;\n    }\n\n    // Encode the snapshot runId into the interrupt id as `${runId}::${toolCallId}`.\n    // A standard-path client (CopilotKit >= 1.61.2) only round-trips `interruptId`\n    // in its ResumeEntry — not metadata — so the id is the one channel that can\n    // carry the runId resume needs (see the input.resume consumer in run()).\n    // `toolCallId` stays its own field for the legacy path and for renderers.\n    const snapshotRunId = payload.runId ?? runId;\n    return {\n      id: `${snapshotRunId}::${payload.toolCallId}`,\n      reason: \"mastra:tool_suspend\",\n      toolCallId: payload.toolCallId,\n      ...(responseSchema ? { responseSchema } : {}),\n      metadata: {\n        mastra: {\n          type: \"mastra_suspend\",\n          toolName: payload.toolName,\n          suspendPayload: payload.suspendPayload,\n          args: payload.args,\n          resumeSchema: payload.resumeSchema,\n          // The id Mastra keys the suspended snapshot by (see onToolSuspended).\n          runId: snapshotRunId,\n        },\n      },\n    };\n  }\n\n  /**\n   * Builds the terminating RUN_FINISHED for a run. When emitInterruptOutcome is\n   * on AND the run suspended at least one tool, attaches the structured\n   * `outcome: { type: \"interrupt\", interrupts }`. Otherwise emits a plain\n   * RUN_FINISHED — the legacy/default behavior. Mirrors LangGraph's\n   * `dispatchInterruptFinish`.\n   *\n   * When the run exposed a Mastra execution traceId (Mastra observability\n   * v-next), it is surfaced on `RUN_FINISHED.result` as `{ traceId }` so the\n   * client/runtime can correlate the produced assistant message with its trace\n   * (e.g. to anchor trace-centric feedback/scores). `result` is left unset\n   * otherwise, preserving the prior event shape.\n   */\n  private makeRunFinishedEvent(\n    threadId: string,\n    runId: string,\n    interrupts: Interrupt[],\n    traceId?: string,\n  ): RunFinishedEvent {\n    const includeOutcome = this.emitInterruptOutcome && interrupts.length > 0;\n    return {\n      type: EventType.RUN_FINISHED,\n      threadId,\n      runId,\n      ...(traceId ? { result: { traceId } } : {}),\n      ...(includeOutcome\n        ? {\n            outcome: {\n              type: \"interrupt\",\n              interrupts,\n            } satisfies RunFinishedInterruptOutcome,\n          }\n        : {}),\n    } as RunFinishedEvent;\n  }\n\n  /**\n   * Fetches working memory from a local agent and emits a STATE_SNAPSHOT event\n   * if valid working memory is available.\n   *\n   * Best-effort: logs a warning and returns gracefully on failure so callers\n   * can proceed with RUN_FINISHED even when the snapshot could not be delivered.\n   */\n  private async emitWorkingMemorySnapshot(\n    subscriber: { next: (event: BaseEvent) => void },\n    threadId: string,\n  ): Promise<boolean> {\n    if (!this.isLocalMastraAgent(this.agent)) return true;\n    try {\n      const memory = await this.agent.getMemory({\n        requestContext: this.requestContext,\n      });\n      if (memory) {\n        const workingMemory = await memory.getWorkingMemory({\n          resourceId: this.resourceId ?? threadId,\n          threadId,\n          memoryConfig: {\n            workingMemory: {\n              enabled: true,\n            },\n          },\n        });\n\n        if (typeof workingMemory === \"string\") {\n          let snapshot: Record<string, any> | null = null;\n          try {\n            snapshot = JSON.parse(workingMemory);\n          } catch {\n            // Working memory is not valid JSON (e.g. markdown template)\n            // Wrap it so the client still receives the state\n            snapshot = { workingMemory };\n          }\n\n          // Skip snapshots containing a JSON Schema definition ($schema) —\n          // these are Mastra's working-memory templates, not actual state.\n          if (snapshot && !(\"$schema\" in snapshot)) {\n            subscriber.next({\n              type: EventType.STATE_SNAPSHOT,\n              snapshot,\n            } as StateSnapshotEvent);\n          }\n        }\n      }\n      return true;\n    } catch (error) {\n      console.warn(\n        `[MastraAgent] Failed to emit working memory snapshot for thread ${threadId}:`,\n        error,\n      );\n      return false;\n    }\n  }\n\n  /**\n   * Creates the callback set used by processFullStream to emit AG-UI events.\n   * messageId is accessed/mutated via getter/setter closures so that when\n   * onFinishMessagePart replaces the ID with a new UUID, subsequent callbacks\n   * in the same run() invocation see the updated value.\n   */\n  private makeStreamCallbacks(\n    subscriber: { next: (event: BaseEvent) => void },\n    getMessageId: () => string,\n    setMessageId: (id: string) => void,\n    runId: string,\n    pendingInterrupts: Interrupt[],\n  ): Omit<MastraAgentStreamOptions, \"onError\" | \"onRunFinished\"> {\n    let reasoningMessageId: string | null = null;\n    let isReasoning = false;\n\n    // --- Assistant message-ordering fix (backend tool -> trailing text) ------\n    // Mastra assigns ONE messageId to an entire assistant turn and re-announces\n    // it on each step-start, so a backend tool call and the model's final\n    // narration text (streamed in a later step) both land under it. Under a\n    // single AG-UI messageId CopilotKit draws a message's text BEFORE its tool\n    // calls, so the narration renders ABOVE the tool card (and, for A2UI, above\n    // the generated surface) even though it streamed LAST. To restore\n    // card -> result -> text order, any assistant text that would stream under a\n    // messageId that already carries a tool call is split into a SEPARATE\n    // continuation message, keyed by a deterministic id derived from that id\n    // (so re-sent history still dedups; see selectNewMessages).\n    //\n    // Keying off the tool call's own parent id (rather than a per-turn flag)\n    // keeps the split correct whether Mastra re-announces the same id across the\n    // step boundary (the real bug: text collapses onto the tool id) or omits\n    // the id and relies on messageId rotation (each step already gets a fresh\n    // id, so nothing collides and no split happens).\n    const toolCallParentIds = new Set<string>();\n\n    const closeReasoning = () => {\n      if (isReasoning && reasoningMessageId) {\n        subscriber.next({\n          type: EventType.REASONING_MESSAGE_END,\n          messageId: reasoningMessageId,\n        } as ReasoningMessageEndEvent);\n        subscriber.next({\n          type: EventType.REASONING_END,\n          messageId: reasoningMessageId,\n        } as ReasoningEndEvent);\n        isReasoning = false;\n        reasoningMessageId = null;\n      }\n    };\n\n    const openReasoning = () => {\n      if (!isReasoning) {\n        reasoningMessageId = randomUUID();\n        isReasoning = true;\n        subscriber.next({\n          type: EventType.REASONING_START,\n          messageId: reasoningMessageId,\n        } as ReasoningStartEvent);\n        subscriber.next({\n          type: EventType.REASONING_MESSAGE_START,\n          messageId: reasoningMessageId,\n          role: \"reasoning\",\n        } as ReasoningMessageStartEvent);\n      }\n    };\n\n    return {\n      onMessageId: (id) => {\n        setMessageId(id);\n      },\n      onReasoningStart: () => {\n        openReasoning();\n      },\n      onReasoningPart: (text) => {\n        openReasoning();\n        subscriber.next({\n          type: EventType.REASONING_MESSAGE_CONTENT,\n          messageId: reasoningMessageId!,\n          delta: text,\n        } as ReasoningMessageContentEvent);\n      },\n      onReasoningEnd: () => {\n        closeReasoning();\n      },\n      onTextPart: (text) => {\n        closeReasoning();\n        // If this text would stream under a messageId that already carries a\n        // tool call, split it into its own continuation message so it renders\n        // BELOW the tool card/result (see the ordering note above). Text under\n        // a fresh id (no tool call on it) keeps that id — including text that\n        // legitimately precedes a tool call in the same message.\n        const currentId = getMessageId();\n        const textMessageId = toolCallParentIds.has(currentId)\n          ? MastraAgent.continuationMessageId(currentId)\n          : currentId;\n        subscriber.next({\n          type: EventType.TEXT_MESSAGE_CHUNK,\n          role: \"assistant\",\n          messageId: textMessageId,\n          delta: text,\n        } as TextMessageChunkEvent);\n      },\n      onToolCallStart: (streamPart) => {\n        closeReasoning();\n        const parentMessageId = getMessageId();\n        // Record the id this tool call renders under; trailing text on the same\n        // id is then split to a continuation message (see onTextPart).\n        toolCallParentIds.add(parentMessageId);\n        subscriber.next({\n          type: EventType.TOOL_CALL_START,\n          parentMessageId,\n          toolCallId: streamPart.toolCallId,\n          toolCallName: streamPart.toolName,\n        } as ToolCallStartEvent);\n      },\n      onToolCallArgs: (streamPart) => {\n        subscriber.next({\n          type: EventType.TOOL_CALL_ARGS,\n          toolCallId: streamPart.toolCallId,\n          delta: streamPart.argsTextDelta,\n        } as ToolCallArgsEvent);\n      },\n      onToolCallEnd: (streamPart) => {\n        subscriber.next({\n          type: EventType.TOOL_CALL_END,\n          toolCallId: streamPart.toolCallId,\n        } as ToolCallEndEvent);\n      },\n      onToolResultPart: (streamPart) => {\n        subscriber.next({\n          type: EventType.TOOL_CALL_RESULT,\n          toolCallId: streamPart.toolCallId,\n          content: JSON.stringify(streamPart.result),\n          messageId: randomUUID(),\n          role: \"tool\",\n        } as ToolCallResultEvent);\n      },\n      onToolSuspended: (payload) => {\n        // Legacy path: always emitted (backward compat, owner decision). The\n        // wrapper stays even when emitInterruptOutcome is on.\n        subscriber.next({\n          type: EventType.CUSTOM,\n          name: \"on_interrupt\",\n          value: JSON.stringify({\n            type: \"mastra_suspend\",\n            toolCallId: payload.toolCallId,\n            toolName: payload.toolName,\n            suspendPayload: payload.suspendPayload,\n            args: payload.args,\n            resumeSchema: payload.resumeSchema,\n            // Prefer the runId Mastra reported on the suspend chunk (the id its\n            // snapshot is keyed by); fall back to the AG-UI run's id when the\n            // chunk omits one. The resume path round-trips this exact value.\n            runId: payload.runId ?? runId,\n          }),\n        } as CustomEvent);\n\n        // Standard path (opt-in): accumulate the suspend as an AG-UI Interrupt\n        // so the terminating RUN_FINISHED carries the structured outcome. Kept\n        // separate from the legacy event above — both fire when the flag is on.\n        if (this.emitInterruptOutcome) {\n          pendingInterrupts.push(this.suspendToInterrupt(payload, runId));\n        }\n      },\n      onFinishMessagePart: () => {\n        closeReasoning();\n        setMessageId(randomUUID());\n      },\n      onActivitySnapshot: ({ messageId, activityType, content }) => {\n        subscriber.next({\n          type: EventType.ACTIVITY_SNAPSHOT,\n          messageId,\n          activityType,\n          content,\n        } as ActivitySnapshotEvent);\n      },\n      onActivityDelta: ({ messageId, activityType, patch }) => {\n        subscriber.next({\n          type: EventType.ACTIVITY_DELTA,\n          messageId,\n          activityType,\n          patch,\n        } as ActivityDeltaEvent);\n      },\n      onStateSnapshot: (snapshot) => {\n        subscriber.next({\n          type: EventType.STATE_SNAPSHOT,\n          snapshot,\n        } as StateSnapshotEvent);\n      },\n      onStateDelta: (delta) => {\n        subscriber.next({\n          type: EventType.STATE_DELTA,\n          delta,\n        } as StateDeltaEvent);\n      },\n    };\n  }\n\n  /**\n   * Creates a stateful chunk processor that maps Mastra stream chunks to\n   * AG-UI events via callbacks.\n   *\n   * Tool-call args are streamed incrementally: Mastra emits\n   * `tool-call-input-streaming-start` → one or more `tool-call-delta` (each a\n   * raw JSON-text fragment) → `tool-call-input-streaming-end` → a final\n   * `tool-call` (with the assembled args) as the model produces the call.\n   * When those delta chunks are present we emit TOOL_CALL_START on the start\n   * chunk, a TOOL_CALL_ARGS per delta, and TOOL_CALL_END on the end chunk —\n   * so the client renders args as they arrive. The trailing `tool-call` for an\n   * already-streamed id is a no-op (args were already emitted).\n   *\n   * Fall-back (backwards compatibility): older @mastra/core in the supported\n   * 1.0.x floor may emit only the final `tool-call` with no delta chunks. In\n   * that case we buffer the `tool-call` and emit a single START + full-args\n   * ARGS + END when it flushes. This buffered path also preserves the\n   * suspend protocol: if a buffered tool-call is followed by\n   * tool-call-suspended, the TOOL_CALL_* events are suppressed (the tool\n   * hasn't executed yet — emitting them confuses CopilotKit's orchestration\n   * which expects a TOOL_CALL_RESULT to follow). Suspendable tools are\n   * server-side and travel the buffered path; client/generative tools (which\n   * never suspend) are the ones whose args stream incrementally.\n   *\n   * Used by both the local agent path (async iterable) and the remote agent\n   * path (processDataStream callback) — single source of truth for chunk\n   * handling and buffering logic.\n   *\n   * @returns An object with two methods:\n   *   - `handleChunk`: processes a single chunk; returns `true` if processing should stop (error or malformed chunk).\n   *   - `flush`: emits any buffered tool-call (call at end of stream).\n   */\n  private createChunkProcessor(\n    callbacks: MastraAgentStreamOptions,\n    clientToolNames: Set<string> = new Set(),\n    initialState: Record<string, any> = {},\n  ) {\n    // Running client-side working-memory state, mapped to AG-UI shared state.\n    // Seeded from the run's input.state (the base the client already holds), so\n    // the first STATE_DELTA patches from what the UI shows, not from empty.\n    // Each `updateWorkingMemory` tool call advances it and emits the patch.\n    let workingMemoryState: Record<string, any> =\n      initialState && typeof initialState === \"object\"\n        ? { ...initialState }\n        : {};\n    // Tool call ids for `updateWorkingMemory` calls — used to suppress their\n    // normal tool render (the update surfaces as STATE_DELTA, not a tool pill)\n    // and to swallow the following `{ success: true }` tool-result.\n    const workingMemoryToolCalls = new Set<string>();\n    // The in-flight `updateWorkingMemory` call whose args are streaming: we\n    // accumulate its raw `tool-call-delta` text and re-parse the growing prefix\n    // so shared state renders progressively (field by field) rather than as one\n    // blob when the call completes.\n    let workingMemoryStream: { toolCallId: string; argsText: string } | null =\n      null;\n\n    // Whether we've emitted the leading STATE_SNAPSHOT for this run yet. The\n    // AG-UI runtime applies STATE_DELTA against a document that starts EMPTY at\n    // run start (it does not seed from input.state), so the first working-memory\n    // state event MUST be a full STATE_SNAPSHOT — it establishes the base the\n    // runtime and client patch against. Without it the first delta's paths (e.g.\n    // `replace /recipe/skill_level`) are unresolvable → the runtime throws\n    // OPERATION_PATH_UNRESOLVABLE, the run never finishes, and the Mastra thread\n    // lock is never released (\"Thread already running\" on the next run).\n    let stateSnapshotEmitted = false;\n\n    // Advance the tracked shared state to the post-update value. The FIRST\n    // change of a run is emitted as a STATE_SNAPSHOT (establishes the base);\n    // every change after that as a STATE_DELTA (RFC-6902 patch, no-op if\n    // nothing changed). Seeding `workingMemoryState` from input.state means the\n    // snapshot preserves fields the streamed prefix hasn't written yet (no\n    // transient collapse of the existing recipe). Shared by the streaming and\n    // final-chunk paths so both advance the same state.\n    const emitWorkingMemoryState = (\n      update: Record<string, any> | undefined,\n    ) => {\n      if (update === undefined) return;\n      const next = deepMergeWorkingMemory(workingMemoryState, update);\n      if (!stateSnapshotEmitted) {\n        stateSnapshotEmitted = true;\n        workingMemoryState = next;\n        callbacks.onStateSnapshot?.(next);\n        return;\n      }\n      const patch = compare(workingMemoryState, next);\n      if (patch.length > 0) {\n        workingMemoryState = next;\n        callbacks.onStateDelta?.(patch as Array<Record<string, any>>);\n      }\n    };\n\n    // Whether to surface Observational Memory background work as activity\n    // events. OFF by default — see MastraAgentConfig.observationalMemory.\n    const surfaceOM = !!this.observationalMemory;\n\n    // Only CLIENT (frontend) tools stream their args live — they are the\n    // generative-UI tools that benefit from progressive rendering, and they\n    // never suspend or background. SERVER tools take the buffered path below so\n    // a following `tool-call-suspended` / `background-task-started` can still\n    // suppress the normal render (you cannot retract an already-emitted live\n    // arg stream). The bridge knows which tools are client tools because they\n    // arrive in `RunAgentInput.tools` (→ `clientTools`); server tools live on\n    // the Mastra agent and are absent from that set.\n    const isClientTool = (toolName?: string) =>\n      !!toolName && clientToolNames.has(toolName);\n\n    // Floor / fall-back path: a final `tool-call` with no preceding client\n    // delta stream is buffered here so a following tool-call-suspended /\n    // background-task-started can suppress it (and reuse its args). Tool calls\n    // that streamed deltas live are NOT buffered.\n    let pendingToolCall: {\n      toolCallId: string;\n      toolName: string;\n      args: any;\n    } | null = null;\n    // Tool calls for which we have emitted TOOL_CALL_START via the streaming\n    // (delta) path, and (separately) for which we have emitted TOOL_CALL_END.\n    const streamedStarted = new Set<string>();\n    const streamedEnded = new Set<string>();\n\n    // Skipped / unrecognized chunk types warn at most once each. Mastra 1.31+\n    // custom-data streams (e.g. `data-*` via context.writer.custom) can emit\n    // the same payload-less type at high frequency; a per-chunk warn would\n    // flood the log (#1635). Dedupe by type so integrators still see the\n    // message without the spam.\n    const warnedChunkTypes = new Set<string>();\n    const warnOnce = (type: string | undefined, message: string) => {\n      const key = type ?? \"undefined\";\n      if (warnedChunkTypes.has(key)) return;\n      warnedChunkTypes.add(key);\n      console.warn(`[MastraAgent] ${message}: type=${key}`);\n    };\n\n    const startStreamedToolCall = (toolCallId: string, toolName: string) => {\n      if (!streamedStarted.has(toolCallId)) {\n        streamedStarted.add(toolCallId);\n        callbacks.onToolCallStart?.({ toolCallId, toolName });\n      }\n    };\n\n    const endStreamedToolCall = (toolCallId: string) => {\n      if (streamedStarted.has(toolCallId) && !streamedEnded.has(toolCallId)) {\n        streamedEnded.add(toolCallId);\n        callbacks.onToolCallEnd?.({ toolCallId });\n      }\n    };\n\n    const flush = () => {\n      if (pendingToolCall) {\n        const { toolCallId, toolName, args } = pendingToolCall;\n        pendingToolCall = null;\n        callbacks.onToolCallStart?.({ toolCallId, toolName });\n        callbacks.onToolCallArgs?.({\n          toolCallId,\n          // The buffered path has the assembled args object — serialize the\n          // whole thing as a single delta (the streaming path emits the raw\n          // JSON-text fragments instead).\n          argsTextDelta: JSON.stringify(args ?? {}),\n        });\n        callbacks.onToolCallEnd?.({ toolCallId });\n      }\n    };\n\n    // --- useProcessedFinalText buffering ------------------------------------\n    // When the flag is on, `text-delta` chunks are accumulated here instead of\n    // streamed, and the assistant text is emitted once per boundary from the\n    // processor-modified `finish.payload.response.uiMessages` (falling back to\n    // this raw buffer on the terminal `finish`). All of this is inert when the\n    // flag is off — bufferedText stays \"\" and the release helpers early-return.\n    let bufferedText = \"\";\n    // The last text we emitted within the current message window. Mastra ends a\n    // response with a `step-finish` immediately followed by a terminal `finish`,\n    // and BOTH can carry the same `response.uiMessages`; without this guard the\n    // second boundary would re-emit the identical text as a duplicate bubble\n    // (under the already-rotated messageId). Reset on each start / step-start so\n    // dedup is scoped to one message and never suppresses distinct per-step text.\n    let lastEmittedText: string | undefined;\n\n    // Emit `text` as one assistant TEXT_MESSAGE_CHUNK, skipping an exact repeat\n    // of what we just emitted for this message (see lastEmittedText).\n    const emitProcessedText = (text: string) => {\n      if (text === lastEmittedText) return;\n      callbacks.onTextPart?.(text);\n      lastEmittedText = text;\n    };\n\n    // Release buffered/processed assistant text at a finish boundary. Prefers\n    // the processor-modified text from `uiMessages`; on the terminal `finish`\n    // falls back to the raw buffer so nothing is dropped. On a non-terminal\n    // `step-finish` with no `uiMessages`, keeps buffering (the text may still be\n    // rewritten and surfaced on a later boundary — emitting raw now then\n    // processed later would double-render).\n    const releaseBufferedText = (chunkPayload: any, isTerminal: boolean) => {\n      if (!this.useProcessedFinalText) return;\n      const processedText = extractLastAssistantText(\n        chunkPayload?.response?.uiMessages,\n      );\n      if (processedText !== undefined) {\n        bufferedText = \"\";\n        emitProcessedText(processedText);\n        return;\n      }\n      if (isTerminal && bufferedText) {\n        const raw = bufferedText;\n        bufferedText = \"\";\n        emitProcessedText(raw);\n      }\n    };\n\n    // Flush the raw buffer as-is (used when a turn ends without a `finish`, e.g.\n    // a tool suspend/interrupt) so text streamed before the interrupt is not\n    // lost. No-op when the flag is off or nothing is buffered.\n    const flushBufferedTextRaw = () => {\n      if (!this.useProcessedFinalText || !bufferedText) return;\n      const raw = bufferedText;\n      bufferedText = \"\";\n      emitProcessedText(raw);\n    };\n\n    // taskIds for which an ACTIVITY_SNAPSHOT has already been emitted. Guards\n    // against emitting a delta before its snapshot and bounds progress ticks to\n    // tasks the client knows about.\n    const knownTasks = new Set<string>();\n\n    // Maps an in-flight background tool call (by toolCallId) to its task, so we\n    // can correlate the loop's inline `tool-result` / `tool-error` back to the\n    // activity. When a backgrounded tool finishes within the agent loop's wait\n    // window, Mastra surfaces only `background-task-started` on the main stream\n    // and delivers the outcome as an ordinary `tool-result` — there is no\n    // `background-task-completed` here (that lives on the manager's own stream).\n    const backgroundToolCalls = new Map<\n      string,\n      { taskId: string; toolName?: string }\n    >();\n\n    const toISO = (value: unknown): unknown =>\n      value instanceof Date ? value.toISOString() : value;\n\n    // Seed an activity for a task if we haven't already (defensive: a running /\n    // output chunk should always follow a started chunk, but a delta with no\n    // prior snapshot would be unrenderable).\n    const ensureTaskSnapshot = (payload: any) => {\n      const { taskId, toolName, toolCallId, args } = payload ?? {};\n      if (!taskId || knownTasks.has(taskId)) return;\n      knownTasks.add(taskId);\n      const content: Record<string, any> = {\n        taskId,\n        toolName,\n        toolCallId,\n        // The task is dispatched and executing out of band; surface it as\n        // \"running\" so the UI reads as active immediately (the inline path\n        // never emits a separate running delta).\n        status: \"running\",\n        outputs: [],\n      };\n      if (args !== undefined) content.args = args;\n      callbacks.onActivitySnapshot?.({\n        messageId: taskId,\n        activityType: MASTRA_BACKGROUND_TASK_ACTIVITY_TYPE,\n        content,\n      });\n    };\n\n    const emitTaskDelta = (\n      taskId: string,\n      patch: Array<Record<string, any>>,\n    ) => {\n      if (!taskId || patch.length === 0) return;\n      callbacks.onActivityDelta?.({\n        messageId: taskId,\n        activityType: MASTRA_BACKGROUND_TASK_ACTIVITY_TYPE,\n        patch,\n      });\n    };\n\n    // --- Observational Memory (OM) activity ---------------------------------\n    // cycleIds for which an OM ACTIVITY_SNAPSHOT has been emitted. Guards\n    // against emitting a delta before its snapshot.\n    const knownOmCycles = new Set<string>();\n\n    const ensureOmSnapshot = (\n      cycleId: string,\n      content: Record<string, any>,\n    ) => {\n      if (!cycleId || knownOmCycles.has(cycleId)) return;\n      knownOmCycles.add(cycleId);\n      callbacks.onActivitySnapshot?.({\n        messageId: cycleId,\n        activityType: MASTRA_OBSERVATIONAL_MEMORY_ACTIVITY_TYPE,\n        content: { cycleId, ...content },\n      });\n    };\n\n    const emitOmDelta = (\n      cycleId: string,\n      patch: Array<Record<string, any>>,\n    ) => {\n      if (!cycleId || patch.length === 0) return;\n      callbacks.onActivityDelta?.({\n        messageId: cycleId,\n        activityType: MASTRA_OBSERVATIONAL_MEMORY_ACTIVITY_TYPE,\n        patch,\n      });\n    };\n\n    // Build a JSON-patch \"add\" op for each defined field on `data` under\n    // `keyMap` (sourceKey -> activity content path). Skips undefined values so\n    // the delta stays minimal. Date values are normalised to ISO strings.\n    const omPatch = (\n      data: Record<string, any>,\n      keyMap: Record<string, string>,\n    ): Array<Record<string, any>> => {\n      const patch: Array<Record<string, any>> = [];\n      for (const [src, path] of Object.entries(keyMap)) {\n        const value = data?.[src];\n        if (value === undefined) continue;\n        patch.push({ op: \"add\", path: `/${path}`, value: toISO(value) });\n      }\n      return patch;\n    };\n\n    // Map a single OM `data-om-*` chunk to activity events. Snapshot on the\n    // start of a cycle, delta on its end/failure; activation is terminal so it\n    // is a snapshot of its own. Only the substantive lifecycle is surfaced —\n    // `data-om-status` (periodic token-window gauge), `data-om-thread-update`\n    // (title changes) and the deprecated `data-om-observed` are intentionally\n    // ignored (still swallowed, never a stream-stopper). The cycleId round-trips\n    // as the activity messageId so start/end address the same activity message.\n    const handleOmChunk = (chunk: any): void => {\n      const data = chunk?.data ?? {};\n      const cycleId: string | undefined = data.cycleId;\n      switch (chunk.type) {\n        case \"data-om-observation-start\": {\n          if (!cycleId) break;\n          ensureOmSnapshot(cycleId, {\n            operationType: data.operationType,\n            phase: \"observation\",\n            status: \"running\",\n            ...(data.threadId !== undefined && { threadId: data.threadId }),\n            ...(data.recordId !== undefined && { recordId: data.recordId }),\n            ...(data.startedAt !== undefined && {\n              startedAt: toISO(data.startedAt),\n            }),\n            ...(data.tokensToObserve !== undefined && {\n              tokensToObserve: data.tokensToObserve,\n            }),\n          });\n          break;\n        }\n        case \"data-om-buffering-start\": {\n          if (!cycleId) break;\n          ensureOmSnapshot(cycleId, {\n            operationType: data.operationType,\n            phase: \"buffering\",\n            status: \"running\",\n            ...(data.threadId !== undefined && { threadId: data.threadId }),\n            ...(data.recordId !== undefined && { recordId: data.recordId }),\n            ...(data.startedAt !== undefined && {\n              startedAt: toISO(data.startedAt),\n            }),\n            ...(data.tokensToBuffer !== undefined && {\n              tokensToBuffer: data.tokensToBuffer,\n            }),\n          });\n          break;\n        }\n        case \"data-om-observation-end\": {\n          if (!cycleId) break;\n          // Defensive: seed a snapshot if the start chunk was missed.\n          ensureOmSnapshot(cycleId, {\n            operationType: data.operationType,\n            phase: \"observation\",\n            status: \"running\",\n          });\n          emitOmDelta(cycleId, [\n            { op: \"add\", path: \"/status\", value: \"completed\" },\n            ...omPatch(data, {\n              completedAt: \"completedAt\",\n              durationMs: \"durationMs\",\n              tokensObserved: \"tokensObserved\",\n              observationTokens: \"observationTokens\",\n              observations: \"observations\",\n              currentTask: \"currentTask\",\n              suggestedResponse: \"suggestedResponse\",\n            }),\n          ]);\n          break;\n        }\n        case \"data-om-buffering-end\": {\n          if (!cycleId) break;\n          ensureOmSnapshot(cycleId, {\n            operationType: data.operationType,\n            phase: \"buffering\",\n            status: \"running\",\n          });\n          emitOmDelta(cycleId, [\n            { op: \"add\", path: \"/status\", value: \"completed\" },\n            ...omPatch(data, {\n              completedAt: \"completedAt\",\n              durationMs: \"durationMs\",\n              tokensBuffered: \"tokensBuffered\",\n              bufferedTokens: \"bufferedTokens\",\n              observations: \"observations\",\n            }),\n          ]);\n          break;\n        }\n        case \"data-om-observation-failed\":\n        case \"data-om-buffering-failed\": {\n          if (!cycleId) break;\n          const phase =\n            chunk.type === \"data-om-buffering-failed\"\n              ? \"buffering\"\n              : \"observation\";\n          ensureOmSnapshot(cycleId, {\n            operationType: data.operationType,\n            phase,\n            status: \"running\",\n          });\n          emitOmDelta(cycleId, [\n            { op: \"add\", path: \"/status\", value: \"failed\" },\n            {\n              op: \"add\",\n              path: \"/error\",\n              value: data.error ?? \"Unknown error\",\n            },\n            ...omPatch(data, {\n              failedAt: \"completedAt\",\n              durationMs: \"durationMs\",\n            }),\n          ]);\n          break;\n        }\n        case \"data-om-activation\": {\n          // Activation moves buffered observations into the active context. In\n          // the async path it REUSES the buffering cycle's id (buffering-start/\n          // -end then activation all share one cycleId), so when the cycle is\n          // already known this is the terminal DELTA that advances that activity\n          // to \"activated\". When the cycle is unknown (defensive / a future path\n          // that activates without a prior buffering cycle on this stream) it is\n          // a self-contained snapshot.\n          if (!cycleId) break;\n          const activationPatch = (data: Record<string, any>) =>\n            omPatch(data, {\n              activatedAt: \"completedAt\",\n              chunksActivated: \"chunksActivated\",\n              tokensActivated: \"tokensActivated\",\n              observationTokens: \"observationTokens\",\n              messagesActivated: \"messagesActivated\",\n              generationCount: \"generationCount\",\n              triggeredBy: \"triggeredBy\",\n              observations: \"observations\",\n            });\n          if (knownOmCycles.has(cycleId)) {\n            emitOmDelta(cycleId, [\n              { op: \"add\", path: \"/phase\", value: \"activation\" },\n              { op: \"add\", path: \"/status\", value: \"activated\" },\n              ...activationPatch(data),\n            ]);\n          } else {\n            ensureOmSnapshot(cycleId, {\n              operationType: data.operationType,\n              phase: \"activation\",\n              status: \"activated\",\n              ...(data.threadId !== undefined && { threadId: data.threadId }),\n              ...(data.recordId !== undefined && { recordId: data.recordId }),\n              ...(data.activatedAt !== undefined && {\n                completedAt: toISO(data.activatedAt),\n              }),\n              ...(data.chunksActivated !== undefined && {\n                chunksActivated: data.chunksActivated,\n              }),\n              ...(data.tokensActivated !== undefined && {\n                tokensActivated: data.tokensActivated,\n              }),\n              ...(data.observationTokens !== undefined && {\n                observationTokens: data.observationTokens,\n              }),\n              ...(data.messagesActivated !== undefined && {\n                messagesActivated: data.messagesActivated,\n              }),\n              ...(data.generationCount !== undefined && {\n                generationCount: data.generationCount,\n              }),\n              ...(data.triggeredBy !== undefined && {\n                triggeredBy: data.triggeredBy,\n              }),\n              ...(data.observations !== undefined && {\n                observations: data.observations,\n              }),\n            });\n          }\n          break;\n        }\n        default:\n          // data-om-status / data-om-thread-update / data-om-observed and any\n          // future data-om-* part: swallow without surfacing.\n          break;\n      }\n    };\n\n    const handleChunk = (chunk: any): boolean => {\n      // Observational Memory data parts arrive on fullStream as\n      // `{ type: \"data-om-*\", data: {...} }` (no `payload`). Handle them before\n      // the payload guard below so they map to activity when surfacing is on,\n      // and are swallowed silently (no warn) when off — an OM-enabled agent\n      // still streams cleanly and emits no activity.\n      if (\n        typeof chunk?.type === \"string\" &&\n        chunk.type.startsWith(\"data-om-\")\n      ) {\n        if (surfaceOM) handleOmChunk(chunk);\n        return false;\n      }\n\n      // Other chunks without a `payload` are not fatal. Mastra 1.31+ emits\n      // custom-data chunks (e.g. `data-*` types via context.writer.custom)\n      // that carry `data` instead of `payload`, plus new lifecycle chunk\n      // types this switch doesn't recognize. Skip them gracefully (warn,\n      // return false) so the rest of the stream — including RUN_FINISHED —\n      // still flows, rather than aborting the run.\n      if (!chunk || !chunk.payload) {\n        warnOnce(chunk?.type, \"Skipping stream chunk without payload\");\n        return false;\n      }\n      switch (chunk.type) {\n        case \"reasoning-start\": {\n          callbacks.onReasoningStart?.();\n          break;\n        }\n        case \"reasoning-delta\": {\n          callbacks.onReasoningPart?.(chunk.payload.text);\n          break;\n        }\n        case \"reasoning-end\": {\n          callbacks.onReasoningEnd?.();\n          break;\n        }\n        case \"reasoning-signature\":\n        case \"redacted-reasoning\":\n          break;\n        // Mastra 1.31+ text lifecycle markers bracket the `text-delta` chunks.\n        // AG-UI streams text via TEXT_MESSAGE_CHUNK and derives message\n        // boundaries from start/finish + messageId rotation, so these markers\n        // need no action — recognize them so they don't hit the `default:`\n        // warning flood (#1635, #836).\n        case \"text-start\":\n        case \"text-end\":\n          break;\n        // A standalone (non-background) `tool-output` streams intermediate tool\n        // output. The bridge surfaces completed tool results via `tool-result`;\n        // there is no AG-UI mapping for interim output, so ignore it. (Task\n        // output under a backgrounded tool is consumed inside\n        // `background-task-output`, not here.) Recognized to avoid the warn.\n        case \"tool-output\":\n          break;\n        case \"text-delta\": {\n          flush();\n          if (this.useProcessedFinalText) {\n            // Hold deltas until a finish boundary — the processor-modified text\n            // arrives via finish.payload.response.uiMessages.\n            bufferedText += chunk.payload.text;\n          } else {\n            callbacks.onTextPart?.(chunk.payload.text);\n          }\n          break;\n        }\n        // Tool-call args stream incrementally: start → delta(s) → end → the\n        // final `tool-call`. For CLIENT tools we emit these live (progressive\n        // render). For SERVER tools we ignore the delta chunks and buffer the\n        // final `tool-call` (below) so it stays suppressible.\n        case \"tool-call-input-streaming-start\": {\n          // A new tool call begins — flush any prior buffered (floor-path) call.\n          flush();\n          // Working-memory update: capture its streaming args so we can emit\n          // progressive STATE_DELTAs (below). It never renders as a tool.\n          if (\n            chunk.payload.toolCallId &&\n            WORKING_MEMORY_TOOL_NAMES.has(chunk.payload.toolName)\n          ) {\n            workingMemoryStream = {\n              toolCallId: chunk.payload.toolCallId,\n              argsText: \"\",\n            };\n            workingMemoryToolCalls.add(chunk.payload.toolCallId);\n            break;\n          }\n          if (\n            chunk.payload.toolCallId &&\n            isClientTool(chunk.payload.toolName)\n          ) {\n            startStreamedToolCall(\n              chunk.payload.toolCallId,\n              chunk.payload.toolName,\n            );\n          }\n          break;\n        }\n        case \"tool-call-delta\": {\n          const { toolCallId, argsTextDelta } = chunk.payload;\n          // Working-memory update streaming: accumulate the raw args text and\n          // re-parse the growing prefix, emitting an incremental STATE_DELTA as\n          // the model writes the update (progressive shared-state render).\n          if (\n            workingMemoryStream &&\n            toolCallId === workingMemoryStream.toolCallId\n          ) {\n            if (argsTextDelta != null) {\n              workingMemoryStream.argsText += argsTextDelta;\n              emitWorkingMemoryState(\n                parseStreamingWorkingMemoryUpdate(workingMemoryStream.argsText),\n              );\n            }\n            break;\n          }\n          // Only forward deltas for a call we opened as a live (client) stream.\n          // Server-tool deltas are ignored; their args ride the final\n          // `tool-call` chunk into the buffered path.\n          if (\n            toolCallId &&\n            streamedStarted.has(toolCallId) &&\n            argsTextDelta != null\n          ) {\n            callbacks.onToolCallArgs?.({ toolCallId, argsTextDelta });\n          }\n          break;\n        }\n        case \"tool-call-input-streaming-end\": {\n          if (\n            workingMemoryStream &&\n            chunk.payload.toolCallId === workingMemoryStream.toolCallId\n          ) {\n            // Args fully streamed; the authoritative final state is emitted from\n            // the following `tool-call` chunk (its assembled object). Stop\n            // accumulating; keep the id suppressed for the tool-result.\n            workingMemoryStream = null;\n            break;\n          }\n          if (chunk.payload.toolCallId) {\n            endStreamedToolCall(chunk.payload.toolCallId);\n          }\n          break;\n        }\n        case \"tool-call\": {\n          const { toolCallId, toolName, args } = chunk.payload;\n          // Working-memory update: Mastra's built-in `updateWorkingMemory` tool.\n          // The assembled args carry the final (authoritative) working memory —\n          // emit a STATE_DELTA to it (a no-op patch if the streamed deltas above\n          // already converged, or the whole change on the fall-back path where\n          // no arg-deltas streamed). Suppress the normal tool render; the\n          // `{ success: true }` result is swallowed below. A preceding buffered\n          // (floor-path) call still flushes first.\n          if (toolName && WORKING_MEMORY_TOOL_NAMES.has(toolName)) {\n            flush();\n            if (toolCallId) workingMemoryToolCalls.add(toolCallId);\n            if (\n              workingMemoryStream &&\n              workingMemoryStream.toolCallId === toolCallId\n            ) {\n              workingMemoryStream = null;\n            }\n            emitWorkingMemoryState(parseWorkingMemoryUpdate(args));\n            break;\n          }\n          if (toolCallId && streamedStarted.has(toolCallId)) {\n            // Client tool: args were already streamed live via deltas — close\n            // the call (the streaming-end chunk may have been absent) and don't\n            // re-emit.\n            endStreamedToolCall(toolCallId);\n            break;\n          }\n          // Server tool (or a client tool that emitted no deltas): buffer so a\n          // following tool-call-suspended / background-task-started can suppress\n          // it and reuse its args, matching the pre-streaming behavior.\n          flush();\n          pendingToolCall = { toolCallId, toolName, args };\n          break;\n        }\n        case \"tool-result\": {\n          // Swallow the `{ success: true }` result of a working-memory update —\n          // its tool-call was mapped to STATE_DELTA and never rendered, so a\n          // TOOL_CALL_RESULT here would have no matching call (and is internal\n          // plumbing regardless).\n          if (workingMemoryToolCalls.has(chunk.payload.toolCallId)) {\n            workingMemoryToolCalls.delete(chunk.payload.toolCallId);\n            break;\n          }\n          // For a backgrounded call, the agent loop's inline tool-result is a\n          // placeholder ack (\"…running in the background; you will be notified\n          // when it completes\"), NOT the real outcome — the task is detached\n          // and its true result is delivered out of band (a later turn / the\n          // manager's own stream). So suppress it: don't render a TOOL_CALL_\n          // RESULT for a tool call we never rendered, and leave the activity in\n          // its \"running\" state. Real completion arrives via the\n          // background-task-completed / -failed chunks handled below.\n          if (backgroundToolCalls.has(chunk.payload.toolCallId)) {\n            backgroundToolCalls.delete(chunk.payload.toolCallId);\n            break;\n          }\n          flush();\n          callbacks.onToolResultPart?.({\n            toolCallId: chunk.payload.toolCallId,\n            result: chunk.payload.result,\n          });\n          break;\n        }\n        case \"tool-error\": {\n          // An inline error on a backgrounded call means dispatch itself failed\n          // -> mark the activity failed. Non-background tool errors fall through\n          // to the stream's `error` handling elsewhere, so just swallow here.\n          const bgError = backgroundToolCalls.get(chunk.payload?.toolCallId);\n          if (bgError) {\n            backgroundToolCalls.delete(chunk.payload.toolCallId);\n            knownTasks.delete(bgError.taskId);\n            emitTaskDelta(bgError.taskId, [\n              { op: \"add\", path: \"/status\", value: \"failed\" },\n              {\n                op: \"add\",\n                path: \"/error\",\n                value:\n                  chunk.payload?.error?.message ??\n                  String(chunk.payload?.error ?? \"Unknown error\"),\n              },\n            ]);\n          }\n          break;\n        }\n        case \"error\": {\n          const error = new Error(chunk.payload.error as string);\n          callbacks.onError(error);\n          return true;\n        }\n        // A2UI progressive streaming (pillar 2): the auto-injected / explicit\n        // `generate_a2ui` tool runs its `render_a2ui` subagent via `.stream()`\n        // and pushes the render call's arg deltas onto this stream as custom\n        // `data-a2ui-render` chunks (see @ag-ui/mastra a2ui-tool renderSubagent).\n        // Translate them into synthetic INNER `render_a2ui` TOOL_CALL_* events so\n        // the @ag-ui/a2ui-middleware paints the \"building\" skeleton + fills the\n        // surface incrementally instead of bulk-painting the final envelope.\n        case \"data-a2ui-render\": {\n          const p = chunk.payload as {\n            phase?: string;\n            toolCallId?: string;\n            toolName?: string;\n            argsTextDelta?: string;\n          };\n          if (!p.toolCallId) break;\n          if (p.phase === \"start\") {\n            // Flush the buffered OUTER `generate_a2ui` tool-call onto the wire\n            // FIRST, so the A2UIMiddleware has registered it as the active outer\n            // call before this inner `render_a2ui` starts. That keys the streamed\n            // surface to the outer call, so the final generate_a2ui result\n            // envelope lands on the SAME activity id and REPLACES the streamed\n            // surface (single paint) instead of duplicating it — and lets the\n            // envelope be intercepted (no residual generate_a2ui tool card).\n            flush();\n            callbacks.onToolCallStart?.({\n              toolCallId: p.toolCallId,\n              toolName: p.toolName ?? \"render_a2ui\",\n            });\n          } else if (p.phase === \"delta\") {\n            if (p.argsTextDelta != null) {\n              callbacks.onToolCallArgs?.({\n                toolCallId: p.toolCallId,\n                argsTextDelta: p.argsTextDelta,\n              });\n            }\n          } else if (p.phase === \"end\") {\n            callbacks.onToolCallEnd?.({ toolCallId: p.toolCallId });\n          }\n          break;\n        }\n        case \"tool-call-suspended\": {\n          // Always discard the pending tool-call: if it matches, the tool\n          // was suspended before execution; if it doesn't match, the pending\n          // call is orphaned (never executed) so emitting TOOL_CALL_START/\n          // ARGS/END without a TOOL_CALL_RESULT would violate the protocol.\n          pendingToolCall = null;\n          if (!chunk.payload.toolCallId || !chunk.payload.toolName) {\n            callbacks.onError(\n              new Error(\n                `Malformed tool-call-suspended: missing toolCallId or toolName in payload`,\n              ),\n            );\n            return true;\n          }\n          // The turn interrupts here — no `finish` will release the buffer, so\n          // emit any assistant text streamed before the suspend (raw; a suspend\n          // carries no processor uiMessages) ahead of the interrupt event.\n          flushBufferedTextRaw();\n          callbacks.onToolSuspended({\n            toolCallId: chunk.payload.toolCallId,\n            toolName: chunk.payload.toolName,\n            suspendPayload: chunk.payload.suspendPayload,\n            args: chunk.payload.args,\n            resumeSchema: chunk.payload.resumeSchema,\n            // Mastra keys the suspended snapshot by the run's id, surfaced on\n            // the chunk (`payload.runId`, else the chunk-level `runId`). This\n            // can differ from the AG-UI RunAgentInput.runId, so it must be the\n            // id resume sends back to `resumeStream`. See the resume path.\n            runId: chunk.payload.runId ?? chunk.runId,\n          });\n          break;\n        }\n        // Both \"finish\" and \"step-finish\" flush any pending tool call and rotate\n        // the messageId so the next step's text gets a fresh ID. When a stream\n        // ends with step-finish followed by finish, onFinishMessagePart fires\n        // twice — the second rotation produces an unused messageId, which is harmless.\n        //\n        // For useProcessedFinalText, both release buffered/processed text BEFORE\n        // rotating the id (so the emitted text inherits the finishing step's\n        // messageId), but only the terminal `finish` may fall back to the raw\n        // buffer — see releaseBufferedText.\n        case \"step-finish\": {\n          flush();\n          releaseBufferedText(chunk.payload, false);\n          callbacks.onFinishMessagePart?.();\n          break;\n        }\n        case \"finish\": {\n          flush();\n          releaseBufferedText(chunk.payload, true);\n          callbacks.onFinishMessagePart?.();\n          break;\n        }\n        // Mastra announces the persisted message id for the upcoming step on\n        // the start / step-start chunk, before any text streams. Adopt it so\n        // the streamed assistant id equals the stored id (see onMessageId).\n        case \"start\":\n        case \"step-start\": {\n          // A fresh message window begins: reset the dedup guard so distinct\n          // per-step text is never suppressed (see lastEmittedText).\n          lastEmittedText = undefined;\n          if (chunk.payload?.messageId) {\n            callbacks.onMessageId?.(chunk.payload.messageId);\n          }\n          break;\n        }\n        // --- Background Tasks (@mastra/core >= 1.29) ---------------------\n        // Mastra runs a tool flagged `background: { enabled: true }` out of\n        // band; its lifecycle surfaces on fullStream as background-task-*\n        // chunks. Map start -> ACTIVITY_SNAPSHOT (full content) and every\n        // subsequent lifecycle chunk -> ACTIVITY_DELTA (JSON patch). The task\n        // id round-trips as the activity messageId so all events for one task\n        // address the same activity message. JSON-patch `add` to an existing\n        // object member replaces it (RFC 6902 §4.1), so it is safe for both\n        // first-write and updates.\n        case \"background-task-started\": {\n          const { taskId, toolName, toolCallId } = chunk.payload;\n          // The agent loop emits `tool-call` immediately before this; the\n          // bridge has it buffered in pendingToolCall. Suppress that normal\n          // tool render (the work is now an activity) but reuse its args for\n          // the snapshot. Mirrors the tool-call-suspended suppression.\n          const args =\n            pendingToolCall && pendingToolCall.toolCallId === toolCallId\n              ? pendingToolCall.args\n              : undefined;\n          pendingToolCall = null;\n          if (taskId && toolCallId) {\n            backgroundToolCalls.set(toolCallId, { taskId, toolName });\n          }\n          ensureTaskSnapshot({ taskId, toolName, toolCallId, args });\n          break;\n        }\n        case \"background-task-running\":\n        case \"background-task-resumed\": {\n          const p = chunk.payload;\n          ensureTaskSnapshot(p);\n          const status =\n            chunk.type === \"background-task-resumed\" ? \"resumed\" : \"running\";\n          const patch: Array<Record<string, any>> = [\n            { op: \"add\", path: \"/status\", value: status },\n          ];\n          if (p.args !== undefined)\n            patch.push({ op: \"add\", path: \"/args\", value: p.args });\n          if (p.startedAt !== undefined)\n            patch.push({\n              op: \"add\",\n              path: \"/startedAt\",\n              value: toISO(p.startedAt),\n            });\n          emitTaskDelta(p.taskId, patch);\n          break;\n        }\n        case \"background-task-output\": {\n          const p = chunk.payload;\n          ensureTaskSnapshot(p);\n          // p.payload is a `tool-output` chunk; surface its inner payload (the\n          // actual streamed output) and fall back to the whole chunk.\n          const output = p.payload?.payload ?? p.payload;\n          emitTaskDelta(p.taskId, [\n            { op: \"add\", path: \"/status\", value: \"running\" },\n            { op: \"add\", path: \"/outputs/-\", value: output },\n          ]);\n          break;\n        }\n        case \"background-task-progress\": {\n          // Aggregate heartbeat across all running tasks (no per-task id).\n          // Tick the elapsed time on each task the client already knows about.\n          const p = chunk.payload;\n          const taskIds: string[] = Array.isArray(p.taskIds) ? p.taskIds : [];\n          for (const taskId of taskIds) {\n            if (!knownTasks.has(taskId)) continue;\n            emitTaskDelta(taskId, [\n              { op: \"add\", path: \"/elapsedMs\", value: p.elapsedMs },\n            ]);\n          }\n          break;\n        }\n        case \"background-task-suspended\": {\n          const p = chunk.payload;\n          ensureTaskSnapshot(p);\n          const patch: Array<Record<string, any>> = [\n            { op: \"add\", path: \"/status\", value: \"suspended\" },\n          ];\n          if (p.suspendPayload !== undefined)\n            patch.push({\n              op: \"add\",\n              path: \"/suspendPayload\",\n              value: p.suspendPayload,\n            });\n          emitTaskDelta(p.taskId, patch);\n          break;\n        }\n        case \"background-task-completed\": {\n          const p = chunk.payload;\n          ensureTaskSnapshot(p);\n          knownTasks.delete(p.taskId);\n          backgroundToolCalls.delete(p.toolCallId);\n          emitTaskDelta(p.taskId, [\n            {\n              op: \"add\",\n              path: \"/status\",\n              value: p.isError ? \"failed\" : \"completed\",\n            },\n            { op: \"add\", path: \"/result\", value: p.result },\n            { op: \"add\", path: \"/completedAt\", value: toISO(p.completedAt) },\n          ]);\n          break;\n        }\n        case \"background-task-failed\": {\n          const p = chunk.payload;\n          ensureTaskSnapshot(p);\n          knownTasks.delete(p.taskId);\n          backgroundToolCalls.delete(p.toolCallId);\n          emitTaskDelta(p.taskId, [\n            { op: \"add\", path: \"/status\", value: \"failed\" },\n            {\n              op: \"add\",\n              path: \"/error\",\n              value: p.error?.message ?? String(p.error ?? \"Unknown error\"),\n            },\n            { op: \"add\", path: \"/completedAt\", value: toISO(p.completedAt) },\n          ]);\n          break;\n        }\n        case \"background-task-cancelled\": {\n          const p = chunk.payload;\n          ensureTaskSnapshot(p);\n          knownTasks.delete(p.taskId);\n          backgroundToolCalls.delete(p.toolCallId);\n          emitTaskDelta(p.taskId, [\n            { op: \"add\", path: \"/status\", value: \"cancelled\" },\n            { op: \"add\", path: \"/completedAt\", value: toISO(p.completedAt) },\n          ]);\n          break;\n        }\n        default: {\n          warnOnce(chunk.type, \"Unrecognized stream chunk type\");\n          break;\n        }\n      }\n      return false;\n    };\n\n    return { handleChunk, flush };\n  }\n\n  /**\n   * Processes a Mastra fullStream (async iterable) using createChunkProcessor.\n   * @returns true if processing stopped early (error chunk or malformed chunk).\n   */\n  private async processFullStream(\n    stream: AsyncIterable<any>,\n    callbacks: MastraAgentStreamOptions,\n    clientToolNames: Set<string> = new Set(),\n    initialState: Record<string, any> = {},\n  ): Promise<boolean> {\n    const { handleChunk, flush } = this.createChunkProcessor(\n      callbacks,\n      clientToolNames,\n      initialState,\n    );\n    for await (const chunk of stream) {\n      if (handleChunk(chunk)) return true;\n    }\n    flush();\n    return false;\n  }\n\n  /**\n   * Returns only the messages Mastra has not already persisted for this thread\n   * — the new turn — so we don't re-feed (and re-persist) history Mastra memory\n   * already owns. Filters the incoming list against the ids Mastra has stored\n   * (recall), mirroring LangGraph's continuation check.\n   *\n   * Faithful because the bridge streams assistant messages under Mastra's\n   * stored id (see onMessageId), so re-sent history matches stored ids and is\n   * dropped. Remote agents and agents without memory get the full list (no\n   * stored history to dedupe against). Defensive: if filtering would drop\n   * everything, or recall fails, forwards the full list.\n   */\n  private async selectNewMessages(\n    threadId: string,\n    resourceId: string,\n    messages: Message[],\n  ): Promise<Message[]> {\n    if (!this.isLocalMastraAgent(this.agent)) return messages;\n    try {\n      const memory = await this.agent.getMemory({\n        requestContext: this.requestContext,\n      });\n      if (!memory) return messages;\n      const { messages: stored } = await memory.recall({\n        threadId,\n        resourceId,\n        perPage: false,\n      });\n      const storedIds = new Set<string>();\n      for (const m of (stored ?? []) as Array<{ id?: string }>) {\n        if (!m?.id) continue;\n        storedIds.add(m.id);\n        // The bridge streams assistant text that follows a tool call under a\n        // deterministic continuation id derived from the turn's base id (see\n        // makeStreamCallbacks). Mastra stores the whole turn under the base id,\n        // so the continuation id never appears in recall — treat it as stored\n        // here, otherwise the split text is re-sent (and duplicated) each turn.\n        storedIds.add(MastraAgent.continuationMessageId(m.id));\n      }\n      if (storedIds.size === 0) return messages; // first turn / empty thread\n      const fresh = messages.filter((m) => !(m.id && storedIds.has(m.id)));\n      // Never send an empty turn (a no-op run). If everything was already\n      // stored, fall back to forwarding the full list.\n      if (fresh.length === 0) return messages;\n\n      // Tool-result tails: a `tool` message must travel with its matching\n      // assistant tool-call so the AI SDK resolves call→result into a single\n      // message. That assistant message is usually already stored (filtered out\n      // above), so re-include it — id-alignment makes Mastra upsert it by id, so\n      // no extra row is created. Without this, a lone tool-result leaves the\n      // stored call unresolved: Mastra appends a separate result message (a\n      // call/result split) and the model re-calls the tool.\n      const freshSet = new Set(fresh);\n      const neededToolCallIds = new Set(\n        fresh\n          .filter((m) => m.role === \"tool\")\n          .map((m) => (m as { toolCallId?: string }).toolCallId)\n          .filter(Boolean),\n      );\n      if (neededToolCallIds.size === 0) return fresh;\n      const pairedCalls = messages.filter(\n        (m) =>\n          !freshSet.has(m) &&\n          m.role === \"assistant\" &&\n          (m.toolCalls ?? []).some((tc) => neededToolCallIds.has(tc.id)),\n      );\n      if (pairedCalls.length === 0) return fresh;\n      // Preserve original order so each tool-call precedes its result.\n      const keep = new Set([...fresh, ...pairedCalls]);\n      return messages.filter((m) => keep.has(m));\n    } catch (error) {\n      console.warn(\n        `[MastraAgent] Failed to compute new-message diff for thread ${threadId}; sending full history:`,\n        error,\n      );\n      return messages;\n    }\n  }\n\n  /**\n   * The shared-state slice of a run's input.state: everything except the\n   * `messages` list (which the bridge strips before syncing state to working\n   * memory). This is what the client holds as its coagent state, so it is the\n   * correct base for the first mid-run STATE_DELTA. Returns `{}` when there is\n   * no usable state.\n   */\n  private workingMemoryStateSlice(\n    state: RunAgentInput[\"state\"],\n  ): Record<string, any> {\n    if (!state || typeof state !== \"object\") return {};\n    const { messages, ...rest } = state as Record<string, any>;\n    void messages;\n    return rest;\n  }\n\n  /**\n   * Coerces a working-memory value read back from Mastra (a JSON string for\n   * schema/json working memory, or already an object, or a `{ workingMemory }`\n   * envelope from the remote HTTP route) into a plain object for merging.\n   * Returns `{}` for markdown/non-JSON/template ($schema) values.\n   */\n  private coerceWorkingMemoryObject(raw: unknown): Record<string, any> {\n    let value: unknown = raw;\n    if (\n      value &&\n      typeof value === \"object\" &&\n      \"workingMemory\" in (value as Record<string, unknown>)\n    ) {\n      value = (value as Record<string, unknown>).workingMemory;\n    }\n    if (typeof value === \"string\") {\n      try {\n        value = JSON.parse(value);\n      } catch {\n        return {};\n      }\n    }\n    if (\n      value &&\n      typeof value === \"object\" &&\n      !Array.isArray(value) &&\n      !(\"$schema\" in (value as Record<string, unknown>))\n    ) {\n      return value as Record<string, any>;\n    }\n    return {};\n  }\n\n  /**\n   * Syncs the run's `input.state` (the client's shared state, minus `messages`)\n   * into Mastra's resource-scoped working memory BEFORE streaming, so a UI edit\n   * reaches the agent on the next run. Merges the client state over the existing\n   * working memory: keys the client doesn't manage are preserved, while its\n   * shared-state keys (e.g. `recipe`) overwrite wholesale — so a removed value\n   * (an unchecked preference) is actually removed, not left lingering.\n   *\n   * Working memory lives in the RESOURCE store (default scope \"resource\"),\n   * written via `updateWorkingMemory` — NOT `thread.metadata`, which the model\n   * never reads. Local agents write through their own `Memory`; remote agents\n   * write through the `MastraClient` (`remoteClient`) so the SAME edit reaches a\n   * remote server. No-op when there is no client state or (for remote) no client.\n   */\n  private async syncInputStateToWorkingMemory(\n    input: RunAgentInput,\n  ): Promise<void> {\n    const rest = this.workingMemoryStateSlice(input.state);\n    if (Object.keys(rest).length === 0) return;\n\n    const resourceId = this.resourceId ?? input.threadId;\n    const memoryConfig = { workingMemory: { enabled: true } };\n\n    if (this.isLocalMastraAgent(this.agent)) {\n      const memory = await this.agent.getMemory({\n        requestContext: this.requestContext,\n      });\n      if (!memory) return;\n\n      let existing: Record<string, any> = {};\n      try {\n        existing = this.coerceWorkingMemoryObject(\n          await memory.getWorkingMemory({\n            resourceId,\n            threadId: input.threadId,\n            memoryConfig,\n          }),\n        );\n      } catch {\n        // No/invalid existing working memory — start from the client state.\n      }\n\n      await memory.updateWorkingMemory({\n        resourceId,\n        threadId: input.threadId,\n        workingMemory: JSON.stringify({ ...existing, ...rest }),\n        memoryConfig,\n      });\n      return;\n    }\n\n    // Remote agent: write through the MastraClient (working-memory HTTP route).\n    // Requires the client (set by getRemoteAgents) and the agent id.\n    if (!this.remoteClient || !this.agentId) return;\n    const client = this.remoteClient;\n    const agentId = this.agentId;\n\n    let existing: Record<string, any> = {};\n    try {\n      existing = this.coerceWorkingMemoryObject(\n        await client.getWorkingMemory({\n          agentId,\n          threadId: input.threadId,\n          resourceId,\n        }),\n      );\n    } catch {\n      // No/invalid (or not-yet-created) working memory — start from client state.\n    }\n\n    const workingMemory = JSON.stringify({ ...existing, ...rest });\n    const write = () =>\n      client.updateWorkingMemory({\n        agentId,\n        threadId: input.threadId,\n        resourceId,\n        workingMemory,\n      });\n\n    try {\n      await write();\n    } catch {\n      // The remote working-memory HTTP route requires the thread to exist. On\n      // the first turn it may not yet (unlike local Memory, which upserts). So\n      // create the thread and retry once. Best-effort: if it still fails, skip\n      // rather than fail the run — the stream creates the thread, and later\n      // turns will sync.\n      try {\n        await client.createMemoryThread({\n          agentId,\n          threadId: input.threadId,\n          resourceId,\n        } as unknown as Parameters<MastraClient[\"createMemoryThread\"]>[0]);\n        await write();\n      } catch (error) {\n        console.warn(\n          `[MastraAgent] Failed to sync input.state to remote working memory for thread ${input.threadId}:`,\n          error,\n        );\n      }\n    }\n  }\n\n  /**\n   * Reads the Mastra execution traceId off a consumed stream response, if any.\n   *\n   * `traceId` is exposed by Mastra observability v-next on the stream response\n   * (`MastraModelOutput.traceId`); it may be a plain string or a Promise that\n   * resolves after the stream is consumed, so we await a thenable. Probed\n   * structurally so the bridge stays compatible with cores / remote clients\n   * that don't expose it (they simply yield undefined). Best-effort: a read\n   * that throws is swallowed so it never blocks RUN_FINISHED.\n   */\n  private async resolveTraceId(response: unknown): Promise<string | undefined> {\n    if (!response || typeof response !== \"object\") return undefined;\n    try {\n      const raw = (response as { traceId?: unknown }).traceId;\n      const traceId =\n        raw && typeof (raw as PromiseLike<unknown>).then === \"function\"\n          ? await (raw as PromiseLike<unknown>)\n          : raw;\n      return typeof traceId === \"string\" && traceId.length > 0\n        ? traceId\n        : undefined;\n    } catch (error) {\n      console.warn(\"[MastraAgent] Failed to read execution traceId:\", error);\n      return undefined;\n    }\n  }\n\n  /**\n   * Streams a local or remote Mastra agent, emitting AG-UI events via callbacks.\n   * For local agents, iterates fullStream with processFullStream.\n   * For remote agents, uses processDataStream with createChunkProcessor.\n   * Calls onRunFinished on success. For errors, onError is called either from\n   * within stream processing (error chunks) or from the catch block (thrown exceptions).\n   */\n  private async streamMastraAgent(\n    {\n      threadId,\n      runId,\n      messages,\n      tools,\n      context: inputContext,\n      forwardedProps,\n      state,\n    }: RunAgentInput,\n    {\n      onMessageId,\n      onTextPart,\n      onReasoningStart,\n      onReasoningPart,\n      onReasoningEnd,\n      onFinishMessagePart,\n      onToolCallStart,\n      onToolCallArgs,\n      onToolCallEnd,\n      onToolResultPart,\n      onToolSuspended,\n      onActivitySnapshot,\n      onActivityDelta,\n      onStateSnapshot,\n      onStateDelta,\n      onError,\n      onRunFinished,\n    }: MastraAgentStreamOptions,\n  ): Promise<void> {\n    const clientTools = tools.reduce(\n      (acc, tool) => {\n        acc[tool.name as string] = {\n          id: tool.name,\n          description: tool.description,\n          inputSchema: tool.parameters,\n        };\n        return acc;\n      },\n      {} as Record<string, any>,\n    );\n    // Names of the frontend tools — only these stream their args live (see\n    // createChunkProcessor). Server tools (on the Mastra agent) are absent here.\n    const clientToolNames = new Set<string>(\n      tools.map((tool) => tool.name as string),\n    );\n    // Seed shared-state diffing from the state the client already holds (its\n    // coagent state, minus the message list the bridge strips before syncing to\n    // working memory). The first mid-run STATE_DELTA then patches from what the\n    // UI shows, not from empty. See createChunkProcessor.\n    const initialState = this.workingMemoryStateSlice(state);\n    const resourceId = this.resourceId ?? threadId;\n\n    // AG-UI clients (e.g. CopilotKit) re-send the entire conversation every\n    // turn. Mastra memory already owns the thread history, so forwarding the\n    // full history re-persists it and balloons storage. Instead we send only\n    // the *new* messages: messages whose id Mastra has not already stored.\n    // This mirrors LangGraph's continuation check (filter incoming against the\n    // checkpoint's message ids) and is faithful because the bridge streams\n    // assistant messages under Mastra's stored id (see onMessageId), so re-sent\n    // history matches and is filtered out. Mastra still loads full history from\n    // memory on read, so the model sees the complete conversation.\n    const messagesToSend = await this.selectNewMessages(\n      threadId,\n      resourceId,\n      messages,\n    );\n    // Convert only the new turn, but resolve tool-message names against the\n    // full incoming history (the assistant tool-call may have been filtered\n    // out of messagesToSend).\n    const convertedMessages = convertAGUIMessagesToMastra(\n      messagesToSend,\n      messages,\n    );\n    const requestContext = this.applyInputContext(inputContext);\n\n    if (this.isLocalMastraAgent(this.agent)) {\n      try {\n        // Auto-inject the backend-owned `generate_a2ui` tool (pillar 1: easy\n        // devex) when the runtime/middleware forwarded `injectA2UITool`. The dev\n        // wires NO tool; recovery + subagent ride along. Injected per-run as a\n        // server toolset so its execute runs in-process (where the loop lives);\n        // the middleware-injected `render_a2ui` client tool is dropped so the\n        // model calls `generate_a2ui`. Opt out via `injectA2UITool:false`;\n        // customize via the `a2ui` config. USER-PREVAILS if the agent already\n        // wires `generate_a2ui`. Best-effort: a failure degrades to no A2UI, the\n        // turn still runs.\n        let a2uiToolsets: Record<string, unknown> | undefined;\n        try {\n          const existing = await this.agent.listTools({ requestContext });\n          const existingToolNames = [\n            ...Object.keys(existing ?? {}),\n            ...clientToolNames,\n          ];\n          const plan = planA2UIInjection({\n            model:\n              this.a2ui?.model ?? (this.agent as { model?: unknown }).model,\n            input: {\n              forwardedProps,\n              context: inputContext,\n              messages,\n              threadId,\n              runId,\n            } as RunAgentInput,\n            existingToolNames,\n            config: this.a2ui,\n          });\n          if (plan) {\n            a2uiToolsets = { a2ui: { [plan.toolName]: plan.tool } };\n            for (const drop of plan.dropToolNames) delete clientTools[drop];\n          }\n        } catch (error) {\n          console.warn(\n            \"[MastraAgent] A2UI auto-injection skipped (continuing without A2UI):\",\n            error,\n          );\n        }\n\n        const streamOptions: Record<string, unknown> = {\n          memory: {\n            thread: threadId,\n            resource: resourceId,\n          },\n          runId,\n          clientTools,\n          requestContext,\n          ...(a2uiToolsets ? { toolsets: a2uiToolsets } : {}),\n        };\n        // Pipe the background-task lifecycle into this run's fullStream (and\n        // re-enter the loop on completion) when opted in. Only meaningful for\n        // local agents with storage + a memory scope; Mastra falls through to\n        // the default stream otherwise.\n        if (this.untilIdle) {\n          streamOptions.untilIdle = this.untilIdle;\n        }\n        if (this.tracingOptions) {\n          streamOptions.tracingOptions = this.tracingOptions;\n        }\n        if (this.headers && Object.keys(this.headers).length > 0) {\n          streamOptions.modelSettings = {\n            ...((streamOptions.modelSettings as\n              | Record<string, unknown>\n              | undefined) ?? {}),\n            headers: this.headers,\n          };\n        }\n        const response = await this.agent.stream(\n          convertedMessages,\n          streamOptions,\n        );\n\n        if (response && typeof response === \"object\") {\n          const hadError = await this.processFullStream(\n            response.fullStream,\n            {\n              onMessageId,\n              onTextPart,\n              onReasoningStart,\n              onReasoningPart,\n              onReasoningEnd,\n              onFinishMessagePart,\n              onToolCallStart,\n              onToolCallArgs,\n              onToolCallEnd,\n              onToolResultPart,\n              onToolSuspended,\n              onActivitySnapshot,\n              onActivityDelta,\n              onStateSnapshot,\n              onStateDelta,\n              onError,\n            },\n            clientToolNames,\n            initialState,\n          );\n\n          if (!hadError) {\n            const traceId = await this.resolveTraceId(response);\n            await onRunFinished?.(traceId);\n          }\n        } else {\n          throw new Error(\"Invalid response from local agent\");\n        }\n      } catch (error) {\n        onError(error as Error);\n      }\n    } else {\n      let stopped = false;\n      try {\n        const streamOptions: Record<string, unknown> = {\n          memory: {\n            thread: threadId,\n            resource: resourceId,\n          },\n          runId,\n          clientTools,\n          requestContext,\n        };\n        if (this.tracingOptions) {\n          streamOptions.tracingOptions = this.tracingOptions;\n        }\n        if (this.headers && Object.keys(this.headers).length > 0) {\n          streamOptions.modelSettings = {\n            ...((streamOptions.modelSettings as\n              | Record<string, unknown>\n              | undefined) ?? {}),\n            headers: this.headers,\n          };\n        }\n        const response = await this.agent.stream(\n          convertedMessages,\n          streamOptions,\n        );\n\n        // Remote agents use processDataStream (callback-based) — share\n        // chunk handling logic via createChunkProcessor.\n        if (response && typeof response.processDataStream === \"function\") {\n          const { handleChunk, flush } = this.createChunkProcessor(\n            {\n              onMessageId,\n              onTextPart,\n              onReasoningStart,\n              onReasoningPart,\n              onReasoningEnd,\n              onFinishMessagePart,\n              onToolCallStart,\n              onToolCallArgs,\n              onToolCallEnd,\n              onToolResultPart,\n              onToolSuspended,\n              onActivitySnapshot,\n              onActivityDelta,\n              onStateSnapshot,\n              onStateDelta,\n              onError,\n            },\n            clientToolNames,\n            initialState,\n          );\n\n          await response.processDataStream({\n            onChunk: async (chunk: any) => {\n              if (stopped) return;\n              if (handleChunk(chunk)) stopped = true;\n            },\n          });\n          if (!stopped) flush();\n          if (!stopped) {\n            const traceId = await this.resolveTraceId(response);\n            await onRunFinished?.(traceId);\n          }\n        } else {\n          throw new Error(\"Invalid response from remote agent\");\n        }\n      } catch (error) {\n        if (!stopped) onError(error as Error);\n      }\n    }\n  }\n\n  static async getRemoteAgents(\n    options: GetRemoteAgentsOptions,\n  ): Promise<Record<string, AbstractAgent>> {\n    return getRemoteAgents(options);\n  }\n\n  static getLocalAgents(\n    options: GetLocalAgentsOptions,\n  ): Record<string, AbstractAgent> {\n    return getLocalAgents(options);\n  }\n\n  static getLocalAgent(options: GetLocalAgentOptions) {\n    return getLocalAgent(options);\n  }\n\n  static getNetwork(options: GetNetworkOptions) {\n    return getNetwork(options);\n  }\n}\n"],"mappings":"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"}