UNPKG

@langchain/langgraph-sdk

Version:

Client library for interacting with the LangGraph API

159 lines (158 loc) • 5.73 kB
require("../_virtual/_rolldown/runtime.cjs"); let _langchain_core_messages = require("@langchain/core/messages"); //#region src/stream/assembled-to-message.ts /** * Convert the protocol-native {@link AssembledMessage} (a namespace + * content-block bag) into a class instance from * `@langchain/core/messages`. * * The v2 messages channel carries `role` on the `message-start` * event, but `MessageAssembler` drops it by the time it produces an * `AssembledMessage`. The selector-side caller therefore captures the * role separately (via the assembler's per-update hook, see * `projections/messages.ts`) and passes it in. * * The conversion is intentionally lossless in the limit: when the * message finishes we emit the same BaseMessage shape that a * `values.messages` entry would round-trip to via * {@link tryCoerceMessageLikeToMessage}. Mid-stream, partial blocks * (e.g. tool_call_chunk) are folded into the same shape so the UI * can render an incrementally-completing message. */ /** * Produce a `BaseMessage` class instance from an in-progress or * finished assembled message. Safe to call repeatedly across deltas — * each call returns a new instance whose content reflects the * currently-observed blocks. */ function assembledToBaseMessage(input) { const { id, role, blocks, namespace, node, runId, toolCallId, metadata, usage, finishMetadata, finishReason } = input; const textContent = extractContentString(blocks); const toolCalls = extractToolCalls(blocks); const toolCallChunks = extractToolCallChunks(blocks); const additionalKwargs = { ...namespace != null ? { namespace } : {}, ...node != null ? { node } : {}, ...runId != null ? { run_id: runId } : {}, ...metadata != null ? { metadata } : {}, ...usage != null ? { usage } : {} }; const hasAdditionalKwargs = Object.keys(additionalKwargs).length > 0; const responseMetadata = { ...finishReason != null ? { finish_reason: finishReason } : {}, ...finishMetadata }; switch (role) { case "human": return new _langchain_core_messages.HumanMessage({ ...id != null ? { id } : {}, content: textContent, ...hasAdditionalKwargs ? { additional_kwargs: additionalKwargs } : {}, ...Object.keys(responseMetadata).length > 0 ? { response_metadata: responseMetadata } : {} }); case "system": return new _langchain_core_messages.SystemMessage({ ...id != null ? { id } : {}, content: textContent, ...hasAdditionalKwargs ? { additional_kwargs: additionalKwargs } : {}, ...Object.keys(responseMetadata).length > 0 ? { response_metadata: responseMetadata } : {} }); case "tool": return new _langchain_core_messages.ToolMessage({ ...id != null ? { id } : {}, content: textContent, tool_call_id: toolCallId ?? "", ...hasAdditionalKwargs ? { additional_kwargs: additionalKwargs } : {}, ...Object.keys(responseMetadata).length > 0 ? { response_metadata: responseMetadata } : {} }); default: { const payload = { ...id != null ? { id } : {}, content: cloneContentBlocks(blocks), ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}, ...toolCallChunks.length > 0 ? { tool_call_chunks: toolCallChunks } : {}, ...hasAdditionalKwargs ? { additional_kwargs: additionalKwargs } : {}, usage_metadata: normalizeUsage(usage), response_metadata: { ...responseMetadata, output_version: "v1" } }; return toolCallChunks.length > 0 ? new _langchain_core_messages.AIMessageChunk(payload) : new _langchain_core_messages.AIMessage(payload); } } } /** * Convenience: given the raw assembled message + the role captured * from `message-start`, produce a `BaseMessage` with the same id. */ function assembledMessageToBaseMessage(assembled, role, extras = {}) { return assembledToBaseMessage({ id: assembled.id, role, blocks: assembled.blocks, namespace: assembled.namespace, node: assembled.node, runId: assembled.runId, toolCallId: extras.toolCallId, metadata: assembled.metadata, usage: assembled.usage, finishMetadata: assembled.finishMetadata, finishReason: assembled.finishReason }); } function normalizeUsage(usage) { if (usage == null) return void 0; return { ...usage, input_tokens: usage.input_tokens ?? 0, output_tokens: usage.output_tokens ?? 0, total_tokens: usage.total_tokens ?? 0 }; } function extractContentString(blocks) { let out = ""; for (const block of blocks) if (block.type === "text" && typeof block.text === "string") out += block.text; return out; } function cloneContentBlocks(blocks) { return blocks.map((block) => structuredClone(block)); } function extractToolCalls(blocks) { const out = []; for (const block of blocks) { if (block.type !== "tool_call" && block.type !== "tool_use") continue; const tc = block; out.push({ id: tc.id ?? "", name: tc.name ?? "", args: normalizeToolCallArgs(tc.args ?? tc.input), type: "tool_call" }); } return out; } function extractToolCallChunks(blocks) { const out = []; for (const block of blocks) { if (block.type !== "tool_call_chunk") continue; const tc = block; out.push({ id: tc.id, name: tc.name, args: tc.args, index: tc.index, type: "tool_call_chunk" }); } return out; } function normalizeToolCallArgs(value) { if (value != null && typeof value === "object" && !Array.isArray(value)) return value; if (typeof value === "string" && value.length > 0) try { const parsed = JSON.parse(value); if (parsed != null && typeof parsed === "object" && !Array.isArray(parsed)) return parsed; } catch {} return {}; } //#endregion exports.assembledMessageToBaseMessage = assembledMessageToBaseMessage; exports.assembledToBaseMessage = assembledToBaseMessage; //# sourceMappingURL=assembled-to-message.cjs.map