Skip to content

dsh-oauth-openai

Verified

@ekin_chen/dsh-oauth-openai · v0.2.4 · MIT · Web UI

OpenAI Codex OAuth provider and model adapter for dsh-oauth and DeepSeek Harness

Install

dsh plugin add @ekin_chen/dsh-oauth-openai

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Tags

Creators

Readme

dsh-oauth-openai

dsh-oauth-openai 是 dsh-oauth 的 OpenAI/Codex 提供方插件:通过 ChatGPT OAuth 获取 Codex 订阅凭据,把 openai-codex 模型路由注册到 DeepSeek Harness,并在派发前修正 Codex 后端不接受的请求参数。整个插件以第三方外置 bundle 安装,不需要重新构建或替换官方应用。

职责边界

  • dsh-oauth:账号页面、登录会话、机密存储、刷新锁和退出。
  • dsh-oauth-openai:OpenAI Codex OAuth 协议、账号解析、刷新、模型适配器与模型目录设置页。
  • 不复制 Codex CLI 的 auth.json,也不把 ChatGPT 订阅令牌当作 OpenAI Platform API Key。

功能

  1. ChatGPT 登录:浏览器 PKCE 回调(本机 1455 端口可用时)或设备码;凭据保存在 Harness 凭据库,自动刷新。
  2. openai-codex 模型路由:基于 pi-ai 的 openai-codex-responses 协议,支持内置目录与自定义模型行(ID、显示名称、上下文窗口、输出上限、输入能力)。
  3. 可编辑模型目录:设置页中的目录编辑器;未保存覆盖时继承 pi-ai 内置 Codex 目录,保存后整体替换,可一键恢复默认。
  4. Codex 参数兼容修复(见下文「temperature 问题」)。

安装(第三方外置)

前提:DeepSeek Harness 0.2.x(已在官方桌面端 0.2.0-rc.2 上验证)。

发行物是两个 tarball,依次安装(应用内:设置 → 插件 → 安装,依次填绝对路径):

包 内容
dist/ekin_chen-dsh-oauth-0.1.2.tgz @ekin_chen/dsh-oauth 账号基座(实现与上游 [email protected] 一致,仅适配 0.2.x 安装清单并改发到本人 scope,详见包内 VENDORED.md)
dist/ekin_chen-dsh-oauth-openai-0.2.4.tgz 本插件(@ekin_chen/dsh-oauth-openai)
dsh plugin --profile desktop add /abs/path/dist/ekin_chen-dsh-oauth-0.1.2.tgz
dsh plugin --profile desktop add /abs/path/dist/ekin_chen-dsh-oauth-openai-0.2.4.tgz

命名说明:npm 上的 dsh-oauth / dsh-oauth-openai 归属第三方(ruihuahe,MIT), 本套改发到本人 scope @ekin_chen/* 并保留署名(THIRD_PARTY_NOTICES)。注册表安装即: dsh plugin --profile desktop add @ekin_chen/dsh-oauth-openai(@ekin_chen/dsh-oauth 作为依赖自动带入)。

add 会自动把包选入 dsh.profile.bundles;profile 未启用 HMR 时,重启应用后生效。

从源码重建发行物:

pnpm install
pnpm test          # 单测与组合测试
pnpm run build
pnpm run pack:check
node scripts/vendor-dsh-oauth.mjs dist   # 重新生成 dsh-oauth 外置包

发布(维护者):npm publish dist/ekin_chen-dsh-oauth-0.1.2.tgz --access public,再 npm publish dist/ekin_chen-dsh-oauth-openai-0.2.4.tgz --access public(scoped 包默认私有,必须显式 --access public)。不要动第三方的 dsh-oauth/dsh-oauth-openai 名字。

注意:pnpm run build 会清空 dist/,先 pack:check 再 vendor-dsh-oauth。

使用

  • 设置 → OpenAI Codex:登录(浏览器 / 设备码)、账号状态与退出、模型目录编辑(增删行、从内置目录添加、保存、恢复默认)。
  • 模型选择器中选择 openai-codex/<模型 ID>;自定义模型同样出现在选择器里。

temperature 问题(Unsupported parameter: temperature)

症状:在 openai-codex 路由上,工具调用前的实验性 Auto review 会用 temperature: 0 发一次分类请求(上游 packages/experimental/auto-review 的 classifyRisk),而 ChatGPT Codex 后端不接受 temperature 字段,请求报 PI_AI_ERROR: Codex error: Unsupported parameter: temperature,工具调用被阻断。

修复:双层剥离。两层都只影响发往 Codex 线路的请求,不改变会话日志里的调用配置——

  1. 适配器层:OpenAICodexAdapter.stream() 在进入 pi-ai 前去掉 temperature(循环装配的请求保留其 loop 标记)。
  2. llm/stream 拦截层:codexTemperatureListener 对 Codex 路由的请求复制一份、去掉 temperature 后重新走同一条瀑布。即使路由仍由 llm-pi-ai 的配置接管(见下节),该层也会修复 Auto review 与任何带 temperature 的调用。

配置开关:stripRequestTemperature(默认 true)。

验证(scripts/smoke-request.mjs,真实栈 + 真实后端,A/B 对照):

strip=true   finish=stop  text="pong"                                         # 修复开启:正常
strip=false  finish=error "Codex error: Unsupported parameter: temperature"   # 修复关闭:精确复现故障

宿主约束(0.2.x)

0.2.x 宿主的 connection.rpc.handle 无法注册自定义通道:注册路径内部访问 owner.webServer 会被 Cordis 的 inject 规则拒绝(cannot get property "webServer" without inject),请求回落到 SPA 静态层并得到 HTTP 405。所有使用该 API 的第三方插件都会遇到(例如 tailscale-serve 的设置开关)。本插件因此改用 /api 共享通道的精确 Fetch 路由(connection.fetch.register),经真实 HTTP 实测:未认证 401、认证后返回标准 server-response 信封。

与内置 llm-pi-ai 路由的关系

路由与 Models 目录条目都是先到先得的注册:

  • 如果 profile 的 cordis.patch.yml 里配置了 llm-pi-ai.providers.openai-codex,内置适配器继续服务该路由。本插件会退避(日志给出迁移提示),但 llm/stream 拦截层仍然生效,temperature 问题照样修复。
  • 要让本插件接管路由(使用 dsh-oauth 账号与本插件的模型目录):删除 llm-pi-ai 的 providers.openai-codex 段,把模型行写进 设置 → OpenAI Codex。迁移后请在设置页重新登录一次本插件的账号(旧的 dsh-oauth 刷新令牌可能已过期)。
  • Models 页中 openai-codex 的原生卡片编辑的是 llm-pi-ai 的段落;本插件的目录在自己的设置页。两处不要混用。

配置参考

- id: llm-openai-codex
  config:
    loginMethod: auto            # auto | browser | device-code
    authorizationTimeoutMs: 900000
    streamIdleTimeoutMs: 300000
    stripRequestTemperature: true
    maxRequestImageBytes: 20971520
    models:                      # 省略=继承内置目录;显式列表=整体替换
      - id: gpt-5.6-luna
        name: GPT-5.6 Luna
        contextWindow: 272000
        maxTokens: 128000        # 显式配置才会成为该模型的请求默认输出上限
        input: [text, image]     # 未知 ID 未声明时继承首个支持图片的内置模型

兼容性与依赖策略

  • peerDependencies 的 @deepseek-ai/dsh-* 范围为 >=0.1.0-rc.6 <0.3.0,供插件兼容性闸门(semver.satisfies(runtime, range, { includePrerelease: true }))在 0.2.x 上放行。
  • 所有 peer 都标记为 optional:宿主运行时通过 Loader 拦截解析提供同版本副本,pnpm 不会向 profile 里塞进重复的 @deepseek-ai/*、pi-ai 或 dsh-oauth 副本。
  • 本插件对 @earendil-works/pi-ai 的耦合版本为 ^0.87.1(与 0.2.0-rc.2 桌面端一致)。

开发与验证

pnpm test                      # temperature 双层修复、目录解析、组合注册、RPC 契约、配置校验
pnpm run typecheck
node scripts/smoke-request.mjs           # 真实请求(需本机已有 Codex 登录凭据)
node scripts/smoke-request.mjs --no-strip # 对照组:应复现原始报错

许可

MIT。第三方组件见 THIRD_PARTY_NOTICES.md。