{"version":3,"file":"stream_events.cjs","names":[],"sources":["../../src/utils/stream_events.ts"],"sourcesContent":["/**\n * Converts a raw Anthropic SSE event stream into LangChain ChatModelStreamEvents.\n *\n * @module\n */\n\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n  ChatModelStreamEvent,\n  ContentBlockDelta,\n  FinishReason,\n} from \"@langchain/core/language_models/event\";\nimport type { ContentBlock } from \"@langchain/core/messages/content\";\nimport type { UsageMetadata } from \"@langchain/core/messages/metadata\";\nimport type { AnthropicMessageStreamEvent } from \"../types.js\";\n\n// ─── Public API ─────────────────────────────────────────────────\n\nexport interface ConvertAnthropicStreamOptions {\n  streamUsage?: boolean;\n}\n\n/**\n * Convert an async iterable of raw Anthropic stream events into\n * LangChain `ChatModelStreamEvent`s with typed deltas.\n */\nexport async function* convertAnthropicStream(\n  source: AsyncIterable<AnthropicMessageStreamEvent>,\n  options: ConvertAnthropicStreamOptions = {}\n): AsyncGenerator<ChatModelStreamEvent> {\n  const shouldStreamUsage = options.streamUsage ?? true;\n\n  // Track accumulated state per content block (for finalization)\n  const blockAccumulators = new Map<\n    number,\n    // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n    Record<string, any>\n  >();\n  let usageSnapshot: UsageMetadata | undefined;\n  let stopReason: string | null = null;\n\n  for await (const data of source) {\n    switch (data.type) {\n      // ── Message lifecycle ──────────────────────────────────\n      case \"message_start\": {\n        const { usage, id, model } = data.message;\n        if (usage && shouldStreamUsage) {\n          usageSnapshot = buildUsageSnapshot(usage);\n        }\n        yield {\n          event: \"message-start\" as const,\n          id,\n          ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n        };\n        yield {\n          event: \"provider\" as const,\n          provider: \"anthropic\",\n          name: \"message_start\",\n          payload: { model, id },\n        };\n        break;\n      }\n\n      case \"message_delta\": {\n        stopReason = data.delta.stop_reason;\n        if (shouldStreamUsage && data.usage) {\n          if (!usageSnapshot) {\n            usageSnapshot = {\n              input_tokens: 0,\n              output_tokens: data.usage.output_tokens,\n              total_tokens: data.usage.output_tokens,\n            };\n          } else {\n            usageSnapshot = {\n              ...usageSnapshot,\n              output_tokens:\n                usageSnapshot.output_tokens + data.usage.output_tokens,\n              total_tokens:\n                usageSnapshot.input_tokens +\n                usageSnapshot.output_tokens +\n                data.usage.output_tokens,\n            };\n          }\n          yield { event: \"usage\" as const, usage: usageSnapshot };\n        }\n        if (\n          \"context_management\" in data.delta &&\n          data.delta.context_management\n        ) {\n          yield {\n            event: \"provider\" as const,\n            provider: \"anthropic\",\n            name: \"context_management\",\n            payload: data.delta.context_management,\n          };\n        }\n        break;\n      }\n\n      case \"message_stop\": {\n        yield {\n          event: \"message-finish\" as const,\n          reason: mapStopReason(stopReason),\n          ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n          metadata: { model_provider: \"anthropic\" },\n        };\n        break;\n      }\n\n      // ── Content block lifecycle ───────────────────────────\n      case \"content_block_start\": {\n        const { index, content_block } = data;\n        const mapped = mapBlockToContentBlock(content_block, index);\n        blockAccumulators.set(index, { ...mapped });\n        yield {\n          event: \"content-block-start\" as const,\n          index,\n          content: mapped,\n        };\n        break;\n      }\n\n      case \"content_block_delta\": {\n        const { index, delta } = data;\n        const acc = blockAccumulators.get(index);\n        if (!acc) break;\n\n        const { contentDelta, accumulated } = applyAnthropicDelta(acc, delta);\n        blockAccumulators.set(index, accumulated);\n\n        yield {\n          event: \"content-block-delta\" as const,\n          index,\n          delta: contentDelta,\n        };\n        break;\n      }\n\n      case \"content_block_stop\": {\n        const { index } = data;\n        const acc = blockAccumulators.get(index);\n        if (!acc) break;\n\n        const finalized = finalizeBlock(acc);\n        yield {\n          event: \"content-block-finish\" as const,\n          index,\n          content: finalized,\n        };\n        blockAccumulators.delete(index);\n        break;\n      }\n\n      // ── Unhandled → provider passthrough ───────────────────\n      default: {\n        yield {\n          event: \"provider\" as const,\n          provider: \"anthropic\",\n          name: data.type,\n          payload: data,\n        };\n        break;\n      }\n    }\n  }\n}\n\n// ─── Internal helpers ───────────────────────────────────────────\n\nfunction mapStopReason(stopReason: string | null | undefined): FinishReason {\n  switch (stopReason) {\n    case \"end_turn\":\n    case \"stop_sequence\":\n      return \"stop\";\n    case \"tool_use\":\n      return \"tool_use\";\n    case \"max_tokens\":\n      return \"length\";\n    default:\n      return \"stop\";\n  }\n}\n\nfunction buildUsageSnapshot(\n  usage: Anthropic.Messages.Usage | Record<string, number>\n): UsageMetadata {\n  const cacheCreation =\n    (usage as Record<string, number>).cache_creation_input_tokens ?? 0;\n  const cacheRead =\n    (usage as Record<string, number>).cache_read_input_tokens ?? 0;\n  const totalInput = usage.input_tokens + cacheCreation + cacheRead;\n  return {\n    input_tokens: totalInput,\n    output_tokens: usage.output_tokens,\n    total_tokens: totalInput + usage.output_tokens,\n    input_token_details: {\n      cache_creation: cacheCreation,\n      cache_read: cacheRead,\n    },\n  };\n}\n\nfunction mapBlockToContentBlock(\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  block: any,\n  index: number\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n): Record<string, any> {\n  switch (block.type) {\n    case \"text\":\n      return { type: \"text\" as const, text: block.text ?? \"\", index };\n    case \"thinking\":\n      return {\n        type: \"reasoning\" as const,\n        reasoning: block.thinking ?? \"\",\n        index,\n      };\n    case \"redacted_thinking\":\n      return { type: \"non_standard\" as const, value: { ...block }, index };\n    case \"tool_use\":\n      return {\n        type: \"tool_call_chunk\" as const,\n        id: block.id,\n        name: block.name,\n        args: \"\",\n        index,\n      };\n    case \"server_tool_use\":\n      return {\n        type: \"server_tool_call_chunk\" as const,\n        id: block.id,\n        name: block.name,\n        args: \"\",\n        index,\n      };\n    default:\n      return { type: \"non_standard\" as const, value: { ...block }, index };\n  }\n}\n\n/**\n * Map an Anthropic content_block_delta to a content block delta\n * and update the accumulated state.\n */\nfunction applyAnthropicDelta(\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  accumulated: Record<string, any>,\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  delta: any\n): {\n  contentDelta: ContentBlockDelta;\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  accumulated: Record<string, any>;\n} {\n  switch (delta.type) {\n    case \"text_delta\":\n      return {\n        contentDelta: { type: \"text-delta\" as const, text: delta.text },\n        accumulated: {\n          ...accumulated,\n          text: (accumulated.text ?? \"\") + delta.text,\n        },\n      };\n\n    case \"thinking_delta\":\n      return {\n        contentDelta: {\n          type: \"reasoning-delta\" as const,\n          reasoning: delta.thinking,\n        },\n        accumulated: {\n          ...accumulated,\n          reasoning: (accumulated.reasoning ?? \"\") + delta.thinking,\n        },\n      };\n\n    case \"input_json_delta\": {\n      const newArgs = (accumulated.args ?? \"\") + delta.partial_json;\n      return {\n        contentDelta: {\n          type: \"block-delta\" as const,\n          fields: { type: accumulated.type, args: newArgs },\n        },\n        accumulated: { ...accumulated, args: newArgs },\n      };\n    }\n\n    case \"citations_delta\": {\n      const annotations = [...(accumulated.annotations ?? []), delta.citation];\n      return {\n        contentDelta: {\n          type: \"block-delta\" as const,\n          fields: {\n            type: accumulated.type,\n            annotations,\n          },\n        },\n        accumulated: {\n          ...accumulated,\n          annotations,\n        },\n      };\n    }\n\n    case \"signature_delta\":\n      return {\n        contentDelta: {\n          type: \"block-delta\" as const,\n          fields: { type: accumulated.type, signature: delta.signature },\n        },\n        accumulated: { ...accumulated, signature: delta.signature },\n      };\n\n    case \"compaction_delta\":\n      return {\n        contentDelta: {\n          type: \"block-delta\" as const,\n          fields: {\n            type: \"non_standard\",\n            value: { ...(accumulated.value ?? {}), compaction: delta },\n          },\n        },\n        accumulated: {\n          ...accumulated,\n          value: { ...(accumulated.value ?? {}), compaction: delta },\n        },\n      };\n\n    default:\n      return {\n        contentDelta: {\n          type: \"block-delta\" as const,\n          fields: { type: accumulated.type, ...delta },\n        },\n        accumulated,\n      };\n  }\n}\n\nfunction finalizeBlock(\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  accumulated: Record<string, any>\n): ContentBlock {\n  if (\n    accumulated.type === \"tool_call_chunk\" ||\n    accumulated.type === \"server_tool_call_chunk\"\n  ) {\n    const finalType =\n      accumulated.type === \"tool_call_chunk\"\n        ? (\"tool_call\" as const)\n        : (\"server_tool_call\" as const);\n    let parsedArgs: unknown;\n    try {\n      parsedArgs = JSON.parse(accumulated.args || \"{}\");\n    } catch {\n      return {\n        type: \"invalid_tool_call\" as const,\n        id: accumulated.id,\n        name: accumulated.name,\n        args: accumulated.args,\n        error: \"Failed to parse tool call arguments as JSON\",\n      } as ContentBlock.Tools.InvalidToolCall;\n    }\n    return {\n      type: finalType,\n      id: accumulated.id,\n      name: accumulated.name,\n      args: parsedArgs,\n      // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n    } as any;\n  }\n\n  const { index: _index, ...rest } = accumulated;\n  return rest as ContentBlock;\n}\n"],"mappings":"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"}