/** * Core types for the capability-based config discovery system. * * This architecture inverts control: instead of callers knowing provider-specific * paths like `.gjc`, `.gemini`, or `.vscode`, they simply ask for `load("mcps")` * and get back a unified array of MCP servers. */ import type { Settings } from "../config/settings"; /** * Context passed to every provider loader. */ export interface LoadContext { /** Current working directory (project root) */ cwd: string; /** User home directory */ home: string; /** * GJC's user-scope config directory: the resolved agent directory * (`getAgentDir()`), which `--agent-dir`, `GJC_CODING_AGENT_DIR` and * `setAgentDir()` redirect away from `/.gjc/agent`. `loadCapability` * always sets it; ad-hoc contexts built for path scanning may omit it, and * native providers then fall back to the home-relative default * `//agent` (see `resolveUserAgentDir` in * `discovery/builtin.ts`). * * A native surface whose write path targets the agent directory resolves its * user scope from here, or discovery reads a different file than the writer * produced. This includes MCP registrations and user-installed skills. */ userAgentDir?: string; /** Git repository root (directory containing .git), or null if not in a repo */ repoRoot: string | null; /** Owning session settings for provider policy decisions. */ settings?: Settings; } /** * Result from a provider's load function. */ export interface LoadResult { items: T[]; /** Warnings encountered during loading (parse errors, etc.) */ warnings?: string[]; } /** * A provider that can load items for a capability. */ export interface Provider { /** Unique provider ID (e.g., "Anthropic model", "gjc", "mcp-json", "agents-md") */ id: string; /** Human-readable name for UI display (e.g., "Anthropic Code", "OpenAI code provider") */ displayName: string; /** Short description for settings UI (e.g., "Load config from .gjc/") */ description: string; /** * Priority (higher = checked first, wins on conflicts). * Suggested ranges: * 100+ : Primary providers (gjc, pi) * 50-99: Tool-specific providers (Anthropic model, OpenAI code backend, gemini) * 1-49 : Shared standards (mcp-json, agents-md) */ priority: number; /** * Load items for this capability. * Returns items in provider's preferred order (usually project before user). */ load(ctx: LoadContext): Promise>; } /** * Options for loading a capability. */ export interface LoadOptions { /** Only use these providers (by ID). Default: all registered */ providers?: string[]; /** Exclude these providers (by ID). Default: none */ excludeProviders?: string[]; /** Custom cwd. Default: getProjectDir() */ cwd?: string; /** * Agent directory backing `LoadContext.userAgentDir`. Default: getAgentDir(). * Set it when loading for a session whose agent directory differs from the * process-wide one (`createAgentSession({ agentDir })`). */ agentDir?: string; /** Include items even if they fail validation. Default: false */ includeInvalid?: boolean; /** Include items disabled via settings. Default: false */ includeDisabled?: boolean; /** * Include providers disabled via settings (for diagnostics). Default: false. * Items loaded from a disabled provider are not marked by the registry; callers * compare `_source.provider` against the disabled-provider set themselves. */ includeDisabledProviders?: boolean; /** Explicit disabled extension IDs to apply instead of settings. */ disabledExtensions?: string[]; /** Session settings whose provider policy applies to this load. */ settings?: Settings; } /** * Source metadata attached to every loaded item. */ export interface SourceMeta { /** Provider ID that loaded this item */ provider: string; /** Provider display name (for UI) */ providerName: string; /** Absolute path to the source file */ path: string; /** Whether this came from user-level, project-level, or native config */ level: "user" | "project" | "native"; } /** * Merged result from loading a capability across all providers. */ export interface CapabilityResult { /** Deduplicated items in priority order */ items: Array; /** All items including shadowed duplicates (for diagnostics) */ all: Array; /** Warnings from all providers */ warnings: string[]; /** Which providers contributed items (IDs) */ providers: string[]; } /** * Definition of a capability. */ export interface Capability { /** Capability ID (e.g., "mcps", "skills", "context-files") */ id: string; /** Human-readable name for UI display (e.g., "MCP Servers", "Skills") */ displayName: string; /** Short description for settings/status UI */ description: string; /** * Extract a unique key from an item for deduplication. * Items with the same key: first one wins (highest priority provider). * Return undefined to never deduplicate (all items kept). */ key(item: T): string | undefined; /** * Optional validation. Return error message if invalid, undefined if valid. */ validate?(item: T): string | undefined; /** * Optional disabledExtensions ID for this item. * When present, loadCapability() can hide items disabled via settings. */ toExtensionId?(item: T): string | undefined; /** Registered providers, sorted by priority (highest first) */ providers: Provider[]; } /** * Metadata about a capability (for introspection/UI). */ export interface CapabilityInfo { id: string; displayName: string; description: string; providers: Array<{ id: string; displayName: string; description: string; priority: number; enabled: boolean; }>; } /** * Metadata about a provider (for introspection/UI). */ export interface ProviderInfo { id: string; displayName: string; description: string; priority: number; /** Which capabilities this provider is registered for */ capabilities: string[]; /** Whether this provider is currently enabled */ enabled: boolean; }