import { ToolStreamEvent } from '../tools/tool.js';
import { interruptFromAgent } from '../interrupt.js';
/**
 * Agent hook events.
 *
 * All events extend {@link StreamEvent} with a `readonly type` discriminator
 * (camelCase of the class name) for switch-based narrowing. Constructor takes
 * a single data-object parameter. Most properties are readonly — writable fields
 * are the hook-driven control/data fields documented per event
 * (e.g. `cancel`, `retry`, `selectedTool`, `resume`, and mutable `toolUse` / `result`).
 *
 * All current events extend {@link HookableEvent} (which itself extends {@link StreamEvent}),
 * making them both streamable and subscribable via hook callbacks. {@link StreamEvent} exists
 * as the base class for potential future events that should be stream-only without hookability.
 *
 * ## Event categories
 *
 * **Lifecycle events** — Before/After pairs that bracket agent operations.
 * - Naming: `Before<Noun>Event` / `After<Noun>Event`
 * - `After*` events override `_shouldReverseCallbacks()` → `true` for cleanup ordering.
 * - Examples: {@link BeforeInvocationEvent}/{@link AfterInvocationEvent},
 *   {@link BeforeModelCallEvent}/{@link AfterModelCallEvent},
 *   {@link BeforeToolsEvent}/{@link AfterToolsEvent},
 *   {@link BeforeToolCallEvent}/{@link AfterToolCallEvent}
 *
 * **State-change events** — Signal that agent state was mutated.
 * - Naming: `<Noun><PastTense>Event`
 * - Examples: {@link InitializedEvent}, {@link MessageAddedEvent}
 *
 * **Data events** — Wrap data objects produced during agent execution.
 * Two sub-categories:
 *
 *   *Update events* — wrap transient streaming data from lower layers.
 *   - Naming: `<Source>StreamUpdateEvent`, payload field: `.event`
 *   - Examples: {@link ModelStreamUpdateEvent}, {@link ToolStreamUpdateEvent}
 *
 *   *Completion events* — wrap finished data after processing completes.
 *   - Naming: descriptive `<Noun>Event`, payload field matches data type
 *     (`.result` for results, `.message` for messages, `.contentBlock` for content blocks).
 *   - Examples: {@link ContentBlockEvent}, {@link ModelMessageEvent},
 *     {@link ToolResultEvent}, {@link AgentResultEvent}
 *
 * ## Field naming conventions
 *
 * | Field              | Usage                                            |
 * |--------------------|--------------------------------------------------|
 * | `agent`            | `LocalAgent` reference on all agent-loop events  |
 * | `invocationState`  | Per-invocation state — see below                 |
 * | `.event`           | Inner event in update wrappers                   |
 * | `.result`          | Finished result object                           |
 * | `.message`         | Message object                                   |
 * | `.contentBlock`    | Content block object                             |
 *
 * ## `invocationState` on events
 *
 * Every hookable event that fires **during** an invocation carries
 * {@link InvocationState} — the per-invocation mutable bag shared across hooks
 * and tools. This lets any callback (lifecycle, data, streaming, completion)
 * correlate back to the caller's request context (`userId`, `traceId`, etc.)
 * without closure workarounds.
 *
 * The only events without `invocationState` are the ones that fire **outside**
 * any invocation scope: {@link InitializedEvent} and `MultiAgentInitializedEvent`,
 * both of which fire at construction.
 *
 * New events should follow the same rule: carry `invocationState` unless the
 * event fires before any invocation exists.
 */
/**
 * Base class for all events yielded by `agent.stream()`.
 * Carries no hookability — subclasses that should be hookable extend {@link HookableEvent} instead.
 */
export class StreamEvent {
}
/**
 * Base class for events that can be subscribed to via the hook system.
 * Only events extending this class are dispatched to {@link HookRegistry} callbacks.
 * All current events extend this class. {@link StreamEvent} exists as the base for
 * potential future stream-only events that should not be hookable.
 */
export class HookableEvent extends StreamEvent {
    /**
     * @internal
     * Check if callbacks should be reversed for this event.
     * Used by HookRegistry for callback ordering.
     */
    _shouldReverseCallbacks() {
        return false;
    }
}
/**
 * Event triggered when an agent has finished initialization.
 * Fired after the agent has been fully constructed and all built-in components have been initialized.
 */
export class InitializedEvent extends HookableEvent {
    type = 'initializedEvent';
    agent;
    constructor(data) {
        super();
        this.agent = data.agent;
    }
    /**
     * Serializes for wire transport, excluding the agent reference.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return { type: this.type };
    }
}
/**
 * Event triggered at the beginning of a new agent request.
 * Fired before any model inference or tool execution occurs.
 */
export class BeforeInvocationEvent extends HookableEvent {
    type = 'beforeInvocationEvent';
    agent;
    invocationState;
    /**
     * Set by hook callbacks to cancel this invocation.
     * When set to `true`, a default cancel message is used.
     * When set to a string, that string is used as the assistant response message.
     */
    cancel = false;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.invocationState = data.invocationState;
    }
    /**
     * Serializes for wire transport, excluding the agent reference and invocationState.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return { type: this.type };
    }
}
/**
 * Event triggered at the end of an agent request.
 * Fired after all processing completes, regardless of success or error.
 * Uses reverse callback ordering for proper cleanup semantics.
 */
export class AfterInvocationEvent extends HookableEvent {
    type = 'afterInvocationEvent';
    agent;
    invocationState;
    /**
     * Set by hook callbacks to trigger a follow-up agent invocation with new input.
     * When set, after this event's callbacks complete the agent re-enters its loop
     * with these args as new input, under the same invocation lock. A fresh
     * {@link BeforeInvocationEvent}/{@link AfterInvocationEvent} pair fires for the
     * resumed run. Ignored if the invocation ended with an error.
     *
     * If multiple callbacks set `resume`, the last callback to run wins.
     */
    resume = undefined;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.invocationState = data.invocationState;
    }
    _shouldReverseCallbacks() {
        return true;
    }
    /**
     * Serializes for wire transport, excluding the agent reference, invocationState,
     * and mutable resume field.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return { type: this.type };
    }
}
/**
 * Event triggered when the framework adds a message to the conversation history.
 * Fired for user input, assistant responses, and tool-result messages added
 * during agent execution. Does not fire for messages preloaded via
 * `AgentConfig.messages` or messages manually pushed to `agent.messages`.
 */
export class MessageAddedEvent extends HookableEvent {
    type = 'messageAddedEvent';
    agent;
    message;
    invocationState;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.message = data.message;
        this.invocationState = data.invocationState;
    }
    /**
     * Serializes for wire transport, excluding the agent reference and invocationState.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return { type: this.type, message: this.message };
    }
}
/**
 * Event triggered just before a tool is executed.
 * Fired after tool lookup but before execution begins.
 *
 * Hook callbacks can:
 * - Set {@link cancel} to prevent the tool from executing.
 * - Set {@link selectedTool} to execute a different tool in place of the registry's match.
 * - Mutate {@link toolUse} to rewrite the tool input, id, or name before execution.
 *   If `name` is changed and `selectedTool` is not set, the tool is re-resolved from
 *   the registry under the new name.
 */
export class BeforeToolCallEvent extends HookableEvent {
    type = 'beforeToolCallEvent';
    agent;
    toolUse;
    tool;
    invocationState;
    /**
     * Set by hook callbacks to cancel this tool call.
     * When set to `true`, a default cancel message is used.
     * When set to a string, that string is used as the tool result error message.
     */
    cancel = false;
    /**
     * Set by hook callbacks to execute a replacement tool instead of {@link tool}.
     * When undefined, the tool looked up from the registry (or re-resolved from a
     * mutated `toolUse.name`) is used.
     *
     * If multiple callbacks set `selectedTool`, the last callback to run wins.
     * Callbacks run in registration order for this event, so the last-registered
     * callback's value is the one used.
     */
    selectedTool = undefined;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.toolUse = data.toolUse;
        this.tool = data.tool;
        this.invocationState = data.invocationState;
    }
    /**
     * Raises an interrupt for human-in-the-loop workflows.
     * If a response is available (from a previous resume), returns it immediately.
     * Otherwise, throws an InterruptError to halt agent execution.
     *
     * @param params - Interrupt parameters including name and optional reason
     * @returns The user's response when resuming from an interrupt
     */
    interrupt(params) {
        return interruptFromAgent(this.agent, `hook:beforeToolCall:${this.toolUse.toolUseId}:${params.name}`, params, 'hook');
    }
    /**
     * Serializes for wire transport, excluding the agent reference, tool instance,
     * invocationState, and mutable cancel / selectedTool fields.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return { type: this.type, toolUse: this.toolUse };
    }
}
/**
 * Event triggered after a tool execution completes.
 * Fired after tool execution finishes, whether successful or failed.
 * Uses reverse callback ordering for proper cleanup semantics.
 *
 * Hook callbacks can mutate {@link result} to rewrite the tool result before it
 * propagates to the model (e.g. to redact or truncate output).
 */
export class AfterToolCallEvent extends HookableEvent {
    type = 'afterToolCallEvent';
    agent;
    toolUse;
    tool;
    /**
     * The tool result. Can be replaced by hook callbacks to transform the result
     * before it enters the conversation history.
     */
    result;
    error;
    invocationState;
    /**
     * Optional flag that can be set by hook callbacks to request a retry of the tool call.
     * When set to true, the agent will re-execute the tool.
     */
    retry;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.toolUse = data.toolUse;
        this.tool = data.tool;
        this.result = data.result;
        this.invocationState = data.invocationState;
        if (data.error !== undefined) {
            this.error = data.error;
        }
    }
    _shouldReverseCallbacks() {
        return true;
    }
    /**
     * Serializes for wire transport, excluding the agent reference, tool instance, invocationState, and mutable retry flag.
     * Converts Error to an extensible object for safe wire serialization.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return {
            type: this.type,
            toolUse: this.toolUse,
            result: this.result,
            ...(this.error !== undefined && { error: { message: this.error.message } }),
        };
    }
}
/**
 * Event triggered just before the model is invoked.
 * Fired before sending messages to the model for inference.
 */
export class BeforeModelCallEvent extends HookableEvent {
    type = 'beforeModelCallEvent';
    agent;
    model;
    invocationState;
    /**
     * Set by hook callbacks to cancel this model call.
     * When set to `true`, a default cancel message is used.
     * When set to a string, that string is used as the assistant response message.
     */
    cancel = false;
    /**
     * Projected input token count for the upcoming model call.
     * Computed by the agent loop from message metadata and token estimation.
     * Available for hooks and plugins (e.g. conversation managers) to make
     * proactive decisions about context management.
     */
    projectedInputTokens;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.model = data.model;
        this.invocationState = data.invocationState;
        if (data.projectedInputTokens !== undefined) {
            this.projectedInputTokens = data.projectedInputTokens;
        }
    }
    /**
     * Serializes for wire transport, excluding the agent reference and invocationState.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return {
            type: this.type,
            ...(this.projectedInputTokens !== undefined && { projectedInputTokens: this.projectedInputTokens }),
        };
    }
}
/**
 * Event triggered after the model invocation completes.
 * Fired after the model finishes generating a response, whether successful or failed.
 * Uses reverse callback ordering for proper cleanup semantics.
 *
 * Note: stopData may be undefined if an error occurs before the model completes.
 */
export class AfterModelCallEvent extends HookableEvent {
    type = 'afterModelCallEvent';
    agent;
    model;
    stopData;
    error;
    invocationState;
    /**
     * 1-indexed count of model attempts for this turn, including the attempt
     * that just completed (or failed). The first call in a turn is `1`; each
     * subsequent retry increments by one.
     *
     * Retry strategies may rely on `attemptCount === 1` to mark the start of a
     * new retry sequence (e.g. to clear per-turn state carried over from a
     * previous turn). The agent loop guarantees this marker on every fresh turn.
     */
    attemptCount;
    /**
     * Optional flag that can be set by hook callbacks to request a retry of the model call.
     * When set to true, the agent will retry the model invocation.
     */
    retry;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.model = data.model;
        this.invocationState = data.invocationState;
        this.attemptCount = data.attemptCount;
        if (data.stopData !== undefined) {
            this.stopData = data.stopData;
        }
        if (data.error !== undefined) {
            this.error = data.error;
        }
    }
    _shouldReverseCallbacks() {
        return true;
    }
    /**
     * Serializes for wire transport, excluding the agent reference, invocationState, and mutable retry flag.
     * Converts Error to an extensible object for safe wire serialization.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return {
            type: this.type,
            attemptCount: this.attemptCount,
            ...(this.stopData !== undefined && { stopData: this.stopData }),
            ...(this.error !== undefined && { error: { message: this.error.message } }),
        };
    }
}
/**
 * Event triggered for each streaming event from the model.
 * Wraps a {@link ModelStreamEvent} (transient streaming delta) during model inference.
 * Completed content blocks are handled separately by {@link ContentBlockEvent}
 * because they represent different granularities: partial deltas vs fully assembled results.
 */
export class ModelStreamUpdateEvent extends HookableEvent {
    type = 'modelStreamUpdateEvent';
    agent;
    event;
    invocationState;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.event = data.event;
        this.invocationState = data.invocationState;
    }
    /**
     * Serializes for wire transport, excluding the agent reference and invocationState.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return { type: this.type, event: this.event };
    }
}
/**
 * Event triggered when a content block completes during model inference.
 * Wraps completed content blocks (TextBlock, ToolUseBlock, ReasoningBlock) from model streaming.
 * This is intentionally separate from {@link ModelStreamUpdateEvent}. The model's
 * `streamAggregated()` yields two kinds of output: {@link ModelStreamEvent} (transient
 * streaming deltas — partial data arriving while the model generates) and
 * {@link ContentBlock} (fully assembled results after all deltas accumulate).
 * These represent different granularities with different semantics, so they are
 * wrapped in distinct event classes rather than combined into a single event.
 */
export class ContentBlockEvent extends HookableEvent {
    type = 'contentBlockEvent';
    agent;
    contentBlock;
    invocationState;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.contentBlock = data.contentBlock;
        this.invocationState = data.invocationState;
    }
    /**
     * Serializes for wire transport, excluding the agent reference and invocationState.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return { type: this.type, contentBlock: this.contentBlock };
    }
}
/**
 * Event triggered when the model completes a full message.
 * Wraps the assembled message and stop reason after model streaming finishes.
 */
export class ModelMessageEvent extends HookableEvent {
    type = 'modelMessageEvent';
    agent;
    message;
    stopReason;
    invocationState;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.message = data.message;
        this.stopReason = data.stopReason;
        this.invocationState = data.invocationState;
    }
    /**
     * Serializes for wire transport, excluding the agent reference and invocationState.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return { type: this.type, message: this.message, stopReason: this.stopReason };
    }
}
/**
 * Event triggered when a tool execution completes.
 * Wraps the tool result block after a tool finishes execution.
 */
export class ToolResultEvent extends HookableEvent {
    type = 'toolResultEvent';
    agent;
    result;
    invocationState;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.result = data.result;
        this.invocationState = data.invocationState;
    }
    /**
     * Serializes for wire transport, excluding the agent reference and invocationState.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return { type: this.type, result: this.result };
    }
}
/**
 * Event triggered for each streaming progress event from a tool during execution.
 * Wraps a {@link ToolStreamEvent} with agent context, keeping the tool authoring
 * interface unchanged — tools construct `ToolStreamEvent` without knowledge of agents
 * or hooks, and the agent layer wraps them at the boundary.
 *
 * Consistent with {@link ModelStreamUpdateEvent} which wraps model streaming events
 * the same way.
 */
export class ToolStreamUpdateEvent extends HookableEvent {
    type = 'toolStreamUpdateEvent';
    agent;
    event;
    invocationState;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.event = data.event;
        this.invocationState = data.invocationState;
    }
    /**
     * Serializes for wire transport, excluding the agent reference and invocationState.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return { type: this.type, event: this.event };
    }
}
/**
 * Event triggered as the final event in the agent stream.
 * Wraps the agent result containing the stop reason and last message.
 */
export class AgentResultEvent extends HookableEvent {
    type = 'agentResultEvent';
    agent;
    result;
    invocationState;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.result = data.result;
        this.invocationState = data.invocationState;
    }
    /**
     * Serializes for wire transport, excluding the agent reference and invocationState.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return { type: this.type, result: this.result };
    }
}
/**
 * Event emitted when an interrupt is raised during agent execution. The `interrupt.source`
 * field discriminates between tool-callback and hook-callback origins. One event fires
 * per unanswered interrupt at the moment the agent stops to wait for responses.
 */
export class InterruptEvent extends HookableEvent {
    type = 'interruptEvent';
    agent;
    interrupt;
    invocationState;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.interrupt = data.interrupt;
        this.invocationState = data.invocationState;
    }
    /** Serializes for wire transport, excluding agent and invocationState. */
    toJSON() {
        return { type: this.type, interrupt: this.interrupt.toJSON() };
    }
}
/**
 * Event triggered before executing tools.
 * Fired when the model returns tool use blocks that need to be executed.
 * Hook callbacks can set {@link cancel} to prevent all tools from executing.
 */
export class BeforeToolsEvent extends HookableEvent {
    type = 'beforeToolsEvent';
    agent;
    message;
    invocationState;
    /**
     * Set by hook callbacks to cancel all tool calls.
     * When set to `true`, a default cancel message is used.
     * When set to a string, that string is used as the tool result error message.
     */
    cancel = false;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.message = data.message;
        this.invocationState = data.invocationState;
    }
    /**
     * Raises an interrupt for human-in-the-loop workflows.
     * If a response is available (from a previous resume), returns it immediately.
     * Otherwise, throws an InterruptError to halt agent execution.
     *
     * @param params - Interrupt parameters including name and optional reason
     * @returns The user's response when resuming from an interrupt
     */
    interrupt(params) {
        return interruptFromAgent(this.agent, `hook:beforeTools:${params.name}`, params, 'hook');
    }
    /**
     * Serializes for wire transport, excluding the agent reference, invocationState, and mutable cancel flag.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return { type: this.type, message: this.message };
    }
}
/**
 * Event triggered after all tools complete execution.
 * Fired after tool results are collected and ready to be added to conversation.
 * Uses reverse callback ordering for proper cleanup semantics.
 */
export class AfterToolsEvent extends HookableEvent {
    type = 'afterToolsEvent';
    agent;
    message;
    invocationState;
    /**
     * When set to `true`, the agent loop halts after this tool batch completes
     * without calling the model again and a default message
     * (`"Turn ended early by hook after tool execution"`) is appended as the
     * final assistant message. When set to a string, that string is used instead
     * of the default — the string becomes literal assistant content (a
     * `TextBlock`), not a reason or label. Contrast with
     * {@link BeforeToolCallEvent.cancel | cancel} fields on other events, where
     * the string is a cancellation reason.
     *
     * In both cases `stopReason` on the returned `AgentResult` is `'endTurn'`.
     */
    endTurn = false;
    constructor(data) {
        super();
        this.agent = data.agent;
        this.message = data.message;
        this.invocationState = data.invocationState;
    }
    _shouldReverseCallbacks() {
        return true;
    }
    /**
     * Serializes for wire transport, excluding the agent reference, invocationState,
     * and mutable endTurn field.
     * Called automatically by JSON.stringify().
     */
    toJSON() {
        return { type: this.type, message: this.message };
    }
}
//# sourceMappingURL=events.js.map