import { type ToolSelectionHint } from "./promotion.ts"; import type { ToolPerformanceKey, ToolPerformanceStore, ToolSelectionIntentClass, ToolSelectionObservation } from "./tool-performance-store.ts"; export interface ToolSelectionTool { name: string; description?: string; parameters?: unknown; profileAllowed?: boolean; capabilityAllowed?: boolean; pathValidated?: boolean; riskCost?: number; contextCost?: number; } export interface ToolSelectionControllerDeps { store: ToolPerformanceStore; getModelRef: () => string; getActiveTools: () => readonly ToolSelectionTool[]; isCandidateAllowed?: (toolName: string) => boolean; /** * Env-var source for the kill switches, injected for hermetic testing; defaults to * `process.env`. `PI_TOOL_SELECTION_OBSERVE=0` disables recording (the observe/stats layer, * default ON); `PI_TOOL_SELECTION_HINTS=0` disables surfacing the evidence-gated prompt hint * (default ON, but the hint itself only ever activates once evidence thresholds are met). */ env?: Record; } export interface ToolSelectionPendingObservation { id: string; key: ToolPerformanceKey; firstTool: boolean; startedAt: number; inputTokenEstimate?: number; selection: Omit; /** Was a promotion hint already active for this (model,intent) bucket before this call? */ hintActiveAtCallTime: boolean; } /** Report row for the observe/agreement/promotion loop — see {@link ToolSelectionController.getReport}. */ export interface ToolSelectionReportEntry { modelRef: string; intentClass: ToolSelectionIntentClass; sampleCount: number; agreementRate?: number; hintTool?: string; hintSampleCount: number; hintAgreementRate?: number; } declare function classifyToolIntent(tool: ToolSelectionTool): ToolSelectionIntentClass; declare function estimateTokens(value: unknown): number | undefined; declare function estimateContentTokens(content: readonly unknown[]): number | undefined; export declare class ToolSelectionController { private readonly deps; private readonly pending; private readonly timings; private firstToolInTurn; /** Kill switch: observe/stats recording, default ON. `PI_TOOL_SELECTION_OBSERVE=0` disables it. */ private readonly observeEnabled; constructor(deps: ToolSelectionControllerDeps); startTurn(): void; begin(toolCallId: string, toolName: string, args: unknown): ToolSelectionPendingObservation; complete(toolCallId: string, succeeded: boolean, content?: readonly unknown[]): void; recordValidation(toolName: string, outcome: "repaired" | "bounced"): void; /** * The currently active evidence-gated hints for the session's current model — one per * (intentClass) at most, only where accumulated evidence clears the promotion gate. Consumed by * `system-prompt-builder.ts` to render a compact, cache-stable prompt block. Empty when the * hint kill switch (`PI_TOOL_SELECTION_HINTS=0`) is set, observing is disabled, or no bucket has * cleared the gate yet. */ getActiveHints(modelRef?: string): ToolSelectionHint[]; formatTimingReport(): string; /** * Report surface for the observe/agreement/promotion loop: per (model,intent), the durable * agreement rate (did the raw ranking's top pick match what was actually called), plus the * currently active hint (if any) and its own efficacy (agreement rate while it has been active). * A read-only diagnostic — never used to gate behavior. Render with * {@link formatToolSelectionReport}. */ getReport(modelRef?: string): ToolSelectionReportEntry[]; private selectionSnapshot; } /** Renders {@link ToolSelectionController.getReport} rows into the /toolhealth-style diagnostic text. */ export declare function formatToolSelectionReport(entries: readonly ToolSelectionReportEntry[]): string; export { classifyToolIntent, estimateContentTokens, estimateTokens }; //# sourceMappingURL=tool-selection-controller.d.ts.map