Catalog ingestor coverage 5/7 → 7/7 — Perplexity + Moonshot complete the set

2026-05-08

routerintelligenceingestors

LOCKSTEP TRACEABILITY MATRIX --- api_endpoints: ["none"] sdk_methods_updated: ["none"] mcp_tools_updated: ["none"] ---

What We Built

Two more provider catalog ingestors — Perplexity and Moonshot — closing the ingestor coverage from 5/7 to 7/7. BR now polls every first-party provider's /v1/models hourly to detect catalog drift (model add/remove) and refresh liveness signals.

The Perplexity ingestor handles a subtle case: Perplexity's /v1/models endpoint is itself a meta-router and returns 23 models (anthropic, openai, google, xai, nvidia, perplexity). We filter to owned_by === "perplexity" so we only ingest first-party Perplexity models — third-party listings are already tracked via their original-provider ingestors.

The Moonshot ingestor extracts three useful signals beyond the OpenAI base shape: context_lengthmaxInputTokens, supports_image_incapabilities.supportsVision, supports_reasoningcapabilities.supportsReasoning. Capability patches are emitted only when flags are present, so partial payloads from older Kimi models cannot overwrite known-good static-catalog values.

Why It Matters

The catalog drift detection narrative is now complete. Until today, two providers' liveness was not auto-tracked — adds/removes had to be caught manually via static-catalog edits. The R20→R23 stochastic assessment trajectory consistently flagged "catalog ingestor coverage X/7" as the most-flagged risk; this PR closes the class.

How It Works

Both ingestors implement the standard ModelIngestor interface and register on hourly intervals when the matching provider env var is set. Registration follows the established pattern:

if (process.env.PERPLEXITY_API_KEY) {
  ingestorScheduler.register(
    new PerplexityIngestor({ getApiKey: () => process.env.PERPLEXITY_API_KEY }),
    60 * 60 * 1000,
  );
}

Diagnostics surface through /v1/intelligence/ingestors automatically (via the existing ingestorScheduler.diagnostics() call in src/api/routes/intelligence.ts).

The Numbers

  • Provider ingestor coverage: 5/7 → 7/7 (+ 28%)
  • New paired regression tests: 17 (10 Moonshot + 7 Perplexity)
  • New tests cover: prefix-stripping, owned_by filtering, third-party

passthrough rejection, capability flag propagation, partial-payload protection, HTTP/network error empty-return, no-API-key skip, default-endpoint correctness

  • Source files: 4 new (2 ingestors + 2 tests), 1 modified

(model-router-init.ts + 2 imports + 2 register blocks)

Competitive Edge

Closed-loop catalog drift detection across all routed providers (7/7) without any static maintenance. Portkey's catalog updates ship manually with releases; LiteLLM relies on contributor PRs; OpenRouter's catalog is its product, not an internal mechanism. BR treats catalog freshness as an autonomic property of the routing fabric, not a release artifact.

Lockstep Checklist

  • [x] API Routes: unchanged (no new endpoints; /v1/intelligence/ingestors discovers new entries via diagnostics)
  • [x] TS SDK: unchanged (no new endpoint to surface)
  • [x] Python SDK: unchanged (no new endpoint to surface)
  • [x] MCP Schemas: unchanged (no agent-facing surface added)
  • [x] Master Record: capability already documented; coverage metric updated implicitly via this entry

R23 risk register: most-flagged item (6/10 agents) closed.