import type { TurnControl } from '../../../types/channel.js'; import type { RunContext } from '../../../types/run-context.js'; import { type TokenSource, type GateOutcome } from './speakGated.js'; import type { StreamMode } from './mode.js'; /** * Streaming dispatch gate. Its only job is to control EMISSION per dispatch mode * and surface the model's own control tool — it does NOT consult the host guard. * The guard has a single owner (`hostLoop`): when this returns empty text and no * control, `hostLoop` runs the guard exactly once. Keeping the guard out of here * avoids double-evaluation and keeps guard telemetry attributable. * * - relaxed: stream live; if the model's own control tool fires, cancel any * streamed text and return that control. * - strict: emit NOTHING until the model's intent is known — buffer until the * first substantive token (answering → flush + stream the rest live) or source * end (no answer → return empty; `hostLoop` then guards with no leak). */ export declare function speakWithHostControl(args: { ctx: RunContext; mode: StreamMode; turnId: string; source: TokenSource; runGate: (fullOrSentence: string, final: boolean) => Promise; dispatchMode: 'strict' | 'relaxed'; getToolControl: () => TurnControl | undefined; }): Promise<{ text: string; control?: TurnControl; confidence?: number; }>;