dsh-codex-subscription 1.1.5 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +5 -5
- package/DIRECTORY.md +30 -0
- package/README.en.md +25 -4
- package/README.md +26 -4
- package/lib/client.js +121 -6
- package/lib/index.js +60 -6
- package/package.json +3 -2
package/AGENTS.md
CHANGED
|
@@ -6,7 +6,7 @@ Use this guide when a user asks an Agent to install, update, verify, or remove
|
|
|
6
6
|
## Safety
|
|
7
7
|
|
|
8
8
|
- Confirm the target DSH installation and profile. Use `web` only when it is the user's target.
|
|
9
|
-
- Use the exact `1.
|
|
9
|
+
- Use the exact `1.2.0` package below; do not install a moving branch.
|
|
10
10
|
- Never print OAuth credentials, account IDs, authorization callbacks, or credential-store contents.
|
|
11
11
|
- Preserve the DSH profile, unrelated plugins, sessions, and saved sign-in.
|
|
12
12
|
- Do not start, stop, or restart DSH without explicit permission.
|
|
@@ -38,19 +38,19 @@ For an official DSH installation run through npm, keep the complete `npx` prefix
|
|
|
38
38
|
run command does not create a global `dsh` command:
|
|
39
39
|
|
|
40
40
|
```sh
|
|
41
|
-
npx -y @deepseek-ai/dsh@0.1.1-rc.1 plugin --profile web add dsh-codex-subscription@1.
|
|
41
|
+
npx -y @deepseek-ai/dsh@0.1.1-rc.1 plugin --profile web add dsh-codex-subscription@1.2.0
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
With an existing global `dsh` command:
|
|
45
45
|
|
|
46
46
|
```sh
|
|
47
|
-
dsh plugin --profile web add dsh-codex-subscription@1.
|
|
47
|
+
dsh plugin --profile web add dsh-codex-subscription@1.2.0
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
From a DSH-Portable folder:
|
|
51
51
|
|
|
52
52
|
```powershell
|
|
53
|
-
.\dsh.exe plugin --profile web add dsh-codex-subscription@1.
|
|
53
|
+
.\dsh.exe plugin --profile web add dsh-codex-subscription@1.2.0
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
Use the same `add` command to update or repair. This is the complete package-changing operation.
|
|
@@ -70,7 +70,7 @@ For DSH-Portable, replace `dsh` with `.\dsh.exe`. Static acceptance requires:
|
|
|
70
70
|
|
|
71
71
|
For the official npm route, run the same checks with `npx -y @deepseek-ai/dsh@0.1.1-rc.1` in place of `dsh`.
|
|
72
72
|
|
|
73
|
-
1. `dsh-codex-subscription` version `1.
|
|
73
|
+
1. `dsh-codex-subscription` version `1.2.0` appears exactly once.
|
|
74
74
|
2. `codex-subscription` appears exactly once in the composed config.
|
|
75
75
|
3. No unrelated plugin or profile was changed and DSH was not restarted.
|
|
76
76
|
|
package/DIRECTORY.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Directory listing copy
|
|
2
|
+
|
|
3
|
+
Use this factual copy when listing `dsh-codex-subscription` in a DSH plugin directory. The repository README remains the installation authority.
|
|
4
|
+
|
|
5
|
+
## Short description
|
|
6
|
+
|
|
7
|
+
Use a ChatGPT subscription in DeepSeek Harness through independent OAuth sign-in, with Codex models, backend-reported quota, subscription web search, image generation, and no silent paid fallback.
|
|
8
|
+
|
|
9
|
+
## 中文短描述
|
|
10
|
+
|
|
11
|
+
通过独立 OAuth 登录在 DeepSeek Harness 中使用 ChatGPT 订阅,提供 Codex 模型、服务端实际额度、订阅搜索和图片生成,不会静默切换其他付费路由。
|
|
12
|
+
|
|
13
|
+
## Facts
|
|
14
|
+
|
|
15
|
+
- Package: `dsh-codex-subscription`
|
|
16
|
+
- Provider: `openai-codex`
|
|
17
|
+
- Authentication: independent ChatGPT OAuth managed on the DSH host
|
|
18
|
+
- Codex CLI required: no
|
|
19
|
+
- OpenAI API key required: no
|
|
20
|
+
- Platforms: official DSH plus DSH-Portable product forms for Windows, macOS, and Linux
|
|
21
|
+
- Main capabilities: Codex models, quota, web search, image generation, optional composer quota, optional Fast mode, secret-free support diagnostics
|
|
22
|
+
- Safety boundary: subscription failures remain visible and never silently fall back to another paid provider
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
dsh plugin --profile web add dsh-codex-subscription
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Do not describe this plugin as reusing a local Codex CLI login, copying `~/.codex/auth.json`, requiring Windows, or providing Claude, Grok, Gemini, or GitHub Copilot subscriptions.
|
package/README.en.md
CHANGED
|
@@ -12,7 +12,7 @@ No OpenAI API key or Codex CLI. Models, search, quota, and image generation stay
|
|
|
12
12
|
[](LICENSE)
|
|
13
13
|
[](https://github.com/WSL043/dsh-codex-subscription/stargazers)
|
|
14
14
|
|
|
15
|
-
[
|
|
15
|
+
[Three-step start](#three-step-start) · [Agent install](#let-an-agent-install-it-recommended) · [Update and uninstall](#update-and-uninstall) · [简体中文](https://github.com/WSL043/dsh-codex-subscription/blob/main/README.md)
|
|
16
16
|
|
|
17
17
|
</div>
|
|
18
18
|
|
|
@@ -20,14 +20,34 @@ No OpenAI API key or Codex CLI. Models, search, quota, and image generation stay
|
|
|
20
20
|
<img src="https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/docs/assets/readme-hero-en.webp" width="900" alt="Your Codex subscription inside DSH: subscription models, web search, live quota, and image generation">
|
|
21
21
|
</p>
|
|
22
22
|
|
|
23
|
+
## Three-step start
|
|
24
|
+
|
|
25
|
+
1. **Install the plugin.** On Windows, open PowerShell and run the line below. Existing `dsh` and DSH-Portable users can use the standard command that follows.
|
|
26
|
+
|
|
27
|
+
```powershell
|
|
28
|
+
irm 'https://github.com/WSL043/dsh-codex-subscription/releases/latest/download/dsh-codex-setup.ps1' | iex
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
2. **Sign in.** Restart DSH yourself, open **Settings -> Codex**, and choose browser sign-in. No Codex CLI and no pasted token are required.
|
|
32
|
+
3. **Use Codex.** Select a Codex model. Quota, subscription search, image generation, and Fast mode remain inside DSH.
|
|
33
|
+
|
|
34
|
+
With an existing `dsh` command, install with:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
dsh plugin --profile web add dsh-codex-subscription
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
From a DSH-Portable product folder, run `./dsh plugin ...` (`.\dsh.exe plugin ...` in Windows PowerShell). See below for the complete official npm, Agent, update, and uninstall routes.
|
|
41
|
+
|
|
23
42
|
## Why this plugin
|
|
24
43
|
|
|
25
44
|
| Capability | What you get |
|
|
26
45
|
| --- | --- |
|
|
27
|
-
| **Codex image generation** | Describe an image in a DSH conversation and view the generated result in that session |
|
|
28
46
|
| **Subscription models** | Sign in to ChatGPT and use Codex without an OpenAI API key or Codex CLI |
|
|
29
|
-
| **
|
|
47
|
+
| **Recoverable and diagnosable** | Sign-in state reconciles automatically; Settings can create a support report without credentials or account identifiers |
|
|
30
48
|
| **Visible quota** | Keep backend-provided standard Codex, Spark, and other limits separate |
|
|
49
|
+
| **Subscription search** | Explicitly choose DSH default search or Codex subscription search |
|
|
50
|
+
| **Codex image generation** | Describe an image in a DSH conversation and view the generated result in that session |
|
|
31
51
|
| **Fast mode (Beta)** | Switch between Standard and Fast directly in the composer |
|
|
32
52
|
|
|
33
53
|
These capabilities reuse the same local ChatGPT sign-in. Subscription routing failures stay visible and never silently switch to another paid route.
|
|
@@ -49,7 +69,7 @@ These capabilities reuse the same local ChatGPT sign-in. Subscription routing fa
|
|
|
49
69
|
|
|
50
70
|
This plugin is currently compatible through DeepSeek Harness `0.1.1-rc.1` and requires a ChatGPT account that currently has Codex access.
|
|
51
71
|
|
|
52
|
-
- Do not want to configure Node.js? Use
|
|
72
|
+
- Do not want to configure Node.js? Use [DSH-Portable](https://github.com/WSL043/DSH-Portable), a community desktop distribution with portable and installed editions for Windows plus desktop packages for macOS and Linux.
|
|
53
73
|
- Prefer the official route? Follow the [DeepSeek Harness run guide](https://github.com/deepseek-ai/deepseek-harness#run).
|
|
54
74
|
|
|
55
75
|
## Install
|
|
@@ -124,6 +144,7 @@ Restart DSH manually after installation, then:
|
|
|
124
144
|
- Separate standard Codex, Codex-Spark, Credits, and other independent limits;
|
|
125
145
|
- Optional composer quota for the selected Codex model (Beta, off by default);
|
|
126
146
|
- Standard or Fast mode for supported Codex models directly in the composer (Beta);
|
|
147
|
+
- A copyable support report in Settings that excludes OAuth credentials, account identifiers, and authorization timestamps;
|
|
127
148
|
- Visible errors when subscription routing is unavailable, with no silent paid fallback.
|
|
128
149
|
|
|
129
150
|
### Composer quota
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
[](LICENSE)
|
|
14
14
|
[](https://github.com/WSL043/dsh-codex-subscription/stargazers)
|
|
15
15
|
|
|
16
|
-
[
|
|
16
|
+
[三步开始](#三步开始) · [交给 Agent 安装](#交给-agent推荐) · [更新与卸载](#更新与卸载) · [English](https://github.com/WSL043/dsh-codex-subscription/blob/main/README.en.md)
|
|
17
17
|
|
|
18
18
|
</div>
|
|
19
19
|
|
|
@@ -21,14 +21,34 @@
|
|
|
21
21
|
<img src="https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/docs/assets/readme-hero.webp" width="900" alt="Codex 订阅直接用在 DSH:订阅模型、联网搜索、实时额度和图片生成">
|
|
22
22
|
</p>
|
|
23
23
|
|
|
24
|
+
## 三步开始
|
|
25
|
+
|
|
26
|
+
1. **安装插件**:Windows 打开 PowerShell,运行下面一行;已有 `dsh` 或 DSH-Portable 的用户也可使用后面的标准命令。
|
|
27
|
+
|
|
28
|
+
```powershell
|
|
29
|
+
irm 'https://github.com/WSL043/dsh-codex-subscription/releases/latest/download/dsh-codex-setup.ps1' | iex
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
2. **登录订阅**:手动重启 DSH,打开 **设置 -> Codex 订阅**,点击浏览器登录。无需 Codex CLI,也不要粘贴 token。
|
|
33
|
+
3. **开始使用**:在模型选择器中选择 Codex;额度、订阅搜索、图片生成和高速模式都在 DSH 内使用。
|
|
34
|
+
|
|
35
|
+
已有 `dsh` 命令时,标准安装命令是:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
dsh plugin --profile web add dsh-codex-subscription
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
DSH-Portable 用户在产品目录中运行 `./dsh plugin ...`,Windows PowerShell 使用 `.\dsh.exe plugin ...`。完整的官方 npm、Agent 安装、更新和卸载方式见下文。
|
|
42
|
+
|
|
24
43
|
## 核心优势
|
|
25
44
|
|
|
26
45
|
| 能力 | 用户得到什么 |
|
|
27
46
|
| --- | --- |
|
|
28
|
-
| **Codex 图片生成** | 在 DSH 对话里直接描述画面,生成结果会显示在当前会话中 |
|
|
29
47
|
| **订阅模型直连** | 登录 ChatGPT 后直接使用 Codex,不需要 OpenAI API Key 或 Codex CLI |
|
|
30
|
-
|
|
|
48
|
+
| **可恢复、可诊断** | 登录状态会自动对账;设置页可生成不含凭据和账号标识的支持报告 |
|
|
31
49
|
| **额度可见** | 普通 Codex、Spark 等服务端实际返回的额度分开显示 |
|
|
50
|
+
| **订阅搜索** | 可在 DSH 默认搜索与 Codex 订阅搜索之间明确切换 |
|
|
51
|
+
| **Codex 图片生成** | 在 DSH 对话里直接描述画面,生成结果会显示在当前会话中 |
|
|
32
52
|
| **高速模式(Beta)** | 直接在输入框切换标准或高速,无需离开当前会话 |
|
|
33
53
|
|
|
34
54
|
这些能力共用同一份本机 ChatGPT 登录。订阅路由失败时会明确报错,不会静默切换到其他付费路由。
|
|
@@ -50,7 +70,7 @@
|
|
|
50
70
|
|
|
51
71
|
本插件当前适配到 DeepSeek Harness `0.1.1-rc.1`,并需要一个当前具有 Codex 使用资格的 ChatGPT 账户。
|
|
52
72
|
|
|
53
|
-
- 不想配置 Node.js:使用 [DSH-Portable
|
|
73
|
+
- 不想配置 Node.js:使用 [DSH-Portable](https://github.com/WSL043/DSH-Portable)。这是社区桌面分发,提供 Windows 便携版和安装版,以及 macOS、Linux 桌面包;
|
|
54
74
|
- 想按官方方式运行:查看 [DeepSeek Harness 官方说明](https://github.com/deepseek-ai/deepseek-harness#run)。
|
|
55
75
|
|
|
56
76
|
## 安装
|
|
@@ -124,6 +144,7 @@ DSH-Portable 请把 `dsh` 换成 `./dsh`(PowerShell 使用 `.\dsh.exe`)。
|
|
|
124
144
|
- 普通 Codex、Codex-Spark、Credits 等独立额度分开显示;
|
|
125
145
|
- 输入框可显示当前 Codex 模型的剩余额度(Beta,默认关闭);
|
|
126
146
|
- 输入框可为支持的 Codex 模型切换标准或高速模式(Beta);
|
|
147
|
+
- 设置页可生成并复制无敏感信息的支持诊断,报告不包含 OAuth 凭据、账号标识或授权时间;
|
|
127
148
|
- 订阅路由不可用时明确报错,不会静默切换到其他付费路由。
|
|
128
149
|
|
|
129
150
|
### 输入框额度
|
|
@@ -175,6 +196,7 @@ DSH-Portable 在其目录中把上述 `dsh` 换成 `.\dsh.exe`。
|
|
|
175
196
|
- **找不到 DSH-Portable**:进入它的目录后重新执行安装命令,或直接运行 `.\dsh.exe plugin --profile web add dsh-codex-subscription`;
|
|
176
197
|
- **电脑上有多个 DSH**:单行助手会合并正在运行的副本与常用目录内检测到的 Portable,输入对应编号即可;交给 Agent 时让它进入目标目录,或明确传入 `-DshPath`;
|
|
177
198
|
- **安装仍然失败**:把上面的 Agent 文档链接发给 Agent,不要删除 profile 或随意修改系统 PATH。
|
|
199
|
+
- **需要提交问题**:在设置页底部生成“支持诊断”并复制到 Issue。报告不含凭据和账号标识;仍不要附上登录链接、授权码或浏览器回调地址。
|
|
178
200
|
|
|
179
201
|
## 边界与支持
|
|
180
202
|
|
package/lib/client.js
CHANGED
|
@@ -79,6 +79,34 @@ window.__ModuleLoader__.load({
|
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
81
|
//#endregion
|
|
82
|
+
//#region src/login-progress.js
|
|
83
|
+
/** Reconcile a login flow with the credential store without exposing credentials. */
|
|
84
|
+
async function readLoginProgress({ flow, readFlow, readAccount }) {
|
|
85
|
+
try {
|
|
86
|
+
const nextFlow = await readFlow();
|
|
87
|
+
if (nextFlow.phase !== "authenticated") return { flow: nextFlow };
|
|
88
|
+
return {
|
|
89
|
+
flow: nextFlow,
|
|
90
|
+
account: await readAccount()
|
|
91
|
+
};
|
|
92
|
+
} catch (flowError) {
|
|
93
|
+
try {
|
|
94
|
+
const account = await readAccount();
|
|
95
|
+
if (account?.authenticated === true) return {
|
|
96
|
+
flow: {
|
|
97
|
+
id: flow.id,
|
|
98
|
+
method: flow.method,
|
|
99
|
+
phase: "authenticated",
|
|
100
|
+
authenticated: true
|
|
101
|
+
},
|
|
102
|
+
account,
|
|
103
|
+
recovered: true
|
|
104
|
+
};
|
|
105
|
+
} catch {}
|
|
106
|
+
throw flowError;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
82
110
|
//#region src/client.jsx
|
|
83
111
|
const inject = [
|
|
84
112
|
"slots",
|
|
@@ -112,6 +140,12 @@ window.__ModuleLoader__.load({
|
|
|
112
140
|
failed: "登录失败,请重试。",
|
|
113
141
|
loadFailed: "无法读取账户状态。",
|
|
114
142
|
accountRetry: "重试",
|
|
143
|
+
diagnostics: "支持诊断",
|
|
144
|
+
diagnosticsHint: "生成不含凭据、账号标识和授权时间的诊断信息。",
|
|
145
|
+
diagnosticsLoad: "生成诊断",
|
|
146
|
+
diagnosticsCopy: "复制诊断",
|
|
147
|
+
diagnosticsCopied: "已复制",
|
|
148
|
+
diagnosticsFailed: "无法生成诊断信息。",
|
|
115
149
|
searchTitle: "搜索来源",
|
|
116
150
|
searchDsh: "DSH 默认",
|
|
117
151
|
searchDshHint: "当前搜索服务",
|
|
@@ -195,6 +229,12 @@ window.__ModuleLoader__.load({
|
|
|
195
229
|
failed: "Sign-in failed. Try again.",
|
|
196
230
|
loadFailed: "Could not read account status.",
|
|
197
231
|
accountRetry: "Retry",
|
|
232
|
+
diagnostics: "Support diagnostics",
|
|
233
|
+
diagnosticsHint: "Create a report without credentials, account identifiers, or authorization timestamps.",
|
|
234
|
+
diagnosticsLoad: "Create report",
|
|
235
|
+
diagnosticsCopy: "Copy report",
|
|
236
|
+
diagnosticsCopied: "Copied",
|
|
237
|
+
diagnosticsFailed: "Could not create diagnostics.",
|
|
198
238
|
searchTitle: "Search source",
|
|
199
239
|
searchDsh: "DSH default",
|
|
200
240
|
searchDshHint: "Current search service",
|
|
@@ -276,6 +316,7 @@ window.__ModuleLoader__.load({
|
|
|
276
316
|
.codexSubscriptionFlow p{font-size:13px;line-height:20px;color:var(--dsw-alias-label-secondary)}.codexSubscriptionCode{width:max-content;max-width:100%;font:600 16px/22px ui-monospace,SFMono-Regular,Consolas,monospace;letter-spacing:.08em;overflow-wrap:anywhere}
|
|
277
317
|
.codexSubscriptionError{font-size:13px;line-height:20px;color:var(--dsw-alias-state-error-primary)}.codexSubscriptionInput{width:100%;box-sizing:border-box}
|
|
278
318
|
.codexSubscriptionRecover{display:flex;align-items:center;justify-content:space-between;gap:12px}.codexSubscriptionRecover .codexSubscriptionError{flex:1}.codexSubscriptionRecover button{flex:0 0 auto}
|
|
319
|
+
.codexSubscriptionDiagnostics pre{max-height:240px;margin:0;padding:10px 12px;border-radius:8px;background:var(--dsw-alias-bg-module-platform);overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere;font:11px/17px ui-monospace,SFMono-Regular,Consolas,monospace;color:var(--dsw-alias-label-secondary)}
|
|
279
320
|
.codexSubscriptionSectionTitle{display:flex;flex:1;min-width:0;flex-direction:column;gap:2px}.codexSubscriptionFreshness{font-size:11px;line-height:17px;color:var(--dsw-alias-label-tertiary)}
|
|
280
321
|
.codexSubscriptionRefresh{flex:0 0 auto;min-width:72px;width:max-content;white-space:nowrap!important;word-break:keep-all!important;overflow-wrap:normal!important;writing-mode:horizontal-tb!important}.codexSubscriptionRefresh *{white-space:nowrap!important;word-break:keep-all!important;writing-mode:horizontal-tb!important}
|
|
281
322
|
.codexSubscriptionEmpty{padding:18px;border:1px dashed var(--dsw-alias-border-l3);border-radius:10px;text-align:center;font-size:13px;line-height:20px;color:var(--dsw-alias-label-tertiary)}
|
|
@@ -985,12 +1026,17 @@ window.__ModuleLoader__.load({
|
|
|
985
1026
|
"cancelled"
|
|
986
1027
|
].includes(flow.phase)) return void 0;
|
|
987
1028
|
const timer = window.setInterval(() => {
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1029
|
+
readLoginProgress({
|
|
1030
|
+
flow,
|
|
1031
|
+
readFlow: () => call("login/status", { id: flow.id }),
|
|
1032
|
+
readAccount: () => call("status")
|
|
1033
|
+
}).then((next) => {
|
|
1034
|
+
setFlow(next.flow);
|
|
1035
|
+
setError(void 0);
|
|
1036
|
+
if (next.account !== void 0) {
|
|
1037
|
+
setAccount(next.account);
|
|
992
1038
|
notifyQuickQuota();
|
|
993
|
-
}
|
|
1039
|
+
}
|
|
994
1040
|
}).catch(() => setError(t("failed")));
|
|
995
1041
|
}, 800);
|
|
996
1042
|
return () => window.clearInterval(timer);
|
|
@@ -1006,7 +1052,21 @@ window.__ModuleLoader__.load({
|
|
|
1006
1052
|
const cancel = () => {
|
|
1007
1053
|
if (flow?.id === void 0) return;
|
|
1008
1054
|
setBusy(true);
|
|
1009
|
-
call("login/cancel", { id: flow.id }).then(
|
|
1055
|
+
call("login/cancel", { id: flow.id }).then((next) => {
|
|
1056
|
+
setFlow(next);
|
|
1057
|
+
return call("status").then((account) => {
|
|
1058
|
+
if (account.authenticated === true) {
|
|
1059
|
+
setAccount(account);
|
|
1060
|
+
setFlow({
|
|
1061
|
+
...next,
|
|
1062
|
+
phase: "authenticated",
|
|
1063
|
+
authenticated: true
|
|
1064
|
+
});
|
|
1065
|
+
setError(void 0);
|
|
1066
|
+
notifyQuickQuota();
|
|
1067
|
+
}
|
|
1068
|
+
});
|
|
1069
|
+
}).catch(() => setError(t("failed"))).finally(() => setBusy(false));
|
|
1010
1070
|
};
|
|
1011
1071
|
const submit = (event) => {
|
|
1012
1072
|
event.preventDefault();
|
|
@@ -1157,6 +1217,57 @@ window.__ModuleLoader__.load({
|
|
|
1157
1217
|
})]
|
|
1158
1218
|
});
|
|
1159
1219
|
}
|
|
1220
|
+
function DiagnosticsCard({ rpc, t }) {
|
|
1221
|
+
const [report, setReport] = (0, react.useState)();
|
|
1222
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
1223
|
+
const [copied, setCopied] = (0, react.useState)(false);
|
|
1224
|
+
const [error, setError] = (0, react.useState)(false);
|
|
1225
|
+
const load = () => {
|
|
1226
|
+
setBusy(true);
|
|
1227
|
+
setError(false);
|
|
1228
|
+
setCopied(false);
|
|
1229
|
+
rpc.call(CHANNEL, "diagnostics", {}).then(unwrap).then(setReport).catch(() => setError(true)).finally(() => setBusy(false));
|
|
1230
|
+
};
|
|
1231
|
+
const copy = () => {
|
|
1232
|
+
if (report === void 0) return;
|
|
1233
|
+
navigator.clipboard.writeText(JSON.stringify(report, null, 2)).then(() => setCopied(true)).catch(() => setError(true));
|
|
1234
|
+
};
|
|
1235
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1236
|
+
className: "codexSubscriptionCard codexSubscriptionDiagnostics",
|
|
1237
|
+
children: [
|
|
1238
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1239
|
+
className: "codexSubscriptionSectionHead",
|
|
1240
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1241
|
+
className: "codexSubscriptionSectionTitle",
|
|
1242
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("diagnostics") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1243
|
+
className: "codexSubscriptionNote",
|
|
1244
|
+
children: t("diagnosticsHint")
|
|
1245
|
+
})]
|
|
1246
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1247
|
+
className: "codexSubscriptionActions",
|
|
1248
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1249
|
+
type: "button",
|
|
1250
|
+
variant: "outline",
|
|
1251
|
+
disabled: busy,
|
|
1252
|
+
onClick: load,
|
|
1253
|
+
children: t("diagnosticsLoad")
|
|
1254
|
+
}), report === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1255
|
+
type: "button",
|
|
1256
|
+
variant: "outline",
|
|
1257
|
+
onClick: copy,
|
|
1258
|
+
children: copied ? t("diagnosticsCopied") : t("diagnosticsCopy")
|
|
1259
|
+
})]
|
|
1260
|
+
})]
|
|
1261
|
+
}),
|
|
1262
|
+
report === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { children: JSON.stringify(report, null, 2) }),
|
|
1263
|
+
error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1264
|
+
className: "codexSubscriptionError",
|
|
1265
|
+
role: "alert",
|
|
1266
|
+
children: t("diagnosticsFailed")
|
|
1267
|
+
}) : null
|
|
1268
|
+
]
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1160
1271
|
function ResetTime({ resetsAt, t }) {
|
|
1161
1272
|
const date = Number.isSafeInteger(resetsAt) ? validDate(resetsAt * 1e3) : void 0;
|
|
1162
1273
|
if (date === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("resetUnknown") });
|
|
@@ -1383,6 +1494,10 @@ window.__ModuleLoader__.load({
|
|
|
1383
1494
|
t,
|
|
1384
1495
|
signedIn: account.authenticated === true,
|
|
1385
1496
|
resetKey
|
|
1497
|
+
}),
|
|
1498
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DiagnosticsCard, {
|
|
1499
|
+
rpc,
|
|
1500
|
+
t
|
|
1386
1501
|
})
|
|
1387
1502
|
]
|
|
1388
1503
|
});
|
package/lib/index.js
CHANGED
|
@@ -373,7 +373,6 @@ var CodexLoginCoordinator = class {
|
|
|
373
373
|
};
|
|
374
374
|
session.controller.abort(/* @__PURE__ */ new Error("Codex login cancelled"));
|
|
375
375
|
}
|
|
376
|
-
await Promise.resolve(session.run).catch(() => void 0);
|
|
377
376
|
return this.read(id);
|
|
378
377
|
}
|
|
379
378
|
async logout(options) {
|
|
@@ -495,7 +494,10 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0 } = {
|
|
|
495
494
|
streamSimple: (model, context, options) => provider.streamSimple(model, context, withSpeed(model, options))
|
|
496
495
|
});
|
|
497
496
|
}
|
|
498
|
-
|
|
497
|
+
//#endregion
|
|
498
|
+
//#region src/version.js
|
|
499
|
+
const PACKAGE_VERSION = "1.2.0";
|
|
500
|
+
const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
|
|
499
501
|
//#endregion
|
|
500
502
|
//#region src/codex-search.js
|
|
501
503
|
const CODEX_SEARCH_PROVIDER_ID = "codex-subscription";
|
|
@@ -823,6 +825,43 @@ function createCodexImageTool(options) {
|
|
|
823
825
|
});
|
|
824
826
|
}
|
|
825
827
|
//#endregion
|
|
828
|
+
//#region src/diagnostics.js
|
|
829
|
+
/** Build a support report that deliberately excludes OAuth and account metadata. */
|
|
830
|
+
async function createSubscriptionDiagnostics({ auth, preferences }) {
|
|
831
|
+
let account = { status: "unknown" };
|
|
832
|
+
const issues = [];
|
|
833
|
+
try {
|
|
834
|
+
account = { status: (await auth.status()).authenticated === true ? "signed-in" : "signed-out" };
|
|
835
|
+
} catch {
|
|
836
|
+
issues.push({ code: "account-status-unavailable" });
|
|
837
|
+
}
|
|
838
|
+
return {
|
|
839
|
+
schemaVersion: 1,
|
|
840
|
+
package: "dsh-codex-subscription",
|
|
841
|
+
version: PACKAGE_VERSION,
|
|
842
|
+
runtime: { node: process.version },
|
|
843
|
+
account,
|
|
844
|
+
provider: {
|
|
845
|
+
id: "openai-codex",
|
|
846
|
+
transport: "sse",
|
|
847
|
+
cache: {
|
|
848
|
+
owner: "dsh/pi-ai",
|
|
849
|
+
retention: "short"
|
|
850
|
+
}
|
|
851
|
+
},
|
|
852
|
+
capabilities: {
|
|
853
|
+
models: true,
|
|
854
|
+
quota: true,
|
|
855
|
+
search: true,
|
|
856
|
+
imageGeneration: true,
|
|
857
|
+
composerQuota: true,
|
|
858
|
+
speedMode: true
|
|
859
|
+
},
|
|
860
|
+
configuration: preferences.status(),
|
|
861
|
+
issues
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
//#endregion
|
|
826
865
|
//#region src/usage.js
|
|
827
866
|
const CODEX_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
|
|
828
867
|
const DEFAULT_TTL_MS = 6e4;
|
|
@@ -1024,8 +1063,18 @@ const publicError = (code, message) => ({
|
|
|
1024
1063
|
details: { issues: [] }
|
|
1025
1064
|
}
|
|
1026
1065
|
});
|
|
1027
|
-
function createSubscriptionRpcHandler({ authHandler, usageReader, preferences }) {
|
|
1066
|
+
function createSubscriptionRpcHandler({ authHandler, usageReader, preferences, diagnosticsReader }) {
|
|
1028
1067
|
return async (endpoint, payload, signal) => {
|
|
1068
|
+
if (endpoint === "diagnostics") try {
|
|
1069
|
+
signal.throwIfAborted();
|
|
1070
|
+
return {
|
|
1071
|
+
ok: true,
|
|
1072
|
+
value: await diagnosticsReader()
|
|
1073
|
+
};
|
|
1074
|
+
} catch (error) {
|
|
1075
|
+
if (signal.aborted) throw error;
|
|
1076
|
+
return publicError("internal", "Could not create support diagnostics");
|
|
1077
|
+
}
|
|
1029
1078
|
if (endpoint === "preferences/status" || endpoint === "preferences/update") try {
|
|
1030
1079
|
signal.throwIfAborted();
|
|
1031
1080
|
if (endpoint === "preferences/update") {
|
|
@@ -1170,7 +1219,8 @@ function apply(ctx) {
|
|
|
1170
1219
|
select(settings.get());
|
|
1171
1220
|
return settings.watch(select);
|
|
1172
1221
|
}, "codex-subscription: search provider selection");
|
|
1173
|
-
const
|
|
1222
|
+
const auth = createCodexAuthService(authModels, store);
|
|
1223
|
+
const coordinator = new CodexLoginCoordinator(auth);
|
|
1174
1224
|
const usageReader = createCodexUsageReader({
|
|
1175
1225
|
getAuth: resolveAuth,
|
|
1176
1226
|
readCredential: (options) => store.read(PROVIDER, options)
|
|
@@ -1178,9 +1228,13 @@ function apply(ctx) {
|
|
|
1178
1228
|
const handler = createSubscriptionRpcHandler({
|
|
1179
1229
|
authHandler: createCodexRpcHandler(coordinator, { openExternal: openCodexAuthUrl }),
|
|
1180
1230
|
usageReader,
|
|
1181
|
-
preferences
|
|
1231
|
+
preferences,
|
|
1232
|
+
diagnosticsReader: () => createSubscriptionDiagnostics({
|
|
1233
|
+
auth,
|
|
1234
|
+
preferences
|
|
1235
|
+
})
|
|
1182
1236
|
});
|
|
1183
1237
|
ctx.effect(() => ctx.connection.rpc.handle(CHANNEL, handler, { authority: "loopback" }), "codex-subscription: loopback account RPC");
|
|
1184
1238
|
}
|
|
1185
1239
|
//#endregion
|
|
1186
|
-
export { CODEX_IMAGE_GENERATION_URL, CODEX_IMAGE_TOOL_NAME, CODEX_USAGE_URL, CodexLoginCoordinator, DshOAuthCredentialStore, apply, assertCodexAuthUrl, commandForCodexAuthUrl, createCodexAuthService, createCodexImageTool, createCodexRpcHandler, createCodexUsageReader, createSearchProviderSwitcher, createSubscriptionRpcHandler, decodeCodexPng, inject, name, openCodexAuthUrl, parseCodexUsage };
|
|
1240
|
+
export { CODEX_IMAGE_GENERATION_URL, CODEX_IMAGE_TOOL_NAME, CODEX_USAGE_URL, CodexLoginCoordinator, DshOAuthCredentialStore, apply, assertCodexAuthUrl, commandForCodexAuthUrl, createCodexAuthService, createCodexImageTool, createCodexRpcHandler, createCodexUsageReader, createSearchProviderSwitcher, createSubscriptionDiagnostics, createSubscriptionRpcHandler, decodeCodexPng, inject, name, openCodexAuthUrl, parseCodexUsage };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "ChatGPT and Codex subscriptions for DeepSeek Harness with OAuth login, image generation, quota, and subscription web search",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"cordis.patch.yml",
|
|
16
16
|
"README.md",
|
|
17
17
|
"README.en.md",
|
|
18
|
+
"DIRECTORY.md",
|
|
18
19
|
"AGENTS.md",
|
|
19
20
|
"compatibility.json",
|
|
20
21
|
"LICENSE",
|
|
@@ -46,7 +47,7 @@
|
|
|
46
47
|
"deepseek-harness",
|
|
47
48
|
"dsh",
|
|
48
49
|
"openai-codex",
|
|
49
|
-
"
|
|
50
|
+
"chatgpt-oauth",
|
|
50
51
|
"chatgpt",
|
|
51
52
|
"chatgpt-plus",
|
|
52
53
|
"subscription",
|