import { AiAdapter } from '@inngest/ai';
import { InngestFunction } from 'inngest/components/InngestFunction';
import { GetStepTools, Inngest } from 'inngest';
import { ZodType, ZodTypeAny, output } from 'zod';
import { AsyncContext } from 'inngest/experimental';

type Message = TextMessage | ToolCallMessage | ToolResultMessage;
/**
 * TextMessage represents plain text messages in the chat history, eg. the user's prompt or
 * an assistant's reply.
 */
interface TextMessage {
    type: "text";
    role: "system" | "user" | "assistant";
    content: string | Array<TextContent>;
    stop_reason?: "tool" | "stop";
}
/**
 * ToolCallMessage represents a message for a tool call.
 */
interface ToolCallMessage {
    type: "tool_call";
    role: "user" | "assistant";
    tools: ToolMessage[];
    stop_reason: "tool";
}
/**
 * ToolResultMessage represents the output of a tool call.
 */
interface ToolResultMessage {
    type: "tool_result";
    role: "tool_result";
    tool: ToolMessage;
    content: unknown;
    stop_reason: "tool";
}
interface TextContent {
    type: "text";
    text: string;
}
interface ToolMessage {
    type: "tool";
    id: string;
    name: string;
    input: Record<string, unknown>;
}
/**
 * State stores state (history) for a given network of agents.  The state
 * includes key-values, plus a stack of all agentic calls.
 *
 * From this, the chat history can be reconstructed (and manipulated) for each
 * subsequent agentic call.
 */
declare class State {
    kv: {
        set: <T = any>(key: string, value: T) => void;
        get: <T = any>(key: string) => T | undefined;
        delete: (key: string) => boolean;
        has: (key: string) => boolean;
        all: () => Record<string, unknown>;
    };
    private _kv;
    private _history;
    constructor(state?: Record<string, any>);
    /**
     * Results returns a new array containing all past inference results in the
     * network. This array is safe to modify.
     */
    get results(): InferenceResult[];
    /**
     * format returns the memory used for agentic calls based off of prior
     * agentic calls.
     *
     * This is used to format the current State as a conversation log when
     * calling an individual agent.
     *
     */
    format(): Message[];
    append(call: InferenceResult): void;
    clone(): State;
}
/**
 * InferenceResult represents a single agentic call as part of the network
 * state.  This stores every input and ouput for a call.
 *
 */
declare class InferenceResult {
    agent: Agent;
    input: string;
    prompt: Message[];
    history: Message[];
    output: Message[];
    toolCalls: ToolResultMessage[];
    raw: string;
    private _historyFormatter;
    constructor(agent: Agent, input: string, prompt: Message[], history: Message[], output: Message[], toolCalls: ToolResultMessage[], raw: string);
    withFormatter(f: (a: InferenceResult) => Message[]): void;
    format(): Message[];
}

type MaybePromise<T> = T | Promise<T>;
/**
 * AnyZodType is a type alias for any Zod type.
 *
 * It specifically matches the typing used for the OpenAI JSON schema typings,
 * which do not use the standardized `z.ZodTypeAny` type.
 *
 * Not that using this type directly can break between any versions of Zod
 * (including minor and patch versions). It may be pertinent to maintain a
 * custom type which matches many versions in the future.
 */
type AnyZodType = ZodType<any> | ZodTypeAny;
/**
 * Given an unknown value, return a string representation of the error if it is
 * an error, otherwise return the stringified value.
 */
declare const stringifyError: (e: unknown) => string;
/**
 * Attempts to retrieve the step tools from the async context.
 */
declare const getStepTools: () => Promise<AsyncContext["ctx"]["step"] | undefined>;
declare const isInngestFn: (fn: unknown) => fn is InngestFunction.Any;
declare const getInngestFnInput: (fn: InngestFunction.Any) => AnyZodType | undefined;

/**
 * Network represents a network of agents.
 */
declare const createNetwork: (opts: Network.Constructor) => Network;
declare const getDefaultRoutingAgent: () => RoutingAgent;
/**
 * Network represents a network of agents.
 */
declare class Network {
    /**
     * The name for the system of agents
     */
    name: string;
    description?: string;
    /**
     * agents are all publicly available agents in the netwrok
     */
    agents: Map<string, Agent>;
    /**
     * state is the entire agent's state.
     */
    defaultState?: State;
    /**
     * defaultModel is the default model to use with the network.  This will not
     * override an agent's specific model if the agent already has a model defined
     * (eg. via withModel or via its constructor).
     */
    defaultModel?: AiAdapter.Any;
    defaultRouter?: Network.Router;
    /**
     * maxIter is the maximum number of times the we can call agents before ending
     * the network's run loop.
     */
    maxIter: number;
    protected _stack: string[];
    protected _counter: number;
    protected _agents: Map<string, Agent>;
    constructor({ name, description, agents, defaultModel, maxIter, defaultState, defaultRouter, }: Network.Constructor);
    availableAgents(networkRun?: NetworkRun): Promise<Agent[]>;
    /**
     * addAgent adds a new agent to the network.
     */
    addAgent(agent: Agent): void;
    /**
     * run handles a given request using the network of agents.  It is not
     * concurrency-safe; you can only call run on a network once, as networks are
     * stateful.
     *
     */
    run(...[input, overrides]: Network.RunArgs): Promise<NetworkRun>;
}
declare namespace Network {
    type Constructor = {
        name: string;
        description?: string;
        agents: Agent[];
        defaultModel?: AiAdapter.Any;
        maxIter?: number;
        defaultState?: State;
        defaultRouter?: Router;
    };
    type RunArgs = [
        input: string,
        overrides?: {
            router?: Router;
            state?: State | Record<string, any>;
        }
    ];
    /**
     * Router defines how a network coordinates between many agents.  A router is
     * either a RoutingAgent which uses inference calls to choose the next Agent,
     * or a function which chooses the next Agent to call.
     *
     * The function gets given the network, current state, future
     * agentic calls, and the last inference result from the network.
     *
     */
    type Router = RoutingAgent | Router.FnRouter;
    namespace Router {
        /**
         * FnRouter defines a function router which returns an Agent, an AgentRouter, or
         * undefined if the network should stop.
         *
         * If the FnRouter returns an AgentRouter (an agent with the .route function),
         * the agent will first be ran, then the `.route` function will be called.
         *
         */
        type FnRouter = (args: Args) => MaybePromise<RoutingAgent | Agent | Agent[] | undefined>;
        interface Args {
            /**
             * input is the input called to the network
             */
            input: string;
            /**
             * Network is the network that this router is coordinating.  Network state
             * is accessible via `network.state`.
             */
            network: NetworkRun;
            /**
             * stack is an ordered array of agents that will be called next.
             */
            stack: Agent[];
            /**
             * callCount is the number of current agent invocations that the network
             * has made.  This is a shorthand for `network.state.results.length`.
             */
            callCount: number;
            /**
             * lastResult is the last inference result that the network made.  This is
             * a shorthand for `network.state.results.pop()`.
             */
            lastResult?: InferenceResult;
        }
    }
}

declare class NetworkRun extends Network {
    state: State;
    constructor(network: Network, state: State);
    run(): never;
    availableAgents(): Promise<Agent[]>;
    /**
     * Schedule is used to push an agent's run function onto the stack.
     */
    schedule(agentName: string): void;
    private execute;
    private getNextAgents;
    private getNextAgentsViaRoutingAgent;
}

type Tool<TInput extends Tool.Input> = {
    name: string;
    description?: string;
    parameters?: TInput;
    mcp?: {
        server: MCP.Server;
        tool: MCP.Tool;
    };
    strict?: boolean;
    handler: (input: output<TInput>, opts: Tool.Options) => MaybePromise<any>;
};
declare namespace Tool {
    type Any = Tool<Tool.Input>;
    type Options = {
        agent: Agent;
        network?: NetworkRun;
        step?: GetStepTools<Inngest.Any>;
    };
    type Input = AnyZodType;
    type Choice = "auto" | "any" | (string & {});
}
declare namespace MCP {
    type Server = {
        name: string;
        transport: TransportSSE | TransportWebsocket;
    };
    type Transport = TransportSSE | TransportWebsocket;
    type TransportSSE = {
        type: "sse";
        url: string;
        eventSourceInit?: EventSourceInit;
        requestInit?: RequestInit;
    };
    type TransportWebsocket = {
        type: "ws";
        url: string;
    };
    type Tool = {
        name: string;
        description?: string;
        inputSchema?: {
            type: "object";
            properties?: unknown;
        };
    };
}

/**
 * createTool is a helper that properly types the input argument for a handler
 * based off of the Zod parameter types.
 */
declare const createTool: <T extends AnyZodType>(t: Tool<T>) => Tool<T>;
/**
 * Agent represents a single agent, responsible for a set of tasks.
 */
declare const createAgent: (opts: Agent.Constructor) => Agent;
declare const createRoutingAgent: (opts: Agent.RoutingConstructor) => RoutingAgent;
declare class RoutingAgent extends Agent {
    type: string;
    lifecycles: Agent.RoutingLifecycle;
    constructor(opts: Agent.RoutingConstructor);
    withModel(model: AiAdapter.Any): RoutingAgent;
}
/**
 * Agent represents a single agent, responsible for a set of tasks.
 */
declare class Agent {
    /**
     * name is the name of the agent.
     */
    name: string;
    /**
     * description is the description of the agent.
     */
    description: string;
    /**
     * system is the system prompt for the agent.
     */
    system: string | ((ctx: {
        network?: NetworkRun;
    }) => MaybePromise<string>);
    /**
     * Assistant is the assistent message used for completion, if any.
     */
    assistant: string;
    /**
     * tools are a list of tools that this specific agent has access to.
     */
    tools: Map<string, Tool.Any>;
    /**
     * tool_choice allows you to specify whether tools are automatically.  this defaults
     * to "auto", allowing the model to detect when to call tools automatically.  Choices are:
     *
     * - "auto": allow the model to choose tools automatically
     * - "any": force the use of any tool in the tools map
     * - string: force the name of a particular tool
     */
    tool_choice?: Tool.Choice;
    /**
     * lifecycles are programmatic hooks used to manage the agent.
     */
    lifecycles: Agent.Lifecycle | Agent.RoutingLifecycle | undefined;
    /**
     * model is the step caller to use for this agent.  This allows the agent
     * to use a specific model which may be different to other agents in the
     * system
     */
    model: AiAdapter.Any | undefined;
    /**
     * mcpServers is a list of MCP (model-context-protocol) servers which can
     * provide tools to the agent.
     */
    mcpServers?: MCP.Server[];
    private _mcpClients;
    constructor(opts: Agent.Constructor | Agent.RoutingConstructor);
    private setTools;
    withModel(model: AiAdapter.Any): Agent;
    /**
     * Run runs an agent with the given user input, treated as a user message.  If
     * the input is an empty string, only the system prompt will execute.
     */
    run(input: string, { model, network, state, maxIter }?: Agent.RunOptions | undefined): Promise<InferenceResult>;
    private performInference;
    /**
     * invokeTools takes output messages from an inference call then invokes any tools
     * in the message responses.
     */
    private invokeTools;
    private agentPrompt;
    private initMCP;
    /**
     * listMCPTools lists all available tools for a given MCP server
     */
    private listMCPTools;
    /**
     * mcpClient creates a new MCP client for the given server.
     */
    private mcpClient;
}
declare namespace Agent {
    interface Constructor {
        name: string;
        description?: string;
        system: string | ((ctx: {
            network?: NetworkRun;
        }) => MaybePromise<string>);
        assistant?: string;
        tools?: (Tool.Any | InngestFunction.Any)[];
        tool_choice?: Tool.Choice;
        lifecycle?: Lifecycle;
        model?: AiAdapter.Any;
        mcpServers?: MCP.Server[];
    }
    interface RoutingConstructor extends Omit<Constructor, "lifecycle"> {
        lifecycle: RoutingLifecycle;
    }
    interface RoutingConstructor extends Omit<Constructor, "lifecycle"> {
        lifecycle: RoutingLifecycle;
    }
    interface RoutingConstructor extends Omit<Constructor, "lifecycle"> {
        lifecycle: RoutingLifecycle;
    }
    interface RunOptions {
        model?: AiAdapter.Any;
        network?: NetworkRun;
        /**
         * State allows you to pass custom state into a single agent run call.  This should only
         * be provided if you are running agents outside of a network.  Networks automatically
         * supply their own state.
         */
        state?: State;
        maxIter?: number;
    }
    interface Lifecycle {
        /**
         * enabled selectively enables or disables this agent based off of network
         * state.  If this function is not provided, the agent is always enabled.
         */
        enabled?: (args: Agent.LifecycleArgs.Base) => MaybePromise<boolean>;
        /**
         * onStart is called just before an agent starts an inference call.
         *
         * This receives the full agent prompt.  If this is a networked agent, the
         * agent will also receive the network's history which will be concatenated
         * to the end of the prompt when making the inference request.
         *
         * The return values can be used to adjust the prompt, history, or to stop
         * the agent from making the call altogether.
         *
         */
        onStart?: (args: Agent.LifecycleArgs.Before) => MaybePromise<{
            prompt: Message[];
            history: Message[];
            stop: boolean;
        }>;
        /**
         * onResponse is called after the inference call finishes, before any tools
         * have been invoked. This allows you to moderate the response prior to
         * running tools.
         */
        onResponse?: (args: Agent.LifecycleArgs.Result) => MaybePromise<InferenceResult>;
        /**
         * onFinish is called with a finalized InferenceResult, including any tool
         * call results. The returned InferenceResult will be saved to network
         * history, if the agent is part of the network.
         *
         */
        onFinish?: (args: Agent.LifecycleArgs.Result) => MaybePromise<InferenceResult>;
    }
    namespace LifecycleArgs {
        interface Base {
            agent: Agent;
            network?: NetworkRun;
        }
        interface Result extends Base {
            result: InferenceResult;
        }
        interface Before extends Base {
            input?: string;
            prompt: Message[];
            history?: Message[];
        }
    }
    interface RoutingLifecycle extends Lifecycle {
        onRoute: RouterFn;
    }
    type RouterFn = (args: Agent.RouterArgs) => string[] | undefined;
    /**
     * Router args are the arguments passed to the onRoute lifecycle hook.
     */
    type RouterArgs = Agent.LifecycleArgs.Result;
}

export { Agent as A, InferenceResult as I, type Message as M, Network as N, RoutingAgent as R, State as S, Tool as T, createAgent as a, createRoutingAgent as b, createTool as c, createNetwork as d, NetworkRun as e, type TextMessage as f, getDefaultRoutingAgent as g, type ToolCallMessage as h, type ToolResultMessage as i, type TextContent as j, type ToolMessage as k, MCP as l, type MaybePromise as m, type AnyZodType as n, getStepTools as o, isInngestFn as p, getInngestFnInput as q, stringifyError as s };
