dsh-codex-subscription 0.3.7 → 1.0.4
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 +4 -4
- package/README.en.md +38 -16
- package/README.md +39 -15
- package/dsh-codex.ps1 +158 -18
- package/lib/client.js +87 -18
- package/lib/index.js +14 -6
- package/package.json +33 -35
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 profile; use `web` only when it is the user's target.
|
|
9
|
-
- Use the pinned `
|
|
9
|
+
- Use the pinned `v1.0.4` release assets for a first install, never a moving branch.
|
|
10
10
|
- Never print OAuth credentials, account IDs, authorization callbacks, or the
|
|
11
11
|
credential store.
|
|
12
12
|
- Do not start, stop, or restart DSH without explicit permission.
|
|
@@ -51,7 +51,7 @@ the user which installation is the target.
|
|
|
51
51
|
Download the fixed release asset to a visible file, then invoke the requested action:
|
|
52
52
|
|
|
53
53
|
```powershell
|
|
54
|
-
curl.exe -fL https://github.com/WSL043/dsh-codex-subscription/releases/download/
|
|
54
|
+
curl.exe -fL https://github.com/WSL043/dsh-codex-subscription/releases/download/v1.0.4/dsh-codex.ps1 -o "$env:TEMP\dsh-codex.ps1"
|
|
55
55
|
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\dsh-codex.ps1" Install
|
|
56
56
|
```
|
|
57
57
|
|
|
@@ -59,7 +59,7 @@ If `curl.exe` is unavailable, download the same pinned asset without executing
|
|
|
59
59
|
remote text in memory:
|
|
60
60
|
|
|
61
61
|
```powershell
|
|
62
|
-
Invoke-WebRequest -UseBasicParsing -Uri 'https://github.com/WSL043/dsh-codex-subscription/releases/download/
|
|
62
|
+
Invoke-WebRequest -UseBasicParsing -Uri 'https://github.com/WSL043/dsh-codex-subscription/releases/download/v1.0.4/dsh-codex.ps1' -OutFile "$env:TEMP\dsh-codex.ps1"
|
|
63
63
|
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\dsh-codex.ps1" Install
|
|
64
64
|
```
|
|
65
65
|
|
|
@@ -93,7 +93,7 @@ When `dsh`, Node.js, and pnpm are already available, install the pinned npm
|
|
|
93
93
|
package directly:
|
|
94
94
|
|
|
95
95
|
```sh
|
|
96
|
-
dsh plugin --profile web add dsh-codex-subscription@0.
|
|
96
|
+
dsh plugin --profile web add dsh-codex-subscription@1.0.4
|
|
97
97
|
```
|
|
98
98
|
|
|
99
99
|
Update with `dsh plugin --profile web update dsh-codex-subscription`. When
|
package/README.en.md
CHANGED
|
@@ -13,7 +13,7 @@ tools, permissions, image generation, search choice, and quota stay in one place
|
|
|
13
13
|
|
|
14
14
|
[Agent install](#let-an-agent-install-it-recommended) · [Windows install](#manual-windows-install) · [Update or uninstall](#update-and-uninstall)
|
|
15
15
|
|
|
16
|
-

|
|
17
17
|
|
|
18
18
|
Settings shows sign-in, search source, and the separate standard Codex and Spark
|
|
19
19
|
quota returned by the service.
|
|
@@ -33,7 +33,7 @@ If this helps, open the [GitHub repository](https://github.com/WSL043/dsh-codex-
|
|
|
33
33
|
|
|
34
34
|
## Prepare DSH
|
|
35
35
|
|
|
36
|
-
This plugin supports DeepSeek Harness `0.1.0-rc.6` and `0.1.0-rc.
|
|
36
|
+
This plugin supports DeepSeek Harness `0.1.0-rc.6`, `0.1.0-rc.7`, and `0.1.0-rc.8`, and requires a ChatGPT account
|
|
37
37
|
that currently has Codex access.
|
|
38
38
|
|
|
39
39
|
- Do not want to configure Node.js? Use the [community DSH-Portable package](https://github.com/WSL043/DSH-Portable).
|
|
@@ -57,22 +57,44 @@ https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/AGENTS.md
|
|
|
57
57
|
|
|
58
58
|
### Manual Windows install
|
|
59
59
|
|
|
60
|
-
Open PowerShell and paste
|
|
61
|
-
and DSH-Portable. Portable users do not need a system Node.js or pnpm.
|
|
60
|
+
Open PowerShell and paste this one line:
|
|
62
61
|
|
|
63
62
|
```powershell
|
|
64
|
-
curl.exe -fL https://github.com/WSL043/dsh-codex-subscription/releases/latest/download/dsh-codex.ps1 -o "$env:TEMP\dsh-codex.ps1"
|
|
65
|
-
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\dsh-codex.ps1" Install
|
|
63
|
+
curl.exe -fL https://github.com/WSL043/dsh-codex-subscription/releases/latest/download/dsh-codex-setup.ps1 -o "$env:TEMP\dsh-codex-setup.ps1"; if ($LASTEXITCODE -eq 0) { powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\dsh-codex-setup.ps1" }
|
|
66
64
|
```
|
|
67
65
|
|
|
66
|
+
The setup asks you to choose **中文(简体)** or **English** first, then discovers DSH:
|
|
67
|
+
|
|
68
|
+
- one DSH installation: it shows the target and continues automatically;
|
|
69
|
+
- multiple DSH installations: it shows a numbered list with status and paths instead of throwing a PowerShell exception;
|
|
70
|
+
- no existing plugin: the operation is clearly shown as **Install**;
|
|
71
|
+
- an existing current or legacy plugin: the operation is clearly shown as **Update**, using the existing safe migration path;
|
|
72
|
+
- success: it shows the result and asks you to restart DSH manually; it never restarts DSH on its own.
|
|
73
|
+
|
|
68
74
|
`Bypass` applies only to this child process and does not change the system
|
|
69
75
|
PowerShell execution policy.
|
|
70
76
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
Both a normal DSH installation and DSH-Portable are supported. Portable users do
|
|
78
|
+
not need a system Node.js or pnpm, and administrator access is not required. The
|
|
79
|
+
friendly setup downloads the core manager, verifies its Release SHA-256, then
|
|
80
|
+
lets the existing manager perform installation, update, verification, and PATH
|
|
81
|
+
handling.
|
|
82
|
+
|
|
83
|
+
<details>
|
|
84
|
+
<summary>Non-interactive / compatibility install</summary>
|
|
85
|
+
|
|
86
|
+
For scripting, Agent workflows, or an explicit `Install` action, the original
|
|
87
|
+
core manager remains available:
|
|
88
|
+
|
|
89
|
+
```powershell
|
|
90
|
+
curl.exe -fL https://github.com/WSL043/dsh-codex-subscription/releases/latest/download/dsh-codex.ps1 -o "$env:TEMP\dsh-codex.ps1"
|
|
91
|
+
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\dsh-codex.ps1" Install
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
When more than one DSH-Portable copy exists, pass `-PortableRoot` explicitly.
|
|
95
|
+
This entry point stays non-interactive for automation.
|
|
96
|
+
|
|
97
|
+
</details>
|
|
76
98
|
|
|
77
99
|
If the portable folder was renamed or moved, start the intended DSH-Portable copy
|
|
78
100
|
once and install again. Restart DSH manually after installation.
|
|
@@ -108,7 +130,7 @@ subscription search when wanted.
|
|
|
108
130
|
|
|
109
131
|
## How quota is shown
|
|
110
132
|
|
|
111
|
-

|
|
112
134
|
|
|
113
135
|
- Settings always shows the detailed quota returned by the backend. The compact percentage is Beta and off by default;
|
|
114
136
|
- When enabled, it appears inside the composer before the model name and only while a Codex model is selected;
|
|
@@ -132,7 +154,8 @@ Windows installer users only need these short commands:
|
|
|
132
154
|
Update verifies the latest Release manager script with SHA-256. Uninstall removes
|
|
133
155
|
the plugin and `dsh-codex` command while preserving the DSH profile, unrelated
|
|
134
156
|
plugins, and saved sign-in. If an older installation has no short command, run
|
|
135
|
-
the
|
|
157
|
+
the Windows setup line above once; the friendly setup detects the existing plugin
|
|
158
|
+
and automatically shows **Update**.
|
|
136
159
|
|
|
137
160
|
<details>
|
|
138
161
|
<summary>Update or uninstall with an existing <code>dsh</code> command</summary>
|
|
@@ -166,9 +189,8 @@ If DSH is running, restart it manually after installation or update.
|
|
|
166
189
|
|
|
167
190
|
- If `dsh-codex` is not found after installation, close and reopen PowerShell;
|
|
168
191
|
- If DSH-Portable is not found, start the intended portable copy once and retry;
|
|
169
|
-
- If
|
|
170
|
-
|
|
171
|
-
PATH or execution policy, and do not delete a profile to force an install.
|
|
192
|
+
- If multiple DSH installations are found, choose the intended one from the numbered list;
|
|
193
|
+
- If `curl.exe` is missing or setup still fails, send the Agent guide URL above to an Agent. Do not change the machine PATH or execution policy, and do not delete a profile to force an install.
|
|
172
194
|
|
|
173
195
|
## Boundaries and support
|
|
174
196
|
|
package/README.md
CHANGED
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
[](https://github.com/WSL043/dsh-codex-subscription/stargazers)
|
|
7
7
|
|
|
8
|
+
[English](https://github.com/WSL043/dsh-codex-subscription/blob/main/README.en.md)
|
|
9
|
+
|
|
8
10
|
在 DeepSeek Harness 中直接登录 ChatGPT 并使用 Codex 订阅,不需要 OpenAI API Key,
|
|
9
11
|
也不依赖 Codex CLI。保留 DSH 原有的会话、工具和权限,还能生成图片、切换联网搜索来源并查看额度。
|
|
10
12
|
|
|
11
13
|
[交给 Agent 安装](#交给-agent推荐) · [Windows 手动安装](#windows-手动安装) · [更新与卸载](#更新与卸载) · [English](#english)
|
|
12
14
|
|
|
13
|
-

|
|
14
16
|
|
|
15
17
|
设置页会显示登录状态、搜索来源,以及服务端实际返回的普通 Codex 与 Spark 独立额度。
|
|
16
18
|
|
|
@@ -29,7 +31,7 @@
|
|
|
29
31
|
|
|
30
32
|
## 准备 DSH
|
|
31
33
|
|
|
32
|
-
本插件适配 DeepSeek Harness `0.1.0-rc.6` 与 `0.1.0-rc.
|
|
34
|
+
本插件适配 DeepSeek Harness `0.1.0-rc.6`、`0.1.0-rc.7` 与 `0.1.0-rc.8`,还需要一个当前具有 Codex 使用资格的
|
|
33
35
|
ChatGPT 账户。
|
|
34
36
|
|
|
35
37
|
- 不想配置 Node.js:使用 [DSH-Portable(社区便携包)](https://github.com/WSL043/DSH-Portable);
|
|
@@ -52,16 +54,37 @@ https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/AGENTS.md
|
|
|
52
54
|
|
|
53
55
|
### Windows 手动安装
|
|
54
56
|
|
|
55
|
-
打开 PowerShell
|
|
57
|
+
打开 PowerShell,只需要复制这一行:
|
|
58
|
+
|
|
59
|
+
```powershell
|
|
60
|
+
curl.exe -fL https://github.com/WSL043/dsh-codex-subscription/releases/latest/download/dsh-codex-setup.ps1 -o "$env:TEMP\dsh-codex-setup.ps1"; if ($LASTEXITCODE -eq 0) { powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\dsh-codex-setup.ps1" }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
安装助手会先让你选择 **中文(简体)** 或 **English**,然后自动寻找 DSH:
|
|
64
|
+
|
|
65
|
+
- 只找到一个 DSH:直接显示目标并继续;
|
|
66
|
+
- 找到多个 DSH:显示编号、状态和路径,让你输入编号选择,不再直接抛英文报错;
|
|
67
|
+
- 没有安装过插件:明确显示 **安装**;
|
|
68
|
+
- 已经安装当前版或旧版插件:明确显示 **更新**,旧包会按原有安全迁移流程处理;
|
|
69
|
+
- 成功后只提示结果和需要手动重启 DSH,不会擅自重启程序。
|
|
70
|
+
|
|
71
|
+
普通安装版和 DSH-Portable 都能使用。便携版不需要另装 Node.js 或 pnpm,整个过程不需要
|
|
72
|
+
管理员权限。安装助手下载核心管理脚本后会校验 Release 提供的 SHA-256,再交给原有管理器
|
|
73
|
+
执行安装、更新、验证和 PATH 处理。
|
|
74
|
+
|
|
75
|
+
<details>
|
|
76
|
+
<summary>非交互安装 / 兼容旧方式</summary>
|
|
77
|
+
|
|
78
|
+
需要脚本化安装、Agent 操作,或想明确指定 `Install` 时,仍然可以使用原来的核心管理器:
|
|
56
79
|
|
|
57
80
|
```powershell
|
|
58
81
|
curl.exe -fL https://github.com/WSL043/dsh-codex-subscription/releases/latest/download/dsh-codex.ps1 -o "$env:TEMP\dsh-codex.ps1"
|
|
59
82
|
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\dsh-codex.ps1" Install
|
|
60
83
|
```
|
|
61
84
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
85
|
+
如果有多个 DSH-Portable,也可以继续显式传入 `-PortableRoot`。这个入口保持非交互,适合自动化。
|
|
86
|
+
|
|
87
|
+
</details>
|
|
65
88
|
|
|
66
89
|
如果便携文件夹改过名字或位置,先启动一次正确的 DSH-Portable,再执行安装。完成后手动
|
|
67
90
|
重启 DSH,让插件生效。
|
|
@@ -95,7 +118,7 @@ Codex 订阅搜索复用同一份 ChatGPT 登录,不需要 OpenAI API Key。
|
|
|
95
118
|
|
|
96
119
|
## 额度如何显示
|
|
97
120
|
|
|
98
|
-

|
|
99
122
|
|
|
100
123
|
- 设置页始终展示服务端返回的详细额度;快捷百分比是 Beta 功能,默认关闭;
|
|
101
124
|
- 开启后,百分比会显示在输入框内、模型名称左侧,只在选择 Codex 模型时出现;
|
|
@@ -118,7 +141,7 @@ Windows 安装器用户只需要两条短命令:
|
|
|
118
141
|
|
|
119
142
|
更新会校验最新 Release 管理脚本的 SHA-256。卸载会移除插件和 `dsh-codex` 命令,但保留
|
|
120
143
|
DSH profile、其他插件和已保存的登录信息。旧版本如果还没有短命令,重新执行一次上面的
|
|
121
|
-
Windows
|
|
144
|
+
Windows 首次安装命令即可;安装助手检测到已有插件时会自动显示并执行“更新”。
|
|
122
145
|
|
|
123
146
|
<details>
|
|
124
147
|
<summary>使用现有 <code>dsh</code> 命令更新或卸载</summary>
|
|
@@ -151,8 +174,8 @@ dsh plugin --profile web remove @wsl043/dsh-codex-subscription
|
|
|
151
174
|
|
|
152
175
|
- 找不到 `dsh-codex`:关闭并重新打开 PowerShell;
|
|
153
176
|
- 找不到 DSH-Portable:先启动一次正确的便携版,再重新安装;
|
|
154
|
-
-
|
|
155
|
-
|
|
177
|
+
- 检测到多个 DSH:新版安装助手会列出编号和路径,选你准备使用的那个即可;
|
|
178
|
+
- 没有 `curl.exe` 或仍然失败:把 Agent 文档链接发给 Agent,不要自行修改系统 PATH、执行策略或删除 profile。
|
|
156
179
|
|
|
157
180
|
## 边界与支持
|
|
158
181
|
|
|
@@ -176,15 +199,16 @@ service.
|
|
|
176
199
|
[installation guide](https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/AGENTS.md)
|
|
177
200
|
to your Agent.
|
|
178
201
|
|
|
179
|
-
**Windows install:** open PowerShell and run
|
|
202
|
+
**Windows install:** open PowerShell and run this one line:
|
|
180
203
|
|
|
181
204
|
```powershell
|
|
182
|
-
curl.exe -fL https://github.com/WSL043/dsh-codex-subscription/releases/latest/download/dsh-codex.ps1 -o "$env:TEMP\dsh-codex.ps1"
|
|
183
|
-
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\dsh-codex.ps1" Install
|
|
205
|
+
curl.exe -fL https://github.com/WSL043/dsh-codex-subscription/releases/latest/download/dsh-codex-setup.ps1 -o "$env:TEMP\dsh-codex-setup.ps1"; if ($LASTEXITCODE -eq 0) { powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\dsh-codex-setup.ps1" }
|
|
184
206
|
```
|
|
185
207
|
|
|
186
|
-
|
|
187
|
-
|
|
208
|
+
The setup asks for Chinese or English first, turns multiple DSH copies into a
|
|
209
|
+
numbered choice, and automatically shows **Install** or **Update** based on the
|
|
210
|
+
selected DSH. DSH-Portable is supported without a separate Node.js or pnpm
|
|
211
|
+
installation. After the first install, use `dsh-codex update` to update and
|
|
188
212
|
`dsh-codex uninstall` to remove it. Open **Settings -> Codex**, sign in with a
|
|
189
213
|
ChatGPT account that has Codex access, choose a search source, and select a Codex
|
|
190
214
|
model. For full usage and troubleshooting, see the
|
package/dsh-codex.ps1
CHANGED
|
@@ -32,8 +32,12 @@ if ($Managed -and -not $PSBoundParameters.ContainsKey('Action')) {
|
|
|
32
32
|
|
|
33
33
|
$PackageName = 'dsh-codex-subscription'
|
|
34
34
|
$LegacyPackageName = '@wsl043/dsh-codex-subscription'
|
|
35
|
-
$
|
|
36
|
-
$
|
|
35
|
+
$ManagerScriptName = 'dsh-codex-manager.ps1'
|
|
36
|
+
$LegacyManagerScriptName = 'dsh-codex.ps1'
|
|
37
|
+
$ManagerShimName = 'dsh-codex.cmd'
|
|
38
|
+
$ManagerStateName = 'install-state.json'
|
|
39
|
+
$PackageVersion = '1.0.4'
|
|
40
|
+
$PackageSpec = 'https://github.com/WSL043/dsh-codex-subscription/releases/download/v1.0.4/dsh-codex-subscription.tgz'
|
|
37
41
|
$PnpmVersion = '11.19.0'
|
|
38
42
|
$PnpmUrl = 'https://registry.npmjs.org/pnpm/-/pnpm-11.19.0.tgz'
|
|
39
43
|
$PnpmSha512 = '7881F3ED590D472C4A955E2B88B2121791116066DCC88CBCA3849EC9B60F1BBAA6D2CCB221FA91DA4E1C65BEF2BCBE379365AEA7AC539C7BF86DEDC3A1B22DCE'
|
|
@@ -224,9 +228,10 @@ function Add-ManagerToUserPath {
|
|
|
224
228
|
|
|
225
229
|
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
226
230
|
$updated = Add-UserPathEntry -UserPath $userPath -Directory $Directory
|
|
227
|
-
if ([string]::Equals([string] $updated, [string] $userPath, [System.StringComparison]::Ordinal)) { return }
|
|
231
|
+
if ([string]::Equals([string] $updated, [string] $userPath, [System.StringComparison]::Ordinal)) { return $false }
|
|
228
232
|
[Environment]::SetEnvironmentVariable('Path', $updated, 'User')
|
|
229
233
|
Publish-UserPathChange
|
|
234
|
+
return $true
|
|
230
235
|
}
|
|
231
236
|
|
|
232
237
|
function Remove-ManagerFromUserPath {
|
|
@@ -243,8 +248,8 @@ function Remove-ManagerFromUserPath {
|
|
|
243
248
|
function Start-ManagerCleanup {
|
|
244
249
|
param([Parameter(Mandatory = $true)][string] $Directory)
|
|
245
250
|
|
|
246
|
-
$installedScript = Join-Path $Directory
|
|
247
|
-
$installedShim = Join-Path $Directory
|
|
251
|
+
$installedScript = Join-Path $Directory $ManagerScriptName
|
|
252
|
+
$installedShim = Join-Path $Directory $ManagerShimName
|
|
248
253
|
if (-not (Test-Path -LiteralPath $installedScript -PathType Leaf) -or
|
|
249
254
|
-not (Test-Path -LiteralPath $installedShim -PathType Leaf)) {
|
|
250
255
|
throw 'Refusing to clean an unrecognized manager command directory.'
|
|
@@ -263,8 +268,9 @@ $cleanupScript = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String(
|
|
|
263
268
|
try {
|
|
264
269
|
Wait-Process -Id $ParentId -ErrorAction SilentlyContinue
|
|
265
270
|
Start-Sleep -Milliseconds 300
|
|
266
|
-
|
|
267
|
-
|
|
271
|
+
foreach ($name in @('dsh-codex-manager.ps1', 'dsh-codex.ps1', 'dsh-codex.cmd', 'install-state.json')) {
|
|
272
|
+
Remove-Item -LiteralPath (Join-Path $directory $name) -Force -ErrorAction SilentlyContinue
|
|
273
|
+
}
|
|
268
274
|
if ((Test-Path -LiteralPath $directory -PathType Container) -and
|
|
269
275
|
-not (Get-ChildItem -LiteralPath $directory -Force -ErrorAction SilentlyContinue | Select-Object -First 1)) {
|
|
270
276
|
Remove-Item -LiteralPath $directory -Force -ErrorAction SilentlyContinue
|
|
@@ -281,16 +287,19 @@ try {
|
|
|
281
287
|
}
|
|
282
288
|
|
|
283
289
|
function Remove-ManagerCommand {
|
|
284
|
-
param(
|
|
290
|
+
param(
|
|
291
|
+
[Parameter(Mandatory = $true)][string] $Directory,
|
|
292
|
+
[bool] $RemovePath
|
|
293
|
+
)
|
|
285
294
|
|
|
286
|
-
if (
|
|
295
|
+
if ($RemovePath) { Remove-ManagerFromUserPath -Directory $Directory }
|
|
287
296
|
if (Test-Path -LiteralPath $Directory -PathType Container) {
|
|
288
|
-
$installedScript = Join-Path $Directory
|
|
297
|
+
$installedScript = Join-Path $Directory $ManagerScriptName
|
|
289
298
|
if ($Managed -and $PSCommandPath -and (Test-SamePath -Left $PSCommandPath -Right $installedScript)) {
|
|
290
299
|
Start-ManagerCleanup -Directory $Directory
|
|
291
300
|
return
|
|
292
301
|
}
|
|
293
|
-
foreach ($ownedFile in @(
|
|
302
|
+
foreach ($ownedFile in @($ManagerScriptName, $LegacyManagerScriptName, $ManagerShimName, $ManagerStateName)) {
|
|
294
303
|
$ownedPath = Join-Path $Directory $ownedFile
|
|
295
304
|
if (Test-Path -LiteralPath $ownedPath -PathType Leaf) {
|
|
296
305
|
Remove-Item -LiteralPath $ownedPath -Force
|
|
@@ -309,7 +318,7 @@ function Install-ManagerCommand {
|
|
|
309
318
|
throw 'The manager command can only be installed from a downloaded script file.'
|
|
310
319
|
}
|
|
311
320
|
New-Item -ItemType Directory -Force -Path $Directory | Out-Null
|
|
312
|
-
$installedScript = Join-Path $Directory
|
|
321
|
+
$installedScript = Join-Path $Directory $ManagerScriptName
|
|
313
322
|
if (-not (Test-SamePath -Left $PSCommandPath -Right $installedScript)) {
|
|
314
323
|
$stagedScript = Join-Path $Directory ('.dsh-codex-' + [guid]::NewGuid().ToString('N') + '.ps1')
|
|
315
324
|
try {
|
|
@@ -322,13 +331,19 @@ function Install-ManagerCommand {
|
|
|
322
331
|
}
|
|
323
332
|
}
|
|
324
333
|
|
|
334
|
+
$legacyInstalledScript = Join-Path $Directory $LegacyManagerScriptName
|
|
335
|
+
if (Test-Path -LiteralPath $legacyInstalledScript -PathType Leaf) {
|
|
336
|
+
Remove-Item -LiteralPath $legacyInstalledScript -Force
|
|
337
|
+
}
|
|
338
|
+
|
|
325
339
|
$shim = @'
|
|
326
340
|
@echo off
|
|
327
|
-
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0dsh-codex.ps1" -Managed %*
|
|
341
|
+
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0dsh-codex-manager.ps1" -Managed %*
|
|
328
342
|
exit /b %ERRORLEVEL%
|
|
329
343
|
'@
|
|
330
|
-
[System.IO.File]::WriteAllText((Join-Path $Directory
|
|
331
|
-
if (
|
|
344
|
+
[System.IO.File]::WriteAllText((Join-Path $Directory $ManagerShimName), $shim, [System.Text.Encoding]::ASCII)
|
|
345
|
+
if ($NoModifyPath) { return $false }
|
|
346
|
+
return Add-ManagerToUserPath -Directory $Directory
|
|
332
347
|
}
|
|
333
348
|
|
|
334
349
|
function Resolve-FullPath {
|
|
@@ -336,6 +351,61 @@ function Resolve-FullPath {
|
|
|
336
351
|
return [System.IO.Path]::GetFullPath([Environment]::ExpandEnvironmentVariables($Path))
|
|
337
352
|
}
|
|
338
353
|
|
|
354
|
+
function Read-ManagerState {
|
|
355
|
+
param([Parameter(Mandatory = $true)][string] $Directory)
|
|
356
|
+
|
|
357
|
+
$path = Join-Path $Directory $ManagerStateName
|
|
358
|
+
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) { return $null }
|
|
359
|
+
try {
|
|
360
|
+
$state = Get-Content -LiteralPath $path -Raw | ConvertFrom-Json
|
|
361
|
+
} catch {
|
|
362
|
+
throw 'The saved dsh-codex installation target is unreadable. Re-run setup and choose DSH again.'
|
|
363
|
+
}
|
|
364
|
+
if ($state.schemaVersion -ne 1 -or $state.mode -notin @('portable', 'global') -or
|
|
365
|
+
[string] $state.profile -notmatch '^[A-Za-z0-9._-]+$' -or
|
|
366
|
+
$state.pathOwned -isnot [bool]) {
|
|
367
|
+
throw 'The saved dsh-codex installation target is invalid. Re-run setup and choose DSH again.'
|
|
368
|
+
}
|
|
369
|
+
if ($state.mode -eq 'portable' -and -not [string] $state.portableRoot) {
|
|
370
|
+
throw 'The saved DSH-Portable target is missing. Re-run setup and choose DSH again.'
|
|
371
|
+
}
|
|
372
|
+
if ($state.mode -eq 'global' -and
|
|
373
|
+
(($state.PSObject.Properties['globalDsh'] -and -not [string] $state.globalDsh) -or
|
|
374
|
+
($state.PSObject.Properties['globalNode'] -and -not [string] $state.globalNode))) {
|
|
375
|
+
throw 'The saved global DSH target is invalid. Re-run setup and choose DSH again.'
|
|
376
|
+
}
|
|
377
|
+
return $state
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function Write-ManagerState {
|
|
381
|
+
param(
|
|
382
|
+
[Parameter(Mandatory = $true)][string] $Directory,
|
|
383
|
+
[Parameter(Mandatory = $true)] $Target,
|
|
384
|
+
[Parameter(Mandatory = $true)][string] $SelectedProfile,
|
|
385
|
+
[Parameter(Mandatory = $true)][bool] $PathOwned
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
$path = Join-Path $Directory $ManagerStateName
|
|
389
|
+
$staged = Join-Path $Directory ('.install-state-' + [guid]::NewGuid().ToString('N') + '.json')
|
|
390
|
+
$state = [ordered]@{
|
|
391
|
+
schemaVersion = 1
|
|
392
|
+
mode = $Target.Mode
|
|
393
|
+
portableRoot = if ($Target.Mode -eq 'portable') { $Target.Layout.Root } else { $null }
|
|
394
|
+
globalDsh = if ($Target.Mode -eq 'global') { Resolve-FullPath $Target.Executable } else { $null }
|
|
395
|
+
globalNode = if ($Target.Mode -eq 'global') { Resolve-FullPath $Target.Node } else { $null }
|
|
396
|
+
profile = $SelectedProfile
|
|
397
|
+
pathOwned = $PathOwned
|
|
398
|
+
} | ConvertTo-Json -Compress
|
|
399
|
+
try {
|
|
400
|
+
[System.IO.File]::WriteAllText($staged, $state, $Utf8NoBom)
|
|
401
|
+
Move-Item -LiteralPath $staged -Destination $path -Force
|
|
402
|
+
} finally {
|
|
403
|
+
if (Test-Path -LiteralPath $staged) {
|
|
404
|
+
Remove-Item -LiteralPath $staged -Force -ErrorAction SilentlyContinue
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
339
409
|
function Get-PortableLayout {
|
|
340
410
|
param([Parameter(Mandatory = $true)][string] $Root)
|
|
341
411
|
|
|
@@ -442,6 +512,11 @@ function Find-CommonPortables {
|
|
|
442
512
|
}
|
|
443
513
|
|
|
444
514
|
function Get-ManagerTarget {
|
|
515
|
+
param(
|
|
516
|
+
[AllowNull()][string] $PreferredMode,
|
|
517
|
+
[AllowNull()] $SavedState
|
|
518
|
+
)
|
|
519
|
+
|
|
445
520
|
if ($PortableRoot) {
|
|
446
521
|
$layout = Get-PortableLayout $PortableRoot
|
|
447
522
|
if ($null -eq $layout) {
|
|
@@ -450,6 +525,40 @@ function Get-ManagerTarget {
|
|
|
450
525
|
return New-PortableTarget $layout
|
|
451
526
|
}
|
|
452
527
|
|
|
528
|
+
if ($PreferredMode -eq 'global') {
|
|
529
|
+
$savedDshPath = if ($null -ne $SavedState -and $SavedState.PSObject.Properties['globalDsh']) {
|
|
530
|
+
[string] $SavedState.globalDsh
|
|
531
|
+
} else { $null }
|
|
532
|
+
$savedNodePath = if ($null -ne $SavedState -and $SavedState.PSObject.Properties['globalNode']) {
|
|
533
|
+
[string] $SavedState.globalNode
|
|
534
|
+
} else { $null }
|
|
535
|
+
if ($savedDshPath -and $savedNodePath) {
|
|
536
|
+
if (-not (Test-Path -LiteralPath $savedDshPath -PathType Leaf) -or
|
|
537
|
+
-not (Test-Path -LiteralPath $savedNodePath -PathType Leaf)) {
|
|
538
|
+
throw 'The saved global DSH target is no longer available. Re-run setup and choose DSH again.'
|
|
539
|
+
}
|
|
540
|
+
return [pscustomobject]@{
|
|
541
|
+
Mode = 'global'
|
|
542
|
+
Layout = $null
|
|
543
|
+
Executable = Resolve-FullPath $savedDshPath
|
|
544
|
+
Node = Resolve-FullPath $savedNodePath
|
|
545
|
+
UsesPortableCli = $false
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
$savedGlobalDsh = Get-Command dsh -ErrorAction SilentlyContinue
|
|
549
|
+
$savedGlobalNode = Get-Command node -ErrorAction SilentlyContinue
|
|
550
|
+
if ($null -eq $savedGlobalDsh -or $null -eq $savedGlobalNode) {
|
|
551
|
+
throw 'The saved global DSH target is no longer available on PATH. Re-run setup and choose DSH again.'
|
|
552
|
+
}
|
|
553
|
+
return [pscustomobject]@{
|
|
554
|
+
Mode = 'global'
|
|
555
|
+
Layout = $null
|
|
556
|
+
Executable = $savedGlobalDsh.Source
|
|
557
|
+
Node = $savedGlobalNode.Source
|
|
558
|
+
UsesPortableCli = $false
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
453
562
|
$layout = Find-PortableFromCurrentDirectory
|
|
454
563
|
if ($null -ne $layout) {
|
|
455
564
|
return New-PortableTarget $layout
|
|
@@ -638,12 +747,36 @@ function Get-InstalledPackages {
|
|
|
638
747
|
}
|
|
639
748
|
|
|
640
749
|
$managerCommandRoot = Get-ManagerCommandRoot
|
|
750
|
+
$managerState = Read-ManagerState -Directory $managerCommandRoot
|
|
751
|
+
if ($Managed -and $null -ne $managerState) {
|
|
752
|
+
$explicitPortableRoot = $PSBoundParameters.ContainsKey('PortableRoot')
|
|
753
|
+
$sameSavedPortable = $explicitPortableRoot -and $managerState.mode -eq 'portable' -and
|
|
754
|
+
(Test-SamePath -Left $PortableRoot -Right ([string] $managerState.portableRoot))
|
|
755
|
+
if (-not $PSBoundParameters.ContainsKey('Profile') -and
|
|
756
|
+
(-not $explicitPortableRoot -or $sameSavedPortable)) {
|
|
757
|
+
$Profile = [string] $managerState.profile
|
|
758
|
+
}
|
|
759
|
+
if (-not $PSBoundParameters.ContainsKey('PortableRoot') -and $managerState.mode -eq 'portable') {
|
|
760
|
+
$PortableRoot = [string] $managerState.portableRoot
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
$legacyManagedPathOwned = $false
|
|
764
|
+
if ($Managed -and $null -eq $managerState -and
|
|
765
|
+
(Test-Path -LiteralPath (Join-Path $managerCommandRoot $ManagerScriptName) -PathType Leaf)) {
|
|
766
|
+
$currentUserPath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
767
|
+
$legacyManagedPathOwned = [string]::Equals(
|
|
768
|
+
[string] (Add-UserPathEntry -UserPath $currentUserPath -Directory $managerCommandRoot),
|
|
769
|
+
[string] $currentUserPath,
|
|
770
|
+
[System.StringComparison]::Ordinal
|
|
771
|
+
)
|
|
772
|
+
}
|
|
641
773
|
if ($Managed -and $Action -eq 'Update' -and -not $SkipSelfUpdate -and -not $DryRun) {
|
|
642
774
|
Invoke-LatestManager -InstalledCommandRoot $managerCommandRoot
|
|
643
775
|
exit 0
|
|
644
776
|
}
|
|
645
777
|
|
|
646
|
-
$
|
|
778
|
+
$preferredMode = if ($Managed -and $null -ne $managerState) { [string] $managerState.mode } else { $null }
|
|
779
|
+
$target = Get-ManagerTarget -PreferredMode $preferredMode -SavedState $managerState
|
|
647
780
|
$managerCommand = Join-Path $managerCommandRoot 'dsh-codex.cmd'
|
|
648
781
|
$pnpmDirectory = Get-PnpmDirectory $target
|
|
649
782
|
$pnpmStore = Get-PnpmStore $target
|
|
@@ -750,7 +883,11 @@ try {
|
|
|
750
883
|
if ($entryCount -ne 0 -or $legacyEntryCount -ne 0) {
|
|
751
884
|
throw 'The plugin package was removed, but its profile entry is still present.'
|
|
752
885
|
}
|
|
753
|
-
|
|
886
|
+
$removePath = (-not $NoModifyPath) -and (
|
|
887
|
+
($null -ne $managerState -and [bool] $managerState.pathOwned) -or
|
|
888
|
+
($null -eq $managerState -and $legacyManagedPathOwned)
|
|
889
|
+
)
|
|
890
|
+
Remove-ManagerCommand -Directory $managerCommandRoot -RemovePath $removePath
|
|
754
891
|
Write-Host 'Uninstalled. The DSH profile and saved credentials were kept.'
|
|
755
892
|
} else {
|
|
756
893
|
$installedPackage = @($installedAfter | Where-Object { $_.Name -eq $PackageName } | Select-Object -First 1)
|
|
@@ -762,7 +899,10 @@ try {
|
|
|
762
899
|
if ($installedAfterNames -contains $LegacyPackageName) { throw 'The legacy package is still present after migration.' }
|
|
763
900
|
if ($entryCount -ne 1) { throw "Expected one plugin profile entry, found $entryCount." }
|
|
764
901
|
if ($legacyEntryCount -ne 0) { throw 'The legacy plugin profile entry is still present after migration.' }
|
|
765
|
-
Install-ManagerCommand -Directory $managerCommandRoot
|
|
902
|
+
$addedPath = Install-ManagerCommand -Directory $managerCommandRoot
|
|
903
|
+
$pathOwned = ($null -ne $managerState -and [bool] $managerState.pathOwned) -or
|
|
904
|
+
$legacyManagedPathOwned -or [bool] $addedPath
|
|
905
|
+
Write-ManagerState -Directory $managerCommandRoot -Target $target -SelectedProfile $Profile -PathOwned $pathOwned
|
|
766
906
|
$verb = if ($Action -eq 'Update') { 'Updated.' } else { 'Installed.' }
|
|
767
907
|
Write-Host "$verb Restart DSH manually to load the change if it is currently running."
|
|
768
908
|
}
|
package/lib/client.js
CHANGED
|
@@ -6,7 +6,6 @@ window.__ModuleLoader__.load({
|
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
7
|
let react = require("react");
|
|
8
8
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
9
|
-
let _deepseek_ai_dsh_client_ui_attachment = require("@deepseek-ai/dsh-client-ui-attachment");
|
|
10
9
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
11
10
|
//#region src/settings-contract.js
|
|
12
11
|
const SETTINGS_NAMESPACE = "codex-subscription";
|
|
@@ -203,7 +202,7 @@ window.__ModuleLoader__.load({
|
|
|
203
202
|
.codexSubscriptionCreditBalance{display:flex;flex-direction:column;gap:6px}.codexSubscriptionCreditBalance span,.codexSubscriptionCreditLabel{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}.codexSubscriptionCreditBalance strong{font:600 18px/24px ui-monospace,SFMono-Regular,Consolas,monospace;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
|
|
204
203
|
.codexSubscriptionSpendLimit{display:flex;flex-direction:column;gap:8px}.codexSubscriptionSpendTop{display:flex;align-items:baseline;justify-content:space-between;gap:12px}.codexSubscriptionSpendTop strong{font:600 16px/22px ui-monospace,SFMono-Regular,Consolas,monospace;font-variant-numeric:tabular-nums}.codexSubscriptionSpendLimit progress{width:100%;height:6px;border:0;border-radius:999px;overflow:hidden;background:var(--dsw-alias-border-l3);accent-color:var(--dsw-alias-brand-primary,#3964fe);-webkit-appearance:none;appearance:none}.codexSubscriptionSpendLimit progress::-webkit-progress-bar{background:var(--dsw-alias-border-l3);border-radius:999px}.codexSubscriptionSpendLimit progress::-webkit-progress-value{background:var(--dsw-alias-brand-primary,#3964fe);border-radius:999px}.codexSubscriptionSpendLimit progress::-moz-progress-bar{background:var(--dsw-alias-brand-primary,#3964fe);border-radius:999px}
|
|
205
204
|
.codexComposerQuota{display:inline-flex;align-items:center;flex:0 0 auto;height:28px;box-sizing:border-box;margin-right:-4px;padding:0;color:var(--dsw-alias-label-secondary);font-family:inherit;font-size:12px;line-height:20px;font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap;user-select:none}
|
|
206
|
-
.codexImageTool{display:flex;flex-direction:column;gap:8px;margin:4px 0;color:var(--dsw-alias-label-primary)}.codexImageToolRow{display:flex;align-items:center;min-height:24px;gap:8px;font-size:13px;line-height:20px}.codexImageToolIcon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;color:var(--dsw-alias-label-secondary)}.codexImageToolIcon::before{content:'';width:8px;height:8px;border:1.5px solid currentColor;border-radius:3px}.codexImageTool[data-state=running] .codexImageToolIcon::before{border-radius:50%;border-right-color:transparent;animation:codexImageSpin 800ms linear infinite}.codexImageTool[data-state=error] .codexImageToolIcon::before{border-color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-state-error-primary)}.codexImageToolTitle{font-weight:500}.codexImageToolState{color:var(--dsw-alias-label-tertiary)}.codexImageToolError{margin:0 0 0 24px;font-size:12px;line-height:18px;color:var(--dsw-alias-state-error-primary)}.codexImageToolGallery{margin-left:24px}@keyframes codexImageSpin{to{transform:rotate(360deg)}}
|
|
205
|
+
.codexImageTool{display:flex;flex-direction:column;gap:8px;margin:4px 0;color:var(--dsw-alias-label-primary)}.codexImageToolRow{display:flex;align-items:center;min-height:24px;gap:8px;font-size:13px;line-height:20px}.codexImageToolIcon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;color:var(--dsw-alias-label-secondary)}.codexImageToolIcon::before{content:'';width:8px;height:8px;border:1.5px solid currentColor;border-radius:3px}.codexImageTool[data-state=running] .codexImageToolIcon::before{border-radius:50%;border-right-color:transparent;animation:codexImageSpin 800ms linear infinite}.codexImageTool[data-state=error] .codexImageToolIcon::before{border-color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-state-error-primary)}.codexImageToolTitle{font-weight:500}.codexImageToolState{color:var(--dsw-alias-label-tertiary)}.codexImageToolError{margin:0 0 0 24px;font-size:12px;line-height:18px;color:var(--dsw-alias-state-error-primary)}.codexImageToolGallery{margin-left:24px}.codexGeneratedImageFrame{display:flex;align-items:center;justify-content:center;width:min(240px,100%);min-height:120px;padding:0;overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-tertiary);cursor:pointer}.codexGeneratedImageFrame img{display:block;width:100%;max-height:240px;object-fit:contain}.codexGeneratedImageRetry{min-height:36px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);cursor:pointer}.codexGeneratedImageLightbox{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;padding:32px;border:0;background:rgba(0,0,0,.72)}.codexGeneratedImageLightbox img{display:block;max-width:min(1100px,calc(100vw - 64px));max-height:calc(100vh - 64px);object-fit:contain}.codexGeneratedImageClose{position:absolute;top:16px;right:16px;width:36px;height:36px;border:1px solid rgba(255,255,255,.35);border-radius:50%;background:rgba(0,0,0,.48);color:#fff;font-size:20px;line-height:1;cursor:pointer}@keyframes codexImageSpin{to{transform:rotate(360deg)}}
|
|
207
206
|
@container (max-width:560px){.codexSubscriptionCreditRows{grid-template-columns:1fr}}
|
|
208
207
|
@container (max-width:480px){.codexSubscriptionAccountRow,.codexSubscriptionSectionHead{align-items:flex-start;flex-direction:column}.codexSubscriptionActions{width:100%}.codexSubscriptionSearchChoices{grid-template-columns:1fr}}
|
|
209
208
|
@media(max-width:640px){.codexSubscriptionCard{padding:14px}}
|
|
@@ -228,17 +227,88 @@ window.__ModuleLoader__.load({
|
|
|
228
227
|
const date = new Date(value);
|
|
229
228
|
return Number.isFinite(date.getTime()) ? date : void 0;
|
|
230
229
|
};
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
230
|
+
function CodexGeneratedImage({ attachment, loadImage, t }) {
|
|
231
|
+
const [attempt, setAttempt] = (0, react.useState)(0);
|
|
232
|
+
const [error, setError] = (0, react.useState)(false);
|
|
233
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
234
|
+
const [src, setSrc] = (0, react.useState)();
|
|
235
|
+
const closeRef = (0, react.useRef)(null);
|
|
236
|
+
const triggerRef = (0, react.useRef)(null);
|
|
237
|
+
(0, react.useEffect)(() => {
|
|
238
|
+
let live = true;
|
|
239
|
+
setError(false);
|
|
240
|
+
setSrc(void 0);
|
|
241
|
+
loadImage(attachment).then((value) => {
|
|
242
|
+
if (live) setSrc(value);
|
|
243
|
+
}).catch(() => {
|
|
244
|
+
if (live) setError(true);
|
|
245
|
+
});
|
|
246
|
+
return () => {
|
|
247
|
+
live = false;
|
|
248
|
+
};
|
|
249
|
+
}, [
|
|
250
|
+
attachment,
|
|
251
|
+
loadImage,
|
|
252
|
+
attempt
|
|
253
|
+
]);
|
|
254
|
+
(0, react.useEffect)(() => {
|
|
255
|
+
if (!open) return void 0;
|
|
256
|
+
const handleKeyDown = (event) => {
|
|
257
|
+
if (event.key === "Escape") {
|
|
258
|
+
event.preventDefault();
|
|
259
|
+
setOpen(false);
|
|
260
|
+
} else if (event.key === "Tab") {
|
|
261
|
+
event.preventDefault();
|
|
262
|
+
closeRef.current?.focus();
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
266
|
+
closeRef.current?.focus();
|
|
267
|
+
return () => {
|
|
268
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
269
|
+
triggerRef.current?.focus();
|
|
270
|
+
};
|
|
271
|
+
}, [open]);
|
|
272
|
+
const label = attachment.name ?? t("imageLabel");
|
|
273
|
+
if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
274
|
+
type: "button",
|
|
275
|
+
className: "codexGeneratedImageRetry",
|
|
276
|
+
onClick: () => setAttempt((value) => value + 1),
|
|
277
|
+
children: t("imageLoadFailed")
|
|
278
|
+
});
|
|
279
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
280
|
+
ref: triggerRef,
|
|
281
|
+
type: "button",
|
|
282
|
+
className: "codexGeneratedImageFrame",
|
|
283
|
+
title: t("imageOpen"),
|
|
284
|
+
"aria-label": fill(t("imageOpenNamed"), { value: label }),
|
|
285
|
+
onClick: () => {
|
|
286
|
+
if (src !== void 0) setOpen(true);
|
|
287
|
+
},
|
|
288
|
+
children: src === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("imageLoading") }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
289
|
+
src,
|
|
290
|
+
alt: label
|
|
291
|
+
})
|
|
292
|
+
}), !open || src === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
293
|
+
className: "codexGeneratedImageLightbox",
|
|
294
|
+
role: "dialog",
|
|
295
|
+
"aria-modal": "true",
|
|
296
|
+
"aria-label": t("imagePreview"),
|
|
297
|
+
onClick: () => setOpen(false),
|
|
298
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
299
|
+
src,
|
|
300
|
+
alt: label,
|
|
301
|
+
onClick: (event) => event.stopPropagation()
|
|
302
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
303
|
+
ref: closeRef,
|
|
304
|
+
type: "button",
|
|
305
|
+
className: "codexGeneratedImageClose",
|
|
306
|
+
"aria-label": t("imageClosePreview"),
|
|
307
|
+
onClick: () => setOpen(false),
|
|
308
|
+
children: "×"
|
|
309
|
+
})]
|
|
310
|
+
})] });
|
|
311
|
+
}
|
|
242
312
|
function CodexImageToolRow({ block, loadImage, t }) {
|
|
243
313
|
const settled = block?.kind === "tool-result";
|
|
244
314
|
const image = settled ? block.content.find((item) => item?.type === "image" && item.attachment !== void 0) : void 0;
|
|
@@ -269,11 +339,10 @@ window.__ModuleLoader__.load({
|
|
|
269
339
|
}),
|
|
270
340
|
image === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
271
341
|
className: "codexImageToolGallery",
|
|
272
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
labels: imageGalleryLabels(t)
|
|
342
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodexGeneratedImage, {
|
|
343
|
+
attachment: image.attachment,
|
|
344
|
+
loadImage,
|
|
345
|
+
t
|
|
277
346
|
})
|
|
278
347
|
}),
|
|
279
348
|
error === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
package/lib/index.js
CHANGED
|
@@ -55,7 +55,7 @@ var DshOAuthCredentialStore = class {
|
|
|
55
55
|
});
|
|
56
56
|
return current;
|
|
57
57
|
}
|
|
58
|
-
async read(providerId, options) {
|
|
58
|
+
async #read(providerId, options) {
|
|
59
59
|
assertProvider(providerId);
|
|
60
60
|
abortIfNeeded(options);
|
|
61
61
|
let hit = await this.credentials.resolve(this.ref);
|
|
@@ -72,6 +72,9 @@ var DshOAuthCredentialStore = class {
|
|
|
72
72
|
if (hit?.value === void 0 || hit.value === "") return void 0;
|
|
73
73
|
return parseOAuthCredential(hit.value);
|
|
74
74
|
}
|
|
75
|
+
read(providerId, options) {
|
|
76
|
+
return this.#enqueue(providerId, () => this.#read(providerId, options), options);
|
|
77
|
+
}
|
|
75
78
|
async list(options) {
|
|
76
79
|
abortIfNeeded(options);
|
|
77
80
|
return await this.read(PROVIDER$1, options) === void 0 ? [] : [{
|
|
@@ -81,7 +84,7 @@ var DshOAuthCredentialStore = class {
|
|
|
81
84
|
}
|
|
82
85
|
modify(providerId, update, options) {
|
|
83
86
|
return this.#enqueue(providerId, async () => {
|
|
84
|
-
const current = await this
|
|
87
|
+
const current = await this.#read(providerId, options);
|
|
85
88
|
const next = await update(clone(current));
|
|
86
89
|
abortIfNeeded(options);
|
|
87
90
|
if (next === void 0) return current;
|
|
@@ -460,6 +463,7 @@ function openaiCodexSubscriptionProvider() {
|
|
|
460
463
|
})
|
|
461
464
|
});
|
|
462
465
|
}
|
|
466
|
+
const USER_AGENT = `dsh-codex-subscription/1.0.4`;
|
|
463
467
|
//#endregion
|
|
464
468
|
//#region src/codex-search.js
|
|
465
469
|
const CODEX_SEARCH_PROVIDER_ID = "codex-subscription";
|
|
@@ -540,7 +544,7 @@ function createCodexSearchProvider(options) {
|
|
|
540
544
|
accept: "application/json",
|
|
541
545
|
"content-type": "application/json",
|
|
542
546
|
originator: "pi",
|
|
543
|
-
"user-agent":
|
|
547
|
+
"user-agent": USER_AGENT
|
|
544
548
|
},
|
|
545
549
|
body: JSON.stringify({
|
|
546
550
|
id,
|
|
@@ -743,7 +747,7 @@ function createCodexImageTool(options) {
|
|
|
743
747
|
"content-type": "application/json",
|
|
744
748
|
originator: "pi",
|
|
745
749
|
"x-codex-image-turn-id": String(exec.callId),
|
|
746
|
-
"user-agent":
|
|
750
|
+
"user-agent": USER_AGENT
|
|
747
751
|
},
|
|
748
752
|
body: JSON.stringify({
|
|
749
753
|
prompt,
|
|
@@ -915,6 +919,7 @@ function createCodexUsageReader(options) {
|
|
|
915
919
|
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
916
920
|
let cached;
|
|
917
921
|
let inFlight;
|
|
922
|
+
let generation = 0;
|
|
918
923
|
const load = async (signal) => {
|
|
919
924
|
const auth = await getAuth({ signal });
|
|
920
925
|
const credential = await readCredential({ signal });
|
|
@@ -929,7 +934,7 @@ function createCodexUsageReader(options) {
|
|
|
929
934
|
"chatgpt-account-id": accountId,
|
|
930
935
|
accept: "application/json",
|
|
931
936
|
"cache-control": "no-store",
|
|
932
|
-
"user-agent":
|
|
937
|
+
"user-agent": USER_AGENT
|
|
933
938
|
},
|
|
934
939
|
signal: requestSignal(signal, timeoutMs)
|
|
935
940
|
});
|
|
@@ -949,8 +954,9 @@ function createCodexUsageReader(options) {
|
|
|
949
954
|
read({ force = false, signal } = {}) {
|
|
950
955
|
if (!force && cached !== void 0 && now() - cached.fetchedAt < ttlMs) return Promise.resolve(structuredClone(cached));
|
|
951
956
|
if (inFlight !== void 0) return inFlight.then(structuredClone);
|
|
957
|
+
const currentGeneration = generation;
|
|
952
958
|
const current = load(signal).then((value) => {
|
|
953
|
-
cached = structuredClone(value);
|
|
959
|
+
if (generation === currentGeneration) cached = structuredClone(value);
|
|
954
960
|
return structuredClone(value);
|
|
955
961
|
}).finally(() => {
|
|
956
962
|
if (inFlight === current) inFlight = void 0;
|
|
@@ -959,7 +965,9 @@ function createCodexUsageReader(options) {
|
|
|
959
965
|
return current;
|
|
960
966
|
},
|
|
961
967
|
clear() {
|
|
968
|
+
generation += 1;
|
|
962
969
|
cached = void 0;
|
|
970
|
+
inFlight = void 0;
|
|
963
971
|
}
|
|
964
972
|
});
|
|
965
973
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"packageManager": "pnpm@11.19.0",
|
|
5
5
|
"description": "ChatGPT and Codex subscriptions for DeepSeek Harness with OAuth login, image generation, quota, and subscription web search",
|
|
6
6
|
"type": "module",
|
|
@@ -80,46 +80,44 @@
|
|
|
80
80
|
},
|
|
81
81
|
"peerDependencies": {
|
|
82
82
|
"@deepseek-ai/cordis": "4.0.1",
|
|
83
|
-
"@deepseek-ai/dsh-api-remotes": "0.1.0-rc.6 || 0.1.0-rc.7",
|
|
84
|
-
"@deepseek-ai/dsh-client-connection": "0.1.0-rc.6 || 0.1.0-rc.7",
|
|
85
|
-
"@deepseek-ai/dsh-client-locale": "0.1.0-rc.6 || 0.1.0-rc.7",
|
|
86
|
-
"@deepseek-ai/dsh-client-runtime": "0.1.0-rc.6 || 0.1.0-rc.7",
|
|
87
|
-
"@deepseek-ai/dsh-client-ui-
|
|
88
|
-
"@deepseek-ai/dsh-client-ui-
|
|
89
|
-
"@deepseek-ai/dsh-client-ui-
|
|
90
|
-
"@deepseek-ai/dsh-client-ui-
|
|
91
|
-
"@deepseek-ai/dsh-client-ui-
|
|
92
|
-
"@deepseek-ai/dsh-client-ui-
|
|
93
|
-
"@deepseek-ai/dsh-
|
|
94
|
-
"@deepseek-ai/dsh-
|
|
95
|
-
"@deepseek-ai/dsh-llm": "0.1.0-rc.6 || 0.1.0-rc.7",
|
|
96
|
-
"@deepseek-ai/dsh-
|
|
97
|
-
"@deepseek-ai/dsh-
|
|
98
|
-
"@deepseek-ai/dsh-
|
|
99
|
-
"@deepseek-ai/dsh-web": "0.1.0-rc.6 || 0.1.0-rc.7",
|
|
83
|
+
"@deepseek-ai/dsh-api-remotes": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
84
|
+
"@deepseek-ai/dsh-client-connection": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
85
|
+
"@deepseek-ai/dsh-client-locale": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
86
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
87
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
88
|
+
"@deepseek-ai/dsh-client-ui-model-selection": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
89
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
90
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
91
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
92
|
+
"@deepseek-ai/dsh-client-ui-tool": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
93
|
+
"@deepseek-ai/dsh-credentials": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
94
|
+
"@deepseek-ai/dsh-llm": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
95
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
96
|
+
"@deepseek-ai/dsh-settings": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
97
|
+
"@deepseek-ai/dsh-tools": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
98
|
+
"@deepseek-ai/dsh-web": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8",
|
|
100
99
|
"@deepseek-ai/schemastery": "3.18.1",
|
|
101
100
|
"@earendil-works/pi-ai": "0.82.1",
|
|
102
101
|
"react": "^18.2.0"
|
|
103
102
|
},
|
|
104
103
|
"devDependencies": {
|
|
105
104
|
"@deepseek-ai/cordis": "4.0.1",
|
|
106
|
-
"@deepseek-ai/dsh-api-remotes": "0.1.0-rc.
|
|
107
|
-
"@deepseek-ai/dsh-client-connection": "0.1.0-rc.
|
|
108
|
-
"@deepseek-ai/dsh-client-locale": "0.1.0-rc.
|
|
109
|
-
"@deepseek-ai/dsh-client-runtime": "0.1.0-rc.
|
|
110
|
-
"@deepseek-ai/dsh-client-ui-
|
|
111
|
-
"@deepseek-ai/dsh-client-ui-
|
|
112
|
-
"@deepseek-ai/dsh-client-ui-
|
|
113
|
-
"@deepseek-ai/dsh-client-ui-
|
|
114
|
-
"@deepseek-ai/dsh-client-ui-
|
|
115
|
-
"@deepseek-ai/dsh-client-ui-
|
|
116
|
-
"@deepseek-ai/dsh-
|
|
117
|
-
"@deepseek-ai/dsh-
|
|
118
|
-
"@deepseek-ai/dsh-llm": "0.1.0-rc.
|
|
119
|
-
"@deepseek-ai/dsh-
|
|
120
|
-
"@deepseek-ai/dsh-
|
|
121
|
-
"@deepseek-ai/dsh-
|
|
122
|
-
"@deepseek-ai/dsh-web": "0.1.0-rc.7",
|
|
105
|
+
"@deepseek-ai/dsh-api-remotes": "0.1.0-rc.8",
|
|
106
|
+
"@deepseek-ai/dsh-client-connection": "0.1.0-rc.8",
|
|
107
|
+
"@deepseek-ai/dsh-client-locale": "0.1.0-rc.8",
|
|
108
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.0-rc.8",
|
|
109
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.8",
|
|
110
|
+
"@deepseek-ai/dsh-client-ui-model-selection": "0.1.0-rc.8",
|
|
111
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.8",
|
|
112
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.8",
|
|
113
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.8",
|
|
114
|
+
"@deepseek-ai/dsh-client-ui-tool": "0.1.0-rc.8",
|
|
115
|
+
"@deepseek-ai/dsh-credentials": "0.1.0-rc.8",
|
|
116
|
+
"@deepseek-ai/dsh-llm": "0.1.0-rc.8",
|
|
117
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.1.0-rc.8",
|
|
118
|
+
"@deepseek-ai/dsh-settings": "0.1.0-rc.8",
|
|
119
|
+
"@deepseek-ai/dsh-tools": "0.1.0-rc.8",
|
|
120
|
+
"@deepseek-ai/dsh-web": "0.1.0-rc.8",
|
|
123
121
|
"@deepseek-ai/schemastery": "3.18.1",
|
|
124
122
|
"@earendil-works/pi-ai": "0.82.1",
|
|
125
123
|
"react": "18.3.1",
|