@eddyskywalker/dsh-chatgpt-subscription 0.1.18 → 0.1.19

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
@@ -313,7 +313,6 @@ window.__ModuleLoader__.load({
313
313
  const apiRef = (0, react.useRef)(new SubscriptionApi());
314
314
  const eventSourceRef = (0, react.useRef)(null);
315
315
  const [status, setStatus] = (0, react.useState)(null);
316
- const [modelCatalog, setModelCatalog] = (0, react.useState)(null);
317
316
  const [busy, setBusy] = (0, react.useState)(null);
318
317
  const [error, setError] = (0, react.useState)(null);
319
318
  const [authUrl, setAuthUrl] = (0, react.useState)(null);
@@ -323,12 +322,11 @@ window.__ModuleLoader__.load({
323
322
  const load = (0, react.useCallback)(async (quiet = false) => {
324
323
  if (!quiet) setError(null);
325
324
  try {
326
- const [next, models] = await Promise.all([apiRef.current.status(), apiRef.current.models()]);
325
+ const next = await apiRef.current.status();
327
326
  setStatus(next);
328
- setModelCatalog(models);
329
327
  if (next.error !== void 0) setError(next.error.message);
330
328
  } catch (cause) {
331
- if (!quiet) setError(messageOf(cause));
329
+ if (!quiet) setError(messageOf$1(cause));
332
330
  }
333
331
  }, []);
334
332
  (0, react.useEffect)(() => {
@@ -388,7 +386,7 @@ window.__ModuleLoader__.load({
388
386
  } catch (cause) {
389
387
  popup?.close();
390
388
  setBusy(null);
391
- setError(messageOf(cause));
389
+ setError(messageOf$1(cause));
392
390
  }
393
391
  };
394
392
  const cancelLogin = async () => {
@@ -402,7 +400,7 @@ window.__ModuleLoader__.load({
402
400
  setAuthUrl(null);
403
401
  await load();
404
402
  } catch (cause) {
405
- setError(messageOf(cause));
403
+ setError(messageOf$1(cause));
406
404
  } finally {
407
405
  setBusy(null);
408
406
  }
@@ -433,7 +431,7 @@ window.__ModuleLoader__.load({
433
431
  });
434
432
  const updateContextWindow = async (model) => {
435
433
  const current = status?.preferences.contextWindowOverrides[model] ?? resolveCodexCatalogEntry(model).contextWindow;
436
- const parsed = parseCapacity(contextDrafts[model] ?? String(current));
434
+ const parsed = parseCapacity$1(contextDrafts[model] ?? String(current));
437
435
  if (parsed === null) {
438
436
  setError(t("contextWindowInvalid"));
439
437
  return;
@@ -458,7 +456,7 @@ window.__ModuleLoader__.load({
458
456
  try {
459
457
  await task();
460
458
  } catch (cause) {
461
- setError(messageOf(cause));
459
+ setError(messageOf$1(cause));
462
460
  } finally {
463
461
  setBusy(null);
464
462
  }
@@ -614,147 +612,6 @@ window.__ModuleLoader__.load({
614
612
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("searchProviderCodex") })] })]
615
613
  })]
616
614
  }),
617
- (() => {
618
- const selectedProvider = modelCatalog?.providers.find((provider) => provider.id === status?.preferences.subagentProvider) ?? modelCatalog?.providers[0];
619
- const selectedModel = selectedProvider?.models.find((model) => model.id === status?.preferences.subagentModel) ?? selectedProvider?.models[0];
620
- const reasoning = selectedModel?.reasoning;
621
- const selectedEffort = status?.preferences.subagentReasoningEffort ?? reasoning?.defaultEffort ?? reasoning?.efforts[0]?.id ?? "";
622
- const savedContext = status?.preferences.subagentContextWindow ?? selectedModel?.contextWindow;
623
- const contextDraft = contextDrafts.subagent;
624
- const parsedContextValue = contextDraft === void 0 ? savedContext ?? null : parsePositiveCapacity(contextDraft);
625
- const parsedContext = parsedContextValue !== null && (selectedModel?.maxContextWindow === void 0 || parsedContextValue <= selectedModel.maxContextWindow) ? parsedContextValue : null;
626
- const contextDirty = contextDraft !== void 0 && parsedContext !== savedContext;
627
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
628
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
629
- className: "dsh-codex-pref-row",
630
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("subagentProvider") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
631
- className: "dsh-codex-muted",
632
- children: t("subagentProviderHint")
633
- })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
634
- className: "dsh-codex-select",
635
- "aria-label": t("subagentProvider"),
636
- value: selectedProvider?.id ?? "",
637
- disabled: busy !== null || selectedProvider === void 0,
638
- onChange: (event) => {
639
- const provider = modelCatalog?.providers.find((entry) => entry.id === event.currentTarget.value);
640
- const model = provider?.models[0];
641
- if (provider === void 0 || model === void 0) return;
642
- const effort = model.reasoning?.defaultEffort ?? model.reasoning?.efforts[0]?.id ?? null;
643
- updatePreferences({
644
- subagentProvider: provider.id,
645
- subagentModel: model.id,
646
- subagentReasoningEffort: effort,
647
- subagentContextWindow: model.contextWindow ?? 1
648
- });
649
- setContextDrafts((drafts) => ({
650
- ...drafts,
651
- subagent: formatCapacity(model.contextWindow ?? 1)
652
- }));
653
- },
654
- children: modelCatalog?.providers.map((provider) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
655
- value: provider.id,
656
- children: provider.name
657
- }, provider.id))
658
- })]
659
- }),
660
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
661
- className: "dsh-codex-pref-row",
662
- 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", {
663
- className: "dsh-codex-muted",
664
- children: t("subagentModelHint")
665
- })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
666
- className: "dsh-codex-select",
667
- "aria-label": t("subagentModel"),
668
- value: selectedModel?.id ?? "",
669
- disabled: busy !== null || selectedModel === void 0,
670
- onChange: (event) => {
671
- const model = selectedProvider?.models.find((entry) => entry.id === event.currentTarget.value);
672
- if (selectedProvider === void 0 || model === void 0) return;
673
- const effort = model.reasoning?.defaultEffort ?? model.reasoning?.efforts[0]?.id ?? null;
674
- updatePreferences({
675
- subagentProvider: selectedProvider.id,
676
- subagentModel: model.id,
677
- subagentReasoningEffort: effort,
678
- subagentContextWindow: model.contextWindow ?? 1
679
- });
680
- setContextDrafts((drafts) => ({
681
- ...drafts,
682
- subagent: formatCapacity(model.contextWindow ?? 1)
683
- }));
684
- },
685
- children: selectedProvider?.models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
686
- value: model.id,
687
- children: model.name
688
- }, model.id))
689
- })]
690
- }),
691
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
692
- className: "dsh-codex-pref-row",
693
- 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", {
694
- className: "dsh-codex-muted",
695
- children: t("subagentReasoningEffortHint")
696
- })] }), reasoning !== void 0 && reasoning.efforts.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
697
- className: "dsh-codex-select",
698
- "aria-label": t("subagentReasoningEffort"),
699
- value: selectedEffort,
700
- disabled: busy !== null,
701
- onChange: (event) => void updatePreferences({ subagentReasoningEffort: event.currentTarget.value }),
702
- children: reasoning.efforts.map((effort) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
703
- value: effort.id,
704
- children: effort.name
705
- }, effort.id))
706
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
707
- className: "dsh-codex-muted",
708
- children: t("providerDefault")
709
- })]
710
- }),
711
- selectedModel?.contextWindow !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
712
- className: "dsh-codex-context-settings",
713
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: [
714
- selectedModel.name,
715
- " · ",
716
- t("contextWindow")
717
- ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
718
- className: "dsh-codex-muted",
719
- children: t("selectedModelContextHint")
720
- })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
721
- className: "dsh-codex-context-row",
722
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
723
- htmlFor: "dsh-subagent-context",
724
- children: t("effectiveContextWindow")
725
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
726
- className: "dsh-codex-capacity-control",
727
- children: [
728
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
729
- id: "dsh-subagent-context",
730
- type: "text",
731
- inputMode: "numeric",
732
- value: contextDraft ?? formatCapacity(savedContext ?? selectedModel.contextWindow),
733
- disabled: busy !== null,
734
- onChange: (event) => {
735
- const value = event.currentTarget.value;
736
- setContextDrafts((drafts) => ({
737
- ...drafts,
738
- subagent: value
739
- }));
740
- }
741
- }),
742
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("tokens") }),
743
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
744
- className: "dsh-codex-context-save",
745
- type: "button",
746
- disabled: busy !== null || !contextDirty || parsedContext === null,
747
- onClick: () => {
748
- if (parsedContext !== null) updatePreferences({ subagentContextWindow: parsedContext });
749
- },
750
- children: t("save")
751
- })
752
- ]
753
- })]
754
- })]
755
- }) : null
756
- ] });
757
- })(),
758
615
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
759
616
  className: "dsh-codex-context-settings",
760
617
  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", {
@@ -764,7 +621,7 @@ window.__ModuleLoader__.load({
764
621
  const entry = resolveCodexCatalogEntry(model);
765
622
  const fallback = status?.preferences.contextWindowOverrides[model] ?? entry.contextWindow;
766
623
  const draft = contextDrafts[model];
767
- const parsedDraft = draft === void 0 ? fallback : parseCapacity(draft);
624
+ const parsedDraft = draft === void 0 ? fallback : parseCapacity$1(draft);
768
625
  const dirty = draft !== void 0 && parsedDraft !== fallback;
769
626
  const inputId = `dsh-codex-context-${model}`;
770
627
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -779,7 +636,7 @@ window.__ModuleLoader__.load({
779
636
  id: inputId,
780
637
  type: "text",
781
638
  inputMode: "numeric",
782
- value: draft ?? formatCapacity(fallback),
639
+ value: draft ?? formatCapacity$1(fallback),
783
640
  disabled: busy !== null,
784
641
  "aria-label": entry.name + " " + t("contextWindow"),
785
642
  onChange: (event) => {
@@ -1008,11 +865,11 @@ window.__ModuleLoader__.load({
1008
865
  const parsed = Number(matched[1]) * multiplier;
1009
866
  return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
1010
867
  }
1011
- function parseCapacity(value) {
868
+ function parseCapacity$1(value) {
1012
869
  const parsed = parsePositiveCapacity(value);
1013
870
  return parsed !== null && parsed <= 1e6 ? parsed : null;
1014
871
  }
1015
- function formatCapacity(value) {
872
+ function formatCapacity$1(value) {
1016
873
  if (value % 1e3 === 0) return `${value / 1e3}K`;
1017
874
  return String(value);
1018
875
  }
@@ -1042,10 +899,320 @@ window.__ModuleLoader__.load({
1042
899
  const [amount, unit] = abs >= 864e5 ? [Math.round(diff / 864e5), "day"] : abs >= 36e5 ? [Math.round(diff / 36e5), "hour"] : [Math.round(diff / 6e4), "minute"];
1043
900
  return `${absolute} (${new Intl.RelativeTimeFormat(void 0, { numeric: "auto" }).format(amount, unit)})`;
1044
901
  }
1045
- function messageOf(error) {
902
+ function messageOf$1(error) {
1046
903
  return error instanceof Error ? error.message : String(error);
1047
904
  }
1048
905
  //#endregion
906
+ //#region src/client/SubagentSettingsSection.tsx
907
+ function SubagentSettingsSection({ t }) {
908
+ const apiRef = (0, react.useRef)(new SubscriptionApi());
909
+ const [preferences, setPreferences] = (0, react.useState)(null);
910
+ const [catalog, setCatalog] = (0, react.useState)(null);
911
+ const [busy, setBusy] = (0, react.useState)(false);
912
+ const [error, setError] = (0, react.useState)(null);
913
+ const [contextDraft, setContextDraft] = (0, react.useState)(null);
914
+ const [depthDraft, setDepthDraft] = (0, react.useState)(null);
915
+ const [agentsDraft, setAgentsDraft] = (0, react.useState)(null);
916
+ const load = (0, react.useCallback)(async () => {
917
+ setError(null);
918
+ try {
919
+ const [status, models] = await Promise.all([apiRef.current.status(), apiRef.current.models()]);
920
+ setPreferences(status.preferences);
921
+ setCatalog(models);
922
+ } catch (cause) {
923
+ setError(messageOf(cause));
924
+ }
925
+ }, []);
926
+ (0, react.useEffect)(() => {
927
+ load();
928
+ }, [load]);
929
+ const update = async (patch) => {
930
+ setBusy(true);
931
+ setError(null);
932
+ try {
933
+ setPreferences(await apiRef.current.updatePreferences(patch));
934
+ } catch (cause) {
935
+ setError(messageOf(cause));
936
+ } finally {
937
+ setBusy(false);
938
+ }
939
+ };
940
+ const selectedProvider = catalog?.providers.find((provider) => provider.id === preferences?.subagentProvider) ?? catalog?.providers[0];
941
+ const selectedModel = selectedProvider?.models.find((model) => model.id === preferences?.subagentModel) ?? selectedProvider?.models[0];
942
+ const reasoning = selectedModel?.reasoning;
943
+ const selectedEffort = preferences?.subagentReasoningEffort ?? reasoning?.defaultEffort ?? reasoning?.efforts[0]?.id ?? "";
944
+ const savedContext = preferences?.subagentContextWindow ?? selectedModel?.contextWindow ?? 1;
945
+ const parsedContext = parseCapacity(contextDraft ?? String(savedContext));
946
+ const contextValid = parsedContext !== null && (selectedModel?.maxContextWindow === void 0 || parsedContext <= selectedModel.maxContextWindow);
947
+ const parsedDepthValue = parseNonNegativeInteger(depthDraft ?? String(preferences?.subagentMaxDepth ?? 0));
948
+ const parsedDepth = parsedDepthValue !== null && parsedDepthValue <= 3 ? parsedDepthValue : null;
949
+ const parsedAgents = parsePositiveInteger(agentsDraft ?? String(preferences?.subagentMaxAgents ?? 1));
950
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
951
+ className: "dsh-codex-page",
952
+ "aria-labelledby": "dsh-subagent-title",
953
+ children: [
954
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
955
+ id: "dsh-subagent-title",
956
+ className: "dsh-codex-title",
957
+ children: t("subagentSettingsTitle")
958
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
959
+ className: "dsh-codex-intro",
960
+ children: t("subagentSettingsIntro")
961
+ })] }),
962
+ error !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
963
+ className: "dsh-codex-errorbar",
964
+ role: "alert",
965
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: error }), preferences === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
966
+ className: "dsh-codex-button",
967
+ type: "button",
968
+ onClick: () => void load(),
969
+ children: t("retry")
970
+ }) : null]
971
+ }) : null,
972
+ preferences === null || catalog === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
973
+ className: "dsh-codex-skeleton",
974
+ role: "status",
975
+ "aria-label": t("loading"),
976
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {})]
977
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
978
+ className: "dsh-codex-group",
979
+ children: [
980
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
981
+ className: "dsh-codex-grouphead",
982
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("subagentModelGroup") })
983
+ }),
984
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
985
+ className: "dsh-codex-pref-row",
986
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("subagentProvider") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
987
+ className: "dsh-codex-muted",
988
+ children: t("subagentProviderHint")
989
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
990
+ className: "dsh-codex-select",
991
+ "aria-label": t("subagentProvider"),
992
+ value: selectedProvider?.id ?? "",
993
+ disabled: busy || selectedProvider === void 0,
994
+ onChange: (event) => {
995
+ const provider = catalog.providers.find((entry) => entry.id === event.currentTarget.value);
996
+ const model = provider?.models[0];
997
+ if (provider === void 0 || model === void 0) return;
998
+ const effort = model.reasoning?.defaultEffort ?? model.reasoning?.efforts[0]?.id ?? null;
999
+ setContextDraft(null);
1000
+ update({
1001
+ subagentProvider: provider.id,
1002
+ subagentModel: model.id,
1003
+ subagentReasoningEffort: effort,
1004
+ subagentContextWindow: model.contextWindow ?? 1
1005
+ });
1006
+ },
1007
+ children: catalog.providers.map((provider) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1008
+ value: provider.id,
1009
+ children: provider.name
1010
+ }, provider.id))
1011
+ })]
1012
+ }),
1013
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1014
+ className: "dsh-codex-pref-row",
1015
+ 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", {
1016
+ className: "dsh-codex-muted",
1017
+ children: t("subagentModelHint")
1018
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
1019
+ className: "dsh-codex-select",
1020
+ "aria-label": t("subagentModel"),
1021
+ value: selectedModel?.id ?? "",
1022
+ disabled: busy || selectedModel === void 0,
1023
+ onChange: (event) => {
1024
+ const model = selectedProvider?.models.find((entry) => entry.id === event.currentTarget.value);
1025
+ if (selectedProvider === void 0 || model === void 0) return;
1026
+ const effort = model.reasoning?.defaultEffort ?? model.reasoning?.efforts[0]?.id ?? null;
1027
+ setContextDraft(null);
1028
+ update({
1029
+ subagentProvider: selectedProvider.id,
1030
+ subagentModel: model.id,
1031
+ subagentReasoningEffort: effort,
1032
+ subagentContextWindow: model.contextWindow ?? 1
1033
+ });
1034
+ },
1035
+ children: selectedProvider?.models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1036
+ value: model.id,
1037
+ children: model.name
1038
+ }, model.id))
1039
+ })]
1040
+ }),
1041
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1042
+ className: "dsh-codex-pref-row",
1043
+ 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", {
1044
+ className: "dsh-codex-muted",
1045
+ children: t("subagentReasoningEffortHint")
1046
+ })] }), reasoning !== void 0 && reasoning.efforts.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
1047
+ className: "dsh-codex-select",
1048
+ "aria-label": t("subagentReasoningEffort"),
1049
+ value: selectedEffort,
1050
+ disabled: busy,
1051
+ onChange: (event) => void update({ subagentReasoningEffort: event.currentTarget.value }),
1052
+ children: reasoning.efforts.map((effort) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1053
+ value: effort.id,
1054
+ children: effort.name
1055
+ }, effort.id))
1056
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1057
+ className: "dsh-codex-muted",
1058
+ children: t("providerDefault")
1059
+ })]
1060
+ }),
1061
+ selectedModel?.contextWindow !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1062
+ className: "dsh-codex-context-settings",
1063
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("effectiveContextWindow") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1064
+ className: "dsh-codex-muted",
1065
+ children: t("selectedModelContextHint")
1066
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1067
+ className: "dsh-codex-context-row",
1068
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
1069
+ htmlFor: "dsh-subagent-context",
1070
+ children: selectedModel.name
1071
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1072
+ className: "dsh-codex-capacity-control",
1073
+ children: [
1074
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1075
+ id: "dsh-subagent-context",
1076
+ type: "text",
1077
+ inputMode: "numeric",
1078
+ value: contextDraft ?? formatCapacity(savedContext),
1079
+ disabled: busy,
1080
+ onChange: (event) => setContextDraft(event.currentTarget.value)
1081
+ }),
1082
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("tokens") }),
1083
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1084
+ className: "dsh-codex-context-save",
1085
+ type: "button",
1086
+ disabled: busy || contextDraft === null || !contextValid || parsedContext === savedContext,
1087
+ onClick: () => {
1088
+ if (parsedContext === null) return;
1089
+ update({ subagentContextWindow: parsedContext }).then(() => setContextDraft(null));
1090
+ },
1091
+ children: t("save")
1092
+ })
1093
+ ]
1094
+ })]
1095
+ })]
1096
+ }) : null
1097
+ ]
1098
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1099
+ className: "dsh-codex-group",
1100
+ children: [
1101
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1102
+ className: "dsh-codex-grouphead",
1103
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("subagentLimitsGroup") })
1104
+ }),
1105
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1106
+ className: "dsh-codex-context-settings",
1107
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("subagentMaxDepth") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1108
+ className: "dsh-codex-muted",
1109
+ children: t("subagentMaxDepthHint")
1110
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1111
+ className: "dsh-codex-context-row",
1112
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
1113
+ htmlFor: "dsh-subagent-depth",
1114
+ children: t("subagentMaxDepth")
1115
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1116
+ className: "dsh-codex-capacity-control",
1117
+ children: [
1118
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1119
+ id: "dsh-subagent-depth",
1120
+ type: "number",
1121
+ min: "0",
1122
+ max: 3,
1123
+ step: "1",
1124
+ inputMode: "numeric",
1125
+ value: depthDraft ?? String(preferences.subagentMaxDepth),
1126
+ disabled: busy,
1127
+ onChange: (event) => setDepthDraft(event.currentTarget.value)
1128
+ }),
1129
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("levels") }),
1130
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1131
+ className: "dsh-codex-context-save",
1132
+ type: "button",
1133
+ disabled: busy || depthDraft === null || parsedDepth === null || parsedDepth === preferences.subagentMaxDepth,
1134
+ onClick: () => {
1135
+ if (parsedDepth === null) return;
1136
+ update({ subagentMaxDepth: parsedDepth }).then(() => setDepthDraft(null));
1137
+ },
1138
+ children: t("save")
1139
+ })
1140
+ ]
1141
+ })]
1142
+ })]
1143
+ }),
1144
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1145
+ className: "dsh-codex-context-settings",
1146
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("subagentMaxAgents") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1147
+ className: "dsh-codex-muted",
1148
+ children: t("subagentMaxAgentsHint")
1149
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1150
+ className: "dsh-codex-context-row",
1151
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
1152
+ htmlFor: "dsh-subagent-agents",
1153
+ children: t("subagentMaxAgents")
1154
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1155
+ className: "dsh-codex-capacity-control",
1156
+ children: [
1157
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1158
+ id: "dsh-subagent-agents",
1159
+ type: "number",
1160
+ min: "1",
1161
+ step: "1",
1162
+ inputMode: "numeric",
1163
+ value: agentsDraft ?? String(preferences.subagentMaxAgents),
1164
+ disabled: busy,
1165
+ onChange: (event) => setAgentsDraft(event.currentTarget.value)
1166
+ }),
1167
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("agents") }),
1168
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1169
+ className: "dsh-codex-context-save",
1170
+ type: "button",
1171
+ disabled: busy || agentsDraft === null || parsedAgents === null || parsedAgents === preferences.subagentMaxAgents,
1172
+ onClick: () => {
1173
+ if (parsedAgents === null) return;
1174
+ update({ subagentMaxAgents: parsedAgents }).then(() => setAgentsDraft(null));
1175
+ },
1176
+ children: t("save")
1177
+ })
1178
+ ]
1179
+ })]
1180
+ })]
1181
+ }),
1182
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1183
+ className: "dsh-codex-notice",
1184
+ children: t("subagentLimitsNotice")
1185
+ })
1186
+ ]
1187
+ })] })
1188
+ ]
1189
+ });
1190
+ }
1191
+ function parseNonNegativeInteger(value) {
1192
+ if (!/^\d+$/.test(value.trim())) return null;
1193
+ const parsed = Number(value.trim());
1194
+ return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null;
1195
+ }
1196
+ function parsePositiveInteger(value) {
1197
+ const parsed = parseNonNegativeInteger(value);
1198
+ return parsed !== null && parsed >= 1 ? parsed : null;
1199
+ }
1200
+ function parseCapacity(value) {
1201
+ const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
1202
+ if (matched === null) return null;
1203
+ const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
1204
+ const parsed = Number(matched[1]) * multiplier;
1205
+ return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
1206
+ }
1207
+ function formatCapacity(value) {
1208
+ if (value % 1e6 === 0) return `${value / 1e6}M`;
1209
+ if (value % 1e3 === 0) return `${value / 1e3}K`;
1210
+ return String(value);
1211
+ }
1212
+ function messageOf(cause) {
1213
+ return cause instanceof Error ? cause.message : String(cause);
1214
+ }
1215
+ //#endregion
1049
1216
  //#region src/client/locales.ts
1050
1217
  const NS = "dsh-chatgpt-subscription";
1051
1218
  const dictionaries = {
@@ -1088,6 +1255,18 @@ window.__ModuleLoader__.load({
1088
1255
  latency: "最近延迟",
1089
1256
  models: "可用模型",
1090
1257
  enhancements: "增强功能",
1258
+ subagentSettingsNav: "子代理",
1259
+ subagentSettingsTitle: "子代理设置",
1260
+ subagentSettingsIntro: "全局配置 DSH 内置子代理。模型、思考深度、上下文预算和运行限制适用于所有父 Agent,不受父 Agent 当前 Provider 或模型影响。",
1261
+ subagentModelGroup: "模型与上下文",
1262
+ subagentLimitsGroup: "运行限制",
1263
+ subagentMaxDepth: "最大嵌套深度",
1264
+ subagentMaxDepthHint: "限制从顶层 Agent 开始的子代理层级(0–3);0 禁止创建子代理,1 仅允许直接子代理。",
1265
+ subagentMaxAgents: "子代理数量上限",
1266
+ subagentMaxAgentsHint: "限制每个父 Agent 子树中同时处于活动或启动中的子代理总数。",
1267
+ subagentLimitsNotice: "限制会立即应用于新的委派,不会中断已经运行的子代理。数量上限统计当前父 Agent 的全部活动后代。",
1268
+ levels: "层",
1269
+ agents: "个",
1091
1270
  searchProvider: "搜索来源",
1092
1271
  searchProviderHint: "选择 DSH Web 搜索工具使用默认来源,或改用当前 ChatGPT 订阅的 Codex 搜索来源。",
1093
1272
  searchProviderDsh: "DSH 默认",
@@ -1095,7 +1274,7 @@ window.__ModuleLoader__.load({
1095
1274
  subagentProvider: "子代理 Provider",
1096
1275
  subagentProviderHint: "选择 DSH 当前已接入且可用的模型提供方。",
1097
1276
  subagentModel: "子代理模型",
1098
- subagentModelHint: "仅当父 Agent 使用 Codex 订阅模型时生效;模型可来自任意已接入 Provider。",
1277
+ subagentModelHint: "全局应用于所有 DSH 内置子代理;模型可来自任意已接入 Provider。",
1099
1278
  subagentReasoningEffort: "子代理思考深度",
1100
1279
  subagentReasoningEffortHint: "选项来自所选模型实际公开的 reasoning effort 能力。",
1101
1280
  providerDefault: "使用 Provider 默认值",
@@ -1193,6 +1372,18 @@ window.__ModuleLoader__.load({
1193
1372
  latency: "Last latency",
1194
1373
  models: "Available models",
1195
1374
  enhancements: "Enhancements",
1375
+ subagentSettingsNav: "Subagents",
1376
+ subagentSettingsTitle: "Subagent settings",
1377
+ subagentSettingsIntro: "Configure DSH built-in subagents globally. Model, reasoning effort, context budget, and runtime limits apply to every parent Agent regardless of its current provider or model.",
1378
+ subagentModelGroup: "Model and context",
1379
+ subagentLimitsGroup: "Runtime limits",
1380
+ subagentMaxDepth: "Maximum nesting depth",
1381
+ subagentMaxDepthHint: "Limit child levels below a top-level Agent (0–3). Zero disables subagents; one allows direct children only.",
1382
+ subagentMaxAgents: "Maximum subagents",
1383
+ subagentMaxAgentsHint: "Limit the total number of active or starting subagents in each parent Agent tree.",
1384
+ subagentLimitsNotice: "Limits apply immediately to new delegations and do not interrupt subagents already running. The count covers all active descendants of the current parent Agent.",
1385
+ levels: "levels",
1386
+ agents: "agents",
1196
1387
  searchProvider: "Search provider",
1197
1388
  searchProviderHint: "Choose whether DSH web search uses its default provider or the Codex search source from this ChatGPT subscription.",
1198
1389
  searchProviderDsh: "DSH default",
@@ -1200,7 +1391,7 @@ window.__ModuleLoader__.load({
1200
1391
  subagentProvider: "Subagent provider",
1201
1392
  subagentProviderHint: "Choose from providers currently connected and available in DSH.",
1202
1393
  subagentModel: "Subagent model",
1203
- subagentModelHint: "Applies only when the parent uses Codex; the selected child model may come from any connected provider.",
1394
+ subagentModelHint: "Applies globally to all built-in DSH subagents; the selected child model may come from any connected provider.",
1204
1395
  subagentReasoningEffort: "Subagent reasoning effort",
1205
1396
  subagentReasoningEffortHint: "Options come from the reasoning-effort capabilities exposed by the selected model.",
1206
1397
  providerDefault: "Use provider default",
@@ -1304,6 +1495,7 @@ window.__ModuleLoader__.load({
1304
1495
  .dsh-codex-context-row{align-items:center;display:flex;font-size:12px;gap:14px;justify-content:space-between}
1305
1496
  .dsh-codex-capacity-control{align-items:center;display:flex;gap:7px}
1306
1497
  .dsh-codex-capacity-control input{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;text-align:right;width:90px}
1498
+ .dsh-codex-capacity-control input[type=number]{width:110px}
1307
1499
  .dsh-codex-capacity-control small{color:var(--dsw-alias-label-tertiary);font-size:11px;width:42px}
1308
1500
  .dsh-codex-context-save{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:7px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;font-size:12px;line-height:1;padding:8px 10px;white-space:nowrap}
1309
1501
  .dsh-codex-context-save:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
@@ -1370,11 +1562,19 @@ window.__ModuleLoader__.load({
1370
1562
  function apply(ctx) {
1371
1563
  ctx.effect(() => ctx.locale.register(NS, dictionaries), "dsh-chatgpt-subscription: dictionaries");
1372
1564
  ctx.effect(() => installStyles(), "dsh-chatgpt-subscription: styles");
1565
+ const t = ctx.locale.bind(NS);
1566
+ ctx.slots.inject("settings.section", () => ctx.slots.register({
1567
+ name: "settings.section",
1568
+ id: "subagents",
1569
+ order: 30,
1570
+ label: () => t("subagentSettingsNav"),
1571
+ locale: NS
1572
+ }, SubagentSettingsSection));
1373
1573
  ctx.slots.inject("settings.section", () => ctx.slots.register({
1374
1574
  name: "settings.section",
1375
1575
  id: "codex-subscription",
1376
1576
  order: 45,
1377
- label: "Codex 订阅",
1577
+ label: () => t("title"),
1378
1578
  locale: NS
1379
1579
  }, CodexSubscriptionSection));
1380
1580
  ctx.slots.inject("conversation.input.right", () => ctx.slots.register({