import { type Event as CEvent, type Message as CMessage } from '@botpress/client';
import { z } from '@botpress/sdk';
import { BotClient } from '@botpress/sdk/dist/bot';
import type { ChannelSpec, Channels } from '../_types/channels';
import type { ConversationDefinitions, ConversationRoutableEvents } from '../_types/conversations';
import type { EventName, EventPayload as CustomEventPayload } from '../_types/events';
import type { Integrations } from '../_types/integrations';
import { WorkflowDefinitions } from '../_types/workflows';
import { Autonomous } from '../runtime/autonomous';
import { BotContext } from '../runtime/context/context';
import { WorkflowCallbackEventType, WorkflowDataRequestEventType, WorkflowNotifyEventType, LifecycleNudgeEventType, LifecycleExpireEventType } from '../runtime/events';
import { ZuiType } from '../types';
import { BaseConversationInstance } from './conversation-instance';
import { BaseCustomComponent } from './custom-component';
import { Definitions } from './definition';
import { BaseWorkflowInstance } from './workflow-instance';
import { Chat } from '../runtime/chat/chat';
type WorkflowRequest = {
    [WfName in keyof WorkflowDefinitions & string]: keyof WorkflowDefinitions[WfName]['requests'] extends never ? never : {
        [ReqName in keyof WorkflowDefinitions[WfName]['requests'] & string]: {
            type: `${WfName}:${ReqName}`;
            workflow: BaseWorkflowInstance<WfName>;
            step: string;
        };
    }[keyof WorkflowDefinitions[WfName]['requests'] & string];
}[keyof WorkflowDefinitions & string];
type WorkflowCallback = {
    [WfName in keyof WorkflowDefinitions & string]: {
        type: WfName;
        workflow: BaseWorkflowInstance<WfName>;
        status: 'completed' | 'failed' | 'canceled' | 'timed_out';
        output?: z.infer<WorkflowDefinitions[WfName]['output']>;
        error?: string;
    };
}[keyof WorkflowDefinitions & string];
type WorkflowNotification = {
    [WfName in keyof WorkflowDefinitions & string]: keyof WorkflowDefinitions[WfName]['notifications'] extends never ? never : {
        [NotificationName in keyof WorkflowDefinitions[WfName]['notifications'] & string]: {
            type: `${WfName}:${NotificationName}`;
            workflow: BaseWorkflowInstance<WfName>;
            step: string;
            payload: WorkflowDefinitions[WfName]['notifications'][NotificationName];
        };
    }[keyof WorkflowDefinitions[WfName]['notifications'] & string];
}[keyof WorkflowDefinitions & string];
export declare namespace Typings {
    export type Message<TChannel extends keyof ConversationDefinitions = keyof ConversationDefinitions, TType extends keyof ConversationDefinitions[TChannel]['messages'] = keyof ConversationDefinitions[TChannel]['messages']> = TChannel extends keyof ConversationDefinitions ? TType extends keyof ConversationDefinitions[TChannel]['messages'] ? Omit<CMessage, 'type' | 'tags' | 'payload'> & {
        type: TType;
        payload: ConversationDefinitions[TChannel]['messages'][TType];
        tags: ConversationDefinitions[TChannel]['messageTags'];
    } : never : never;
    export type Event<TChannel extends keyof ConversationDefinitions = keyof ConversationDefinitions> = TChannel extends keyof ConversationDefinitions ? {
        [EType in keyof ConversationDefinitions[TChannel]['events']]: {
            type: EType;
            payload: ConversationDefinitions[TChannel]['events'][EType];
        };
    }[keyof ConversationDefinitions[TChannel]['events'] & (string | number)] | WorkflowCallbackEventType : never;
    export type ExtractChannel<T extends ChannelSpec> = T extends readonly string[] ? T[number] : T extends '*' ? Channels : T;
    /**
     * Extract event name from "integration:eventName" format.
     * e.g., "webchat:conversationStarted" -> "conversationStarted"
     */
    type ExtractEventName<T extends string> = T extends `${string}:${infer EventName}` ? EventName : T;
    /**
     * Check if an event name is a custom event (no colon separator).
     * Custom events are defined in agent.config.ts.
     */
    type IsCustomEvent<T extends string> = T extends `${string}:${string}` ? false : true;
    /**
     * Extract integration alias from "alias:eventName" format.
     * e.g., "webchat:conversationStarted" -> "webchat"
     */
    type ExtractIntegrationAlias<T extends string> = T extends `${infer Alias}:${string}` ? Alias : never;
    /**
     * Get event payload from an event type string.
     * Supports both integration events and custom events.
     *
     * For integration events (format "alias:eventName"), this looks up the event
     * directly from the Integrations type using the alias and event name.
     * For custom events (no colon), this uses the EventPayload type.
     */
    type GetEventPayload<T extends string> = IsCustomEvent<T> extends true ? T extends EventName ? CustomEventPayload<T> : unknown : ExtractIntegrationAlias<T> extends infer Alias ? Alias extends keyof Integrations ? ExtractEventName<T> extends keyof Integrations[Alias]['events'] ? Integrations[Alias]['events'][ExtractEventName<T>] : unknown : unknown : unknown;
    /**
     * Create a discriminated union of event handler props for each event type.
     * The conversation instance is always typed based on the conversation's channel,
     * not the event's source integration.
     */
    type EventHandlerProps<TEvents extends readonly string[], State extends ZuiType, TChannel extends keyof ConversationDefinitions = keyof ConversationDefinitions> = TEvents extends readonly [] ? never : {
        [K in TEvents[number]]: {
            type: 'event';
            channel: TChannel;
            conversation: BaseConversationInstance<TChannel>;
            event: {
                type: K;
                payload: GetEventPayload<K>;
            } | WorkflowCallbackEventType;
            message?: never;
            workflow?: never;
            request?: never;
            completion?: never;
            notification?: never;
            state: z.infer<State>;
            client: BotClient<any>;
            execute: Autonomous.ConvoExecuteFn;
            chat: Chat;
        };
    }[TEvents[number]];
    /**
     * Fallback handler props for wildcard channel (`"*"`).
     * Used when `ConversationDefinitions` has no entry for the incoming channel —
     * i.e. the handler was registered with `channel: "*"` and no specific handler
     * populated that channel in the generated types.
     *
     * `execute` is always correctly typed and callable.
     * Channel-specific properties (`message`, `event`, `conversation`) are `unknown`
     * because the concrete channel is only known at runtime.
     */
    type WildcardHandlerProps<State extends ZuiType> = {
        type: 'message' | 'event' | 'workflow_request' | 'workflow_callback' | 'workflow_notify' | 'nudge' | 'expire';
        channel: Channels;
        conversation: {
            readonly channel: Channels;
            readonly id: string;
            send: (type: string, payload?: unknown) => Promise<void>;
            startTyping: () => Promise<void>;
            stopTyping: () => Promise<void>;
        };
        message?: unknown;
        event?: unknown;
        request?: unknown;
        completion?: unknown;
        notification?: unknown;
        state: z.infer<State>;
        client: BotClient<any>;
        execute: Autonomous.ConvoExecuteFn;
        chat: Chat;
    };
    export type HandlerProps<TChannelSpec extends ChannelSpec = ChannelSpec, State extends ZuiType = ZuiType, TEvents extends readonly string[] = readonly [], Channel extends string = ExtractChannel<TChannelSpec>> = TChannelSpec extends '*' ? WildcardHandlerProps<State> : Channel extends keyof ConversationDefinitions ? TEvents extends readonly [] ? {
        type: 'message';
        channel: Channel;
        conversation: BaseConversationInstance<Channel>;
        message: Message<Channel>;
        event?: never;
        workflow?: never;
        request?: never;
        completion?: never;
        notification?: never;
        state: z.infer<State>;
        client: BotClient<any>;
        execute: Autonomous.ConvoExecuteFn;
        chat: Chat;
    } | {
        type: 'workflow_request';
        channel: Channel;
        conversation: BaseConversationInstance<Channel>;
        event: WorkflowDataRequestEventType;
        message?: never;
        workflow?: never;
        request: WorkflowRequest;
        completion?: never;
        notification?: never;
        state: z.infer<State>;
        client: BotClient<any>;
        execute: Autonomous.ConvoExecuteFn;
        chat: Chat;
    } | {
        type: 'workflow_notify';
        channel: Channel;
        conversation: BaseConversationInstance<Channel>;
        event: WorkflowNotifyEventType;
        message?: never;
        workflow?: never;
        request?: never;
        completion?: never;
        notification: WorkflowNotification;
        state: z.infer<State>;
        client: BotClient<any>;
        execute: Autonomous.ConvoExecuteFn;
        chat: Chat;
    } | {
        type: 'workflow_callback';
        channel: Channel;
        conversation: BaseConversationInstance<Channel>;
        event: WorkflowCallbackEventType;
        message?: never;
        workflow?: never;
        request?: never;
        completion: WorkflowCallback;
        notification?: never;
        state: z.infer<State>;
        client: BotClient<any>;
        execute: Autonomous.ConvoExecuteFn;
        chat: Chat;
    } | {
        type: 'nudge';
        channel: Channel;
        conversation: BaseConversationInstance<Channel>;
        event: LifecycleNudgeEventType;
        message?: never;
        workflow?: never;
        request?: never;
        completion?: never;
        notification?: never;
        state: z.infer<State>;
        client: BotClient<any>;
        execute: Autonomous.ConvoExecuteFn;
        chat: Chat;
    } | {
        type: 'expire';
        channel: Channel;
        conversation: BaseConversationInstance<Channel>;
        event: LifecycleExpireEventType;
        message?: never;
        workflow?: never;
        request?: never;
        completion?: never;
        notification?: never;
        state: z.infer<State>;
        client: BotClient<any>;
        execute: Autonomous.ConvoExecuteFn;
        chat: Chat;
    } : {
        type: 'message';
        channel: Channel;
        conversation: BaseConversationInstance<Channel>;
        message: Message<Channel>;
        event?: never;
        workflow?: never;
        request?: never;
        completion?: never;
        notification?: never;
        state: z.infer<State>;
        client: BotClient<any>;
        execute: Autonomous.ConvoExecuteFn;
        chat: Chat;
    } | EventHandlerProps<TEvents, State, Channel> | {
        type: 'workflow_request';
        channel: Channel;
        conversation: BaseConversationInstance<Channel>;
        event: WorkflowDataRequestEventType;
        message?: never;
        workflow?: never;
        request: WorkflowRequest;
        completion?: never;
        notification?: never;
        state: z.infer<State>;
        client: BotClient<any>;
        execute: Autonomous.ConvoExecuteFn;
        chat: Chat;
    } | {
        type: 'workflow_notify';
        channel: Channel;
        conversation: BaseConversationInstance<Channel>;
        event: WorkflowNotifyEventType;
        message?: never;
        workflow?: never;
        request?: never;
        completion?: never;
        notification: WorkflowNotification;
        state: z.infer<State>;
        client: BotClient<any>;
        execute: Autonomous.ConvoExecuteFn;
        chat: Chat;
    } | {
        type: 'workflow_callback';
        channel: Channel;
        conversation: BaseConversationInstance<Channel>;
        event: WorkflowCallbackEventType;
        message?: never;
        workflow?: never;
        request?: never;
        completion: WorkflowCallback;
        notification?: never;
        state: z.infer<State>;
        client: BotClient<any>;
        execute: Autonomous.ConvoExecuteFn;
        chat: Chat;
    } | {
        type: 'nudge';
        channel: Channel;
        conversation: BaseConversationInstance<Channel>;
        event: LifecycleNudgeEventType;
        message?: never;
        workflow?: never;
        request?: never;
        completion?: never;
        notification?: never;
        state: z.infer<State>;
        client: BotClient<any>;
        execute: Autonomous.ConvoExecuteFn;
        chat: Chat;
    } | {
        type: 'expire';
        channel: Channel;
        conversation: BaseConversationInstance<Channel>;
        event: LifecycleExpireEventType;
        message?: never;
        workflow?: never;
        request?: never;
        completion?: never;
        notification?: never;
        state: z.infer<State>;
        client: BotClient<any>;
        execute: Autonomous.ConvoExecuteFn;
        chat: Chat;
    } : never;
    export type Handler<TChannelSpec extends ChannelSpec = ChannelSpec, State extends ZuiType = ZuiType, TEvents extends readonly string[] = readonly []> = (props: HandlerProps<TChannelSpec, State, TEvents>) => Promise<void> | void;
    /**
     * Get available routable event names for a given channel.
     * These are events that have a conversationId property and can be routed to conversations.
     */
    export type RoutableEventNames<TChannel extends keyof ConversationDefinitions> = TChannel extends keyof ConversationRoutableEvents ? ConversationRoutableEvents[TChannel][number] : never;
    /**
     * Event specification type for conversations.
     * Includes both:
     * - Integration events that are routable for the channel(s) (have conversationId)
     * - Custom events defined in agent.config.ts
     */
    export type EventSpec<TChannelSpec extends ChannelSpec> = ExtractChannel<TChannelSpec> extends keyof ConversationRoutableEvents ? readonly (ConversationRoutableEvents[ExtractChannel<TChannelSpec>][number] | EventName)[] : readonly (string | EventName)[];
    /**
     * Input passed to the {@link Props.shouldInterrupt} predicate for each event
     * that arrives while the handler is running.
     *
     * The candidate is surfaced in its raw form (`message_created` events carry a
     * `message`; everything else carries an `event`) rather than the resolved
     * handler discriminated union — resolving workflow/notification objects would
     * require loading workflow instances inside the polling loop, which is too
     * expensive for a per-event hot path.
     *
     * - `kind: 'message'` — a user message arrived. `message` is set.
     * - `kind: 'event'` — any other event arrived. `event` is set; branch on
     *   `event.type` (e.g. custom event names, `"slack:reactionAdded"`).
     *
     * Internal `workflowNotify` / `lifecycleNudge` / `lifecycleExpire` events
     * never reach this predicate — they are guaranteed never to interrupt.
     */
    export type ShouldInterruptProps = {
        kind: 'message';
        /** The incoming message. */
        message: CMessage;
        event?: never;
        /** The event currently being processed (the one the handler was invoked for). */
        current: CEvent | undefined;
    } | {
        kind: 'event';
        message?: never;
        /** The incoming raw event. Branch on `event.type`. */
        event: CEvent;
        /** The event currently being processed (the one the handler was invoked for). */
        current: CEvent | undefined;
    };
    export type Props<TChannelSpec extends ChannelSpec = ChannelSpec, State extends ZuiType = ZuiType, TEvents extends EventSpec<TChannelSpec> = readonly []> = {
        channel: TChannelSpec;
        handler: Handler<TChannelSpec, State, TEvents>;
        state?: State;
        /**
         * Narrow which incoming events interrupt (abort) the in-flight handler.
         *
         * Internal `workflowNotify` / `lifecycleNudge` / `lifecycleExpire` events
         * never interrupt — that is a fixed invariant. By default every *other*
         * newer event interrupts. This predicate lets you opt specific events out:
         * it is called only for events that are already interruption candidates
         * (newer than the event being processed, not that event itself, and not an
         * internal event), and can only narrow further — it cannot make an internal
         * event interrupt.
         *
         * Return `true` to abort current processing, `false` to let the handler
         * finish — the ignored event stays pending and is picked up by the next
         * handler invocation (it is processed, just not mid-flight). A predicate
         * that always returns `false` puts the conversation in "let me finish my
         * turn" mode, queueing messages and processing them one run at a time.
         *
         * Must be synchronous — it runs inside a 50ms polling loop.
         */
        shouldInterrupt?: (props: ShouldInterruptProps) => boolean;
        /**
         * Array of event names this conversation should listen to.
         * Supports both:
         * - Integration events with conversationId (e.g., "webchat:conversationStarted")
         * - Custom events defined in agent.config.ts (e.g., "orderPlaced")
         * By default, conversations only receive messages, not events.
         */
        events?: TEvents;
        chat?: (props: {
            context: BotContext;
            channel: ExtractChannel<TChannelSpec>;
        }) => Chat;
        /**
         * Optional lifecycle management for nudge-on-silence and idle expiration.
         * Durations use `ms`-compatible strings (e.g., "5m", "1h", "30s").
         *
         * - `nudge.after`: time of silence before the first nudge fires
         * - `nudge.interval`: time between subsequent nudges (defaults to `nudge.after`)
         * - `nudge.max`: maximum number of nudges before stopping (unlimited if omitted)
         * - `expire.after`: time of silence before the conversation session expires
         */
        lifecycle?: {
            nudge?: {
                after: string;
                interval?: string;
                max?: number;
            };
            expire?: {
                after: string;
            };
        };
        /**
         * Custom components the LLM can yield during autonomous execution.
         * Each component must have been created with component metadata:
         * `new CustomComponent(component, { description, props, exampleValues })`
         */
        components?: BaseCustomComponent<any>[];
    };
    export const Primitive: "conversation";
    export {};
}
/**
 * Parsed lifecycle configuration with durations converted to milliseconds.
 * Stored on BaseConversation after construction-time validation.
 */
export type LifecycleConfig = {
    nudge?: {
        afterMs: number;
        intervalMs: number;
        max?: number;
    };
    expire?: {
        afterMs: number;
    };
};
/**
 * Base Conversation definition class.
 * This defines a conversation handler for one or more channels.
 * At runtime, it will be instantiated as a BaseConversationInstance.
 *
 * The generated Conversation class in runtime.d.ts provides proper typing.
 */
export declare class BaseConversation<TChannelSpec extends ChannelSpec = ChannelSpec, State extends ZuiType = ZuiType, TEvents extends Typings.EventSpec<TChannelSpec> = readonly []> implements Definitions.Primitive {
    #private;
    readonly channel: ChannelSpec;
    /**
     * Array of event names this conversation listens to.
     * Only events with conversationId property are allowed.
     * Empty array means no events (only messages).
     */
    readonly events: readonly string[];
    constructor(props: Typings.Props<TChannelSpec, State, TEvents>);
    /**
     * Load a conversation by explicit ID.
     * Delegates to BaseConversationInstance.get().
     *
     * @param id - The conversation ID to load
     * @returns A BaseConversationInstance (unparameterized channel)
     */
    static get(id: string): Promise<BaseConversationInstance>;
}
export {};
//# sourceMappingURL=conversation.d.ts.map