fix(byok): support user OpenAI/Anthropic API keys + working effort pill#25
Merged
Conversation
Three connected bugs that surfaced when a user supplied their own OpenAI/Anthropic key (BYOK) instead of using the Anton/OpenRouter proxy. 1. resolveModel only had fallbacks for `anton` and `openrouter`. For direct-API providers (openai, anthropic, google, groq, mistral) it relied entirely on pi SDK's hardcoded registry, so any model the registry didn't know about (e.g. `gpt-5.5`) failed to start a session. New `buildDirectApiModel` builder mirrors `buildOpenRouterModel` for these providers and routes to the right `api`/`baseUrl`. resolveModel now also threads an optional baseUrl override so users with self-hosted/proxy endpoints work. 2. Mid-conversation `switchModel` was brittle: it called pi SDK's `setModel` but didn't reconcile the rest of the session's model-derived state. Hardened it to (a) fail fast with a clear error when the new provider has no API key, (b) clamp thinking level to 'off' on reasoning -> non-reasoning transitions so the upstream API doesn't reject the request, (c) refresh compactionConfig.maxContextTokens so the gauge and compaction threshold match the new model's window. 3. The composer's Effort pill was hidden for API sessions on `gpt-5.x` because `supportsReasoningEffort()`'s regex didn't include the gpt-5 family. Worked for the `codex` harness because that branch returns true unconditionally. Pi SDK and the server-side wiring were already correct; only the UI gate needed the fix. Regex now matches the same families `buildDirectApiModel` detects, with a comment pointing the two heuristics at each other so they don't drift. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Place pending-confirm prompts immediately above the composer (inside `conv-dock__inner`) instead of higher in the chat shell, so the dialog sits where the user is already looking. Adjust `.chat-shell__confirm` spacing to match the new placement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
OmGuptaIND
added a commit
that referenced
this pull request
May 4, 2026
### Other - fix(byok): support user OpenAI/Anthropic API keys + working effort pill (#25)
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.
Summary
Three connected bugs that surfaced when a user supplies their own OpenAI/Anthropic key (BYOK) instead of using the Anton/OpenRouter proxy:
resolveModelrejected BYOK models. Onlyantonandopenrouterhad fallbacks — direct-API providers (openai, anthropic, google, groq, mistral) relied entirely on pi SDK's hardcoded registry, so any model the registry didn't know (e.g.gpt-5.5) failed to start a session. NewbuildDirectApiModelmirrorsbuildOpenRouterModelfor these providers and routes to the rightapi/baseUrl.resolveModelnow also threads an optionalbaseUrloverride so users with self-hosted/proxy endpoints work.Mid-conversation
switchModelwas brittle. It called pi SDK'ssetModelbut didn't reconcile the rest of the model-derived state. Hardened to (a) fail fast with a clear error when the new provider has no API key, (b) clamp thinking level to'off'on reasoning → non-reasoning transitions so the upstream API doesn't reject the request, (c) refreshcompactionConfig.maxContextTokensso the gauge and compaction threshold match the new model's window.Effort pill was hidden for API sessions on
gpt-5.x. Pi SDK and the server-side wiring were already correct —Session.setThinkingLevelforwards topiAgent.setThinkingLevel. The composer'ssupportsReasoningEffort()regex just didn't include the gpt-5 family. Worked for thecodexharness because that branch returnstrueunconditionally. Regex now matches the same familiesbuildDirectApiModeldetects, with a comment pointing the two heuristics at each other so they don't drift.Test plan
gpt-5.5, send a message → session starts, response streams.claude-sonnet-4-6, send a message → works.claude-opus-4-6(reasoning) → a non-reasoning model → next turn doesn't get rejected for sending athinkingLevel.provider=openai, model=gpt-5.5selected, the Effort pill is visible in the composer and changes the next turn's effort.provider=codex(harness), the Effort pill still shows.provider=claude(Claude Code harness), the Effort pill stays hidden (CLI has no thinking flag).🤖 Generated with Claude Code