dsh-codex-subscription 2.5.8 → 2.5.9

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/README.en.md CHANGED
@@ -106,7 +106,7 @@ This plugin supports the latest DeepSeek Harness release recorded in its package
106
106
  2. Paste this package name, with its version, into the **Package name or address** field:
107
107
 
108
108
  ```text
109
- dsh-codex-subscription@2.5.8
109
+ dsh-codex-subscription@2.5.9
110
110
  ```
111
111
 
112
112
  3. Click **Install** and wait for completion. Follow the page instructions; save your work before restarting if requested.
package/README.md CHANGED
@@ -106,7 +106,7 @@
106
106
  2. 在 **包名或地址** 输入框中粘贴下面的包名(已带版本号):
107
107
 
108
108
  ```text
109
- dsh-codex-subscription@2.5.8
109
+ dsh-codex-subscription@2.5.9
110
110
  ```
111
111
 
112
112
  3. 点击 **安装**,等待安装完成;按页面提示操作,需要重启时先保存工作。
package/lib/client.js CHANGED
@@ -896,7 +896,7 @@ window.__ModuleLoader__.load({
896
896
  d: "M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"
897
897
  }));
898
898
  }
899
- const ForwardRef$6 = /*#__PURE__*/ react.forwardRef(ArrowPathIcon);
899
+ const ForwardRef$8 = /*#__PURE__*/ react.forwardRef(ArrowPathIcon);
900
900
  //#endregion
901
901
  //#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/ArrowsPointingOutIcon.js
902
902
  function ArrowsPointingOutIcon({ title, titleId, ...props }, svgRef) {
@@ -916,7 +916,27 @@ window.__ModuleLoader__.load({
916
916
  d: "M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15"
917
917
  }));
918
918
  }
919
- const ForwardRef$5 = /*#__PURE__*/ react.forwardRef(ArrowsPointingOutIcon);
919
+ const ForwardRef$7 = /*#__PURE__*/ react.forwardRef(ArrowsPointingOutIcon);
920
+ //#endregion
921
+ //#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/ChatBubbleLeftEllipsisIcon.js
922
+ function ChatBubbleLeftEllipsisIcon({ title, titleId, ...props }, svgRef) {
923
+ return /*#__PURE__*/ react.createElement("svg", Object.assign({
924
+ xmlns: "http://www.w3.org/2000/svg",
925
+ fill: "none",
926
+ viewBox: "0 0 24 24",
927
+ strokeWidth: 1.5,
928
+ stroke: "currentColor",
929
+ "aria-hidden": "true",
930
+ "data-slot": "icon",
931
+ ref: svgRef,
932
+ "aria-labelledby": titleId
933
+ }, props), title ? /*#__PURE__*/ react.createElement("title", { id: titleId }, title) : null, /*#__PURE__*/ react.createElement("path", {
934
+ strokeLinecap: "round",
935
+ strokeLinejoin: "round",
936
+ d: "M8.625 9.75a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H8.25m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H12m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0h-.375m-13.5 3.01c0 1.6 1.123 2.994 2.707 3.227 1.087.16 2.185.283 3.293.369V21l4.184-4.183a1.14 1.14 0 0 1 .778-.332 48.294 48.294 0 0 0 5.83-.498c1.585-.233 2.708-1.626 2.708-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z"
937
+ }));
938
+ }
939
+ const ForwardRef$6 = /*#__PURE__*/ react.forwardRef(ChatBubbleLeftEllipsisIcon);
920
940
  //#endregion
921
941
  //#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/ExclamationCircleIcon.js
922
942
  function ExclamationCircleIcon({ title, titleId, ...props }, svgRef) {
@@ -936,7 +956,7 @@ window.__ModuleLoader__.load({
936
956
  d: "M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
937
957
  }));
938
958
  }
939
- const ForwardRef$4 = /*#__PURE__*/ react.forwardRef(ExclamationCircleIcon);
959
+ const ForwardRef$5 = /*#__PURE__*/ react.forwardRef(ExclamationCircleIcon);
940
960
  //#endregion
941
961
  //#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/PaintBrushIcon.js
942
962
  function PaintBrushIcon({ title, titleId, ...props }, svgRef) {
@@ -956,7 +976,27 @@ window.__ModuleLoader__.load({
956
976
  d: "M9.53 16.122a3 3 0 0 0-5.78 1.128 2.25 2.25 0 0 1-2.4 2.245 4.5 4.5 0 0 0 8.4-2.245c0-.399-.078-.78-.22-1.128Zm0 0a15.998 15.998 0 0 0 3.388-1.62m-5.043-.025a15.994 15.994 0 0 1 1.622-3.395m3.42 3.42a15.995 15.995 0 0 0 4.764-4.648l3.876-5.814a1.151 1.151 0 0 0-1.597-1.597L14.146 6.32a15.996 15.996 0 0 0-4.649 4.763m3.42 3.42a6.776 6.776 0 0 0-3.42-3.42"
957
977
  }));
958
978
  }
959
- const ForwardRef$3 = /*#__PURE__*/ react.forwardRef(PaintBrushIcon);
979
+ const ForwardRef$4 = /*#__PURE__*/ react.forwardRef(PaintBrushIcon);
980
+ //#endregion
981
+ //#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/PencilIcon.js
982
+ function PencilIcon({ title, titleId, ...props }, svgRef) {
983
+ return /*#__PURE__*/ react.createElement("svg", Object.assign({
984
+ xmlns: "http://www.w3.org/2000/svg",
985
+ fill: "none",
986
+ viewBox: "0 0 24 24",
987
+ strokeWidth: 1.5,
988
+ stroke: "currentColor",
989
+ "aria-hidden": "true",
990
+ "data-slot": "icon",
991
+ ref: svgRef,
992
+ "aria-labelledby": titleId
993
+ }, props), title ? /*#__PURE__*/ react.createElement("title", { id: titleId }, title) : null, /*#__PURE__*/ react.createElement("path", {
994
+ strokeLinecap: "round",
995
+ strokeLinejoin: "round",
996
+ d: "m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125"
997
+ }));
998
+ }
999
+ const ForwardRef$3 = /*#__PURE__*/ react.forwardRef(PencilIcon);
960
1000
  //#endregion
961
1001
  //#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/PhotoIcon.js
962
1002
  function PhotoIcon({ title, titleId, ...props }, svgRef) {
@@ -1268,7 +1308,7 @@ window.__ModuleLoader__.load({
1268
1308
  showOutput ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1269
1309
  className: "codexImageToolRow",
1270
1310
  children: [
1271
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(!settled ? ForwardRef$6 : failed ? ForwardRef$4 : ForwardRef$2, {
1311
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(!settled ? ForwardRef$8 : failed ? ForwardRef$5 : ForwardRef$2, {
1272
1312
  className: "codexImageToolIcon",
1273
1313
  "aria-hidden": "true"
1274
1314
  }),
@@ -5434,7 +5474,7 @@ window.__ModuleLoader__.load({
5434
5474
  const IconCopyOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconCopyOutlineRegular;
5435
5475
  const IconDownloadOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconDownloadOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconDownloadOutlineRegular;
5436
5476
  const IconEditOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconEditOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular;
5437
- const IconFullscreenOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconFullscreenOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconFullscreenOutlineRegular;
5477
+ _deepseek_ai_dsh_client_ui_primitives.IconFullscreenOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconFullscreenOutlineRegular;
5438
5478
  //#endregion
5439
5479
  //#region src/image-workspace.jsx
5440
5480
  function ImageWorkspace(props) {
@@ -5767,7 +5807,7 @@ window.__ModuleLoader__.load({
5767
5807
  imageEntryPoints_on: "显示",
5768
5808
  imageEntryPoints_off: "隐藏",
5769
5809
  imageBrowsing: "图片浏览",
5770
- imageBrowsingHint: "预览粘贴图片与会话图片,标注后回到输入框编辑。",
5810
+ imageBrowsingHint: "预览粘贴图片与会话图片,可标注、移除背景、擦除、调整大小。",
5771
5811
  imageBrowsing_on: "增强",
5772
5812
  imageBrowsing_off: "DSH 默认",
5773
5813
  imageGroupMixed: "保留原设置",
@@ -5987,7 +6027,7 @@ window.__ModuleLoader__.load({
5987
6027
  resetAcknowledgeRequired: "请先确认已了解这次操作可能消耗重置次数。",
5988
6028
  resetAccountChanged: "登录账号已变更,请重新开始。",
5989
6029
  resetUncertain: "服务端返回结果不确定。请再次确认,插件会复用同一个请求,不会另外发起一次重置。",
5990
- creditsNote: "额外 Credits、消费上限、重置次数分别显示。",
6030
+ creditsNote: "下方的额外 Credits 和额度重置与套餐额度分开计算。",
5991
6031
  creditsExpires: "预计 {date} 到期,还剩 {days} 天",
5992
6032
  creditsExpiredToday: "今天 {date} 到期",
5993
6033
  creditsExpiryEstimate: "(估计:官方公布的 Pro 200 补偿 Credits 到期日,接口未返回,以 ChatGPT 使用情况页为准)",
@@ -6066,7 +6106,7 @@ window.__ModuleLoader__.load({
6066
6106
  modelMenuAria: "模型、推理等级、速度与输出详略",
6067
6107
  modelLabel: "模型",
6068
6108
  effortLabel: "推理等级",
6069
- providerDefault: "Default",
6109
+ providerDefault: "默认",
6070
6110
  selectModel: "选择模型",
6071
6111
  modelsLoading: "正在读取模型…",
6072
6112
  modelsEmpty: "没有可用模型;请先登录,并确认网络可用。",
@@ -6354,7 +6394,7 @@ window.__ModuleLoader__.load({
6354
6394
  imageEntryPoints_on: "Show",
6355
6395
  imageEntryPoints_off: "Hide",
6356
6396
  imageBrowsing: "Image browsing",
6357
- imageBrowsingHint: "Preview pasted and conversation images, annotate and return to the composer.",
6397
+ imageBrowsingHint: "Preview pasted and conversation images; annotate, remove the background, erase or resize.",
6358
6398
  imageBrowsing_on: "Enhanced",
6359
6399
  imageBrowsing_off: "DSH default",
6360
6400
  imageGroupMixed: "Keep existing",
@@ -6574,7 +6614,7 @@ window.__ModuleLoader__.load({
6574
6614
  resetAcknowledgeRequired: "Confirm that you understand this may consume a reset.",
6575
6615
  resetAccountChanged: "The signed-in account changed. Start again.",
6576
6616
  resetUncertain: "The server result is uncertain. Confirm again to check the same request; the plugin will not start a separate reset.",
6577
- creditsNote: "Extra Credits, spending caps, and resets are separate items.",
6617
+ creditsNote: "Extra Credits and quota resets below are counted separately from the plan quota.",
6578
6618
  creditsExpires: "Expires {date} ({days} days left)",
6579
6619
  creditsExpiredToday: "Expires today ({date})",
6580
6620
  creditsExpiryEstimate: "(Estimate: the published expiry of the Pro 200 compensation Credits; the API does not report it, so check ChatGPT usage settings)",
@@ -6788,7 +6828,7 @@ window.__ModuleLoader__.load({
6788
6828
  .codexSubscriptionRecover{display:flex;align-items:center;justify-content:space-between;gap:12px}
6789
6829
  .codexSubscriptionRecover .codexSubscriptionError{flex:1}
6790
6830
  .codexSubscriptionRecover button{flex:0 0 auto}
6791
- .codexSubscriptionDiagnostics{color:var(--dsw-alias-label-secondary)}
6831
+ .codexSubscriptionDiagnostics{color:var(--dsw-alias-label-secondary)}.codexSubscriptionDiagnostics h3{color:var(--dsw-alias-label-primary)}
6792
6832
  .codexSubscriptionDiagnostics ul{margin:0;padding-left:18px;font-size:13px;line-height:20px}
6793
6833
  .codexSubscriptionDiagnostics li+li{margin-top:6px}
6794
6834
  .codexSubscriptionDiagnostics li strong{font-weight:600;color:var(--dsw-alias-label-primary)}
@@ -7111,12 +7151,12 @@ window.__ModuleLoader__.load({
7111
7151
  .dcsiv-nav{position:absolute;top:50%;z-index:4;width:42px;height:42px;padding:0;transform:translateY(-50%);background:rgba(48,49,53,.82);box-shadow:0 8px 24px rgba(0,0,0,.28);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px)}.dcsiv-prev{left:6px}.dcsiv-next{right:6px}.dcsiv-counter{position:absolute;bottom:8px;left:50%;padding:5px 10px;border-radius:999px;background:rgba(38,39,43,.86);color:rgba(255,255,255,.72);font-size:11px;transform:translateX(-50%);backdrop-filter:blur(16px)}
7112
7152
  .dcsiv-hint{display:none}
7113
7153
  .dcsiv-mask{position:absolute;inset:0;width:100%;height:100%;border-radius:12px;cursor:crosshair;touch-action:none}
7114
- .dcsiv-tool-icon{width:16px;height:16px;flex:none}.dcsiv-menu{position:fixed;z-index:12;display:flex;flex-direction:column;min-width:150px;padding:6px;border:1px solid rgba(255,255,255,.12);border-radius:12px;background:rgba(32,33,37,.97);box-shadow:0 12px 32px rgba(0,0,0,.4)}.dcsiv-menu button{height:32px;padding:0 10px;border:0;border-radius:8px;background:none;color:rgba(255,255,255,.9);font:inherit;font-size:13px;text-align:left;cursor:pointer}.dcsiv-menu button:hover,.dcsiv-menu button:focus-visible{background:rgba(255,255,255,.1)}
7115
- .dcsiv-erase-bar{position:absolute;left:50%;top:22px;z-index:7;display:flex;align-items:center;gap:10px;padding:6px 8px 6px 14px;transform:translateX(-50%);border:1px solid rgba(255,255,255,.1);border-radius:999px;background:rgba(38,39,43,.92);color:rgba(255,255,255,.86);font-size:12px;white-space:nowrap}.dcsiv-erase-bar label{display:inline-flex;align-items:center;gap:6px}.dcsiv-erase-bar input{width:90px}.dcsiv-primary{background:#fff!important;color:#111!important}
7154
+ .dcsiv-tool-icon{width:16px;height:16px;flex:none}.dcsiv-icon-button,.dcsiv-download[data-compact="true"]{width:34px;padding:0!important;justify-content:center}.dcsiv-zoom{min-width:52px;font-variant-numeric:tabular-nums}.dcsiv-divider{width:1px;height:18px;margin:0 4px;background:rgba(255,255,255,.14)}.dcsiv-menu{position:fixed;z-index:12;display:flex;flex-direction:column;min-width:150px;padding:6px;border:1px solid rgba(255,255,255,.12);border-radius:12px;background:rgba(32,33,37,.97);box-shadow:0 12px 32px rgba(0,0,0,.4)}.dcsiv-menu button{height:32px;padding:0 10px;border:0;border-radius:8px;background:none;color:rgba(255,255,255,.9);font:inherit;font-size:13px;text-align:left;cursor:pointer}.dcsiv-menu button:hover,.dcsiv-menu button:focus-visible{outline:none;background:rgba(255,255,255,.1)}
7155
+ .dcsiv-erase-bar{position:absolute;left:50%;top:22px;z-index:7;display:flex;align-items:center;gap:10px;padding:6px 8px 6px 14px;transform:translateX(-50%);border:1px solid rgba(255,255,255,.1);border-radius:999px;background:rgba(38,39,43,.92);color:rgba(255,255,255,.86);font-size:12px;white-space:nowrap}.dcsiv-erase-bar label{display:inline-flex;align-items:center;gap:6px}.dcsiv-erase-bar input{width:90px}.dcsiv-primary{background:#fff!important;color:#111!important}.dcsiv-primary[data-state="failed"]{color:#c62828!important}.dcsiv-brush-cursor{position:fixed;z-index:9;pointer-events:none;border:1.5px solid #fff;border-radius:50%;corner-shape:round;box-shadow:0 0 0 1px rgba(0,0,0,.45),inset 0 0 0 1px rgba(0,0,0,.25);transform:translate(-50%,-50%)}@media(pointer:fine){.dcsiv-mask{cursor:none}}.dcsiv-button[data-state="pending"] .dcsiv-tool-icon{animation:dcsiv-pulse 1s ease-in-out infinite}.dcsiv-button[data-state="failed"]{color:#ff8a80!important}@keyframes dcsiv-pulse{50%{opacity:.3}}
7116
7156
  .dcsiv-copy-notes{position:absolute;right:20px;bottom:22px;z-index:6;display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 11px;border:1px solid rgba(255,255,255,.1);border-radius:999px;background:rgba(38,39,43,.86);color:rgba(255,255,255,.82);font:inherit;font-size:12px;cursor:pointer;backdrop-filter:blur(16px)}
7117
7157
  .dcsiv-edit-short{display:none}
7118
7158
  @media(max-width:760px){.dcsiv-actions{flex-wrap:wrap;justify-content:center}.dcsiv-edit-short{display:inline;white-space:normal;max-width:min(280px,calc(100vw - 80px))}.dcsiv-edit-action{height:auto;min-height:32px}.dcsiv-close-floating{top:12px;right:12px;width:40px;height:40px}.dcsiv-workspace{padding:60px 12px 68px}.dcsiv-image{max-width:calc(100vw - 24px);max-height:calc(100vh - 136px)}.dcsiv-topbar{bottom:12px;max-width:calc(100vw - 24px)}.dcsiv-button{padding:0 8px}.dcsiv-button span.dcsiv-label{display:none}.dcsiv-inline-note{width:min(260px,calc(100vw - 40px))}.dcsiv-copy-notes{display:none}}
7119
- @media(prefers-reduced-motion:reduce){.dcsiv-surface{transition:none}}
7159
+ @media(prefers-reduced-motion:reduce){.dcsiv-surface{transition:none}.dcsiv-tool-icon{animation:none!important}}
7120
7160
  `;
7121
7161
  //#endregion
7122
7162
  //#region src/subscription-image-transform.js
@@ -7298,8 +7338,10 @@ window.__ModuleLoader__.load({
7298
7338
  //#region src/subscription-image-viewer.jsx
7299
7339
  const TOOL_ICONS = {
7300
7340
  "remove-background": ForwardRef$1,
7301
- erase: ForwardRef$3,
7302
- resize: ForwardRef$5
7341
+ erase: ForwardRef$4,
7342
+ resize: ForwardRef$7,
7343
+ sketch: ForwardRef$3,
7344
+ annotate: ForwardRef$6
7303
7345
  };
7304
7346
  const ToolIcon = ({ id }) => {
7305
7347
  const Icon = TOOL_ICONS[id];
@@ -7322,12 +7364,41 @@ window.__ModuleLoader__.load({
7322
7364
  const [state, setState] = (0, react.useState)("idle");
7323
7365
  const [menu, setMenu] = (0, react.useState)();
7324
7366
  const active = (0, react.useRef)(true);
7367
+ const menuRef = (0, react.useRef)(null);
7368
+ const menuButtonRef = (0, react.useRef)(null);
7325
7369
  (0, react.useEffect)(() => {
7326
7370
  active.current = true;
7327
7371
  return () => {
7328
7372
  active.current = false;
7329
7373
  };
7330
7374
  }, []);
7375
+ (0, react.useEffect)(() => {
7376
+ if (menu === void 0) return void 0;
7377
+ menuRef.current?.querySelector("[role=\"menuitem\"]")?.focus();
7378
+ const onKeyDown = (event) => {
7379
+ const items = [...menuRef.current?.querySelectorAll("[role=\"menuitem\"]") ?? []];
7380
+ if (event.key === "Escape") {
7381
+ event.preventDefault();
7382
+ event.stopPropagation();
7383
+ setMenu(void 0);
7384
+ menuButtonRef.current?.focus();
7385
+ } else if ((event.key === "ArrowDown" || event.key === "ArrowUp") && items.length > 0) {
7386
+ event.preventDefault();
7387
+ event.stopPropagation();
7388
+ const step = event.key === "ArrowDown" ? 1 : -1;
7389
+ items[(items.indexOf(document.activeElement) + step + items.length) % items.length].focus();
7390
+ } else if (event.key === "Tab") setMenu(void 0);
7391
+ };
7392
+ const onPointerDown = (event) => {
7393
+ if (!menuRef.current?.contains(event.target) && !menuButtonRef.current?.contains(event.target)) setMenu(void 0);
7394
+ };
7395
+ window.addEventListener("keydown", onKeyDown, true);
7396
+ window.addEventListener("pointerdown", onPointerDown, true);
7397
+ return () => {
7398
+ window.removeEventListener("keydown", onKeyDown, true);
7399
+ window.removeEventListener("pointerdown", onPointerDown, true);
7400
+ };
7401
+ }, [menu]);
7331
7402
  const invoke = async (extra = {}) => {
7332
7403
  if (state === "pending") return;
7333
7404
  setState("pending");
@@ -7346,32 +7417,42 @@ window.__ModuleLoader__.load({
7346
7417
  }
7347
7418
  };
7348
7419
  const label = state === "pending" ? action.pendingLabel : state === "failed" ? action.errorLabel : action.label;
7349
- if (action.kind === "mask") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
7420
+ if (action.kind === "mask") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7350
7421
  type: "button",
7351
- className: "dcsiv-button",
7422
+ className: "dcsiv-button dcsiv-icon-button",
7423
+ title: action.label,
7424
+ "aria-label": action.label,
7352
7425
  onClick: () => onStartMask(action),
7353
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: action.id }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7354
- className: "dcsiv-label",
7355
- children: action.label
7356
- })]
7426
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: action.id })
7357
7427
  });
7358
- if (action.kind === "tool") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
7428
+ if (action.kind === "tool") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7359
7429
  type: "button",
7360
- className: "dcsiv-button",
7430
+ className: "dcsiv-button dcsiv-icon-button",
7431
+ title: label,
7432
+ "aria-label": label,
7433
+ "data-state": state,
7361
7434
  disabled: state === "pending",
7362
7435
  onClick: () => {
7363
7436
  invoke();
7364
7437
  },
7365
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: action.id }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7366
- className: "dcsiv-label",
7367
- children: label
7368
- })]
7438
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: action.id })
7439
+ });
7440
+ if (action.id === "sketch" && state === "idle") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7441
+ type: "button",
7442
+ className: "dcsiv-button dcsiv-icon-button",
7443
+ title: action.label,
7444
+ "aria-label": action.label,
7445
+ onClick: () => {
7446
+ invoke();
7447
+ },
7448
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: "sketch" })
7369
7449
  });
7370
- if (action.kind === "choice") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
7450
+ if (action.kind === "choice") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7451
+ ref: menuButtonRef,
7371
7452
  type: "button",
7372
- className: "dcsiv-button",
7373
7453
  "aria-haspopup": "menu",
7374
7454
  "aria-expanded": menu !== void 0,
7455
+ "data-state": state,
7375
7456
  disabled: state === "pending",
7376
7457
  onClick: (event) => {
7377
7458
  const box = event.currentTarget.getBoundingClientRect();
@@ -7384,13 +7465,15 @@ window.__ModuleLoader__.load({
7384
7465
  }
7385
7466
  } : void 0);
7386
7467
  },
7387
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: action.id }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7388
- className: "dcsiv-label",
7389
- children: label
7390
- })]
7468
+ className: "dcsiv-button dcsiv-icon-button",
7469
+ title: label,
7470
+ "aria-label": label,
7471
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: action.id })
7391
7472
  }), menu ? (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7473
+ ref: menuRef,
7392
7474
  className: "dcsiv-menu",
7393
7475
  role: "menu",
7476
+ "aria-label": action.label,
7394
7477
  style: menu.style,
7395
7478
  children: action.options.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7396
7479
  type: "button",
@@ -7462,10 +7545,13 @@ window.__ModuleLoader__.load({
7462
7545
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
7463
7546
  type: "button",
7464
7547
  className: "dcsiv-download",
7548
+ "data-compact": state === "idle",
7549
+ title: label,
7550
+ "aria-label": label,
7465
7551
  onClick: () => {
7466
7552
  invoke();
7467
7553
  },
7468
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownloadOutline16, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7554
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownloadOutline16, {}), state === "idle" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7469
7555
  className: "dcsiv-label",
7470
7556
  children: state === "pending" ? `${label} ${progress}% · ${t("cancel")}` : label
7471
7557
  })]
@@ -7492,6 +7578,16 @@ window.__ModuleLoader__.load({
7492
7578
  const [strokes, setStrokes] = (0, react.useState)([]);
7493
7579
  const [brush, setBrush] = (0, react.useState)(.05);
7494
7580
  const [sending, setSending] = (0, react.useState)(false);
7581
+ const [sendFailed, setSendFailed] = (0, react.useState)(false);
7582
+ const [brushCursor, setBrushCursor] = (0, react.useState)();
7583
+ const eraseRef = (0, react.useRef)({
7584
+ erasing: void 0,
7585
+ sending: false
7586
+ });
7587
+ eraseRef.current = {
7588
+ erasing,
7589
+ sending
7590
+ };
7495
7591
  const drawingRef = (0, react.useRef)(false);
7496
7592
  const maskRef = (0, react.useRef)(null);
7497
7593
  const rootRef = (0, react.useRef)(null);
@@ -7523,6 +7619,28 @@ window.__ModuleLoader__.load({
7523
7619
  document.body.style.overflow = "hidden";
7524
7620
  rootRef.current?.focus();
7525
7621
  const onKeyDown = (event) => {
7622
+ if (eraseRef.current.erasing !== void 0) {
7623
+ const key = event.key.toLowerCase();
7624
+ if (event.key === "Escape") {
7625
+ event.preventDefault();
7626
+ if (!eraseRef.current.sending) {
7627
+ setErasing(void 0);
7628
+ setStrokes([]);
7629
+ }
7630
+ return;
7631
+ }
7632
+ if ((event.ctrlKey || event.metaKey) && key === "z") {
7633
+ event.preventDefault();
7634
+ if (!eraseRef.current.sending) setStrokes((current) => current.slice(0, -1));
7635
+ return;
7636
+ }
7637
+ if (event.key === "[" || event.key === "]") {
7638
+ event.preventDefault();
7639
+ setBrush((value) => Math.round(clamp(value + (event.key === "]" ? .01 : -.01), .01, .15) * 100) / 100);
7640
+ return;
7641
+ }
7642
+ if (event.key === "ArrowLeft" || event.key === "ArrowRight") return;
7643
+ }
7526
7644
  if (event.key === "Escape") {
7527
7645
  event.preventDefault();
7528
7646
  if (event.target instanceof Element && event.target.closest(".dcsiv-inline-note") !== null) {
@@ -7621,6 +7739,12 @@ window.__ModuleLoader__.load({
7621
7739
  }]);
7622
7740
  },
7623
7741
  onPointerMove: (event) => {
7742
+ const bounds = maskRef.current?.getBoundingClientRect();
7743
+ if (bounds !== void 0) setBrushCursor({
7744
+ left: event.clientX,
7745
+ top: event.clientY,
7746
+ span: Math.min(bounds.width, bounds.height) / transformRef.current.zoom
7747
+ });
7624
7748
  if (!drawingRef.current) return;
7625
7749
  const point = strokePoint(event);
7626
7750
  if (point === void 0) return;
@@ -7634,18 +7758,24 @@ window.__ModuleLoader__.load({
7634
7758
  },
7635
7759
  onPointerCancel: () => {
7636
7760
  drawingRef.current = false;
7761
+ },
7762
+ onPointerLeave: () => {
7763
+ setBrushCursor(void 0);
7637
7764
  }
7638
7765
  };
7639
7766
  const startMask = (action) => {
7640
7767
  resetGesture();
7641
7768
  setAnnotating(false);
7642
7769
  setStrokes([]);
7770
+ setSendFailed(false);
7771
+ setBrushCursor(void 0);
7643
7772
  setErasing(action);
7644
7773
  };
7645
7774
  const sendMask = async () => {
7646
7775
  const image = imageRef.current;
7647
7776
  if (!erasing || strokes.length === 0 || image === null || sending) return;
7648
7777
  setSending(true);
7778
+ setSendFailed(false);
7649
7779
  try {
7650
7780
  const canvas = document.createElement("canvas");
7651
7781
  canvas.width = image.naturalWidth;
@@ -7661,6 +7791,8 @@ window.__ModuleLoader__.load({
7661
7791
  setErasing(void 0);
7662
7792
  setStrokes([]);
7663
7793
  if (erasing.closeOnSuccess) service.close();
7794
+ } catch {
7795
+ setSendFailed(true);
7664
7796
  } finally {
7665
7797
  setSending(false);
7666
7798
  }
@@ -7726,18 +7858,19 @@ window.__ModuleLoader__.load({
7726
7858
  children: [
7727
7859
  request.annotations ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
7728
7860
  type: "button",
7729
- className: "dcsiv-button",
7861
+ className: annotating ? "dcsiv-button" : "dcsiv-button dcsiv-icon-button",
7730
7862
  "data-active": annotating,
7863
+ title: annotating ? t("imageAnnotateCancel") : t("imageAnnotate"),
7731
7864
  "aria-label": annotating ? t("imageAnnotateCancel") : t("imageAnnotate"),
7732
7865
  "aria-pressed": annotating,
7733
7866
  onClick: () => {
7734
7867
  resetGesture();
7735
7868
  setAnnotating((value) => !value);
7736
7869
  },
7737
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconEditOutline16, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7870
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: "annotate" }), annotating ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7738
7871
  className: "dcsiv-label",
7739
- children: annotating ? t("imageAnnotateCancel") : t("imageAnnotate")
7740
- })]
7872
+ children: t("imageAnnotateCancel")
7873
+ }) : null]
7741
7874
  }) : null,
7742
7875
  annotations.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
7743
7876
  type: "button",
@@ -7759,32 +7892,27 @@ window.__ModuleLoader__.load({
7759
7892
  }) : null,
7760
7893
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
7761
7894
  type: "button",
7762
- className: "dcsiv-button",
7763
- "aria-label": t("imageFit"),
7764
- onClick: fit,
7765
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFullscreenOutline16, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7766
- className: "dcsiv-label",
7767
- children: t("imageFit")
7768
- })]
7769
- }),
7770
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7771
- type: "button",
7772
- className: "dcsiv-button",
7773
- onClick: actual,
7774
- children: t("imageActual")
7775
- }),
7776
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7777
- className: "dcsiv-zoom",
7895
+ className: "dcsiv-button dcsiv-zoom",
7896
+ title: transform.zoom === 1 ? t("imageActual") : t("imageFit"),
7897
+ "aria-label": transform.zoom === 1 ? t("imageActual") : t("imageFit"),
7898
+ onClick: () => {
7899
+ if (transform.zoom === 1) actual();
7900
+ else fit();
7901
+ },
7778
7902
  children: [Math.round(transform.zoom * pixelScale * 100), "%"]
7779
7903
  }),
7780
- item.download === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
7904
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7905
+ className: "dcsiv-divider",
7906
+ "aria-hidden": "true"
7907
+ }),
7908
+ item.download === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
7781
7909
  className: "dcsiv-download",
7910
+ "data-compact": "true",
7782
7911
  href: item.src,
7783
7912
  download: downloadName(item.name),
7784
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownloadOutline16, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7785
- className: "dcsiv-label",
7786
- children: t("imageDownload")
7787
- })]
7913
+ title: t("imageDownload"),
7914
+ "aria-label": t("imageDownload"),
7915
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownloadOutline16, {})
7788
7916
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ViewerDownload, {
7789
7917
  download: item.download,
7790
7918
  item,
@@ -7982,14 +8110,25 @@ window.__ModuleLoader__.load({
7982
8110
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7983
8111
  type: "button",
7984
8112
  className: "dcsiv-button dcsiv-primary",
8113
+ "data-state": sendFailed ? "failed" : void 0,
7985
8114
  disabled: strokes.length === 0 || sending,
7986
8115
  onClick: () => {
7987
8116
  sendMask();
7988
8117
  },
7989
- children: sending ? t("imageEditPreparing") : t("imageSend")
8118
+ children: sending ? t("imageEditPreparing") : sendFailed ? t("imageEditFailed") : t("imageSend")
7990
8119
  })
7991
8120
  ]
7992
8121
  }) : null,
8122
+ erasing && brushCursor ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8123
+ className: "dcsiv-brush-cursor",
8124
+ "aria-hidden": "true",
8125
+ style: {
8126
+ left: brushCursor.left,
8127
+ top: brushCursor.top,
8128
+ width: brush * brushCursor.span,
8129
+ height: brush * brushCursor.span
8130
+ }
8131
+ }) : null,
7993
8132
  annotations.some((annotation) => annotation.note.trim() !== "") ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
7994
8133
  type: "button",
7995
8134
  className: "dcsiv-copy-notes",
@@ -8952,7 +9091,7 @@ window.__ModuleLoader__.load({
8952
9091
  }
8953
9092
  //#endregion
8954
9093
  //#region src/version.js
8955
- const PACKAGE_VERSION = "2.5.8";
9094
+ const PACKAGE_VERSION = "2.5.9";
8956
9095
  //#endregion
8957
9096
  //#region src/client-recovery.js
8958
9097
  async function recoveryCall(rpc, endpoint, payload = {}, timeoutMs = 1e4) {
@@ -11631,6 +11770,7 @@ window.__ModuleLoader__.load({
11631
11770
  //#endregion
11632
11771
  //#region src/client-usage.jsx
11633
11772
  const count = (value) => Number(value).toLocaleString();
11773
+ const creditAmount = (value) => Number.isFinite(Number(value)) && String(value).trim() !== "" ? Number(value).toLocaleString(void 0, { maximumFractionDigits: 2 }) : value;
11634
11774
  function CreditExpiry({ credits, t }) {
11635
11775
  const date = validDate(credits.expiresAt);
11636
11776
  if (date === void 0 || credits.unlimited) return null;
@@ -12033,7 +12173,7 @@ window.__ModuleLoader__.load({
12033
12173
  children: [
12034
12174
  visibleUsage?.credits ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
12035
12175
  className: "codexSubscriptionCreditBalance",
12036
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("creditsBalance") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: visibleUsage.credits.unlimited ? t("unlimited") : `${visibleUsage.credits.balance ?? t("unavailable")} ${t("creditsUnit")}` })]
12176
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("creditsBalance") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: visibleUsage.credits.unlimited ? t("unlimited") : visibleUsage.credits.balance == null ? t("unavailable") : `${creditAmount(visibleUsage.credits.balance)} ${t("creditsUnit")}` })]
12037
12177
  }) : null,
12038
12178
  visibleUsage?.credits ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditExpiry, {
12039
12179
  credits: visibleUsage.credits,
package/lib/index.js CHANGED
@@ -2049,7 +2049,7 @@ function inheritedOriginalImageRef(session, assetId) {
2049
2049
  }
2050
2050
  //#endregion
2051
2051
  //#region src/version.js
2052
- const PACKAGE_VERSION = "2.5.8";
2052
+ const PACKAGE_VERSION = "2.5.9";
2053
2053
  const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
2054
2054
  //#endregion
2055
2055
  //#region src/codex-images.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-codex-subscription",
3
- "version": "2.5.8",
3
+ "version": "2.5.9",
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",