/** * AgentBrowser — composition primitive for grouped, selectable agent lists. * * Authored for Lane A (Cleaning Up UX Mistakes) Sub-P3A under R1.0 * fallback amendment 2026-04-17T22:02:30Z. P3C polish round 2026-04-19 * adds group counts, collapsible groups, search, and a `compact` * density mode matching the Agent Definition + Evaluations sidebars. * * Lives in Grain (not Temper) because: * - Multiple consumers need it (Temper Fleet Overview + Agent Detail * + other agent-list views). * - Per Lane A spec D10, @goforgeit/grain is the canonical * source for cross-page composed surfaces. * - It composes existing Grain primitives (StatusDot, AgentCard) so * the pattern naturally lives alongside them. * * Portability contract: AgentBrowserAgent is the minimal shape Grain * owns. Consumers map their domain types (e.g., Temper's AgentSummary) * into it at the seam — Grain has no Temper-specific dependencies. */ import * as React from 'react'; /** * Minimal portable shape Grain owns. Consumers map their richer * domain types into this at the seam. */ export interface AgentBrowserAgent { /** Stable identity. Used for selection comparison + data-testid. */ id: string; /** Display name (rendered in monospace per AgentCard). */ name: string; /** * Type used for grouping when groupBy='type'. Recognized values map * to typed groups; anything else falls into the 'Other' group with * a warning indicator (per Lane A spec R1.2). */ type: string; /** Status mapped to StatusDot. Unrecognized values map to 'idle'. */ status: string; /** Optional metric line below the type tag (e.g., "0.85 eval"). */ metric?: React.ReactNode; /** * When true, render the row in a muted/disabled visual state with a * `title=` tooltip carrying `disabledReason`. The row remains * clickable (so the operator can navigate to the agent detail page * and see how to fix it) but is visually distinct. */ disabled?: boolean; /** Tooltip text when disabled is true. */ disabledReason?: string; } export type AgentBrowserGroupBy = 'type' | 'status' | 'none'; /** * Density mode controls per-row rendering: * - `comfortable` (default): full with type chip + metric line * - `compact`: status dot + name only (Agent Definition style; no chip, * no metric — type info lives in the group header) */ export type AgentBrowserDensity = 'comfortable' | 'compact'; export interface AgentBrowserProps { agents: readonly AgentBrowserAgent[]; /** Currently selected agent (highlighted). */ activeAgentId?: string; /** Click / Enter on an agent invokes this callback. */ onSelect: (agentId: string) => void; /** Default 'type'. 'none' renders a flat list. */ groupBy?: AgentBrowserGroupBy; /** * Default 'comfortable'. Switch to 'compact' for sidebar-style * minimal rows (status dot + name only, like Agent Definition). */ density?: AgentBrowserDensity; /** * When true (default in compact mode), each group header shows a * right-aligned count of agents in that group. Defaults to true * to match Agent Definition + Evaluations sidebars. */ showGroupCounts?: boolean; /** * When true (default), groups can be collapsed via the caret on the * group header. Defaults to true. */ collapsible?: boolean; /** * When true, render a search input above the list. Filters by * case-insensitive substring match on `agent.name`. */ searchable?: boolean; /** * Placeholder for the search input. Defaults to "Search agents…". */ searchPlaceholder?: string; /** * In comfortable density only: when true, hide the per-card type chip * because the group header already conveys type. Avoids redundant * "orchestrator" chip under an "ORCHESTRATORS" header. Default false * to preserve historical behavior. */ hideTypeChipUnderTypeGroups?: boolean; /** Rendered when agents.length === 0. Consumer's choice (e.g., ). */ emptyState?: React.ReactNode; /** Pass-through for AC3 DOM-structural-diff + scoped queries. */ 'data-testid'?: string; } export declare const AgentBrowser: React.ForwardRefExoticComponent>;