dsh-codex-suite
Maintenance: Activedamonbao/dsh-codex-suite
OpenAI Codex provider for DeepSeek Harness with ChatGPT OAuth, native settings, and account usage.
$ dsh plugin add dsh-codex-suiteInstall
dsh has no central install command — add this plugin’s entry (documented in its README below) to your profile or patch config, then restart.
How installs work5
stars
1
forks
TypeScript
Language
MIT
License
2026-08-14
Created
2026-09-20
Last push
README
DSH Codex Suite
English | 简体中文
A suite of DeepSeek Harness (DSH) plugins that brings ChatGPT/OpenAI Codex models and a Codex-style conversation experience to the DSH Web UI. Built against DSH 0.1.6-alpha.2 (peer range >=0.1.6-alpha.2 <0.1.7-0).
The repository is a pnpm monorepo containing two independent runtime plugins and one pure bundle package:
| Package | Kind | What it does |
|---|---|---|
@jcy2387/dsh-codex-provider |
Runtime plugin | Registers the openai-codex provider with ChatGPT OAuth login, proactive token refresh, usage dashboard, proxy-aware networking, and a native Settings page. |
@jcy2387/dsh-conversation-ui |
Runtime plugin | Re-renders the Web chat as a Codex-style event stream: turn folding, semantic tool activity, streaming reveal, deliverables, and smooth viewport follow. |
@jcy2387/dsh-suite |
Pure bundle | No runtime code — a single profile patch that installs both plugins at once. |
The two plugins are fully decoupled: the Conversation UI works with any model, and the Codex Provider works with the stock chat UI.
Why this suite
Codex Provider — reliable ChatGPT access without an API key
- ChatGPT OAuth, both flows. Browser-based login with device-code fallback. Login failures are classified into secret-free, localized reasons (region restrictions, callback port conflicts, token exchange errors, network issues…) instead of raw stack traces.
- IPv6 loopback callback bridge. pi-ai's OAuth listener only binds IPv4; on IPv6-preferred hosts the suite transparently relays the loopback callback, so login still works.
- Proactive token refresh. Access tokens rotate ~5 minutes before expiry with retry backoff; a dead refresh token is detected precisely and surfaces as reconnect required instead of failing mid-stream.
- Usage dashboard. Plan (shown under its user-facing name such as Plus, Pro 5x, or Pro 20x), credits, and primary/secondary rate-limit windows with used-percent bars and reset times, fetched from the account-scoped ChatGPT endpoint.
- Banked rate-limit resets. View how many resets the account has banked and their earliest expiry, then redeem one from a confirmation dialog to restore the 5-hour and weekly limit windows.
- Proxy-aware networking. Auto-detects environment and system proxies (macOS / Windows / Linux), routes only OpenAI traffic through them, keeps loopback direct, and exposes an explicit proxy mode (auto / environment / off).
- Reliability-first defaults. SSE transport by default (no partial-output duplication on WebSocket failure), 5-minute stream idle timeout, configurable retry policy.
- Native Settings page at Settings → OpenAI Codex with zh/en localization, live status, and a loopback-only RPC boundary — credentials never leave the Host.
Conversation UI — the chat rendered like Codex CLI
- One ordered event stream. Process updates, thinking, tool calls, retries, workflows, compaction, and commands appear in natural order within each turn.
- Turn folding. A turn starts with an elapsed timer and a thinking placeholder; once the final answer lands, the process section collapses automatically (expandable, with a durable auto-expand thinking preference).
- Semantic tool icons. Search, file read/edit, shell, database, web, skill, and agent tools each get a distinct icon so activity is scannable at a glance.
- Two reveal modes.
teleprompter(default): instant snapshots gliding upward;typewriter: grapheme-safe progressive reveal. Three smoothing presets (realtime/balanced/silky) tune the cadence. - Smart viewport follow. New content is followed within bounded scroll speeds; scrolling up releases the follow, returning to the bottom resumes it. Respects
prefers-reduced-motionand degrades gracefully under low frame rates. - Deliverables card. Each finished turn lists produced files and websites with added/removed line counts.
Installation
Prerequisites: DeepSeek Harness (dsh) >=0.1.6-alpha.2 <0.1.7-0 with the web profile, Node.js ^22.19 || >=24, pnpm 11.
Install the whole suite (recommended):
dsh plugin --profile web add @jcy2387/dsh-suite@0.1.6-alpha.2
dsh web
Or install plugins individually:
dsh plugin --profile web add @jcy2387/dsh-codex-provider@0.1.6-alpha.2
dsh plugin --profile web add @jcy2387/dsh-conversation-ui@0.1.6-alpha.2
dsh web
Local development — link a workspace package instead of the published one:
dsh plugin --profile web add link:$PWD/packages/codex-provider
dsh plugin --profile web add link:$PWD/packages/conversation-ui
dsh web
Install either the suite or the individual plugins in a given profile — not both copies of the same plugin. Coexistence does not crash (the suite mounts its plugins inside a nested loader group, which avoids duplicate loader entry ids), but a direct install and the suite's copy share one loader entry: removing either side from the bundle list of a running dsh process silently stops that plugin until the next restart. Restart dsh after any bundle-list change.
Quick start
- Install the suite (see above) and open the Web UI (
dsh web). - Go to Settings → OpenAI Codex, click Connect, and choose Browser login (or Device login on a headless/remote machine). Complete the ChatGPT authorization.
- Back in the chat, pick an
openai-codexmodel in the model selector and start talking. - Optional: review the usage panel in the same settings page, and tune the conversation stream in Plugins → DSH Codex Suite (or Conversation UI).
Configuration
Both plugins are configured through the profile's cordis.patch.yml overlay; user-level preferences live in the Settings UI and persist across restarts.
Codex Provider (profile patch ID: codex-provider)
| Option | Values | Default | Notes |
|---|---|---|---|
transport |
sse | websocket | websocket-cached | auto |
sse |
SSE avoids duplicating partial output if a stream fails late. |
streamIdleTimeoutMs |
positive integer | 300000 |
Max idle interval while reading one response stream. |
timeoutMs / websocketConnectTimeoutMs |
positive integer | — | Optional request-level timeouts. |
retryPolicy |
retry policy object | built-in | Request retry behavior. |
credentialRef |
credential reference | OPENAI_CODEX_OAUTH |
Harness credential slot holding the OAuth state. |
ipv6CallbackBridge |
boolean | true |
Relay the OAuth loopback callback for IPv6-only hosts. |
proactiveRefresh |
boolean | true |
Refresh tokens ahead of expiry. |
proxyMode |
auto | environment | off |
auto |
Restart-applied; also editable in the Settings page. |
Conversation UI (profile patch ID: conversation-ui)
| Option | Values | Default | Notes |
|---|---|---|---|
mode |
teleprompter | typewriter |
teleprompter |
Reveal style of assistant content. |
preset |
realtime | balanced | silky |
balanced |
Smoothing cadence. |
revealCharsPerSec |
5–200 | 80 |
Typewriter reveal rate. |
scrollSpeedPxPerSec |
1–200 | 48 |
Deprecated compatibility field; DSH owns scrolling. |
maxScrollSpeedPxPerSec |
1–2000 | 1000 |
Deprecated compatibility field; DSH owns scrolling. |
To temporarily disable the Conversation UI without uninstalling it, apply the bundled conversation-ui-off.yml overlay:
- id: conversation-ui
disabled: true
Settings surfaces
| Location | Controls |
|---|---|
| Settings → OpenAI Codex | Connect/disconnect account, login method, usage dashboard, banked-reset view and redemption, proxy mode. |
| Plugins → DSH Codex Suite (or Conversation UI) | Auto-expand thinking (live), plugin version, one-click update for npm installs. |
Architecture
Each runtime plugin ships two halves:
- Host half (Node) — Cordis plugin: provider registration, OAuth lifecycle, networking, settings persistence. Loaded from the package root.
- Web half (browser) — React views discovered through the
dsh.clientmanifest. The Codex Provider contributes the Settings section; the Conversation UI replaces the assistant node view and wraps tool rows.
The halves communicate through two narrow channels: an inline boot-config global (window.__DSH_CONVERSATION_UI_CONFIG__) injected into the served HTML carries validated plugin config to the browser, and the authenticated Connection RPC carries settings reads/writes back to the Host. Secrets (tokens, proxy URLs) never cross the RPC boundary.
Package-level docs: codex-provider · conversation-ui · suite
Development
Requirements: Node.js ^22.19.0 || >=24.0.0 and pnpm 11.7.
pnpm install
pnpm run check # typecheck + test + build + pack dry-run, same as CI
Per-package commands:
pnpm --filter @jcy2387/dsh-codex-provider check # typecheck + test + build + publint
pnpm --filter @jcy2387/dsh-conversation-ui typecheck
pnpm --filter @jcy2387/dsh-conversation-ui test
pnpm --filter @jcy2387/dsh-conversation-ui build
pnpm --dir packages/all pack --dry-run
Tests run on vitest — 15 suites covering the OAuth state machine, token refresh, network/proxy detection, usage and banked-reset parsing, the settings controllers, and the streaming client views. Client tests resolve the installed published DSH packages (a small module-table stand-in instantiates the shipped browser factory bundles). CI verifies release tags match all three package versions and audits the published tarball contents, then runs a consumer smoke test that installs the packed tarballs into a scratch project (resolving the published peer ranges against the real registry) and imports every Node-side entry point.
Release
Publishing is automated by the Release workflow (.github/workflows/release.yml), which runs whenever a GitHub Release is published. It requires the release tag to equal the shared version of all three packages (an optional v prefix is stripped), re-runs the full quality gates, packs the three tarballs, verifies the suite bundle no longer carries workspace: ranges, and publishes to npm in dependency order (provider → conversation UI → suite) with provenance via OIDC trusted publishing — no long-lived NPM_TOKEN secret is involved.
One-time setup: configure trusted publishing on npmjs.com for @jcy2387/dsh-codex-provider, @jcy2387/dsh-conversation-ui, and @jcy2387/dsh-suite, each authorizing repository DamonBao/dsh-codex-suite with workflow release.yml (no environment).
The dist-tag follows the GitHub Release's pre-release flag: a full release (checkbox unchecked) publishes under latest — including rc versions — while a pre-release publishes under the channel tag derived from the version (0.1.2-alpha.4 → alpha, 0.1.2-rc.1 → rc). The workflow is idempotent — a package whose version already exists on npm is skipped, so a re-run after a partial failure republishes only what is missing.
A typical release:
# bump the version in all three packages/*/package.json files, then:
pnpm run check
VERSION="$(node -p "require('./packages/codex-provider/package.json').version")"
git commit -am "release: $VERSION"
git tag "$VERSION"
git push origin main --tags
Then create and publish a GitHub Release for that tag. Dependabot checks GitHub Actions dependencies weekly. npm version updates are intentionally not enabled for Dependabot: it regenerates pnpm-lock.yaml without the workspace overrides, so its PRs cannot pass pnpm install --frozen-lockfile — bump dependencies manually with pnpm update.
Repository layout
.
├─ packages/
│ ├─ codex-provider/ # @jcy2387/dsh-codex-provider
│ │ ├─ src/ # Host half: OAuth, refresh, network, usage, banked resets, LLM adapter
│ │ ├─ src/client/ # Web half: Settings section UI
│ │ ├─ tests/ # 12 vitest suites
│ │ └─ cordis.patch.yml
│ ├─ conversation-ui/ # @jcy2387/dsh-conversation-ui
│ │ ├─ src/ # Host half: config bridge, settings RPC
│ │ ├─ src/client/ # Web half: stream views, cards, native-scroll bridge
│ │ ├─ tests/ # 3 vitest suites
│ │ └─ cordis.patch.yml
│ └─ all/ # @jcy2387/dsh-suite (pure bundle, no runtime code)
├─ .github/workflows/ci.yml # validate + tarball audit + consumer smoke
├─ .github/workflows/release.yml # npm publish on GitHub Release
├─ pnpm-workspace.yaml
└─ README.md / README.zh.md
Troubleshooting
- Browser login never completes — the callback bridge listens on
127.0.0.1:1455; make sure the port is free and the browser can reach loopback. The settings page classifies the exact failure (port conflict, timeout, state mismatch…). - Region not supported — OpenAI rejects the login for unsupported regions; the settings page surfaces this as a distinct reason. A proxy (
proxyMode) can change the egress route (restart required). reauth requiredafter some time — the refresh token expired or was revoked (e.g. password change). Reconnect once from the settings page.
License
MIT © jcy2387
More in Security & Auth
dsh-infinite-gen-4
by minglink
Red-team security testing toolkit for DeepSeek v4.1 Flash, with jailbreak prompts and a test suite for DeepSeek Harness.
tencentmeeting-cli
by tencentcloud
Tencent Meeting command-line tool with OAuth2 authorization for meeting, recording and attendance-report management.
dsh-auto-review
by perrylink
Second-model AI auto-review for DeepSeek Harness approval requests: a read-only reviewer subagent returns structured allow/deny verdicts with reasons, fail-closed by default, fully auditable from the session log (approval/asked -> autoReview/verdict -> approval/decided).
dsh-permission-rules
by perrylink
Claude Code-style declarative permission rules for DeepSeek Harness: ordered allow/deny/ask rules with tool-name, argument (glob/regex), and workspace-path matching on the tools/pre-execute waterfall, session-log audit, and HMR reload.
