import type { ModelMessage, TextStreamPart, ToolSet } from "ai";
type ToolResponsePart = Extract<ModelMessage, {
    role: "tool";
}>["content"][number];
type InlineToolResultPart = Extract<ToolResponsePart, {
    type: "tool-result";
}>;
import type { AssistantStepFinishReason, RuntimeIdentity } from "#protocol/message.js";
import type { RunMode } from "#shared/run-mode.js";
import type { JsonObject } from "#shared/json.js";
import type { HarnessEmitFn, HarnessSession, SessionStateMap, StepInput } from "#harness/types.js";
/**
 * Tracks emission lifecycle state across harness step invocations.
 *
 * Persisted on `session.state` so the state survives when the durable
 * workflow runtime recreates the harness at each `"use step"` boundary.
 */
export interface HarnessEmissionState {
    readonly sessionStarted: boolean;
    readonly sequence: number;
    readonly stepIndex: number;
    readonly turnId: string;
}
/** Reads the emission state, returning defaults when absent. */
export declare function getHarnessEmissionState(state: SessionStateMap | undefined): HarnessEmissionState;
/**
 * Returns `true` when the harness is **between turns** — either no turn
 * has started yet (initial state) or the previous turn has emitted its
 * epilogue (or recoverable failure cascade) and reset.
 *
 * Returns `false` while a turn is in progress, including during
 * tool-loop continuations and runtime-action resumes within the same
 * turn. Callers that gate per-turn work (eg. lifecycle hook dispatch)
 * use this predicate to distinguish a fresh delivery from a
 * continuation of an in-flight turn.
 *
 * Implemented over the empty-`turnId` sentinel that `emitTurnEpilogue`
 * and `emitRecoverableFailedTurn` write — clients should never read
 * `state.turnId` directly to make this distinction.
 */
export declare function isHarnessBetweenTurns(session: HarnessSession): boolean;
/**
 * Writes the emission state onto a new copy of the session.
 */
export declare function setHarnessEmissionState(session: HarnessSession, state: HarnessEmissionState): HarnessSession;
/**
 * Emits `session.started` (once), `turn.started`, and `message.received` at the
 * beginning of a new turn. Returns updated emission state.
 */
export declare function emitTurnPreamble(emitFn: HarnessEmitFn, input: StepInput, state: HarnessEmissionState, runtimeIdentity?: RuntimeIdentity): Promise<HarnessEmissionState>;
/**
 * Emits `step.started` for one model call.
 */
export declare function emitStepStarted(emitFn: HarnessEmitFn, state: HarnessEmissionState, messages?: readonly import("ai").ModelMessage[]): Promise<void>;
interface FailedStepPayload {
    readonly code: string;
    readonly details?: JsonObject;
    readonly message: string;
}
/**
 * Emits the full terminal failure cascade: `step.failed` →
 * `turn.failed` → `session.failed`.
 *
 * Use this when the session cannot be salvaged (structural config
 * error, auth misconfig, non-recoverable provider response). The
 * `session.failed` tail tells adapters the session is dead and no
 * further follow-up is possible on the same continuation token.
 */
export declare function emitFailedStep(emitFn: HarnessEmitFn, state: HarnessEmissionState, input: FailedStepPayload & {
    readonly sessionId: string;
}): Promise<void>;
/**
 * Emits the recoverable failure cascade: `step.failed` →
 * `turn.failed` → `session.waiting`.
 */
export declare function emitRecoverableFailedTurn(emitFn: HarnessEmitFn, state: HarnessEmissionState, input: FailedStepPayload): Promise<HarnessEmissionState>;
/**
 * Returns updated emission state for the next step in the current turn.
 */
export declare function advanceStep(state: HarnessEmissionState): HarnessEmissionState;
/**
 * Emits `turn.completed` and either `session.waiting` or `session.completed`.
 * Returns updated emission state with an incremented sequence.
 */
export declare function emitTurnEpilogue(emitFn: HarnessEmitFn, state: HarnessEmissionState, mode: RunMode): Promise<HarnessEmissionState>;
/**
 * Maps an AI SDK finish reason string to the Eve-owned
 * {@link AssistantStepFinishReason} union. Unknown values become `"other"`.
 */
export declare function normalizeAssistantStepFinishReason(value: string | undefined): AssistantStepFinishReason;
/**
 * Result of consuming one step's `fullStream`.
 *
 * `inlineActionResultCallIds` lists tool-result call ids the stream
 * already emitted as `action.result` events. `emitStepActions` skips
 * these to avoid double-emission.
 *
 * `inlineToolResultParts` holds the same tool-results in
 * `ToolResultPart` shape. The AI SDK omits them from
 * `stepResult.response.messages` on the approval-resume path, so the
 * harness splices them into persisted history to keep the prior turn's
 * `tool_use` block balanced with a matching `tool_result` on replay.
 */
interface EmittedStreamContent {
    readonly inlineActionResultCallIds: ReadonlySet<string>;
    readonly inlineToolResultParts: readonly InlineToolResultPart[];
}
/**
 * Consumes the AI SDK `fullStream` and emits real-time text and reasoning
 * events.
 *
 * `tool-result` parts that have no preceding `tool-call` in this stream
 * are emitted inline as `action.result` events. This is the
 * approval-resume path: when a previously-parked tool call is approved,
 * the AI SDK enqueues the executed tool-result onto the same step's
 * stream before the next LLM call. Emitting `action.result` inline keeps
 * it ahead of the message events that depend on it.
 *
 * Tool-call, tool-approval-request, and non-resumed tool-result events
 * are still emitted by `emitStepActions` from the `onStepFinish`
 * callback so the existing single-step batch ordering is preserved.
 */
export declare function emitStreamContent(emitFn: HarnessEmitFn, state: HarnessEmissionState, fullStream: AsyncIterable<TextStreamPart<ToolSet>>): Promise<EmittedStreamContent>;
export {};
