{"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, UsageMetadata } from \"@langchain/core/messages\";\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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"}