import type { ActionListenerEvent } from './actions/index.js';
import { type AgentLike } from './facade.js';
import type { RelayMessage, RelayMessageChannelRef, RelayMessageCreatedEvent, RelayMessageReadEvent, RelayMessageSender, RelayMessageTarget, RelayMessagingEvent, RelayMessagingEventsSurface, RelayReactionEvent } from './messaging/index.js';
import type { AgentSessionEvent, AgentSessionStatus } from './session/index.js';
/** A session event tagged with the id of the agent that produced it. */
export interface SessionListenerEnvelope {
    agentId: string;
    event: AgentSessionEvent;
}
/** Wiring handed to a predicate when `relay.on(...)` subscribes it. */
export interface ListenerContext {
    events: RelayMessagingEventsSurface;
    onActionEvent(handler: (event: ActionListenerEvent) => void): () => void;
    onSessionEvent(handler: (envelope: SessionListenerEnvelope) => void): () => void;
    /** Receives handler errors; defaults to a console warning when unset. */
    onError?: RelayErrorHook;
}
export type ListenerHandler<TEvent = unknown> = (event: TEvent) => void | Promise<void>;
export interface ListenerPredicate<TEvent = unknown> {
    subscribe(context: ListenerContext, handler: ListenerHandler<TEvent>): () => void;
}
/** Identifies the listener or action that produced a handler error. */
export interface RelayErrorContext {
    source: 'listener' | 'action';
    /** Selector string or predicate event name for listener errors. */
    selector?: string;
    /** Action name for action-related errors. */
    action?: string;
    /** The action wiring operation that failed (e.g. `register`, `complete_invocation`). */
    operation?: string;
}
/** Hook invoked when a listener or action handler throws. */
export type RelayErrorHook = (error: unknown, context: RelayErrorContext) => void;
/** Default reporting for handler errors when no `onError` hook is registered. */
export declare function logRelayHandlerError(error: unknown, context: RelayErrorContext): void;
export declare class MessageCreatedPredicate implements ListenerPredicate<RelayMessageCreatedEvent> {
    private channel?;
    private mentioned?;
    in(channel: string): this;
    mentions(agent: AgentLike): this;
    subscribe(context: ListenerContext, handler: ListenerHandler<RelayMessageCreatedEvent>): () => void;
}
export declare class MessageReadPredicate implements ListenerPredicate<RelayMessageReadEvent> {
    subscribe(context: ListenerContext, handler: ListenerHandler<RelayMessageReadEvent>): () => void;
}
export declare class MessageReactedPredicate implements ListenerPredicate<RelayReactionEvent> {
    subscribe(context: ListenerContext, handler: ListenerHandler<RelayReactionEvent>): () => void;
}
export interface MessageEventBuilders {
    created(): MessageCreatedPredicate;
    read(): MessageReadPredicate;
    reacted(): MessageReactedPredicate;
}
export interface EnrichedEvents extends RelayMessagingEventsSurface {
    message: MessageEventBuilders;
}
export declare function createEnrichedEvents(base: RelayMessagingEventsSurface): EnrichedEvents;
export declare class ActionPredicate implements ListenerPredicate<ActionListenerEvent> {
    private readonly action;
    private caller?;
    private phase;
    constructor(action: string);
    calledBy(agent: AgentLike): this;
    completed(): this;
    failed(): this;
    denied(): this;
    subscribe(context: ListenerContext, handler: ListenerHandler<ActionListenerEvent>): () => void;
}
/**
 * Shared shape of the typed action events delivered by the predicates on a
 * {@link TypedActionHandle}. Mirrors the public {@link RelayActionEvent} (the
 * caller surfaces as `agent`), with `input`/`output` carrying the generics
 * captured at `registerAction(...)` time instead of `unknown`.
 */
export interface TypedActionEventBase<TInput = unknown> {
    action: string;
    agent: ActionListenerEvent['caller'];
    input?: TInput;
    at: string;
}
export interface ActionInvokedEvent<TInput = unknown> extends TypedActionEventBase<TInput> {
    type: 'action.invoked';
}
export interface ActionCompletedEvent<TInput = unknown, TOutput = unknown> extends TypedActionEventBase<TInput> {
    type: 'action.completed';
    /** The handler's return value, typed from the `output` schema (or the handler's return type). */
    output: TOutput;
}
export interface ActionFailedEvent<TInput = unknown> extends TypedActionEventBase<TInput> {
    type: 'action.failed';
    error: string;
}
export interface ActionDeniedEvent<TInput = unknown> extends TypedActionEventBase<TInput> {
    type: 'action.denied';
    reason?: string;
}
/**
 * A phase-bound action predicate carrying the event type captured at
 * registration. Built by the {@link TypedActionHandle} returned from
 * `relay.registerAction(...)`; behaves like {@link ActionPredicate} at runtime
 * but delivers a typed event, so handlers read `event.output` without casts.
 */
export declare class TypedActionPredicate<TEvent extends TypedActionEventBase> implements ListenerPredicate<TEvent> {
    private readonly action;
    private readonly phase;
    private caller?;
    constructor(action: string, phase: ActionListenerEvent['type']);
    calledBy(agent: AgentLike): this;
    subscribe(context: ListenerContext, handler: ListenerHandler<TEvent>): () => void;
}
/**
 * Handle returned by `relay.registerAction(...)`. Alongside `unregister()` it
 * exposes typed predicate builders bound to the registered action, so result
 * subscriptions keep the registration's `input`/`output` types:
 *
 * ```ts
 * const handle = relay.registerAction({ name: 'score', input, output, handler });
 * relay.addListener(handle.completed(), (event) => event.output); // typed, no cast
 * relay.addListener(handle.failed(), (event) => event.error);
 * ```
 */
export interface TypedActionHandle<TInput = unknown, TOutput = unknown> {
    /** The registered action name. */
    readonly name: string;
    unregister(): void;
    invoked(): TypedActionPredicate<ActionInvokedEvent<TInput>>;
    completed(): TypedActionPredicate<ActionCompletedEvent<TInput, TOutput>>;
    failed(): TypedActionPredicate<ActionFailedEvent<TInput>>;
    denied(): TypedActionPredicate<ActionDeniedEvent<TInput>>;
}
export declare function createTypedActionHandle<TInput, TOutput>(name: string, unregister: () => void): TypedActionHandle<TInput, TOutput>;
export declare class StatusPredicate implements ListenerPredicate<AgentSessionEvent> {
    private readonly agentId;
    private readonly status;
    constructor(agentId: string, status: AgentSessionStatus);
    subscribe(context: ListenerContext, handler: ListenerHandler<AgentSessionEvent>): () => void;
}
type ToolCalledEvent = Extract<AgentSessionEvent, {
    type: 'tool.called';
}>;
export declare class ToolCalledPredicate implements ListenerPredicate<ToolCalledEvent> {
    private readonly agentId;
    private readonly tool;
    private filter?;
    constructor(agentId: string, tool: string);
    where(filter: (event: ToolCalledEvent) => boolean): this;
    subscribe(context: ListenerContext, handler: ListenerHandler<ToolCalledEvent>): () => void;
}
export interface AgentStatusBuilders {
    becomes(status: AgentSessionStatus): StatusPredicate;
}
export interface AgentToolBuilders {
    called(tool: string): ToolCalledPredicate;
}
/**
 * A live handle for an agent that carries its identity plus predicate builders
 * used with `relay.on(...)`. Returned by harness `create(...)` and `relay.agent(...)`.
 */
export interface RelayAgentHandle {
    id: string;
    name: string;
    handle: string;
    token?: string;
    status: AgentStatusBuilders;
    tools: AgentToolBuilders;
}
export interface AgentHandleInput {
    id: string;
    name: string;
    handle?: string;
    token?: string;
}
/** Flat, ergonomic view of a message event's participants and location. */
export interface RelayEventEnvelope {
    from?: RelayMessageSender;
    to?: RelayMessageTarget;
    channel?: RelayMessageChannelRef;
    parent?: string;
}
export type RelayMessageEventType = 'message.created' | 'message.updated' | 'thread.reply' | 'dm.received' | 'group_dm.received';
export interface RelayMessageEvent<TType extends RelayMessageEventType = RelayMessageEventType> {
    type: TType;
    message: RelayMessage;
    envelope: RelayEventEnvelope;
}
export interface RelayMessageReadEventPublic {
    type: 'message.read';
    messageId: string;
    agentName: string;
    readAt?: string;
}
export interface RelayMessageReactedEvent {
    type: 'message.reacted';
    messageId: string;
    emoji: string;
    agentName: string;
    action: 'added' | 'removed';
}
export type RelayActionEventType = 'action.invoked' | 'action.completed' | 'action.failed' | 'action.denied';
export interface RelayActionEvent<TType extends RelayActionEventType = RelayActionEventType> {
    type: TType;
    action: string;
    agent: ActionListenerEvent['caller'];
    input?: unknown;
    output?: unknown;
    error?: string;
    reason?: string;
    at: string;
}
export interface RelayAgentStatusEvent {
    type: 'agent.status.changed' | 'agent.status.idle' | 'agent.status.active' | 'agent.status.blocked' | 'agent.status.waiting' | 'agent.status.offline';
    agentId: string;
    status?: AgentSessionStatus;
    reason?: string;
}
export interface RelaySessionEvent {
    type: string;
    agentId: string;
    event: AgentSessionEvent;
}
/** The discriminated event object delivered to every `addListener` handler. */
export type RelayEvent = RelayMessageEvent | RelayMessageReadEventPublic | RelayMessageReactedEvent | RelayActionEvent | RelayAgentStatusEvent | RelaySessionEvent;
/**
 * Maps exact dotted selectors to the event type their handlers receive.
 * Wildcard selectors (`'*'`, `'message.*'`) and arbitrary strings keep the
 * full {@link RelayEvent} union.
 */
export interface RelayEventMap {
    'message.created': RelayMessageEvent<'message.created'>;
    'message.updated': RelayMessageEvent<'message.updated'>;
    'thread.reply': RelayMessageEvent<'thread.reply'>;
    'dm.received': RelayMessageEvent<'dm.received'>;
    'group_dm.received': RelayMessageEvent<'group_dm.received'>;
    'message.read': RelayMessageReadEventPublic;
    'message.reacted': RelayMessageReactedEvent;
    'action.invoked': RelayActionEvent<'action.invoked'>;
    'action.completed': RelayActionEvent<'action.completed'>;
    'action.failed': RelayActionEvent<'action.failed'>;
    'action.denied': RelayActionEvent<'action.denied'>;
    'agent.status.changed': RelayAgentStatusEvent;
    'agent.status.idle': RelayAgentStatusEvent;
    'agent.status.active': RelayAgentStatusEvent;
    'agent.status.blocked': RelayAgentStatusEvent;
    'agent.status.waiting': RelayAgentStatusEvent;
    'agent.status.offline': RelayAgentStatusEvent;
}
/** Map a raw messaging event to its public form, or `undefined` if not surfaced. */
export declare function toPublicMessagingEvent(raw: RelayMessagingEvent): RelayEvent | undefined;
/** Match a selector (`'*'`, `'message.*'`, or an exact dotted name) against an event type. */
export declare function matchesSelector(selector: string, type: string): boolean;
export interface ActionEventSource {
    onEvent?(handler: (event: ActionListenerEvent) => void): () => void;
}
export interface ListenerHubOptions {
    /** Receives listener handler errors; defaults to a console warning when unset. */
    onError?: RelayErrorHook;
}
export interface ListenerHub {
    readonly events: EnrichedEvents;
    on<TEvent>(predicate: ListenerPredicate<TEvent>, handler: ListenerHandler<TEvent>): () => void;
    /** Subscribe with a typed predicate — the handler receives the predicate's event type. */
    addListener<TEvent>(selector: ListenerPredicate<TEvent>, handler: ListenerHandler<TEvent>): () => void;
    /** Subscribe by dotted event name, `'*'`/prefix wildcard, or a predicate. */
    addListener<K extends keyof RelayEventMap>(selector: K, handler: ListenerHandler<RelayEventMap[K]>): () => void;
    addListener(selector: string | ListenerPredicate, handler: ListenerHandler<RelayEvent>): () => void;
    /** Like `addListener`, but auto-unsubscribes after the first matching event. */
    once<K extends keyof RelayEventMap>(selector: K, handler: ListenerHandler<RelayEventMap[K]>): () => void;
    once(selector: string | ListenerPredicate, handler: ListenerHandler<RelayEvent>): () => void;
    action(name: string): ActionPredicate;
    agent(input: AgentHandleInput): RelayAgentHandle;
    /** Feed a harness session event into the hub so agent predicates can fire. */
    emitSessionEvent(agentId: string, event: AgentSessionEvent): void;
}
export declare function createListenerHub(baseEvents: RelayMessagingEventsSurface, actions: ActionEventSource, options?: ListenerHubOptions): ListenerHub;
export declare function createAgentHandle(input: AgentHandleInput): RelayAgentHandle;
export {};
//# sourceMappingURL=listeners.d.ts.map