import type { ComponentType } from 'react';
import type { TChatMessage, TMessageContent, ToolMessageContentData } from "../../types/messages.js";
import { type MessageRendererRegistry } from "../messageTypeRegistry.js";
export type ToolSchemaResult<TArgs> = {
    success: true;
    data: TArgs;
} | {
    success: false;
    error: {
        message: string;
    };
};
export type ToolSchema<TArgs> = {
    validate: (input: unknown) => ToolSchemaResult<TArgs>;
};
export type ToolComponentProps<TArgs, TResult> = {
    args: TArgs;
    result?: TResult;
    submitResult: (result: TResult) => void;
};
export type ToolExecutionStatus = 'success' | 'error' | 'cancelled';
/**
 * Discriminated outcome returned by a tool's `execute` callback.
 * A tool may also return a bare `TResult`; it is then treated as
 * `{status: 'success', result}` to keep simple cases boilerplate-free.
 */
export type ToolExecutionOutcome<TResult> = {
    status: 'success';
    result: TResult;
} | {
    status: 'error';
    result?: TResult;
    error?: {
        message: string;
    };
} | {
    status: 'cancelled';
    result?: TResult;
};
export type ToolDefinition<TArgs, TResult, TName extends string = string> = {
    name: TName;
    description: string;
    parameters: Record<string, unknown>;
    schema: ToolSchema<TArgs>;
    component: ComponentType<ToolComponentProps<TArgs, TResult>>;
    /**
     * Run after the user submits a result inside the tool component.
     * Return:
     *  - `TResult` (or a Promise of one) for a successful execution;
     *  - a `ToolExecutionOutcome<TResult>` to explicitly report `error`
     *    or `cancelled`. A thrown error is surfaced as `{status: 'error'}`.
     */
    execute?: (params: {
        args: TArgs;
        result: TResult;
        toolCallId: string;
    }) => TResult | ToolExecutionOutcome<TResult> | Promise<TResult | ToolExecutionOutcome<TResult>>;
};
export type RuntimeToolDefinition<TName extends string = string> = {
    name: TName;
    description: string;
    parameters: Record<string, unknown>;
    validate: (input: unknown) => ToolSchemaResult<unknown>;
    /**
     * Rendered as `<Renderer ... />` JSX. Hooks placed at the top of this
     * component work normally because it is a real React component, not a
     * function called inside another render path.
     */
    Renderer: ComponentType<ToolComponentProps<unknown, unknown>>;
    execute: (params: {
        args: unknown;
        result: unknown;
        toolCallId: string;
    }) => unknown | ToolExecutionOutcome<unknown> | Promise<unknown | ToolExecutionOutcome<unknown>>;
};
export type Toolset = Record<string, RuntimeToolDefinition>;
export type ToolPartContentData<TArgs = unknown, TResult = unknown> = ToolMessageContentData & {
    toolCallId: string;
    args?: TArgs;
    result?: TResult;
};
export type ToolPartContent<TArgs = unknown, TResult = unknown> = TMessageContent<'tool', ToolPartContentData<TArgs, TResult>>;
export type ToolsetResultEvent = {
    toolCallId: string;
    toolName: string;
    status: ToolExecutionStatus;
    result: unknown;
    error?: {
        message: string;
    };
};
/**
 * Wrap a typed tool definition into an erased runtime entry that the
 * toolset renderer can dispatch by `toolName`. The literal `name` is
 * preserved as a type parameter so `createToolset` can derive its keys.
 */
export declare function defineTool<TArgs, TResult, const TName extends string>(definition: ToolDefinition<TArgs, TResult, TName>): RuntimeToolDefinition<TName>;
/**
 * Build a `Toolset` from a list of `defineTool(...)` results. Keys are
 * derived from `definition.name`, so the call site cannot drift between
 * a literal-object key and the embedded `name`. The return type narrows
 * its keys to the union of literal tool names, giving name-autocomplete
 * on lookups. Throws on duplicates.
 */
export declare function createToolset<const T extends readonly RuntimeToolDefinition<string>[]>(...tools: T): {
    [K in T[number]['name']]: RuntimeToolDefinition<T[number]['name']>;
};
/**
 * Map a `Toolset` to the OpenAI `tools[]` shape so chat clients can pass
 * tool definitions to the model without reimplementing the conversion.
 */
export declare function toolsetToOpenAIDefinitions(toolset: Toolset): Array<{
    type: 'function';
    function: {
        name: string;
        description: string;
        parameters: Record<string, unknown>;
    };
}>;
export type CreateToolsetRendererOptions = {
    onToolResult: (event: ToolsetResultEvent) => void;
    /**
     * Existing registry whose entries should be preserved. A shallow copy
     * is taken; the input reference is never mutated.
     */
    registry?: MessageRendererRegistry;
};
/**
 * Build a `MessageRendererRegistry` whose `tool` renderer dispatches
 * by `toolName` into the provided toolset. Unknown tools and invalid
 * args fall back to a generic `<ToolMessage status="error" />`. Errors
 * thrown inside `execute` are surfaced via an `error` outcome.
 */
export declare function createToolsetRenderer(toolset: Toolset, options: CreateToolsetRendererOptions): MessageRendererRegistry;
/**
 * Merge a tool result into the matching `tool` part of the chat history.
 * Honors `event.status` so the part reflects success / error / cancelled.
 * For backward compatibility, a missing `status` is treated as `'success'`.
 * Returns the original array reference when nothing matched, so React state
 * setters can skip needless updates.
 */
export declare function applyToolResult<TCustom extends TMessageContent = never>(messages: TChatMessage<TCustom>[], event: ToolsetResultEvent): TChatMessage<TCustom>[];
