dsh-subscriptions 0.2.2 → 0.2.3

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/lib/client.js CHANGED
@@ -56,7 +56,7 @@ const en = {
56
56
  accountsCatalogUnavailable: "Model discovery is currently unavailable. Saved model selections are preserved.",
57
57
  modelsPartialSave: "Some reasoning defaults were saved. Remaining changes are still in the draft; retry to finish.",
58
58
  modelsEdit: "Edit model list",
59
- modelsHint: "Configure model visibility, default reasoning effort, context and tools here; Save changes below submits them together with the account settings. Hidden models remain usable by existing sessions; tool changes apply to new sessions.",
59
+ modelsHint: "Configure model visibility, default reasoning effort, subagent speed, context and tools here; Save changes below submits them together with the account settings. Hidden models remain usable by existing sessions; tool changes apply to new sessions.",
60
60
  modelsAutomatic: "Automatically show all models, including new models",
61
61
  modelsSelectAll: "Select all",
62
62
  modelsSelectNone: "Clear selection",
@@ -64,6 +64,8 @@ const en = {
64
64
  modelsContextBounds: "Default {default} · Maximum {max}",
65
65
  modelsContextHint: "Leave blank to follow the provider. The requested window is capped by the account’s advertised maximum; account pools use the smallest member window. This controls local history and compaction, not the API’s capacity.",
66
66
  modelsContextInvalid: "Enter a positive whole number of tokens for {model}.",
67
+ modelsSubagentSpeed: "Subagent default speed",
68
+ modelsSubagentSpeedHint: "Applies to subsequent subagent requests using this model, regardless of the parent model. Main conversations keep their own Speed setting. Fast requires model support.",
67
69
  modelsTools: "Provider tools",
68
70
  modelsToolsHint: "Changes apply only to sessions created after saving. Existing sessions keep their tools. Shared tools remain available if any supporting provider is enabled.",
69
71
  modelsImage: "Image generation",
@@ -113,6 +115,7 @@ const en = {
113
115
  usageRefresh: "Refresh",
114
116
  usageLoading: "Loading usage…",
115
117
  usageEmpty: "No usage windows reported.",
118
+ usageNoVisibleModels: "No usage windows for the models visible in the picker.",
116
119
  usageUnsupported: "This endpoint has no usage surface.",
117
120
  usageError: "Usage lookup failed: {message}",
118
121
  usageSession: "5-hour window",
@@ -211,6 +214,9 @@ const en = {
211
214
  modelDefaultsSummaryEmpty: "No model advertises reasoning levels",
212
215
  modelDefaultsFilterPlaceholder: "Filter models",
213
216
  modelDefaultsFilterEmpty: "No model matches “{query}”.",
217
+ modelDefaultsNoModels: "This provider reports no models.",
218
+ modelDefaultsNoAccount: "No connected accounts. Connect one on the provider card first.",
219
+ modelDefaultsDiscoveryFailed: "Model discovery failed or timed out. Use Refresh to try again.",
214
220
  generating: "Generating image…",
215
221
  image: "image",
216
222
  viewImage: "View image",
@@ -296,7 +302,7 @@ const zh = {
296
302
  accountsCatalogUnavailable: "暂时无法获取模型目录,已保存的模型选择会被保留。",
297
303
  modelsPartialSave: "部分推理档已保存,其余更改仍保留在草稿中,请重试完成保存。",
298
304
  modelsEdit: "编辑模型列表",
299
- modelsHint: "在此配置模型显示、默认推理档、上下文与工具,底部的「保存更改」会连同账号设置一起提交。隐藏模型不影响已有会话;工具开关对新建会话生效。",
305
+ modelsHint: "在此配置模型显示、默认推理档、子代理速度、上下文与工具,底部的「保存更改」会连同账号设置一起提交。隐藏模型不影响已有会话;工具开关对新建会话生效。",
300
306
  modelsAutomatic: "自动显示全部模型(包含以后新增的模型)",
301
307
  modelsSelectAll: "全选",
302
308
  modelsSelectNone: "清空选择",
@@ -304,6 +310,8 @@ const zh = {
304
310
  modelsContextBounds: "默认 {default} · 最大 {max}",
305
311
  modelsContextHint: "留空跟随服务商。配置值按账号返回的最大窗口限制;账号池取各成员的最小窗口。此设置控制本地历史保留和压缩时机,不会扩大 API 本身的容量。",
306
312
  modelsContextInvalid: "请为 {model} 输入正整数 token 数。",
313
+ modelsSubagentSpeed: "子代理默认速度",
314
+ modelsSubagentSpeedHint: "对使用此模型的子代理后续请求生效,与父会话模型无关。主会话仍使用自己的速度设置;快速档仅在模型支持时生效。",
307
315
  modelsTools: "Provider 工具",
308
316
  modelsToolsHint: "仅对保存后新建的会话生效,已有会话保留原工具。任一支持的服务商启用共享工具时,该工具仍会显示。",
309
317
  modelsImage: "图片生成",
@@ -353,6 +361,7 @@ const zh = {
353
361
  usageRefresh: "刷新",
354
362
  usageLoading: "用量加载中…",
355
363
  usageEmpty: "服务商未返回任何用量窗口。",
364
+ usageNoVisibleModels: "选择器中的可见模型没有任何用量窗口。",
356
365
  usageUnsupported: "该端点不提供用量查询。",
357
366
  usageError: "用量查询失败:{message}",
358
367
  usageSession: "5 小时窗口",
@@ -451,6 +460,9 @@ const zh = {
451
460
  modelDefaultsSummaryEmpty: "没有模型声明推理档",
452
461
  modelDefaultsFilterPlaceholder: "筛选模型",
453
462
  modelDefaultsFilterEmpty: "没有匹配「{query}」的模型。",
463
+ modelDefaultsNoModels: "这个服务商没有报告任何模型。",
464
+ modelDefaultsNoAccount: "还没有连接账号。请先在卡片上连接一个账号。",
465
+ modelDefaultsDiscoveryFailed: "模型列表发现失败或超时。可以点「刷新」重试。",
454
466
  generating: "正在生成图片…",
455
467
  image: "图片",
456
468
  viewImage: "查看图片",
@@ -527,6 +539,19 @@ function resetActionBlock(usage, now = Date.now()) {
527
539
  if (!usage.resetCredits.some((c) => c.id && (c.expiresAt === void 0 || c.expiresAt > now))) return "resetUseRefresh";
528
540
  }
529
541
 
542
+ //#endregion
543
+ //#region src/client/usage-window-filter.ts
544
+ /**
545
+ * Keep model-scoped Google quotas aligned with the saved model-picker selection.
546
+ * Account-wide windows and other providers are unaffected; an absent selection
547
+ * follows discovery, while an empty selection hides every model-scoped window.
548
+ */
549
+ function visibleUsageWindows(provider, windows, visibleModels) {
550
+ if (windows === void 0) return [];
551
+ if (provider !== "antigravity" || visibleModels === void 0) return windows;
552
+ return windows.filter((window$1) => !window$1.scope || visibleModels.includes(window$1.scope));
553
+ }
554
+
530
555
  //#endregion
531
556
  //#region src/client/subscriptions-rpc.ts
532
557
  /**
@@ -610,6 +635,43 @@ function mergeAccountChanges(latest, changes) {
610
635
  };
611
636
  }
612
637
 
638
+ //#endregion
639
+ //#region src/client/model-filter.ts
640
+ /** Distinguish an empty provider from a query that filtered out every row. */
641
+ function modelListState(total, matched) {
642
+ if (total === 0) return "provider-empty";
643
+ return matched === 0 ? "filter-empty" : "rows";
644
+ }
645
+ /**
646
+ * Retain saved model ids when discovery returns no rows. A temporary catalog
647
+ * failure must not hide the visibility or subagent-speed settings they edit.
648
+ */
649
+ function savedModelIds(visibleModels, subagentSpeeds) {
650
+ return [...new Set([...visibleModels ?? [], ...Object.keys(subagentSpeeds ?? {})])];
651
+ }
652
+ /**
653
+ * Use account discovery evidence to explain an empty provider. Connected
654
+ * accounts with failed discovery need a retry, not another login prompt.
655
+ */
656
+ function modelEditorNotice(accounts) {
657
+ if (accounts === void 0) return "noModels";
658
+ if (accounts.length === 0) return "noAccount";
659
+ return accounts.every((account) => account.unavailable === true) ? "discoveryFailed" : "noModels";
660
+ }
661
+ /** Locale keys for the three empty states. */
662
+ const NOTICE_KEYS = {
663
+ noAccount: "modelDefaultsNoAccount",
664
+ discoveryFailed: "modelDefaultsDiscoveryFailed",
665
+ noModels: "modelDefaultsNoModels"
666
+ };
667
+ /** Combine discovered and saved rows, filter results, and discovery evidence. */
668
+ function modelEditorState(input) {
669
+ return {
670
+ listState: modelListState(input.discovered + input.saved, input.matched),
671
+ noticeKey: NOTICE_KEYS[modelEditorNotice(input.accounts)]
672
+ };
673
+ }
674
+
613
675
  //#endregion
614
676
  //#region src/client/ProviderModelEditor.tsx
615
677
  /** Providers whose runtime honours a local context-window override. */
@@ -711,12 +773,18 @@ const ProviderModelEditor = (0, react.forwardRef)(function ProviderModelEditor$1
711
773
  ]);
712
774
  const allModels = catalog?.models ?? [];
713
775
  const known = new Set(allModels.map((model) => model.id));
714
- const missing = (draft.visibleModels ?? []).filter((id) => !known.has(id)).map((id) => ({
776
+ const missing = savedModelIds(draft.visibleModels, draft.subagentSpeeds).filter((id) => !known.has(id)).map((id) => ({
715
777
  id,
716
778
  name: id
717
779
  }));
718
780
  const models = [...allModels, ...missing].filter((model) => `${model.name} ${model.id}`.toLowerCase().includes(query.trim().toLowerCase()));
719
- const selected = new Set(draft.visibleModels ?? allModels.map((model) => model.id));
781
+ const editorState = modelEditorState({
782
+ discovered: allModels.length,
783
+ saved: missing.length,
784
+ matched: models.length,
785
+ accounts: catalog?.accounts
786
+ });
787
+ const selected = new Set(draft.visibleModels ?? [...allModels, ...missing].map((model) => model.id));
720
788
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
721
789
  style: {
722
790
  borderTop: border$2,
@@ -756,7 +824,7 @@ const ProviderModelEditor = (0, react.forwardRef)(function ProviderModelEditor$1
756
824
  children: t("modelDefaultsLoading")
757
825
  })]
758
826
  }),
759
- catalog && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("fieldset", {
827
+ !busy && catalog && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("fieldset", {
760
828
  disabled: busy || disabled,
761
829
  style: {
762
830
  border: 0,
@@ -781,7 +849,10 @@ const ProviderModelEditor = (0, react.forwardRef)(function ProviderModelEditor$1
781
849
  " ",
782
850
  t("modelsAutomatic")
783
851
  ] }),
784
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
852
+ editorState.listState === "provider-empty" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
853
+ className: "dsh-subscription-hint",
854
+ children: t(editorState.noticeKey)
855
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
785
856
  style: actions$2,
786
857
  children: [
787
858
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
@@ -808,8 +879,7 @@ const ProviderModelEditor = (0, react.forwardRef)(function ProviderModelEditor$1
808
879
  children: t("modelsSelectNone")
809
880
  })
810
881
  ]
811
- }),
812
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
882
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
813
883
  style: {
814
884
  maxHeight: 360,
815
885
  overflowY: "auto",
@@ -823,87 +893,118 @@ const ProviderModelEditor = (0, react.forwardRef)(function ProviderModelEditor$1
823
893
  display: "grid",
824
894
  gap: 8
825
895
  },
826
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
827
- style: { overflowWrap: "anywhere" },
828
- children: [
829
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
830
- type: "checkbox",
831
- checked: selected.has(model.id),
832
- onChange: (event) => {
833
- const next = new Set(selected);
834
- if (event.target.checked) next.add(model.id);
835
- else next.delete(model.id);
836
- edit({
837
- ...draft,
838
- visibleModels: [...next]
839
- });
840
- }
841
- }),
842
- " ",
843
- model.name,
844
- !known.has(model.id) && ` (${t("modelsUnavailable")})`
845
- ]
846
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
847
- style: actions$2,
848
- children: [(model.efforts?.length ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
849
- style: actions$2,
850
- children: [t("modelDefaultsTitle"), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
851
- "aria-label": `${model.name} ${t("modelDefaultsTitle")}`,
852
- value: efforts[model.id] ?? "",
853
- onChange: (event) => {
854
- setEfforts({
855
- ...efforts,
856
- [model.id]: event.target.value
857
- });
858
- setDirty(true);
859
- },
860
- children: [
861
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
862
- value: "",
863
- children: t("modelDefaultsFollowProvider")
864
- }),
865
- model.configured && !model.efforts?.some((effort) => effort.id === model.configured) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
866
- value: model.configured,
867
- disabled: true,
868
- children: [
869
- model.configured,
870
- " (",
871
- t("modelsUnavailable"),
872
- ")"
873
- ]
874
- }),
875
- model.efforts?.map((effort) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
876
- value: effort.id,
877
- children: effort.name
878
- }, effort.id))
879
- ]
880
- })]
881
- }), supportsContext(provider) && model.maxContextWindow !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
896
+ children: [
897
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
898
+ style: { overflowWrap: "anywhere" },
899
+ children: [
900
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
901
+ type: "checkbox",
902
+ checked: selected.has(model.id),
903
+ onChange: (event) => {
904
+ const next = new Set(selected);
905
+ if (event.target.checked) next.add(model.id);
906
+ else next.delete(model.id);
907
+ edit({
908
+ ...draft,
909
+ visibleModels: [...next]
910
+ });
911
+ }
912
+ }),
913
+ " ",
914
+ model.name,
915
+ !known.has(model.id) && ` (${t("modelsUnavailable")})`
916
+ ]
917
+ }),
918
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
882
919
  style: actions$2,
883
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
920
+ children: [(model.efforts?.length ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
884
921
  style: actions$2,
885
- children: [t("modelsContext"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
886
- style: { width: 140 },
887
- inputMode: "numeric",
888
- value: contexts[model.id] ?? "",
889
- "aria-label": `${model.name} ${t("modelsContext")}`,
890
- placeholder: String(model.defaultContextWindow),
922
+ children: [t("modelDefaultsTitle"), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
923
+ "aria-label": `${model.name} ${t("modelDefaultsTitle")}`,
924
+ value: efforts[model.id] ?? "",
891
925
  onChange: (event) => {
892
- setContexts({
893
- ...contexts,
926
+ setEfforts({
927
+ ...efforts,
894
928
  [model.id]: event.target.value
895
929
  });
896
930
  setDirty(true);
897
- }
931
+ },
932
+ children: [
933
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
934
+ value: "",
935
+ children: t("modelDefaultsFollowProvider")
936
+ }),
937
+ model.configured && !model.efforts?.some((effort) => effort.id === model.configured) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
938
+ value: model.configured,
939
+ disabled: true,
940
+ children: [
941
+ model.configured,
942
+ " (",
943
+ t("modelsUnavailable"),
944
+ ")"
945
+ ]
946
+ }),
947
+ model.efforts?.map((effort) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
948
+ value: effort.id,
949
+ children: effort.name
950
+ }, effort.id))
951
+ ]
898
952
  })]
899
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("modelsContextBounds", {
900
- default: model.defaultContextWindow,
901
- max: model.maxContextWindow
902
- }) })]
903
- })]
904
- })]
953
+ }), supportsContext(provider) && model.maxContextWindow !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
954
+ style: actions$2,
955
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
956
+ style: actions$2,
957
+ children: [t("modelsContext"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
958
+ style: { width: 140 },
959
+ inputMode: "numeric",
960
+ value: contexts[model.id] ?? "",
961
+ "aria-label": `${model.name} ${t("modelsContext")}`,
962
+ placeholder: String(model.defaultContextWindow),
963
+ onChange: (event) => {
964
+ setContexts({
965
+ ...contexts,
966
+ [model.id]: event.target.value
967
+ });
968
+ setDirty(true);
969
+ }
970
+ })]
971
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("modelsContextBounds", {
972
+ default: model.defaultContextWindow,
973
+ max: model.maxContextWindow
974
+ }) })]
975
+ })]
976
+ }),
977
+ provider === "codex" && (model.fastTier === true || Object.hasOwn(draft.subagentSpeeds ?? {}, model.id)) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
978
+ style: {
979
+ display: "grid",
980
+ gap: 6
981
+ },
982
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
983
+ style: actions$2,
984
+ children: [t("modelsSubagentSpeed"), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
985
+ "aria-label": `${model.name} ${t("modelsSubagentSpeed")}`,
986
+ value: Object.hasOwn(draft.subagentSpeeds ?? {}, model.id) ? draft.subagentSpeeds[model.id] : "standard",
987
+ onChange: (event) => edit({
988
+ ...draft,
989
+ subagentSpeeds: {
990
+ ...draft.subagentSpeeds,
991
+ [model.id]: event.target.value
992
+ }
993
+ }),
994
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
995
+ value: "standard",
996
+ children: t("speedStandard")
997
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
998
+ value: "fast",
999
+ disabled: !model.fastTier,
1000
+ children: [t("speedFast"), !model.fastTier && ` (${t("modelsUnavailable")})`]
1001
+ })]
1002
+ })]
1003
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("modelsSubagentSpeedHint") })]
1004
+ })
1005
+ ]
905
1006
  }, model.id)), models.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("modelDefaultsFilterEmpty", { query }) })]
906
- }),
1007
+ })] }),
907
1008
  supportsContext(provider) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("modelsContextHint") }),
908
1009
  catalog.tools.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
909
1010
  style: {
@@ -4452,6 +4553,7 @@ function SubscriptionsSection(props) {
4452
4553
  accounts.map((account) => {
4453
4554
  const usageKey = `${id}:${account.key}`;
4454
4555
  const usage = usages[usageKey];
4556
+ const shownWindows = visibleUsageWindows(id, usage?.windows, status?.visibleModels);
4455
4557
  const usageError = usageErrors[usageKey];
4456
4558
  const display = account.account ?? account.key;
4457
4559
  const sortedCredits = [...usage?.resetCredits ?? []].sort((a, b) => (a.expiresAt ?? Infinity) - (b.expiresAt ?? Infinity));
@@ -4534,7 +4636,11 @@ function SubscriptionsSection(props) {
4534
4636
  style: styles$5.statusLine,
4535
4637
  children: t("usageEmpty")
4536
4638
  }),
4537
- (usage?.windows ?? []).map((window$1, index) => {
4639
+ usage?.windows !== void 0 && usage.windows.length > 0 && shownWindows.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4640
+ style: styles$5.statusLine,
4641
+ children: t("usageNoVisibleModels")
4642
+ }),
4643
+ shownWindows.map((window$1, index) => {
4538
4644
  const percent = displayUsedPercent(window$1.usedPercent);
4539
4645
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4540
4646
  style: styles$5.usageRow,
@@ -4605,7 +4711,7 @@ function SubscriptionsSection(props) {
4605
4711
  },
4606
4712
  children: t("addAccount")
4607
4713
  }),
4608
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4714
+ !busy && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4609
4715
  type: "button",
4610
4716
  "aria-haspopup": "dialog",
4611
4717
  onClick: () => setManagedProvider({
@@ -4697,7 +4803,10 @@ function SubscriptionsSection(props) {
4697
4803
  name: managedProvider.name,
4698
4804
  rpc,
4699
4805
  t,
4700
- onClose: () => setManagedProvider(void 0)
4806
+ onClose: () => {
4807
+ setManagedProvider(void 0);
4808
+ refresh();
4809
+ }
4701
4810
  }),
4702
4811
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: ".subscriptions-reset-dialog::backdrop { background: var(--dsw-alias-bg-mask-1, #0006); backdrop-filter: var(--dsw-mask-blur, none); }" }),
4703
4812
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dialog", {
@@ -5537,22 +5646,17 @@ function VideoGenerateToolview(props) {
5537
5646
  */
5538
5647
  function createSpeedLoader(connection, models, sessionId) {
5539
5648
  return async () => {
5540
- const state = await callSubscriptionsAuth(connection.rpc, "speed", { sessionId });
5541
5649
  const directories = models();
5542
- if (directories === void 0) return {
5543
- visible: false,
5544
- tier: state.tier
5545
- };
5546
- let current;
5547
- try {
5650
+ let current = null;
5651
+ if (directories !== void 0) try {
5548
5652
  current = (await directories.directoryFor(sessionId).load()).current;
5549
5653
  } catch (error) {
5550
5654
  if (!modelSelectionUnavailable(error)) throw error;
5551
- return {
5552
- visible: false,
5553
- tier: state.tier
5554
- };
5555
5655
  }
5656
+ const state = await callSubscriptionsAuth(connection.rpc, "speed", {
5657
+ sessionId,
5658
+ ...current?.provider === "codex" ? { model: current.model } : {}
5659
+ });
5556
5660
  return {
5557
5661
  visible: current !== null && current.provider === "codex" && state.fastModels.includes(current.model),
5558
5662
  tier: state.tier