import { type Result } from "smoltalk"; import type { DecideConfig, DecideResult, DecisionQuestion, DecisionState } from "../llmClient.js"; /** The cap used for a model the registry does not know. */ export declare const DEFAULT_QUESTION_CAP = 64; export type DecisionRequest = { state: DecisionState; questions: Record; config: DecideConfig; /** The most questions one request to this model may carry. */ questionCap: number; signal: AbortSignal; }; export type DecisionSender = (state: DecisionState, questions: Record, config: DecideConfig, signal: AbortSignal) => Promise>; export type BatchGroupReport = { model: string; armKeys: string[]; callCount: number; questionCount: number; }; /** Why a round was sent: the block went idle, or a group reached the cap. */ export type BatchReason = "idle" | "cap"; export type DecisionBatchReport = { reason: BatchReason; groups: BatchGroupReport[]; }; export type CollectorHooks = { /** Runs one round. `work` sends every group and resolves when all have * answered; the hook wraps it, so a span opened before `work` and closed * after it encloses the whole round. */ runRound: (report: DecisionBatchReport, work: () => Promise) => Promise; /** A group reached the model's cap and was sent early. */ capReached: (model: string, cap: number) => void; }; /** What an arm's frame carries: the block's collector and the arm's key. */ export type DecisionScope = { collector: DecisionCollector; armKey: string; }; /** The name a call's question travels under in a merged request. */ export declare function questionKey(callId: number, name: string): string; /** The call id a merged question name carries, or undefined for a plain name. */ export declare function questionCallId(name: string): number | undefined; /** A merged question name without its call prefix. */ export declare function unprefixedQuestionName(name: string): string; /** Split `total` in proportion to `weights`, integer parts, remainder to the first. */ export declare function splitCounts(total: number, weights: number[]): number[]; export declare class DecisionCollector { private readonly send; private readonly hooks; private settledArms; private armKeys; private pending; private inflight; private nextId; constructor(armKeys: string[], send: DecisionSender, hooks: CollectorHooks); armSettled(armKey: string): void; submit(armKey: string, request: DecisionRequest): Promise>; /** An arm's status follows its calls, so no delivery can leave an arm * marked running while a second call of its still waits. */ private statusOf; private groups; private groupOf; private fireIfIdle; private fire; /** Send one group's merged request and deliver each call its share. * Every exit, including a throw anywhere in here, resolves or rejects * every call in the group, so no arm is ever left waiting. */ private sendGroup; }