{"version":3,"file":"tanstack.cjs","names":["EventType"],"sources":["../../../src/agent/converters/tanstack.ts"],"sourcesContent":["import type {\n  BaseEvent,\n  RunAgentInput,\n  Message,\n  TextMessageChunkEvent,\n  ToolCallArgsEvent,\n  ToolCallEndEvent,\n  ToolCallStartEvent,\n  ToolCallResultEvent,\n  StateSnapshotEvent,\n  StateDeltaEvent,\n  ReasoningStartEvent,\n  ReasoningMessageStartEvent,\n  ReasoningMessageContentEvent,\n  ReasoningMessageEndEvent,\n  ReasoningEndEvent,\n} from \"@ag-ui/client\";\nimport { EventType } from \"@ag-ui/client\";\nimport { randomUUID } from \"@copilotkit/shared\";\n\ntype ContentPartSource =\n  | { type: \"data\"; value: string; mimeType: string }\n  | { type: \"url\"; value: string; mimeType?: string };\n\n/**\n * A TanStack AI content part (text, image, audio, video, or document).\n */\nexport type TanStackContentPart =\n  | { type: \"text\"; content: string }\n  | { type: \"image\"; source: ContentPartSource }\n  | { type: \"audio\"; source: ContentPartSource }\n  | { type: \"video\"; source: ContentPartSource }\n  | { type: \"document\"; source: ContentPartSource };\n\n/**\n * Message format expected by TanStack AI's `chat()`.\n *\n * Content is typed as `any[]` for the multimodal case so messages are directly\n * passable to any adapter without casts — different adapters constrain which\n * modalities they accept (e.g. OpenAI only allows text + image).\n * Use `TanStackContentPart` to inspect individual parts if needed.\n */\nexport interface TanStackChatMessage {\n  role: \"user\" | \"assistant\" | \"tool\";\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  content: string | null | any[];\n  name?: string;\n  toolCalls?: Array<{\n    id: string;\n    type: \"function\";\n    function: { name: string; arguments: string };\n  }>;\n  toolCallId?: string;\n}\n\n/**\n * A TanStack AI client-side tool, derived from a frontend-provided AG-UI tool.\n *\n * Shaped to match `@tanstack/ai`'s `ClientTool` (`__toolSide: \"client\"`, no\n * `execute`): the model may CALL it, but TanStack does not run it — it pauses\n * the run and hands the call back to the AG-UI client (the CopilotKit frontend\n * / bot) to execute, mirroring CopilotKit's client-tool round-trip. `chat()`\n * accepts a JSON Schema directly as `inputSchema`, so the AG-UI tool's\n * `parameters` pass through unchanged.\n */\nexport interface TanStackClientTool {\n  __toolSide: \"client\";\n  name: string;\n  description: string;\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  inputSchema: any;\n}\n\n/**\n * Result of converting RunAgentInput to TanStack AI format.\n */\nexport interface TanStackInputResult {\n  /** Chat messages (only user/assistant/tool roles; all others excluded) */\n  messages: TanStackChatMessage[];\n  /** System prompts extracted from system/developer messages, context, and state */\n  systemPrompts: string[];\n  /**\n   * Client-side tools derived from `input.tools` (the frontend-provided tools\n   * the CopilotKit client forwards on every run). Pass these into `chat()`\n   * alongside any server/provider tools so the model can call the frontend's\n   * generative-UI and human-in-the-loop tools; TanStack pauses the run on a\n   * client-tool call and the client executes it.\n   */\n  tools: TanStackClientTool[];\n}\n\n/**\n * Converts AG-UI user message content to TanStack AI format.\n * Handles plain strings, multimodal parts (image/audio/video/document),\n * and legacy BinaryInputContent for backward compatibility.\n */\nfunction convertUserContent(\n  content: unknown,\n): string | null | TanStackContentPart[] {\n  if (!content) return null;\n  if (typeof content === \"string\") return content;\n  if (!Array.isArray(content)) return null;\n  if (content.length === 0) return \"\";\n\n  const parts: TanStackContentPart[] = [];\n\n  for (const part of content) {\n    if (!part || typeof part !== \"object\" || !(\"type\" in part)) continue;\n\n    switch ((part as { type: string }).type) {\n      case \"text\": {\n        const text = (part as { text?: string }).text;\n        if (text != null) parts.push({ type: \"text\", content: text });\n        break;\n      }\n\n      case \"image\":\n      case \"audio\":\n      case \"video\":\n      case \"document\": {\n        const source = (part as { source?: any }).source;\n        if (!source) break;\n        const partType = (part as { type: string }).type as\n          | \"image\"\n          | \"audio\"\n          | \"video\"\n          | \"document\";\n        if (source.type === \"data\") {\n          parts.push({\n            type: partType,\n            source: {\n              type: \"data\",\n              value: source.value,\n              mimeType: source.mimeType,\n            },\n          });\n        } else if (source.type === \"url\") {\n          parts.push({\n            type: partType,\n            source: {\n              type: \"url\",\n              value: source.value,\n              ...(source.mimeType ? { mimeType: source.mimeType } : {}),\n            },\n          });\n        }\n        break;\n      }\n\n      // Legacy BinaryInputContent backward compatibility\n      case \"binary\": {\n        const legacy = part as {\n          mimeType?: string;\n          data?: string;\n          url?: string;\n        };\n        const mimeType = legacy.mimeType ?? \"application/octet-stream\";\n        const isImage = mimeType.startsWith(\"image/\");\n\n        if (legacy.data) {\n          const partType = isImage ? \"image\" : \"document\";\n          parts.push({\n            type: partType,\n            source: { type: \"data\", value: legacy.data, mimeType },\n          });\n        } else if (legacy.url) {\n          const partType = isImage ? \"image\" : \"document\";\n          parts.push({\n            type: partType,\n            source: { type: \"url\", value: legacy.url, mimeType },\n          });\n        }\n        break;\n      }\n    }\n  }\n\n  return parts.length > 0 ? parts : \"\";\n}\n\n/**\n * Recursively normalizes a frontend tool's JSON Schema so OpenAI accepts it as\n * a function-tool schema.\n *\n * Frontend tools are often authored with permissive Zod (`z.any()`,\n * `z.record(...)`, `.passthrough()`), which serialize to open objects —\n * `additionalProperties: {}` (an empty sub-schema) or `additionalProperties:\n * true`. OpenAI rejects both: strict mode requires `additionalProperties:\n * false`, and an empty `{}` sub-schema fails base validation (\"schema must\n * have a 'type' key\"). The classic (Vercel AI SDK) path sanitized these\n * implicitly via a Zod round-trip; the TanStack path forwards the raw schema,\n * so we close open objects here to match. (Models can't supply free-form extra\n * keys either way — same as the classic path.)\n */\nfunction sanitizeClientToolSchema(schema: unknown): unknown {\n  if (Array.isArray(schema)) {\n    return schema.map(sanitizeClientToolSchema);\n  }\n  if (!schema || typeof schema !== \"object\") {\n    return schema;\n  }\n  const node: Record<string, unknown> = {\n    ...(schema as Record<string, unknown>),\n  };\n\n  // Any `additionalProperties` (empty `{}`, `true`, or a sub-schema) becomes\n  // `false` — the only form OpenAI accepts for strict function tools.\n  if (\"additionalProperties\" in node) {\n    node.additionalProperties = false;\n  }\n\n  if (node.properties && typeof node.properties === \"object\") {\n    const props: Record<string, unknown> = {};\n    for (const [key, value] of Object.entries(\n      node.properties as Record<string, unknown>,\n    )) {\n      props[key] = sanitizeClientToolSchema(value);\n    }\n    node.properties = props;\n  }\n\n  if (\"items\" in node) {\n    node.items = sanitizeClientToolSchema(node.items);\n  }\n\n  for (const combinator of [\"anyOf\", \"allOf\", \"oneOf\"] as const) {\n    if (Array.isArray(node[combinator])) {\n      node[combinator] = (node[combinator] as unknown[]).map(\n        sanitizeClientToolSchema,\n      );\n    }\n  }\n\n  return node;\n}\n\n/**\n * Converts a RunAgentInput into the format expected by TanStack AI's `chat()`.\n *\n * - Keeps only user/assistant/tool messages (activity, reasoning, and other roles are also excluded)\n * - Extracts system/developer messages into `systemPrompts`\n * - Appends context entries and application state to `systemPrompts`\n * - Preserves tool calls on assistant messages and toolCallId on tool messages\n */\nexport function convertInputToTanStackAI(\n  input: RunAgentInput,\n): TanStackInputResult {\n  // Allowlist: only pass user/assistant/tool messages to TanStack.\n  // Other roles (system, developer, activity, reasoning) are either\n  // extracted into systemPrompts or not applicable.\n  const chatRoles = new Set([\"user\", \"assistant\", \"tool\"]);\n  const messages: TanStackChatMessage[] = input.messages\n    .filter((m: Message) => chatRoles.has(m.role))\n    .map((m: Message): TanStackChatMessage => {\n      const msg: TanStackChatMessage = {\n        role: m.role as \"user\" | \"assistant\" | \"tool\",\n        content:\n          m.role === \"user\"\n            ? convertUserContent(m.content)\n            : typeof m.content === \"string\"\n              ? m.content\n              : null,\n      };\n      if (m.role === \"assistant\" && \"toolCalls\" in m && m.toolCalls) {\n        msg.toolCalls = m.toolCalls.map((tc) => ({\n          id: tc.id,\n          type: \"function\" as const,\n          function: {\n            name: tc.function.name,\n            arguments: tc.function.arguments,\n          },\n        }));\n      }\n      if (m.role === \"tool\" && \"toolCallId\" in m) {\n        msg.toolCallId = (m as Record<string, unknown>).toolCallId as string;\n      }\n      return msg;\n    });\n\n  const systemPrompts: string[] = [];\n  for (const m of input.messages) {\n    if ((m.role === \"system\" || m.role === \"developer\") && m.content) {\n      systemPrompts.push(\n        typeof m.content === \"string\" ? m.content : JSON.stringify(m.content),\n      );\n    }\n  }\n\n  if (input.context?.length) {\n    for (const ctx of input.context) {\n      systemPrompts.push(`${ctx.description}:\\n${ctx.value}`);\n    }\n  }\n\n  if (\n    input.state !== undefined &&\n    input.state !== null &&\n    typeof input.state === \"object\" &&\n    Object.keys(input.state).length > 0\n  ) {\n    systemPrompts.push(\n      `Application State:\\n\\`\\`\\`json\\n${JSON.stringify(input.state, null, 2)}\\n\\`\\`\\``,\n    );\n  }\n\n  // Frontend-provided tools become client-side TanStack tools (no executor):\n  // the model can call them, TanStack pauses the run, and the AG-UI client\n  // executes them and resumes — the CopilotKit client-tool round-trip.\n  const tools: TanStackClientTool[] = (input.tools ?? []).map((t) => ({\n    __toolSide: \"client\",\n    name: t.name,\n    description: t.description,\n    inputSchema: sanitizeClientToolSchema(t.parameters),\n  }));\n\n  return { messages, systemPrompts, tools };\n}\n\n/**\n * Converts a TanStack AI stream into AG-UI `BaseEvent` objects.\n *\n * This is a pure converter — it does NOT emit lifecycle events\n * (RUN_STARTED / RUN_FINISHED / RUN_ERROR). The caller (Agent class)\n * is responsible for those.\n */\nexport async function* convertTanStackStream(\n  stream: AsyncIterable<unknown>,\n  abortSignal: AbortSignal,\n): AsyncGenerator<BaseEvent> {\n  const messageId = randomUUID();\n  const toolNamesById = new Map<string, string>();\n  // Track the reasoning lifecycle at two granularities so closeReasoningIfOpen\n  // emits exactly the events still owed. A single boolean conflates the run\n  // (REASONING_START → REASONING_END) with the message\n  // (REASONING_MESSAGE_START → REASONING_MESSAGE_END) and produces a duplicate\n  // REASONING_MESSAGE_END when upstream emits MSG_END but not END before\n  // text/tools resume.\n  let reasoningRunOpen = false;\n  let reasoningMessageOpen = false;\n  let reasoningMessageId = randomUUID();\n\n  function* closeReasoningIfOpen(): Generator<BaseEvent> {\n    if (reasoningMessageOpen) {\n      reasoningMessageOpen = false;\n      const msgEnd: ReasoningMessageEndEvent = {\n        type: EventType.REASONING_MESSAGE_END,\n        messageId: reasoningMessageId,\n      };\n      yield msgEnd;\n    }\n    if (reasoningRunOpen) {\n      reasoningRunOpen = false;\n      const end: ReasoningEndEvent = {\n        type: EventType.REASONING_END,\n        messageId: reasoningMessageId,\n      };\n      yield end;\n    }\n  }\n\n  // TanStack's chat() engine runs a multi-turn agent loop and emits a\n  // RUN_STARTED / RUN_FINISHED pair PER model turn — not once for the whole\n  // run. When it executes a tool itself (an MCP server tool or a provider tool\n  // like web_search), it does so between turns and streams a TOOL_CALL_RESULT\n  // followed by the next turn's text. The overall run lifecycle is owned by the\n  // Agent wrapper (it emits exactly one outer RUN_STARTED / RUN_FINISHED), so\n  // we drop TanStack's per-turn lifecycle markers and convert every content\n  // event across all turns. (A previous version stopped converting at the first\n  // RUN_FINISHED — that truncated the run at the first tool turn and silently\n  // dropped both the tool result and the model's final answer.)\n  //\n  // chat() can re-announce a tool call when it re-prompts after executing it,\n  // so START / END are de-duplicated by toolCallId to avoid emitting a pair\n  // twice (which would violate the ag-ui verify middleware).\n  const startedToolCalls = new Set<string>();\n  const endedToolCalls = new Set<string>();\n\n  for await (const chunk of stream) {\n    if (abortSignal.aborted) break;\n\n    const raw = chunk as Record<string, unknown>;\n    const type = raw.type as string;\n\n    // Per-turn lifecycle markers are owned by the Agent wrapper, not forwarded.\n    if (type === \"RUN_STARTED\" || type === \"RUN_FINISHED\") {\n      continue;\n    }\n\n    // Surface engine errors instead of dropping them: throw so the Agent\n    // wrapper emits a terminal RUN_ERROR. Without this a failed run (e.g. a\n    // provider 4xx) would finish empty with no indication of what went wrong.\n    if (type === \"RUN_ERROR\") {\n      throw new Error(\n        typeof raw.message === \"string\" ? raw.message : \"TanStack AI run error\",\n      );\n    }\n\n    if (type === \"TEXT_MESSAGE_CONTENT\" && raw.delta != null) {\n      yield* closeReasoningIfOpen();\n      const textEvent: TextMessageChunkEvent = {\n        type: EventType.TEXT_MESSAGE_CHUNK,\n        role: \"assistant\",\n        messageId,\n        delta: raw.delta as string,\n      };\n      yield textEvent;\n    } else if (type === \"TOOL_CALL_START\") {\n      const toolCallId = raw.toolCallId as string;\n      if (startedToolCalls.has(toolCallId)) continue;\n      startedToolCalls.add(toolCallId);\n      yield* closeReasoningIfOpen();\n      toolNamesById.set(toolCallId, raw.toolCallName as string);\n      const startEvent: ToolCallStartEvent = {\n        type: EventType.TOOL_CALL_START,\n        parentMessageId: messageId,\n        toolCallId,\n        toolCallName: raw.toolCallName as string,\n      };\n      yield startEvent;\n    } else if (type === \"TOOL_CALL_ARGS\") {\n      // Drop args re-announced after the call has ended (the re-prompt pass);\n      // forwarding them would corrupt the already-closed call's accumulated args.\n      if (endedToolCalls.has(raw.toolCallId as string)) continue;\n      yield* closeReasoningIfOpen();\n      const argsEvent: ToolCallArgsEvent = {\n        type: EventType.TOOL_CALL_ARGS,\n        toolCallId: raw.toolCallId as string,\n        delta: raw.delta as string,\n      };\n      yield argsEvent;\n    } else if (type === \"TOOL_CALL_END\") {\n      const toolCallId = raw.toolCallId as string;\n      if (endedToolCalls.has(toolCallId)) continue;\n      endedToolCalls.add(toolCallId);\n      yield* closeReasoningIfOpen();\n      const endEvent: ToolCallEndEvent = {\n        type: EventType.TOOL_CALL_END,\n        toolCallId,\n      };\n      yield endEvent;\n    } else if (type === \"TOOL_CALL_RESULT\") {\n      yield* closeReasoningIfOpen();\n      const toolCallId = raw.toolCallId as string;\n      const toolName = toolNamesById.get(toolCallId);\n      // Accept the payload from either `content` (canonical TanStack shape)\n      // or `result` (alternate shape used by some adapters / tests). Both\n      // state-tool detection and the final TOOL_CALL_RESULT serialization\n      // must read the same field, otherwise STATE_SNAPSHOT/STATE_DELTA can\n      // be silently dropped when upstream uses `result`.\n      const rawPayload = raw.content ?? raw.result;\n\n      const parsedContent =\n        typeof rawPayload === \"string\" ? safeParse(rawPayload) : rawPayload;\n\n      if (\n        toolName === \"AGUISendStateSnapshot\" &&\n        parsedContent &&\n        typeof parsedContent === \"object\" &&\n        \"snapshot\" in parsedContent\n      ) {\n        const stateSnapshotEvent: StateSnapshotEvent = {\n          type: EventType.STATE_SNAPSHOT,\n          snapshot: (parsedContent as Record<string, unknown>).snapshot,\n        };\n        yield stateSnapshotEvent;\n      }\n\n      if (\n        toolName === \"AGUISendStateDelta\" &&\n        parsedContent &&\n        typeof parsedContent === \"object\" &&\n        \"delta\" in parsedContent\n      ) {\n        const stateDeltaEvent: StateDeltaEvent = {\n          type: EventType.STATE_DELTA,\n          delta: (parsedContent as Record<string, unknown>).delta as never,\n        };\n        yield stateDeltaEvent;\n      }\n\n      let serializedContent: string;\n      if (typeof rawPayload === \"string\") {\n        serializedContent = rawPayload;\n      } else {\n        try {\n          serializedContent = JSON.stringify(rawPayload ?? null);\n        } catch {\n          serializedContent = \"[Unserializable tool result]\";\n        }\n      }\n\n      const resultEvent: ToolCallResultEvent = {\n        type: EventType.TOOL_CALL_RESULT,\n        role: \"tool\",\n        messageId: randomUUID(),\n        toolCallId,\n        content: serializedContent,\n      };\n      yield resultEvent;\n      toolNamesById.delete(toolCallId);\n    } else if (type === \"REASONING_START\") {\n      // If a prior reasoning run is still open (no REASONING_END before this\n      // new START), close it cleanly first so MSG_END / END pair correctly.\n      yield* closeReasoningIfOpen();\n      reasoningRunOpen = true;\n      reasoningMessageId = (raw.messageId as string) ?? randomUUID();\n      const startEvt: ReasoningStartEvent = {\n        type: EventType.REASONING_START,\n        messageId: reasoningMessageId,\n      };\n      yield startEvt;\n    } else if (type === \"REASONING_MESSAGE_START\") {\n      reasoningMessageOpen = true;\n      const evt: ReasoningMessageStartEvent = {\n        type: EventType.REASONING_MESSAGE_START,\n        messageId: reasoningMessageId,\n        role: \"reasoning\",\n      };\n      yield evt;\n    } else if (type === \"REASONING_MESSAGE_CONTENT\") {\n      const evt: ReasoningMessageContentEvent = {\n        type: EventType.REASONING_MESSAGE_CONTENT,\n        messageId: reasoningMessageId,\n        delta: raw.delta as string,\n      };\n      yield evt;\n    } else if (type === \"REASONING_MESSAGE_END\") {\n      reasoningMessageOpen = false;\n      const evt: ReasoningMessageEndEvent = {\n        type: EventType.REASONING_MESSAGE_END,\n        messageId: reasoningMessageId,\n      };\n      yield evt;\n    } else if (type === \"REASONING_END\") {\n      // If upstream sends REASONING_END while a message is still open, emit\n      // the missing REASONING_MESSAGE_END FIRST so the closing pair stays in\n      // order (MSG_END before END). Otherwise the next non-reasoning chunk\n      // would trigger closeReasoningIfOpen and emit MSG_END after END.\n      if (reasoningMessageOpen) {\n        reasoningMessageOpen = false;\n        const msgEnd: ReasoningMessageEndEvent = {\n          type: EventType.REASONING_MESSAGE_END,\n          messageId: reasoningMessageId,\n        };\n        yield msgEnd;\n      }\n      reasoningRunOpen = false;\n      const evt: ReasoningEndEvent = {\n        type: EventType.REASONING_END,\n        messageId: reasoningMessageId,\n      };\n      yield evt;\n    }\n  }\n\n  yield* closeReasoningIfOpen();\n}\n\nfunction safeParse(value: string): unknown {\n  try {\n    return JSON.parse(value);\n  } catch {\n    return value;\n  }\n}\n"],"mappings":"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"}