Skip to content

Commit ca42235

Browse files
committed
refactor: extract backend settings helpers
1 parent 3b19047 commit ca42235

2 files changed

Lines changed: 176 additions & 137 deletions

File tree

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import type { PluginConfig } from "../types.js";
2+
import {
3+
BACKEND_DEFAULTS,
4+
BACKEND_NUMBER_OPTION_BY_KEY,
5+
BACKEND_NUMBER_OPTIONS,
6+
BACKEND_TOGGLE_OPTIONS,
7+
type BackendNumberSettingKey,
8+
type BackendNumberSettingOption,
9+
type BackendSettingFocusKey,
10+
} from "./backend-settings-schema.js";
11+
12+
export function cloneBackendPluginConfig(config: PluginConfig): PluginConfig {
13+
const fallbackChain = config.unsupportedCodexFallbackChain;
14+
return {
15+
...BACKEND_DEFAULTS,
16+
...config,
17+
unsupportedCodexFallbackChain:
18+
fallbackChain && typeof fallbackChain === "object"
19+
? { ...fallbackChain }
20+
: {},
21+
};
22+
}
23+
24+
export function backendSettingsSnapshot(
25+
config: PluginConfig,
26+
): Record<string, unknown> {
27+
const snapshot: Record<string, unknown> = {};
28+
for (const option of BACKEND_TOGGLE_OPTIONS) {
29+
snapshot[option.key] =
30+
config[option.key] ?? BACKEND_DEFAULTS[option.key] ?? false;
31+
}
32+
for (const option of BACKEND_NUMBER_OPTIONS) {
33+
snapshot[option.key] =
34+
config[option.key] ?? BACKEND_DEFAULTS[option.key] ?? option.min;
35+
}
36+
return snapshot;
37+
}
38+
39+
export function backendSettingsEqual(
40+
left: PluginConfig,
41+
right: PluginConfig,
42+
): boolean {
43+
return (
44+
JSON.stringify(backendSettingsSnapshot(left)) ===
45+
JSON.stringify(backendSettingsSnapshot(right))
46+
);
47+
}
48+
49+
export function formatBackendNumberValue(
50+
option: BackendNumberSettingOption,
51+
value: number,
52+
): string {
53+
if (option.unit === "percent") return `${Math.round(value)}%`;
54+
if (option.unit === "count") return `${Math.round(value)}`;
55+
if (value >= 60_000 && value % 60_000 === 0) {
56+
return `${Math.round(value / 60_000)}m`;
57+
}
58+
if (value >= 1_000 && value % 1_000 === 0) {
59+
return `${Math.round(value / 1_000)}s`;
60+
}
61+
return `${Math.round(value)}ms`;
62+
}
63+
64+
export function clampBackendNumber(
65+
option: BackendNumberSettingOption,
66+
value: number,
67+
): number {
68+
return Math.max(option.min, Math.min(option.max, Math.round(value)));
69+
}
70+
71+
export function buildBackendSettingsPreview(
72+
config: PluginConfig,
73+
ui: ReturnType<typeof import("../ui/runtime.js").getUiRuntimeOptions>,
74+
focus: BackendSettingFocusKey,
75+
deps: {
76+
highlightPreviewToken: (
77+
text: string,
78+
ui: ReturnType<typeof import("../ui/runtime.js").getUiRuntimeOptions>,
79+
) => string;
80+
},
81+
): { label: string; hint: string } {
82+
const liveSync =
83+
config.liveAccountSync ?? BACKEND_DEFAULTS.liveAccountSync ?? true;
84+
const affinity =
85+
config.sessionAffinity ?? BACKEND_DEFAULTS.sessionAffinity ?? true;
86+
const preemptive =
87+
config.preemptiveQuotaEnabled ??
88+
BACKEND_DEFAULTS.preemptiveQuotaEnabled ??
89+
true;
90+
const threshold5h =
91+
config.preemptiveQuotaRemainingPercent5h ??
92+
BACKEND_DEFAULTS.preemptiveQuotaRemainingPercent5h ??
93+
5;
94+
const threshold7d =
95+
config.preemptiveQuotaRemainingPercent7d ??
96+
BACKEND_DEFAULTS.preemptiveQuotaRemainingPercent7d ??
97+
5;
98+
const fetchTimeout =
99+
config.fetchTimeoutMs ?? BACKEND_DEFAULTS.fetchTimeoutMs ?? 60_000;
100+
const stallTimeout =
101+
config.streamStallTimeoutMs ??
102+
BACKEND_DEFAULTS.streamStallTimeoutMs ??
103+
45_000;
104+
const fetchTimeoutOption = BACKEND_NUMBER_OPTION_BY_KEY.get("fetchTimeoutMs");
105+
const stallTimeoutOption = BACKEND_NUMBER_OPTION_BY_KEY.get(
106+
"streamStallTimeoutMs",
107+
);
108+
109+
const highlightIfFocused = (
110+
key: BackendSettingFocusKey,
111+
text: string,
112+
): string => {
113+
if (focus !== key) return text;
114+
return deps.highlightPreviewToken(text, ui);
115+
};
116+
117+
const label = [
118+
`live sync ${highlightIfFocused("liveAccountSync", liveSync ? "on" : "off")}`,
119+
`affinity ${highlightIfFocused("sessionAffinity", affinity ? "on" : "off")}`,
120+
`preemptive ${highlightIfFocused("preemptiveQuotaEnabled", preemptive ? "on" : "off")}`,
121+
].join(" | ");
122+
123+
const hint = [
124+
`thresholds 5h<=${highlightIfFocused("preemptiveQuotaRemainingPercent5h", `${threshold5h}%`)}`,
125+
`7d<=${highlightIfFocused("preemptiveQuotaRemainingPercent7d", `${threshold7d}%`)}`,
126+
`timeouts ${highlightIfFocused("fetchTimeoutMs", fetchTimeoutOption ? formatBackendNumberValue(fetchTimeoutOption, fetchTimeout) : `${fetchTimeout}ms`)}/${highlightIfFocused("streamStallTimeoutMs", stallTimeoutOption ? formatBackendNumberValue(stallTimeoutOption, stallTimeout) : `${stallTimeout}ms`)}`,
127+
].join(" | ");
128+
129+
return { label, hint };
130+
}
131+
132+
export function buildBackendConfigPatch(
133+
config: PluginConfig,
134+
): Partial<PluginConfig> {
135+
const patch: Partial<PluginConfig> = {};
136+
for (const option of BACKEND_TOGGLE_OPTIONS) {
137+
const value = config[option.key];
138+
if (typeof value === "boolean") {
139+
patch[option.key] = value;
140+
}
141+
}
142+
for (const option of BACKEND_NUMBER_OPTIONS) {
143+
const value = config[option.key];
144+
if (typeof value === "number" && Number.isFinite(value)) {
145+
patch[option.key] = clampBackendNumber(option, value);
146+
}
147+
}
148+
return patch;
149+
}
150+
151+
export function clampBackendNumberForTests(
152+
settingKey: string,
153+
value: number,
154+
): number {
155+
const option = BACKEND_NUMBER_OPTION_BY_KEY.get(
156+
settingKey as BackendNumberSettingKey,
157+
);
158+
if (!option) {
159+
throw new Error(`Unknown backend numeric setting key: ${settingKey}`);
160+
}
161+
return clampBackendNumber(option, value);
162+
}

lib/codex-manager/settings-hub.ts

Lines changed: 14 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,20 @@ import { getUiRuntimeOptions, setUiRuntimeOptions } from "../ui/runtime.js";
2727
import { type MenuItem, select } from "../ui/select.js";
2828
import { getUnifiedSettingsPath } from "../unified-settings.js";
2929
import { sleep } from "../utils.js";
30+
import {
31+
backendSettingsEqual,
32+
buildBackendConfigPatch,
33+
buildBackendSettingsPreview,
34+
clampBackendNumberForTests,
35+
cloneBackendPluginConfig,
36+
formatBackendNumberValue,
37+
} from "./backend-settings-helpers.js";
3038
import {
3139
BACKEND_CATEGORY_OPTIONS,
3240
BACKEND_DEFAULTS,
3341
BACKEND_NUMBER_OPTION_BY_KEY,
3442
BACKEND_NUMBER_OPTIONS,
3543
BACKEND_TOGGLE_OPTION_BY_KEY,
36-
BACKEND_TOGGLE_OPTIONS,
3744
type BackendCategoryConfigAction,
3845
type BackendCategoryKey,
3946
type BackendCategoryOption,
@@ -607,137 +614,13 @@ function dashboardSettingsEqual(
607614
});
608615
}
609616

610-
function cloneBackendPluginConfig(config: PluginConfig): PluginConfig {
611-
const fallbackChain = config.unsupportedCodexFallbackChain;
612-
return {
613-
...BACKEND_DEFAULTS,
614-
...config,
615-
unsupportedCodexFallbackChain:
616-
fallbackChain && typeof fallbackChain === "object"
617-
? { ...fallbackChain }
618-
: {},
619-
};
620-
}
621-
622-
function backendSettingsSnapshot(
623-
config: PluginConfig,
624-
): Record<string, unknown> {
625-
const snapshot: Record<string, unknown> = {};
626-
for (const option of BACKEND_TOGGLE_OPTIONS) {
627-
snapshot[option.key] =
628-
config[option.key] ?? BACKEND_DEFAULTS[option.key] ?? false;
629-
}
630-
for (const option of BACKEND_NUMBER_OPTIONS) {
631-
snapshot[option.key] =
632-
config[option.key] ?? BACKEND_DEFAULTS[option.key] ?? option.min;
633-
}
634-
return snapshot;
635-
}
636-
637-
function backendSettingsEqual(
638-
left: PluginConfig,
639-
right: PluginConfig,
640-
): boolean {
641-
return (
642-
JSON.stringify(backendSettingsSnapshot(left)) ===
643-
JSON.stringify(backendSettingsSnapshot(right))
644-
);
645-
}
646-
647-
function formatBackendNumberValue(
648-
option: BackendNumberSettingOption,
649-
value: number,
650-
): string {
651-
if (option.unit === "percent") return `${Math.round(value)}%`;
652-
if (option.unit === "count") return `${Math.round(value)}`;
653-
if (value >= 60_000 && value % 60_000 === 0) {
654-
return `${Math.round(value / 60_000)}m`;
655-
}
656-
if (value >= 1_000 && value % 1_000 === 0) {
657-
return `${Math.round(value / 1_000)}s`;
658-
}
659-
return `${Math.round(value)}ms`;
660-
}
661-
662617
function clampBackendNumber(
663618
option: BackendNumberSettingOption,
664619
value: number,
665620
): number {
666621
return Math.max(option.min, Math.min(option.max, Math.round(value)));
667622
}
668623

669-
function buildBackendSettingsPreview(
670-
config: PluginConfig,
671-
ui: ReturnType<typeof getUiRuntimeOptions>,
672-
focus: BackendSettingFocusKey = null,
673-
): { label: string; hint: string } {
674-
const liveSync =
675-
config.liveAccountSync ?? BACKEND_DEFAULTS.liveAccountSync ?? true;
676-
const affinity =
677-
config.sessionAffinity ?? BACKEND_DEFAULTS.sessionAffinity ?? true;
678-
const preemptive =
679-
config.preemptiveQuotaEnabled ??
680-
BACKEND_DEFAULTS.preemptiveQuotaEnabled ??
681-
true;
682-
const threshold5h =
683-
config.preemptiveQuotaRemainingPercent5h ??
684-
BACKEND_DEFAULTS.preemptiveQuotaRemainingPercent5h ??
685-
5;
686-
const threshold7d =
687-
config.preemptiveQuotaRemainingPercent7d ??
688-
BACKEND_DEFAULTS.preemptiveQuotaRemainingPercent7d ??
689-
5;
690-
const fetchTimeout =
691-
config.fetchTimeoutMs ?? BACKEND_DEFAULTS.fetchTimeoutMs ?? 60_000;
692-
const stallTimeout =
693-
config.streamStallTimeoutMs ??
694-
BACKEND_DEFAULTS.streamStallTimeoutMs ??
695-
45_000;
696-
const fetchTimeoutOption = BACKEND_NUMBER_OPTION_BY_KEY.get("fetchTimeoutMs");
697-
const stallTimeoutOption = BACKEND_NUMBER_OPTION_BY_KEY.get(
698-
"streamStallTimeoutMs",
699-
);
700-
701-
const highlightIfFocused = (
702-
key: BackendSettingFocusKey,
703-
text: string,
704-
): string => {
705-
if (focus !== key) return text;
706-
return highlightPreviewToken(text, ui);
707-
};
708-
709-
const label = [
710-
`live sync ${highlightIfFocused("liveAccountSync", liveSync ? "on" : "off")}`,
711-
`affinity ${highlightIfFocused("sessionAffinity", affinity ? "on" : "off")}`,
712-
`preemptive ${highlightIfFocused("preemptiveQuotaEnabled", preemptive ? "on" : "off")}`,
713-
].join(" | ");
714-
715-
const hint = [
716-
`thresholds 5h<=${highlightIfFocused("preemptiveQuotaRemainingPercent5h", `${threshold5h}%`)}`,
717-
`7d<=${highlightIfFocused("preemptiveQuotaRemainingPercent7d", `${threshold7d}%`)}`,
718-
`timeouts ${highlightIfFocused("fetchTimeoutMs", fetchTimeoutOption ? formatBackendNumberValue(fetchTimeoutOption, fetchTimeout) : `${fetchTimeout}ms`)}/${highlightIfFocused("streamStallTimeoutMs", stallTimeoutOption ? formatBackendNumberValue(stallTimeoutOption, stallTimeout) : `${stallTimeout}ms`)}`,
719-
].join(" | ");
720-
721-
return { label, hint };
722-
}
723-
724-
function buildBackendConfigPatch(config: PluginConfig): Partial<PluginConfig> {
725-
const patch: Partial<PluginConfig> = {};
726-
for (const option of BACKEND_TOGGLE_OPTIONS) {
727-
const value = config[option.key];
728-
if (typeof value === "boolean") {
729-
patch[option.key] = value;
730-
}
731-
}
732-
for (const option of BACKEND_NUMBER_OPTIONS) {
733-
const value = config[option.key];
734-
if (typeof value === "number" && Number.isFinite(value)) {
735-
patch[option.key] = clampBackendNumber(option, value);
736-
}
737-
}
738-
return patch;
739-
}
740-
741624
function applyUiThemeFromDashboardSettings(
742625
settings: DashboardDisplaySettings,
743626
): void {
@@ -789,16 +672,6 @@ function formatMenuQuotaTtl(ttlMs: number): string {
789672
return `${ttlMs}ms`;
790673
}
791674

792-
function clampBackendNumberForTests(settingKey: string, value: number): number {
793-
const option = BACKEND_NUMBER_OPTION_BY_KEY.get(
794-
settingKey as BackendNumberSettingKey,
795-
);
796-
if (!option) {
797-
throw new Error(`Unknown backend numeric setting key: ${settingKey}`);
798-
}
799-
return clampBackendNumber(option, value);
800-
}
801-
802675
async function withQueuedRetryForTests<T>(
803676
pathKey: string,
804677
task: () => Promise<T>,
@@ -1050,7 +923,9 @@ async function promptBackendCategorySettings(
1050923
.filter((option): option is BackendNumberSettingOption => !!option);
1051924

1052925
while (true) {
1053-
const preview = buildBackendSettingsPreview(draft, ui, focusKey);
926+
const preview = buildBackendSettingsPreview(draft, ui, focusKey, {
927+
highlightPreviewToken,
928+
});
1054929
const toggleItems: MenuItem<BackendCategoryConfigAction>[] =
1055930
toggleOptions.map((option, index) => {
1056931
const enabled =
@@ -1256,7 +1131,9 @@ async function promptBackendSettings(
12561131

12571132
while (true) {
12581133
const previewFocus = focusByCategory[activeCategory] ?? null;
1259-
const preview = buildBackendSettingsPreview(draft, ui, previewFocus);
1134+
const preview = buildBackendSettingsPreview(draft, ui, previewFocus, {
1135+
highlightPreviewToken,
1136+
});
12601137
const categoryItems: MenuItem<BackendSettingsHubAction>[] =
12611138
BACKEND_CATEGORY_OPTIONS.map((category, index) => {
12621139
return {

0 commit comments

Comments
 (0)