Skip to content

feat(models): explicit wire protocol declarations for providers#93

Merged
ezynda3 merged 4 commits into
masterfrom
provider-wire-overrides
Jul 10, 2026
Merged

feat(models): explicit wire protocol declarations for providers#93
ezynda3 merged 4 commits into
masterfrom
provider-wire-overrides

Conversation

@ezynda3

@ezynda3 ezynda3 commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Description

Providers have their wire protocol (OpenAI / Anthropic / Google) inferred from the models.dev npm-package heuristic, with no escape hatch besides --provider-url — which always forces the OpenAI-compatible wire. When the database misroutes a provider, omits one entirely, or an internal gateway speaks a non-OpenAI wire, there was no way to fix it locally.

This adopts the explicit provider-type design from charmbracelet/catwalk without switching data sources: the wire protocol becomes a first-class, declarable attribute of a provider, while the npm heuristic remains the default for the 144-provider models.dev long tail.

Before — only workaround was the custom/ provider (openai-compat wire only):

kit --provider-url http://gateway.corp/v1 "Hello"   # always chat-completions wire

After — declare any provider on any wire, in config or ad hoc:

# ~/.kit.yml
providers:
  minimax:                    # patch a known provider's wire
    wire: anthropic
  corp-llm:                   # declare a new provider
    wire: anthropic
    baseUrl: https://llm.internal.corp/api
    apiKeyEnv: [CORP_LLM_KEY]
    headers:
      X-Team: platform
kit -m corp-llm/claude-sonnet-4-5 "Hello"
# or one-off, no config edit:
kit -m proxy/claude-x --provider-url https://proxy.example/api --provider-wire anthropic "Hello"

Changes

  • ProviderInfo gains Wire and Headers fields; the internal wireProtocol enum splits wireOpenAI (Responses API) from wireOpenAICompat (chat completions), removing the npm == "@ai-sdk/openai" dispatch special case
  • New providers config section (internal/models/provider_overrides.go): name, wire, baseUrl, apiKeyEnv, headers. Merged as the final registry layer — non-empty fields win, unset fields inherit models.dev values, unknown IDs register fresh. Invalid wires warn and skip the whole override
  • New --provider-wire flag (+ kit.Options.ProviderWire / WithProviderWire() in the SDK, inherited by subagents). With --provider-url it synthesizes unknown providers on the fly and skips the custom/ openai-compat rewrite
  • Wire resolution precedence: --provider-wire > providers config > npm heuristic > api-URL openaicompat fallback (long-tail behavior unchanged)
  • Per-provider default headers via an http.RoundTripper wrapper on all four auto-routed constructors, composing with the existing TLS and gemini-proxy transports (doesn't overwrite request-set headers)

Type of Change

  • New feature (non-breaking change that adds functionality)
  • Bug fix
  • Breaking change
  • Documentation update
  • Refactor

Backward Compatibility

  • No schema change to the embedded models.dev snapshot or the on-disk cache format
  • ProviderInfo changes are additive (new fields), so pkg/kit SDK consumers are unaffected
  • Auto-routing for all existing providers behaves identically when no override is declared
  • --provider-url without --provider-wire keeps its existing custom/ rewrite semantics

Testing

  • 15 new tests in internal/models/provider_overrides_test.go: wire parsing/aliases, explicit-wire routing to all four transports, flag-beats-config-beats-npm precedence, provider synthesis, override merge semantics (patch/declare/invalid-wire skip), config parsing, header round-tripper contract
  • Existing autoroute_test.go updated for the enum split
  • Full go test -race ./... green; go vet clean
  • Verified end-to-end with a built binary: config-declared provider hit <baseUrl>/v1/messages with env-resolved key; ad-hoc --provider-wire anthropic synthesized and routed; invalid wires produce targeted errors

Checklist

  • Code follows the repository style guidelines (go fmt, go vet)
  • Self-reviewed the diff
  • Tests added for new functionality
  • Documentation updated (README, www/pages/{configuration,providers,cli/flags,sdk/options,sdk/overview}.md, godoc on all new exported symbols; docs site verified with tome build)

Summary by CodeRabbit

  • New Features
    • Added --provider-wire (and SDK ProviderWire) to select the wire protocol for auto-routed providers.
    • Introduced “Provider overrides” via config to patch or define providers with wire, baseUrl, apiKeyEnv, and default request headers.
  • Bug Fixes
    • Improved auto-routing so OpenAI-compatible wrapper packages route using the correct wire protocol.
  • Documentation
    • Updated CLI/config/provider/SKD docs with new flags, precedence rules, accepted wire values, and override examples.

ezynda3 added 3 commits July 10, 2026 15:26
Providers previously had their wire protocol (openai, anthropic, google)
inferred solely from the models.dev npm-package heuristic, with no escape
hatch besides --provider-url (which forces the OpenAI-compatible wire).
This adopts the explicit provider-type design from charmbracelet/catwalk
without switching data sources:

- ProviderInfo gains Wire and Headers fields; the wireProtocol enum
  splits wireOpenAI (Responses API) from wireOpenAICompat (chat
  completions), removing the npm=="@ai-sdk/openai" dispatch special case
- New `providers` config section declares or patches providers: wire,
  baseUrl, apiKeyEnv, headers, name. Unknown IDs register fresh, so
  internal gateways work without a database entry
- New --provider-wire flag (also kit.Options.ProviderWire, inherited by
  subagents); with --provider-url it synthesizes unknown providers on
  the fly and skips the custom/ openai-compat rewrite
- Wire resolution precedence: --provider-wire > providers config >
  npm heuristic > api-URL openaicompat fallback (unchanged long tail)
- Per-provider default headers ride an http.RoundTripper wrapper on all
  four auto-routed constructors, composing with TLS and gemini-proxy
  transports
Options.ProviderWire landed without a matching functional option;
every other provider override field (ProviderAPIKey, ProviderURL) has one.
Covers the --provider-wire flag, the providers config section, and
Options.ProviderWire / WithProviderWire:

- www/pages/configuration.md: provider-wire config key, new Provider
  overrides section with field reference, cross-ref from Custom models
- www/pages/providers.md: link to field reference, when-to-use-which
  table comparing custom provider / customModels / providers overrides /
  --provider-wire
- www/pages/cli/flags.md + README flag list: --provider-wire row
- www/pages/sdk/options.md: ProviderWire field row + struct example
- www/pages/sdk/overview.md: WithProviderWire functional option row

Docs site verified with 'tome build'.
@mark-iii-labs-huly

Copy link
Copy Markdown

Connected to Huly®: KIT-94

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds explicit provider wire selection through CLI, SDK, and configuration; introduces provider overrides for registry entries and new providers; updates auto-routing precedence and protocol mappings; and applies configured headers to auto-routed HTTP clients.

Changes

Provider wire routing and overrides

Layer / File(s) Summary
Wire protocols and provider overrides
internal/models/modelsdb.go, internal/models/provider_overrides.go, internal/models/registry.go, internal/models/*_test.go
Adds canonical and aliased wire parsing, provider override declarations, registry merging, explicit-wire support detection, and updated OpenAI-compatible package mappings.
Auto-routing and provider HTTP clients
internal/models/providers.go, internal/models/autoroute_test.go, internal/models/provider_overrides_test.go
Adds wire precedence and unknown-provider synthesis, separates OpenAI and OpenAI-compatible dispatch, and applies non-overwriting default headers to auto-routed clients.
CLI and SDK propagation
cmd/root.go, internal/kitsetup/setup.go, pkg/kit/kit.go, pkg/kit/options.go, pkg/kit/mcp_tasks_test.go
Adds --provider-wire, ProviderWire, and WithProviderWire, then propagates the setting through Viper, provider setup, and child agents.
CLI, configuration, and SDK documentation
README.md, www/pages/cli/flags.md, www/pages/configuration.md, www/pages/providers.md, www/pages/sdk/*
Documents supported wire values, provider override fields, precedence, one-off routing, and SDK configuration.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLIorSDK
  participant Viper
  participant BuildProviderConfig
  participant autoRouteProvider
  participant ModelsRegistry
  participant ProviderConstructor
  CLIorSDK->>Viper: Set provider-wire and provider-url
  Viper->>BuildProviderConfig: Read provider configuration
  BuildProviderConfig->>autoRouteProvider: Pass ProviderWire and ProviderURL
  autoRouteProvider->>ModelsRegistry: Resolve provider metadata and wire
  autoRouteProvider->>ProviderConstructor: Create protocol-specific provider
  ProviderConstructor->>ProviderConstructor: Apply configured headers
Loading

Possibly related PRs

  • mark3labs/kit#42: Extends related per-instance provider configuration inheritance into provider-wire.
  • mark3labs/kit#43: Covers related wire-protocol mappings and auto-routing dispatch behavior.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 97.56% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: explicit wire protocol declarations for providers.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch provider-wire-overrides

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
pkg/kit/kit.go (1)

2294-2294: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover ProviderWire in the subagent inheritance test.

Extend TestInheritProviderConfig to set provider-wire on the parent and assert child.ProviderWire. This protects the new propagation path from silently regressing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/kit/kit.go` at line 2294, Update TestInheritProviderConfig to configure
provider-wire on the parent provider settings, then assert that the inherited
child.ProviderWire matches the configured value, covering the ProviderWire
propagation path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/models/providers.go`:
- Around line 488-495: Update ProviderResult to carry the resolved wire/protocol
from the auto-routing logic in createAutoRoutedOpenAIProvider and related
provider constructors, then make CreateProvider’s cache-options merge guard use
that resolved protocol instead of only checking provider == "openai". Ensure
providers configured with wireOpenAI skip incompatible cache merging even when
their declared provider name is not "openai".
- Around line 533-539: headerRoundTripper.RoundTrip must distinguish absent
headers from explicitly empty ones. Replace the Header.Get check with
presence-aware lookup (such as checking the map key) so configured values are
added only when the request header is not already present, preserving
intentionally cleared Authorization and other headers.
- Line 540: Update the RoundTrip method to capture the error returned by
h.base.RoundTrip(req) and wrap any failure with fmt.Errorf using the %w verb,
adding request/transport context before returning the response and wrapped
error.

---

Nitpick comments:
In `@pkg/kit/kit.go`:
- Line 2294: Update TestInheritProviderConfig to configure provider-wire on the
parent provider settings, then assert that the inherited child.ProviderWire
matches the configured value, covering the ProviderWire propagation path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f0992ee4-993e-41ad-a2d3-d89a4498f2a6

📥 Commits

Reviewing files that changed from the base of the PR and between 10e9e27 and 2a91ba1.

📒 Files selected for processing (16)
  • README.md
  • cmd/root.go
  • internal/kitsetup/setup.go
  • internal/models/autoroute_test.go
  • internal/models/modelsdb.go
  • internal/models/provider_overrides.go
  • internal/models/provider_overrides_test.go
  • internal/models/providers.go
  • internal/models/registry.go
  • pkg/kit/kit.go
  • pkg/kit/options.go
  • www/pages/cli/flags.md
  • www/pages/configuration.md
  • www/pages/providers.md
  • www/pages/sdk/options.md
  • www/pages/sdk/overview.md

Comment thread internal/models/providers.go
Comment thread internal/models/providers.go
Comment thread internal/models/providers.go
- Make the cache-options merge guard wire-aware: detect
  ResponsesProviderOptions by type via hasResponsesProviderOptions()
  instead of checking provider == "openai", so providers auto-routed
  to the Responses wire (wire: openai / npm @ai-sdk/openai) are
  guarded too; regression test ties the guard to the real options
  producer (buildOpenAIProviderOptions)
- headerRoundTripper: presence-aware header check so an explicitly
  cleared (empty) request header is not replaced by the configured
  default; regression test added
- Cover ProviderWire in TestInheritProviderConfig

Skipped (intentional): wrapping h.base.RoundTrip errors — http.Client
already wraps transport errors in *url.Error with method+URL context,
and the sibling geminiProxyTransport uses the same pass-through
pattern; wrapping inside middleware adds noise without new context.
@ezynda3 ezynda3 merged commit 3dd2f58 into master Jul 10, 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