import { Command, END } from "../constants.js";
import { RunnableCallable } from "../utils.js";
import { MessagesAnnotation } from "../graph/messages_annotation.js";
import { RunnableConfig, RunnableToolLike } from "@langchain/core/runnables";
import { BaseMessage, ToolMessage } from "@langchain/core/messages";
import { DynamicTool, StructuredToolInterface } from "@langchain/core/tools";
import { ToolCall } from "@langchain/core/messages/tool";

//#region src/prebuilt/tool_node.d.ts
type ToolNodeOptions = {
  name?: string;
  tags?: string[];
  handleToolErrors?: boolean;
};
/**
 * A node that runs the tools requested in the last AIMessage. It can be used
 * either in StateGraph with a "messages" key or in MessageGraph. If multiple
 * tool calls are requested, they will be run in parallel. The output will be
 * a list of ToolMessages, one for each tool call.
 *
 * @example
 * ```ts
 * import { ToolNode } from "@langchain/langgraph/prebuilt";
 * import { tool } from "@langchain/core/tools";
 * import { z } from "zod";
 * import { AIMessage } from "@langchain/core/messages";
 *
 * const getWeather = tool((input) => {
 *   if (["sf", "san francisco"].includes(input.location.toLowerCase())) {
 *     return "It's 60 degrees and foggy.";
 *   } else {
 *     return "It's 90 degrees and sunny.";
 *   }
 * }, {
 *   name: "get_weather",
 *   description: "Call to get the current weather.",
 *   schema: z.object({
 *     location: z.string().describe("Location to get the weather for."),
 *   }),
 * });
 *
 * const tools = [getWeather];
 * const toolNode = new ToolNode(tools);
 *
 * const messageWithSingleToolCall = new AIMessage({
 *   content: "",
 *   tool_calls: [
 *     {
 *       name: "get_weather",
 *       args: { location: "sf" },
 *       id: "tool_call_id",
 *       type: "tool_call",
 *     }
 *   ]
 * })
 *
 * await toolNode.invoke({ messages: [messageWithSingleToolCall] });
 * // Returns tool invocation responses as:
 * // { messages: ToolMessage[] }
 * ```
 *
 * @example
 * ```ts
 * import {
 *   StateGraph,
 *   MessagesAnnotation,
 * } from "@langchain/langgraph";
 * import { ToolNode } from "@langchain/langgraph/prebuilt";
 * import { tool } from "@langchain/core/tools";
 * import { z } from "zod";
 * import { ChatAnthropic } from "@langchain/anthropic";
 *
 * const getWeather = tool((input) => {
 *   if (["sf", "san francisco"].includes(input.location.toLowerCase())) {
 *     return "It's 60 degrees and foggy.";
 *   } else {
 *     return "It's 90 degrees and sunny.";
 *   }
 * }, {
 *   name: "get_weather",
 *   description: "Call to get the current weather.",
 *   schema: z.object({
 *     location: z.string().describe("Location to get the weather for."),
 *   }),
 * });
 *
 * const tools = [getWeather];
 * const modelWithTools = new ChatAnthropic({
 *   model: "claude-3-haiku-20240307",
 *   temperature: 0
 * }).bindTools(tools);
 *
 * const toolNodeForGraph = new ToolNode(tools)
 *
 * const shouldContinue = (state: typeof MessagesAnnotation.State) => {
 *   const { messages } = state;
 *   const lastMessage = messages[messages.length - 1];
 *   if ("tool_calls" in lastMessage && Array.isArray(lastMessage.tool_calls) && lastMessage.tool_calls?.length) {
 *     return "tools";
 *   }
 *   return "__end__";
 * }
 *
 * const callModel = async (state: typeof MessagesAnnotation.State) => {
 *   const { messages } = state;
 *   const response = await modelWithTools.invoke(messages);
 *   return { messages: response };
 * }
 *
 * const graph = new StateGraph(MessagesAnnotation)
 *   .addNode("agent", callModel)
 *   .addNode("tools", toolNodeForGraph)
 *   .addEdge("__start__", "agent")
 *   .addConditionalEdges("agent", shouldContinue)
 *   .addEdge("tools", "agent")
 *   .compile();
 *
 * const inputs = {
 *   messages: [{ role: "user", content: "what is the weather in SF?" }],
 * };
 *
 * const stream = await graph.stream(inputs, {
 *   streamMode: "values",
 * });
 *
 * for await (const { messages } of stream) {
 *   console.log(messages);
 * }
 * // Returns the messages in the state at each step of execution
 * ```
 */
declare class ToolNode<T = any> extends RunnableCallable<T, T> {
  tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[];
  handleToolErrors: boolean;
  trace: boolean;
  constructor(tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[], options?: ToolNodeOptions);
  protected runTool(call: ToolCall, config: RunnableConfig): Promise<ToolMessage | Command>;
  protected run(input: unknown, config: RunnableConfig): Promise<T>;
}
/**
 * A conditional edge function that determines whether to route to a tools node or end the graph.
 *
 * This function is designed to be used as a conditional edge in a LangGraph state graph to implement
 * the common pattern of checking if an AI message contains tool calls that need to be executed.
 *
 * @param state - The current state of the graph, which can be either:
 *   - An array of `BaseMessage` objects, where the last message is checked for tool calls
 *   - A state object conforming to `MessagesAnnotation.State`, which contains a `messages` array
 *
 * @returns A string indicating the next node to route to:
 *   - `"tools"` - If the last message contains tool calls that need to be executed
 *   - `END` - If there are no tool calls, indicating the graph should terminate
 *
 * @example
 * ```typescript
 * import { StateGraph, MessagesAnnotation, END, START } from "@langchain/langgraph";
 * import { ToolNode, toolsCondition } from "@langchain/langgraph/prebuilt";
 *
 * const graph = new StateGraph(MessagesAnnotation)
 *   .addNode("agent", agentNode)
 *   .addNode("tools", new ToolNode([searchTool, calculatorTool]))
 *   .addEdge(START, "agent")
 *   .addConditionalEdges("agent", toolsCondition, ["tools", END])
 *   .addEdge("tools", "agent")
 *   .compile();
 * ```
 *
 * @remarks
 * The function checks the last message in the state for the presence of `tool_calls`.
 * If the message is an `AIMessage` with one or more tool calls, it returns `"tools"`,
 * indicating that the graph should route to a tools node (typically a `ToolNode`) to
 * execute those tool calls. Otherwise, it returns `END` to terminate the graph execution.
 *
 * This is a common pattern in agentic workflows where an AI model decides whether to
 * use tools or provide a final response.
 */
declare function toolsCondition(state: BaseMessage[] | typeof MessagesAnnotation.State): "tools" | typeof END;
//#endregion
export { ToolNode, ToolNodeOptions, toolsCondition };
//# sourceMappingURL=tool_node.d.ts.map