Skip to content

feat(codersdk): generate chat model provider options schema from Go structs#22568

Merged
kylecarbs merged 11 commits intomainfrom
kylecarbs/gen-model-options
Mar 3, 2026
Merged

feat(codersdk): generate chat model provider options schema from Go structs#22568
kylecarbs merged 11 commits intomainfrom
kylecarbs/gen-model-options

Conversation

@kylecarbs
Copy link
Copy Markdown
Member

@kylecarbs kylecarbs commented Mar 3, 2026

Summary

Adds make gen script that generates a JSON schema from Go structs for chat model provider configuration fields, eliminating manual frontend duplication.

Problem

The frontend manually defines ~75 fields across 6 providers. Adding a new field requires editing multiple files, and the frontend can't track backend changes to field names, types, enums, or descriptions.

Solution

Go struct tags are now the source of truth:

  • description:"..." — field label
  • enum:"val1,val2,..." — valid options for select fields
  • hidden:"true" — exclude from UI forms (infrastructure fields only)

The scripts/modeloptionsgen/main.go script uses reflection to introspect ChatModel*ProviderOptions structs, reads these tags, infers input types, flattens nested structs with dot notation, and outputs JSON schema.

Changes

File Description
codersdk/chats.go Added struct tags to all 14 provider option structs (~75 fields)
scripts/modeloptionsgen/main.go Reflection-based generator (576 lines)
site/src/api/chatModelOptionsGenerated.json Generated schema (auto-formatted with biome)
site/src/api/chatModelOptions.ts TypeScript utilities for consuming the schema
Makefile Wired into make gen

Generated Schema

Visible fields by provider

Provider Visible Fields
general (6) max_output_tokens, temperature, top_p, top_k, presence_penalty, frequency_penalty
openai (8) max_tool_calls, parallel_tool_calls, reasoning_effort, reasoning_summary, max_completion_tokens, text_verbosity, service_tier, audio
anthropic (4) send_reasoning, thinking.budget_tokens, effort, disable_parallel_tool_use
google (2) thinking_config.thinking_budget, thinking_config.include_thoughts
openaicompat (1) reasoning_effort
openrouter (5) reasoning.effort, reasoning.budget_tokens, parallel_tool_calls, transforms, models
vercel (5) reasoning.effort, reasoning.budget_tokens, reasoning.content, parallel_tool_calls, headers

22 infrastructure fields marked hidden:"true" (e.g., logit_bias, metadata, safety_settings, provider, extra_body)

Schema structure

{
  "general": {"fields": [...]},
  "providers": {
    "openai": {"fields": [...]},
    "anthropic": {"fields": [...]},
    // ...
  },
  "provider_aliases": {"azure": "openai", "bedrock": "anthropic"}
}

Each field includes:

  • json_name, go_name — API and Go identifiers
  • type"string", "integer", "number", "boolean", "array", "object"
  • description — human-readable label
  • required — always false (all fields optional in DB configs)
  • enum — valid values for select fields (6 fields total)
  • input_type"select", "input", or "json" (UI widget hint)
  • hiddentrue for infrastructure-only fields

Next Steps

Frontend work to consume this schema and replace manual field definitions will come in a follow-up PR. This PR establishes the codegen pipeline and schema format.

…tructs

Adds a codegen script (scripts/modeloptionsgen) that uses Go reflect to
introspect the ChatModel*ProviderOptions structs in codersdk/chats.go and
emits a JSON schema describing every configurable field. The frontend can
import this schema to dynamically render model config forms instead of
manually maintaining per-provider field definitions.

Changes:
- codersdk/chats.go: Add description, enum, and hidden struct tags to all
  provider option structs. These are the source of truth for field metadata.
- scripts/modeloptionsgen/main.go: New Go script that reflects on codersdk
  structs and outputs JSON with field name, type, description, enum values,
  input_type hint, and hidden flag.
- site/src/api/chatModelOptionsGenerated.json: Generated schema covering
  6 general fields and all provider-specific fields across 6 providers.
- site/src/api/chatModelOptions.ts: Typed TS module with utility functions
  (getVisibleProviderFields, resolveProvider, toFormFieldKey, etc.).
- Makefile: Wire into make gen so the schema regenerates when chats.go or
  the generator script changes.
- Vercel reasoning effort: add 'none' and 'xhigh' (valid per Fantasy)
- OpenAI strict_json_schema: mark hidden
- Anthropic send_reasoning: keep visible
- Google stray threshold field: mark hidden
- OpenRouter/Vercel logit_bias, log_probs, top_logprobs, extra_body: mark hidden
OpenAI's API supports these values even though Fantasy's consts don't
include them yet.
Copy link
Copy Markdown
Member

@johnstcn johnstcn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with this impl, but don't forget about https://github.com/coder/guts

modeloptionsgen Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add to .gitignore please!

@kylecarbs kylecarbs enabled auto-merge (squash) March 3, 2026 21:03
@kylecarbs kylecarbs merged commit f758443 into main Mar 3, 2026
44 of 50 checks passed
@kylecarbs kylecarbs deleted the kylecarbs/gen-model-options branch March 3, 2026 21:30
@github-actions github-actions bot locked and limited conversation to collaborators Mar 3, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants