Skip to content

Derive ProviderCatalogEntry from ProviderSettings instead of duplicating its field list - #391

Merged
TheGreatAxios merged 2 commits into
mainfrom
cl-5680-providercatalogentry-and-providersettings-are-parallel-type
Aug 8, 2026
Merged

Derive ProviderCatalogEntry from ProviderSettings instead of duplicating its field list#391
TheGreatAxios merged 2 commits into
mainfrom
cl-5680-providercatalogentry-and-providersettings-are-parallel-type

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Collaborator

Summary

  • ProviderCatalogEntry (src/config/index.ts:95-130) and ProviderSettings (src/config/settings.ts:21-45) declared the same provider record independently. A field added to one and forgotten in the other is silently dropped wherever a settings provider is converted to a catalog entry, with no compiler error — the exact gap this fixes.
  • ProviderCatalogEntry is now Omit<ProviderSettings, "name" | "contextWindow"> & { name: string; codexProfile?; codexAccountId?; xaiProfile? }. name becomes required (every catalog entry resolves to a concrete provider id); contextWindow is excluded because it was already never forwarded by buildProviderCatalog/catalogEntryAsProviderSettings — a settings-only override, not surfaced to the /agent modal. The three OAuth-profile markers stay explicit because they have no ProviderSettings counterpart (Codex/xAI OAuth entries are never written to settings.json).
  • No behavior change: the field set carried by the catalog is unchanged, only how it's declared.

Bug this closes

Before this change there was no link between the two types at all — a conversion function (catalogEntryAsProviderSettings) already existed, but its return type and ProviderCatalogEntry's field list were two independent hand-written lists with no compiler tie. That absence of a link was the bug: nothing would catch a new ProviderSettings field never being added to ProviderCatalogEntry, or vice versa.

Test plan

  • Added round-trips every ProviderSettings field a catalog entry can carry through buildProviderCatalog and back in src/config.test.ts, which pushes a full-field provider through buildProviderCatalog then catalogEntryAsProviderSettings and asserts the fields survive intact — this now fails if a shared field stops making it through either conversion.
  • bun run typecheck — no new errors (pre-existing unrelated arktype-version errors present on main across vendor/tui code).
  • bun run build — clean.
  • bun run test — 1 pre-existing, unrelated failure (detectLanguageServerAvailable, environment-dependent), everything else passes including the new test.

@linear-code

linear-code Bot commented Aug 8, 2026

Copy link
Copy Markdown

CL-5680

…ing its field list

src/config/index.ts:95-130 (ProviderCatalogEntry) and src/config/settings.ts:21-45
(ProviderSettings) independently declared the same provider record, so a field
added to one silently never reached the catalog conversion in
catalogEntryAsProviderSettings/buildProviderCatalog. ProviderCatalogEntry is now
Omit<ProviderSettings, "name" | "contextWindow"> plus its required name and the
OAuth-only markers (codexProfile/codexAccountId/xaiProfile) that have no
settings.json counterpart. Added a round-trip test in src/config.test.ts that
fails if a shared field stops surviving buildProviderCatalog ->
catalogEntryAsProviderSettings.
@TheGreatAxios
TheGreatAxios force-pushed the cl-5680-providercatalogentry-and-providersettings-are-parallel-type branch from 6338a55 to e1e344e Compare August 8, 2026 18:56
The round-trip test omitted keyless, anthropic, and opencodeGo, so it
could not actually catch a dropped optional field despite claiming to
exercise every field. Split anthropic/opencodeGo into their own cases
since both also normalize baseURL in buildProviderCatalog, and cover
keyless in the base case. Also correct the ProviderCatalogEntry doc
comment: the Omit/intersection only forces literals to supply a newly
required field: an optional field can still be silently dropped by a
hand-written conversion, which is why the round-trip test exists.
@TheGreatAxios
TheGreatAxios merged commit 201de86 into main Aug 8, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant