UNPKG

@langchain/core

Version:
1 lines 23.4 kB
{"version":3,"file":"compat.cjs","names":["AIMessageChunk"],"sources":["../../src/language_models/compat.ts"],"sourcesContent":["/**\n * Compatibility bridge: converts legacy `_streamResponseChunks`\n * (`ChatGenerationChunk` / `AIMessageChunk`) output to the new\n * `ChatModelStreamEvent` protocol.\n *\n * @module\n */\n\nimport { AIMessageChunk } from \"../messages/ai.js\";\nimport type { ContentBlock } from \"../messages/content/index.js\";\nimport type { ChatGenerationChunk } from \"../outputs.js\";\nimport type { ChatModelStreamEvent, ContentBlockDelta } from \"./event.js\";\n\nconst MIME_TYPE_BY_AUDIO_FORMAT: Record<string, string> = {\n wav: \"audio/wav\",\n mp3: \"audio/mpeg\",\n flac: \"audio/flac\",\n opus: \"audio/opus\",\n aac: \"audio/aac\",\n pcm16: \"audio/pcm\",\n};\n\nconst MIME_TYPE_BY_IMAGE_FORMAT: Record<string, string> = {\n png: \"image/png\",\n jpeg: \"image/jpeg\",\n jpg: \"image/jpeg\",\n webp: \"image/webp\",\n gif: \"image/gif\",\n};\n\ntype AudioStreamState = {\n index: number;\n id?: string;\n mimeType: string;\n transcript: string;\n};\n\nfunction nextBlockIndex(activeBlocks: Map<number, unknown>): number {\n let next = 0;\n for (const index of activeBlocks.keys()) {\n if (index >= next) next = index + 1;\n }\n return next;\n}\n\nfunction getAdditionalKwargs(message: unknown): Record<string, unknown> {\n const additional = (message as { additional_kwargs?: unknown })\n .additional_kwargs;\n return additional != null && typeof additional === \"object\"\n ? (additional as Record<string, unknown>)\n : {};\n}\n\nfunction extractImageBlocksFromToolOutputs(message: unknown): ContentBlock[] {\n const toolOutputs = getAdditionalKwargs(message).tool_outputs;\n if (!Array.isArray(toolOutputs)) return [];\n\n const blocks: ContentBlock[] = [];\n for (const entry of toolOutputs) {\n if (entry == null || typeof entry !== \"object\") continue;\n const record = entry as Record<string, unknown>;\n if (record.type !== \"image_generation_call\") continue;\n\n const data = typeof record.result === \"string\" ? record.result : undefined;\n const url = typeof record.url === \"string\" ? record.url : undefined;\n if (data == null && url == null) continue;\n\n const outputFormat =\n typeof record.output_format === \"string\"\n ? record.output_format.toLowerCase()\n : undefined;\n const mimeType =\n (outputFormat != null\n ? MIME_TYPE_BY_IMAGE_FORMAT[outputFormat]\n : undefined) ?? \"image/png\";\n\n blocks.push({\n type: \"image\",\n ...(typeof record.id === \"string\" ? { id: record.id } : {}),\n ...(url != null ? { url } : {}),\n ...(data != null ? { data } : {}),\n mimeType,\n } as ContentBlock);\n }\n return blocks;\n}\n\n/**\n * Get the audio payload from the message.\n *\n * This handles the OpenAI-shaped `additional_kwargs.audio` payload used by\n * legacy chunk streams; other providers must normalize into this shape first.\n *\n * @param message - The message to get the audio payload from.\n * @returns The audio payload.\n * @internal\n */\nfunction getAudioPayload(message: unknown):\n | {\n id?: string;\n data?: string;\n url?: string;\n transcript?: string;\n mimeType: string;\n }\n | undefined {\n const audio = getAdditionalKwargs(message).audio;\n if (audio == null || typeof audio !== \"object\") return undefined;\n const record = audio as Record<string, unknown>;\n\n const data = typeof record.data === \"string\" ? record.data : undefined;\n const url = typeof record.url === \"string\" ? record.url : undefined;\n const transcript =\n typeof record.transcript === \"string\" ? record.transcript : undefined;\n if (data == null && url == null && transcript == null) return undefined;\n\n const explicitMimeType =\n typeof record.mime_type === \"string\"\n ? record.mime_type\n : typeof record.mimeType === \"string\"\n ? record.mimeType\n : undefined;\n const format =\n typeof record.format === \"string\" ? record.format.toLowerCase() : undefined;\n const mimeType =\n explicitMimeType ??\n (format != null ? MIME_TYPE_BY_AUDIO_FORMAT[format] : undefined) ??\n (data != null ? \"audio/wav\" : \"audio/pcm\");\n\n return {\n ...(typeof record.id === \"string\" ? { id: record.id } : {}),\n ...(data != null ? { data } : {}),\n ...(url != null ? { url } : {}),\n ...(transcript != null ? { transcript } : {}),\n mimeType,\n };\n}\n\n/**\n * Convert an async iterable of legacy `ChatGenerationChunk`s into\n * `ChatModelStreamEvent`s with typed deltas.\n */\nexport async function* convertChunksToEvents(\n chunks: AsyncIterable<ChatGenerationChunk>,\n options?: { signal?: AbortSignal }\n): AsyncGenerator<ChatModelStreamEvent> {\n const activeBlocks = new Map<\n number,\n { type: string; accumulated: ContentBlock }\n >();\n let messageStarted = false;\n let lastUsage:\n | { input_tokens: number; output_tokens: number; total_tokens: number }\n | undefined;\n let audioStream: AudioStreamState | undefined;\n const emittedImageKeys = new Set<string>();\n\n for await (const chunk of chunks) {\n options?.signal?.throwIfAborted();\n\n const msg = chunk.message;\n\n // Message start\n let usageHandledInStart = false;\n if (!messageStarted) {\n messageStarted = true;\n const startEvent: ChatModelStreamEvent = {\n event: \"message-start\" as const,\n id: msg.id ?? undefined,\n };\n if (AIMessageChunk.isInstance(msg) && msg.usage_metadata) {\n (startEvent as { usage?: unknown }).usage = msg.usage_metadata;\n lastUsage = { ...msg.usage_metadata };\n usageHandledInStart = true;\n }\n yield startEvent;\n }\n\n // Process content\n const content = msg.content;\n if (typeof content === \"string\") {\n if (content !== \"\") {\n const blockIndex = 0;\n if (!activeBlocks.has(blockIndex)) {\n const initial: ContentBlock.Text = { type: \"text\", text: \"\" };\n activeBlocks.set(blockIndex, {\n type: \"text\",\n accumulated: initial,\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: initial,\n };\n }\n const block = activeBlocks.get(blockIndex)!;\n block.accumulated = {\n ...block.accumulated,\n text: ((block.accumulated as { text?: string }).text ?? \"\") + content,\n };\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta: { type: \"text-delta\" as const, text: content },\n };\n }\n } else if (Array.isArray(content)) {\n for (const part of content) {\n const blockIndex =\n typeof part.index === \"number\" ? part.index : activeBlocks.size;\n\n if (!activeBlocks.has(blockIndex)) {\n activeBlocks.set(blockIndex, {\n type: part.type,\n accumulated: { ...part },\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: { ...part },\n };\n } else {\n const block = activeBlocks.get(blockIndex)!;\n const delta = contentBlockToDelta(part);\n block.accumulated = applyDeltaToBlock(block.accumulated, delta);\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta,\n };\n }\n }\n }\n\n // Tool call chunks\n if (\n AIMessageChunk.isInstance(msg) &&\n msg.tool_call_chunks &&\n msg.tool_call_chunks.length > 0\n ) {\n for (const toolChunk of msg.tool_call_chunks) {\n const blockIndex =\n typeof toolChunk.index === \"number\"\n ? toolChunk.index\n : activeBlocks.size;\n\n if (!activeBlocks.has(blockIndex)) {\n const initial: ContentBlock = {\n type: \"tool_call_chunk\" as const,\n id: toolChunk.id,\n name: toolChunk.name,\n args: \"\",\n index: blockIndex,\n };\n activeBlocks.set(blockIndex, {\n type: \"tool_call_chunk\",\n accumulated: initial,\n });\n yield {\n event: \"content-block-start\" as const,\n index: blockIndex,\n content: initial,\n };\n }\n\n // Accumulate tool call args internally, emit incremental content chunks.\n const block = activeBlocks.get(blockIndex)!;\n const acc = block.accumulated as {\n args?: string;\n id?: string;\n name?: string;\n };\n if (toolChunk.id != null) acc.id = toolChunk.id;\n if (toolChunk.name != null) acc.name = toolChunk.name;\n acc.args = (acc.args ?? \"\") + (toolChunk.args ?? \"\");\n yield {\n event: \"content-block-delta\" as const,\n index: blockIndex,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(\"id\" in acc && acc.id != null ? { id: acc.id } : {}),\n ...(\"name\" in acc && acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n }\n }\n\n const audioPayload = getAudioPayload(msg);\n if (audioPayload != null) {\n if (audioStream == null) {\n const index = nextBlockIndex(activeBlocks);\n audioStream = {\n index,\n id: audioPayload.id,\n mimeType: audioPayload.mimeType,\n transcript: \"\",\n };\n const initial = {\n type: \"audio\",\n ...(audioPayload.id != null ? { id: audioPayload.id } : {}),\n ...(audioPayload.url != null ? { url: audioPayload.url } : {}),\n data: \"\",\n mimeType: audioPayload.mimeType,\n } as ContentBlock;\n activeBlocks.set(index, {\n type: \"audio\",\n accumulated: initial,\n });\n yield {\n event: \"content-block-start\" as const,\n index,\n content: initial,\n };\n }\n\n const activeAudio = activeBlocks.get(audioStream.index);\n if (activeAudio != null) {\n const accumulated = activeAudio.accumulated as ContentBlock & {\n data?: string;\n transcript?: string;\n };\n if (audioPayload.id != null && audioStream.id == null) {\n audioStream.id = audioPayload.id;\n (accumulated as { id?: string }).id = audioPayload.id;\n }\n if (audioPayload.transcript != null) {\n audioStream.transcript += audioPayload.transcript;\n accumulated.transcript = audioStream.transcript;\n yield {\n event: \"content-block-delta\" as const,\n index: audioStream.index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"audio\",\n transcript: audioStream.transcript,\n },\n },\n };\n }\n if (audioPayload.data != null && audioPayload.data.length > 0) {\n accumulated.data = (accumulated.data ?? \"\") + audioPayload.data;\n yield {\n event: \"content-block-delta\" as const,\n index: audioStream.index,\n delta: {\n type: \"data-delta\" as const,\n data: audioPayload.data,\n encoding: \"base64\" as const,\n },\n };\n }\n }\n }\n\n for (const imageBlock of extractImageBlocksFromToolOutputs(msg)) {\n const imageRecord = imageBlock as ContentBlock & {\n id?: string;\n url?: string;\n data?: string;\n };\n const imageKey =\n imageRecord.id ??\n imageRecord.url ??\n (imageRecord.data != null\n ? `${imageRecord.data.length}:${imageRecord.data.slice(0, 32)}`\n : undefined);\n if (imageKey != null && emittedImageKeys.has(imageKey)) continue;\n if (imageKey != null) emittedImageKeys.add(imageKey);\n\n const index = nextBlockIndex(activeBlocks);\n activeBlocks.set(index, {\n type: \"image\",\n accumulated: imageBlock,\n });\n yield {\n event: \"content-block-start\" as const,\n index,\n content: imageBlock,\n };\n }\n\n // Usage\n if (\n !usageHandledInStart &&\n AIMessageChunk.isInstance(msg) &&\n msg.usage_metadata\n ) {\n const chunkUsage = msg.usage_metadata;\n if (!lastUsage) {\n lastUsage = { ...chunkUsage };\n } else {\n lastUsage = {\n input_tokens: lastUsage.input_tokens + chunkUsage.input_tokens,\n output_tokens: lastUsage.output_tokens + chunkUsage.output_tokens,\n total_tokens: lastUsage.total_tokens + chunkUsage.total_tokens,\n };\n }\n yield { event: \"usage\" as const, usage: { ...lastUsage } };\n }\n }\n\n // Finish all blocks\n for (const [index, block] of activeBlocks) {\n const finalized = finalizeContentBlock(block.accumulated);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalized,\n };\n }\n\n yield {\n event: \"message-finish\" as const,\n reason: \"stop\" as const,\n ...(lastUsage ? { usage: lastUsage } : {}),\n };\n}\n\n/**\n * Apply a typed delta to an accumulated content block.\n * @internal\n */\nfunction applyDeltaToBlock(\n block: ContentBlock,\n delta: ContentBlockDelta\n): ContentBlock {\n switch (delta.type) {\n case \"text-delta\":\n if (block.type === \"text\") {\n return {\n ...block,\n text: (block.text ?? \"\") + delta.text,\n };\n }\n return block;\n case \"reasoning-delta\":\n if (block.type === \"thinking\") {\n return {\n ...block,\n thinking: (block.thinking ?? \"\") + delta.reasoning,\n };\n }\n if (block.type === \"reasoning\") {\n return {\n ...block,\n reasoning: (block.reasoning ?? \"\") + delta.reasoning,\n };\n }\n return block;\n case \"data-delta\":\n return {\n ...block,\n data: (block.data ?? \"\") + delta.data,\n };\n case \"block-delta\":\n return { ...block, ...delta.fields } as ContentBlock;\n default:\n throw new Error(`Unknown delta type: ${JSON.stringify(delta)}`);\n }\n}\n\nfunction contentBlockToDelta(block: ContentBlock): ContentBlockDelta {\n if (block.type === \"text\") {\n return { type: \"text-delta\", text: (block as ContentBlock.Text).text };\n }\n if (block.type === \"reasoning\") {\n return {\n type: \"reasoning-delta\",\n reasoning: (block as ContentBlock.Reasoning).reasoning,\n };\n }\n if (block.type === \"thinking\" && typeof block.thinking === \"string\") {\n return {\n type: \"reasoning-delta\",\n reasoning: block.thinking,\n };\n }\n if (typeof block.data === \"string\") {\n return {\n type: \"data-delta\",\n data: block.data,\n encoding: \"base64\",\n };\n }\n if (typeof block.type === \"string\") {\n return {\n type: \"block-delta\",\n fields: {\n ...(block as unknown as { type: string } & Record<string, unknown>),\n },\n };\n }\n\n throw new Error(`Unsupported content block delta: ${JSON.stringify(block)}`);\n}\n\n/**\n * Finalize a content block for the finish event.\n * For tool calls, parse the accumulated JSON args string.\n */\nexport function finalizeContentBlock(block: ContentBlock): ContentBlock {\n if (block.type === \"tool_call_chunk\") {\n const chunk = block as ContentBlock.Tools.ToolCallChunk;\n let parsedArgs: unknown;\n try {\n parsedArgs = JSON.parse(chunk.args ?? \"{}\");\n } catch {\n return {\n type: \"invalid_tool_call\" as const,\n id: chunk.id,\n name: chunk.name,\n args: chunk.args,\n error: \"Failed to parse tool call arguments as JSON\",\n } as ContentBlock.Tools.InvalidToolCall;\n }\n return {\n type: \"tool_call\" as const,\n id: chunk.id,\n name: chunk.name!,\n args: parsedArgs,\n } as ContentBlock.Tools.ToolCall;\n }\n\n return block;\n}\n"],"mappings":"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"}