UNPKG

@langchain/langgraph-sdk

Version:

Client library for interacting with the LangGraph API

84 lines (83 loc) • 3.21 kB
require("../_virtual/_rolldown/runtime.cjs"); const require_tools = require("../client/stream/handles/tools.cjs"); let _langchain_core_messages = require("@langchain/core/messages"); //#region src/stream/tool-calls.ts /** * Insert or replace an assembled tool call by call id. * * ToolCallAssembler mutates its active handle in place as `tool-finished` / * `tool-error` events arrive. Publish a fresh object here so framework * adapters that pass individual tool calls as props (notably Vue's shallow * prop tracking) observe status/output changes. */ function upsertToolCall(current, next) { const snapshot = { ...next }; const idx = current.findIndex((toolCall) => toolCall.callId === next.callId); if (idx < 0) return [...current, snapshot]; const updated = current.slice(); updated[idx] = snapshot; return updated; } /** * Backfill unfinished tool-call handles from authoritative ToolMessages in a * values snapshot. This covers headless tools whose graph state contains the * result even when the `tools` channel omits a matching `tool-finished` event. */ function reconcileToolCallsFromMessages(toolCalls, messages) { let updated; for (const message of messages) { if (!_langchain_core_messages.ToolMessage.isInstance(message)) continue; const callId = message.tool_call_id; if (typeof callId !== "string" || callId.length === 0) continue; const currentToolCalls = updated ?? toolCalls; const idx = currentToolCalls.findIndex((toolCall) => toolCall.callId === callId); if (idx < 0) continue; const current = currentToolCalls[idx]; if (current.status === "finished" && current.output != null) continue; const output = require_tools.parseToolOutput(message.content); if (output == null) continue; updated = upsertToolCall(currentToolCalls, { ...current, output, status: "finished", error: void 0 }); } return updated ?? toolCalls; } /** * Build completed scoped tool-call handles from an authoritative * `values.messages` snapshot. Used when an idle thread hydrates card panels * from checkpoint history instead of replaying scoped `/events`. */ function seedToolCallsFromMessages(namespace, messages) { let toolCalls = []; for (const message of messages) { const raw = message.tool_calls; if (!Array.isArray(raw)) continue; for (const toolCall of raw) { if (toolCall == null || typeof toolCall !== "object") continue; const record = toolCall; if (typeof record.id !== "string" || record.id.length === 0) continue; if (typeof record.name !== "string" || record.name.length === 0) continue; if (namespace.length > 0 && record.name === "task") continue; toolCalls = upsertToolCall(toolCalls, { id: record.id, callId: record.id, name: record.name, namespace: [...namespace, `tools:${record.id}`], input: record.args ?? {}, args: record.args ?? {}, output: null, status: "running", error: void 0 }); } } return reconcileToolCallsFromMessages(toolCalls, messages); } //#endregion exports.reconcileToolCallsFromMessages = reconcileToolCallsFromMessages; exports.seedToolCallsFromMessages = seedToolCallsFromMessages; exports.upsertToolCall = upsertToolCall; //# sourceMappingURL=tool-calls.cjs.map