@eddyskywalker/dsh-chatgpt-subscription 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ - 设置页新增内置子代理模型与思考深度选择,新启动的 spawn/fork 子代理可统一路由到指定的 ChatGPT 订阅模型和 reasoning effort;可选深度随模型能力联动。
6
+ - 设置页新增 GPT-5.6 Sol / Terra / Luna 有效上下文窗口配置:默认 272K,可选最高 1M,并动态影响 DSH 的模型解析、压缩阈值与溢出判断。
7
+
3
8
  ## 0.1.12 - 2026-08-20
4
9
 
5
10
  - 适配 DSH `0.1.0-rc.8`:peerDependencies / devDependencies 中全部 DSH 包范围从 `^0.1.0-rc.6` 提升至 `^0.1.0-rc.8`,并重新生成 package-lock.json。已在本机 rc.8 依赖集上验证:typecheck、55 项测试与 tsdown 构建全部通过,插件代码无需改动。
package/README.md CHANGED
@@ -39,6 +39,8 @@
39
39
  **设置页**
40
40
 
41
41
  - 展示账号(脱敏 email、套餐、账号 ID 后四位)、连接状态、额度与订阅增强功能开关;
42
+ - 可选择新启动的内置子代理使用哪个 ChatGPT 订阅模型及思考深度;可选深度会随模型能力联动,该设置不改变父会话模型;
43
+ - 5.6 Sol / Terra / Luna 默认使用 272K 有效上下文,可在设置中选择最高 1M,用于 DSH 压缩与溢出判断;其他模型保持目录声明值;
42
44
  - 可访问的进度条、窄窗口/200% 缩放布局、深浅主题与 reduced-motion。
43
45
 
44
46
  ## 模型目录
@@ -108,7 +110,7 @@ npx @deepseek-ai/dsh plugin --profile web add "link:C:\absolute\path\to\dsh-chat
108
110
  3. 完成 ChatGPT 登录;
109
111
  4. 执行 **测试连接**。
110
112
 
111
- DSH 模型选择器应显示 **“Codex(ChatGPT 订阅)”**。
113
+ DSH 模型选择器应显示 **“Codex(ChatGPT 订阅)”**。在同一设置页的“增强功能”中,还可配置新子代理模型和 GPT-5.6 系列的有效上下文窗口。子代理模型设置适用于 DSH 内置的 spawn/fork 子代理(其会话标记为 `origin: subagent`);外部 ACP/Codex CLI 等 provider-managed 子代理不经过本插件路由。
112
114
 
113
115
  卸载前建议先在设置页点击 **“注销”**,它会删除当前平台的凭据和 Host 内存中的额度缓存。
114
116
 
package/lib/client.js CHANGED
@@ -175,8 +175,6 @@ window.__ModuleLoader__.load({
175
175
  const text = blocks.map((block) => block.type === "text" || block.type === "reasoning" ? block.text : "").filter(Boolean).join(" ").trim();
176
176
  return text === "" ? null : text;
177
177
  }
178
- //#endregion
179
- //#region src/shared/model-catalog.ts
180
178
  const CODEX_MODEL_CATALOG = [
181
179
  {
182
180
  id: "gpt-5.6-sol",
@@ -242,7 +240,26 @@ window.__ModuleLoader__.load({
242
240
  supportsReasoningSummary: false
243
241
  }
244
242
  ];
245
- CODEX_MODEL_CATALOG[0];
243
+ const DEFAULT_CODEX_MODEL = CODEX_MODEL_CATALOG[0];
244
+ const CONFIGURABLE_CONTEXT_MODEL_IDS = [
245
+ "gpt-5.6-sol",
246
+ "gpt-5.6-terra",
247
+ "gpt-5.6-luna"
248
+ ];
249
+ const STANDARD_REASONING_EFFORTS = [
250
+ "none",
251
+ "low",
252
+ "medium",
253
+ "high",
254
+ "xhigh"
255
+ ];
256
+ const GPT_56_REASONING_EFFORTS = [...STANDARD_REASONING_EFFORTS, "max"];
257
+ function reasoningEffortsForModel(model) {
258
+ return resolveCodexCatalogEntry(model).reasoningProfile === "gpt-5.6" ? GPT_56_REASONING_EFFORTS : STANDARD_REASONING_EFFORTS;
259
+ }
260
+ function resolveCodexCatalogEntry(model) {
261
+ return CODEX_MODEL_CATALOG.find((entry) => entry.id === model) ?? DEFAULT_CODEX_MODEL;
262
+ }
246
263
  //#endregion
247
264
  //#region src/client/api.ts
248
265
  var SubscriptionApi = class {
@@ -309,6 +326,7 @@ window.__ModuleLoader__.load({
309
326
  const [authUrl, setAuthUrl] = (0, react.useState)(null);
310
327
  const [popupBlocked, setPopupBlocked] = (0, react.useState)(false);
311
328
  const [connection, setConnection] = (0, react.useState)(null);
329
+ const [contextDrafts, setContextDrafts] = (0, react.useState)({});
312
330
  const load = (0, react.useCallback)(async (quiet = false) => {
313
331
  if (!quiet) setError(null);
314
332
  try {
@@ -419,6 +437,19 @@ window.__ModuleLoader__.load({
419
437
  preferences
420
438
  });
421
439
  });
440
+ const updateContextWindow = async (model) => {
441
+ const current = status?.preferences.contextWindowOverrides[model] ?? resolveCodexCatalogEntry(model).contextWindow;
442
+ const parsed = parseCapacity(contextDrafts[model] ?? String(current));
443
+ if (parsed === null) {
444
+ setError(t("contextWindowInvalid"));
445
+ return;
446
+ }
447
+ await updatePreferences({ contextWindowOverrides: { [model]: parsed } });
448
+ setContextDrafts((drafts) => ({
449
+ ...drafts,
450
+ [model]: String(parsed)
451
+ }));
452
+ };
422
453
  const logout = async () => run("logout", async () => {
423
454
  await apiRef.current.logout();
424
455
  eventSourceRef.current?.close();
@@ -564,38 +595,116 @@ window.__ModuleLoader__.load({
564
595
  }),
565
596
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Section, {
566
597
  title: t("enhancements"),
567
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
568
- className: "dsh-codex-pref-row",
569
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("searchProvider") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
570
- className: "dsh-codex-muted",
571
- children: t("searchProviderHint")
572
- })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
573
- className: "dsh-codex-segments",
574
- role: "radiogroup",
575
- "aria-label": t("searchProvider"),
576
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
577
- type: "radio",
578
- name: "dsh-codex-search-provider",
579
- checked: status?.preferences.searchProvider === "dsh",
598
+ children: [
599
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
600
+ className: "dsh-codex-pref-row",
601
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("searchProvider") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
602
+ className: "dsh-codex-muted",
603
+ children: t("searchProviderHint")
604
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
605
+ className: "dsh-codex-segments",
606
+ role: "radiogroup",
607
+ "aria-label": t("searchProvider"),
608
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
609
+ type: "radio",
610
+ name: "dsh-codex-search-provider",
611
+ checked: status?.preferences.searchProvider === "dsh",
612
+ disabled: busy !== null,
613
+ onChange: () => updatePreferences({ searchProvider: "dsh" })
614
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("searchProviderDsh") })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
615
+ type: "radio",
616
+ name: "dsh-codex-search-provider",
617
+ checked: status?.preferences.searchProvider === "codex",
618
+ disabled: busy !== null,
619
+ onChange: () => updatePreferences({ searchProvider: "codex" })
620
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("searchProviderCodex") })] })]
621
+ })]
622
+ }),
623
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
624
+ className: "dsh-codex-pref-row",
625
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("subagentModel") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
626
+ className: "dsh-codex-muted",
627
+ children: t("subagentModelHint")
628
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
629
+ className: "dsh-codex-select",
630
+ "aria-label": t("subagentModel"),
631
+ value: status?.preferences.subagentModel ?? CODEX_MODEL_CATALOG[0].id,
580
632
  disabled: busy !== null,
581
- onChange: () => updatePreferences({ searchProvider: "dsh" })
582
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("searchProviderDsh") })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
583
- type: "radio",
584
- name: "dsh-codex-search-provider",
585
- checked: status?.preferences.searchProvider === "codex",
633
+ onChange: (event) => {
634
+ const subagentModel = event.currentTarget.value;
635
+ const currentEffort = status?.preferences.subagentReasoningEffort ?? resolveCodexCatalogEntry(subagentModel).defaultReasoningEffort;
636
+ const supportedEfforts = reasoningEffortsForModel(subagentModel);
637
+ updatePreferences({
638
+ subagentModel,
639
+ subagentReasoningEffort: supportedEfforts.includes(currentEffort) ? currentEffort : resolveCodexCatalogEntry(subagentModel).defaultReasoningEffort
640
+ });
641
+ },
642
+ children: CODEX_MODEL_CATALOG.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
643
+ value: model.id,
644
+ children: model.name
645
+ }, model.id))
646
+ })]
647
+ }),
648
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
649
+ className: "dsh-codex-pref-row",
650
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("subagentReasoningEffort") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
651
+ className: "dsh-codex-muted",
652
+ children: t("subagentReasoningEffortHint")
653
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
654
+ className: "dsh-codex-select",
655
+ "aria-label": t("subagentReasoningEffort"),
656
+ value: status?.preferences.subagentReasoningEffort ?? "medium",
657
+ disabled: busy !== null,
658
+ onChange: (event) => void updatePreferences({
659
+ subagentModel: status?.preferences.subagentModel ?? CODEX_MODEL_CATALOG[0].id,
660
+ subagentReasoningEffort: event.currentTarget.value
661
+ }),
662
+ children: reasoningEffortsForModel(status?.preferences.subagentModel ?? CODEX_MODEL_CATALOG[0].id).map((effort) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
663
+ value: effort,
664
+ children: reasoningEffortLabel(effort, t)
665
+ }, effort))
666
+ })]
667
+ }),
668
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
669
+ className: "dsh-codex-context-settings",
670
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("contextWindows") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
671
+ className: "dsh-codex-muted",
672
+ children: t("contextWindowsHint")
673
+ })] }), CONFIGURABLE_CONTEXT_MODEL_IDS.map((model) => {
674
+ const fallback = status?.preferences.contextWindowOverrides[model] ?? resolveCodexCatalogEntry(model).contextWindow;
675
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
676
+ className: "dsh-codex-context-row",
677
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: resolveCodexCatalogEntry(model).name }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
678
+ className: "dsh-codex-capacity-control",
679
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
680
+ type: "text",
681
+ inputMode: "numeric",
682
+ value: contextDrafts[model] ?? formatCapacity(fallback),
683
+ disabled: busy !== null,
684
+ "aria-label": resolveCodexCatalogEntry(model).name + " " + t("contextWindow"),
685
+ onChange: (event) => setContextDrafts((drafts) => ({
686
+ ...drafts,
687
+ [model]: event.currentTarget.value
688
+ })),
689
+ onBlur: () => void updateContextWindow(model),
690
+ onKeyDown: (event) => {
691
+ if (event.key === "Enter") event.currentTarget.blur();
692
+ }
693
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("tokens") })]
694
+ })]
695
+ }, model);
696
+ })]
697
+ }),
698
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
699
+ className: "dsh-codex-check",
700
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
701
+ type: "checkbox",
702
+ checked: status?.preferences.quickQuotaVisible === true,
586
703
  disabled: busy !== null,
587
- onChange: () => updatePreferences({ searchProvider: "codex" })
588
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("searchProviderCodex") })] })]
589
- })]
590
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
591
- className: "dsh-codex-check",
592
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
593
- type: "checkbox",
594
- checked: status?.preferences.quickQuotaVisible === true,
595
- disabled: busy !== null,
596
- onChange: (event) => updatePreferences({ quickQuotaVisible: event.currentTarget.checked })
597
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("quickQuota") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("quickQuotaHint") })] })]
598
- })]
704
+ onChange: (event) => updatePreferences({ quickQuotaVisible: event.currentTarget.checked })
705
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("quickQuota") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("quickQuotaHint") })] })]
706
+ })
707
+ ]
599
708
  }),
600
709
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Section, {
601
710
  title: t("quota"),
@@ -777,6 +886,27 @@ window.__ModuleLoader__.load({
777
886
  unitDisplay: "long"
778
887
  }).format(value)} ${t("limitWindow")}`;
779
888
  }
889
+ function reasoningEffortLabel(effort, t) {
890
+ return t({
891
+ none: "reasoningNone",
892
+ low: "reasoningLow",
893
+ medium: "reasoningMedium",
894
+ high: "reasoningHigh",
895
+ xhigh: "reasoningXhigh",
896
+ max: "reasoningMax"
897
+ }[effort] ?? "unknown");
898
+ }
899
+ function parseCapacity(value) {
900
+ const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
901
+ if (matched === null) return null;
902
+ const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
903
+ const parsed = Number(matched[1]) * multiplier;
904
+ return Number.isSafeInteger(parsed) && parsed >= 1 && parsed <= 1e6 ? parsed : null;
905
+ }
906
+ function formatCapacity(value) {
907
+ if (value % 1e3 === 0) return `${value / 1e3}K`;
908
+ return String(value);
909
+ }
780
910
  function formatPercent(value) {
781
911
  return `${new Intl.NumberFormat(void 0, { maximumFractionDigits: 1 }).format(value)}%`;
782
912
  }
@@ -853,6 +983,21 @@ window.__ModuleLoader__.load({
853
983
  searchProviderHint: "选择 DSH Web 搜索工具使用默认来源,或改用当前 ChatGPT 订阅的 Codex 搜索来源。",
854
984
  searchProviderDsh: "DSH 默认",
855
985
  searchProviderCodex: "Codex 订阅",
986
+ subagentModel: "子代理模型",
987
+ subagentModelHint: "新启动的内置子代理使用此 ChatGPT 订阅模型;父会话的模型选择不受影响。",
988
+ subagentReasoningEffort: "子代理思考深度",
989
+ subagentReasoningEffortHint: "控制子代理请求的 reasoning effort;可选项会随所选模型变化。",
990
+ reasoningNone: "无",
991
+ reasoningLow: "低",
992
+ reasoningMedium: "中",
993
+ reasoningHigh: "高",
994
+ reasoningXhigh: "超高",
995
+ reasoningMax: "最大",
996
+ contextWindows: "GPT-5.6 上下文窗口",
997
+ contextWindowsHint: "默认 272K;可选启用最高 1M。该值用于 DSH 的压缩与溢出判断,可输入 1M、512K 等容量。",
998
+ contextWindow: "上下文窗口",
999
+ contextWindowInvalid: "上下文窗口必须是 1 到 1M 的整数,可使用 K 或 M 后缀。",
1000
+ tokens: "tokens",
856
1001
  quickQuota: "在输入框旁显示快捷用量",
857
1002
  quickQuotaHint: "仅在当前会话选中 codex-chatgpt 模型时显示。",
858
1003
  quota: "用量与限额",
@@ -936,6 +1081,21 @@ window.__ModuleLoader__.load({
936
1081
  searchProviderHint: "Choose whether DSH web search uses its default provider or the Codex search source from this ChatGPT subscription.",
937
1082
  searchProviderDsh: "DSH default",
938
1083
  searchProviderCodex: "Codex subscription",
1084
+ subagentModel: "Subagent model",
1085
+ subagentModelHint: "New built-in subagents use this ChatGPT subscription model; the parent session selection is unchanged.",
1086
+ subagentReasoningEffort: "Subagent reasoning effort",
1087
+ subagentReasoningEffortHint: "Controls reasoning effort for subagent requests. Available values follow the selected model.",
1088
+ reasoningNone: "None",
1089
+ reasoningLow: "Low",
1090
+ reasoningMedium: "Medium",
1091
+ reasoningHigh: "High",
1092
+ reasoningXhigh: "Extra high",
1093
+ reasoningMax: "Maximum",
1094
+ contextWindows: "GPT-5.6 context windows",
1095
+ contextWindowsHint: "Defaults to 272K, with an optional value up to 1M. DSH uses it for compaction and overflow detection; values such as 1M and 512K are accepted.",
1096
+ contextWindow: "Context window",
1097
+ contextWindowInvalid: "The context window must be an integer from 1 to 1M. K and M suffixes are accepted.",
1098
+ tokens: "tokens",
939
1099
  quickQuota: "Show quick usage beside the composer",
940
1100
  quickQuotaHint: "Shown only when the current session uses a codex-chatgpt model.",
941
1101
  quota: "Usage and limits",
@@ -1014,6 +1174,14 @@ window.__ModuleLoader__.load({
1014
1174
  .dsh-codex-segments input:checked+span{background:var(--dsw-alias-bg-base);box-shadow:0 1px 2px rgba(0,0,0,.08);color:var(--dsw-alias-label-primary)}
1015
1175
  .dsh-codex-segments input:focus-visible+span{outline:2px solid var(--dsw-alias-button-info-fill,#397ee8);outline-offset:2px}
1016
1176
  .dsh-codex-segments input:disabled+span{cursor:default;opacity:.5}
1177
+ .dsh-codex-select,.dsh-codex-capacity-control input{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:7px;color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;padding:7px 9px}
1178
+ .dsh-codex-select{max-width:210px;min-width:150px}
1179
+ .dsh-codex-context-settings{border-bottom:1px solid var(--dsw-alias-border-l2);display:grid;gap:10px;padding:12px 0}
1180
+ .dsh-codex-context-settings>div>strong{font-size:13px;font-weight:600}
1181
+ .dsh-codex-context-row{align-items:center;display:flex;font-size:12px;gap:14px;justify-content:space-between}
1182
+ .dsh-codex-capacity-control{align-items:center;display:flex;gap:7px}
1183
+ .dsh-codex-capacity-control input{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;text-align:right;width:90px}
1184
+ .dsh-codex-capacity-control small{color:var(--dsw-alias-label-tertiary);font-size:11px;width:42px}
1017
1185
  .dsh-codex-check{align-items:flex-start;border-bottom:1px solid var(--dsw-alias-border-l2);cursor:pointer;display:flex;gap:10px;padding:12px 0}
1018
1186
  .dsh-codex-check input{flex:none;margin-top:2px}
1019
1187
  .dsh-codex-check small{color:var(--dsw-alias-label-secondary);display:block;font-size:12px;line-height:1.45;margin-top:2px}
@@ -1052,7 +1220,7 @@ window.__ModuleLoader__.load({
1052
1220
  .dsh-codex-image-loading,.dsh-codex-image-failed{border:1px dashed var(--dsw-alias-border-l2);border-radius:8px;color:var(--dsw-alias-label-tertiary);display:inline-flex;font-size:12px;line-height:1.4;padding:18px 20px}
1053
1221
  .dsh-codex-image-failed{color:var(--dsw-alias-label-danger,#d94b4b)}
1054
1222
  @keyframes dsh-codex-pulse{0%,100%{opacity:.55}50%{opacity:1}}
1055
- @media(max-width:560px){.dsh-codex-row,.dsh-codex-pref-row,.dsh-codex-quota-fact{align-items:flex-start;flex-direction:column;gap:3px}.dsh-codex-value,.dsh-codex-quota-fact strong{text-align:left}.dsh-codex-actions{justify-content:flex-start}.dsh-codex-grouphead{align-items:flex-start;flex-direction:column;gap:0;padding:12px 0}.dsh-codex-meter-meta{align-items:flex-start;flex-direction:column;gap:2px}.dsh-codex-errorbar{align-items:flex-start;flex-direction:column}.dsh-codex-segments{width:100%}.dsh-codex-segments label{flex:1}.dsh-codex-segments span{text-align:center}.dsh-codex-image-tool{max-width:100%;margin-left:0}}
1223
+ @media(max-width:560px){.dsh-codex-row,.dsh-codex-pref-row,.dsh-codex-quota-fact{align-items:flex-start;flex-direction:column;gap:3px}.dsh-codex-value,.dsh-codex-quota-fact strong{text-align:left}.dsh-codex-actions{justify-content:flex-start}.dsh-codex-grouphead{align-items:flex-start;flex-direction:column;gap:0;padding:12px 0}.dsh-codex-meter-meta{align-items:flex-start;flex-direction:column;gap:2px}.dsh-codex-errorbar{align-items:flex-start;flex-direction:column}.dsh-codex-segments{width:100%}.dsh-codex-select{max-width:none;width:100%}.dsh-codex-context-row{align-items:flex-start;flex-direction:column;gap:5px}.dsh-codex-segments label{flex:1}.dsh-codex-segments span{text-align:center}.dsh-codex-image-tool{max-width:100%;margin-left:0}}
1056
1224
  @media(prefers-reduced-motion:reduce){.dsh-codex-meter>span{transition:none}.dsh-codex-skeleton span{animation:none}}
1057
1225
  `;
1058
1226
  function installStyles() {