Inline providers.json schema descriptions and fix schema delivery - #86
Open
sharon-wang wants to merge 5 commits into
Open
Inline providers.json schema descriptions and fix schema delivery#86sharon-wang wants to merge 5 commits into
sharon-wang wants to merge 5 commits into
Conversation
The Zod schema had no `.describe()` calls at all — every bit of prose lived in TSDoc, which Zod cannot see, so `providers.schema.json` shipped as a bare type listing. Anything generated from it was strictly worse than hand-written docs, which blocked generating a providers.json reference for the Assistant docs site. Descriptions are sourced from the existing TSDoc where it existed, from the hand-written Provider Settings section of the docs site, and from the bridge's ModelInfo comments. They avoid the `"` character so downstream consumers can quote them without escaping. The coverage test walks the generated JSON Schema and throws on any construct it does not explicitly handle, so an unsupported shape fails loudly instead of being skipped into vacuous success. It found eight genuinely undescribed fields (the capability section objects) that a field-count baseline would have missed. Also adds a CI guard: ai-config's `prebuild` regenerates the schema into the working tree and never diffs it, so a schema.ts change could merge against a stale artifact with CI green. The guard diffs against HEAD rather than the working tree, since `build` has already refreshed the file by that point.
Two bugs kept the schema from reaching users, so editors never showed
validation or hover descriptions for providers.json.
First, the schema was resolved at runtime with
`require.resolve("ai-config/providers.schema.json")`. Consumers bundle
ai-config (esbuild inlines it) and ship no `node_modules/ai-config` — the
Positron extension's .vscodeignore excludes node_modules entirely, and
standalone is a single bundled main.js. So that resolve throws in every
packaged build, lands in the catch, logs a warning, and writes nothing. Only
dev checkouts ever got a schema.
Second, the copy ran only inside the race-safe file-creation branch, so even
where it worked it wrote once and never again. An install whose providers.json
predates a schema change stayed pinned to whatever shipped that day.
generate-schema now emits the same bytes as a string constant that
`mutateProvidersConfig` writes directly. Inlining is the only form that
survives bundling. It is stored minified and pretty-printed on write, which
halves what every consumer bundles (440KB to 224KB, measured +1.5% on the
standalone server bundle) and reproduces the .json file byte for byte.
The write runs after the mutation rather than before, so it cannot perturb the
mutation's own read/write sequence, and is skipped when the mutation fails. It
compares content first, so the common path does no disk write.
Note this still only refreshes on a mutation, which fires on migrations,
Snowflake auth, and settings writes — not at every startup. A user who
upgrades and never changes a setting still will not see a refresh; closing
that needs an explicit call from the hosts.
Drop "Node-backed surfaces" jargon from providers.custom and snowflake.connectionName, and say "Maximum" instead of "Largest" for maxInputTokens/maxOutputTokens, matching common usage.
sharon-wang
force-pushed
the
inline-providers-schema
branch
from
August 26, 2026 15:46
e4f9eb3 to
099be97
Compare
It said headers are "sent with every request," but several built-in providers (copilot, google-vertex, ollama, lmstudio) never look at customHeaders at all. Since this field is shared across every provider block, the description needs to hold true everywhere it's attached, not just for the providers that happen to forward it.
Also fixes a description regression the merge surfaced: origin/main's gateway reserved-header validation (gatewayCustomHeadersSchema) built customHeaders from a bare z.record(z.string(), z.string()) for every built-in provider, dropping the field's description and its per-key/ value descriptions entirely (caught by schema-descriptions.test.ts). Extracted the described base schema (customHeadersSchema) so the gateway refinement builds on it instead of a fresh undescribed record.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
addresses posit-dev/positron#15434
pre-req to https://github.com/posit-dev/assistant/pull/2224
Summary
.describe()calls throughout the providers.json Zod schema soproviders.schema.jsoncarries real field descriptions instead of a bare type listing, unblocking a generated providers.json reference for the Assistant docs site.providers.schema.jsonnever actually reaching packaged consumers: it was resolved at runtime viarequire.resolve, which throws in every bundled build (Positron, standalone) since neither shipsnode_modules/ai-config.generate-schemanow emits the same bytes as an inlined string constant thatmutateProvidersConfigwrites directly, and the write now runs on every mutation instead of only during file creation.providers.schema.jsonand the new inlined source file) stay in sync with the Zod schema.Test plan
npm run generate-schema -w ai-configand diff against committed outputnpm run test -w ai-config(includes newschema-descriptions.test.tsand updatedload-config.test.ts)npm run check-types -w ai-provider-bridge