import { ToolCategory, ToolHandler } from "../../confluent/tools/base-tools.js"; import { ToolDisabledReason } from "../../confluent/tools/connection-predicates.js"; import { ToolName } from "../../confluent/tools/tool-name.js"; import { ServerRuntime } from "../../server-runtime.js"; /** * One bucket of disabled tools sharing a single bucket key. The key field * is discriminated by {@linkcode ToolGatingReport.groupBy}: * * - `groupBy: "reason"` ⇒ each bucket carries `reason: ToolDisabledReason` * (the default — "what config piece would unlock these tools?"). * - `groupBy: "category"` ⇒ each bucket carries `category: ToolCategory` * ("which area of functionality is offline?"). * * Use `"reason" in group` (or `"category" in group`) to narrow at the use site. * Tool order within `tools` follows the order handlers were iterated. */ export type DisabledToolGroup = { readonly reason: ToolDisabledReason; readonly tools: readonly ToolName[]; } | { readonly category: ToolCategory; readonly tools: readonly ToolName[]; }; /** Bucket-key projection for a {@linkcode DisabledToolGroup}, irrespective of axis. */ export declare function disabledToolGroupKey(group: DisabledToolGroup): string; /** * One configured connection's view of the gating report: the tools disabled * *on this connection*, bucketed by the report's chosen axis, plus the * connection's own enabled/disabled tallies. A tool enabled on this connection * never appears in `disabledGroups` here; a tool enabled on a sibling * connection but disabled on this one shows up in this section's buckets, so * the cross-connection asymmetry is readable by comparing sections. */ export interface ConnectionGatingSection { readonly connectionId: string; readonly disabledGroups: readonly DisabledToolGroup[]; /** Tools advertisable on this connection: `totalRegistered - disabledCount`. */ readonly enabledCount: number; /** Tools disabled on this connection: the sum of `disabledGroups[].tools.length`. */ readonly disabledCount: number; } /** * Output of {@linkcode buildToolGatingReport}; drives the * `explain-disabled-tools` diagnostic tool. * * The report is connection-shaped: one {@linkcode ConnectionGatingSection} per * configured connection, each carrying that connection's disabled-tool buckets. * A single-connection config yields exactly one section — there is one shape * regardless of connection count. * * `groupBy` records which axis the section buckets carry so consumers * (renderer, MCP-client UIs) can pick the right framing. * * `operatorBlocked` is the server-wide allow/block-list verdict, held apart * from the per-connection sections because the operator filter is the * outermost gate: it excludes a tool from every connection at once and owes * nothing to any connection's config. A blocked tool appears here and in no * section's buckets, and is subtracted from each section's `enabledCount`. * * The top-level `enabledCount` / `disabledCount` are whole-server rollups: a * tool counts as enabled if it survives the operator filter AND is * connection-independent or enabled on at least one connection; it counts as * disabled when the operator filter excludes it, or when it is * connection-dependent and dark on every connection (or there are no * connections at all). */ export interface ToolGatingReport { readonly groupBy: "reason" | "category"; /** Tools the operator's allow/block-list excluded server-wide, in handler iteration order. */ readonly operatorBlocked: readonly ToolName[]; /** One section per configured connection, lex-sorted by id; empty iff no connections are configured. */ readonly connections: readonly ConnectionGatingSection[]; readonly enabledCount: number; readonly disabledCount: number; } /** * One bucket of tools sharing the same `(connectionId, reason)` pair — the * unit of one grouped log line at server startup. `toolNames` preserves * input iteration order. Distinct from {@linkcode DisabledToolGroup}, which * is the operator-facing diagnostic-surface shape: this one carries the * `connectionId` axis the multi-connection log line needs. */ export interface StartupLogToolGroup { readonly connectionId: string; readonly reason: ToolDisabledReason; readonly toolNames: ToolName[]; } /** * Group fully-disabled tools by `(connectionId, reason)`. A tool is "fully * disabled" when every configured connection reports a non-enabled verdict; * tools enabled on at least one connection are omitted entirely (they are * already going to be advertised by the server, so they don't belong in a * disabled-tool log line). * * Returned groups are sorted lexicographically by `connectionId`. Stable * sort preserves the relative order of groups within the same connection. */ export declare function groupDisabledToolsByReason(handlers: Iterable, runtime: ServerRuntime): StartupLogToolGroup[]; /** * Assemble a connection-shaped {@linkcode ToolGatingReport} for the given * handler set against the configured connections. * * One pass over the handlers: * - a tool the operator's allow/block-list excludes (`!isToolAllowed`) is * recorded in `operatorBlocked` and counts as disabled, ahead of and * independent of its predicate verdict — the filter is the outermost gate, * so it never reaches a connection section; * - connection-independent tools count as enabled and appear in no section * (they are enabled on every connection); * - a connection-dependent tool on a zero-connection config counts as disabled * with no section to attribute it to; * - otherwise each connection that disables it gets the tool added to its * section bucket (keyed by reason, or by {@linkcode ToolHandler.category} * under `groupBy: "category"`), and the tool counts as enabled iff at least * one connection enables it. * * Sections are lex-sorted by `connectionId` and buckets lex by * {@linkcode disabledToolGroupKey}. Tools within a bucket — and within * `operatorBlocked` — follow handler iteration order. */ export declare function buildToolGatingReport(handlers: Iterable, runtime: ServerRuntime, groupBy?: "reason" | "category"): ToolGatingReport; //# sourceMappingURL=tool-availability.d.ts.map