import type { AttributionUnit, Embedder, UnitScore } from './types.js'; export interface ExplainChoiceArgs { /** * The chosen tool being explained. `text` is what gets embedded — pass * name + description (the name matters: a data snippet that NAMES the * thing the tool acts on, e.g. "id: d42", is its strongest citation). */ readonly tool: { readonly name: string; readonly text: string; }; /** * The context units, tagged by channel — e.g. `'system'` rules, * the `'task'`, `'data'` snippets from `snippetUnits`. Channels are * free-form strings; the verdict reports whatever labels it is given. */ readonly units: readonly AttributionUnit[]; /** Injected embedder. Wrap in an `EmbeddingCache` so rule texts embed once. */ readonly embedder: Embedder; /** Abort signal threaded to the embedder (network backends). */ readonly signal?: AbortSignal; } /** One channel's verdict: how much of the pick's positive similarity * mass it owns, and the best unit inside it to quote. */ export interface ChannelVerdict { readonly channel: string; /** * 0..1 share of POSITIVE similarity mass (negatives are clamped out, * same as `attributeChoice.byChannel`). Shares across all channels sum * to ~1 — or are all 0 when no unit had positive similarity. */ readonly share: number; /** The best-scoring unit IN this channel, text included for quoting. * Omitted only when the channel has no units. */ readonly top?: UnitScore & { readonly text: string; }; } /** The full explanation for one tool pick — `attributeChoice` reshaped * for display: text carried through, channels ranked. */ export interface ChoiceExplanation { /** The chosen tool being explained. */ readonly tool: string; /** * One verdict per channel present in the units, sorted by share * descending (ties keep first-appearance order). Zero-share channels * are listed too — absence of pull is part of the verdict. */ readonly channels: readonly ChannelVerdict[]; /** The overall best unit — the citation ("picked because …"). */ readonly top: UnitScore & { readonly text: string; }; /** Every unit ranked descending (ties keep input order), text included. */ readonly units: readonly (UnitScore & { readonly text: string; })[]; } /** * Run `attributeChoice` and reshape the result for a UI: join each unit's * text back by id, pick the best unit per channel, and rank the channels * by their share of positive similarity mass. * * Fail-loud validation is inherited from `attributeChoice`: empty units * or duplicate unit ids throw — caller wiring bugs, not runtime conditions. */ export declare function explainChoice(args: ExplainChoiceArgs): Promise;