import { OpenAI } from 'openai';
import { z } from 'zod';

interface Steps<T = void, Omitted extends string = never> {
    /**
     * Adds a schema for the tool. This will be used to validate the input and to infer the type of the input in the `run()` function.
     * @param s The schema for the input. Must be a `z.object({})`
     * @returns A tool with the input schema set.
     */
    input<S extends z.AnyZodObject>(schema: S): Omit<Steps<z.infer<S>, Omitted | "input">, "input" | Omitted> & InternalTool;
    /**
     * The function to run when the model calls the tool. This is the only required builder step.
     * @param args The arguments for the `run()` function.
     *   The type of the arguments will be inferred from the input schema. If there is no input schema, the type will be `void`.
     * @returns A tool with the `run()` function set.
     */
    run(func: (input: T extends void ? never : T) => unknown): Omit<Steps<T, Omitted | "run">, "run" | "input" | Omitted> & InternalTool;
    /**
     * Adds a description to the tool. This will be provided to the model to aid in understanding the tool.
     * @param d The description of the tool as a string.
     *   It is good to explain what data the tool returns and what it does here.
     * @returns A tool with the description set.
     */
    describe(description: string): Omit<Steps<T, Omitted | "describe">, Omitted | "describe"> & InternalTool;
}
type CheckHasSetRun<T> = T extends {
    run: any;
} ? never : T;
interface Data {
    func: (input: any) => unknown;
    schema: z.AnyZodObject;
    description: string | undefined;
}
interface InternalTool {
    _data: Data;
    _parameters: OpenAI.Beta.FunctionTool["function"]["parameters"];
}
type OpenAIBuiltInTool = OpenAI.Beta.Assistant["tools"][number];
type Tool<T = void, O extends string = never> = Steps<T, O> & InternalTool;
/**
 * Creates a tool for use with openai assistants
 * @example
 * ```ts
 * const getWeather = t
 *   .input(
 *     z.object({
 *       city: z.string(),
 *      }))
 *   .describe("Gets the weather")
 *   .run(async ({ city }) => ({
 *     weather: "sunny",
 *   }));
 * ```
 */
declare const t: Steps<void> & {
    /**
     * Alias to the `file_search` tool
     * @see https://platform.openai.com/docs/assistants/tools/knowledge-retrieval
     */
    fileSearch: OpenAI.Beta.FileSearchTool;
    /**
     * Alias to the `code_interpreter` tool
     * @see https://platform.openai.com/docs/assistants/tools/code-interpreter
     */
    codeInterpreter: OpenAI.Beta.CodeInterpreterTool;
};
/**
 *
 * @param tools An object containing tools created with `t.run()`. Name them using the key.
 * @param onError A function that will be called when a tool throws an error. The error will be passed as the first argument.
 *  If this function returns a value, that value will be used as the output of the tool.
 *  If you do not provide a function, the error will be stringified and sent to the assistant.
 *  If the function returns `undefined` or `null`, the error will be sent to the assistant.
 * @returns An object containing the tools and a function to process actions.
 * @example
 * ```ts
 * const { t, processAssistantActions, processChatActions } = createTools({
 *   getWeather,  // These are created with `t.run()` and `t.input()`, see the example for `t`
 *   exponential,
 * });
 *
 * // Then use them like this:
 * const assistant = await openai.beta.assistants.create({
 *   tools,
 *   //...
 * });
 * ```
 */
declare function createTools<T>(tools: {
    [K in keyof T]: InternalTool & CheckHasSetRun<T[K]>;
}, onError?: (error: unknown) => any): {
    tools: (OpenAI.Beta.Assistants.FunctionTool & OpenAI.Chat.Completions.ChatCompletionTool)[];
    /**
     * Process the actions from the chat completion.
     * @param data The tool calls generated from the chat completion. (`message.tool_calls`)
     * @returns The message which should be sent with the messages to generate the result based on the tool calls
     */
    processChatActions(data?: OpenAI.Chat.ChatCompletionMessageToolCall[]): Promise<OpenAI.Chat.Completions.ChatCompletionToolMessageParam[]>;
    /**
     * Process the actions from the assistant run.
     * @param data The tool calls generated from the assistant run. (`run.required_action.submit_tool_outputs.tool_calls`)
     * @returns The tool outputs which should be sent to `runs.submitToolOutputs()` to continue the run.
     */
    processAssistantActions(data?: OpenAI.Beta.Threads.Runs.RequiredActionFunctionToolCall[]): Promise<OpenAI.Beta.Threads.Runs.RunSubmitToolOutputsParams.ToolOutput[]>;
};
type CreateToolsOutput = ReturnType<typeof createTools>;
type AnyTool = ReturnType<typeof createTools> | OpenAIBuiltInTool;
/**
 * Combine multiple tools into one object that can be used with an assistant.
 * @param tools All tools to combine. You can provide tools created with `createTools()` or built in tools from the OpenAI API (CodeInterpreter and Retrieval).
 * @returns The same object as `createTools()`, but with all tools combined.
 * @see https://platform.openai.com/docs/assistants/tools - for more information on the OpenAI API tools.
 * @example
 * ```ts
 * const { tools, processAssistantActions } = combineTools(
 *   createTools({
 *     getWeather,
 *     exponential,
 *   }),
 *   { type: "code_interpreter" },
 *   { type: "retrieval" },
 * );
 * ```
 */
declare function combineTools(...tools: AnyTool[]): Omit<CreateToolsOutput, "tools"> & {
    tools: OpenAIBuiltInTool[];
};

export { type Tool, combineTools, createTools, t };
