/** * Two-stage intent detection — the instructions and the decoders, zero runtime imports. * * Stage 1 (task 'detect_flow'): which primary flow, if any, the latest message starts. * Stage 2 (task 'extract_parameters'): the values the user gave for the SELECTED flow's parameters. * * For each stage jsfe builds ONE instruction set per executor — `llm` (a text model) and `systemOne` * (TypeSafe System One) — from the same rules and the same flow fields, and passes both to aiCallback as * its 4th argument. The host is the executor: it runs either, or both as a hedge (the first complete * answer wins and the other is cancelled), and returns the CANONICAL reply as a JSON string: * stage 1: { "flowName": "" | "None" } * stage 2: { "parameters": { "": value, … } } * The decoders below turn either executor's raw answer into that reply, so the host never interprets one. * * What each stage reads, and nothing else: * stage 1: each primary flow's `description` (what should trigger it); * stage 2: the selected flow's `parameterInstructions` (optional: rules that span its parameters) and its * parameters — name, type, enum and `description` (that parameter's rule). Parameters marked * `internal: true` (or whose description begins "Internal") are the flow's own, never asked. * System One answers only closed values (enum, boolean): its stage-2 instructions cover those parameters, * so a flow with any free-text parameter is answered completely only by the LLM. */ import type { FlowParameterDefinition } from '../index.js'; /** A noul at or above this is a yes. */ export declare const STAGE_YES_THRESHOLD = 0.5; /** Stage 1, System One: two top flows that together reach this pick the higher one (prod 10-17). */ export declare const STAGE_PAIR_SUM = 0.7; export interface StageTurn { role: 'user' | 'assistant'; content: string; } export interface StageFlow { id: string; name: string; description: string; } export interface StageParameter { name: string; type?: string; enum?: string[]; description?: string; internal?: boolean; jsonSchema?: Record; } export interface StageLlm { system: string; user: string; schema: Record; } export interface StageSystemOne { state: Record; questions: Record; index: I[]; } export interface FlowQuestionRef { id: string; flow: number; } export type ParameterQuestionRef = { id: string; kind: 'enum'; param: string; value: string; } | { id: string; kind: 'boolean'; param: string; }; export interface FlowStageRequest { task: 'detect_flow'; stage: 1; input: string; conversation: StageTurn[]; flows: StageFlow[]; llm: StageLlm; systemOne: StageSystemOne; } export interface ParameterStageRequest { task: 'extract_parameters'; stage: 2; input: string; conversation: StageTurn[]; flow: { id: string; name: string; parameterInstructions?: string; parameters: StageParameter[]; }; llm: StageLlm; /** null when the flow declares no enum or boolean parameter */ systemOne: StageSystemOne | null; /** parameters only a text model can answer (free text) */ freeText: string[]; } export type IntentStageRequest = FlowStageRequest | ParameterStageRequest; /** System One's answers, keyed by question id. */ export type StageSystemOneAnswers = Record | undefined; /** The flow's own parameters, never asked of the user. */ export declare const isInternalParameter: (p: StageParameter | FlowParameterDefinition) => boolean; /** Stage 1's instructions for both executors. `flows` are the primaries offered. */ export declare function buildFlowStage(input: string, conversation: StageTurn[], flows: StageFlow[]): FlowStageRequest; /** A text model's stage-1 answer as the canonical reply; throws when it names no offered flow. */ export declare function decodeFlowLlm(text: string, stage: FlowStageRequest): { flowName: string; }; /** * System One's stage-1 answers as the canonical reply, with the top three scores (for logs and a host's hedge * policy) and `pair` when two close candidates picked the higher. Throws if any question is unanswered. */ export declare function decodeFlowSystemOne(answers: StageSystemOneAnswers, stage: FlowStageRequest, { threshold, pairSum }?: { threshold?: number | undefined; pairSum?: number | undefined; }): { flowName: string; scores: { name: string; p: number; }[]; pair: boolean; }; /** * A System One "None" that is a near miss: the chance that at least one of its two top flows applies, * 1 − (1 − p1)(1 − p2), clears the threshold — a flow is wanted and the doubt is which. A host hedge waits * for the other executor on it rather than accepting "None". */ export declare function isNearMiss(scores: { p: number; }[], threshold?: number): boolean; /** Does `parameters` hold anything stage 2 asks (a parameter that is not internal)? */ export declare function hasStageParameters(parameters: (StageParameter | FlowParameterDefinition)[] | undefined): boolean; /** Stage 2's instructions for the selected flow, for both executors. */ export declare function buildParameterStage(input: string, conversation: StageTurn[], flow: { id: string; name: string; parameterInstructions?: string; parameters?: (StageParameter | FlowParameterDefinition)[]; }): ParameterStageRequest; /** A text model's stage-2 answer as the canonical reply: declared parameters with a value only. Throws on non-JSON. */ export declare function decodeParametersLlm(text: string, stage: ParameterStageRequest): { parameters: Record; }; /** * System One's stage-2 answers as the canonical reply: an enum takes its argmax value if it clears the cut, a * boolean is true if it clears it; otherwise the parameter is omitted (the flow asks), never set false. */ export declare function decodeParametersSystemOne(answers: StageSystemOneAnswers, stage: ParameterStageRequest, { threshold }?: { threshold?: number | undefined; }): { parameters: Record; }; /** Is this jsfe's stage request (a host's aiCallback receives it as the 4th argument)? */ export declare function isIntentStageRequest(request: unknown): request is IntentStageRequest; //# sourceMappingURL=intent-stages.d.ts.map