/**
 * The multi-step tool loop that the ai package's `generateText` used to supply.
 *
 * It deliberately loops over a provider's own `doGenerate` rather than over any
 * streaming machinery. That is the whole lesson of the reverted first attempt:
 * `doGenerate` is where the JSON-versus-SSE wire choice lives, along with the
 * 400 retry, the context-overflow refit and the provider's own structured-output
 * handling. Looping around the streaming path instead silently changed
 * generate() to send `stream: true` and broke ten providers against a
 * non-streaming body.
 *
 * Every provider whose delegating model exposes a v3-shaped `doGenerate` can
 * share this: the v3 result shape (`content` parts, `finishReason`, `usage`) is
 * the same across Anthropic, the OpenAI-compatible family and SageMaker.
 */
import type { NativeGenerateLoopArgs, NativeGenerateLoopResult, StepResult, StepToolChoiceInput, Tool, ToolExecutionSummaryInternal } from "../types/index.js";
/**
 * Decide the tool choice for ONE step of a multi-step loop.
 *
 * A forced choice held on every step compels a tool call on every step, so
 * the loop could only end when `maxSteps` ran out — which is exactly what
 * happened before this existed. The rule: a forced choice applies while
 * `step < toolChoiceSteps` (default 1), after which the model chooses
 * (`"auto"`). `"auto"` and `"none"` pass through unchanged on every step.
 *
 * A `prepareStep` hook, when supplied, runs first and its `toolChoice` wins
 * for the step — including a forced choice past `toolChoiceSteps`, which is
 * how a caller forces a tool on step 3 only. A hook that returns no
 * `toolChoice` defers to the rule. Nothing else on the hook's result is read.
 *
 * A forced single-tool choice, from the hook or from the turn, that names a
 * tool outside `declaredTools` is warned about and not sent. A hook's choice
 * is then treated as "no override" and the rule decides; the turn's own
 * choice becomes `"auto"`. Without `declaredTools` nothing is checked.
 *
 * A hook that THROWS is logged and treated as "no override": the steps
 * already billed are kept and the rule decides. An abort of the turn while
 * the hook is pending is not a hook failure and is re-thrown. The two are
 * told apart by the LOOP's signal, never by the error's name: a hook that
 * rejects with its own `AbortError` (its policy service timed out) has
 * failed, and must not end a turn the caller never cancelled.
 */
export declare function resolveStepToolChoice(input: StepToolChoiceInput): Promise<unknown>;
/**
 * Translate a NeuroLink-shape tool choice (`"auto"` / `"none"` /
 * `"required"` / `{ type: "tool", toolName }`) into the v3 call-option
 * OBJECT every `doGenerate` converter switches on. The bare strings were
 * being handed straight to `doGenerate`; Anthropic's converter normalises
 * them, but the OpenAI-compatible one reads `.type` off the value and
 * silently dropped every string form. An already-object value passes
 * through untouched.
 */
export declare const toV3ToolChoice: (choice: unknown) => Record<string, unknown> | undefined;
/**
 * The record of one completed step that `prepareStep` receives in `steps`.
 * Built the same way by every native loop so a hook sees one shape.
 */
export declare const toPrepareStepRecord: (step: {
    stepNumber: number;
    content: Array<Record<string, unknown>>;
    text: string;
    toolCalls: Array<{
        toolName: string;
        toolCallId: string;
        input: unknown;
    }>;
    toolResults: Array<{
        toolName: string;
        toolCallId: string;
        output: unknown;
    }>;
    finishReason: string;
    inputTokens: number;
    outputTokens: number;
    /** Prompt-cache tokens for the step, when the provider reports them. */
    cacheReadTokens?: number;
    cacheWriteTokens?: number;
}) => StepResult<Record<string, Tool>>;
/**
 * Narrow a model handle to the delegating shape this loop drives.
 * `LanguageModel` is a union that includes a bare string id, and a double
 * assertion through unknown is banned by Critical Rule 14.
 */
export declare const hasNativeDoGenerate: (value: unknown) => value is {
    doGenerate: (options: Record<string, unknown>) => Promise<Record<string, unknown>>;
};
/**
 * Spell a JSON Schema into the conversation's system turn.
 *
 * The structured-output fallback for vendors that reject or ignore
 * `response_format`. Merged into an existing trailing system message rather
 * than appended as a second one: several self-hosted OpenAI-compatible stacks
 * honour only the first system message, so a second would be dropped and the
 * fallback would silently do nothing.
 */
export declare const appendJsonSchemaInstruction: (conversation: Array<Record<string, unknown>>, schema: unknown) => Array<Record<string, unknown>>;
export declare function runNativeGenerateLoop(args: NativeGenerateLoopArgs, toolExecutionSummaries: ToolExecutionSummaryInternal[]): Promise<NativeGenerateLoopResult>;
