@@ -15,10 +15,12 @@ import { residualIdFromSelection, type ResidualCatalogEntry } from "./residuals.
1515import {
1616 captureOverlayContinuation ,
1717 closeInsetOverlay ,
18+ closeReplaceableOverlay ,
1819 isOverlayContinuationCurrent ,
1920 openHelpOverlay ,
2021 openListOverlay ,
2122 openSettingsOverlay ,
23+ reserveOverlayHost ,
2224 setOwnedOverlayItems ,
2325 setStatusFlash ,
2426 type AppShell ,
@@ -435,8 +437,8 @@ function renderSettingsMenu(
435437 // against the just-written value; closing first forces a real reopen (a
436438 // second open of the same primary kind while one is showing is a no-op)
437439 // while the captured index keeps the cursor where the operator left it.
438- const activeIndex = shell . overlayList ?. activeIndex ?? 0 ;
439- closeInsetOverlay ( shell ) ;
440+ const activeIndex = shell . overlayKind === "settings" ? ( shell . overlayList ?. activeIndex ?? 0 ) : 0 ;
441+ closeReplaceableOverlay ( shell ) ;
440442 const snapshot = settings . read ( ) ;
441443 const cycleRows = settingsCycleRows ( snapshot , settings ) ;
442444 const byId = new Map < string , SettingsCycleRow > ( cycleRows . map ( ( r ) => [ r . id , r ] ) ) ;
@@ -506,12 +508,26 @@ export function openSettingsSurface(shell: AppShell, deps: CommandSurfaceDeps):
506508 renderSettingsMenu ( shell , deps , settings , settingsSyncNavRows ( deps ) ) ;
507509 return ;
508510 }
509- void deps . permissions . list ( ) . then ( ( entries ) => {
510- renderSettingsMenu ( shell , deps , settings , [
511- permissionsNavRow ( entries . length ) ,
512- ...settingsSyncNavRows ( deps ) ,
513- ] ) ;
514- } ) ;
511+ const release = reserveOverlayHost ( shell ) ;
512+ void deps . permissions . list ( ) . then (
513+ ( entries ) => {
514+ try {
515+ renderSettingsMenu ( shell , deps , settings , [
516+ permissionsNavRow ( entries . length ) ,
517+ ...settingsSyncNavRows ( deps ) ,
518+ ] ) ;
519+ } finally {
520+ release ( ) ;
521+ }
522+ } ,
523+ ( err : unknown ) => {
524+ try {
525+ deps . notify ( `Could not read remembered approvals: ${ errorText ( err ) } ` ) ;
526+ } finally {
527+ release ( ) ;
528+ }
529+ } ,
530+ ) ;
515531}
516532
517533/** Remembered approvals; Enter revokes the highlighted grant. */
@@ -521,40 +537,51 @@ export function openPermissionsSurface(shell: AppShell, deps: CommandSurfaceDeps
521537 deps . notify ( "Permission administration is not available in this session." ) ;
522538 return ;
523539 }
540+ const release = reserveOverlayHost ( shell ) ;
524541 void permissions . list ( ) . then (
525542 ( entries ) => {
526- closeInsetOverlay ( shell ) ;
527- const rows : ResidualCatalogEntry [ ] = entries . map ( ( e ) => ( {
528- id : e . id ,
529- label : grantRowLabel ( e ) ,
530- } ) ) ;
531- if ( rows . length === 0 ) {
532- rows . push ( {
533- id : CLOSE_ID ,
534- label : "No remembered approvals — grants you accept appear here" ,
543+ try {
544+ closeReplaceableOverlay ( shell ) ;
545+ const rows : ResidualCatalogEntry [ ] = entries . map ( ( e ) => ( {
546+ id : e . id ,
547+ label : grantRowLabel ( e ) ,
548+ } ) ) ;
549+ if ( rows . length === 0 ) {
550+ rows . push ( {
551+ id : CLOSE_ID ,
552+ label : "No remembered approvals — grants you accept appear here" ,
553+ } ) ;
554+ }
555+ rows . push ( { id : BACK_ID , label : "Back to settings" } ) ;
556+ openListOverlay ( shell , {
557+ kind : "permissions" ,
558+ title : "permissions · Enter revokes" ,
559+ frameId : "overlay-permissions" ,
560+ ...payload ( rows ) ,
561+ onAccept : ( selection ) => {
562+ const id = selectedId ( selection , rows ) ;
563+ if ( id === undefined || id === CLOSE_ID ) return ;
564+ if ( id === BACK_ID ) {
565+ openSettingsSurface ( shell , deps ) ;
566+ return ;
567+ }
568+ void permissions . revoke ( id ) . then (
569+ ( ) => openPermissionsSurface ( shell , deps ) ,
570+ ( err : unknown ) => deps . notify ( `Revoke failed: ${ errorText ( err ) } ` ) ,
571+ ) ;
572+ } ,
535573 } ) ;
574+ } finally {
575+ release ( ) ;
576+ }
577+ } ,
578+ ( err : unknown ) => {
579+ try {
580+ deps . notify ( `Could not read remembered approvals: ${ errorText ( err ) } ` ) ;
581+ } finally {
582+ release ( ) ;
536583 }
537- rows . push ( { id : BACK_ID , label : "Back to settings" } ) ;
538- openListOverlay ( shell , {
539- kind : "permissions" ,
540- title : "permissions · Enter revokes" ,
541- frameId : "overlay-permissions" ,
542- ...payload ( rows ) ,
543- onAccept : ( selection ) => {
544- const id = selectedId ( selection , rows ) ;
545- if ( id === undefined || id === CLOSE_ID ) return ;
546- if ( id === BACK_ID ) {
547- openSettingsSurface ( shell , deps ) ;
548- return ;
549- }
550- void permissions . revoke ( id ) . then (
551- ( ) => openPermissionsSurface ( shell , deps ) ,
552- ( err : unknown ) => deps . notify ( `Revoke failed: ${ errorText ( err ) } ` ) ,
553- ) ;
554- } ,
555- } ) ;
556584 } ,
557- ( err : unknown ) => deps . notify ( `Could not read remembered approvals: ${ errorText ( err ) } ` ) ,
558585 ) ;
559586}
560587
@@ -786,7 +813,7 @@ export function openPluginsSurface(shell: AppShell, deps: CommandSurfaceDeps): v
786813 deps . notify ( "Plugin administration is not available in this session." ) ;
787814 return ;
788815 }
789- closeInsetOverlay ( shell ) ;
816+ closeReplaceableOverlay ( shell ) ;
790817 const entries = plugins . list ( ) ;
791818 const rows : ResidualCatalogEntry [ ] = entries . map ( ( e ) => ( {
792819 id : e . id ,
@@ -901,7 +928,7 @@ export function openHooksSurface(shell: AppShell, deps: CommandSurfaceDeps): voi
901928 deps . notify ( "Hook administration is not available in this session." ) ;
902929 return ;
903930 }
904- closeInsetOverlay ( shell ) ;
931+ closeReplaceableOverlay ( shell ) ;
905932 const entries = hooks . list ( ) ;
906933 const rows : ResidualCatalogEntry [ ] = entries . map ( ( e ) => ( { id : e . id , label : hookRowLabel ( e ) } ) ) ;
907934 if ( rows . length === 0 ) {
@@ -1075,7 +1102,7 @@ export function openMcpSurface(
10751102 deps . notify ( "MCP administration is not available in this session." ) ;
10761103 return ;
10771104 }
1078- closeInsetOverlay ( shell ) ;
1105+ closeReplaceableOverlay ( shell ) ;
10791106 const entries = mcp . list ( ) ;
10801107 const canAdd = canAddMCPServer ( mcp ) ;
10811108 const rows : ResidualCatalogEntry [ ] = mcpSurfaceRows ( entries , canAdd ) ;
0 commit comments