import type { Model, ModelRef, ModelRoles, ThinkingLevel } from "../core/types.js";
/** The deployment role map behind the runner (`Runner.agentCatalog.roles`) — same posture as `runnerModelCatalog` (subagent.ts):
 *  host code, a throwing/absent stand-in reads as "no role map", never as a failed delegation. */
export declare function runnerRoleMap(runner: unknown): ModelRoles | undefined;
/**
 * Did the deployment STATE a model for its subagents? True iff `roles.subagent` names a model source of its
 * own: a string ref other than the literal `"default"`, a `Model` object, or a `{ model | select }` config
 * whose `model` is not that literal. The word `"default"` is how a deployment spells "no subagent tier of my
 * own — same as the main model" (a catalog key of that name is the boot default), so it reads as NOT stated;
 * a role entry carrying only a `thinking` / `systemPrompt` preset states no model either.
 */
export declare function deploymentStatesSubagentModel(roles: ModelRoles | undefined): boolean;
/**
 * Did the deployment STATE a thinking level for its subagents — and which? The `thinking` member of an
 * object-form `roles.subagent` entry; a string ref, a `Model` object or an entry without the member states
 * none (`undefined`). The thinking axis's twin of {@link deploymentStatesSubagentModel}: the SAME seat is
 * read (`roles.subagent` only — never the fallback chain, whose thinking the parent's own effective level
 * already reflects when the parent ran on it).
 */
export declare function deploymentSubagentThinking(roles: ModelRoles | undefined): ThinkingLevel | undefined;
/**
 * Did the deployment STATE a system prompt for its subagents — and which? The `systemPrompt` member of an
 * object-form `roles.subagent` entry; a string ref, a `Model` object or an entry without the member states
 * none. The third axis, read off the SAME seat as {@link deploymentSubagentThinking}. It has no parent rung:
 * a child never inherits its PARENT's system prompt, only the deployment's statement for subagents. Which
 * station needs to read it: one whose default persona is written onto the spec itself (the workflow lane
 * frames an empty `systemPrompt` with the workflow-subagent persona, so the preset must be written first, as
 * a custom persona to that frame); the delegation station's default rides the trusted internals channel
 * below the role chain, so prepare reads the preset there without this helper.
 */
export declare function deploymentSubagentSystemPrompt(roles: ModelRoles | undefined): string | undefined;
/**
 * The child run's THINKING seat — {@link childModelSeat}'s sister, the same rung order on the other axis
 * (#651): an EXPLICIT level for this spawn wins (the agent definition's `thinking`; a fork's explicit is the
 * caller's own level, as its model is the caller's); else the deployment's STATED subagent level
 * ({@link deploymentSubagentThinking}); else the PARENT run's effective level (the harness's current level —
 * a mid-run degrade/boost carries into new children); else nothing (the role chain decides, as before).
 *
 * The stated level is WRITTEN onto the spec rather than left to the role chain, unlike the model axis,
 * because the two axes resolve differently inside `resolveTaskModel`: the role chain reads `thinking` off
 * the role that SUPPLIED THE MODEL (the `subagent` entry when it states one, else the fallback role that
 * did), so a `roles.subagent` entry stating a level but no model would have its level skipped in favour of
 * the fallback role's. Writing the literal is the same value the seat rule resolves, on every seat shape;
 * the seat's role identity (`modelRole: "subagent"`, on every engine-spawned seat) still keys the
 * `systemPrompt` preset, which has no such fallback drift.
 *
 * Why the parent's level used to be wrong here: the parent's RESOLVED run level (`"off"` when the parent
 * declared nothing — the harness contract) was inherited as if it were an explicit declaration, and
 * `spec.thinking` outranks the role preset, so a deployment that stated `roles.subagent.thinking` watched
 * every child run with thinking off. The parent's level is the LAST rung now, where the model axis has it.
 */
export declare function childThinkingSeat(explicit: ThinkingLevel | undefined, deploymentStated: ThinkingLevel | undefined, parent: ThinkingLevel | undefined): {
    thinking?: ThinkingLevel;
};
/**
 * The deployment's stated subagent tier as a resolved `Model` — for a spawn lane that needs the concrete
 * model up front (the workflow lane keys call identity and the display label on it), so both lanes read the
 * same rule: `undefined` when the deployment stated nothing (the caller then falls to the parent's model),
 * else the role chain's answer for `subagent`. A stated ref the catalog cannot resolve throws here, loudly,
 * exactly where a child's own prepare would have thrown.
 */
export declare function deploymentSubagentTierModel(deps: {
    models?: Record<string, Model>;
    roles?: ModelRoles;
} | undefined): InheritedModelPick | undefined;
/**
 * The child run's model seat — ONE rule for every engine-spawned run (the delegation child at
 * `buildChildSpec`, the observer sidecar, the workflow launch site): an EXPLICIT model for this spawn wins
 * (per-call `model`, the agent definition's `model`, the tool-level `model`); else a deployment that STATED
 * a subagent tier gets it (no model on the seat — the role chain resolves the stated entry, `select` forms
 * included); else the child runs on the PARENT run's effective model — taken as the REF that chose it and
 * resolved against the catalog generation in force at THIS spawn ({@link inheritedParentModel}), so
 * per-model routing/credentials ride along and a hot-swapped catalog reaches the child; else — no parent
 * model readable, which only happens outside a Runner-enriched ctx — the bare role, whose chain ends at the
 * deployment default.
 *
 * THE ROLE IDENTITY IS CONSTANT: every seat carries `modelRole: "subagent"`, the explicit-model seat too.
 * `resolveTaskModel` keys the role's `systemPrompt` / `thinking` presets on `modelRole` in BOTH of its
 * branches (an explicit model reads `roles[modelRole]`'s presets; a role-resolved model reads them along the
 * chain), so a deployment's `roles.subagent` preset reaches a child whatever decided its model. An explicit
 * seat without the identity read the `default` role's presets instead — a child spawned with a per-call or
 * definition model silently ran under the deployment's MAIN persona while its sibling with no explicit model
 * ran under the subagent one, and the workflow station (which writes the stated persona onto the spec)
 * disagreed with the delegation station on the same input. The two arms below differ ONLY in whether a
 * model rides the seat; the identity never varies. A FORK is not a seat of this rule — see {@link forkModelSeat}.
 *
 * Why "default" was the wrong last resort: `FALLBACK.subagent = ["default"]` resolves to the deployment's
 * boot default, which is not the model the parent run was switched to — a run whose main turn was moved to
 * model B by the caller spawned children on boot model A (and a deployment whose boot default was removed
 * from the roster spawned children that failed at prepare). The parent's effective model is the honest
 * default; the deployment's stated tier keeps outranking it because that statement is operator intent.
 */
/** The seat: the role identity, with the model that rides it (explicit or inherited) or none (the stated tier resolves through the role chain). */
export type ChildModelSeat = {
    modelRole: "subagent";
    model?: ModelRef;
};
/**
 * The PARENT rung's value, resolved at THIS spawn tick. The parent leg travels as the REF that chose its
 * model (`ToolExecuteContext.modelRef`), not as the object it has been holding since its own prepare, so:
 *  · a catalog word resolves against the catalog generation in force NOW — a child spawned after a hot
 *    swap runs on the generation its own prepare would have seen, which is what the swap law already
 *    promises every string ref ("resolves against the new catalog at the next prepare");
 *  · a word the swap RETIRED throws here, loudly, under the same unknown-ref policy a caller-written
 *    retired word meets — never a silent fall back to the retired object, which is the shape that let a
 *    child run for its whole life on a generation the deployment had withdrawn;
 *  · a `Model` OBJECT is its own ref and passes through pinned, the swap law's other existing arm.
 * Resolved lazily by {@link childModelSeat}, on the arm actually taken: a spawn that names its own model,
 * or a deployment that stated a subagent tier, never consults the parent rung and so never inherits its
 * refusal. A word with NO catalog to ask refuses under that same policy rather than travelling on as a
 * word: a seat that cannot name the model it seats is not a seat, and the caller learns it here.
 *
 * @contract child_seat.parent_model_travels_as_its_catalog_word — an engine-spawned run that inherits its
 * parent's model inherits the parent's CURRENT model BY THE REF THAT CHOSE IT, resolved once against the
 * catalog generation in force at the child's own spawn: a catalog word therefore lands the child on the
 * generation its own prepare would have seen (and refuses loudly, under the shared unknown-ref policy, when
 * the word has been retired), while a parent whose model is a `Model` object travels as that object and is
 * never re-resolved. The resolution happens at the spawn, not in the child's prepare, so the model the spawn
 * frames name and the model the child runs on stay one value.
 */
export declare function inheritedParentModel(parent: ModelRef | undefined, catalog: Record<string, Model> | undefined): Model | undefined;
/**
 * What a spawn seats, and WHICH catalog word chose it.
 *
 * The two travel on different channels ON PURPOSE. `seat` is spread onto the child SPEC and carries the
 * RESOLVED object, so the model the spawn frames name is the model the child runs — nothing re-resolves
 * between the judgement and the child's prepare. `modelRef` is the word that object came from, and it rides
 * the TRUSTED internals channel (`RunInternals.inheritedModelRef`) so the child is not silently PINNED by
 * having been handed an object: its own children inherit the word in turn, and the deployment's per-model
 * window overlay — which is keyed by word — still reaches it. Absent `modelRef` = there is no word (an
 * object the caller pinned, a `select` criteria), and a leg with no word is never re-resolved and never
 * overlaid, which is exactly what pinning means.
 */
/** A resolved model together with the catalog WORD that chose it — the shape a lane hands its launch site
 *  when the two travel separately (the object onto the child spec, the word onto its trusted channel). */
export interface InheritedModelPick {
    readonly model: Model;
    readonly modelRef?: ModelRef;
}
export interface ChildModelSeatPick<S> {
    readonly seat: S;
    readonly modelRef?: ModelRef;
}
export declare function childModelSeat(explicit: ModelRef | undefined, deploymentStated: boolean, parent: ModelRef | undefined, catalog?: Record<string, Model>, 
/** The word the CALLER resolved `explicit` from, when the caller resolved one (a per-call model word a
 *  delegation gate judged into an object before the seat ever saw it). An explicit STRING needs none — it
 *  travels as itself and the child's own prepare resolves it, which already leaves the child its word. */
explicitRef?: ModelRef): ChildModelSeatPick<ChildModelSeat>;
/**
 * The FORK's model seat — the caller CONTINUED, not a subagent to the role chain. A fork always runs on the
 * caller's model (the caller's current `Model`, else the delegation tool's own `model`), and it carries NO
 * role identity: its system prompt is meant to be the PARENT's (the delegation station leaves the fork's
 * `systemPrompt` unset and threads no default persona, so prepare resolves the same role presets the
 * caller's own explicit-model run reads — the `default` role's — never the subagent persona a deployment
 * stated for its workers). No caller model readable (only outside a Runner-enriched ctx) ⇒ an empty seat: the
 * role chain's `default` start, exactly what a caller run with no `modelRole` of its own resolves.
 */
export declare function forkModelSeat(callerModel: ModelRef | undefined, inheritedRef?: ModelRef, catalog?: Record<string, Model>): ChildModelSeatPick<{
    model?: ModelRef;
}>;
