Skip to main content

Provider Manager

The Provider Manager orchestrates multiple skill providers, providing a unified search interface that queries all registered providers, merges results, and handles graceful degradation when providers are unavailable.

createProviderManager

Create a provider manager that orchestrates multiple skill providers.
import { createProviderManager } from 'auto-skill/core/providers';

const manager = createProviderManager();

Return Type

{
  /** Register a provider. Earlier registrations have higher priority. */
  register(provider: SkillProvider): void;
  
  /** List of registered providers in priority order. */
  providers: SkillProvider[];
  
  /**
   * Search all available providers and merge results.
   *
   * Results are ordered by provider priority (first registered = highest).
   * Each provider contributes up to `limit` results, then the combined
   * list is deduplicated and truncated.
   *
   * @param query - Search keywords.
   * @param limit - Maximum total results to return (default 10).
   * @returns Merged and deduplicated list of SkillSearchResult objects.
   */
  searchAll(query: string, limit?: number): Promise<SkillSearchResult[]>;
  
  /**
   * Get skill details from the first provider that has it.
   *
   * @param skillId - The skill identifier.
   * @param sourceId - Optional provider sourceId to query specifically.
   * @returns SkillSearchResult if found, null otherwise.
   */
  getSkillDetails(
    skillId: string,
    sourceId?: string,
  ): Promise<SkillSearchResult | null>;
}

SkillProvider Interface

All skill providers must implement the SkillProvider interface:
interface SkillProvider {
  /** Human-readable name of this provider (e.g., 'Skills.sh'). */
  readonly name: string;

  /** Short identifier used in results (e.g., 'skillssh', 'local'). */
  readonly sourceId: string;

  /**
   * Search for skills matching a query.
   *
   * @param query - Search keywords.
   * @param limit - Maximum number of results (default 10).
   * @returns List of matching SkillSearchResult objects.
   */
  search(query: string, limit?: number): Promise<SkillSearchResult[]>;

  /**
   * Get detailed information about a specific skill.
   *
   * @param skillId - The skill identifier.
   * @returns SkillSearchResult with full details, or null if not found.
   */
  getSkillDetails(skillId: string): Promise<SkillSearchResult | null>;

  /**
   * Check if this provider is currently available.
   *
   * @returns True if the provider can serve requests, false otherwise.
   */
  isAvailable(): boolean;
}

SkillSearchResult Type

interface SkillSearchResult {
  id: string;
  name: string;
  description: string;
  source: string; // provider id, e.g. "skillssh" | "local" | "wellknown"
  confidence: number;
  author: string;
  tags: string[];
  installCount: number;
  sourceUrl: string;
  compatibleAgents: string[];
  metadata?: Record<string, unknown> | null;
}

Example Usage

import {
  createProviderManager,
  createLocalProvider,
  createWellKnownProvider,
} from 'auto-skill/core/providers';

const manager = createProviderManager();

// Register providers (order matters - first = highest priority)
manager.register(createLocalProvider());
manager.register(createWellKnownProvider(['example.com']));

// Search across all providers
const results = await manager.searchAll('typescript testing', 5);
console.log(`Found ${results.length} skills`);

// Get details for a specific skill
const skill = await manager.getSkillDetails('my-skill');
if (skill) {
  console.log(`${skill.name}: ${skill.description}`);
}

// Get details from a specific provider
const localSkill = await manager.getSkillDetails('my-skill', 'local');

How It Works

Priority Ordering

Providers registered first have higher priority. When search results from multiple providers match, higher-priority results appear first in the merged results.
manager.register(localProvider);      // Highest priority
manager.register(skillsshProvider);   // Medium priority
manager.register(wellknownProvider);  // Lowest priority

Result Deduplication

The manager automatically deduplicates results using a composite key of (source, id). If multiple providers return the same skill, only the first occurrence (by priority) is kept.

Graceful Degradation

  • Checks provider.isAvailable() before querying
  • Catches and logs errors from individual providers
  • Continues querying remaining providers if one fails
  • Returns best-effort results even if some providers are unavailable

Search Algorithm

  1. Iterate through providers in priority order
  2. Skip unavailable providers
  3. Query each provider for up to limit results
  4. Merge all results into a single list
  5. Deduplicate by (source, id) key
  6. Truncate to limit total results

Source Code Reference

Implementation: src/core/providers/manager.ts Base interface: src/core/providers/base.ts

Build docs developers (and LLMs) love