UNPKG

@langchain/langgraph-sdk

Version:

Client library for interacting with the LangGraph API

1 lines • 3.74 kB
{"version":3,"file":"tools.cjs","names":[],"sources":["../../src/utils/tools.ts"],"sourcesContent":["import type {\n Message,\n AIMessage,\n ToolMessage,\n ToolCallState,\n ToolCallWithResult,\n DefaultToolCall,\n} from \"../types.messages.js\";\n\n/**\n * Extracts tool calls with their results from a list of messages.\n *\n * @template ToolCall The type of tool calls.\n * @param messages The list of messages to extract tool calls from.\n * @returns An array of ToolCallWithResult objects.\n *\n * @example\n * ```ts\n * const toolCalls = getToolCallsWithResults(messages);\n * for (const { call, result } of toolCalls) {\n * if (call.name === \"get_weather\") {\n * console.log(`Weather for ${call.args.location}:`, result?.content);\n * }\n * }\n * ```\n */\n/**\n * Computes the lifecycle state of a tool call based on its result.\n */\nfunction computeToolCallState(\n result: ToolMessage | undefined,\n impliedCompleted: boolean\n): ToolCallState {\n if (result) return result.status === \"error\" ? \"error\" : \"completed\";\n if (impliedCompleted) return \"completed\";\n return \"pending\";\n}\n\nexport function getToolCallsWithResults<ToolCall = DefaultToolCall>(\n messages: Message<ToolCall>[]\n): ToolCallWithResult<ToolCall>[] {\n const results: ToolCallWithResult<ToolCall>[] = [];\n\n // Create a map of tool_call_id to ToolMessage for quick lookup\n const toolResultsById = new Map<string, ToolMessage>();\n for (const msg of messages) {\n if (msg.type === \"tool\") {\n toolResultsById.set(msg.tool_call_id, msg);\n }\n }\n\n // Find all AI messages with tool calls and pair them with results.\n // For each, independently check if there's a subsequent AI message,\n // which implies the tools completed (handles tools returning Commands\n // where ToolMessages are embedded in the state update rather than streamed).\n for (let msgIdx = 0; msgIdx < messages.length; msgIdx += 1) {\n const msg = messages[msgIdx];\n if (msg.type === \"ai\" && msg.tool_calls && msg.tool_calls.length > 0) {\n const aiMessage = msg as AIMessage<ToolCall>;\n\n let impliedCompleted = false;\n for (let j = msgIdx + 1; j < messages.length; j += 1) {\n if (messages[j].type === \"ai\") {\n impliedCompleted = true;\n break;\n }\n }\n\n for (let i = 0; i < aiMessage.tool_calls!.length; i += 1) {\n const call = aiMessage.tool_calls![i] as ToolCall & { id?: string };\n const callId = call.id as string | undefined;\n const result = callId ? toolResultsById.get(callId) : undefined;\n\n results.push({\n id: callId ?? `${aiMessage.id ?? \"unknown\"}-${i}`,\n call,\n result,\n aiMessage,\n index: i,\n state: computeToolCallState(result, impliedCompleted),\n });\n }\n }\n }\n\n return results;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA6BA,SAAS,qBACP,QACA,kBACe;AACf,KAAI,OAAQ,QAAO,OAAO,WAAW,UAAU,UAAU;AACzD,KAAI,iBAAkB,QAAO;AAC7B,QAAO;;AAGT,SAAgB,wBACd,UACgC;CAChC,MAAM,UAA0C,EAAE;CAGlD,MAAM,kCAAkB,IAAI,KAA0B;AACtD,MAAK,MAAM,OAAO,SAChB,KAAI,IAAI,SAAS,OACf,iBAAgB,IAAI,IAAI,cAAc,IAAI;AAQ9C,MAAK,IAAI,SAAS,GAAG,SAAS,SAAS,QAAQ,UAAU,GAAG;EAC1D,MAAM,MAAM,SAAS;AACrB,MAAI,IAAI,SAAS,QAAQ,IAAI,cAAc,IAAI,WAAW,SAAS,GAAG;GACpE,MAAM,YAAY;GAElB,IAAI,mBAAmB;AACvB,QAAK,IAAI,IAAI,SAAS,GAAG,IAAI,SAAS,QAAQ,KAAK,EACjD,KAAI,SAAS,GAAG,SAAS,MAAM;AAC7B,uBAAmB;AACnB;;AAIJ,QAAK,IAAI,IAAI,GAAG,IAAI,UAAU,WAAY,QAAQ,KAAK,GAAG;IACxD,MAAM,OAAO,UAAU,WAAY;IACnC,MAAM,SAAS,KAAK;IACpB,MAAM,SAAS,SAAS,gBAAgB,IAAI,OAAO,GAAG,KAAA;AAEtD,YAAQ,KAAK;KACX,IAAI,UAAU,GAAG,UAAU,MAAM,UAAU,GAAG;KAC9C;KACA;KACA;KACA,OAAO;KACP,OAAO,qBAAqB,QAAQ,iBAAiB;KACtD,CAAC;;;;AAKR,QAAO"}