feat: add Command Code OAuth provider - #1066
Conversation
Review readiness checklistThis PR is kept in draft until every requirement below is fulfilled. The tickable checklist has been added to your PR description — tick all four boxes there.
✅ 4/4 boxes ticked. ✅ All four boxes are ticked. |
|
✅ PR quality gates passed This pull request now targets The title was left unchanged. Its existing draft status has been preserved. |
|
✅ Deterministic PR hygiene checks passed. |
This comment was marked as outdated.
This comment was marked as outdated.
49bc0b6 to
4b95fdb
Compare
This comment was marked as outdated.
This comment was marked as outdated.
…data - Preserve tool-result image parts as [image] markers instead of silently dropping them (contentPartsToText), matching other adapters. - Bind the OAuth callback on both IPv4 and IPv6 loopback and race the shared manual-paste fallback (raw API key or pasted callback JSON/URL), matching OAuthCallbackFlow behavior for Windows/headless/remote cases. - Minimize workspace metadata: cap the directory listing at 64 entries, bound the x-project-slug header, and drop the always-empty git stubs. - Update providers docs (EN + ja/ko/ru/zh) and the registry note to describe OAuth login with local CLI credential import. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
|
@CodeRabbit review |
✅ Action performedReview finished.
|
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
…streaming - Carry tool-result image parts in a follow-up user message (the proprietary tool-result output is text-only), so view_image data reaches the model instead of being dropped or flattened to a marker. - Honor ctrl.signal during local CLI credential import (abort during whoami). - Always stop callback servers even when controller callbacks throw. - Bound the model-profile page read with readBoundedResponseBody. - Cancel the NDJSON reader on teardown, send parsed.stream as the wire stream field, and emit a fallback done when a stream ends without a finish event. - Add error-event, fallback-done, and stream-field tests; assert callback keys never leak into thrown errors. - Fix the remaining "public catalog / unverifiable" claims in providers docs (EN + ja/ko/ru/zh) so they match the authenticated discovery wording. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
This comment was marked as resolved.
This comment was marked as resolved.
- Send memory as the schema-strict empty string instead of null. - Treat finish-step as a terminal event (usage + finishReason) and emit only one done even when finish-step and finish both appear in the stream. - Defensively strip SSE data: framing so a gateway shape drift cannot silently drop every event; raw newline-delimited JSON still parses as before. - Make x-command-code-version configurable via provider.commandCodeVersion and update the default to the current CLI protocol version. - Add finish-step and SSE-frame regression tests. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
The Command Code OAuth and API presets were only distinct in the provider workspace; data-driven surfaces rendered the raw config id (command-code / commandcode), so both still read as "Command Code". Route the provider id through formatProviderDisplayName in: - Models tab group headers and model tooltip - Logs provider column, detail row, and attempt rows - Usage per-model and per-provider tables - API keys source label - Dashboard active-providers table and dashboard models groups - Combo target provider select Route/path strings (e.g. command-code/model selects and cost breakdowns) keep the raw id since it is the routing key and already disambiguates. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
command-code and commandcode differ by a single dash, so raw model routes were still hard to tell apart. Add formatNamespacedModelId, which rewrites the provider prefix of a provider/model route to its display name (command-code/x -> "Command Code - Auth/x", commandcode/x -> "Command Code - API/x"), and use it in the visible model-route surfaces: - Models tab model rows and tooltip id - Dashboard injection/shadow-call model selects - Subagents delegation model select The raw config id stays as the underlying value/key and in the Switch aria-label; only the visible label changes. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
The Models page side rail under "Providers" still rendered the raw config ids (command-code / commandcode). Route it and the custom-model modal title through formatProviderDisplayName so both Command Code entries read as "Command Code - Auth" / "Command Code - API" consistently. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
Only the Models "Providers" side rail and custom-model modal title should show the friendly display names; the collapsing provider group headers and the model rows/tooltips inside stay as the raw config ids and namespaced routes, as they were before. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
…ames The Codex model picker (coding harness) lists routed models by their raw slug, so the two Command Code presets were still `command-code/x` vs `commandcode/x` — a single dash apart. For Command Code routed models only, stamp the catalog display_name as `<registry label>/<model>` (e.g. "Command Code - Auth/deepseek-v4-flash") so the harness picker distinguishes them. The routing slug is untouched, other providers are unchanged, and a configured user displayName still overrides the label. Also route the Models-tab shadow-call model dropdown and the dashboard injection/shadow-call/subagent delegation selects through the same friendly label. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
|
@CodeRabbit review |
|
…h/api Keep the raw config ids (command-code / commandcode) untouched so nothing breaks, but relabel the model-picker/route display to the lowercase-dash style the opencode presets use (opencode-free/x, opencode-go/x): - GUI dropdowns and Models route labels: command-code/x -> commandcode-auth/x, commandcode/x -> commandcode-api/x - Codex catalog display_name for Command Code routed models: same relabel; the routing slug is unchanged and other providers are untouched. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
…ng cards - Drop the redundant vendor prefix in encoded Command Code model ids for display: command-code/deepseek-deepseek-v4-flash -> commandcode-auth/deepseek-v4-flash (GUI + Codex catalog display_name). - Apply the friendly commandcode-auth/commandcode-api slugs to the Models tab collapsing group headers and model rows (not just the side rail), so the dropdowns in the screenshot are relabeled too. - Add a providerDisplaySlug helper and tests for the de-dup behavior. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3bbad09f9e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…, docs) - Add mediaType to wire image parts (data URL parse + remote extension fallback) for /alpha/generate schema validation and gateway decoding. - Mark the command-code adapter tool-capable in the routing capability path so profiles with require.tools stop excluding this provider. - Preserve an operator's commandCodeVersion pin across login/add-account/reauth (upsertOAuthProvider no longer drops it). - Let pasted JSON callback payloads through the shared manual-code gate for Command Code so the provider JSON parser is reachable in remote/headless logins. - Iterate workspace entries with opendir and stop at the 64-entry cap instead of materializing every name. - Update documented provider totals (69 -> 70, seven -> eight OAuth) across EN and ja/ko/ru/zh providers guides and quickstarts. Declined with evidence: GLM effort refresh case-sensitivity — keyFor already lowercases lookups against the lowercase table, verified against the live catalog id (zai-org/GLM-5.2). Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
[GD] Verdict: gated (re-review)PR: Re-review summaryFixed on
Declined with evidence (1 finding):
Validation: 221 provider/catalog tests pass, typecheck clean, GUI lint + i18n lint + privacy scan clean. Remaining gates:
Bottom line: All re-review findings are addressed (6 fixed, 1 declined with evidence, 1 duplicate). The PR is mergeable and code-clean; only the base-sync, draft, and CI-approval operational gates remain. Full detailFindings fixed
Declined
Validation
Owner actions (foreign PR)
|
formatNamespacedModelId was title-casing every provider prefix (e.g. fallback-provider -> Fallback Provider), breaking the Models page shadow-call dropdown and its GUI test. Restrict the rewrite to the two Command Code ids (commandcode-auth / commandcode-api); every other provider keeps its raw route. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 920134efa5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
… lookup - supportedCommandCodeEffort now maps both xhigh and ultra to the wire value max when the model's official ladder includes it, so an advertised ultra rung actually takes effect instead of silently dropping reasoning_effort. - The effort lookup resolves compatibility ids (deepseek-v4-flash / glm-5.2) to their canonical Command Code id first, so legacy/migrated configs keep their reasoning behavior. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
|
Thanks @hanbinnoh — merging this. Why it helps: this adds Command Code as a first-class provider with OAuth login (local CLI credential import), live model discovery from the authenticated catalog, a streaming adapter for the proprietary |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 22644158ae
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const stopReason = typeof event.rawFinishReason === "string" ? event.rawFinishReason : typeof event.finishReason === "string" ? event.finishReason : undefined; | ||
| yield { type: "done", usage: usage(usageValue), stopReason }; |
There was a problem hiding this comment.
Normalize Command Code finish reasons
When /alpha/generate finishes with provider-native reasons such as stop or length, this forwards them directly as AdapterEvent.stopReason. The bridge treats an absent stopReason as a clean final answer and only recognizes max_tokens/content_filter as incomplete, so normal stop responses lose final-answer phase inference and length truncations are reported as completed instead of incomplete. Map length to max_tokens and omit stopReason for normal/tool-call stops before yielding done.
Useful? React with 👍 / 👎.
| "azure", | ||
| "kiro", | ||
| "mimo-free", | ||
| "command-code", |
There was a problem hiding this comment.
Make tool capability apply to live rows
Fresh evidence after the TOOL_CAPABLE_ADAPTERS fix: adding command-code here still only helps when catalogRow === undefined in the tools expression below. Once Command Code live discovery has written a catalog row without capabilities:["tools"], policy routing for require.tools or tool-bearing requests still sees tools as unknown and can exclude this provider, so the adapter-level signal needs to apply even when a catalog row exists without a positive tools flag.
Useful? React with 👍 / 👎.
| <Select | ||
| value={shadowCall?.model ?? ""} | ||
| options={[{ value: "", label: "—" }, ...models.map(m => ({ value: m.id, label: `${m.provider}/${m.id}` }))]} | ||
| options={[{ value: "", label: "—" }, ...models.map(m => ({ value: m.id, label: formatNamespacedModelId(`${m.provider}/${m.id}`, t) }))]} |
There was a problem hiding this comment.
Save the selected shadow-call route
When the Dashboard overview shadow-call picker is used with both Command Code account/API rows, the label now shows a provider-qualified commandcode-* choice but the saved value is still only m.id. /api/shadow-call-settings persists that bare native id, and routeModel() resolves bare slash ids by provider order/defaults rather than the provider the user selected, so helper calls can be redirected to the wrong Command Code account/API provider; use the row's namespaced slug for the option value, as the Models page does.
AGENTS.md reference: gui/AGENTS.md:L10-L10
Useful? React with 👍 / 👎.
Summary
Validation
Review readiness checklist
This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:
All CI tests are green on my local testing.
I pushed my PR to the latest dev commit.
I fixed all correct Codex and CodeRabbit findings.
My PR is ready for review.
Summary by CodeRabbit
New Features
Documentation