/** * constrainedEnumPick — ONE model call that can only answer from a fixed * list (9.19.0). The machinery extracted from `llmClassifier` so the tier-3 * decider (RouteTurn's out-of-band menu resolver) and the classifier share * one enum discipline instead of two drifting copies: * * • On a provider that declares `carriesForcedToolChoice`, the pick rides * a forced synthetic tool whose single argument is `enum: allowed` — * the same mechanism the `'tool-forced'` output strategy uses. The * provider constrains generation; an answer outside the enum cannot be * emitted at all. * • On any other provider it is a strict single-line parse validated * against the enum, ONE structured re-ask, then the caller's fallback. * * An off-enum answer is a PARSE FAILURE, never a pick — this function can * never return an id it was not given (the `allowed` list plus `fallback`). * Callers put their own "none" sentinel INTO `allowed` (and as `fallback`) * so the model can decline explicitly; the sentinel is a first-class enum * member on the wire, exactly as `llmClassifier` has always sent it. */ import type { LLMProvider } from '../../adapters/types.js'; /** The synthetic pick tool, named by the caller (the wire shows this name). */ export interface EnumPickTool { readonly name: string; readonly description: string; /** The single argument's name (`'intent'` for the classifier, `'skill'` * for the decider) — a reader of the raw request sees the domain word. */ readonly argName: string; readonly argDescription: string; } export interface ConstrainedEnumPickRequest { readonly provider: LLMProvider; /** Model id for the call. Left unset, the request carries an empty model * id, which only the mock tolerates — name it for any real provider. */ readonly model?: string; /** The catalog/context prompt — WITHOUT the parse instruction; the parse * path appends its own, so both paths read one catalog. */ readonly systemPrompt: string; readonly messages: ReadonlyArray<{ readonly role: 'user' | 'assistant'; readonly content: string; }>; /** The complete enum, the caller's decline-sentinel included. */ readonly allowed: readonly string[]; /** Returned on parse failure / off-enum after the one re-ask (callers pass * their decline-sentinel, conventionally `'none'`). */ readonly fallback: string; readonly pickTool: EnumPickTool; readonly signal?: AbortSignal; } /** Run the pick. Resolves to a member of `allowed`, else `fallback`. */ export declare function constrainedEnumPick(req: ConstrainedEnumPickRequest): Promise;