dsh-codex-subscription 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md 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.8.0` package below; do not install a moving branch.
9
+ - Use the exact `1.9.0` package below; do not install a moving branch.
10
10
  - Never print OAuth credentials, account IDs, authorization callbacks, or credential-store contents.
11
11
  - Preserve the DSH profile, unrelated plugins, sessions, and saved sign-in.
12
12
  - Do not start, stop, or restart DSH without explicit permission.
@@ -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.8.0
37
+ npx -y @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add dsh-codex-subscription@1.9.0
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.8.0
43
+ dsh plugin --profile web add dsh-codex-subscription@1.9.0
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.8.0` appears exactly once.
61
+ 1. `dsh-codex-subscription` version `1.9.0` 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
@@ -48,7 +48,7 @@ DSH-Portable exposes the same standard plugin command, so the command above also
48
48
  | **Visible quota** | Keep backend-provided standard Codex, Spark, and other limits separate |
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
- | **Subscription search** | Explicitly choose DSH default search or Codex subscription search |
51
+ | **Subscription search** | Explicitly route search globally through DSH default search or the signed-in Codex subscription |
52
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
  | **Model-aware context** | Keep catalog defaults, use each model's supported extended window, or enter a full numeric token limit for each model |
@@ -58,21 +58,16 @@ These capabilities reuse the same local ChatGPT sign-in. Subscription routing fa
58
58
  ## Product screen
59
59
 
60
60
  <p align="center">
61
- <img src="https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/docs/assets/settings-focus-en.png" width="820" alt="Codex subscription settings in DeepSeek Harness">
61
+ <img src="https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/docs/assets/context-settings-en.png" width="820" alt="Current Codex subscription settings in DeepSeek Harness with search, model-aware context, composer quota, and support diagnostics">
62
62
  </p>
63
63
 
64
- <details>
65
- <summary>View the complete settings screen</summary>
66
-
67
- ![Complete Codex subscription settings in DeepSeek Harness](https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/docs/assets/settings-en.png)
68
-
69
- </details>
64
+ Captured from the installed official DeepSeek Harness `0.1.1-rc.2` product with the current plugin build.
70
65
 
71
66
  ## Prepare DSH
72
67
 
73
68
  This plugin is currently compatible through DeepSeek Harness `0.1.1-rc.2` and requires a ChatGPT account that currently has Codex access.
74
69
 
75
- - Do not want to configure Node.js? Use [DSH-Portable](https://github.com/WSL043/DSH-Portable), a community desktop distribution with portable and installed editions for Windows plus desktop packages for macOS and Linux.
70
+ - Do not want to configure Node.js? Use [DSH-Portable](https://github.com/WSL043/DSH-Portable), a community portable desktop distribution for Windows, macOS, and Linux.
76
71
  - Prefer the official route? Follow the [DeepSeek Harness run guide](https://github.com/deepseek-ai/deepseek-harness#run).
77
72
 
78
73
  ## Install
@@ -142,7 +137,7 @@ Restart DSH manually after installation, then:
142
137
 
143
138
  - ChatGPT OAuth sign-in with credentials kept on the host;
144
139
  - Codex models and Beta image generation/editing directly inside DSH conversations;
145
- - A clear choice between DSH default search and Codex subscription search;
140
+ - A clear global choice between DSH default search and Codex subscription search; it applies to every model and session rather than following the selected model;
146
141
  - Actual backend-provided quota, reset time, and freshness;
147
142
  - Separate standard Codex, Codex-Spark, Credits, and other independent limits;
148
143
  - Visible quota-reset count and earliest expiry, with deliberate early redemption, layered confirmation, and no automatic retry;
package/README.zh-CN.md CHANGED
@@ -49,7 +49,7 @@ DSH-Portable 也提供相同的标准插件命令,因此同样使用上面的
49
49
  | **额度可见** | 普通 Codex、Spark 等服务端实际返回的额度分开显示 |
50
50
  | **输入框额度** | 可选择紧凑百分比、进度条或完全关闭输入框额度显示 |
51
51
  | **安全额度重置** | 直接查看最早到期时间,并通过冷静期和知情确认主动尝试重置 |
52
- | **订阅搜索** | 可在 DSH 默认搜索与 Codex 订阅搜索之间明确切换 |
52
+ | **订阅搜索** | 可将全部模型的搜索明确路由到 DSH 默认搜索或已登录的 Codex 订阅 |
53
53
  | **Codex 图片生成与编辑(Beta)** | 可无参考图全新生成,也可明确选择会话图片继续编辑;支持预览、缩放和下载原图 |
54
54
  | **高速模式** | 直接在输入框切换标准或高速,无需离开当前会话 |
55
55
  | **模型感知上下文** | 可保留目录默认值、按模型启用扩展窗口,或为每个模型填写完整数字 Token 上限 |
@@ -59,21 +59,16 @@ DSH-Portable 也提供相同的标准插件命令,因此同样使用上面的
59
59
  ## 实际界面
60
60
 
61
61
  <p align="center">
62
- <img src="https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/docs/assets/settings-focus.png" width="820" alt="DeepSeek Harness 中的 Codex 订阅设置">
62
+ <img src="https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/docs/assets/context-settings.png" width="820" alt="当前 DeepSeek Harness Codex 订阅设置,包含搜索来源、模型感知上下文、输入框额度和支持诊断">
63
63
  </p>
64
64
 
65
- <details>
66
- <summary>查看完整设置界面</summary>
67
-
68
- ![DeepSeek Harness 的完整 Codex 订阅设置](https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/docs/assets/settings.png)
69
-
70
- </details>
65
+ 图片来自已安装的官方 DeepSeek Harness `0.1.1-rc.2` 与当前插件构建。
71
66
 
72
67
  ## 准备 DSH
73
68
 
74
69
  本插件当前适配到 DeepSeek Harness `0.1.1-rc.2`,并需要一个当前具有 Codex 使用资格的 ChatGPT 账户。
75
70
 
76
- - 不想配置 Node.js:使用 [DSH-Portable](https://github.com/WSL043/DSH-Portable)。这是社区桌面分发,提供 Windows 便携版和安装版,以及 macOS、Linux 桌面包;
71
+ - 不想配置 Node.js:使用 [DSH-Portable](https://github.com/WSL043/DSH-Portable)。这是面向 Windows、macOS Linux 的社区便携桌面分发;
77
72
  - 想按官方方式运行:查看 [DeepSeek Harness 官方说明](https://github.com/deepseek-ai/deepseek-harness#run)。
78
73
 
79
74
  ## 安装
@@ -142,7 +137,7 @@ dsh --profile web --dump-config
142
137
 
143
138
  - ChatGPT OAuth 登录,凭据保留在本机;
144
139
  - Codex 模型和 Beta 图片生成与编辑直接出现在 DSH 会话中;
145
- - DSH 默认搜索与 Codex 订阅搜索可随时切换;
140
+ - 搜索来源是全局设置,可在 DSH 默认搜索与 Codex 订阅搜索之间切换;它对所有模型和会话生效,不会随当前模型自动切换;
146
141
  - 设置页显示服务端返回的额度、重置时间和更新时间;
147
142
  - 普通 Codex、Codex-Spark、Credits 等独立额度分开显示;
148
143
  - 显示重置卡数量与最早到期时间,也允许在额度未完全用尽时主动尝试,并经过分层确认且不会自动重试;
package/lib/client.js CHANGED
@@ -49,6 +49,17 @@ window.__ModuleLoader__.load({
49
49
  }
50
50
  const ForwardRef = /*#__PURE__*/ react.forwardRef(BoltIcon);
51
51
  //#endregion
52
+ //#region src/image-edit.js
53
+ function buildImageEditDraft({ prompt = "", annotations = [], translate }) {
54
+ if (typeof translate !== "function") throw new TypeError("translate must be a function");
55
+ const notes = annotations.map((annotation, index) => ({
56
+ number: index + 1,
57
+ note: typeof annotation?.note === "string" ? annotation.note.trim() : ""
58
+ })).filter((annotation) => annotation.note !== "").map((annotation) => String(annotation.number) + ". " + annotation.note);
59
+ const base = prompt.trim() === "" ? translate("imageEditDefault") : prompt.trim();
60
+ return notes.length === 0 ? base : base + "\n\n" + translate("imageRegionNotes") + "\n" + notes.join("\n");
61
+ }
62
+ //#endregion
52
63
  //#region src/settings-contract.js
53
64
  const SETTINGS_NAMESPACE = "codex-subscription";
54
65
  const QUICK_QUOTA_MODE_FIELD = "quickQuotaMode";
@@ -212,10 +223,11 @@ window.__ModuleLoader__.load({
212
223
  diagnosticsFailed: "无法生成诊断信息。",
213
224
  feedbackOpen: "反馈问题",
214
225
  searchTitle: "搜索来源",
226
+ searchScope: "此设置对所有模型和会话生效,不会随当前模型自动切换。",
215
227
  searchDsh: "DSH 默认",
216
- searchDshHint: "当前搜索服务",
228
+ searchDshHint: "所有模型使用 DSH 当前搜索服务",
217
229
  searchCodex: "Codex 订阅",
218
- searchCodexHint: "ChatGPT 订阅搜索",
230
+ searchCodexHint: "所有模型通过已登录的 ChatGPT 订阅搜索",
219
231
  preferenceFailed: "设置未保存。",
220
232
  preferenceRetry: "重试",
221
233
  usage: "订阅额度",
@@ -354,10 +366,11 @@ window.__ModuleLoader__.load({
354
366
  diagnosticsFailed: "Could not create diagnostics.",
355
367
  feedbackOpen: "Report a problem",
356
368
  searchTitle: "Search source",
369
+ searchScope: "Applies to every model and session; it does not switch with the selected model.",
357
370
  searchDsh: "DSH default",
358
- searchDshHint: "Current search service",
371
+ searchDshHint: "Use DSH's current search service for every model",
359
372
  searchCodex: "Codex subscription",
360
- searchCodexHint: "ChatGPT subscription search",
373
+ searchCodexHint: "Search through the signed-in ChatGPT subscription for every model",
361
374
  preferenceFailed: "The setting was not saved.",
362
375
  preferenceRetry: "Retry",
363
376
  usage: "Subscription quota",
@@ -471,6 +484,7 @@ window.__ModuleLoader__.load({
471
484
  imageRemoveAnnotation: "Remove note"
472
485
  };
473
486
  const STYLE = `
487
+ .codexSubscriptionSearchHead{display:flex;flex-direction:column;gap:1px}.codexSubscriptionSearchScope{font-size:11px;line-height:17px;color:var(--dsw-alias-label-tertiary)}
474
488
  .codexSubscription{display:flex;flex-direction:column;gap:10px;max-width:720px;color:var(--dsw-alias-label-primary);container-type:inline-size}
475
489
  .codexSubscription h2,.codexSubscription h3,.codexSubscription p{margin:0}.codexSubscriptionHead{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
476
490
  .codexSubscription h2{font-size:16px;line-height:24px;font-weight:500}.codexSubscription h3{font-size:14px;line-height:22px;font-weight:500}
@@ -552,15 +566,7 @@ window.__ModuleLoader__.load({
552
566
  return cleaned.toLowerCase().endsWith(".png") ? cleaned : `${cleaned}.png`;
553
567
  };
554
568
  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`;
555
- function editDraft(prompt, annotations, t) {
556
- const notes = annotations.map((annotation, index) => ({
557
- number: index + 1,
558
- note: annotation.note.trim()
559
- })).filter((annotation) => annotation.note !== "").map((annotation) => String(annotation.number) + ". " + annotation.note);
560
- const base = prompt.trim() === "" ? t("imageEditDefault") : prompt.trim();
561
- return notes.length === 0 ? base : base + "\n\n" + t("imageRegionNotes") + "\n" + notes.join("\n");
562
- }
563
- function CodexGeneratedImage({ attachment, loadImage, attachForEdit, t }) {
569
+ function CodexGeneratedImage({ attachment, loadImage, attachForEdit, getImageViewer, t }) {
564
570
  const [attempt, setAttempt] = (0, react.useState)(0);
565
571
  const [error, setError] = (0, react.useState)(false);
566
572
  const [open, setOpen] = (0, react.useState)(false);
@@ -646,7 +652,11 @@ window.__ModuleLoader__.load({
646
652
  setEditBusy(true);
647
653
  setEditError(false);
648
654
  try {
649
- await attachForEdit(src, downloadName, editDraft(prompt, annotations, t));
655
+ await attachForEdit(src, downloadName, buildImageEditDraft({
656
+ prompt,
657
+ annotations,
658
+ translate: t
659
+ }));
650
660
  close();
651
661
  } catch {
652
662
  setEditError(true);
@@ -654,6 +664,35 @@ window.__ModuleLoader__.load({
654
664
  setEditBusy(false);
655
665
  }
656
666
  };
667
+ const openImage = () => {
668
+ if (src === void 0) return;
669
+ if ((getImageViewer?.())?.open?.({
670
+ items: [{
671
+ id: attachment.attachmentId ?? downloadName,
672
+ src,
673
+ name: label,
674
+ width: attachment.width,
675
+ height: attachment.height,
676
+ bytes: attachment.bytes
677
+ }],
678
+ opener: triggerRef.current,
679
+ source: "codex-generated",
680
+ annotations: true,
681
+ editor: {
682
+ label: t("imageEdit"),
683
+ busyLabel: t("imageEditPreparing"),
684
+ errorLabel: t("imageEditFailed"),
685
+ placeholder: t("imageEditPrompt"),
686
+ onSubmit: ({ prompt: nextPrompt, annotations: nextAnnotations }) => attachForEdit(src, downloadName, buildImageEditDraft({
687
+ prompt: nextPrompt,
688
+ annotations: nextAnnotations,
689
+ translate: t
690
+ }))
691
+ }
692
+ }) === true) return;
693
+ setZoom(1);
694
+ setOpen(true);
695
+ };
657
696
  if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
658
697
  type: "button",
659
698
  className: "codexGeneratedImageRetry",
@@ -819,19 +858,14 @@ window.__ModuleLoader__.load({
819
858
  className: "codexGeneratedImageFrame",
820
859
  title: t("imageOpen"),
821
860
  "aria-label": fill(t("imageOpenNamed"), { value: label }),
822
- onClick: () => {
823
- if (src !== void 0) {
824
- setZoom(1);
825
- setOpen(true);
826
- }
827
- },
861
+ onClick: openImage,
828
862
  children: src === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("imageLoading") }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
829
863
  src,
830
864
  alt: label
831
865
  })
832
866
  }), lightbox] });
833
867
  }
834
- function CodexImageToolRow({ block, loadImage, attachForEdit, t }) {
868
+ function CodexImageToolRow({ block, loadImage, attachForEdit, getImageViewer, t }) {
835
869
  const settled = block?.kind === "tool-result";
836
870
  const image = settled ? block.content.find((item) => item?.type === "image" && item.attachment !== void 0) : void 0;
837
871
  const failed = settled && block.isError === true;
@@ -869,6 +903,7 @@ window.__ModuleLoader__.load({
869
903
  attachment: image.attachment,
870
904
  loadImage,
871
905
  attachForEdit,
906
+ getImageViewer,
872
907
  t
873
908
  })
874
909
  }),
@@ -1100,7 +1135,13 @@ window.__ModuleLoader__.load({
1100
1135
  });
1101
1136
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1102
1137
  className: "codexSubscriptionSearch",
1103
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("searchTitle") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1138
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1139
+ className: "codexSubscriptionSearchHead",
1140
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("searchTitle") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1141
+ className: "codexSubscriptionSearchScope",
1142
+ children: t("searchScope")
1143
+ })]
1144
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1104
1145
  className: "codexSubscriptionSearchChoices",
1105
1146
  role: "radiogroup",
1106
1147
  "aria-label": t("searchTitle"),
@@ -2337,6 +2378,13 @@ window.__ModuleLoader__.load({
2337
2378
  inject: (sessionId) => ({
2338
2379
  t,
2339
2380
  loadImage: (attachment) => conversation.resolveImage(sessionId, attachment),
2381
+ getImageViewer: () => {
2382
+ try {
2383
+ return ctx.get("nativeImageViewer");
2384
+ } catch {
2385
+ return;
2386
+ }
2387
+ },
2340
2388
  attachForEdit: async (src, filename, draft) => {
2341
2389
  const actx = sessions.scope(sessionId);
2342
2390
  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");
package/lib/index.js CHANGED
@@ -902,7 +902,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
902
902
  }
903
903
  //#endregion
904
904
  //#region src/version.js
905
- const PACKAGE_VERSION = "1.8.0";
905
+ const PACKAGE_VERSION = "1.9.0";
906
906
  const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
907
907
  //#endregion
908
908
  //#region src/codex-search.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-codex-subscription",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
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",