Skip to content

feat: support Codex CLI login for the openai provider - #18

Merged
Suprhimp merged 2 commits into
masterfrom
support-cli-login-auth
Jul 2, 2026
Merged

feat: support Codex CLI login for the openai provider#18
Suprhimp merged 2 commits into
masterfrom
support-cli-login-auth

Conversation

@Suprhimp

@Suprhimp Suprhimp commented Jul 2, 2026

Copy link
Copy Markdown
Member

Summary

Lets DUUL use OpenAI Codex CLI login for the openai provider — no OPENAI_API_KEY required. When no explicit key is set, DUUL falls back to ~/.codex/auth.json (override with CODEX_HOME):

  • Sign in with ChatGPT (Plus/Pro/Team): uses the OAuth access token against the ChatGPT backend Responses endpoint (https://chatgpt.com/backend-api/codex), billed to the ChatGPT plan. Tokens auto-refresh on expiry and on a mid-review 401.
  • API-key login: uses the OPENAI_API_KEY stored in auth.json.

An explicit env var or per-request api_key always takes precedence over the CLI login.

How it works

The ChatGPT backend is stateless (store: false), so the provider:

  • streams the request and aggregates output items from the stream (the backend leaves response.completed.output empty),
  • resends the full input across tool rounds (echoing encrypted reasoning),
  • drops params the backend rejects (temperature, top_p, max_output_tokens, previous_response_id),
  • preserves cross-round context by replaying prior turns (new conversationReplay provider capability — same mechanism as the Anthropic provider), so previous_review_id keeps working.

DUUL_REASONING_EFFORT (default medium) tunes reasoning effort. Model is limited to plan-exposed slugs (default gpt-5.4).

Capability semantics cleanup

previousResponseId now means native server-side chaining only (OpenAI api-key mode); replay-based continuity is the new conversationReplay. Anthropic → previousResponseId=false, conversationReplay=true.

Testing

  • 94 unit tests pass — new: codex-auth.test.ts (JWT/expiry/refresh perms+failure+fallback), openai-capabilities.test.ts (per-mode capability flags), reviewer-continuity.test.ts (continuityPlan, store roundtrip, workspace-switch isolation).
  • Live-verified against the real ChatGPT backend on a Plus account: structured output, tool-calling, 8-round tool loop, and cross-round memory recall.
  • Validated via DUUL itself — plan reviewed over ChatGPT login across 5 rounds to a final APPROVE (conf 0.95); each round exercised previous_review_id replay.

Files

  • New: src/services/providers/codex-auth.ts
  • Changed: openai.ts, reviewer.ts, types.ts, anthropic.ts, google.ts, README.md/README.ko.md, changeset

🤖 Generated with Claude Code

Suprhimp and others added 2 commits July 2, 2026 13:16
Fall back to OpenAI Codex CLI credentials (~/.codex/auth.json, override
with CODEX_HOME) when no OPENAI_API_KEY/api_key is set. Two modes:

- Sign in with ChatGPT: use the OAuth access token against the ChatGPT
  backend Responses endpoint (chatgpt.com/backend-api/codex), billed to
  the ChatGPT plan. Tokens auto-refresh on expiry and on a mid-review 401.
- API-key login: use the OPENAI_API_KEY stored in auth.json.

The ChatGPT backend is stateless (store: false): stream the request,
aggregate output items from the stream, resend the full input (echoing
encrypted reasoning) across tool rounds, and drop unsupported params
(temperature, top_p, max_output_tokens, previous_response_id). Model is
limited to plan-exposed slugs (default gpt-5.4).

Cross-round continuity is preserved by replaying prior rounds' turns via
a new conversationReplay provider capability (same mechanism as the
Anthropic provider), so previous_review_id keeps working. Explicit
env/request keys always take precedence over the CLI login.

Add DUUL_REASONING_EFFORT (default medium) to tune reasoning effort.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Addresses blocking issues raised over five DUUL plan-review rounds:

- reviewer: clear the conversation memoryCache on workspace switch so one
  workspace's turns are never flushed into or replayed from another's
  .duul/conversations.json.
- codex-auth: when a ChatGPT token is expired, fall back to a stored
  OPENAI_API_KEY if refresh is unavailable or fails, instead of returning
  a credential that will 401.
- codex-auth: chmodSync(auth.json, 0600) after refresh — the writeFileSync
  mode option only applies on create, not overwrite.
- capabilities: previousResponseId now means NATIVE server-side chaining
  only (OpenAI api-key mode); replay-based continuity is conversationReplay.
  Anthropic set to previousResponseId=false/conversationReplay=true.
- reviewer: extract pure continuityPlan() helper for the load/warn decision.

Tests (94 total): OpenAI capability flags per mode, codex-auth refresh
perms/failure/fallback, continuityPlan cases, conversation store roundtrip,
and workspace-switch isolation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Suprhimp
Suprhimp merged commit 19b5420 into master Jul 2, 2026
1 check passed
@Suprhimp Suprhimp mentioned this pull request Jul 2, 2026
@Suprhimp
Suprhimp deleted the support-cli-login-auth branch July 3, 2026 07:37
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