@@ -28,7 +28,7 @@ import type { PluginConfig } from "../types.js";
2828import { ANSI } from "../ui/ansi.js" ;
2929import { UI_COPY } from "../ui/copy.js" ;
3030import { getUiRuntimeOptions , setUiRuntimeOptions } from "../ui/runtime.js" ;
31- import { type MenuItem , select } from "../ui/select.js" ;
31+ import { type MenuItem , select , type SelectOptions } from "../ui/select.js" ;
3232import { getUnifiedSettingsPath } from "../unified-settings.js" ;
3333import { sleep } from "../utils.js" ;
3434
@@ -186,6 +186,7 @@ type ThemeConfigAction =
186186
187187type BackendToggleSettingKey =
188188 | "liveAccountSync"
189+ | "codexCliSessionSupervisor"
189190 | "sessionAffinity"
190191 | "proactiveRefreshGuardian"
191192 | "retryAllAccountsRateLimited"
@@ -272,6 +273,7 @@ type SettingsHubAction =
272273 | { type : "back" } ;
273274
274275type ExperimentalSettingsAction =
276+ | { type : "toggle-session-supervisor" }
275277 | { type : "sync" }
276278 | { type : "backup" }
277279 | { type : "toggle-refresh-guardian" }
@@ -281,12 +283,54 @@ type ExperimentalSettingsAction =
281283 | { type : "save" }
282284 | { type : "back" } ;
283285
286+ function getExperimentalSelectOptions (
287+ ui : ReturnType < typeof getUiRuntimeOptions > ,
288+ help : string ,
289+ onInput ?: SelectOptions < ExperimentalSettingsAction > [ "onInput" ] ,
290+ ) : SelectOptions < ExperimentalSettingsAction > {
291+ return {
292+ message : UI_COPY . settings . experimentalTitle ,
293+ subtitle : UI_COPY . settings . experimentalSubtitle ,
294+ help,
295+ clearScreen : true ,
296+ theme : ui . theme ,
297+ selectedEmphasis : "minimal" ,
298+ onInput,
299+ } ;
300+ }
301+
302+ function mapExperimentalMenuHotkey (
303+ raw : string ,
304+ ) : ExperimentalSettingsAction | undefined {
305+ if ( raw === "1" ) return { type : "toggle-session-supervisor" } ;
306+ if ( raw === "2" ) return { type : "sync" } ;
307+ if ( raw === "3" ) return { type : "backup" } ;
308+ if ( raw === "4" ) return { type : "toggle-refresh-guardian" } ;
309+ if ( raw === "[" || raw === "-" ) return { type : "decrease-refresh-interval" } ;
310+ if ( raw === "]" || raw === "+" ) return { type : "increase-refresh-interval" } ;
311+ const lower = raw . toLowerCase ( ) ;
312+ if ( lower === "q" ) return { type : "back" } ;
313+ if ( lower === "s" ) return { type : "save" } ;
314+ return undefined ;
315+ }
316+
317+ function mapExperimentalStatusHotkey (
318+ raw : string ,
319+ ) : ExperimentalSettingsAction | undefined {
320+ return raw . toLowerCase ( ) === "q" ? { type : "back" } : undefined ;
321+ }
322+
284323const BACKEND_TOGGLE_OPTIONS : BackendToggleSettingOption [ ] = [
285324 {
286325 key : "liveAccountSync" ,
287326 label : "Enable Live Sync" ,
288327 description : "Keep accounts synced when files change in another window." ,
289328 } ,
329+ {
330+ key : "codexCliSessionSupervisor" ,
331+ label : "Enable Session Resume Supervisor" ,
332+ description : "Wrap interactive Codex sessions so they can relaunch with resume after rotation." ,
333+ } ,
290334 {
291335 key : "sessionAffinity" ,
292336 label : "Enable Session Affinity" ,
@@ -1279,6 +1323,8 @@ const __testOnly = {
12791323 cloneDashboardSettings,
12801324 withQueuedRetry : withQueuedRetryForTests ,
12811325 loadExperimentalSyncTarget,
1326+ mapExperimentalMenuHotkey,
1327+ mapExperimentalStatusHotkey,
12821328 promptExperimentalSettings,
12831329 persistDashboardSettingsSelection : persistDashboardSettingsSelectionForTests ,
12841330 persistBackendConfigSelection : persistBackendConfigSelectionForTests ,
@@ -2530,6 +2576,11 @@ async function promptExperimentalSettings(
25302576 while ( true ) {
25312577 const action = await select < ExperimentalSettingsAction > (
25322578 [
2579+ {
2580+ label : `${ formatDashboardSettingState ( draft . codexCliSessionSupervisor ?? BACKEND_DEFAULTS . codexCliSessionSupervisor ?? false ) } ${ UI_COPY . settings . experimentalSessionSupervisor } ` ,
2581+ value : { type : "toggle-session-supervisor" } ,
2582+ color : "yellow" ,
2583+ } ,
25332584 {
25342585 label : UI_COPY . settings . experimentalSync ,
25352586 value : { type : "sync" } ,
@@ -2573,19 +2624,25 @@ async function promptExperimentalSettings(
25732624 color : "red" ,
25742625 } ,
25752626 ] ,
2576- {
2577- message : UI_COPY . settings . experimentalTitle ,
2578- subtitle : UI_COPY . settings . experimentalSubtitle ,
2579- help : UI_COPY . settings . experimentalHelpMenu ,
2580- clearScreen : true ,
2581- theme : ui . theme ,
2582- selectedEmphasis : "minimal" ,
2583- onInput : ( raw ) =>
2584- raw . toLowerCase ( ) === "q" ? { type : "back" } : undefined ,
2585- } ,
2627+ getExperimentalSelectOptions (
2628+ ui ,
2629+ UI_COPY . settings . experimentalHelpMenu ,
2630+ mapExperimentalMenuHotkey ,
2631+ ) ,
25862632 ) ;
25872633 if ( ! action || action . type === "back" ) return null ;
25882634 if ( action . type === "save" ) return draft ;
2635+ if ( action . type === "toggle-session-supervisor" ) {
2636+ draft = {
2637+ ...draft ,
2638+ codexCliSessionSupervisor : ! (
2639+ draft . codexCliSessionSupervisor ??
2640+ BACKEND_DEFAULTS . codexCliSessionSupervisor ??
2641+ false
2642+ ) ,
2643+ } ;
2644+ continue ;
2645+ }
25892646 if ( action . type === "toggle-refresh-guardian" ) {
25902647 draft = {
25912648 ...draft ,
@@ -2647,14 +2704,11 @@ async function promptExperimentalSettings(
26472704 color : "red" ,
26482705 } ,
26492706 ] ,
2650- {
2651- message : UI_COPY . settings . experimentalTitle ,
2652- subtitle : UI_COPY . settings . experimentalSubtitle ,
2653- help : UI_COPY . settings . experimentalHelpStatus ,
2654- clearScreen : true ,
2655- theme : ui . theme ,
2656- selectedEmphasis : "minimal" ,
2657- } ,
2707+ getExperimentalSelectOptions (
2708+ ui ,
2709+ UI_COPY . settings . experimentalHelpStatus ,
2710+ mapExperimentalStatusHotkey ,
2711+ ) ,
26582712 ) ;
26592713 } catch ( error ) {
26602714 const message =
@@ -2674,14 +2728,11 @@ async function promptExperimentalSettings(
26742728 color : "red" ,
26752729 } ,
26762730 ] ,
2677- {
2678- message : UI_COPY . settings . experimentalTitle ,
2679- subtitle : UI_COPY . settings . experimentalSubtitle ,
2680- help : UI_COPY . settings . experimentalHelpStatus ,
2681- clearScreen : true ,
2682- theme : ui . theme ,
2683- selectedEmphasis : "minimal" ,
2684- } ,
2731+ getExperimentalSelectOptions (
2732+ ui ,
2733+ UI_COPY . settings . experimentalHelpStatus ,
2734+ mapExperimentalStatusHotkey ,
2735+ ) ,
26852736 ) ;
26862737 }
26872738 } finally {
@@ -2708,14 +2759,11 @@ async function promptExperimentalSettings(
27082759 color : "red" ,
27092760 } ,
27102761 ] ,
2711- {
2712- message : UI_COPY . settings . experimentalTitle ,
2713- subtitle : UI_COPY . settings . experimentalSubtitle ,
2714- help : UI_COPY . settings . experimentalHelpStatus ,
2715- clearScreen : true ,
2716- theme : ui . theme ,
2717- selectedEmphasis : "minimal" ,
2718- } ,
2762+ getExperimentalSelectOptions (
2763+ ui ,
2764+ UI_COPY . settings . experimentalHelpStatus ,
2765+ mapExperimentalStatusHotkey ,
2766+ ) ,
27192767 ) ;
27202768 continue ;
27212769 }
@@ -2747,14 +2795,11 @@ async function promptExperimentalSettings(
27472795 color : "red" ,
27482796 } ,
27492797 ] ,
2750- {
2751- message : UI_COPY . settings . experimentalTitle ,
2752- subtitle : UI_COPY . settings . experimentalSubtitle ,
2753- help : UI_COPY . settings . experimentalHelpStatus ,
2754- clearScreen : true ,
2755- theme : ui . theme ,
2756- selectedEmphasis : "minimal" ,
2757- } ,
2798+ getExperimentalSelectOptions (
2799+ ui ,
2800+ UI_COPY . settings . experimentalHelpStatus ,
2801+ mapExperimentalStatusHotkey ,
2802+ ) ,
27582803 ) ;
27592804 continue ;
27602805 }
@@ -2793,20 +2838,16 @@ async function promptExperimentalSettings(
27932838 color : "red" ,
27942839 } ,
27952840 ] ,
2796- {
2797- message : UI_COPY . settings . experimentalTitle ,
2798- subtitle : UI_COPY . settings . experimentalSubtitle ,
2799- help : UI_COPY . settings . experimentalHelpStatus ,
2800- clearScreen : true ,
2801- theme : ui . theme ,
2802- selectedEmphasis : "minimal" ,
2803- onInput : ( raw ) => {
2841+ getExperimentalSelectOptions (
2842+ ui ,
2843+ UI_COPY . settings . experimentalHelpPreview ,
2844+ ( raw ) => {
28042845 const lower = raw . toLowerCase ( ) ;
28052846 if ( lower === "q" ) return { type : "back" } ;
28062847 if ( lower === "a" ) return { type : "apply" } ;
28072848 return undefined ;
28082849 } ,
2809- } ,
2850+ ) ,
28102851 ) ;
28112852 if ( ! review || review . type === "back" ) continue ;
28122853
@@ -2837,14 +2878,11 @@ async function promptExperimentalSettings(
28372878 } ,
28382879 { label : UI_COPY . settings . back , value : { type : "back" } , color : "red" } ,
28392880 ] ,
2840- {
2841- message : UI_COPY . settings . experimentalTitle ,
2842- subtitle : UI_COPY . settings . experimentalSubtitle ,
2843- help : UI_COPY . settings . experimentalHelpStatus ,
2844- clearScreen : true ,
2845- theme : ui . theme ,
2846- selectedEmphasis : "minimal" ,
2847- } ,
2881+ getExperimentalSelectOptions (
2882+ ui ,
2883+ UI_COPY . settings . experimentalHelpStatus ,
2884+ mapExperimentalStatusHotkey ,
2885+ ) ,
28482886 ) ;
28492887 }
28502888}
0 commit comments