import type { Span } from '#compiled/@opentelemetry/api/index.js';
import { type SerializedData, type WorkflowRun, type World } from '#compiled/@workflow/world/index.js';
import type { StepInvocationQueueItem, WorkflowSuspension } from '../global.js';
import { type MutableEventLog } from './helpers.js';
export interface SuspensionHandlerParams {
    suspension: WorkflowSuspension;
    world: World;
    run: WorkflowRun;
    span?: Span;
    requestId?: string;
    /**
     * The runtime's loaded event log. Each event creation is sent with this
     * snapshot's `stateUpdatedAt` and, if the backend rejects it as stale (412),
     * the log is reloaded in place and the create is retried — see
     * `withPreconditionRetry`. Guarding per-create (rather than the whole
     * suspension) ensures a retry never re-issues an already-created event.
     */
    eventLog?: MutableEventLog;
    /**
     * Turbo mode only: a promise that resolves once the backgrounded
     * `run_started` has landed (the run exists). When present, every world write
     * this suspension performs (`hook_created`, `wait_created`, eager overflow
     * `step_created`, …) is gated on it so the write never races ahead of the
     * run's creation. The pure inline hot path defers all of its steps and writes
     * nothing here, so it never awaits this barrier. `undefined` outside turbo,
     * where `run_started` was already awaited up front.
     */
    runReadyBarrier?: Promise<unknown>;
}
/**
 * Result of handling a suspension. Returns pending step items so the caller
 * can decide which to execute inline vs queue to background.
 */
export interface SuspensionHandlerResult {
    /** Pending step items with events created but NOT queued */
    pendingSteps: StepInvocationQueueItem[];
    /**
     * Correlation IDs for which this suspension call actually wrote the
     * step_created event (as opposed to catching EntityConflictError because
     * a concurrent handler wrote it first). Only the handler that wrote the
     * step_created event should queue / inline-execute the step — this
     * guarantees a single owner per step, even when multiple handlers race
     * into the same batch boundary.
     */
    createdStepCorrelationIds: Set<string>;
    /**
     * The steps whose `step_created` writes were intentionally deferred so the
     * caller can run them inline via lazy `step_started` events (which create
     * the step on the fly), saving one world round-trip per inline step. Up to
     * `getMaxInlineSteps()` steps are deferred; the caller runs them inline in
     * parallel and queues the rest. Empty when no step was deferred (nothing
     * pending, or a `hook.getConflict()` awaiter is present so nothing is
     * executed inline). The caller passes each `dehydratedInput` straight to
     * `executeStep`, which sends it as the `step_started` payload. The atomic
     * create-claim inside each `step_started` is the exactly-one-owner gate that
     * the standalone `step_created` provided before: the loser of the race gets
     * `EntityConflictError` → `skipped` and does not run the body.
     */
    lazyInlineSteps: Array<{
        correlationId: string;
        stepName: string;
        dehydratedInput: SerializedData;
    }>;
    /**
     * The soonest pending wait, if any: seconds until it elapses and the
     * correlationId of the wait that produced that timeout. The
     * correlationId seeds the idempotency key for the wait-continuation
     * queue message so that repeated suspension passes over the same
     * pending wait collapse into a single delayed continuation.
     */
    waitTimeout?: {
        seconds: number;
        correlationId: string;
    };
    /** Whether a hook conflict was detected (should re-invoke immediately) */
    hasHookConflict: boolean;
    /** Whether a `hook.getConflict()` awaiter needs the workflow to continue immediately */
    hasAwaitedHookCreation: boolean;
    /** Whether native workflow attribute events were written for replay. */
    hasAttributeEvents: boolean;
    /**
     * Whether this suspension created any hook (`hook_created`) events. Unlike
     * `hasHookConflict` / `hasAwaitedHookCreation`, this is true even for a plain
     * fire-and-forget hook with no conflict and no awaiter. Turbo mode uses it to
     * detect "a hook was created this suspension" and stop forcing optimistic
     * inline start (a hook introduces later resume invocations that could race).
     */
    hasHookEvents: boolean;
    /**
     * Wall-clock ms spent committing this suspension's `hook_created` events
     * (0 when it created none). The caller accumulates this across iterations
     * and subtracts it from the TTFS latency measurement, so time spent
     * durably creating the user's hooks doesn't count as runtime overhead.
     */
    hookCreationMs: number;
}
/**
 * Handles a workflow suspension by processing all pending operations (hooks, steps, waits).
 * Creates events for all operations but does NOT queue step messages — returns the pending
 * steps so the caller can decide which to execute inline vs queue to background.
 *
 * Processing order:
 * 1. Hooks are processed first to prevent race conditions with webhook receivers
 * 2. Step events and wait events are created in parallel
 */
export declare function handleSuspension({ suspension, world, run, span, requestId, eventLog, runReadyBarrier, }: SuspensionHandlerParams): Promise<SuspensionHandlerResult>;
//# sourceMappingURL=suspension-handler.d.ts.map