dsh-codex-connect 0.1.0-alpha.4.14 → 0.1.0-alpha.4.15
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/INSTALL.md +2 -2
- package/README.i18n.yaml +2 -2
- package/README.md +28 -5
- package/compatibility.json +1 -1
- package/docs/README.zh.md +27 -4
- package/docs/assets/composer-capabilities.jpg +0 -0
- package/docs/design.md +2 -2
- package/docs/design.zh.md +2 -2
- package/lib/bin.js +1 -1
- package/lib/client.js +409 -34
- package/lib/index.d.ts +3 -3
- package/lib/index.js +1 -1
- package/lib/{src-15cHQKm5.js → src-D5OQGYt6.js} +29 -19
- package/package.json +43 -45
package/INSTALL.md
CHANGED
|
@@ -12,7 +12,7 @@ Install `dsh-codex-connect` into one requested DeepSeek Harness profile without
|
|
|
12
12
|
|
|
13
13
|
## Install and validate
|
|
14
14
|
|
|
15
|
-
The only verified combination is DSH plugin API packages `0.1.
|
|
15
|
+
The only verified combination is DSH plugin API packages `0.1.1-rc.2`, `@earendil-works/pi-ai` `0.82.1`, and Node.js `^22.19.0 || >=24.0.0`. Alpha 4.15 uses the rc.2 keyed Plugin configuration slot; users of older DSH API packages should upgrade the DSH API packages and pi-ai together, then rerun `dsh-codex-connect doctor --json` and `pnpm --silent run check:compatibility`; the contract does not make claims about future versions.
|
|
16
16
|
|
|
17
17
|
1. Check `dsh --version` or `dsh --help`. From a Harness checkout use `pnpm dsh`.
|
|
18
18
|
2. Install the package:
|
|
@@ -21,7 +21,7 @@ The only verified combination is DSH plugin API packages `0.1.0-rc.7`, `@earendi
|
|
|
21
21
|
dsh plugin --profile web add dsh-codex-connect@alpha
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
After `0.1.0-alpha.4.
|
|
24
|
+
After `0.1.0-alpha.4.15` is published, pin it exactly with `dsh plugin --profile web add dsh-codex-connect@0.1.0-alpha.4.15`. If npm is unavailable after its matching GitHub prerelease is created, use `dsh plugin --profile web add 'github:franksong2702/dsh-codex-connect#v0.1.0-alpha.4.15'`.
|
|
25
25
|
|
|
26
26
|
3. Run `dsh --profile web --dump-config` and require exactly one `llm-openai-codex` row loading `dsh-codex-connect`.
|
|
27
27
|
4. Confirm the effective `agent-default-model` and `web.searchProvider` values are unchanged from before installation.
|
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# git hash-object README.md docs/README.zh.md
|
|
5
|
-
README.md:
|
|
6
|
-
docs/README.zh.md:
|
|
5
|
+
README.md: 3100a9d730d2eb072e5afcb5897b548da0e00fab
|
|
6
|
+
docs/README.zh.md: a7c3497b9676910b0857e71937241acdcb20b76e
|
package/README.md
CHANGED
|
@@ -10,11 +10,11 @@ Connect your ChatGPT subscription to DeepSeek Harness with OAuth, optional GPT I
|
|
|
10
10
|
<img src="https://raw.githubusercontent.com/franksong2702/dsh-codex-connect/main/docs/assets/en/hero.jpg" alt="Codex Connect — ChatGPT OAuth for DeepSeek Harness" width="100%">
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
|
-
`dsh-codex-connect` adds the `openai-codex` model catalog and a separate ChatGPT OAuth login. Models run through Harness's normal LLM service, so streaming, tool calls, reasoning replay, compaction, filesystem controls, permission gates, and approval prompts remain Harness-owned. It does not turn a ChatGPT subscription into an OpenAI Platform API credential.
|
|
13
|
+
`dsh-codex-connect` adds the `openai-codex` model catalog and a separate ChatGPT OAuth login. Models run through Harness's normal LLM service, so streaming, tool calls, reasoning replay, compaction, filesystem controls, permission gates, and approval prompts remain Harness-owned. It does not turn a ChatGPT subscription into an OpenAI Platform API credential. When an eligible GPT Codex model is selected, the Composer also shows a conversation-scoped Fast Mode toggle and a compact weekly-quota indicator.
|
|
14
14
|
|
|
15
15
|
Installation is additive. The bundle does not replace the current default model or search route. Standalone search, `view_image`, and image generation remain disabled until explicitly enabled.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
The setup and image-result screenshots in this English guide are captured from the English-localized Harness UI. The shared Composer crop is a language-neutral feature strip; the [Chinese guide](docs/README.zh.md) uses the same strip and Chinese captures for the other screens. Model and provider identifiers keep their canonical spelling in both languages.
|
|
18
18
|
|
|
19
19
|
## Quick start (about five minutes)
|
|
20
20
|
|
|
@@ -28,7 +28,7 @@ dsh plugin --profile web add dsh-codex-connect@alpha
|
|
|
28
28
|
|
|
29
29
|
Expected result: the package is added to that profile. This does not change the profile's default model or global search route.
|
|
30
30
|
|
|
31
|
-
To reproduce this release exactly, use `dsh plugin --profile web add dsh-codex-connect@0.1.0-alpha.4.
|
|
31
|
+
To reproduce this release exactly, use `dsh plugin --profile web add dsh-codex-connect@0.1.0-alpha.4.15`. If npm is unavailable after the matching GitHub prerelease exists, use `dsh plugin --profile web add 'github:franksong2702/dsh-codex-connect#v0.1.0-alpha.4.15'`. A local checkout can be installed as `link:/absolute/path/to/dsh-codex-connect`.
|
|
32
32
|
|
|
33
33
|
### 2. Start Harness
|
|
34
34
|
|
|
@@ -85,6 +85,18 @@ dsh plugin --profile web exec dsh-codex-connect doctor --json
|
|
|
85
85
|
|
|
86
86
|
Expected result: `status --json` reports `signed-in` and exits `0`, while `doctor --json` prints one secret-free JSON document. A signed-out `status --json` exits `1`; return to step 4 instead of treating that as a plugin failure.
|
|
87
87
|
|
|
88
|
+
### Composer controls for GPT Codex conversations
|
|
89
|
+
|
|
90
|
+
The two small controls are shown only when the current conversation is using a GPT model from the `openai-codex` provider. They are session controls, not profile-wide settings:
|
|
91
|
+
|
|
92
|
+
- **Fast Mode (lightning icon)** is off by default for each conversation. Click it to request the faster `1.5×` mode; click it again to return to Standard speed. The control is bound to that conversation and does not change the selected model or other conversations. Hover or focus the icon to see the current state and its quota-consumption warning.
|
|
93
|
+
- **Weekly quota bar** is the short horizontal bar beside the model selector. Its color moves from green through yellow/orange to red as the remaining amount falls. Hover or focus it to see the exact remaining percentage and the server-provided reset time. It is hidden for non-GPT models or when usage data is unavailable.
|
|
94
|
+
- For the exact `gpt-5.3-codex-spark` model, the Composer reads the Spark weekly bucket. Other GPT Codex models read the standard Codex weekly bucket; these are separate limits.
|
|
95
|
+
|
|
96
|
+
<p align="center">
|
|
97
|
+
<img src="https://raw.githubusercontent.com/franksong2702/dsh-codex-connect/main/docs/assets/composer-capabilities.jpg" alt="DeepSeek Harness Composer with the per-conversation Fast Mode lightning control and weekly quota bar" width="820">
|
|
98
|
+
</p>
|
|
99
|
+
|
|
88
100
|
## Optional capabilities (off by default)
|
|
89
101
|
|
|
90
102
|
The installed bundle is intentionally inert beyond model-provider registration:
|
|
@@ -103,7 +115,7 @@ Open **Settings → Plugins → Plugin configuration → Codex Connect** to mana
|
|
|
103
115
|
|
|
104
116
|
- `enableSearch: true` registers Codex as an available search provider. It does not select the profile's global search route.
|
|
105
117
|
- `enableImageTool: true` enables `view_image` for approved local reads and public-network image fetches on vision-capable models.
|
|
106
|
-
- `enableImageGeneration: true` enables the prompt-only image generation tool. Use the image generation capability included with your current GPT subscription. Generated images are saved as DSH attachments and shown in the
|
|
118
|
+
- `enableImageGeneration: true` enables the prompt-only image generation tool. Use the image generation capability included with your current GPT subscription. Generated images are saved as DSH attachments and shown in the Codex Connect result gallery.
|
|
107
119
|
|
|
108
120
|
The screenshot below is an example after someone has explicitly enabled capabilities. It does not show the fresh-install default. This English guide uses the English-localized capture; the Chinese guide shows the matching Chinese-localized state.
|
|
109
121
|
|
|
@@ -124,6 +136,17 @@ This capability uses the image generation access included with your current GPT
|
|
|
124
136
|
<img src="https://raw.githubusercontent.com/franksong2702/dsh-codex-connect/main/docs/assets/en/image-generation.png" alt="English-localized Codex Connect GPT Image result with preview, copyable prompt, download action, and image details" width="780">
|
|
125
137
|
</p>
|
|
126
138
|
|
|
139
|
+
The detailed image prompt is authored by the selected GPT model. Codex Connect does not silently add image parameters: it validates the prompt-only request, forwards it through the ChatGPT subscription capability, and stores the returned image as a DSH attachment. On the result card you can scroll through and copy the complete prompt. **Try again** and **Generate another** send that card's own prompt again, so an older card is not accidentally regenerated from a newer conversation message. **Modify this image** first asks what you want to change, then continues from that card's prompt.
|
|
140
|
+
|
|
141
|
+
### Usage limits in Plugin configuration
|
|
142
|
+
|
|
143
|
+
After sign-in, the Codex Connect settings card can show several server-reported windows. They are separate buckets, not three views of one number:
|
|
144
|
+
|
|
145
|
+
- **Codex · Weekly** is the standard Codex weekly bucket used by ordinary GPT Codex models.
|
|
146
|
+
- **GPT-5.3-Codex-Spark · 5-hour** and **GPT-5.3-Codex-Spark · Weekly** are the two Spark windows returned for the Spark model.
|
|
147
|
+
|
|
148
|
+
Each bar shows the remaining percentage and its local reset time. OpenAI controls the returned windows, eligibility, and reset values; missing usage data is treated as unavailable rather than guessed.
|
|
149
|
+
|
|
127
150
|
### Change a default model or global search route separately
|
|
128
151
|
|
|
129
152
|
To make a Codex model the default for new agents, add or update the separate Harness row yourself:
|
|
@@ -180,7 +203,7 @@ Selecting Codex as the profile's global search route is another explicit change:
|
|
|
180
203
|
|
|
181
204
|
## Compatibility and security boundary
|
|
182
205
|
|
|
183
|
-
- The only verified compatibility combination is DSH plugin API packages `0.1.
|
|
206
|
+
- The only verified compatibility combination is DSH plugin API packages `0.1.1-rc.2`, `@earendil-works/pi-ai` `0.82.1`, and Node.js `^22.19.0 || >=24.0.0`; see [compatibility.json](compatibility.json). Alpha 4.15 uses the rc.2 keyed Plugin configuration slot; users of older DSH API packages should upgrade to the rc.2 API packages.
|
|
184
207
|
- Upgrade the DSH plugin API packages and `@earendil-works/pi-ai` as one group, then run `dsh-codex-connect doctor --json` and the compatibility check again. This contract does not make claims about future versions.
|
|
185
208
|
- ChatGPT plan eligibility, model access, quotas, and backend behavior are controlled by OpenAI and may change.
|
|
186
209
|
- The Codex endpoint does not enforce the ordinary Responses `max_output_tokens` field. Harness compaction still works, but that summary cap cannot be imposed server-side on this route.
|
package/compatibility.json
CHANGED
package/docs/README.zh.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<img src="https://raw.githubusercontent.com/franksong2702/dsh-codex-connect/main/docs/assets/zh/hero.jpg" alt="Codex Connect — 通过 ChatGPT OAuth 连接 DeepSeek Harness" width="100%">
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
|
-
`dsh-codex-connect` 提供 `openai-codex` 模型目录和独立的 ChatGPT OAuth 登录。模型仍走 Harness 标准 LLM 服务,因此流式输出、工具调用、reasoning replay、压缩、文件系统控制、权限门禁和审批提示仍由 Harness 负责。ChatGPT 订阅不会因此变成 OpenAI Platform API
|
|
13
|
+
`dsh-codex-connect` 提供 `openai-codex` 模型目录和独立的 ChatGPT OAuth 登录。模型仍走 Harness 标准 LLM 服务,因此流式输出、工具调用、reasoning replay、压缩、文件系统控制、权限门禁和审批提示仍由 Harness 负责。ChatGPT 订阅不会因此变成 OpenAI Platform API 凭据。选择符合条件的 GPT Codex 模型后,Composer 还会显示按对话绑定的 Fast Mode 开关和紧凑的周额度指示条。
|
|
14
14
|
|
|
15
15
|
安装是增量的:bundle 不会替换当前主模型或搜索路由;独立搜索、`view_image` 和图片生成也默认关闭,必须显式开启。
|
|
16
16
|
|
|
@@ -28,7 +28,7 @@ dsh plugin --profile web add dsh-codex-connect@alpha
|
|
|
28
28
|
|
|
29
29
|
预期结果:包被加入该 profile。这个动作不会更改 profile 的默认模型或全局搜索路由。
|
|
30
30
|
|
|
31
|
-
如需精确复现这个版本,使用 `dsh plugin --profile web add dsh-codex-connect@0.1.0-alpha.4.
|
|
31
|
+
如需精确复现这个版本,使用 `dsh plugin --profile web add dsh-codex-connect@0.1.0-alpha.4.15`。对应 GitHub prerelease 已创建但 npm 不可用时,可使用 `dsh plugin --profile web add 'github:franksong2702/dsh-codex-connect#v0.1.0-alpha.4.15'`。本地 checkout 可安装为 `link:/absolute/path/to/dsh-codex-connect`。
|
|
32
32
|
|
|
33
33
|
### 2. 启动 Harness
|
|
34
34
|
|
|
@@ -85,6 +85,18 @@ dsh plugin --profile web exec dsh-codex-connect doctor --json
|
|
|
85
85
|
|
|
86
86
|
预期结果:`status --json` 报告 `signed-in` 并以 `0` 退出,`doctor --json` 只输出一条非敏感 JSON。尚未登录时 `status --json` 会以 `1` 退出;回到第 4 步登录即可,不要把它当作插件故障。
|
|
87
87
|
|
|
88
|
+
### GPT Codex 对话中的 Composer 控件
|
|
89
|
+
|
|
90
|
+
只有当前对话选择了 `openai-codex` 提供方的 GPT 模型时,Composer 才会显示下面两个小控件。它们都是当前对话级别的控制,不是 profile 全局设置:
|
|
91
|
+
|
|
92
|
+
- **Fast Mode(闪电图标)**:每个对话默认关闭。点击后请求更快的 `1.5 倍` 模式,再点一次恢复标准速度。它只绑定当前对话,不会改变模型选择,也不会影响其他对话。鼠标悬停或键盘聚焦闪电图标,可以看到当前状态和额度消耗提示。
|
|
93
|
+
- **周额度进度条**:位于模型选择器旁边的短横条。剩余额度越低,颜色会从绿色经过黄色/橙色变为红色。鼠标悬停或键盘聚焦时,会显示精确剩余百分比和服务端提供的重置时间。非 GPT 模型或额度暂时不可用时不会显示。
|
|
94
|
+
- 对于精确模型 `gpt-5.3-codex-spark`,Composer 读取 Spark 的每周额度;其他 GPT Codex 模型读取标准 Codex 周额度,两者是分开的额度桶。
|
|
95
|
+
|
|
96
|
+
<p align="center">
|
|
97
|
+
<img src="https://raw.githubusercontent.com/franksong2702/dsh-codex-connect/main/docs/assets/composer-capabilities.jpg" alt="DeepSeek Harness Composer 中按对话绑定的 Fast Mode 闪电控件和周额度进度条" width="820">
|
|
98
|
+
</p>
|
|
99
|
+
|
|
88
100
|
## 可选能力(默认关闭)
|
|
89
101
|
|
|
90
102
|
安装后的 bundle 只注册模型提供方,默认不额外启用任何能力:
|
|
@@ -103,7 +115,7 @@ dsh plugin --profile web exec dsh-codex-connect doctor --json
|
|
|
103
115
|
|
|
104
116
|
- `enableSearch: true` 会把 Codex 注册为可选择的搜索提供方,不会把它选为 profile 的全局搜索路由。
|
|
105
117
|
- `enableImageTool: true` 会为具备视觉能力的模型启用 `view_image`,用于审批后的本地读取和公网图片获取。
|
|
106
|
-
- `enableImageGeneration: true` 会启用只接受文字描述的图片生成工具。使用你当前 GPT 订阅计划提供的图片生成能力。生成结果会保存为 DSH
|
|
118
|
+
- `enableImageGeneration: true` 会启用只接受文字描述的图片生成工具。使用你当前 GPT 订阅计划提供的图片生成能力。生成结果会保存为 DSH 附件,并通过 Codex Connect 结果画廊展示。
|
|
107
119
|
|
|
108
120
|
下图是有人显式开启能力之后的配置示例,不是新安装的默认状态。本中文指南使用中文本地化截图;English 版展示同一状态的英文截图。
|
|
109
121
|
|
|
@@ -124,6 +136,17 @@ dsh plugin --profile web exec dsh-codex-connect doctor --json
|
|
|
124
136
|
<img src="https://raw.githubusercontent.com/franksong2702/dsh-codex-connect/main/docs/assets/zh/image-generation.png" alt="Codex Connect 中文 GPT Image 结果卡片,包含图片预览、可复制提示词、下载操作和图片详情" width="780">
|
|
125
137
|
</p>
|
|
126
138
|
|
|
139
|
+
图片的详细提示词由当前选择的 GPT 模型生成。Codex Connect 不会偷偷添加图片参数:它只校验“提示词”请求,通过 ChatGPT 订阅提供的图片能力发送,并把返回图片保存为 DSH 附件。结果卡片里的提示词可以滚动查看和复制。点击 **再次尝试** 或 **再生成一张** 时,会重新发送这张卡片自己的提示词,不会因为后来出现了新的对话消息而误用最新上下文。点击 **基于此图修改** 时,模型会先询问你想改什么,再基于这张卡片的提示词继续处理。
|
|
140
|
+
|
|
141
|
+
### 插件配置中的额度说明
|
|
142
|
+
|
|
143
|
+
登录后,Codex Connect 设置卡片可能显示多个服务端额度窗口。它们是不同的额度桶,不是同一个数字重复显示:
|
|
144
|
+
|
|
145
|
+
- **Codex · 每周额度**:普通 GPT Codex 模型使用的标准 Codex 周额度。
|
|
146
|
+
- **GPT-5.3-Codex-Spark · 5 小时额度** 和 **GPT-5.3-Codex-Spark · 每周额度**:Spark 模型返回的两个独立窗口。
|
|
147
|
+
|
|
148
|
+
每条进度条都会显示剩余百分比和按本地时区格式化的重置时间。额度窗口、模型资格和重置时间由 OpenAI 返回;数据缺失时界面会显示不可用,不会自行猜测。
|
|
149
|
+
|
|
127
150
|
### 单独更改默认模型或全局搜索路由
|
|
128
151
|
|
|
129
152
|
如需把 Codex 模型设为新 agent 的默认模型,需要自行添加或修改独立的 Harness 配置项:
|
|
@@ -180,7 +203,7 @@ dsh plugin --profile web exec dsh-codex-connect doctor --json
|
|
|
180
203
|
|
|
181
204
|
## 兼容性与安全边界
|
|
182
205
|
|
|
183
|
-
- 当前唯一已验证的兼容组合是 DSH 插件 API packages `0.1.
|
|
206
|
+
- 当前唯一已验证的兼容组合是 DSH 插件 API packages `0.1.1-rc.2`、`@earendil-works/pi-ai` `0.82.1` 和 Node.js `^22.19.0 || >=24.0.0`;详见 [compatibility.json](../compatibility.json)。Alpha 4.15 使用 rc.2 的 keyed 插件配置 slot;旧版 DSH API packages 用户应升级到 rc.2 API packages。
|
|
184
207
|
- 升级时请将 DSH 插件 API packages 与 `@earendil-works/pi-ai` 作为一组升级,再运行 `dsh-codex-connect doctor --json` 和兼容性检查。本契约不对未来版本作判断。
|
|
185
208
|
- ChatGPT 套餐资格、模型权限、额度和后端行为由 OpenAI 控制,可能变化。
|
|
186
209
|
- Codex 端点不会强制普通 Responses 的 `max_output_tokens` 字段。Harness 压缩仍可工作,但这个摘要上限不能由服务端在该路由上强制。
|
|
Binary file
|
package/docs/design.md
CHANGED
|
@@ -6,7 +6,7 @@ The package registers `openai-codex` through Harness's public `LlmRuntime` and `
|
|
|
6
6
|
|
|
7
7
|
The bundle patch inserts only `llm-openai-codex`. It never writes `agent-default-model` or `web.searchProvider`. `enableSearch` and `enableImageTool` are capability gates defaulting to `false`; the optional service injections are not registered while disabled.
|
|
8
8
|
|
|
9
|
-
The Host registers `llm-openai-codex` as the plugin-owned settings namespace
|
|
9
|
+
The Host registers `llm-openai-codex` as the plugin-owned capability settings namespace. DSH's `llm-pi-ai` catalog owns the `openai-codex` configurable-provider directory entry, while Codex Connect registers the active adapter without redeclaring that entry. The browser binds the plugin namespace through Harness's settings-scope transport and renders account, quota, Save/Discard capability controls in the existing Plugin configuration card. Revision-fenced field writes preserve unrelated settings. Committed changes reconcile search and image registrations live; the default-model and global-search namespaces are never written.
|
|
10
10
|
|
|
11
11
|
## OAuth persistence
|
|
12
12
|
|
|
@@ -26,4 +26,4 @@ Before registration the plugin checks current provider ids. An existing `openai-
|
|
|
26
26
|
|
|
27
27
|
## Compatibility boundary
|
|
28
28
|
|
|
29
|
-
The Alpha pins Harness `0.1.
|
|
29
|
+
The Alpha pins Harness `0.1.1-rc.2` development dependencies and uses its keyed `settings.plugin.item` contract; supported Node.js is `^22.19.0 || >=24.0.0`. It pins `@earendil-works/pi-ai` `0.82.1`. Backend eligibility, quotas, models, and protocol details remain controlled upstream. Tests use temporary OAuth documents and mocked network responses; CI does not perform real authentication.
|
package/docs/design.zh.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
bundle patch 只插入 `llm-openai-codex`,不会写入 `agent-default-model` 或 `web.searchProvider`。`enableSearch` 与 `enableImageTool` 默认均为 `false`;关闭时不会注册对应可选服务。
|
|
8
8
|
|
|
9
|
-
Host 将 `llm-openai-codex`
|
|
9
|
+
Host 将 `llm-openai-codex` 注册为插件自有的能力 settings namespace。DSH 的 `llm-pi-ai` catalog 持有 `openai-codex` 可配置 provider 目录条目,Codex Connect 只注册实际 adapter,不重复声明该条目。浏览器通过 Harness settings-scope transport 绑定插件 namespace,把账户、额度以及带保存/放弃的能力配置放在现有“插件配置”卡片中。带 revision 防护的逐字段写入不会覆盖无关设置;提交后会即时协调搜索与图片能力的注册状态,且绝不写入默认模型或全局搜索 namespace。
|
|
10
10
|
|
|
11
11
|
## OAuth 持久化
|
|
12
12
|
|
|
@@ -22,4 +22,4 @@ Host 将 `llm-openai-codex` 注册为插件自有 settings namespace,并在 LL
|
|
|
22
22
|
|
|
23
23
|
注册前检查现有 provider id;发现 `openai-codex` 已被占用时,给出旧 bundle 或手动 provider 配置的定向迁移提示。boot-free CLI doctor 只报告包/运行时版本、OAuth 路径元数据、能力默认值和安全提示。
|
|
24
24
|
|
|
25
|
-
Alpha 固定使用 Harness `0.1.
|
|
25
|
+
Alpha 固定使用 Harness `0.1.1-rc.2` 开发依赖,并采用其 keyed `settings.plugin.item` 契约;Node.js 支持 `^22.19.0 || >=24.0.0`。`@earendil-works/pi-ai` 固定为 `0.82.1`。资格、额度、模型和后端协议仍由上游控制。测试仅使用临时 OAuth 文档和模拟网络响应,CI 不执行真实认证。
|
package/lib/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { L as diagnoseOpenAICodex, c as migrateOpenAICodexSearchHistory, ct as logoutOpenAICodex, lt as openAICodexAuthStatus, nt as OpenAICodexTrustedOriginsStore, pt as openAICodexAuthPath, rt as normalizeTrustedOrigin, st as loginOpenAICodex, z as CODEX_CONNECT_VERSION } from "./src-
|
|
2
|
+
import { L as diagnoseOpenAICodex, c as migrateOpenAICodexSearchHistory, ct as logoutOpenAICodex, lt as openAICodexAuthStatus, nt as OpenAICodexTrustedOriginsStore, pt as openAICodexAuthPath, rt as normalizeTrustedOrigin, st as loginOpenAICodex, z as CODEX_CONNECT_VERSION } from "./src-D5OQGYt6.js";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { realpathSync } from "node:fs";
|
|
5
5
|
import { spawn } from "node:child_process";
|
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 react_jsx_runtime = require("react/jsx-runtime");
|
|
9
|
-
let _deepseek_ai_dsh_client_ui_attachment = require("@deepseek-ai/dsh-client-ui-attachment");
|
|
10
9
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
11
10
|
//#region src/settings-contract.ts
|
|
12
11
|
/** Node-free settings contract shared by the Host plugin and browser card. */
|
|
@@ -158,7 +157,7 @@ window.__ModuleLoader__.load({
|
|
|
158
157
|
background: "var(--dsw-alias-brand-primary)",
|
|
159
158
|
color: "white"
|
|
160
159
|
};
|
|
161
|
-
const errorStyle$
|
|
160
|
+
const errorStyle$2 = {
|
|
162
161
|
...bodyStyle$1,
|
|
163
162
|
color: "var(--dsw-alias-state-error-primary)"
|
|
164
163
|
};
|
|
@@ -271,12 +270,12 @@ window.__ModuleLoader__.load({
|
|
|
271
270
|
children: t("settingsLoading")
|
|
272
271
|
}) : null,
|
|
273
272
|
snapshot.status === "unavailable" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
274
|
-
style: errorStyle$
|
|
273
|
+
style: errorStyle$2,
|
|
275
274
|
role: "alert",
|
|
276
275
|
children: t("settingsUnavailable")
|
|
277
276
|
}) : null,
|
|
278
277
|
snapshot.status === "ready" && !snapshot.writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
279
|
-
style: errorStyle$
|
|
278
|
+
style: errorStyle$2,
|
|
280
279
|
role: "alert",
|
|
281
280
|
children: t("settingsReadOnly")
|
|
282
281
|
}) : null,
|
|
@@ -439,12 +438,12 @@ window.__ModuleLoader__.load({
|
|
|
439
438
|
]
|
|
440
439
|
}),
|
|
441
440
|
!validModel && draft !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
442
|
-
style: errorStyle$
|
|
441
|
+
style: errorStyle$2,
|
|
443
442
|
role: "alert",
|
|
444
443
|
children: t("invalidSearchModel")
|
|
445
444
|
}) : null,
|
|
446
445
|
!validTokens && draft !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
447
|
-
style: errorStyle$
|
|
446
|
+
style: errorStyle$2,
|
|
448
447
|
role: "alert",
|
|
449
448
|
children: t("invalidSearchTokens")
|
|
450
449
|
}) : null,
|
|
@@ -460,7 +459,7 @@ window.__ModuleLoader__.load({
|
|
|
460
459
|
style: successStyle,
|
|
461
460
|
children: t("settingsSaved")
|
|
462
461
|
}) : null, feedback === "error" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
463
|
-
style: errorStyle$
|
|
462
|
+
style: errorStyle$2,
|
|
464
463
|
children: t("settingsSaveFailed")
|
|
465
464
|
}) : null]
|
|
466
465
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
@@ -563,7 +562,7 @@ window.__ModuleLoader__.load({
|
|
|
563
562
|
background: "var(--dsw-alias-brand-primary)",
|
|
564
563
|
color: "white"
|
|
565
564
|
};
|
|
566
|
-
const errorStyle = {
|
|
565
|
+
const errorStyle$1 = {
|
|
567
566
|
...bodyStyle,
|
|
568
567
|
color: "var(--dsw-alias-state-error-primary)"
|
|
569
568
|
};
|
|
@@ -701,7 +700,7 @@ window.__ModuleLoader__.load({
|
|
|
701
700
|
children: t("quotaUnavailable")
|
|
702
701
|
}) : null,
|
|
703
702
|
quotaError === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
704
|
-
style: errorStyle,
|
|
703
|
+
style: errorStyle$1,
|
|
705
704
|
children: t("quotaUnavailable")
|
|
706
705
|
})
|
|
707
706
|
]
|
|
@@ -909,7 +908,7 @@ window.__ModuleLoader__.load({
|
|
|
909
908
|
})]
|
|
910
909
|
}),
|
|
911
910
|
status.status === "error" || status.status === "reauth-required" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
912
|
-
style: errorStyle,
|
|
911
|
+
style: errorStyle$1,
|
|
913
912
|
children: status.message
|
|
914
913
|
}) : null,
|
|
915
914
|
status.status === "remote-web-origin-not-trusted" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -920,7 +919,7 @@ window.__ModuleLoader__.load({
|
|
|
920
919
|
},
|
|
921
920
|
children: [
|
|
922
921
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
923
|
-
style: errorStyle,
|
|
922
|
+
style: errorStyle$1,
|
|
924
923
|
children: t("remoteOriginDescription")
|
|
925
924
|
}),
|
|
926
925
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
@@ -941,7 +940,7 @@ window.__ModuleLoader__.load({
|
|
|
941
940
|
},
|
|
942
941
|
children: copied ? t("remoteOriginCopied") : t("remoteOriginCopy")
|
|
943
942
|
}), copyFailed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
944
|
-
style: errorStyle,
|
|
943
|
+
style: errorStyle$1,
|
|
945
944
|
children: t("remoteOriginCopyFailed")
|
|
946
945
|
}) : null]
|
|
947
946
|
})
|
|
@@ -1551,12 +1550,22 @@ window.__ModuleLoader__.load({
|
|
|
1551
1550
|
enableImageGeneration: "Enable GPT Image generation",
|
|
1552
1551
|
enableImageGenerationHelp: "Let GPT models use GPT Image to generate images in conversations.",
|
|
1553
1552
|
generating: "Generating image",
|
|
1554
|
-
generatingDetail: "Image generation is in progress.",
|
|
1553
|
+
generatingDetail: "Image generation is in progress. Stopping cancels the current turn.",
|
|
1554
|
+
cancelGeneration: "Stop this turn",
|
|
1555
|
+
cancelingGeneration: "Stopping…",
|
|
1555
1556
|
promptLabel: "Prompt used for image generation",
|
|
1556
1557
|
copyPrompt: "Copy prompt",
|
|
1557
1558
|
promptCopied: "Copied",
|
|
1558
1559
|
promptCopyFailed: "Copy unavailable",
|
|
1559
1560
|
completed: "Image generated",
|
|
1561
|
+
retryGeneration: "Try again",
|
|
1562
|
+
regenerate: "Generate another",
|
|
1563
|
+
editImage: "Modify this image",
|
|
1564
|
+
retryRequest: "Retry the previous image generation.",
|
|
1565
|
+
regenerateRequest: "Generate another image with the previous image prompt unchanged.",
|
|
1566
|
+
editRequest: "Continue from the previous image. Ask me what I want to change before generating a new image.",
|
|
1567
|
+
actionSending: "Sending…",
|
|
1568
|
+
actionFailed: "The follow-up request could not be sent.",
|
|
1560
1569
|
failed: "Image generation failed",
|
|
1561
1570
|
canceled: "Image generation canceled",
|
|
1562
1571
|
canceledDetail: "Local waiting stopped. The request may still be processing.",
|
|
@@ -1650,12 +1659,22 @@ window.__ModuleLoader__.load({
|
|
|
1650
1659
|
enableImageGeneration: "启用 GPT Image 图片生成",
|
|
1651
1660
|
enableImageGenerationHelp: "启用后,GPT 模型可以在对话中调用 GPT Image 生成图片。",
|
|
1652
1661
|
generating: "正在生成图片",
|
|
1653
|
-
generatingDetail: "
|
|
1662
|
+
generatingDetail: "图片生成正在进行中。停止操作会取消当前回合。",
|
|
1663
|
+
cancelGeneration: "停止当前回合",
|
|
1664
|
+
cancelingGeneration: "正在停止…",
|
|
1654
1665
|
promptLabel: "用于生成图片的提示词",
|
|
1655
1666
|
copyPrompt: "复制提示词",
|
|
1656
1667
|
promptCopied: "已复制",
|
|
1657
1668
|
promptCopyFailed: "无法复制",
|
|
1658
1669
|
completed: "图片已生成",
|
|
1670
|
+
retryGeneration: "再次尝试",
|
|
1671
|
+
regenerate: "再生成一张",
|
|
1672
|
+
editImage: "基于此图修改",
|
|
1673
|
+
retryRequest: "重试上一张图片生成。",
|
|
1674
|
+
regenerateRequest: "再生成一张,保持上一张图片的提示词不变。",
|
|
1675
|
+
editRequest: "基于上一张图片继续修改。请先询问我需要修改什么,再生成新图片。",
|
|
1676
|
+
actionSending: "正在发送…",
|
|
1677
|
+
actionFailed: "无法发送后续请求。",
|
|
1659
1678
|
failed: "图片生成失败",
|
|
1660
1679
|
canceled: "图片生成已取消",
|
|
1661
1680
|
canceledDetail: "本地等待已停止,请求可能仍在处理中。",
|
|
@@ -1720,6 +1739,229 @@ window.__ModuleLoader__.load({
|
|
|
1720
1739
|
};
|
|
1721
1740
|
}
|
|
1722
1741
|
//#endregion
|
|
1742
|
+
//#region src/client/CodexImageGallery.tsx
|
|
1743
|
+
/** Self-contained result-image gallery for the tool-call view.
|
|
1744
|
+
*
|
|
1745
|
+
* DSH 0.1.1-rc.2 keeps the attachment package's React atoms behind its
|
|
1746
|
+
* conversation slots. A tool-call view cannot render those slots, so this
|
|
1747
|
+
* gallery owns only the durable-image presentation it needs and receives all
|
|
1748
|
+
* stateful work through props.
|
|
1749
|
+
*/
|
|
1750
|
+
const galleryStyle = {
|
|
1751
|
+
display: "flex",
|
|
1752
|
+
flexWrap: "wrap",
|
|
1753
|
+
alignItems: "flex-start",
|
|
1754
|
+
gap: 8
|
|
1755
|
+
};
|
|
1756
|
+
const imageFrameStyle = {
|
|
1757
|
+
display: "grid",
|
|
1758
|
+
placeItems: "center",
|
|
1759
|
+
padding: 0,
|
|
1760
|
+
overflow: "hidden",
|
|
1761
|
+
border: "1px solid var(--dsw-alias-border-l2)",
|
|
1762
|
+
borderRadius: 8,
|
|
1763
|
+
background: "var(--dsw-alias-bg-base)",
|
|
1764
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
1765
|
+
cursor: "pointer"
|
|
1766
|
+
};
|
|
1767
|
+
const loadingStyle = {
|
|
1768
|
+
padding: 10,
|
|
1769
|
+
fontSize: 12
|
|
1770
|
+
};
|
|
1771
|
+
const errorStyle = {
|
|
1772
|
+
minHeight: 32,
|
|
1773
|
+
padding: "6px 10px",
|
|
1774
|
+
border: "1px solid var(--dsw-alias-border-l2)",
|
|
1775
|
+
borderRadius: 7,
|
|
1776
|
+
background: "transparent",
|
|
1777
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
1778
|
+
cursor: "pointer"
|
|
1779
|
+
};
|
|
1780
|
+
const lightboxStyle = {
|
|
1781
|
+
position: "relative",
|
|
1782
|
+
display: "grid",
|
|
1783
|
+
maxWidth: "min(96vw, 1200px)",
|
|
1784
|
+
maxHeight: "96vh",
|
|
1785
|
+
minWidth: 0,
|
|
1786
|
+
minHeight: 0
|
|
1787
|
+
};
|
|
1788
|
+
const lightboxImageStyle = {
|
|
1789
|
+
display: "block",
|
|
1790
|
+
maxWidth: "96vw",
|
|
1791
|
+
maxHeight: "92vh",
|
|
1792
|
+
objectFit: "contain"
|
|
1793
|
+
};
|
|
1794
|
+
const closeStyle = {
|
|
1795
|
+
position: "absolute",
|
|
1796
|
+
top: 8,
|
|
1797
|
+
right: 8,
|
|
1798
|
+
zIndex: 1,
|
|
1799
|
+
width: 32,
|
|
1800
|
+
height: 32,
|
|
1801
|
+
border: "1px solid rgba(255,255,255,0.35)",
|
|
1802
|
+
borderRadius: 7,
|
|
1803
|
+
background: "rgba(0,0,0,0.5)",
|
|
1804
|
+
color: "#fff",
|
|
1805
|
+
font: "inherit",
|
|
1806
|
+
cursor: "pointer"
|
|
1807
|
+
};
|
|
1808
|
+
function singleFit(attachment) {
|
|
1809
|
+
const natural = attachment.width / attachment.height;
|
|
1810
|
+
const ratio = Math.min(4, Math.max(.25, natural));
|
|
1811
|
+
const box = ratio >= 1 ? {
|
|
1812
|
+
width: 240,
|
|
1813
|
+
height: 240 / ratio
|
|
1814
|
+
} : {
|
|
1815
|
+
width: 240 * ratio,
|
|
1816
|
+
height: 240
|
|
1817
|
+
};
|
|
1818
|
+
const scale = Math.min(1, attachment.width / box.width, attachment.height / box.height);
|
|
1819
|
+
return {
|
|
1820
|
+
width: Math.max(1, Math.round(box.width * scale)),
|
|
1821
|
+
height: Math.max(1, Math.round(box.height * scale)),
|
|
1822
|
+
objectPosition: natural < .25 ? "center top" : natural > 4 ? "left center" : "center"
|
|
1823
|
+
};
|
|
1824
|
+
}
|
|
1825
|
+
function CodexImageLightbox({ src, alt, labels, opener, onClose }) {
|
|
1826
|
+
const closeButton = (0, react.useRef)(null);
|
|
1827
|
+
(0, react.useEffect)(() => {
|
|
1828
|
+
closeButton.current?.focus();
|
|
1829
|
+
return () => {
|
|
1830
|
+
opener?.focus();
|
|
1831
|
+
};
|
|
1832
|
+
}, [opener]);
|
|
1833
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
1834
|
+
open: true,
|
|
1835
|
+
onClose,
|
|
1836
|
+
title: labels.dialog,
|
|
1837
|
+
closeLabel: labels.close,
|
|
1838
|
+
headless: true,
|
|
1839
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1840
|
+
style: lightboxStyle,
|
|
1841
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1842
|
+
ref: closeButton,
|
|
1843
|
+
type: "button",
|
|
1844
|
+
"aria-label": labels.close,
|
|
1845
|
+
title: labels.close,
|
|
1846
|
+
style: closeStyle,
|
|
1847
|
+
onClick: onClose,
|
|
1848
|
+
children: "×"
|
|
1849
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
1850
|
+
src,
|
|
1851
|
+
alt,
|
|
1852
|
+
style: lightboxImageStyle
|
|
1853
|
+
})]
|
|
1854
|
+
})
|
|
1855
|
+
});
|
|
1856
|
+
}
|
|
1857
|
+
function CodexMessageImage({ attachment, load, variant, labels }) {
|
|
1858
|
+
const [src, setSrc] = (0, react.useState)(null);
|
|
1859
|
+
const [error, setError] = (0, react.useState)(false);
|
|
1860
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
1861
|
+
const [attempt, setAttempt] = (0, react.useState)(0);
|
|
1862
|
+
const opener = (0, react.useRef)(null);
|
|
1863
|
+
const retry = (0, react.useCallback)(() => {
|
|
1864
|
+
setAttempt((value) => value + 1);
|
|
1865
|
+
}, []);
|
|
1866
|
+
const closeLightbox = (0, react.useCallback)(() => {
|
|
1867
|
+
setOpen(false);
|
|
1868
|
+
}, []);
|
|
1869
|
+
const fit = (0, react.useMemo)(() => variant === "single" ? singleFit(attachment) : void 0, [
|
|
1870
|
+
attachment.attachmentId,
|
|
1871
|
+
attachment.height,
|
|
1872
|
+
attachment.width,
|
|
1873
|
+
variant
|
|
1874
|
+
]);
|
|
1875
|
+
(0, react.useEffect)(() => {
|
|
1876
|
+
let live = true;
|
|
1877
|
+
setError(false);
|
|
1878
|
+
setSrc(null);
|
|
1879
|
+
load(attachment).then((url) => {
|
|
1880
|
+
if (live) setSrc(url);
|
|
1881
|
+
}).catch(() => {
|
|
1882
|
+
if (live) setError(true);
|
|
1883
|
+
});
|
|
1884
|
+
return () => {
|
|
1885
|
+
live = false;
|
|
1886
|
+
};
|
|
1887
|
+
}, [
|
|
1888
|
+
attachment.attachmentId,
|
|
1889
|
+
attachment.bytes,
|
|
1890
|
+
attachment.height,
|
|
1891
|
+
attachment.mediaType,
|
|
1892
|
+
attachment.name,
|
|
1893
|
+
attachment.width,
|
|
1894
|
+
attempt,
|
|
1895
|
+
load
|
|
1896
|
+
]);
|
|
1897
|
+
const label = attachment.name ?? labels.image;
|
|
1898
|
+
if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1899
|
+
type: "button",
|
|
1900
|
+
style: errorStyle,
|
|
1901
|
+
"data-variant": variant,
|
|
1902
|
+
onClick: retry,
|
|
1903
|
+
children: labels.loadFailed
|
|
1904
|
+
});
|
|
1905
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1906
|
+
type: "button",
|
|
1907
|
+
ref: opener,
|
|
1908
|
+
style: fit === void 0 ? {
|
|
1909
|
+
...imageFrameStyle,
|
|
1910
|
+
width: 64,
|
|
1911
|
+
height: 64
|
|
1912
|
+
} : {
|
|
1913
|
+
...imageFrameStyle,
|
|
1914
|
+
width: fit.width,
|
|
1915
|
+
height: fit.height
|
|
1916
|
+
},
|
|
1917
|
+
"data-variant": variant,
|
|
1918
|
+
title: labels.open,
|
|
1919
|
+
"aria-label": labels.openNamed(label),
|
|
1920
|
+
onClick: () => {
|
|
1921
|
+
if (src !== null) setOpen(true);
|
|
1922
|
+
},
|
|
1923
|
+
children: src === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1924
|
+
style: loadingStyle,
|
|
1925
|
+
children: labels.loading
|
|
1926
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
1927
|
+
src,
|
|
1928
|
+
alt: label,
|
|
1929
|
+
style: {
|
|
1930
|
+
display: "block",
|
|
1931
|
+
width: "100%",
|
|
1932
|
+
height: "100%",
|
|
1933
|
+
objectFit: "cover",
|
|
1934
|
+
objectPosition: fit?.objectPosition
|
|
1935
|
+
}
|
|
1936
|
+
})
|
|
1937
|
+
}), open && src !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodexImageLightbox, {
|
|
1938
|
+
src,
|
|
1939
|
+
alt: label,
|
|
1940
|
+
labels: labels.lightbox,
|
|
1941
|
+
opener: opener.current,
|
|
1942
|
+
onClose: closeLightbox
|
|
1943
|
+
}) : null] });
|
|
1944
|
+
}
|
|
1945
|
+
/** Render durable generated images without relying on rc.2 private React atoms. */
|
|
1946
|
+
function CodexImageGallery({ images, load, align, labels }) {
|
|
1947
|
+
if (images.length === 0) return null;
|
|
1948
|
+
const variant = images.length === 1 ? "single" : "tile";
|
|
1949
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1950
|
+
"data-testid": "codex-image-gallery",
|
|
1951
|
+
"data-align": align,
|
|
1952
|
+
style: {
|
|
1953
|
+
...galleryStyle,
|
|
1954
|
+
justifyContent: align === "end" ? "flex-end" : "flex-start"
|
|
1955
|
+
},
|
|
1956
|
+
children: images.map((image, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodexMessageImage, {
|
|
1957
|
+
...image,
|
|
1958
|
+
load,
|
|
1959
|
+
variant,
|
|
1960
|
+
labels
|
|
1961
|
+
}, `${image.attachment.attachmentId}:${index}`))
|
|
1962
|
+
});
|
|
1963
|
+
}
|
|
1964
|
+
//#endregion
|
|
1723
1965
|
//#region src/client/CodexImageToolView.tsx
|
|
1724
1966
|
/** Native browser view for Codex image-generation tool results. */
|
|
1725
1967
|
const shell = {
|
|
@@ -1757,6 +1999,12 @@ window.__ModuleLoader__.load({
|
|
|
1757
1999
|
font: "inherit",
|
|
1758
2000
|
cursor: "pointer"
|
|
1759
2001
|
};
|
|
2002
|
+
const actionRow = {
|
|
2003
|
+
display: "flex",
|
|
2004
|
+
flexWrap: "wrap",
|
|
2005
|
+
alignItems: "center",
|
|
2006
|
+
gap: 8
|
|
2007
|
+
};
|
|
1760
2008
|
const promptText = {
|
|
1761
2009
|
boxSizing: "border-box",
|
|
1762
2010
|
width: "100%",
|
|
@@ -1872,6 +2120,62 @@ window.__ModuleLoader__.load({
|
|
|
1872
2120
|
if (decoded !== void 0) return decoded.prompt;
|
|
1873
2121
|
return block.call === null ? void 0 : promptFromArgs(block.call.argsRaw);
|
|
1874
2122
|
}
|
|
2123
|
+
function useSessionActions(sessionId, sessions) {
|
|
2124
|
+
const [pending, setPending] = (0, react.useState)(null);
|
|
2125
|
+
const [failed, setFailed] = (0, react.useState)(false);
|
|
2126
|
+
const alive = (0, react.useRef)(true);
|
|
2127
|
+
(0, react.useEffect)(() => () => {
|
|
2128
|
+
alive.current = false;
|
|
2129
|
+
}, []);
|
|
2130
|
+
const run = (0, react.useCallback)(async (actionName, content) => {
|
|
2131
|
+
if (pending !== null) return false;
|
|
2132
|
+
const binding = sessions.binding(sessionId);
|
|
2133
|
+
if (binding === void 0) {
|
|
2134
|
+
setFailed(true);
|
|
2135
|
+
return false;
|
|
2136
|
+
}
|
|
2137
|
+
setFailed(false);
|
|
2138
|
+
setPending(actionName);
|
|
2139
|
+
try {
|
|
2140
|
+
const accepted = (actionName === "cancel" ? await binding.session.cancel() : await binding.session.prompt(content ?? [], "queue")).ok;
|
|
2141
|
+
if (alive.current) {
|
|
2142
|
+
setPending(null);
|
|
2143
|
+
setFailed(!accepted);
|
|
2144
|
+
}
|
|
2145
|
+
return accepted;
|
|
2146
|
+
} catch {
|
|
2147
|
+
if (alive.current) {
|
|
2148
|
+
setPending(null);
|
|
2149
|
+
setFailed(true);
|
|
2150
|
+
}
|
|
2151
|
+
return false;
|
|
2152
|
+
}
|
|
2153
|
+
}, [
|
|
2154
|
+
pending,
|
|
2155
|
+
sessionId,
|
|
2156
|
+
sessions
|
|
2157
|
+
]);
|
|
2158
|
+
return {
|
|
2159
|
+
pending,
|
|
2160
|
+
failed,
|
|
2161
|
+
cancel: (0, react.useCallback)(() => run("cancel"), [run]),
|
|
2162
|
+
followUp: (0, react.useCallback)((text) => run("follow-up", [{
|
|
2163
|
+
type: "text",
|
|
2164
|
+
text
|
|
2165
|
+
}]), [run])
|
|
2166
|
+
};
|
|
2167
|
+
}
|
|
2168
|
+
function followUpPrompt(kind, prompt, t) {
|
|
2169
|
+
if (kind === "edit") return `${prompt}\n\n${t("editRequest")}`;
|
|
2170
|
+
return prompt;
|
|
2171
|
+
}
|
|
2172
|
+
function ActionError({ visible, t }) {
|
|
2173
|
+
return visible ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2174
|
+
role: "status",
|
|
2175
|
+
style: detail,
|
|
2176
|
+
children: t("actionFailed")
|
|
2177
|
+
}) : null;
|
|
2178
|
+
}
|
|
1875
2179
|
function PromptPanel({ prompt, t }) {
|
|
1876
2180
|
const [copyState, setCopyState] = (0, react.useState)("idle");
|
|
1877
2181
|
const [hovered, setHovered] = (0, react.useState)(false);
|
|
@@ -2084,24 +2388,48 @@ window.__ModuleLoader__.load({
|
|
|
2084
2388
|
}
|
|
2085
2389
|
function CodexImageToolView({ block, sessionId, t, sessions }) {
|
|
2086
2390
|
const load = useImageLoader(sessionId, sessions);
|
|
2391
|
+
const sessionActions = useSessionActions(sessionId, sessions);
|
|
2087
2392
|
const galleryLabels = (0, react.useMemo)(() => labels(t), [t]);
|
|
2088
2393
|
const prompt = promptFor(block);
|
|
2394
|
+
const decoded = (0, react.useMemo)(() => presentation(block), [block]);
|
|
2089
2395
|
if (!("kind" in block)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResponsiveCard, {
|
|
2090
2396
|
label: t("generating"),
|
|
2091
|
-
visual: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
}
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2397
|
+
visual: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2398
|
+
style: {
|
|
2399
|
+
display: "grid",
|
|
2400
|
+
gap: 10
|
|
2401
|
+
},
|
|
2402
|
+
children: [
|
|
2403
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2404
|
+
style: header,
|
|
2405
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("generating") })
|
|
2406
|
+
}),
|
|
2407
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("progress", {
|
|
2408
|
+
style: progress,
|
|
2409
|
+
"aria-label": t("generating")
|
|
2410
|
+
}),
|
|
2411
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2412
|
+
style: detail,
|
|
2413
|
+
children: t("generatingDetail")
|
|
2414
|
+
}),
|
|
2415
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2416
|
+
style: actionRow,
|
|
2417
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2418
|
+
type: "button",
|
|
2419
|
+
style: action,
|
|
2420
|
+
disabled: sessionActions.pending !== null,
|
|
2421
|
+
"aria-busy": sessionActions.pending === "cancel",
|
|
2422
|
+
onClick: () => {
|
|
2423
|
+
sessionActions.cancel();
|
|
2424
|
+
},
|
|
2425
|
+
children: sessionActions.pending === "cancel" ? t("cancelingGeneration") : t("cancelGeneration")
|
|
2426
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionError, {
|
|
2427
|
+
visible: sessionActions.failed,
|
|
2428
|
+
t
|
|
2429
|
+
})]
|
|
2430
|
+
})
|
|
2431
|
+
]
|
|
2432
|
+
}),
|
|
2105
2433
|
side: prompt === void 0 ? void 0 : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PromptPanel, {
|
|
2106
2434
|
prompt,
|
|
2107
2435
|
t
|
|
@@ -2117,10 +2445,29 @@ window.__ModuleLoader__.load({
|
|
|
2117
2445
|
display: "grid",
|
|
2118
2446
|
gap: 10
|
|
2119
2447
|
},
|
|
2120
|
-
children: [
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2448
|
+
children: [
|
|
2449
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: state.title }),
|
|
2450
|
+
state.detail === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2451
|
+
style: detail,
|
|
2452
|
+
children: state.detail
|
|
2453
|
+
}),
|
|
2454
|
+
prompt === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2455
|
+
style: actionRow,
|
|
2456
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2457
|
+
type: "button",
|
|
2458
|
+
style: action,
|
|
2459
|
+
disabled: sessionActions.pending !== null,
|
|
2460
|
+
"aria-busy": sessionActions.pending === "follow-up",
|
|
2461
|
+
onClick: () => {
|
|
2462
|
+
sessionActions.followUp(followUpPrompt("retry", prompt, t));
|
|
2463
|
+
},
|
|
2464
|
+
children: sessionActions.pending === "follow-up" ? t("actionSending") : t("retryGeneration")
|
|
2465
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionError, {
|
|
2466
|
+
visible: sessionActions.failed,
|
|
2467
|
+
t
|
|
2468
|
+
})]
|
|
2469
|
+
})
|
|
2470
|
+
]
|
|
2124
2471
|
}),
|
|
2125
2472
|
side: prompt === void 0 ? void 0 : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PromptPanel, {
|
|
2126
2473
|
prompt,
|
|
@@ -2128,7 +2475,6 @@ window.__ModuleLoader__.load({
|
|
|
2128
2475
|
})
|
|
2129
2476
|
});
|
|
2130
2477
|
}
|
|
2131
|
-
const decoded = presentation(block);
|
|
2132
2478
|
if (decoded === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
2133
2479
|
style: shell,
|
|
2134
2480
|
role: "status",
|
|
@@ -2152,7 +2498,7 @@ window.__ModuleLoader__.load({
|
|
|
2152
2498
|
visual: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2153
2499
|
style: header,
|
|
2154
2500
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("completed") })
|
|
2155
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
2501
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodexImageGallery, {
|
|
2156
2502
|
images: decoded.images.map((attachment) => ({ attachment })),
|
|
2157
2503
|
load,
|
|
2158
2504
|
align: "start",
|
|
@@ -2163,6 +2509,35 @@ window.__ModuleLoader__.load({
|
|
|
2163
2509
|
prompt: decoded.prompt,
|
|
2164
2510
|
t
|
|
2165
2511
|
}),
|
|
2512
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2513
|
+
style: actionRow,
|
|
2514
|
+
children: [
|
|
2515
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2516
|
+
type: "button",
|
|
2517
|
+
style: action,
|
|
2518
|
+
disabled: sessionActions.pending !== null,
|
|
2519
|
+
"aria-busy": sessionActions.pending === "follow-up",
|
|
2520
|
+
onClick: () => {
|
|
2521
|
+
sessionActions.followUp(followUpPrompt("regenerate", decoded.prompt, t));
|
|
2522
|
+
},
|
|
2523
|
+
children: sessionActions.pending === "follow-up" ? t("actionSending") : t("regenerate")
|
|
2524
|
+
}),
|
|
2525
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2526
|
+
type: "button",
|
|
2527
|
+
style: action,
|
|
2528
|
+
disabled: sessionActions.pending !== null,
|
|
2529
|
+
"aria-busy": sessionActions.pending === "follow-up",
|
|
2530
|
+
onClick: () => {
|
|
2531
|
+
sessionActions.followUp(followUpPrompt("edit", decoded.prompt, t));
|
|
2532
|
+
},
|
|
2533
|
+
children: sessionActions.pending === "follow-up" ? t("actionSending") : t("editImage")
|
|
2534
|
+
}),
|
|
2535
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionError, {
|
|
2536
|
+
visible: sessionActions.failed,
|
|
2537
|
+
t
|
|
2538
|
+
})
|
|
2539
|
+
]
|
|
2540
|
+
}),
|
|
2166
2541
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2167
2542
|
style: {
|
|
2168
2543
|
display: "flex",
|
package/lib/index.d.ts
CHANGED
|
@@ -125,7 +125,7 @@ declare const IMAGE_GENERATE_TOOL_NAME = "codex_connect_image_generate";
|
|
|
125
125
|
//#region src/compatibility.d.ts
|
|
126
126
|
declare const COMPATIBILITY_SCHEMA_VERSION: 1;
|
|
127
127
|
declare const SUPPORTED_NODE_RANGE = "^22.19.0 || >=24.0.0";
|
|
128
|
-
declare const SUPPORTED_DSH_PLUGIN_API_VERSION = "0.1.
|
|
128
|
+
declare const SUPPORTED_DSH_PLUGIN_API_VERSION = "0.1.1-rc.2";
|
|
129
129
|
declare const SUPPORTED_PI_AI_VERSION = "0.82.1";
|
|
130
130
|
declare const PI_AI_PACKAGE = "@earendil-works/pi-ai";
|
|
131
131
|
declare const DSH_PLUGIN_API_PACKAGES: readonly ["@deepseek-ai/dsh-agent", "@deepseek-ai/dsh-atomic-write", "@deepseek-ai/dsh-attachment", "@deepseek-ai/dsh-home-paths", "@deepseek-ai/dsh-host-webserver", "@deepseek-ai/dsh-invariants", "@deepseek-ai/dsh-llm", "@deepseek-ai/dsh-llm-pi-ai", "@deepseek-ai/dsh-fs", "@deepseek-ai/dsh-session", "@deepseek-ai/dsh-settings", "@deepseek-ai/dsh-tools", "@deepseek-ai/dsh-web"];
|
|
@@ -169,7 +169,7 @@ declare const COMPATIBILITY_CONTRACT: {
|
|
|
169
169
|
readonly node: "^22.19.0 || >=24.0.0";
|
|
170
170
|
};
|
|
171
171
|
readonly dshPluginApi: {
|
|
172
|
-
readonly version: "0.1.
|
|
172
|
+
readonly version: "0.1.1-rc.2";
|
|
173
173
|
readonly packages: readonly ["@deepseek-ai/dsh-agent", "@deepseek-ai/dsh-atomic-write", "@deepseek-ai/dsh-attachment", "@deepseek-ai/dsh-home-paths", "@deepseek-ai/dsh-host-webserver", "@deepseek-ai/dsh-invariants", "@deepseek-ai/dsh-llm", "@deepseek-ai/dsh-llm-pi-ai", "@deepseek-ai/dsh-fs", "@deepseek-ai/dsh-session", "@deepseek-ai/dsh-settings", "@deepseek-ai/dsh-tools", "@deepseek-ai/dsh-web"];
|
|
174
174
|
};
|
|
175
175
|
readonly piAi: {
|
|
@@ -517,7 +517,7 @@ declare module '@deepseek-ai/cordis' {
|
|
|
517
517
|
declare const name = "llm-openai-codex";
|
|
518
518
|
/** The model registry required before the provider can register. */
|
|
519
519
|
declare const inject: string[];
|
|
520
|
-
/** Branded Host settings namespace
|
|
520
|
+
/** Branded Host settings namespace for Codex Connect capability configuration. */
|
|
521
521
|
declare const OPENAI_CODEX_SETTINGS_NS: import("@deepseek-ai/dsh-settings").SettingsNamespace;
|
|
522
522
|
/** Composite model and standalone-search configuration. */
|
|
523
523
|
interface Config {
|
package/lib/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as OPENAI_CODEX_FAST_MODE_MAX_SESSIONS, A as OPENAI_CODEX_TRANSPORT_SERVICE, B as COMPATIBILITY_CONTRACT, C as OPENAI_CODEX_IMAGE_MAX_COUNT, D as OPENAI_CODEX_IMAGE_REQUEST_TIMEOUT_MS, E as OPENAI_CODEX_IMAGE_PROMPT_MAX_LENGTH, F as IMAGE_GENERATE_TOOL_NAME, G as SUPPORTED_DSH_PLUGIN_API_VERSION, H as COMPATIBILITY_SCHEMA_VERSION, I as assertNoOpenAICodexProviderConflict, J as assessCompatibility, K as SUPPORTED_NODE_RANGE, L as diagnoseOpenAICodex, M as OpenAICodexTransportError, N as isOpenAICodexTransportError, O as OPENAI_CODEX_TRANSPORT_API_VERSION, P as VIEW_IMAGE_TOOL_NAME, Q as FastModeRegistry, R as openAICodexConflictMessage, S as OPENAI_CODEX_IMAGE_GENERATION_URL, T as OPENAI_CODEX_IMAGE_MAX_RESPONSE_BYTES, U as DSH_PLUGIN_API_PACKAGES, V as COMPATIBILITY_PACKAGES, W as PI_AI_PACKAGE, X as evaluateCompatibility, Y as detectCompatibility, Z as OPENAI_CODEX_FAST_MODE_PATH, _ as DEFAULT_OPENAI_CODEX_SEARCH_MODEL, a as name, at as parseOpenAICodexUsage, b as decodeOpenAICodexSettings, c as migrateOpenAICodexSearchHistory, ct as logoutOpenAICodex, d as OPENAI_CODEX_SEARCH_URL, dt as OPENAI_CODEX_PROVIDER, et as OPENAI_CODEX_FAST_MODE_MAX_SESSION_ID_LENGTH, f as OpenAICodexSearchProvider, ft as OpenAICodexCredentialStore, g as DEFAULT_OPENAI_CODEX_SEARCH_MODE, h as DEFAULT_OPENAI_CODEX_SEARCH_MAX_OUTPUT_TOKENS, i as inject, it as OPENAI_CODEX_USAGE_URL, j as OpenAICodexTransport, k as OPENAI_CODEX_TRANSPORT_ERROR_CODES, l as OPENAI_CODEX_BASE_URL, lt as openAICodexAuthStatus, m as DEFAULT_OPENAI_CODEX_SEARCH_CONTEXT_SIZE, n as OPENAI_CODEX_SETTINGS_NS, o as OPENAI_CODEX_HISTORY_BACKUP_SUFFIX, ot as readOpenAICodexRateLimits, p as mapOpenAICodexSearchResponse, pt as openAICodexAuthPath, q as SUPPORTED_PI_AI_VERSION, r as apply, s as OPENAI_CODEX_SEARCH_MODEL_REQUEST_EVENT, st as loginOpenAICodex, t as Config, tt as isFastModeSessionId, u as OPENAI_CODEX_SEARCH_PROVIDER, ut as OPENAI_CODEX_AUTH_FILENAME, v as DEFAULT_OPENAI_CODEX_SETTINGS, w as OPENAI_CODEX_IMAGE_MAX_ERROR_BYTES, x as resolveOpenAICodexSettings, y as OPENAI_CODEX_SETTINGS_NAMESPACE } from "./src-
|
|
1
|
+
import { $ as OPENAI_CODEX_FAST_MODE_MAX_SESSIONS, A as OPENAI_CODEX_TRANSPORT_SERVICE, B as COMPATIBILITY_CONTRACT, C as OPENAI_CODEX_IMAGE_MAX_COUNT, D as OPENAI_CODEX_IMAGE_REQUEST_TIMEOUT_MS, E as OPENAI_CODEX_IMAGE_PROMPT_MAX_LENGTH, F as IMAGE_GENERATE_TOOL_NAME, G as SUPPORTED_DSH_PLUGIN_API_VERSION, H as COMPATIBILITY_SCHEMA_VERSION, I as assertNoOpenAICodexProviderConflict, J as assessCompatibility, K as SUPPORTED_NODE_RANGE, L as diagnoseOpenAICodex, M as OpenAICodexTransportError, N as isOpenAICodexTransportError, O as OPENAI_CODEX_TRANSPORT_API_VERSION, P as VIEW_IMAGE_TOOL_NAME, Q as FastModeRegistry, R as openAICodexConflictMessage, S as OPENAI_CODEX_IMAGE_GENERATION_URL, T as OPENAI_CODEX_IMAGE_MAX_RESPONSE_BYTES, U as DSH_PLUGIN_API_PACKAGES, V as COMPATIBILITY_PACKAGES, W as PI_AI_PACKAGE, X as evaluateCompatibility, Y as detectCompatibility, Z as OPENAI_CODEX_FAST_MODE_PATH, _ as DEFAULT_OPENAI_CODEX_SEARCH_MODEL, a as name, at as parseOpenAICodexUsage, b as decodeOpenAICodexSettings, c as migrateOpenAICodexSearchHistory, ct as logoutOpenAICodex, d as OPENAI_CODEX_SEARCH_URL, dt as OPENAI_CODEX_PROVIDER, et as OPENAI_CODEX_FAST_MODE_MAX_SESSION_ID_LENGTH, f as OpenAICodexSearchProvider, ft as OpenAICodexCredentialStore, g as DEFAULT_OPENAI_CODEX_SEARCH_MODE, h as DEFAULT_OPENAI_CODEX_SEARCH_MAX_OUTPUT_TOKENS, i as inject, it as OPENAI_CODEX_USAGE_URL, j as OpenAICodexTransport, k as OPENAI_CODEX_TRANSPORT_ERROR_CODES, l as OPENAI_CODEX_BASE_URL, lt as openAICodexAuthStatus, m as DEFAULT_OPENAI_CODEX_SEARCH_CONTEXT_SIZE, n as OPENAI_CODEX_SETTINGS_NS, o as OPENAI_CODEX_HISTORY_BACKUP_SUFFIX, ot as readOpenAICodexRateLimits, p as mapOpenAICodexSearchResponse, pt as openAICodexAuthPath, q as SUPPORTED_PI_AI_VERSION, r as apply, s as OPENAI_CODEX_SEARCH_MODEL_REQUEST_EVENT, st as loginOpenAICodex, t as Config, tt as isFastModeSessionId, u as OPENAI_CODEX_SEARCH_PROVIDER, ut as OPENAI_CODEX_AUTH_FILENAME, v as DEFAULT_OPENAI_CODEX_SETTINGS, w as OPENAI_CODEX_IMAGE_MAX_ERROR_BYTES, x as resolveOpenAICodexSettings, y as OPENAI_CODEX_SETTINGS_NAMESPACE } from "./src-D5OQGYt6.js";
|
|
2
2
|
export { COMPATIBILITY_CONTRACT, COMPATIBILITY_PACKAGES, COMPATIBILITY_SCHEMA_VERSION, Config, DEFAULT_OPENAI_CODEX_SEARCH_CONTEXT_SIZE, DEFAULT_OPENAI_CODEX_SEARCH_MAX_OUTPUT_TOKENS, DEFAULT_OPENAI_CODEX_SEARCH_MODE, DEFAULT_OPENAI_CODEX_SEARCH_MODEL, DEFAULT_OPENAI_CODEX_SETTINGS, DSH_PLUGIN_API_PACKAGES, FastModeRegistry, FastModeRegistry as OpenAICodexFastModeRegistry, IMAGE_GENERATE_TOOL_NAME, OPENAI_CODEX_AUTH_FILENAME, OPENAI_CODEX_BASE_URL, OPENAI_CODEX_FAST_MODE_MAX_SESSIONS, OPENAI_CODEX_FAST_MODE_MAX_SESSION_ID_LENGTH, OPENAI_CODEX_FAST_MODE_PATH, OPENAI_CODEX_HISTORY_BACKUP_SUFFIX, OPENAI_CODEX_IMAGE_GENERATION_URL, OPENAI_CODEX_IMAGE_MAX_COUNT, OPENAI_CODEX_IMAGE_MAX_ERROR_BYTES, OPENAI_CODEX_IMAGE_MAX_RESPONSE_BYTES, OPENAI_CODEX_IMAGE_PROMPT_MAX_LENGTH, OPENAI_CODEX_IMAGE_REQUEST_TIMEOUT_MS, OPENAI_CODEX_PROVIDER, OPENAI_CODEX_SEARCH_MODEL_REQUEST_EVENT, OPENAI_CODEX_SEARCH_PROVIDER, OPENAI_CODEX_SEARCH_URL, OPENAI_CODEX_SETTINGS_NAMESPACE, OPENAI_CODEX_SETTINGS_NS, OPENAI_CODEX_TRANSPORT_API_VERSION, OPENAI_CODEX_TRANSPORT_ERROR_CODES, OPENAI_CODEX_TRANSPORT_SERVICE, OPENAI_CODEX_USAGE_URL, OpenAICodexCredentialStore, OpenAICodexSearchProvider, OpenAICodexTransport, OpenAICodexTransportError, PI_AI_PACKAGE, SUPPORTED_DSH_PLUGIN_API_VERSION, SUPPORTED_NODE_RANGE, SUPPORTED_PI_AI_VERSION, VIEW_IMAGE_TOOL_NAME, apply, assertNoOpenAICodexProviderConflict, assessCompatibility, decodeOpenAICodexSettings, detectCompatibility, diagnoseOpenAICodex, evaluateCompatibility, inject, isFastModeSessionId, isOpenAICodexTransportError, loginOpenAICodex, logoutOpenAICodex, mapOpenAICodexSearchResponse, migrateOpenAICodexSearchHistory, name, openAICodexAuthPath, openAICodexAuthStatus, openAICodexConflictMessage, parseOpenAICodexUsage, readOpenAICodexRateLimits, resolveOpenAICodexSettings };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { deepEqualJson, installSettingsSection, settingsNamespace } from "@deepseek-ai/dsh-settings";
|
|
4
|
-
import { createModels } from "@earendil-works/pi-ai";
|
|
4
|
+
import { createModels, defaultProviderAuthContext } from "@earendil-works/pi-ai";
|
|
5
5
|
import { openaiCodexProvider } from "@earendil-works/pi-ai/providers/openai-codex";
|
|
6
6
|
import { createUserMessage, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
7
7
|
import { PiAiAdapter } from "@deepseek-ai/dsh-llm-pi-ai";
|
|
@@ -166,6 +166,12 @@ var OpenAICodexCredentialStore = class {
|
|
|
166
166
|
/** OpenAI Codex adapter assembled from public dsh-llm-pi-ai extension points. */
|
|
167
167
|
/** Provider idle ceiling used by the composite route. */
|
|
168
168
|
const OPENAI_CODEX_STREAM_IDLE_TIMEOUT_MS = 3e5;
|
|
169
|
+
/** rc.2 default maximum base64 image payload retained in one request. */
|
|
170
|
+
const OPENAI_CODEX_MAX_REQUEST_IMAGE_BYTES = 20971520;
|
|
171
|
+
/** rc.2 default total-pixel budget for one deterministic inline image version. */
|
|
172
|
+
const OPENAI_CODEX_REQUEST_IMAGE_PIXEL_BUDGET = 4194304;
|
|
173
|
+
/** rc.2 default raw encoded-byte cap for one deterministic inline image version. */
|
|
174
|
+
const OPENAI_CODEX_REQUEST_IMAGE_MAX_BYTES = 1048576;
|
|
169
175
|
/**
|
|
170
176
|
* Give the generic dsh adapter a request-scoped bearer-token entry without
|
|
171
177
|
* changing the provider's user-facing OAuth flow. The resolver accepts only
|
|
@@ -217,6 +223,20 @@ function requestProvider(provider, fastMode) {
|
|
|
217
223
|
}
|
|
218
224
|
};
|
|
219
225
|
}
|
|
226
|
+
/** Build the immutable profile consumed by the rc.2 pi-ai adapter. */
|
|
227
|
+
function createOpenAICodexProfile(provider, fastMode) {
|
|
228
|
+
return {
|
|
229
|
+
provider: OPENAI_CODEX_PROVIDER,
|
|
230
|
+
displayName: "OpenAI Codex",
|
|
231
|
+
streamIdleTimeoutMs: OPENAI_CODEX_STREAM_IDLE_TIMEOUT_MS,
|
|
232
|
+
maxRequestImageBytes: OPENAI_CODEX_MAX_REQUEST_IMAGE_BYTES,
|
|
233
|
+
requestImagePixelBudget: OPENAI_CODEX_REQUEST_IMAGE_PIXEL_BUDGET,
|
|
234
|
+
requestImageMaxBytes: OPENAI_CODEX_REQUEST_IMAGE_MAX_BYTES,
|
|
235
|
+
retryPolicy: resolveRetryPolicy(void 0, "dsh-codex-connect retryPolicy"),
|
|
236
|
+
configuredMaxTokens: /* @__PURE__ */ new Map(),
|
|
237
|
+
piProvider: requestProvider(provider, fastMode)
|
|
238
|
+
};
|
|
239
|
+
}
|
|
220
240
|
/**
|
|
221
241
|
* Create the Codex subscription adapter without requiring a dsh fork. The
|
|
222
242
|
* public pi-ai adapter owns Harness message conversion, image attachment
|
|
@@ -225,19 +245,16 @@ function requestProvider(provider, fastMode) {
|
|
|
225
245
|
*/
|
|
226
246
|
function createOpenAICodexAdapter(credentials, resolveAttachments, fastMode) {
|
|
227
247
|
const provider = openaiCodexProvider();
|
|
228
|
-
const profiles = /* @__PURE__ */ new Map([[OPENAI_CODEX_PROVIDER,
|
|
229
|
-
provider: OPENAI_CODEX_PROVIDER,
|
|
230
|
-
displayName: "OpenAI Codex",
|
|
231
|
-
streamIdleTimeoutMs: OPENAI_CODEX_STREAM_IDLE_TIMEOUT_MS,
|
|
232
|
-
retryPolicy: resolveRetryPolicy(void 0, "dsh-codex-connect retryPolicy"),
|
|
233
|
-
configuredMaxTokens: /* @__PURE__ */ new Map(),
|
|
234
|
-
piProvider: requestProvider(provider, fastMode)
|
|
235
|
-
}]]);
|
|
248
|
+
const profiles = /* @__PURE__ */ new Map([[OPENAI_CODEX_PROVIDER, createOpenAICodexProfile(provider, fastMode)]]);
|
|
236
249
|
const models = createModels({ credentials });
|
|
237
250
|
models.setProvider(provider);
|
|
238
251
|
return new PiAiAdapter({
|
|
239
252
|
profiles: () => profiles,
|
|
240
253
|
resolveApiKey: async () => (await models.getAuth(OPENAI_CODEX_PROVIDER))?.auth.apiKey,
|
|
254
|
+
auth: {
|
|
255
|
+
credentials,
|
|
256
|
+
authContext: defaultProviderAuthContext()
|
|
257
|
+
},
|
|
241
258
|
resolveAttachments
|
|
242
259
|
});
|
|
243
260
|
}
|
|
@@ -1075,7 +1092,7 @@ function registerOpenAICodexAuthRoutes(ctx, store, trustedOriginsOverride, fastM
|
|
|
1075
1092
|
//#region src/compatibility.ts
|
|
1076
1093
|
const COMPATIBILITY_SCHEMA_VERSION = 1;
|
|
1077
1094
|
const SUPPORTED_NODE_RANGE = "^22.19.0 || >=24.0.0";
|
|
1078
|
-
const SUPPORTED_DSH_PLUGIN_API_VERSION = "0.1.
|
|
1095
|
+
const SUPPORTED_DSH_PLUGIN_API_VERSION = "0.1.1-rc.2";
|
|
1079
1096
|
const SUPPORTED_PI_AI_VERSION = "0.82.1";
|
|
1080
1097
|
const PI_AI_PACKAGE = "@earendil-works/pi-ai";
|
|
1081
1098
|
const DSH_PLUGIN_API_PACKAGES = [
|
|
@@ -1211,7 +1228,7 @@ async function detectCompatibility(options = {}) {
|
|
|
1211
1228
|
}
|
|
1212
1229
|
//#endregion
|
|
1213
1230
|
//#region src/version.ts
|
|
1214
|
-
const CODEX_CONNECT_VERSION = "0.1.0-alpha.4.
|
|
1231
|
+
const CODEX_CONNECT_VERSION = "0.1.0-alpha.4.15";
|
|
1215
1232
|
//#endregion
|
|
1216
1233
|
//#region src/doctor.ts
|
|
1217
1234
|
/** Secret-free diagnostics and duplicate-provider guidance. */
|
|
@@ -2740,7 +2757,7 @@ async function migrateOpenAICodexSearchHistory(options = {}) {
|
|
|
2740
2757
|
const name = "llm-openai-codex";
|
|
2741
2758
|
/** The model registry required before the provider can register. */
|
|
2742
2759
|
const inject = ["llm"];
|
|
2743
|
-
/** Branded Host settings namespace
|
|
2760
|
+
/** Branded Host settings namespace for Codex Connect capability configuration. */
|
|
2744
2761
|
const OPENAI_CODEX_SETTINGS_NS = settingsNamespace(OPENAI_CODEX_SETTINGS_NAMESPACE);
|
|
2745
2762
|
const Config = z.object({
|
|
2746
2763
|
enableSearch: z.boolean().default(false),
|
|
@@ -2773,13 +2790,6 @@ function apply(ctx, config) {
|
|
|
2773
2790
|
assertNoOpenAICodexProviderConflict(ctx.llm.listProviders().map((provider) => provider.id));
|
|
2774
2791
|
new OpenAICodexTransport(ctx, credentials);
|
|
2775
2792
|
ctx.llm.registerAdapter([OPENAI_CODEX_PROVIDER], createOpenAICodexAdapter(credentials, () => ctx.get("attachments"), fastMode));
|
|
2776
|
-
ctx.llm.registerConfigurableProviders([{
|
|
2777
|
-
provider: OPENAI_CODEX_PROVIDER,
|
|
2778
|
-
displayName: "OpenAI Codex",
|
|
2779
|
-
settingsNs: OPENAI_CODEX_SETTINGS_NS,
|
|
2780
|
-
settingsPath: [],
|
|
2781
|
-
declared: false
|
|
2782
|
-
}]);
|
|
2783
2793
|
ctx.inject(["webServer"], (webCtx) => registerOpenAICodexAuthRoutes(webCtx, credentials, void 0, fastMode));
|
|
2784
2794
|
let stopped = false;
|
|
2785
2795
|
let searchFiber;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-codex-connect",
|
|
3
3
|
"displayName": "Codex Connect",
|
|
4
4
|
"description": "ChatGPT OAuth and Codex models for DeepSeek Harness.",
|
|
5
|
-
"version": "0.1.0-alpha.4.
|
|
5
|
+
"version": "0.1.0-alpha.4.15",
|
|
6
6
|
"author": "Frank Song",
|
|
7
7
|
"contributors": [
|
|
8
8
|
"Yan-Zero (original dsh-codex author)"
|
|
@@ -96,22 +96,21 @@
|
|
|
96
96
|
"peerDependencies": {
|
|
97
97
|
"@earendil-works/pi-ai": "0.82.1",
|
|
98
98
|
"@deepseek-ai/cordis": "^4.0.1-rc.1",
|
|
99
|
-
"@deepseek-ai/dsh-agent": "0.1.
|
|
100
|
-
"@deepseek-ai/dsh-atomic-write": "0.1.
|
|
101
|
-
"@deepseek-ai/dsh-attachment": "0.1.
|
|
102
|
-
"@deepseek-ai/dsh-client-ui-
|
|
103
|
-
"@deepseek-ai/dsh-client-ui-
|
|
104
|
-
"@deepseek-ai/dsh-
|
|
105
|
-
"@deepseek-ai/dsh-
|
|
106
|
-
"@deepseek-ai/dsh-
|
|
107
|
-
"@deepseek-ai/dsh-
|
|
108
|
-
"@deepseek-ai/dsh-llm": "0.1.
|
|
109
|
-
"@deepseek-ai/dsh-
|
|
110
|
-
"@deepseek-ai/dsh-
|
|
111
|
-
"@deepseek-ai/dsh-
|
|
112
|
-
"@deepseek-ai/dsh-
|
|
113
|
-
"@deepseek-ai/dsh-
|
|
114
|
-
"@deepseek-ai/dsh-web": "0.1.0-rc.7",
|
|
99
|
+
"@deepseek-ai/dsh-agent": "0.1.1-rc.2",
|
|
100
|
+
"@deepseek-ai/dsh-atomic-write": "0.1.1-rc.2",
|
|
101
|
+
"@deepseek-ai/dsh-attachment": "0.1.1-rc.2",
|
|
102
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.1-rc.2",
|
|
103
|
+
"@deepseek-ai/dsh-client-ui-tool": "0.1.1-rc.2",
|
|
104
|
+
"@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
|
|
105
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
|
|
106
|
+
"@deepseek-ai/dsh-invariants": "0.1.1-rc.2",
|
|
107
|
+
"@deepseek-ai/dsh-llm": "0.1.1-rc.2",
|
|
108
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.1.1-rc.2",
|
|
109
|
+
"@deepseek-ai/dsh-fs": "0.1.1-rc.2",
|
|
110
|
+
"@deepseek-ai/dsh-session": "0.1.1-rc.2",
|
|
111
|
+
"@deepseek-ai/dsh-settings": "0.1.1-rc.2",
|
|
112
|
+
"@deepseek-ai/dsh-tools": "0.1.1-rc.2",
|
|
113
|
+
"@deepseek-ai/dsh-web": "0.1.1-rc.2",
|
|
115
114
|
"@deepseek-ai/schemastery": "^3.18.1-rc.1",
|
|
116
115
|
"react": "^18.2.0"
|
|
117
116
|
},
|
|
@@ -120,34 +119,33 @@
|
|
|
120
119
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
121
120
|
"@deepseek-ai/cordis-plugin-include": "1.0.6",
|
|
122
121
|
"@deepseek-ai/cordis-plugin-loader": "1.0.2",
|
|
123
|
-
"@deepseek-ai/dsh-agent": "0.1.
|
|
124
|
-
"@deepseek-ai/dsh-api-remotes": "0.1.
|
|
125
|
-
"@deepseek-ai/dsh-atomic-write": "0.1.
|
|
126
|
-
"@deepseek-ai/dsh-attachment": "0.1.
|
|
127
|
-
"@deepseek-ai/dsh-attachment-local": "0.1.
|
|
128
|
-
"@deepseek-ai/dsh-client-locale": "0.1.
|
|
129
|
-
"@deepseek-ai/dsh-client-connection": "0.1.
|
|
130
|
-
"@deepseek-ai/dsh-client-runtime": "0.1.
|
|
131
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.
|
|
132
|
-
"@deepseek-ai/dsh-client-ui-
|
|
133
|
-
"@deepseek-ai/dsh-client-ui-
|
|
134
|
-
"@deepseek-ai/dsh-client-ui-
|
|
135
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.1.
|
|
136
|
-
"@deepseek-ai/dsh-client-ui-
|
|
137
|
-
"@deepseek-ai/dsh-client-ui-
|
|
138
|
-
"@deepseek-ai/dsh-
|
|
139
|
-
"@deepseek-ai/dsh-fs": "0.1.
|
|
140
|
-
"@deepseek-ai/dsh-
|
|
141
|
-
"@deepseek-ai/dsh-
|
|
142
|
-
"@deepseek-ai/dsh-
|
|
143
|
-
"@deepseek-ai/dsh-
|
|
144
|
-
"@deepseek-ai/dsh-llm": "0.1.
|
|
145
|
-
"@deepseek-ai/dsh-
|
|
146
|
-
"@deepseek-ai/dsh-
|
|
147
|
-
"@deepseek-ai/dsh-
|
|
148
|
-
"@deepseek-ai/dsh-
|
|
149
|
-
"@deepseek-ai/dsh-
|
|
150
|
-
"@deepseek-ai/dsh-web": "0.1.0-rc.7",
|
|
122
|
+
"@deepseek-ai/dsh-agent": "0.1.1-rc.2",
|
|
123
|
+
"@deepseek-ai/dsh-api-remotes": "0.1.1-rc.2",
|
|
124
|
+
"@deepseek-ai/dsh-atomic-write": "0.1.1-rc.2",
|
|
125
|
+
"@deepseek-ai/dsh-attachment": "0.1.1-rc.2",
|
|
126
|
+
"@deepseek-ai/dsh-attachment-local": "0.1.1-rc.2",
|
|
127
|
+
"@deepseek-ai/dsh-client-locale": "0.1.1-rc.2",
|
|
128
|
+
"@deepseek-ai/dsh-client-connection": "0.1.1-rc.2",
|
|
129
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
130
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.1-rc.2",
|
|
131
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.1-rc.2",
|
|
132
|
+
"@deepseek-ai/dsh-client-ui-model-selection": "0.1.1-rc.2",
|
|
133
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.1-rc.2",
|
|
134
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "0.1.1-rc.2",
|
|
135
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
|
|
136
|
+
"@deepseek-ai/dsh-client-ui-tool": "0.1.1-rc.2",
|
|
137
|
+
"@deepseek-ai/dsh-fs": "0.1.1-rc.2",
|
|
138
|
+
"@deepseek-ai/dsh-fs-local": "0.1.1-rc.2",
|
|
139
|
+
"@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
|
|
140
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
|
|
141
|
+
"@deepseek-ai/dsh-invariants": "0.1.1-rc.2",
|
|
142
|
+
"@deepseek-ai/dsh-llm": "0.1.1-rc.2",
|
|
143
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.1.1-rc.2",
|
|
144
|
+
"@deepseek-ai/dsh-session": "0.1.1-rc.2",
|
|
145
|
+
"@deepseek-ai/dsh-settings": "0.1.1-rc.2",
|
|
146
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.1-rc.2",
|
|
147
|
+
"@deepseek-ai/dsh-tools": "0.1.1-rc.2",
|
|
148
|
+
"@deepseek-ai/dsh-web": "0.1.1-rc.2",
|
|
151
149
|
"@deepseek-ai/schemastery": "3.18.1",
|
|
152
150
|
"@testing-library/react": "^16.3.2",
|
|
153
151
|
"@types/node": "^22.20.0",
|