@jcy2387/dsh-codex-provider
English | 简体中文
OpenAI Codex as an installable DeepSeek Harness (DSH) LLM provider — ChatGPT account login instead of API keys, with a native Settings page, usage dashboard, and proxy-aware networking. Part of the DSH Codex Suite monorepo.
OpenAI Codex settings in DeepSeek Harness
Features
ChatGPT OAuth, both flows
- Browser login opens the ChatGPT authorization page and completes via a loopback callback; device login (device code) covers headless or remote machines.
- Login failures are classified on the Host into secret-free, localized reasons — region restrictions, callback port conflicts, callback timeout, state mismatch, token-exchange errors, account access, network issues, and more — so the browser never sees raw (potentially sensitive) error text.
- IPv6 callback bridge: pi-ai's OAuth listener binds IPv4 only. On hosts where
localhost resolves to ::1 first, the plugin temporarily listens on the IPv6 loopback and relays the callback to pi-ai's IPv4 listener on port 1455, so browser login still works.
Proactive token refresh
- The access token rotates ~5 minutes before expiry (
marginMs, default 300_000).
- Transient refresh failures retry after 60 s, then every 300 s (
retryDelaysMs).
- A terminal refresh failure (dead refresh token:
invalid_grant, explicit expiry/revocation, 401/403) is detected precisely — server errors (5xx) and rate limits (429) stay retryable — and surfaces the reconnect required state instead of failing mid-stream or condemning a healthy token.
Usage dashboard
Fetched from the account-scoped ChatGPT endpoint (chatgpt.com/backend-api/wham/usage) and rendered in Settings:
- Plan and credits (balance, or unlimited). Plans render under their user-facing names:
plus → Plus, prolite → Pro 5x, promax / pro → Pro 20x, free → Free, and likewise for Team / Business / Enterprise / Education; unrecognized identifiers pass through unchanged so new tiers stay visible.
- Primary and secondary rate-limit windows with used-percent progress bars and localized reset times.
- A limit reached notice; auto-refreshes every 60 s while connected, plus a manual refresh button.
Banked rate-limit resets
OpenAI grants eligible accounts one-time banked resets (launch and referral promotions) that can be redeemed to restore the 5-hour and weekly limit windows:
- The usage dashboard shows the available reset count (riding the 60 s auto-refresh) and hides itself when the endpoint does not report the field; while resets exist, the same row also shows the earliest expiry (details are fetched silently whenever resets exist, falling back to the count alone on failure).
- Redeem a reset only opens a confirmation dialog — nothing is redeemed yet: the dialog lists each reset by title and expiry (earliest first) with an explicit cannot be undone warning, and redemption runs only after a second Redeem reset click.
- On confirm the Host calls the redemption endpoint (
wham/rate-limit-reset-credits/consume) with a fresh idempotency key — one request, no automatic retries, so an ambiguous network failure never spends a second credit.
- All four OpenAI result codes are localized (reset / already redeemed / nothing to reset / no credit); success silently refreshes usage and the remaining count.
- Enabled only from loopback, like every other account action.
Proxy-aware networking
- Auto-detects proxies from environment variables (
http_proxy / https_proxy / all_proxy / no_proxy) and system settings — macOS (scutil --proxy), Windows registry, and Linux (GNOME gsettings / KDE).
- Routes only OpenAI traffic (
openai.com, chatgpt.com) through the proxy via a scoped undici dispatcher; loopback stays direct and unrelated traffic is untouched.
- Explicit proxy mode setting:
auto (detect), environment (env vars only), or off (direct). The active route and any detection issue are shown in Settings; changing the mode applies after a Host restart.
Reliability-first transport
- Default transport is
sse — upstream auto falls back to SSE only before WebSocket stream events begin, so a late WebSocket failure would otherwise duplicate partial output by replaying the request.
- 5-minute stream idle timeout (configurable) bounds a hung response without killing slow thinking turns.
- Configurable request timeouts and retry policy.
Security boundaries
- OAuth state persists in the Harness credentials store (default ref
OPENAI_CODEX_OAUTH); tokens never cross the browser RPC, which is registered with loopback-only authority.
- Usage responses from OpenAI are validated and redacted before reaching the UI.
Install
dsh plugin --profile web add @jcy2387/dsh-codex-provider
dsh web
For a local development copy:
dsh plugin --profile web add link:/path/to/dsh-codex-suite/packages/codex-provider
dsh web
The plugin works in headless profiles too — the Web client half is optional; account management then happens through the browser on a loopback session.
Quick start
- Open Plugins → DSH Codex Suite → codex-provider and click Connect.
- In the login modal choose Browser login (or Device login on a remote machine) and complete ChatGPT authorization. Progress is shown live; you can cancel at any time.
- Once connected, pick an
openai-codex model in the normal model selector and start chatting.
The same settings page also shows the usage dashboard (including banked resets) and the proxy mode control while connected; available resets can be redeemed from a confirmation dialog. Account actions (connect/disconnect/reset/proxy) are only enabled when the Web UI is accessed from loopback.
Configuration
Profile patch ID: codex-provider. Set values in the profile's cordis.patch.yml overlay.
| Option | Values | Default | Notes |
|---|
transport | sse | websocket | websocket-cached | auto | sse | See Reliability-first transport above. |
streamIdleTimeoutMs | positive integer | 300000 | Max idle interval while reading one response stream. |
timeoutMs | positive integer | — | Optional overall request timeout. |
websocketConnectTimeoutMs | positive integer | — | Optional WebSocket connect timeout. |
retryPolicy | retry policy object | built-in | Request retry behavior (same schema as other DSH providers). |
credentialRef | credential reference | OPENAI_CODEX_OAUTH | Harness credential slot holding the serialized OAuth state. |
ipv6CallbackBridge | boolean | true | Relay the OAuth loopback callback for IPv6-preferred hosts. |
proactiveRefresh | boolean | true | Refresh access tokens ahead of expiry. |
proxyMode | auto | environment | off | auto | Also editable in the Settings page; applies after restart. |
Example overlay:
- id: codex-provider
name: '@jcy2387/dsh-codex-provider'
config:
transport: sse
streamIdleTimeoutMs: 300000
proxyMode: auto
Architecture
The package ships two halves:
- Host half (
src/, exported from the package root) — a Cordis plugin injecting llm, credentials, and settings. It owns the OAuth lifecycle (CodexAuthService), token refresh (CodexTokenRefresher), network manager, usage service, and banked-reset service (CodexResetService), and registers the provider through PiAiAdapter (backed by @earendil-works/pi-ai's openaiCodexProvider). The model catalog is validated at load (context window / max tokens must be usable for context budgeting and compaction).
- Web half (
src/client/, bundled to lib/client.cjs and discovered via the dsh.client manifest) — a React settings section registered into the Web UI's Settings page, localized in Chinese and English.
The halves talk over one loopback-authority RPC channel (status, network, setProxyMode, usage, reset-credits, reset-credits/consume, login, cancel, logout). Failure reasons crossing this boundary are enum values, not error text.
Development
pnpm --filter @jcy2387/dsh-codex-provider check # typecheck + test + build + publint
pnpm --filter @jcy2387/dsh-codex-provider typecheck
pnpm --filter @jcy2387/dsh-codex-provider test
pnpm --filter @jcy2387/dsh-codex-provider build
Eleven vitest suites cover the auth state machine and failure classification, the IPv6 callback bridge, terminal-vs-transient refresh detection, proxy discovery (macOS / Windows / Linux / env), usage parsing and redaction, banked-reset listing/redeeming/idempotency, the settings card controller, and the RPC contract.
See the monorepo README for workspace-wide commands.
License
MIT © jcy2387
This release targets DSH 0.1.7-rc.2. It imports openai-codex.proxyMode from settings.yaml or settings.yaml.imported into the active profile’s cordis.patch.yml, recording a marker after success and retaining the source after failure. The plugin’s compatibility import fills only missing values. Exported locale/en.json and locale/zh.json localize the name and description in DSH.