dsh-codex-subscription 1.6.0 → 1.7.1
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.md +9 -5
- package/README.zh-CN.md +8 -4
- package/lib/client.js +296 -80
- package/lib/index.js +34 -6
- package/package.json +5 -4
- package/docs/assets/composer-quota-en.png +0 -0
- package/docs/assets/settings-en.png +0 -0
- package/docs/assets/settings-focus-en.png +0 -0
- package/docs/assets/settings-focus.png +0 -0
- package/docs/assets/settings.png +0 -0
package/AGENTS.md
CHANGED
|
@@ -6,7 +6,7 @@ Use this guide when a user asks an Agent to install, update, verify, or remove
|
|
|
6
6
|
## Safety
|
|
7
7
|
|
|
8
8
|
- Confirm the target DSH installation and profile. Use `web` only when it is the user's target.
|
|
9
|
-
- Use the exact `1.
|
|
9
|
+
- Use the exact `1.7.1` package below; do not install a moving branch.
|
|
10
10
|
- Never print OAuth credentials, account IDs, authorization callbacks, or credential-store contents.
|
|
11
11
|
- Preserve the DSH profile, unrelated plugins, sessions, and saved sign-in.
|
|
12
12
|
- Do not start, stop, or restart DSH without explicit permission.
|
|
@@ -34,13 +34,13 @@ For an official DSH installation run through npm, keep the complete `npx` prefix
|
|
|
34
34
|
run command does not create a global `dsh` command:
|
|
35
35
|
|
|
36
36
|
```sh
|
|
37
|
-
npx -y @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add dsh-codex-subscription@1.
|
|
37
|
+
npx -y @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add dsh-codex-subscription@1.7.1
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
With an existing global `dsh` command:
|
|
41
41
|
|
|
42
42
|
```sh
|
|
43
|
-
dsh plugin --profile web add dsh-codex-subscription@1.
|
|
43
|
+
dsh plugin --profile web add dsh-codex-subscription@1.7.1
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
Use the same `add` command to update or repair. This is the complete package-changing operation.
|
|
@@ -58,7 +58,7 @@ dsh --profile web --dump-config
|
|
|
58
58
|
|
|
59
59
|
For the official npm route, run the same checks with `npx -y @deepseek-ai/dsh@0.1.1-rc.2` in place of `dsh`.
|
|
60
60
|
|
|
61
|
-
1. `dsh-codex-subscription` version `1.
|
|
61
|
+
1. `dsh-codex-subscription` version `1.7.1` appears exactly once.
|
|
62
62
|
2. `codex-subscription` appears exactly once in the composed config.
|
|
63
63
|
3. No unrelated plugin or profile was changed and DSH was not restarted.
|
|
64
64
|
|
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ DSH-Portable exposes the same standard plugin command, so the command above also
|
|
|
49
49
|
| **Composer quota** | Choose a compact percentage, progress bar, or no inline quota display |
|
|
50
50
|
| **Safe quota reset** | See the next expiry and deliberately try a reset with a cooldown and acknowledgement |
|
|
51
51
|
| **Subscription search** | Explicitly choose DSH default search or Codex subscription search |
|
|
52
|
-
| **Codex image generation and editing (Beta)** | Generate without references, or explicitly edit selected
|
|
52
|
+
| **Codex image generation and editing (Beta)** | Generate without references, or explicitly edit one selected image; preview, zoom, annotate regions, download the original, and continue in the same composer |
|
|
53
53
|
| **Fast mode** | Switch between Standard and Fast directly in the composer |
|
|
54
54
|
|
|
55
55
|
These capabilities reuse the same local ChatGPT sign-in. Subscription routing failures stay visible and never silently switch to another paid route.
|
|
@@ -169,11 +169,15 @@ clicks are single-flight, and an uncertain network result is never retried autom
|
|
|
169
169
|
|
|
170
170
|
### Image generation and editing (Beta)
|
|
171
171
|
|
|
172
|
-
Generated images open in a DSH-native preview with zoom, fit, dimensions,
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
Generated images open in a DSH-native preview with zoom, fit, dimensions, **Download original**, and numbered region notes.
|
|
173
|
+
**Continue editing in composer** attaches exactly the image you opened and writes the region notes into the draft without
|
|
174
|
+
sending it. A new image request does not silently include earlier images. GPT Image 2 can take longer than a normal text
|
|
175
175
|
turn, and detailed text, exact composition, or repeated-character consistency may still need another pass.
|
|
176
176
|
|
|
177
|
+
<p align="center">
|
|
178
|
+
<img src="https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/docs/assets/image-preview-annotations-en.png" width="900" alt="DSH-native generated-image preview with zoom, original download, and numbered region annotations">
|
|
179
|
+
</p>
|
|
180
|
+
|
|
177
181
|
### Composer speed
|
|
178
182
|
|
|
179
183
|
With a supported Codex model selected, open the composer's model menu to choose Standard or Fast.
|
|
@@ -210,7 +214,7 @@ dsh plugin --profile web remove dsh-codex-subscription
|
|
|
210
214
|
- **`dsh` is not recognized:** the official npm route does not create a global `dsh` command; use the complete `npx -y @deepseek-ai/dsh@0.1.1-rc.2 ...` command above;
|
|
211
215
|
- **More than one DSH exists:** run the standard command from the intended DSH environment. For an Agent, specify the target or pass `-DshPath` explicitly;
|
|
212
216
|
- **Setup still fails:** send the Agent guide above to an Agent. Do not delete the profile or change the system PATH to force an install.
|
|
213
|
-
- **Need to report a problem:** generate a **Support diagnostics** report at the bottom of Settings, then open the [bug report form](https://github.com/WSL043/dsh-codex-subscription/issues/new?template=install-problem.yml). The
|
|
217
|
+
- **Need to report a problem:** generate a **Support diagnostics** report at the bottom of Settings, then open the [bug report form](https://github.com/WSL043/dsh-codex-subscription/issues/new?template=install-problem.yml). The report includes the OS/runtime and a bounded sign-in phase, but excludes credentials, account identifiers, raw errors, and full logs. Paste it into the required diagnostics field; never attach sign-in URLs, authorization codes, or browser callback addresses.
|
|
214
218
|
|
|
215
219
|
The ChatGPT Codex backend and DSH can change independently. This community project is not affiliated with or endorsed by DeepSeek or OpenAI.
|
|
216
220
|
|
package/README.zh-CN.md
CHANGED
|
@@ -166,9 +166,13 @@ ChatGPT 返回可用重置卡时,设置页会用紧凑的一行显示数量和
|
|
|
166
166
|
|
|
167
167
|
### 图片生成与编辑(Beta)
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
169
|
+
生成图片会在 DSH 原生查看器中打开,可缩放、适合窗口、查看尺寸、下载原图,并对具体部位添加编号标注。
|
|
170
|
+
点击“在输入框中继续编辑”时,只会附上当前打开的这一张图,并把部位标注写入草稿,不会自动发送。
|
|
171
|
+
新的图片请求不会静默带入历史图片。GPT Image 2 的耗时可能明显长于文本回复,复杂文字、精确构图和连续角色一致性也可能需要再次调整。
|
|
172
|
+
|
|
173
|
+
<p align="center">
|
|
174
|
+
<img src="https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/docs/assets/image-preview-annotations.png" width="900" alt="DSH 原生图片预览中的缩放、原图下载与编号部位标注">
|
|
175
|
+
</p>
|
|
172
176
|
|
|
173
177
|
### 输入框速度
|
|
174
178
|
|
|
@@ -206,7 +210,7 @@ dsh plugin --profile web remove dsh-codex-subscription
|
|
|
206
210
|
- **`dsh` 无法识别**:官方 npm 方式本来就不会创建全局 `dsh` 命令,请使用上面的完整 `npx -y @deepseek-ai/dsh@0.1.1-rc.2 ...` 命令;
|
|
207
211
|
- **电脑上有多个 DSH**:请在目标 DSH 环境中运行标准命令;交给 Agent 时明确目标,或传入 `-DshPath`;
|
|
208
212
|
- **安装仍然失败**:把上面的 Agent 文档链接发给 Agent,不要删除 profile 或随意修改系统 PATH。
|
|
209
|
-
- **需要提交问题**:在设置页底部生成“支持诊断”,然后打开[使用问题表单](https://github.com/WSL043/dsh-codex-subscription/issues/new?template=install-problem.yml)
|
|
213
|
+
- **需要提交问题**:在设置页底部生成“支持诊断”,然后打开[使用问题表单](https://github.com/WSL043/dsh-codex-subscription/issues/new?template=install-problem.yml)。报告包含系统/运行时和有限的登录阶段,但不含凭据、账号标识、原始错误或完整日志;请粘贴到必填诊断栏,且不要附上登录链接、授权码或浏览器回调地址。
|
|
210
214
|
|
|
211
215
|
## 边界与支持
|
|
212
216
|
|
package/lib/client.js
CHANGED
|
@@ -28,6 +28,7 @@ window.__ModuleLoader__.load({
|
|
|
28
28
|
//#endregion
|
|
29
29
|
let react = require("react");
|
|
30
30
|
react = __toESM(react, 1);
|
|
31
|
+
let react_dom = require("react-dom");
|
|
31
32
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
32
33
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
33
34
|
//#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/16/solid/esm/BoltIcon.js
|
|
@@ -91,6 +92,19 @@ window.__ModuleLoader__.load({
|
|
|
91
92
|
async function readLoginProgress({ flow, readFlow, readAccount }) {
|
|
92
93
|
try {
|
|
93
94
|
const nextFlow = await readFlow();
|
|
95
|
+
if (nextFlow.phase === "failed") try {
|
|
96
|
+
const account = await readAccount();
|
|
97
|
+
if (account?.authenticated === true) return {
|
|
98
|
+
flow: {
|
|
99
|
+
id: flow.id,
|
|
100
|
+
method: flow.method,
|
|
101
|
+
phase: "authenticated",
|
|
102
|
+
authenticated: true
|
|
103
|
+
},
|
|
104
|
+
account,
|
|
105
|
+
recovered: true
|
|
106
|
+
};
|
|
107
|
+
} catch {}
|
|
94
108
|
if (nextFlow.phase !== "authenticated") return { flow: nextFlow };
|
|
95
109
|
return {
|
|
96
110
|
flow: nextFlow,
|
|
@@ -250,8 +264,17 @@ window.__ModuleLoader__.load({
|
|
|
250
264
|
imageZoomOut: "缩小",
|
|
251
265
|
imageZoomIn: "放大",
|
|
252
266
|
imageFit: "适合窗口",
|
|
253
|
-
|
|
254
|
-
|
|
267
|
+
imageAnnotate: "标注部位",
|
|
268
|
+
imageAnnotateHint: "点击图片添加编号标注",
|
|
269
|
+
imageAnnotation: "标注 {value}",
|
|
270
|
+
imageAnnotationPlaceholder: "描述这个部位要修改什么",
|
|
271
|
+
imageEditPrompt: "描述你想怎样修改这张图",
|
|
272
|
+
imageEditDefault: "编辑这张图片。",
|
|
273
|
+
imageRegionNotes: "部位修改:",
|
|
274
|
+
imageEdit: "在输入框中继续编辑",
|
|
275
|
+
imageEditPreparing: "正在添加到输入框…",
|
|
276
|
+
imageEditFailed: "无法把图片添加到输入框。",
|
|
277
|
+
imageRemoveAnnotation: "删除标注"
|
|
255
278
|
};
|
|
256
279
|
const en = {
|
|
257
280
|
nav: "Codex",
|
|
@@ -373,8 +396,17 @@ window.__ModuleLoader__.load({
|
|
|
373
396
|
imageZoomOut: "Zoom out",
|
|
374
397
|
imageZoomIn: "Zoom in",
|
|
375
398
|
imageFit: "Fit to window",
|
|
376
|
-
|
|
377
|
-
|
|
399
|
+
imageAnnotate: "Annotate",
|
|
400
|
+
imageAnnotateHint: "Click the image to add a numbered note",
|
|
401
|
+
imageAnnotation: "Note {value}",
|
|
402
|
+
imageAnnotationPlaceholder: "Describe what should change in this area",
|
|
403
|
+
imageEditPrompt: "Describe how you want to change this image",
|
|
404
|
+
imageEditDefault: "Edit this image.",
|
|
405
|
+
imageRegionNotes: "Region changes:",
|
|
406
|
+
imageEdit: "Continue editing in composer",
|
|
407
|
+
imageEditPreparing: "Adding to composer…",
|
|
408
|
+
imageEditFailed: "Could not add the image to the composer.",
|
|
409
|
+
imageRemoveAnnotation: "Remove note"
|
|
378
410
|
};
|
|
379
411
|
const STYLE = `
|
|
380
412
|
.codexSubscription{display:flex;flex-direction:column;gap:10px;max-width:720px;color:var(--dsw-alias-label-primary);container-type:inline-size}
|
|
@@ -409,11 +441,24 @@ window.__ModuleLoader__.load({
|
|
|
409
441
|
.codexModelSelect{position:relative;min-width:0}.codexModelSelectTrigger{display:flex;align-items:center;gap:4px;min-width:0;max-width:min(360px,45cqw);height:28px;padding:0 4px 0 8px;border:0;border-radius:24px;outline:0;background:transparent;color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:500;line-height:20px;cursor:pointer}.codexModelSelectTrigger:hover:not(:disabled),.codexModelSelectTrigger[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover)}.codexModelSelectTrigger:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}.codexModelSelectTrigger:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.codexModelSelectBolt{display:block;flex:none;width:14px;height:14px;color:var(--dsw-alias-label-primary)}.codexModelSelectLabel{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.codexModelSelectEffort{flex:none;color:var(--dsw-alias-label-caption)}.codexModelSelectChevron{flex:none;color:var(--dsw-alias-label-caption);transition:transform 120ms}.codexModelSelectTrigger[aria-expanded=true] .codexModelSelectChevron{transform:rotate(180deg)}
|
|
410
442
|
.codexModelSelectMenu,.codexModelSelectSubmenu{position:absolute;z-index:30;box-sizing:border-box;width:max-content;min-width:min(240px,calc(100vw - 32px));max-width:min(420px,calc(100vw - 32px));max-height:min(360px,calc(100vh - 96px));padding:4px;border:1px solid var(--dsw-alias-border-inverted);border-radius:12px;background:var(--dsw-specific-menu);box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-primary);overflow:hidden}.codexModelSelectMenu{right:0;bottom:calc(100% + 8px)}.codexModelSelectSubmenu{right:calc(100% + 8px);bottom:0;min-width:min(230px,calc(100vw - 32px))}.codexModelSelectCell{display:flex;align-items:center;gap:8px;width:100%;min-width:100%;height:40px;box-sizing:border-box;padding:0 10px;border:0;border-radius:10px;background:transparent;color:inherit;font-size:14px;line-height:22px;text-align:left;cursor:pointer}.codexModelSelectCell:hover,.codexModelSelectCell:focus-visible,.codexModelSelectCell[data-open=true]{background:var(--dsw-alias-interactive-bg-hover);outline:0}.codexModelSelectCell:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.codexModelSelectCellLabel{flex:none;white-space:nowrap}.codexModelSelectCellValue{flex:auto;min-width:0;overflow:hidden;color:var(--dsw-alias-label-tertiary);text-align:right;text-overflow:ellipsis;white-space:nowrap}.codexModelSelectCellChevron{flex:none;color:var(--dsw-alias-label-tertiary)}.codexModelSelectGroups{min-height:0;max-height:352px;overflow-y:auto}.codexModelSelectGroup+.codexModelSelectGroup{margin-top:4px}.codexModelSelectGroupTitle{position:sticky;top:0;z-index:1;padding:5px 8px 3px;background:var(--dsw-specific-menu);color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:500;line-height:18px}.codexModelSelectOption{display:flex;align-items:center;gap:8px;width:100%;min-width:100%;min-height:38px;box-sizing:border-box;padding:6px 8px;border:0;border-radius:10px;outline:0;background:transparent;color:inherit;text-align:left;cursor:pointer}.codexModelSelectOption:hover:not(:disabled),.codexModelSelectOption:focus-visible{background:var(--dsw-alias-interactive-bg-hover)}.codexModelSelectOption:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.codexModelSelectOptionCopy{display:flex;flex:1;min-width:0;flex-direction:column}.codexModelSelectOptionName{overflow:hidden;color:inherit;font-size:14px;font-weight:500;line-height:20px;text-overflow:ellipsis;white-space:nowrap}.codexModelSelectOptionDescription{overflow:hidden;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;text-overflow:ellipsis;white-space:nowrap}.codexModelSelectCheck{display:grid;place-items:center;flex:0 0 18px;color:var(--dsw-alias-label-primary)}.codexModelSelectStatus,.codexModelSelectEmpty{padding:10px;color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px}.codexModelSelectError,.codexModelSelectWarning{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;margin-bottom:4px;padding:7px 8px;border-radius:8px;background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}.codexModelSelectWarning{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-state-warn-label)}.codexModelSelectRetry{flex:none;padding:0;border:0;background:transparent;color:inherit;font:inherit;font-weight:600;cursor:pointer}
|
|
411
443
|
.codexModelSelectMenu{overflow:visible}
|
|
412
|
-
.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%);
|
|
444
|
+
.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%);height:240px;padding:0;overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:16px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-tertiary);cursor:pointer}.codexGeneratedImageFrame img{display:block;width:100%;height:100%;object-fit:cover}.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}.codexGeneratedImageModal{width:min(920px,calc(100vw - 32px));max-height:calc(100vh - 32px)}.codexGeneratedImageModalContent{min-height:0;overflow:hidden}.codexGeneratedImageViewer{display:flex;min-width:0;flex-direction:column;gap:12px}.codexGeneratedImageStage{display:grid;place-items:center;min-height:280px;max-height:calc(100vh - 260px);overflow:auto;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-module-platform)}.codexGeneratedImageStage img{display:block;max-width:100%;max-height:calc(100vh - 280px);object-fit:contain;transform-origin:center;transition:transform 120ms ease}.codexGeneratedImageMeta{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.codexGeneratedImageToolbar{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}.codexGeneratedImageZoom{display:flex;align-items:center;gap:6px}.codexGeneratedImageZoomValue{min-width:44px;color:var(--dsw-alias-label-secondary);font-size:12px;text-align:center}.codexGeneratedImageDownload{display:inline-flex;align-items:center;gap:6px;min-height:32px;box-sizing:border-box;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:999px;background:transparent;color:var(--dsw-alias-label-primary);font-size:13px;text-decoration:none}.codexGeneratedImageDownload:hover{background:var(--dsw-alias-interactive-bg-hover)}.codexGeneratedImageGuidance{display:flex;flex-direction:column;gap:2px;padding-top:2px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}@keyframes codexImageSpin{to{transform:rotate(360deg)}}
|
|
413
445
|
.codexImageBeta{padding:0 5px;border:1px solid var(--dsw-alias-border-l2);border-radius:999px;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:16px}
|
|
414
446
|
@container (max-width:560px){.codexSubscriptionCreditRows{grid-template-columns:1fr}}
|
|
415
447
|
@container (max-width:480px){.codexSubscriptionAccountRow,.codexSubscriptionSectionHead{align-items:flex-start;flex-direction:column}.codexSubscriptionActions{width:100%}.codexSubscriptionSearchChoices{grid-template-columns:1fr}}
|
|
416
448
|
@media(max-width:640px){.codexSubscriptionCard{padding:14px}}
|
|
449
|
+
`;
|
|
450
|
+
const IMAGE_STYLE = String.raw`
|
|
451
|
+
.codexGeneratedImageLightbox{position:fixed;inset:0;z-index:1000;display:grid;grid-template-rows:auto minmax(0,1fr) auto;background:var(--dsw-alias-bg-base,#111);color:var(--dsw-alias-label-primary);outline:0}.codexGeneratedImageTopbar{display:flex;align-items:center;justify-content:space-between;gap:20px;min-height:58px;padding:8px 14px;border-bottom:1px solid var(--dsw-alias-border-l2);background:color-mix(in srgb,var(--dsw-alias-bg-base,#111) 92%,transparent);backdrop-filter:blur(18px)}.codexGeneratedImageTopbar>div:first-child{display:flex;min-width:0;flex-direction:column}.codexGeneratedImageTopbar strong{overflow:hidden;font-size:13px;font-weight:600;line-height:20px;text-overflow:ellipsis;white-space:nowrap}.codexGeneratedImageTopbar small{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:17px}.codexGeneratedImageActions{display:flex;align-items:center;gap:6px}.codexGeneratedImageActions button,.codexGeneratedImageActions a{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;gap:5px;height:32px;padding:0 10px;border:1px solid transparent;border-radius:16px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;text-decoration:none;cursor:pointer}.codexGeneratedImageActions button:hover,.codexGeneratedImageActions a:hover,.codexGeneratedImageActions button.is-active{background:var(--dsw-alias-interactive-bg-hover)}.codexGeneratedImageActions button:focus-visible,.codexGeneratedImageActions a:focus-visible{outline:2px solid var(--dsw-alias-border-l3);outline-offset:1px}.codexGeneratedImageActions button:disabled{opacity:.4;cursor:default}.codexGeneratedImageActions>span{min-width:38px;color:var(--dsw-alias-label-tertiary);font-size:11px;text-align:center}.codexGeneratedImageClose{font-size:20px!important}.codexGeneratedImageCanvas{position:relative;display:grid;place-items:center;min-height:0;overflow:auto;padding:24px;background:var(--dsw-alias-bg-base,#111)}.codexGeneratedImageSurface{position:relative;display:inline-flex;max-width:calc(100vw - 48px);max-height:calc(100vh - 210px);transform-origin:center;transition:transform 120ms ease}.codexGeneratedImageSurface img{display:block;max-width:100%;max-height:calc(100vh - 210px);border-radius:12px;object-fit:contain}.codexGeneratedImageCanvas.is-annotating .codexGeneratedImageSurface{cursor:crosshair}.codexGeneratedImagePin{position:absolute;display:grid;place-items:center;width:24px;height:24px;padding:0;border:2px solid white;border-radius:50%;background:var(--dsw-alias-label-primary);box-shadow:0 1px 4px rgba(0,0,0,.35);color:var(--dsw-alias-bg-base,#111);font:inherit;font-size:11px;font-weight:700;transform:translate(-50%,-50%);cursor:pointer}.codexGeneratedImagePin.is-active{background:var(--dsw-alias-state-business-primary,#3964fe);color:white}.codexGeneratedImageAnnotateHint{position:absolute;bottom:14px;left:50%;padding:6px 10px;border-radius:14px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-3) 90%,transparent);box-shadow:var(--dsw-shadow-lv2);color:var(--dsw-alias-label-secondary);font-size:11px;transform:translateX(-50%)}.codexGeneratedImageEditDock{display:flex;flex-direction:column;gap:8px;padding:10px 14px 14px;border-top:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-bg-base))}.codexGeneratedImagePrompt,.codexGeneratedImageAnnotation{display:flex;align-items:center;gap:8px;width:min(820px,100%);margin:0 auto}.codexGeneratedImagePrompt>*:first-child,.codexGeneratedImageAnnotation>*:nth-child(2){min-width:0;flex:1}.codexGeneratedImagePrompt button{flex:none;white-space:nowrap}.codexGeneratedImageAnnotation>span{flex:none;color:var(--dsw-alias-label-secondary);font-size:12px}.codexGeneratedImageAnnotation>button{flex:none;height:28px;padding:0 8px;border:0;border-radius:14px;background:transparent;color:var(--dsw-alias-label-tertiary);font:inherit;font-size:11px;cursor:pointer}.codexGeneratedImageAnnotation>button:hover{background:var(--dsw-alias-interactive-bg-hover)}.codexGeneratedImageEditError{width:min(820px,100%);margin:0 auto;color:var(--dsw-alias-state-error-primary);font-size:11px;line-height:17px}@media(max-width:760px){.codexGeneratedImageTopbar{align-items:flex-start;flex-direction:column}.codexGeneratedImageActions{width:100%;overflow-x:auto}.codexGeneratedImageActions>span{display:none}.codexGeneratedImageCanvas{padding:12px}.codexGeneratedImageSurface{max-width:calc(100vw - 24px);max-height:calc(100vh - 270px)}.codexGeneratedImageSurface img{max-height:calc(100vh - 270px)}.codexGeneratedImagePrompt,.codexGeneratedImageAnnotation{align-items:stretch;flex-direction:column}.codexGeneratedImagePrompt button{width:100%}}
|
|
452
|
+
`;
|
|
453
|
+
const IMAGE_LAYOUT_STYLE = String.raw`
|
|
454
|
+
.codexGeneratedImageWorkspace{display:grid;min-height:0;grid-template-columns:minmax(0,1fr)}
|
|
455
|
+
.codexGeneratedImageWorkspace.has-comments{grid-template-columns:minmax(0,1fr) 296px}
|
|
456
|
+
.codexGeneratedImageComments{display:flex;min-width:0;flex-direction:column;gap:12px;overflow:auto;padding:18px 14px;border-left:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-bg-base))}
|
|
457
|
+
.codexGeneratedImageComments>header{display:flex;flex-direction:column;gap:2px}.codexGeneratedImageComments>header strong{font-size:13px;font-weight:600;line-height:20px}.codexGeneratedImageComments>header small{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:17px}
|
|
458
|
+
.codexGeneratedImageCommentList{display:flex;flex-direction:column;gap:8px}.codexGeneratedImageCommentList article{display:grid;grid-template-columns:24px minmax(0,1fr) 24px;align-items:start;gap:7px;padding:9px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-3)}.codexGeneratedImageCommentList article.is-active{border-color:var(--dsw-alias-state-business-primary,#3964fe)}
|
|
459
|
+
.codexGeneratedImageCommentList article>span{display:grid;place-items:center;width:22px;height:22px;border-radius:50%;background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-base,#111);font-size:10px;font-weight:700}.codexGeneratedImageCommentList textarea{box-sizing:border-box;width:100%;min-height:64px;resize:vertical;border:0;outline:0;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;line-height:18px}.codexGeneratedImageCommentList textarea::placeholder{color:var(--dsw-alias-label-dimmed)}
|
|
460
|
+
.codexGeneratedImageCommentList article>button{display:grid;place-items:center;width:22px;height:22px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--dsw-alias-label-tertiary);font:inherit;font-size:17px;cursor:pointer}.codexGeneratedImageCommentList article>button:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
461
|
+
@media(max-width:760px){.codexGeneratedImageWorkspace.has-comments{grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr) minmax(118px,34vh)}.codexGeneratedImageComments{border-top:1px solid var(--dsw-alias-border-l2);border-left:0;padding:10px 12px}}
|
|
417
462
|
`;
|
|
418
463
|
const unwrap = (response) => {
|
|
419
464
|
if (!response?.ok) throw new Error(response?.error?.message ?? "Codex RPC failed");
|
|
@@ -443,13 +488,28 @@ window.__ModuleLoader__.load({
|
|
|
443
488
|
return cleaned.toLowerCase().endsWith(".png") ? cleaned : `${cleaned}.png`;
|
|
444
489
|
};
|
|
445
490
|
const imageByteSize = (bytes) => bytes < 1024 * 1024 ? `${Math.max(.1, bytes / 1024).toLocaleString(void 0, { maximumFractionDigits: 1 })} KB` : `${(bytes / 1024 / 1024).toLocaleString(void 0, { maximumFractionDigits: 1 })} MB`;
|
|
446
|
-
function
|
|
491
|
+
function editDraft(prompt, annotations, t) {
|
|
492
|
+
const notes = annotations.map((annotation, index) => ({
|
|
493
|
+
number: index + 1,
|
|
494
|
+
note: annotation.note.trim()
|
|
495
|
+
})).filter((annotation) => annotation.note !== "").map((annotation) => String(annotation.number) + ". " + annotation.note);
|
|
496
|
+
const base = prompt.trim() === "" ? t("imageEditDefault") : prompt.trim();
|
|
497
|
+
return notes.length === 0 ? base : base + "\n\n" + t("imageRegionNotes") + "\n" + notes.join("\n");
|
|
498
|
+
}
|
|
499
|
+
function CodexGeneratedImage({ attachment, loadImage, attachForEdit, t }) {
|
|
447
500
|
const [attempt, setAttempt] = (0, react.useState)(0);
|
|
448
501
|
const [error, setError] = (0, react.useState)(false);
|
|
449
502
|
const [open, setOpen] = (0, react.useState)(false);
|
|
450
503
|
const [src, setSrc] = (0, react.useState)();
|
|
451
504
|
const [zoom, setZoom] = (0, react.useState)(1);
|
|
505
|
+
const [annotationMode, setAnnotationMode] = (0, react.useState)(false);
|
|
506
|
+
const [annotations, setAnnotations] = (0, react.useState)([]);
|
|
507
|
+
const [selectedAnnotation, setSelectedAnnotation] = (0, react.useState)();
|
|
508
|
+
const [prompt, setPrompt] = (0, react.useState)("");
|
|
509
|
+
const [editBusy, setEditBusy] = (0, react.useState)(false);
|
|
510
|
+
const [editError, setEditError] = (0, react.useState)(false);
|
|
452
511
|
const triggerRef = (0, react.useRef)(null);
|
|
512
|
+
const dialogRef = (0, react.useRef)(null);
|
|
453
513
|
(0, react.useEffect)(() => {
|
|
454
514
|
let live = true;
|
|
455
515
|
setError(false);
|
|
@@ -471,15 +531,224 @@ window.__ModuleLoader__.load({
|
|
|
471
531
|
setOpen(false);
|
|
472
532
|
window.requestAnimationFrame(() => triggerRef.current?.focus());
|
|
473
533
|
};
|
|
534
|
+
(0, react.useEffect)(() => {
|
|
535
|
+
if (!open) return void 0;
|
|
536
|
+
const previousOverflow = document.body.style.overflow;
|
|
537
|
+
document.body.style.overflow = "hidden";
|
|
538
|
+
dialogRef.current?.focus();
|
|
539
|
+
const keydown = (event) => {
|
|
540
|
+
if (event.key === "Escape") {
|
|
541
|
+
event.preventDefault();
|
|
542
|
+
close();
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
if (event.key === "Tab") {
|
|
546
|
+
const focusable = [...dialogRef.current.querySelectorAll("button:not(:disabled),a[href],input:not(:disabled),textarea:not(:disabled),[tabindex]:not([tabindex=\"-1\"])")];
|
|
547
|
+
if (focusable.length === 0) return;
|
|
548
|
+
const first = focusable[0];
|
|
549
|
+
const last = focusable.at(-1);
|
|
550
|
+
if (event.shiftKey && document.activeElement === first) {
|
|
551
|
+
event.preventDefault();
|
|
552
|
+
last.focus();
|
|
553
|
+
} else if (!event.shiftKey && document.activeElement === last) {
|
|
554
|
+
event.preventDefault();
|
|
555
|
+
first.focus();
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
document.addEventListener("keydown", keydown);
|
|
560
|
+
return () => {
|
|
561
|
+
document.body.style.overflow = previousOverflow;
|
|
562
|
+
document.removeEventListener("keydown", keydown);
|
|
563
|
+
};
|
|
564
|
+
}, [open]);
|
|
474
565
|
const label = attachment.name ?? t("imageLabel");
|
|
475
566
|
const downloadName = imageDownloadName(attachment);
|
|
476
|
-
const imageMeta =
|
|
567
|
+
const imageMeta = attachment.width + " × " + attachment.height + " · " + imageByteSize(attachment.bytes);
|
|
568
|
+
const addAnnotation = (event) => {
|
|
569
|
+
if (!annotationMode || event.target.closest(".codexGeneratedImagePin")) return;
|
|
570
|
+
const bounds = event.currentTarget.getBoundingClientRect();
|
|
571
|
+
const annotation = {
|
|
572
|
+
id: crypto.randomUUID(),
|
|
573
|
+
x: Math.max(0, Math.min(1, (event.clientX - bounds.left) / bounds.width)),
|
|
574
|
+
y: Math.max(0, Math.min(1, (event.clientY - bounds.top) / bounds.height)),
|
|
575
|
+
note: ""
|
|
576
|
+
};
|
|
577
|
+
setAnnotations((value) => [...value, annotation]);
|
|
578
|
+
setSelectedAnnotation(annotation.id);
|
|
579
|
+
};
|
|
580
|
+
const continueEditing = async () => {
|
|
581
|
+
if (editBusy || src === void 0) return;
|
|
582
|
+
setEditBusy(true);
|
|
583
|
+
setEditError(false);
|
|
584
|
+
try {
|
|
585
|
+
await attachForEdit(src, downloadName, editDraft(prompt, annotations, t));
|
|
586
|
+
close();
|
|
587
|
+
} catch {
|
|
588
|
+
setEditError(true);
|
|
589
|
+
} finally {
|
|
590
|
+
setEditBusy(false);
|
|
591
|
+
}
|
|
592
|
+
};
|
|
477
593
|
if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
478
594
|
type: "button",
|
|
479
595
|
className: "codexGeneratedImageRetry",
|
|
480
596
|
onClick: () => setAttempt((value) => value + 1),
|
|
481
597
|
children: t("imageLoadFailed")
|
|
482
598
|
});
|
|
599
|
+
const lightbox = !open || src === void 0 ? null : (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
600
|
+
ref: dialogRef,
|
|
601
|
+
className: "codexGeneratedImageLightbox",
|
|
602
|
+
role: "dialog",
|
|
603
|
+
"aria-modal": "true",
|
|
604
|
+
"aria-label": t("imagePreview"),
|
|
605
|
+
tabIndex: -1,
|
|
606
|
+
children: [
|
|
607
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
608
|
+
className: "codexGeneratedImageTopbar",
|
|
609
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: imageMeta })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
610
|
+
className: "codexGeneratedImageActions",
|
|
611
|
+
children: [
|
|
612
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
613
|
+
type: "button",
|
|
614
|
+
className: annotationMode ? "is-active" : "",
|
|
615
|
+
"aria-pressed": annotationMode,
|
|
616
|
+
onClick: () => setAnnotationMode((value) => !value),
|
|
617
|
+
children: t("imageAnnotate")
|
|
618
|
+
}),
|
|
619
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
620
|
+
type: "button",
|
|
621
|
+
"aria-label": t("imageZoomOut"),
|
|
622
|
+
disabled: zoom <= .5,
|
|
623
|
+
onClick: () => setZoom((value) => Math.max(.5, value - .25)),
|
|
624
|
+
children: "−"
|
|
625
|
+
}),
|
|
626
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [Math.round(zoom * 100), "%"] }),
|
|
627
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
628
|
+
type: "button",
|
|
629
|
+
"aria-label": t("imageZoomIn"),
|
|
630
|
+
disabled: zoom >= 3,
|
|
631
|
+
onClick: () => setZoom((value) => Math.min(3, value + .25)),
|
|
632
|
+
children: "+"
|
|
633
|
+
}),
|
|
634
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
635
|
+
type: "button",
|
|
636
|
+
onClick: () => setZoom(1),
|
|
637
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFullscreenOutline16, { "aria-hidden": "true" }), t("imageFit")]
|
|
638
|
+
}),
|
|
639
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
|
|
640
|
+
href: src,
|
|
641
|
+
download: downloadName,
|
|
642
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDownloadOutline16, { "aria-hidden": "true" }), t("imageDownload")]
|
|
643
|
+
}),
|
|
644
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
645
|
+
type: "button",
|
|
646
|
+
className: "codexGeneratedImageClose",
|
|
647
|
+
"aria-label": t("imageClosePreview"),
|
|
648
|
+
onClick: close,
|
|
649
|
+
children: "×"
|
|
650
|
+
})
|
|
651
|
+
]
|
|
652
|
+
})]
|
|
653
|
+
}),
|
|
654
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
655
|
+
className: "codexGeneratedImageWorkspace " + (annotationMode || annotations.length > 0 ? "has-comments" : ""),
|
|
656
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("main", {
|
|
657
|
+
className: "codexGeneratedImageCanvas " + (annotationMode ? "is-annotating" : ""),
|
|
658
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
659
|
+
className: "codexGeneratedImageSurface",
|
|
660
|
+
onClick: addAnnotation,
|
|
661
|
+
style: { transform: "scale(" + zoom + ")" },
|
|
662
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
663
|
+
src,
|
|
664
|
+
alt: label
|
|
665
|
+
}), annotations.map((annotation, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
666
|
+
type: "button",
|
|
667
|
+
className: "codexGeneratedImagePin " + (annotation.id === selectedAnnotation ? "is-active" : ""),
|
|
668
|
+
"aria-label": fill(t("imageAnnotation"), { value: index + 1 }),
|
|
669
|
+
style: {
|
|
670
|
+
left: annotation.x * 100 + "%",
|
|
671
|
+
top: annotation.y * 100 + "%"
|
|
672
|
+
},
|
|
673
|
+
onClick: (event) => {
|
|
674
|
+
event.stopPropagation();
|
|
675
|
+
setSelectedAnnotation(annotation.id);
|
|
676
|
+
},
|
|
677
|
+
children: index + 1
|
|
678
|
+
}, annotation.id))]
|
|
679
|
+
}), annotationMode ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
680
|
+
className: "codexGeneratedImageAnnotateHint",
|
|
681
|
+
children: t("imageAnnotateHint")
|
|
682
|
+
}) : null]
|
|
683
|
+
}), annotationMode || annotations.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
|
|
684
|
+
className: "codexGeneratedImageComments",
|
|
685
|
+
"aria-label": t("imageAnnotate"),
|
|
686
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("imageAnnotate") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("imageAnnotateHint") })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
687
|
+
className: "codexGeneratedImageCommentList",
|
|
688
|
+
children: annotations.map((annotation, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
|
|
689
|
+
className: annotation.id === selectedAnnotation ? "is-active" : "",
|
|
690
|
+
onClick: () => setSelectedAnnotation(annotation.id),
|
|
691
|
+
children: [
|
|
692
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: index + 1 }),
|
|
693
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
694
|
+
value: annotation.note,
|
|
695
|
+
rows: 3,
|
|
696
|
+
"aria-label": fill(t("imageAnnotation"), { value: index + 1 }),
|
|
697
|
+
placeholder: t("imageAnnotationPlaceholder"),
|
|
698
|
+
onFocus: () => setSelectedAnnotation(annotation.id),
|
|
699
|
+
onChange: (event) => {
|
|
700
|
+
const note = event.target.value;
|
|
701
|
+
setAnnotations((value) => value.map((item) => item.id === annotation.id ? {
|
|
702
|
+
...item,
|
|
703
|
+
note
|
|
704
|
+
} : item));
|
|
705
|
+
}
|
|
706
|
+
}),
|
|
707
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
708
|
+
type: "button",
|
|
709
|
+
"aria-label": t("imageRemoveAnnotation"),
|
|
710
|
+
onClick: (event) => {
|
|
711
|
+
event.stopPropagation();
|
|
712
|
+
setAnnotations((value) => value.filter((item) => item.id !== annotation.id));
|
|
713
|
+
if (selectedAnnotation === annotation.id) setSelectedAnnotation(void 0);
|
|
714
|
+
},
|
|
715
|
+
children: "×"
|
|
716
|
+
})
|
|
717
|
+
]
|
|
718
|
+
}, annotation.id))
|
|
719
|
+
})]
|
|
720
|
+
}) : null]
|
|
721
|
+
}),
|
|
722
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("footer", {
|
|
723
|
+
className: "codexGeneratedImageEditDock",
|
|
724
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
725
|
+
className: "codexGeneratedImagePrompt",
|
|
726
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
727
|
+
value: prompt,
|
|
728
|
+
placeholder: t("imageEditPrompt"),
|
|
729
|
+
onChange: (event) => setPrompt(event.target.value),
|
|
730
|
+
onKeyDown: (event) => {
|
|
731
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
732
|
+
event.preventDefault();
|
|
733
|
+
continueEditing();
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
737
|
+
type: "button",
|
|
738
|
+
disabled: editBusy,
|
|
739
|
+
onClick: () => {
|
|
740
|
+
continueEditing();
|
|
741
|
+
},
|
|
742
|
+
children: editBusy ? t("imageEditPreparing") : t("imageEdit")
|
|
743
|
+
})]
|
|
744
|
+
}), editError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
745
|
+
className: "codexGeneratedImageEditError",
|
|
746
|
+
role: "alert",
|
|
747
|
+
children: t("imageEditFailed")
|
|
748
|
+
}) : null]
|
|
749
|
+
})
|
|
750
|
+
]
|
|
751
|
+
}), document.body);
|
|
483
752
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
484
753
|
ref: triggerRef,
|
|
485
754
|
type: "button",
|
|
@@ -496,78 +765,9 @@ window.__ModuleLoader__.load({
|
|
|
496
765
|
src,
|
|
497
766
|
alt: label
|
|
498
767
|
})
|
|
499
|
-
}),
|
|
500
|
-
open,
|
|
501
|
-
onClose: close,
|
|
502
|
-
title: t("imagePreview"),
|
|
503
|
-
closeLabel: t("imageClosePreview"),
|
|
504
|
-
className: "codexGeneratedImageModal",
|
|
505
|
-
contentClassName: "codexGeneratedImageModalContent",
|
|
506
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
507
|
-
className: "codexGeneratedImageViewer",
|
|
508
|
-
children: [
|
|
509
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
510
|
-
className: "codexGeneratedImageStage",
|
|
511
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
512
|
-
src,
|
|
513
|
-
alt: label,
|
|
514
|
-
style: { transform: `scale(${zoom})` }
|
|
515
|
-
})
|
|
516
|
-
}),
|
|
517
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
518
|
-
className: "codexGeneratedImageMeta",
|
|
519
|
-
children: imageMeta
|
|
520
|
-
}),
|
|
521
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
522
|
-
className: "codexGeneratedImageToolbar",
|
|
523
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
524
|
-
className: "codexGeneratedImageZoom",
|
|
525
|
-
children: [
|
|
526
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
527
|
-
type: "button",
|
|
528
|
-
variant: "outline",
|
|
529
|
-
"aria-label": t("imageZoomOut"),
|
|
530
|
-
title: t("imageZoomOut"),
|
|
531
|
-
disabled: zoom <= .5,
|
|
532
|
-
onClick: () => setZoom((value) => Math.max(.5, value - .25)),
|
|
533
|
-
children: "−"
|
|
534
|
-
}),
|
|
535
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
536
|
-
className: "codexGeneratedImageZoomValue",
|
|
537
|
-
children: [Math.round(zoom * 100), "%"]
|
|
538
|
-
}),
|
|
539
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
540
|
-
type: "button",
|
|
541
|
-
variant: "outline",
|
|
542
|
-
"aria-label": t("imageZoomIn"),
|
|
543
|
-
title: t("imageZoomIn"),
|
|
544
|
-
disabled: zoom >= 3,
|
|
545
|
-
onClick: () => setZoom((value) => Math.min(3, value + .25)),
|
|
546
|
-
children: "+"
|
|
547
|
-
}),
|
|
548
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
549
|
-
type: "button",
|
|
550
|
-
variant: "outline",
|
|
551
|
-
onClick: () => setZoom(1),
|
|
552
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFullscreenOutline16, { "aria-hidden": "true" }), t("imageFit")]
|
|
553
|
-
})
|
|
554
|
-
]
|
|
555
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
|
|
556
|
-
className: "codexGeneratedImageDownload",
|
|
557
|
-
href: src,
|
|
558
|
-
download: downloadName,
|
|
559
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDownloadOutline16, { "aria-hidden": "true" }), t("imageDownload")]
|
|
560
|
-
})]
|
|
561
|
-
}),
|
|
562
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
563
|
-
className: "codexGeneratedImageGuidance",
|
|
564
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("imageRefineHint") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("imageNewHint") })]
|
|
565
|
-
})
|
|
566
|
-
]
|
|
567
|
-
})
|
|
568
|
-
})] });
|
|
768
|
+
}), lightbox] });
|
|
569
769
|
}
|
|
570
|
-
function CodexImageToolRow({ block, loadImage, t }) {
|
|
770
|
+
function CodexImageToolRow({ block, loadImage, attachForEdit, t }) {
|
|
571
771
|
const settled = block?.kind === "tool-result";
|
|
572
772
|
const image = settled ? block.content.find((item) => item?.type === "image" && item.attachment !== void 0) : void 0;
|
|
573
773
|
const failed = settled && block.isError === true;
|
|
@@ -604,6 +804,7 @@ window.__ModuleLoader__.load({
|
|
|
604
804
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodexGeneratedImage, {
|
|
605
805
|
attachment: image.attachment,
|
|
606
806
|
loadImage,
|
|
807
|
+
attachForEdit,
|
|
607
808
|
t
|
|
608
809
|
})
|
|
609
810
|
}),
|
|
@@ -1868,7 +2069,7 @@ window.__ModuleLoader__.load({
|
|
|
1868
2069
|
ctx.effect(() => {
|
|
1869
2070
|
const tag = document.createElement("style");
|
|
1870
2071
|
tag.dataset.plugin = "dsh-codex-subscription";
|
|
1871
|
-
tag.textContent = STYLE;
|
|
2072
|
+
tag.textContent = STYLE + IMAGE_STYLE + IMAGE_LAYOUT_STYLE;
|
|
1872
2073
|
document.head.append(tag);
|
|
1873
2074
|
return () => tag.remove();
|
|
1874
2075
|
}, "codex-subscription: style");
|
|
@@ -1935,7 +2136,22 @@ window.__ModuleLoader__.load({
|
|
|
1935
2136
|
locale: NS,
|
|
1936
2137
|
inject: (sessionId) => ({
|
|
1937
2138
|
t,
|
|
1938
|
-
loadImage: (attachment) => conversation.resolveImage(sessionId, attachment)
|
|
2139
|
+
loadImage: (attachment) => conversation.resolveImage(sessionId, attachment),
|
|
2140
|
+
attachForEdit: async (src, filename, draft) => {
|
|
2141
|
+
const actx = sessions.scope(sessionId);
|
|
2142
|
+
if (actx === void 0 || typeof conversation.createDraftImages !== "function" || conversation.input?.for === void 0) throw new Error("This DSH version does not provide the image composer bridge");
|
|
2143
|
+
const response = await fetch(src);
|
|
2144
|
+
if (!response.ok) throw new Error("Could not read generated image");
|
|
2145
|
+
const blob = await response.blob();
|
|
2146
|
+
const created = conversation.createDraftImages([new File([blob], filename, { type: blob.type || "image/png" })]);
|
|
2147
|
+
const input = conversation.input.for(actx);
|
|
2148
|
+
if (!input.addImages(created.map((item) => item.id))) {
|
|
2149
|
+
conversation.releaseDraftImages(created);
|
|
2150
|
+
throw new Error("The composer is busy");
|
|
2151
|
+
}
|
|
2152
|
+
sessions.open(sessionId);
|
|
2153
|
+
input.setDraft(draft);
|
|
2154
|
+
}
|
|
1939
2155
|
})
|
|
1940
2156
|
}, CodexImageToolRow));
|
|
1941
2157
|
}
|
package/lib/index.js
CHANGED
|
@@ -229,6 +229,14 @@ var CodexLoginCoordinator = class {
|
|
|
229
229
|
async accountStatus(options) {
|
|
230
230
|
return publicClone(await this.auth.status(options));
|
|
231
231
|
}
|
|
232
|
+
supportState() {
|
|
233
|
+
const active = this.#activeId === void 0 ? void 0 : this.#sessions.get(this.#activeId);
|
|
234
|
+
if (active === void 0) return { phase: "idle" };
|
|
235
|
+
return {
|
|
236
|
+
method: active.view.method,
|
|
237
|
+
phase: active.view.phase
|
|
238
|
+
};
|
|
239
|
+
}
|
|
232
240
|
async start({ method }) {
|
|
233
241
|
if (!LOGIN_METHODS.has(method)) throw new Error(`unsupported Codex login method: ${String(method)}`);
|
|
234
242
|
const active = this.#activeId === void 0 ? void 0 : this.#sessions.get(this.#activeId);
|
|
@@ -317,7 +325,7 @@ var CodexLoginCoordinator = class {
|
|
|
317
325
|
authenticated: status.authenticated === true,
|
|
318
326
|
...typeof status.expiresAt === "number" ? { expiresAt: status.expiresAt } : {}
|
|
319
327
|
};
|
|
320
|
-
}).catch((error) => {
|
|
328
|
+
}).catch(async (error) => {
|
|
321
329
|
if (controller.signal.aborted) {
|
|
322
330
|
session.view = {
|
|
323
331
|
id,
|
|
@@ -328,6 +336,20 @@ var CodexLoginCoordinator = class {
|
|
|
328
336
|
};
|
|
329
337
|
return;
|
|
330
338
|
}
|
|
339
|
+
try {
|
|
340
|
+
const status = await this.auth.status();
|
|
341
|
+
if (status.authenticated === true) {
|
|
342
|
+
session.view = {
|
|
343
|
+
id,
|
|
344
|
+
provider: "openai-codex",
|
|
345
|
+
method,
|
|
346
|
+
phase: "authenticated",
|
|
347
|
+
authenticated: true,
|
|
348
|
+
...typeof status.expiresAt === "number" ? { expiresAt: status.expiresAt } : {}
|
|
349
|
+
};
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
} catch {}
|
|
331
353
|
session.view = {
|
|
332
354
|
id,
|
|
333
355
|
provider: "openai-codex",
|
|
@@ -504,7 +526,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0 } = {
|
|
|
504
526
|
}
|
|
505
527
|
//#endregion
|
|
506
528
|
//#region src/version.js
|
|
507
|
-
const PACKAGE_VERSION = "1.
|
|
529
|
+
const PACKAGE_VERSION = "1.7.1";
|
|
508
530
|
const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
|
|
509
531
|
//#endregion
|
|
510
532
|
//#region src/codex-search.js
|
|
@@ -898,7 +920,7 @@ function createCodexImageTool(options) {
|
|
|
898
920
|
//#endregion
|
|
899
921
|
//#region src/diagnostics.js
|
|
900
922
|
/** Build a support report that deliberately excludes OAuth and account metadata. */
|
|
901
|
-
async function createSubscriptionDiagnostics({ auth, preferences }) {
|
|
923
|
+
async function createSubscriptionDiagnostics({ auth, preferences, login = { phase: "idle" } }) {
|
|
902
924
|
let account = { status: "unknown" };
|
|
903
925
|
const issues = [];
|
|
904
926
|
try {
|
|
@@ -907,11 +929,16 @@ async function createSubscriptionDiagnostics({ auth, preferences }) {
|
|
|
907
929
|
issues.push({ code: "account-status-unavailable" });
|
|
908
930
|
}
|
|
909
931
|
return {
|
|
910
|
-
schemaVersion:
|
|
932
|
+
schemaVersion: 2,
|
|
911
933
|
package: "dsh-codex-subscription",
|
|
912
934
|
version: PACKAGE_VERSION,
|
|
913
|
-
runtime: {
|
|
935
|
+
runtime: {
|
|
936
|
+
node: process.version,
|
|
937
|
+
platform: process.platform,
|
|
938
|
+
arch: process.arch
|
|
939
|
+
},
|
|
914
940
|
account,
|
|
941
|
+
login,
|
|
915
942
|
provider: {
|
|
916
943
|
id: "openai-codex",
|
|
917
944
|
transport: "sse",
|
|
@@ -1558,7 +1585,8 @@ function apply(ctx) {
|
|
|
1558
1585
|
preferences,
|
|
1559
1586
|
diagnosticsReader: () => createSubscriptionDiagnostics({
|
|
1560
1587
|
auth,
|
|
1561
|
-
preferences
|
|
1588
|
+
preferences,
|
|
1589
|
+
login: coordinator.supportState()
|
|
1562
1590
|
})
|
|
1563
1591
|
});
|
|
1564
1592
|
ctx.effect(() => ctx.connection.rpc.handle(CHANNEL, handler, { authority: "loopback" }), "codex-subscription: loopback account RPC");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Use ChatGPT and Codex subscriptions in DeepSeek Harness with OAuth, quota, safe resets, web search, images, and Fast mode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -20,8 +20,7 @@
|
|
|
20
20
|
"compatibility.json",
|
|
21
21
|
"LICENSE",
|
|
22
22
|
"SECURITY.md",
|
|
23
|
-
"THIRD_PARTY_NOTICES.md"
|
|
24
|
-
"docs/assets/*.png"
|
|
23
|
+
"THIRD_PARTY_NOTICES.md"
|
|
25
24
|
],
|
|
26
25
|
"dsh": {
|
|
27
26
|
"bundle": {
|
|
@@ -95,7 +94,8 @@
|
|
|
95
94
|
"@deepseek-ai/dsh-web": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2",
|
|
96
95
|
"@deepseek-ai/schemastery": "3.18.1",
|
|
97
96
|
"@earendil-works/pi-ai": "0.82.1",
|
|
98
|
-
"react": "^18.2.0"
|
|
97
|
+
"react": "^18.2.0",
|
|
98
|
+
"react-dom": "^18.2.0"
|
|
99
99
|
},
|
|
100
100
|
"devDependencies": {
|
|
101
101
|
"@deepseek-ai/cordis": "4.0.1",
|
|
@@ -119,6 +119,7 @@
|
|
|
119
119
|
"@earendil-works/pi-ai": "0.82.1",
|
|
120
120
|
"@heroicons/react": "2.2.0",
|
|
121
121
|
"react": "18.3.1",
|
|
122
|
+
"react-dom": "18.3.1",
|
|
122
123
|
"tsdown": "0.22.2"
|
|
123
124
|
},
|
|
124
125
|
"scripts": {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/assets/settings.png
DELETED
|
Binary file
|