/** * Federated skill search — query local, canonical, and federation sources * in parallel then rank by `trustLevel × textMatch × usage`. * * Default behaviour is OPT-IN: callers MUST pass `includeFederated=true` * to fan out to federation peers (per `~/.cleo/federation.json`). Without * that flag the search only hits the local filesystem + the optional * `localMarketplaceSearch` callback (typically the canonical marketplace * client from caamp). * * Network failures on individual federation peers DO NOT fail the whole * query — the search degrades gracefully and surfaces a per-peer warning * in the returned `warnings` array. * * @task T9731 * @epic T9564 * @saga T9560 */ import { type FederationEntry } from './federation-store.js'; import type { SkillTrustLevel } from './skills-guard.js'; /** * One result from {@link federatedSearch}. * * `source` identifies origin tier: * - `'local'` — found in `~/.cleo/skills/` or `~/.agents/skills/` * - `'canonical'` — found via the supplied marketplace callback * - `'federation:'`— found via one of the federation peers * * `usage` is populated from `skill_usage` rollups when available — used by * the ranker but never required. */ export interface FederatedSearchResult { /** Skill name (basename / scoped). */ readonly name: string; /** Origin tier label. */ readonly source: string; /** Trust level resolved from the origin. */ readonly trustLevel: SkillTrustLevel; /** Raw text-match score before trust + usage weighting. */ readonly textMatchScore: number; /** Final ranked score (deterministic for given inputs). */ readonly score: number; /** Optional description (rendered in CLI). */ readonly description?: string; /** Optional usage count (number of `skill_usage` rows). */ readonly usage?: number; } /** * Options accepted by {@link federatedSearch}. * * `localMarketplaceSearch` is a callback to keep the canonical marketplace * client (which lives in caamp) out of the core dep graph. Pass `undefined` * to skip canonical lookup entirely. */ export interface FederatedSearchOptions { /** Search query — case-insensitive substring match. */ readonly query: string; /** OPT-IN flag: when `true`, fan out to federation peers. */ readonly includeFederated?: boolean; /** Maximum results per source (NOT total). */ readonly perSourceLimit?: number; /** Optional override for the federation index path (test hook). */ readonly federationIndexPath?: string; /** Optional local-skills root override (defaults to `~/.cleo/skills`). */ readonly localSkillsRoot?: string; /** Optional callback to query the canonical marketplace. */ readonly localMarketplaceSearch?: (q: string) => Promise>; /** Optional callback to query a federation peer URL. */ readonly fetchPeer?: (peer: FederationEntry, q: string) => Promise>; } /** * Composite shape returned by {@link federatedSearch}. */ export interface FederatedSearchResponse { /** Ranked results across every searched source. */ readonly results: readonly FederatedSearchResult[]; /** Per-source warnings (network failures, parse errors). */ readonly warnings: readonly string[]; } /** * Compute the final score for a candidate. * * Formula: `trustWeight × textMatchScore × (1 + log(1 + usage))`. * * The log term means a skill used 100 times scores ~3× higher than the * unused one — but a never-used skill still scores `1× trust × match` * rather than zero, so brand-new federation skills remain discoverable. * * @param trustLevel - Resolved trust tier. * @param textMatchScore - Raw text match (1.0 = exact name hit, 0.5 = description). * @param usage - Optional usage count (defaults to 0). * @returns Numeric score — higher is better. * * @task T9731 */ export declare function computeScore(trustLevel: SkillTrustLevel, textMatchScore: number, usage?: number): number; /** * Run a federated skill search across every enabled source tier. * * Search order (each tier is a NO-OP when its source is empty / disabled): * 1. Local `~/.cleo/skills/` (always — `builtin` trust) * 2. Legacy `~/.agents/skills/` (always — `builtin` trust) * 3. Canonical marketplace via `localMarketplaceSearch` (always when supplied) * 4. Federation peers from `federation.json` (ONLY when `includeFederated=true`) * * Usage data merges via {@link getTopUsed} when the skills DB is available, * but a missing DB is non-fatal (search still works, just without * usage-weighted ranking). * * @param opts - Search options — see {@link FederatedSearchOptions}. * @returns Ranked results + warnings. Results sorted by `score DESC`. * * @task T9731 */ export declare function federatedSearch(opts: FederatedSearchOptions): Promise; //# sourceMappingURL=federated-search.d.ts.map