dsh-image-gen 0.6.7 → 0.6.8

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.
Files changed (40) hide show
  1. package/README.en.md +387 -375
  2. package/README.md +387 -375
  3. package/README.zh-CN.md +3 -3
  4. package/docs/assets/readme/chat-generate.webp +0 -0
  5. package/docs/assets/readme/other-features.webp +0 -0
  6. package/lib/client.js +146 -37
  7. package/lib/client.js.map +1 -1
  8. package/lib/index.js +200 -37
  9. package/lib/types/client/conversation-image-revisions.d.ts +2 -2
  10. package/lib/types/client/gallery-view.d.ts +4 -0
  11. package/lib/types/client/multi-model-compare.d.ts +3 -3
  12. package/lib/types/client/provider-pill.d.ts +1 -1
  13. package/lib/types/client/studio-chat-panel.d.ts +23 -0
  14. package/lib/types/client/studio-view.d.ts +4 -0
  15. package/lib/types/client/tl/diagram-landing.d.ts +75 -0
  16. package/lib/types/client/tl/diagram-layout.d.ts +76 -0
  17. package/lib/types/client/tl/diagram-measure.d.ts +40 -0
  18. package/lib/types/diagram.d.ts +42 -0
  19. package/lib/types/shared.d.ts +16 -4
  20. package/lib/types/studio-chat.d.ts +48 -0
  21. package/lib/types/studio.d.ts +3 -2
  22. package/lib/types/subscription/manager.d.ts +15 -0
  23. package/lib/types/subscription/vendors/antigravity.d.ts +10 -1
  24. package/lib/types/subscription/vendors/codex.d.ts +2 -0
  25. package/lib/types/subscription/vendors/grok.d.ts +2 -0
  26. package/lib/types/subscription.d.ts +7 -5
  27. package/package.json +10 -8
  28. package/skills/install-dsh-image-gen/SKILL.md +22 -22
  29. package/lib/types/client/inspiration-api.d.ts +0 -10
  30. package/lib/types/client/inspiration-detail.d.ts +0 -14
  31. package/lib/types/client/tldraw/generated/tldraw-assets.d.ts +0 -12
  32. package/lib/types/client/tldraw/generated/tldraw-css.d.ts +0 -1
  33. package/lib/types/client/tldraw/tldraw-style.d.ts +0 -1
  34. package/lib/types/client/tldraw/tldraw-workspace.d.ts +0 -1
  35. package/lib/types/inspiration/cache.d.ts +0 -20
  36. package/lib/types/inspiration/downloader.d.ts +0 -27
  37. package/lib/types/inspiration/routes.d.ts +0 -13
  38. package/lib/types/inspiration/sources.d.ts +0 -33
  39. package/lib/types/inspiration/types.d.ts +0 -65
  40. package/lib/types/inspiration/updater.d.ts +0 -7
package/README.zh-CN.md CHANGED
@@ -1,3 +1,3 @@
1
- # dsh-image-gen 中文文档
2
-
3
- 此文件为兼容旧链接而保留。完整的简体中文文档请参阅 [README.md](README.md)。
1
+ # dsh-image-gen 中文文档
2
+
3
+ 此文件为兼容旧链接而保留。完整的简体中文文档请参阅 [README.md](README.md)。
package/lib/client.js CHANGED
@@ -129,6 +129,12 @@ window.__ModuleLoader__.load({
129
129
  "xai",
130
130
  "zhipu"
131
131
  ];
132
+ /**
133
+ * Providers the browser workbench can drive: the BYOK cloud set plus the
134
+ * logged-in subscription channels. ComfyUI stays out; it has its own workflow
135
+ * pipeline and no shared request shape.
136
+ */
137
+ const STUDIO_PROVIDERS = [...CLOUD_IMAGE_PROVIDERS, ...SUBSCRIPTION_PROVIDERS];
132
138
  /** The credential reference each cloud provider's API key is stored under. */
133
139
  const CLOUD_CREDENTIAL_REFS = {
134
140
  google: "GEMINI_API_KEY",
@@ -116255,6 +116261,9 @@ img.ProseMirror-separator {
116255
116261
  configuredCount: "API 已配置 · {count}",
116256
116262
  unconfiguredStatus: "API 未配置",
116257
116263
  providerStatus: "云端提供商与模型状态",
116264
+ configuredSplit: "API {api} · 订阅 {sub}",
116265
+ subSignedIn: "已登录",
116266
+ subSignedOut: "未登录",
116258
116267
  collapseSidebar: "折叠最近生成",
116259
116268
  expandSidebar: "展开最近生成",
116260
116269
  collapseGenerate: "折叠生成面板",
@@ -116360,6 +116369,9 @@ img.ProseMirror-separator {
116360
116369
  configuredCount: "API configured · {count}",
116361
116370
  unconfiguredStatus: "Not configured",
116362
116371
  providerStatus: "Provider & Model Status",
116372
+ configuredSplit: "API {api} · Sub {sub}",
116373
+ subSignedIn: "Signed in",
116374
+ subSignedOut: "Signed out",
116363
116375
  collapseSidebar: "Collapse sidebar",
116364
116376
  expandSidebar: "Expand recent list",
116365
116377
  collapseGenerate: "Collapse generate panel",
@@ -116374,7 +116386,7 @@ img.ProseMirror-separator {
116374
116386
  };
116375
116387
  /** localStorage flag remembering that the one-time infinite-canvas hint was dismissed. */
116376
116388
  const INFINITE_CANVAS_HINT_KEY = "dsh-ig-infinite-canvas-hint-dismissed";
116377
- const StudioView = ({ locale, workspace, initialPrompt, initialCanvasSurface, showInfiniteCanvasHint, onInitialPromptApplied, onOpenInspiration }) => {
116389
+ const StudioView = ({ locale, credentialEvents, workspace, initialPrompt, initialCanvasSurface, showInfiniteCanvasHint, onInitialPromptApplied, onOpenInspiration }) => {
116378
116390
  const [lang, setLang] = (0, react.useState)(() => locale?.getSnapshot?.().active?.startsWith("en") ? "en" : "zh");
116379
116391
  const [config, setConfig] = (0, react.useState)(null);
116380
116392
  const [configLoading, setConfigLoading] = (0, react.useState)(true);
@@ -116481,15 +116493,28 @@ img.ProseMirror-separator {
116481
116493
  const maxReferences = comparisonEnabled ? comparisonProviders.includes("dashscope") ? 3 : 5 : provider === "dashscope" ? 3 : 5;
116482
116494
  const referencesRef = (0, react.useRef)(references);
116483
116495
  referencesRef.current = references;
116496
+ const comparisonSelectionsAllSubscription = comparisonEnabled && comparisonProviders.length > 0 && comparisonProviders.every((provider) => isSubscriptionProvider(provider));
116497
+ const singleProviderIsSubscription = !comparisonEnabled && isSubscriptionProvider(provider);
116484
116498
  const t = (key, values) => {
116485
116499
  let text = COPY$1[lang][key];
116486
116500
  for (const [name, value] of Object.entries(values ?? {})) text = text.replace(`{${name}}`, value);
116487
116501
  return text;
116488
116502
  };
116489
116503
  (0, react.useEffect)(() => locale?.subscribe?.(() => setLang(locale.getSnapshot().active?.startsWith("en") ? "en" : "zh")), [locale]);
116490
- const loadConfig = (0, react.useCallback)(async () => {
116491
- setConfigLoading(true);
116492
- setConfigError(null);
116504
+ const formStateRef = (0, react.useRef)({
116505
+ provider,
116506
+ model
116507
+ });
116508
+ formStateRef.current = {
116509
+ provider,
116510
+ model
116511
+ };
116512
+ const loadConfig = (0, react.useCallback)(async (options) => {
116513
+ const silent = options?.silent === true;
116514
+ if (!silent) {
116515
+ setConfigLoading(true);
116516
+ setConfigError(null);
116517
+ }
116493
116518
  const controller = new AbortController();
116494
116519
  try {
116495
116520
  const response = await fetch(STUDIO_ROUTE, {
@@ -116499,20 +116524,35 @@ img.ProseMirror-separator {
116499
116524
  const payload = await response.json();
116500
116525
  if (!response.ok || !("providers" in payload)) throw new Error("error" in payload && payload.error ? payload.error : "Studio unavailable");
116501
116526
  setConfig(payload);
116527
+ if (silent) {
116528
+ const { provider: currentProvider, model: currentModel } = formStateRef.current;
116529
+ const activeProfile = payload.providers.find((item) => item.provider === currentProvider);
116530
+ if (activeProfile !== void 0 && activeProfile.model !== currentModel) setModel(activeProfile.model);
116531
+ setComparisonProviders((current) => current.filter((selectedProvider) => payload.providers.some((item) => item.provider === selectedProvider && item.configured)));
116532
+ return;
116533
+ }
116502
116534
  const initial = payload.providers.find((item) => item.provider === payload.activeProvider) ?? payload.providers[0];
116503
116535
  if (initial !== void 0) {
116504
116536
  applyProvider(initial);
116505
116537
  setComparisonProviders(initialComparisonProviders(payload.providers, initial.provider));
116506
116538
  }
116507
116539
  } catch (fetchError) {
116508
- if (!controller.signal.aborted) setConfigError(messageOf(fetchError));
116540
+ if (!silent && !controller.signal.aborted) setConfigError(messageOf(fetchError));
116509
116541
  } finally {
116510
- setConfigLoading(false);
116542
+ if (!silent) setConfigLoading(false);
116511
116543
  }
116512
116544
  }, []);
116513
116545
  (0, react.useEffect)(() => {
116514
116546
  loadConfig();
116515
116547
  }, [loadConfig]);
116548
+ (0, react.useEffect)(() => {
116549
+ if (credentialEvents === void 0) return;
116550
+ return credentialEvents.listen(() => {
116551
+ window.setTimeout(() => {
116552
+ loadConfig({ silent: true });
116553
+ }, 1e3);
116554
+ });
116555
+ }, [credentialEvents, loadConfig]);
116516
116556
  (0, react.useEffect)(() => {
116517
116557
  let mounted = true;
116518
116558
  const load = () => void getGalleryItems().then((next) => {
@@ -116584,6 +116624,8 @@ img.ProseMirror-separator {
116584
116624
  }, []);
116585
116625
  const activeProfile = (0, react.useMemo)(() => config?.providers.find((item) => item.provider === provider), [config, provider]);
116586
116626
  const configuredCount = config?.providers.filter((item) => item.configured).length ?? 0;
116627
+ const apiConfiguredCount = config?.providers.filter((item) => item.configured && !isSubscriptionProvider(item.provider)).length ?? 0;
116628
+ const subscriptionSignedInCount = config?.providers.filter((item) => item.configured && isSubscriptionProvider(item.provider)).length ?? 0;
116587
116629
  const displayItems = (0, react.useMemo)(() => items.slice(0, visibleLimit), [items, visibleLimit]);
116588
116630
  const comparisonProfiles = (0, react.useMemo)(() => (config?.providers ?? []).filter((item) => item.configured && (mode === "generate" || item.supportsEditing)), [config, mode]);
116589
116631
  const comparisonTargets = (0, react.useMemo)(() => buildComparisonTargets(comparisonProfiles, comparisonProviders, ratio, quality), [
@@ -117179,7 +117221,10 @@ img.ProseMirror-separator {
117179
117221
  (0, react_jsx_runtime.jsx)("span", { className: `dsh-ig-status-dot ${configuredCount > 0 ? "is-ready" : "is-muted"}` }),
117180
117222
  (0, react_jsx_runtime.jsx)("span", {
117181
117223
  className: "dsh-ig-status-text",
117182
- children: configuredCount > 0 ? t("configuredCount", { count: String(configuredCount) }) : t("unconfiguredStatus")
117224
+ children: configuredCount > 0 ? subscriptionSignedInCount > 0 ? t("configuredSplit", {
117225
+ api: String(apiConfiguredCount),
117226
+ sub: String(subscriptionSignedInCount)
117227
+ }) : t("configuredCount", { count: String(apiConfiguredCount) }) : t("unconfiguredStatus")
117183
117228
  }),
117184
117229
  (0, react_jsx_runtime.jsx)(ChevronDown, {
117185
117230
  size: 11,
@@ -117200,7 +117245,7 @@ img.ProseMirror-separator {
117200
117245
  children: [(0, react_jsx_runtime.jsx)("strong", { children: p.label }), (0, react_jsx_runtime.jsx)("small", { children: p.model })]
117201
117246
  }), (0, react_jsx_runtime.jsx)("span", {
117202
117247
  className: "dsh-ig-status-item-tag",
117203
- children: p.configured ? t("configured") : t("unconfigured")
117248
+ children: isSubscriptionProvider(p.provider) ? p.configured ? t("subSignedIn") : t("subSignedOut") : p.configured ? t("configured") : t("unconfigured")
117204
117249
  })]
117205
117250
  }, p.provider))
117206
117251
  })]
@@ -117646,7 +117691,26 @@ img.ProseMirror-separator {
117646
117691
  }),
117647
117692
  (0, react_jsx_runtime.jsx)("p", { children: t("compareParameterHint") })
117648
117693
  ]
117649
- }), (0, react_jsx_runtime.jsxs)("div", {
117694
+ }), comparisonSelectionsAllSubscription ? (0, react_jsx_runtime.jsxs)("div", {
117695
+ className: "dsh-ig-field-grid",
117696
+ children: [(0, react_jsx_runtime.jsx)(FieldSelect, {
117697
+ label: t("ratio"),
117698
+ value: "auto",
117699
+ onChange: () => {},
117700
+ options: [{
117701
+ value: "auto",
117702
+ label: lang === "en" ? "Channel default" : "通道默认"
117703
+ }]
117704
+ }), (0, react_jsx_runtime.jsx)(FieldSelect, {
117705
+ label: t("quality"),
117706
+ value: "auto",
117707
+ onChange: () => {},
117708
+ options: [{
117709
+ value: "auto",
117710
+ label: lang === "en" ? "Channel default" : "通道默认"
117711
+ }]
117712
+ })]
117713
+ }) : (0, react_jsx_runtime.jsxs)("div", {
117650
117714
  className: "dsh-ig-field-grid",
117651
117715
  children: [(0, react_jsx_runtime.jsx)(FieldSelect, {
117652
117716
  label: t("ratio"),
@@ -117680,7 +117744,26 @@ img.ProseMirror-separator {
117680
117744
  }]
117681
117745
  })]
117682
117746
  }),
117683
- (0, react_jsx_runtime.jsxs)("div", {
117747
+ singleProviderIsSubscription ? (0, react_jsx_runtime.jsxs)("div", {
117748
+ className: "dsh-ig-field-grid",
117749
+ children: [(0, react_jsx_runtime.jsx)(FieldSelect, {
117750
+ label: t("ratio"),
117751
+ value: "auto",
117752
+ onChange: () => {},
117753
+ options: [{
117754
+ value: "auto",
117755
+ label: lang === "en" ? "Channel default" : "通道默认"
117756
+ }]
117757
+ }), (0, react_jsx_runtime.jsx)(FieldSelect, {
117758
+ label: t("quality"),
117759
+ value: "auto",
117760
+ onChange: () => {},
117761
+ options: [{
117762
+ value: "auto",
117763
+ label: lang === "en" ? "Channel default" : "通道默认"
117764
+ }]
117765
+ })]
117766
+ }) : (0, react_jsx_runtime.jsxs)("div", {
117684
117767
  className: "dsh-ig-field-grid",
117685
117768
  children: [(0, react_jsx_runtime.jsx)(FieldSelect, {
117686
117769
  label: t("ratio"),
@@ -119533,7 +119616,7 @@ img.ProseMirror-separator {
119533
119616
  return "1:1";
119534
119617
  }
119535
119618
  const GalleryViewTab = (props) => {
119536
- const { locale, sessionId, useSessions, useWorkspaces, inSidebar, defaultTab, initialCanvasSurface } = props;
119619
+ const { locale, sessionId, useSessions, useWorkspaces, credentialEvents, inSidebar, defaultTab, initialCanvasSurface } = props;
119537
119620
  const [activeTab, setActiveTab] = (0, react.useState)(defaultTab ?? "gallery");
119538
119621
  const [studioDraft, setStudioDraft] = (0, react.useState)(void 0);
119539
119622
  const [items, setItems] = (0, react.useState)([]);
@@ -120290,6 +120373,7 @@ img.ProseMirror-separator {
120290
120373
  onUsePrompt: useInspirationPrompt
120291
120374
  }) : (0, react_jsx_runtime.jsx)(StudioView, {
120292
120375
  locale,
120376
+ credentialEvents,
120293
120377
  workspace: activeWorkspace,
120294
120378
  initialPrompt: studioDraft,
120295
120379
  initialCanvasSurface,
@@ -121478,7 +121562,7 @@ img.ProseMirror-separator {
121478
121562
  function isRevision(value) {
121479
121563
  if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
121480
121564
  const candidate = value;
121481
- return isAttachment(candidate.attachment) && typeof candidate.provider === "string" && CLOUD_IMAGE_PROVIDERS.includes(candidate.provider) && typeof candidate.prompt === "string" && typeof candidate.model === "string" && typeof candidate.output === "string" && typeof candidate.createdAt === "number" && Number.isFinite(candidate.createdAt) && typeof candidate.ratio === "string" && typeof candidate.quality === "string";
121565
+ return isAttachment(candidate.attachment) && typeof candidate.provider === "string" && STUDIO_PROVIDERS.includes(candidate.provider) && typeof candidate.prompt === "string" && typeof candidate.model === "string" && typeof candidate.output === "string" && typeof candidate.createdAt === "number" && Number.isFinite(candidate.createdAt) && typeof candidate.ratio === "string" && typeof candidate.quality === "string";
121482
121566
  }
121483
121567
  function isAttachment(value) {
121484
121568
  if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
@@ -121523,19 +121607,36 @@ img.ProseMirror-separator {
121523
121607
  switchFailed: "Switch failed"
121524
121608
  }
121525
121609
  };
121526
- /** Short row labels; the settings card keeps the longer descriptive names. */
121610
+ /** Provider row names, per locale. Brand words stay untranslated; only the
121611
+ * qualifier ("订阅" / "Sub") localizes, so the pill and the menu agree with the
121612
+ * settings card in both languages. */
121527
121613
  const PILL_PROVIDER_LABELS = {
121528
- google: "Gemini",
121529
- openai: "OpenAI",
121530
- "openai-compat": "OpenAI 兼容",
121531
- seedream: "Seedream",
121532
- dashscope: "DashScope",
121533
- xai: "Grok",
121534
- zhipu: "智谱 GLM",
121535
- comfyui: "ComfyUI",
121536
- "chatgpt-sub": "ChatGPT 订阅",
121537
- "grok-sub": "Grok 订阅",
121538
- "google-sub": "Google 订阅"
121614
+ zh: {
121615
+ google: "Gemini",
121616
+ openai: "OpenAI",
121617
+ "openai-compat": "OpenAI 兼容",
121618
+ seedream: "Seedream",
121619
+ dashscope: "DashScope",
121620
+ xai: "Grok",
121621
+ zhipu: "智谱 GLM",
121622
+ comfyui: "ComfyUI",
121623
+ "chatgpt-sub": "ChatGPT 订阅",
121624
+ "grok-sub": "Grok 订阅",
121625
+ "google-sub": "Google 订阅"
121626
+ },
121627
+ en: {
121628
+ google: "Gemini",
121629
+ openai: "OpenAI",
121630
+ "openai-compat": "OpenAI Compatible",
121631
+ seedream: "Seedream",
121632
+ dashscope: "DashScope",
121633
+ xai: "Grok",
121634
+ zhipu: "Zhipu GLM",
121635
+ comfyui: "ComfyUI",
121636
+ "chatgpt-sub": "ChatGPT Sub",
121637
+ "grok-sub": "Grok Sub",
121638
+ "google-sub": "Google Sub"
121639
+ }
121539
121640
  };
121540
121641
  /** Compute the fixed-position anchor from the pill button: open upward when
121541
121642
  * the chat pane leaves room above the composer, drop down otherwise. */
@@ -121787,7 +121888,7 @@ img.ProseMirror-separator {
121787
121888
  }),
121788
121889
  (0, react_jsx_runtime.jsx)("span", {
121789
121890
  className: "dsh-ig-pill-provider",
121790
- children: PILL_PROVIDER_LABELS[current]
121891
+ children: PILL_PROVIDER_LABELS[lang][current]
121791
121892
  }),
121792
121893
  (0, react_jsx_runtime.jsx)("span", {
121793
121894
  className: `dsh-ig-pill-caret${open ? " dsh-ig-pill-caret-open" : ""}`,
@@ -121833,7 +121934,7 @@ img.ProseMirror-separator {
121833
121934
  className: "dsh-ig-pill-option-text",
121834
121935
  children: [(0, react_jsx_runtime.jsx)("span", {
121835
121936
  className: "dsh-ig-pill-option-name",
121836
- children: PILL_PROVIDER_LABELS[provider]
121937
+ children: PILL_PROVIDER_LABELS[lang][provider]
121837
121938
  }), (0, react_jsx_runtime.jsx)("span", {
121838
121939
  className: "dsh-ig-pill-option-sub",
121839
121940
  children: subtitleOf(provider)
@@ -121871,16 +121972,20 @@ img.ProseMirror-separator {
121871
121972
  }
121872
121973
  /** Styles for the pill and its fixed-position menu; injected by the client entry. */
121873
121974
  const PROVIDER_PILL_STYLE = `
121874
- .dsh-ig-pill-root{position:relative;display:inline-flex;align-items:center;height:26px}
121875
- .dsh-ig-pill-button{display:inline-flex;align-items:center;gap:5px;height:26px;padding:0 8px 0 7px;border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:13px;background:var(--dsw-alias-bg-layer-3,#fff);color:var(--dsw-alias-label-secondary,#4b5563);font:inherit;font-size:12px;line-height:1;cursor:pointer;transition:border-color .15s,background .15s,color .15s;-webkit-user-select:none;user-select:none}
121975
+ .dsh-ig-pill-root{position:relative;display:inline-flex;align-items:center;height:28px}
121976
+ .dsh-ig-pill-button{display:inline-flex;align-items:center;gap:5px;height:28px;padding:0 9px 0 8px;border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:14px;background:var(--dsw-alias-bg-layer-3,#fff);color:var(--dsw-alias-label-secondary,#4b5563);font:inherit;font-size:13px;line-height:20px;cursor:pointer;transition:border-color .15s,background .15s,color .15s;-webkit-user-select:none;user-select:none}
121876
121977
  .dsh-ig-pill-button:hover:not(:disabled){border-color:var(--dsw-alias-label-dimmed,#9ca3af);color:var(--dsw-alias-label-primary,#111827)}
121877
121978
  .dsh-ig-pill-button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#4c78ff);outline-offset:1px}
121878
121979
  .dsh-ig-pill-button:disabled{opacity:.5;cursor:not-allowed}
121879
121980
  .dsh-ig-pill-button-open{border-color:var(--dsw-alias-brand-primary,#4c78ff);color:var(--dsw-alias-label-primary,#111827)}
121880
121981
  .dsh-ig-pill-icon{flex:none;color:var(--dsw-alias-brand-primary,#4c78ff)}
121881
- .dsh-ig-pill-provider{max-width:96px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
121982
+ .dsh-ig-pill-provider{max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
121882
121983
  .dsh-ig-pill-caret{display:inline-flex;flex:none;transition:transform .15s}
121883
121984
  .dsh-ig-pill-caret-open{transform:rotate(180deg)}
121985
+ @container (max-width:700px){
121986
+ .dsh-ig-pill-caret{display:none}
121987
+ .dsh-ig-pill-button{padding:0 7px 0 6px}
121988
+ }
121884
121989
  .dsh-ig-pill-menu{position:fixed;z-index:1000;min-width:264px;max-width:min(320px,calc(100vw - 24px));padding:6px;border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;background:var(--dsw-alias-bg-layer-3,#fff);box-shadow:0 12px 32px rgba(0,0,0,.16),0 2px 8px rgba(0,0,0,.08);max-height:min(320px,calc(100vh - 48px));overflow-y:auto}
121885
121990
  .dsh-ig-pill-menu-title{padding:6px 8px 4px;font-size:11px;font-weight:600;color:var(--dsw-alias-label-tertiary,#6b7280)}
121886
121991
  .dsh-ig-pill-option{display:flex;width:100%;align-items:center;gap:9px;padding:7px 8px;border:0;border-radius:8px;background:none;font:inherit;color:inherit;text-align:left;cursor:pointer}
@@ -121900,7 +122005,7 @@ img.ProseMirror-separator {
121900
122005
  `;
121901
122006
  //#endregion
121902
122007
  //#region lib/types/client/index.js
121903
- console.info(`[dsh-image-gen] canvas bundle 2026-09-14T07:49:16.664Z`);
122008
+ console.info(`[dsh-image-gen] canvas bundle 2026-09-14T15:26:26.831Z`);
121904
122009
  /** Right-sidebar tab-type registration id (DSH 0.1.5 `sidebarRightTabs`). */
121905
122010
  const SIDEBAR_STUDIO_TAB_ID = "dsh-image-gen/studio";
121906
122011
  /** The tab kind: a page type opened by kind, recognizing no resource address. */
@@ -121939,8 +122044,8 @@ img.ProseMirror-separator {
121939
122044
  subLoginOk: "登录成功",
121940
122045
  subModelLabel: "订阅模型",
121941
122046
  subModelHint: "由订阅通道固定,不可更改。",
121942
- subEditUnsupported: "订阅通道暂不支持图生图(编辑图片),仅支持文字生图。",
121943
- subDefaultHint: "订阅 Provider 只能生成,不能编辑图片;需要编辑时请切换到 API Key Provider。",
122047
+ subEditCapability: "订阅生图 · 图生图:支持。对话 edit_image、Studio 图生图与多模型对比均可上传参考图(最多 5 张)。",
122048
+ subDefaultHint: "订阅 Provider 已支持文字生图与图生图;图生图使用各订阅渠道默认参数。",
121944
122049
  apiKeyLabel: "{provider} API Key",
121945
122050
  apiKeyPlaceholder: "留空即可保留已配置的 Key",
121946
122051
  apiKeyHint: "安全保存为 {key};页面不会读回明文。",
@@ -122068,8 +122173,8 @@ img.ProseMirror-separator {
122068
122173
  subLoginOk: "Signed in",
122069
122174
  subModelLabel: "Subscription model",
122070
122175
  subModelHint: "Fixed by the subscription channel; not changeable.",
122071
- subEditUnsupported: "The subscription channel does not support image editing yet; text-to-image only.",
122072
- subDefaultHint: "Subscription providers can only generate; switch to an API-key provider for editing.",
122176
+ subEditCapability: "Subscription image editing is now supported: edit_image in chats, Studio and multi-model compare all accept reference images (up to 5).",
122177
+ subDefaultHint: "Subscription providers support both text-to-image and image editing; edits use each channel's default parameters.",
122073
122178
  apiKeyLabel: "{provider} API Key",
122074
122179
  apiKeyPlaceholder: "Leave empty to keep configured key",
122075
122180
  apiKeyHint: "Securely saved as {key}; never read back in plaintext.",
@@ -122597,7 +122702,10 @@ img.ProseMirror-separator {
122597
122702
  label: () => {
122598
122703
  return (locale?.getSnapshot?.()?.active)?.startsWith("en") ? "Gallery" : "画廊";
122599
122704
  },
122600
- inject: () => ({ locale })
122705
+ inject: () => ({
122706
+ locale,
122707
+ credentialEvents
122708
+ })
122601
122709
  }, GalleryViewTab));
122602
122710
  ctx.inject(["sidebarRightTabs"], (owner) => {
122603
122711
  const sidebarTabs = owner.get("sidebarRightTabs");
@@ -122620,6 +122728,7 @@ img.ProseMirror-separator {
122620
122728
  key: SIDEBAR_STUDIO_TAB_ID,
122621
122729
  inject: () => ({
122622
122730
  locale,
122731
+ credentialEvents,
122623
122732
  inSidebar: true,
122624
122733
  defaultTab: "studio",
122625
122734
  initialCanvasSurface: "infinite"
@@ -123871,8 +123980,8 @@ img.ProseMirror-separator {
123871
123980
  (0, react_jsx_runtime.jsx)("div", {
123872
123981
  className: "dsh-ig-field",
123873
123982
  children: (0, react_jsx_runtime.jsx)("span", {
123874
- className: "dsh-ig-label",
123875
- children: t("subEditUnsupported")
123983
+ className: "dsh-ig-hint",
123984
+ children: t("subEditCapability")
123876
123985
  })
123877
123986
  }),
123878
123987
  (0, react_jsx_runtime.jsxs)("div", {