Skip to content

feat: add Command Code OAuth provider - #1066

Draft
hanbinnoh wants to merge 2 commits into
lidge-jun:devfrom
hanbinnoh:feat/command-code-auth
Draft

feat: add Command Code OAuth provider#1066
hanbinnoh wants to merge 2 commits into
lidge-jun:devfrom
hanbinnoh:feat/command-code-auth

Conversation

@hanbinnoh

@hanbinnoh hanbinnoh commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add the direct Command Code OAuth adapter with CLI-auth import and browser authorization
  • discover models dynamically from the authenticated provider catalog, without a static model fallback
  • expose generic provider accounts, usage, and GUI catalog integration

Validation

  • bun run test
  • cd gui && bun test tests && bun run lint && bun run lint:i18n && bun run build
  • bun run typecheck
  • bun run privacy:scan
  • live local Command Code request through OpenCodex

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
    • Added Command Code as a supported AI provider.
    • Added browser-based account login and optional local CLI credential import.
    • Added live model discovery with a default model and support for model aliases.
    • Added streaming responses with text, reasoning, tool calls, usage, and completion events.
    • Added support for workspace metadata, parallel tool calls, and extended output limits.
    • Added Command Code provider branding and icons in the interface.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review readiness checklist

This 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.

  • ⬜ 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.

0/4 boxes ticked.

This PR stays in draft until every box above is ticked.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

⚠️ UI screenshot required

This pull request mentions gui in its title or description, so it is treated as a GUI change.

@hanbinnoh Please add a screenshot of the UI change to the description — drag and drop the image into the description editor, or paste a markdown image such as ![Screenshot](https://example.com/after.png). The check re-runs automatically once the description is edited.

Review readiness checklist

This pull request stays in draft until all four boxes of the readiness checklist in the description are ticked (currently 0/4).

@hanbinnoh Tick the boxes once your local CI is green, your branch is on the latest dev commit, and every correct Codex and CodeRabbit finding is fixed.

This pull request is being kept as a draft automatically. Once every issue above is resolved, it will be marked ready for review again.

@github-actions
github-actions Bot marked this pull request as draft August 5, 2026 15:39
@github-actions github-actions Bot added enhancement New feature or request intake: hygiene-blocked Deterministic PR hygiene checks failed labels Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

⚠️ Deterministic hygiene checks failed.

  • unsponsored_surface — This changes an authentication, workflow, release-automation, or dependency surface. MAINTAINERS.md requires security review for these; ask a maintainer to apply maintainer-sponsored once they have reviewed it. Paths: src/oauth/command-code.ts, src/oauth/index.ts.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8690f507-ba1b-44bd-9442-c5cef09b243b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Changes

Command Code is now a first-class OAuth provider. The change adds local CLI credential import, browser OAuth, live model discovery, authenticated agent-mode streaming, adapter routing, provider icons, and comprehensive tests.

Command Code provider

Layer / File(s) Summary
Command Code OAuth support
src/oauth/command-code.ts, src/oauth/index.ts
src/oauth/command-code.ts:1-149 adds local credential import, state-validated callbacks, timeout and abort handling, and API-key refresh. src/oauth/index.ts:164-171, 734-752, 861 registers the provider and migrates the legacy static model catalog to live discovery.
Provider registry and adapter routing
src/providers/registry.ts, src/server/adapter-resolve.ts
src/providers/registry.ts:802-824 adds live model discovery, a default model, a 64,000-token output limit, and parallel tool-call support. src/server/adapter-resolve.ts:8, 61-62 routes command-code configurations to the adapter.
Authenticated streaming adapter
src/adapters/command-code.ts
src/adapters/command-code.ts:1-182 serializes requests and translates NDJSON responses into text, reasoning, tool-call, completion, usage, and error events.
Catalog and integration validation
gui/src/provider-icons.ts, tests/command-code-provider.test.ts, tests/provider-registry-parity.test.ts, tests/provider-workspace-data.test.ts
gui/src/provider-icons.ts:66-67 adds both Command Code display IDs. Tests cover OAuth parity, callback validation, discovery, request construction, streaming events, featured-provider parity, and catalog membership.

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

Sequence Diagram(s)

sequenceDiagram
  participant OAuthController
  participant CommandCodeOAuth
  participant CommandCodeCallbackServer
  OAuthController->>CommandCodeOAuth: start loginCommandCode()
  CommandCodeOAuth->>CommandCodeCallbackServer: start callback server
  CommandCodeCallbackServer->>CommandCodeOAuth: return validated callback
  CommandCodeOAuth->>OAuthController: return OAuthCredentials
Loading
sequenceDiagram
  participant ProviderAdapter
  participant CommandCodeAgentModeEndpoint
  participant NDJSONParser
  ProviderAdapter->>CommandCodeAgentModeEndpoint: send authenticated streaming request
  CommandCodeAgentModeEndpoint->>NDJSONParser: stream NDJSON events
  NDJSONParser->>ProviderAdapter: emit normalized adapter events
Loading

Possibly related PRs

  • lidge-jun/opencodex#923: Adds the earlier Command Code provider preset that this change extends with OAuth and streaming adapter support.
  • lidge-jun/opencodex#652: Defines the registry-owned live model-discovery contract used by the Command Code provider.
  • lidge-jun/opencodex#480: Refactors provider icon handling touched by the new Command Code catalog mappings.

Suggested reviewers: wibias, ingwannu, lidge-jun

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: adding the Command Code OAuth provider.
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.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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 `@gui/src/provider-icons.ts`:
- Around line 66-67: Move the “Command Code” display text out of
PROVIDER_DISPLAY_NAMES by adding one shared key to PROVIDER_DISPLAY_NAME_KEYS,
then define that key’s localized value in each locale file and reference it
wherever both command-code provider identifiers are displayed.

In `@src/adapters/command-code.ts`:
- Around line 61-75: Update createCommandCodeAdapter and commandCodeConfig to
resolve process.cwd() once inside a guarded flow with a safe fallback, then
reuse that value everywhere request metadata is built. The issue is that
commandCodeConfig and the x-project-slug path both call process.cwd() outside
the existing readdirSync protection, so a removed or renamed working directory
can still throw ENOENT. Fix it by centralizing the cwd lookup in the adapter,
omitting directory-derived fields such as workingDir and x-project-slug when the
cwd is unavailable, and keeping the rest of the request construction unchanged.

In `@src/oauth/command-code.ts`:
- Around line 112-131: Update loginCommandCode so it checks ctrl.signal?.aborted
before any local credential import or createCallbackServer work, and immediately
rejects or throws using the signal’s existing reason instead of proceeding to
the timeout path. Keep the current abort listener for in-flight cancellations,
but add a regression test that invokes loginCommandCode with an already-aborted
signal and verifies it fails right away without leaving the callback server
waiting for LOGIN_TIMEOUT_MS.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d55d8757-991c-40b0-a675-cf19264bf213

📥 Commits

Reviewing files that changed from the base of the PR and between aaa7196 and 49bc0b6.

📒 Files selected for processing (9)
  • gui/src/provider-icons.ts
  • src/adapters/command-code.ts
  • src/oauth/command-code.ts
  • src/oauth/index.ts
  • src/providers/registry.ts
  • src/server/adapter-resolve.ts
  • tests/command-code-provider.test.ts
  • tests/provider-registry-parity.test.ts
  • tests/provider-workspace-data.test.ts

Comment thread gui/src/provider-icons.ts Outdated
Comment on lines +66 to +67
"command-code": "Command Code",
commandcode: "Command Code",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Move the display names into the locale files.

Lines 66-67 add user-visible strings to PROVIDER_DISPLAY_NAMES. Add one shared key to PROVIDER_DISPLAY_NAME_KEYS and define its value in the locale files instead.

As per path instructions, “user-visible strings go through the i18n locale files rather than hardcoded text.”

🤖 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 `@gui/src/provider-icons.ts` around lines 66 - 67, Move the “Command Code”
display text out of PROVIDER_DISPLAY_NAMES by adding one shared key to
PROVIDER_DISPLAY_NAME_KEYS, then define that key’s localized value in each
locale file and reference it wherever both command-code provider identifiers are
displayed.

Source: Path instructions

Comment thread src/adapters/command-code.ts Outdated
Comment on lines +61 to +75
function commandCodeConfig(): Record<string, unknown> {
let structure: string[] = [];
try { structure = readdirSync(process.cwd()).filter(name => !name.startsWith(".")); } catch { /* cwd may disappear */ }
return {
workingDir: process.cwd(),
date: new Date().toISOString().slice(0, 10),
environment: process.platform,
structure,
isGitRepo: false,
currentBranch: "",
mainBranch: "",
gitStatus: "",
recentCommits: [],
};
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
git ls-files | grep -F 'src/adapters/command-code.ts' || true

echo "== file outline =="
ast-grep outline src/adapters/command-code.ts --view expanded || true

echo "== relevant source =="
sed -n '1,220p' src/adapters/command-code.ts

echo "== usages of commandCodeConfig/cwd =="
rg -n "commandCodeConfig|process\.cwd\(|readdirSync" src/adapters/command-code.ts src || true

Repository: lidge-jun/opencodex

Length of output: 16493


🌐 Web query:

Bun Node.js process.cwd behavior when current working directory is deleted renamed fs.ErrNoSuchFile

💡 Result:

When the current working directory (CWD) of a Node.js or Bun process is deleted, renamed, or otherwise becomes inaccessible, calling process.cwd will typically throw an ENOENT error [1][2][3]. In both Node.js and Bun, the behavior is rooted in the fact that process.cwd relies on the underlying operating system's getcwd system call [4][5][2]. When the directory is removed, this system call fails because the path to the current location is no longer valid, resulting in an ENOENT (no such file or directory) error [4][1][2]. Key Behavioral Details: 1. Bun's Behavior: Historically, Bun had issues where deleting the CWD caused crashes or inconsistent behavior in certain scenarios, such as when using Bun Shell [6] or compiled binaries [4]. Recent updates have improved this, ensuring that Bun behaves more predictably—typically by throwing a proper ENOENT error rather than crashing [4][5]. Bun has also been updated to ensure that process.cwd accurately re-queries the kernel after a process.chdir call, allowing it to correctly observe if the new CWD has been removed or renamed [5]. 2. Node.js Behavior: Node.js has consistently maintained that throwing an error is the correct, secure behavior when the CWD disappears, as it avoids presenting potentially misleading information [3]. Recent versions of Node.js have focused on improving the clarity of the error message to explicitly inform users that the failure is likely due to the CWD being removed while the process was still running [2][7][8]. If you encounter this error in your application, it usually means your process is currently executing in a directory that no longer exists on the filesystem. This is common in automated environments or CI/CD pipelines where directories are dynamically created and cleaned up. The standard resolution is to ensure the process changes its working directory to an existing path (e.g., via process.chdir('/')) before attempting operations that rely on the CWD [9].

Citations:


Handle a removed working directory before building Command Code request metadata.

process.cwd() in src/adapters/command-code.ts:65 and src/adapters/command-code.ts:150 is outside the readdirSync catch block. If the directory is removed or renamed concurrently with createCommandCodeAdapter, both calls can throw ENOENT and fail request construction before the upstream fetch. Resolve the working directory once with a safe fallback; omit directory-derived metadata like workingDir or x-project-slug when it is unavailable.

🤖 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 `@src/adapters/command-code.ts` around lines 61 - 75, Update
createCommandCodeAdapter and commandCodeConfig to resolve process.cwd() once
inside a guarded flow with a safe fallback, then reuse that value everywhere
request metadata is built. The issue is that commandCodeConfig and the
x-project-slug path both call process.cwd() outside the existing readdirSync
protection, so a removed or renamed working directory can still throw ENOENT.
Fix it by centralizing the cwd lookup in the adapter, omitting directory-derived
fields such as workingDir and x-project-slug when the cwd is unavailable, and
keeping the rest of the request construction unchanged.

Comment thread src/oauth/command-code.ts
Comment on lines +112 to +131
export async function loginCommandCode(ctrl: OAuthController, options: CommandCodeLoginOptions = {}): Promise<OAuthCredentials> {
if (shouldImportLocalCommandCodeAuth(options)) {
const local = await importLocalCommandCodeAuth();
if (local) {
ctrl.onProgress?.("Imported existing Command Code CLI authentication.");
return local;
}
}
const state = randomState();
const { server, callback } = createCallbackServer(state);
const callbackUrl = `http://localhost:${server.port}/callback`;
const authUrl = `${COMMAND_CODE_STUDIO_URL}/studio/auth/cli?callback=${encodeURIComponent(callbackUrl)}&state=${encodeURIComponent(state)}`;
ctrl.onAuth?.({ url: authUrl, instructions: "Sign in with Command Code in the browser." });
ctrl.onProgress?.("Waiting for Command Code authentication...");
let timeoutId: ReturnType<typeof setTimeout> | undefined;
try {
const timeout = new Promise<never>((_, reject) => {
timeoutId = setTimeout(() => reject(new Error("Command Code OAuth callback timed out")), LOGIN_TIMEOUT_MS);
ctrl.signal?.addEventListener("abort", () => { if (timeoutId) clearTimeout(timeoutId); reject(ctrl.signal?.reason); }, { once: true });
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Reject an already-aborted login immediately.

At Line 130, addEventListener("abort", ...) does not run when ctrl.signal was already aborted. The login then keeps the callback server open until the 120-second timeout.

Check ctrl.signal?.aborted before local credential I/O and before starting the callback server. Add a regression test that passes an already-aborted signal.

🤖 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 `@src/oauth/command-code.ts` around lines 112 - 131, Update loginCommandCode so
it checks ctrl.signal?.aborted before any local credential import or
createCallbackServer work, and immediately rejects or throws using the signal’s
existing reason instead of proceeding to the timeout path. Keep the current
abort listener for in-flight cancellations, but add a regression test that
invokes loginCommandCode with an already-aborted signal and verifies it fails
right away without leaving the callback server waiting for LOGIN_TIMEOUT_MS.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 49bc0b657d

ℹ️ 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".

Comment thread src/adapters/command-code.ts Outdated
params: {
model: COMMAND_CODE_MODEL_ALIASES[parsed.modelId] ?? parsed.modelId,
messages: wireMessages(parsed.context.messages),
tools: wireTools(parsed.context.tools),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor tool_choice before advertising Command Code tools

When a request sets tool_choice: "none" or an allowed_tools subset, this still serializes every tool into params.tools and sends no equivalent choice constraint. In tool-disabled or forced-final turns, Command Code can therefore return a tool call the client explicitly disallowed, and the bridge may surface/execute it. Filter/drop the advertised tools and forward the provider's choice equivalent before building the request.

AGENTS.md reference: src/AGENTS.md:L19-L19

Useful? React with 👍 / 👎.

Comment thread src/adapters/command-code.ts Outdated
body: JSON.stringify(body),
};
},
async *parseStream(response: Response, _budget: TranslatorBudget): AsyncGenerator<AdapterEvent> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Enforce translator budgets while parsing streams

This parser accepts a TranslatorBudget but never uses it, while ndjson() accumulates buffer until a newline and tool-call inputs are stringified into emitted deltas. If Command Code or a proxy sends a very large/unterminated NDJSON line or huge tool arguments, this path can allocate unbounded memory instead of producing the bounded translation failure that the other adapters provide. Please charge/release the budget around stream buffering and retained events.

AGENTS.md reference: src/AGENTS.md:L17-L19

Useful? React with 👍 / 👎.

Comment thread src/providers/registry.ts
noVisionModels: ["grok-build-0.1", "grok-composer-2.5-fast"],
},
{
id: "command-code",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Update Command Code docs for OAuth login

This adds a user-facing command-code OAuth account provider, but the provider guide still documents only the API-key Provider plan and says CLI auth bridging for Go/Pro subscriptions is not available. Users following docs-site/src/content/docs/guides/providers.md and the translated copies will miss ocx login command-code or choose the wrong setup path, so update the English source and locales with the new account flow.

AGENTS.md reference: AGENTS.md:L231-L232

Useful? React with 👍 / 👎.

Comment thread src/adapters/command-code.ts Outdated
max_tokens: parsed.options.maxOutputTokens ?? provider.defaultMaxOutputTokens ?? 64_000,
stream: true,
...(parsed.options.temperature !== undefined ? { temperature: parsed.options.temperature } : {}),
...(parsed.options.reasoning && parsed.options.reasoning !== "none" ? { reasoning_effort: parsed.options.reasoning } : {}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Strip unsupported reasoning effort before Command Code calls

The registry intentionally exposes reasoningEfforts: [] for this provider, but this still forwards any requested parsed.options.reasoning except none. For normal Codex turns that carry a default effort, models whose Command Code catalog does not support an effort knob can receive an unsupported reasoning_effort even though the picker hid effort control; use the shared effort mapper/config checks and omit the field when the configured ladder is empty.

Useful? React with 👍 / 👎.

out.push({ role: "tool", content: [{
type: "tool-result",
toolCallId: message.toolCallId,
toolName: namespacedToolName(message.toolNamespace, message.toolName),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve images returned by tools

When a tool result contains image parts, this conversion calls textContent() and drops every non-text part before sending the result upstream. A turn that uses view_image or any image-returning MCP tool will therefore continue with only the text portion of the tool result, leaving the model unable to inspect the image output; mirror the existing adapter pattern that carries tool-result images forward instead of filtering them out.

AGENTS.md reference: src/AGENTS.md:L19-L19

Useful? React with 👍 / 👎.

Comment thread src/oauth/command-code.ts Outdated
}
const state = randomState();
const { server, callback } = createCallbackServer(state);
const callbackUrl = `http://localhost:${server.port}/callback`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reuse the shared OAuth callback fallback path

This custom callback flow binds only IPv4 127.0.0.1 but advertises localhost, and it never races ctrl.onManualCodeInput; on Windows where localhost resolves to ::1 first, or in remote/headless GUI sessions where the browser cannot reach the proxy loopback, Command Code login will wait until timeout instead of using the existing IPv6/manual paste fallback. Please route this through the shared OAuth callback flow or add the same fallback behavior here.

Useful? React with 👍 / 👎.

Comment thread src/adapters/command-code.ts Outdated
name: "command-code",
buildRequest(parsed: OcxParsedRequest): AdapterRequest {
if (!provider.apiKey) throw new Error("Command Code credential missing — run ocx login command-code");
const system = parsed.context.systemPrompt?.join("\n\n") ?? "";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Neutralize Codex identity in Command Code prompts

This sends Codex's system prompt to Command Code unchanged, but that prompt includes the native GPT/OpenAI identity text that the other routed adapters rewrite before calling non-OpenAI models. When users pick Command Code-hosted DeepSeek, Kimi, GLM, or other non-OpenAI models, the model can be instructed to present itself as GPT/OpenAI; run the system text through the same routed-model identity rewrite before serializing it.

Useful? React with 👍 / 👎.

Comment thread src/providers/registry.ts Outdated
// Command Code documents effort support as model-dependent. Do not synthesize a ladder.
reasoningEfforts: [],
defaultMaxOutputTokens: 64_000,
parallelToolCalls: true,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor parallel_tool_calls=false for Command Code

The registry advertises Command Code as supporting parallel tool calls, so Codex may send parallel_tool_calls:false on turns that require serialized tool use, but the adapter never reads parsed.options.parallelToolCalls or sends a disable flag. In those turns Command Code can still emit multiple simultaneous tool calls despite the caller's constraint; either forward the provider's equivalent flag or avoid advertising parallel support.

AGENTS.md reference: src/AGENTS.md:L19-L19

Useful? React with 👍 / 👎.

@Wibias

Wibias commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

[GD] Verdict: gated

TLDR

  • PR: feat: add Command Code OAuth provider #1066 — feat: add Command Code OAuth provider
  • Head: 4b95fdb0a on dev (mergeStateStatus: UNSTABLE)
  • Decision: Useful OAuth provider work, but still draft/gated and blocked by correctness, docs, CI gates, and owner follow-ups
  • Usefulness: Real value — adds featured command-code OAuth + live model discovery alongside the existing key commandcode preset
  • Bugs: tool-result images dropped; custom OAuth callback lacks shared IPv6/manual-paste fallback; docs still deny CLI auth bridging; open bot findings remain
  • Security: medium residual — workspace structure/cwd metadata sent upstream; auth surface needs maintainer sponsorship; no critical exploit confirmed on tip
  • Spec / standards: docs/spec drift on OAuth login; readiness checklist unticked; missing GUI screenshot for provider UI change
  • Reviews: 11 unresolved bot threads (CodeRabbit + Codex); no owner/maintainer human threads
  • Base / CI: 0 behind dev; failing enforce-target (missing UI screenshot) and hygiene (unsponsored_surface); no full test matrix on draft head
  • Gate: draft + WIP readiness checklist incomplete + hygiene-blocked
  • Owner actions (foreign PR): mark ready only after fixes; update docs; fix adapter/OAuth gaps; attach GUI screenshot; request maintainer security sponsorship; apply listed simplification candidates if desired
  • Bottom line: Do not ship yet. Keep draft until owner fixes the correctness/docs/CI items below; foreign PR so no code was pushed from this review.
Full verdict

Semantic propagation

  • Concepts audited: Command Code OAuth provider surface; dual key/OAuth catalog identity; reasoning-effort ladder; adapter capability contract; GUI display name / icon catalog
  • Authoritative sources: src/providers/registry.ts (command-code OAuth + commandcode key entries); src/oauth/index.ts OAUTH_PROVIDERS; live /provider/v1/models discovery; official profile effort table in src/providers/command-code-efforts.ts
  • Producers and consumers checked: adapter resolve, OAuth login/refresh, model discovery request builder, GUI featured preset projection, provider-icons display keys, focused tests
  • Public/derived representations checked: registry notes, docs-site providers guide (EN + locales), GUI i18n keys, featured provider list, adapter wire shape
  • Material variant partitions checked: OAuth account vs key Provider plan; models with official efforts vs unknown live models; tool_choice none/required/allowed; aborted vs in-flight login cancel
  • Positive and negative assertions checked: no static OAuth model list; unsupported efforts omitted; tool_choice none filters tools; already-aborted login rejects; effort rejection refresh path
  • Unmapped surfaces: docs still document only key Provider plan and deny CLI bridging while code adds OAuth; no provider icon asset/alias for command-code
  • Unproven equivalence assumptions: none material beyond upstream proprietary generate wire (not fully parity-tested against all Codex tool/image paths)
  • Representation mismatches: docs/registry key note say CLI auth bridging unavailable; OAuth path implements CLI import + browser auth
  • Variant coverage gaps: tool-result image parts; manual OAuth paste / dual-stack callback; docs locales not updated for OAuth
  • Axis verdict: blocked

Linked: none

Usefulness

Useful. This is a real provider integration: OAuth login with optional local CLI import, proprietary generate adapter, live model discovery without a static fallback catalog, reasoning-effort profile facts, GUI display name keys, and focused tests. Claimed live local validation is author-side only and not reproducible here.

Bugs / correctness

  • Method: bug-review.md — Bugbot: n/a-unavailable (Codex host); complementary lenses: done; trio: done in-session
  • Local focused tests on 4b95fdb0a after install: tests/command-code-provider.test.ts 11 pass; tests/provider-registry-parity.test.ts pass including Command Code seed; tests/provider-workspace-data.test.ts pass after gui deps
  • Findings (blocking / high-confidence):
    1. Tool-result images droppedsrc/adapters/command-code.ts toolResult path uses textContent() only. Other adapters (openai-chat / anthropic) preserve tool images. view_image / image MCP results lose visual content. Confidence: high.
    2. OAuth callback path incomplete vs shared infrastructuresrc/oauth/command-code.ts uses a one-off Bun.serve on 127.0.0.1 only and does not race ctrl.onManualCodeInput. Shared OAuthCallbackFlow binds dual-stack and supports manual paste for headless/Windows/remote cases. Confidence: high for reliability.
    3. Docs / product-contract driftdocs-site/.../providers.md and key preset note still say CLI auth bridging is not available, while this PR adds ocx login command-code + local ~/.commandcode/auth.json import. Confidence: high.
    4. Missing GUI screenshot / readiness — enforce-target fails missing UI screenshot; PR body checklist unticked; still draft.
  • Findings (secondary / still valid bot items):
    • CodeRabbit: already-aborted login is fixed on tip (test present) — thread stale/outdated relative to harden commit.
    • CodeRabbit: display-name i18n already uses PROVIDER_DISPLAY_NAME_KEYS + locales on tip — thread stale/outdated.
    • CodeRabbit: cwd guard already wrapped in currentWorkingDirectory() try/catch on tip — residual nit only if concurrent unlink races readdir separately.
    • Codex: translator budget is used in current ndjson / tool-call path — earlier budget finding is largely addressed; keep monitoring large-line edge cases.
    • Codex: identity rewrite via identifyRoutedModel is present — identity finding outdated.
    • Codex: tool_choice filtering via visibleTools is present — tool_choice finding outdated for none/allowed; still no parallel_tool_calls wire flag (registry correctly sets parallelToolCalls: false).
    • Codex: unsupported effort stripping is present via supportedCommandCodeEffort — outdated as stated.
  • Fixed this session: none (foreign PR; no push)

Security

  • Scope reviewed: authn/oauth callback, secrets/local CLI import, outbound fixed hosts, AI agent tool surface, workspace metadata in generate config, supply-chain fixed endpoints, data_storage of apiKey as access/refresh
  • Decision: Do not ship yet
  • Risk: Medium residual
  • Findings:
    1. Auth surface unsponsored — hygiene unsponsored_surface correctly blocks until a maintainer applies maintainer-sponsored after security review.
    2. Workspace metadata disclosure — adapter sends absolute workingDir and top-level directory structure (non-dot names) in the generate config payload plus x-project-slug. This may be intentional for Command Code workspace context, but it is privacy-sensitive and should be documented / optional / minimized.
    3. Local CLI import — reads ~/.commandcode/auth.json and validates with /alpha/whoami; forceLogin disables import (good). Callback CORS locked to studio origin; state checked (good). Refresh is a no-op rewrap of the same API key (document expiry model).
    4. No dependency/lockfile changes; no workflow permission changes.
  • Fixed this session: none
  • AI-agent note: tool catalog is filtered for tool_choice: none; identity neutralization applied; residual risk is tool-result image omission and unadvertised parallel tool behavior rather than open tool execution authz bypass.

Spec / standards

  • Spec source: PR body + existing providers guide + registry notes
  • Gaps:
    • User-facing OAuth behavior not reflected in docs-site EN or locales
    • Key preset note still claims CLI bridging unavailable
    • PR readiness checklist incomplete; draft gate active
    • GUI change without screenshot in description (repo enforce-target rule)
    • Featured OAuth count / parity tests updated, but no icon alias/asset for Command Code branding claimed in CodeRabbit summary

Reviews

  • Owners/maintainers: none open
  • Bots: 11 unresolved threads on tip GraphQL snapshot (3 CodeRabbit, 8 Codex). Several are already fixed by 4b95fdb0a (abort, i18n keys, identity, tool_choice none, effort strip, budget wiring) and should be re-checked/resolved after owner push; remaining real open items: docs OAuth update, tool-result images, shared OAuth callback/manual paste, optional icon asset, screenshot/hygiene sponsorship.

Base / CI

  • Behind/conflicts: clean vs dev (0 behind, 2 ahead); mergeable but UNSTABLE
  • Required/visible checks: enforce-target FAILURE (missing UI screenshot); hygiene FAILURE (unsponsored_surface); label SUCCESS; CodeRabbit SUCCESS with draft-skipped full review; no platform test matrix results on this draft head
  • Local tip compile/tests: focused Command Code + registry + provider-workspace tests green after local bun install / gui bun install

Simplification (for the PR owner)

Foreign PR — nothing edited or pushed. Bounded candidates only:

  1. src/oauth/command-code.ts custom callback server

    • Problem: reimplements loopback listen/timeout without shared dual-stack + manual paste behavior
    • Change: reuse OAuthCallbackFlow / shared callback helpers where Command Code’s POST JSON callback can fit, or at least add onManualCodeInput race + ::1 bind
    • Preserve: state validation, CORS allowlist, local CLI import policy, port 5959 preference
    • Risk: medium (auth UX)
    • Validate: login abort test + manual paste / Windows localhost cases
  2. src/adapters/command-code.ts request metadata helpers

    • Problem: cwd/config/header slug logic is clear enough; optional small extract of slug sanitizer only if duplicated later
    • Change: only if callback refactor lands; do not chase line count
    • Risk: low
    • Validate: buildRequest unit tests
  3. No other high-confidence simplify worth doing before correctness fixes.

Gate

draft | incomplete readiness checklist | workflow: hygiene-blocked | missing screenshot | unsponsored auth surface

Bottom line

Ship only after @hanbinnoh (owner) addresses tool-result images, OAuth callback robustness, docs/OAuth product copy, GUI screenshot, and maintainer security sponsorship. This review did not push to the fork head. Re-request full review on the next tip.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request intake: hygiene-blocked Deterministic PR hygiene checks failed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants