/** endpoint name → mode name → raw endpoint config object. */ export type EndpointMap = Record>>; /** Parsed existing gateway.yaml split into reserved top-level fields and the endpoint/mode tree. */ export interface ParsedGateway { /** Reserved top-level keys preserved verbatim: port, mode, status_check, auth, host, endpoint_modes, endpoints. */ top: Record; endpoints: EndpointMap; } export interface MergeGatewayResult { endpoints: EndpointMap; top: Record; /** Existing (endpoint, mode) pairs NOT produced by this discovery — kept verbatim. */ preservedCustom: Array<{ endpoint: string; mode: string; }>; /** Subset of preservedCustom that looks like it should have been rediscovered (i.e. not * anthropic/plan|api) — surfaced as a warning so a failed `pi --list-models` is visible. */ droppedFromDiscovery: Array<{ endpoint: string; mode: string; }>; } export interface GatewayValidationIssue { profile: string; mode: string; provider?: string; reason: string; } export interface DiscoveredEndpoint { /** Mode key in gateway.yaml + cortex profile (e.g. "plan", "deepseek", "openai-codex") */ mode: string; /** Endpoint group name (e.g. "anthropic", "deepseek", "openai-codex") */ endpoint: string; base_url: string; auth_style: string; keys: string[]; passthrough: boolean; /** Model IDs known to be available for this endpoint */ models: string[]; /** Whether gateway.yaml should render an endpoint section for this entry. PI providers without a * known upstream URL are surfaced as profiles but skipped in gateway.yaml. */ gatewayManaged: boolean; } export interface PiDiscoveredModel { provider: string; model: string; } /** * Parse the table output of `pi --list-models` into structured entries. * Skips header row, blank lines, and the "No models available" fallback message. * * Example input: * provider model context max-out thinking images * anthropic claude-3-5-haiku-20241022 200K 8.2K no yes * deepseek deepseek-v4-pro 1M 384K yes no */ export declare function parsePiListModelsOutput(stdout: string): PiDiscoveredModel[]; /** * Scan Claude Code and PI configurations and return discovered endpoints. * * @param backends - Optional filter: when provided, only discover endpoints for the listed backends * (e.g. `['claude']`, `['pi']`, `['claude', 'pi']`). When omitted, all backends are discovered. * * - Claude Code plan mode: generated when 'claude' is in backends (or backends is omitted). * - Claude Code api mode: generated only if ANTHROPIC_API_KEY env var is set and 'claude' is included. * - PI providers: discovered via `pi --list-models` when 'pi' is in backends (or backends is omitted). * Each provider becomes one endpoint with `mode = endpoint = provider name`. `gatewayManaged` * is true only if the provider has a known upstream URL in PI_PROVIDER_UPSTREAM (otherwise profile * is generated but gateway.yaml entry is skipped). */ export declare function discoverEndpoints(backends?: string[]): DiscoveredEndpoint[]; /** * Generate gateway.yaml content from discovered endpoints. * Outputs a formatted YAML string with comments explaining each mode. * * Endpoints with gatewayManaged=false are skipped (their profile still exists in profiles.json, * but gateway.yaml has no entry for them — PI traffic to those providers is currently direct). */ export declare function generateGatewayYaml(endpoints: DiscoveredEndpoint[], defaultMode?: string): string; /** * Write gateway.yaml to the specified path or ~/.aistatus/gateway.yaml. * If file already exists and outputDir is not specified, backs it up as gateway.yaml.bak before overwriting. * When outputDir is provided, writes to /gateway.yaml without backup. * * @deprecated Use writeMergedGatewayYaml — full overwrite drops hand-maintained custom modes. */ export declare function writeGatewayYaml(yamlContent: string, outputDir?: string): string; /** * Parse an existing gateway.yaml into reserved top-level fields + the endpoint/mode tree. * Returns null if the file is absent or unparseable (caller degrades to full generation). */ export declare function readGatewayYaml(filePath: string): ParsedGateway | null; /** Build an endpoint/mode tree from freshly discovered endpoints (gatewayManaged only). */ export declare function discoveredToEndpointMap(endpoints: DiscoveredEndpoint[]): EndpointMap; /** * Merge freshly discovered endpoints over an existing gateway config. * * Add-only at the (endpoint, mode) PAIR level (mirrors mergeProfilesJson overwrite=false): a pair * absent from the existing file is added from discovery; any pair that already exists is preserved * verbatim — its base_url, auth_style and (critically) managed keys are never clobbered. This both * fixes the original bug (a missing mode gets added) and protects hand-customized routes, e.g. a * `deepseek` mode pointed at a private relay with a secret key, even though `pi --list-models` * reports the canonical upstream for that provider. A failed/empty discovery therefore can never * drop or alter previously-configured modes. To intentionally update an existing route's URL/keys, * edit gateway.yaml directly. */ export declare function mergeGatewayConfig(discovered: DiscoveredEndpoint[], existing: ParsedGateway | null, defaultMode?: string): MergeGatewayResult; /** Serialize a merged gateway config back to YAML (re-serializes; inline comments in custom blocks are not retained). */ export declare function serializeGatewayYaml(result: MergeGatewayResult): string; /** * Read existing gateway.yaml, merge discovery over it, and write the result. Always backs up an * existing file to .bak first (including when outputDir is given, since merge now touches real data). */ export declare function writeMergedGatewayYaml(discovered: DiscoveredEndpoint[], outputDir?: string, defaultMode?: string): { path: string; result: MergeGatewayResult; }; /** * Validate that every profile (and its fallback chain) in profiles.json references a gateway mode * that actually exists in the merged endpoint map. Pure + non-fatal — returns the list of problems * so the caller can warn loudly. This is what catches the `400 Unknown mode: ` class of bug. */ export declare function validateProfilesAgainstGateway(mergedEndpoints: EndpointMap, profilesConfigDir?: string): GatewayValidationIssue[]; /** * Run discovery and return the YAML string (without writing to disk). * Useful for dry-run / preview. */ export declare function dryRunGatewayYaml(): string;