@@ -41,6 +41,9 @@ class MockModeManager {
4141 /** Tracks whether a drift-toast was shown during initialize */
4242 lastDriftToast : string | null = null
4343
44+ /** Tracks whether a no-drift info toast was shown during initialize */
45+ lastInfoToast : string | null = null
46+
4447 constructor ( client : OpencodeClient ) {
4548 this . client = client
4649 }
@@ -79,30 +82,35 @@ class MockModeManager {
7982 }
8083
8184 const drifted = this . hasConfigDrift ( preset )
82- if ( ! drifted ) {
83- return
84- }
8585
86- // Apply preset to in-memory configs using recursive merge
87- if ( this . opencodeConfig ) {
88- if ( preset . model ) {
89- this . opencodeConfig . model = preset . model
86+ if ( drifted ) {
87+ // Apply preset to in-memory configs using recursive merge
88+ if ( this . opencodeConfig ) {
89+ if ( preset . model ) {
90+ this . opencodeConfig . model = preset . model
91+ }
92+ this . opencodeConfig . agent = this . opencodeConfig . agent || { }
93+ deepMergeModel (
94+ this . opencodeConfig . agent as Record < string , unknown > ,
95+ preset . opencode
96+ )
9097 }
91- this . opencodeConfig . agent = this . opencodeConfig . agent || { }
92- deepMergeModel (
93- this . opencodeConfig . agent as Record < string , unknown > ,
94- preset . opencode
95- )
96- }
9798
98- if ( this . ohMyConfig && preset [ 'oh-my-opencode' ] ) {
99- deepMergeModel (
100- this . ohMyConfig as Record < string , unknown > ,
101- preset [ 'oh-my-opencode' ]
102- )
99+ if ( this . ohMyConfig && preset [ 'oh-my-opencode' ] ) {
100+ deepMergeModel (
101+ this . ohMyConfig as Record < string , unknown > ,
102+ preset [ 'oh-my-opencode' ]
103+ )
104+ }
105+
106+ this . lastDriftToast = `applied "${ this . config . currentMode } " mode.\nrestart opencode to take effect.`
107+ return
103108 }
104109
105- this . lastDriftToast = `Applied "${ this . config . currentMode } " mode. Restart opencode to take effect.`
110+ // No drift: show informational toast if configured
111+ if ( this . config . showToastOnStartup ) {
112+ this . lastInfoToast = `current mode: ${ this . config . currentMode } `
113+ }
106114 }
107115
108116 private hasConfigDrift ( preset : ModePreset ) : boolean {
@@ -495,7 +503,7 @@ describe('ModeManager', () => {
495503 await manager . initialize ( )
496504
497505 expect ( manager . lastDriftToast ) . toContain ( 'economy' )
498- expect ( manager . lastDriftToast ) . toContain ( 'Restart opencode' )
506+ expect ( manager . lastDriftToast ) . toContain ( 'restart opencode' )
499507 } )
500508
501509 test ( 'applies preset when oh-my-opencode.json has drifted' , async ( ) => {
@@ -546,6 +554,88 @@ describe('ModeManager', () => {
546554 expect ( manager . lastDriftToast ) . toBeNull ( )
547555 } )
548556
557+ test ( 'shows info toast when no drift and showToastOnStartup is true' , async ( ) => {
558+ const config = clonePluginConfig ( )
559+ config . currentMode = 'economy'
560+ config . showToastOnStartup = true
561+ manager . setConfig ( config )
562+
563+ manager . setOpencodeConfig ( {
564+ model : 'opencode/glm-4.7-free' ,
565+ agent : {
566+ build : { model : 'opencode/glm-4.7-free' } ,
567+ plan : { model : 'opencode/glm-4.7-free' } ,
568+ } ,
569+ } )
570+
571+ manager . setOhMyConfig ( {
572+ agents : {
573+ sisyphus : { model : 'opencode/glm-4.7-free' } ,
574+ oracle : { model : 'opencode/glm-4.7-free' } ,
575+ } ,
576+ categories : {
577+ 'visual-engineering' : { model : 'opencode/glm-4.7-free' } ,
578+ quick : { model : 'opencode/glm-4.7-free' } ,
579+ } ,
580+ } )
581+
582+ await manager . initialize ( )
583+
584+ expect ( manager . lastDriftToast ) . toBeNull ( )
585+ expect ( manager . lastInfoToast ) . toBe ( 'current mode: economy' )
586+ } )
587+
588+ test ( 'does not show info toast when no drift and showToastOnStartup is false' , async ( ) => {
589+ const config = clonePluginConfig ( )
590+ config . currentMode = 'economy'
591+ config . showToastOnStartup = false
592+ manager . setConfig ( config )
593+
594+ manager . setOpencodeConfig ( {
595+ model : 'opencode/glm-4.7-free' ,
596+ agent : {
597+ build : { model : 'opencode/glm-4.7-free' } ,
598+ plan : { model : 'opencode/glm-4.7-free' } ,
599+ } ,
600+ } )
601+
602+ manager . setOhMyConfig ( {
603+ agents : {
604+ sisyphus : { model : 'opencode/glm-4.7-free' } ,
605+ oracle : { model : 'opencode/glm-4.7-free' } ,
606+ } ,
607+ categories : {
608+ 'visual-engineering' : { model : 'opencode/glm-4.7-free' } ,
609+ quick : { model : 'opencode/glm-4.7-free' } ,
610+ } ,
611+ } )
612+
613+ await manager . initialize ( )
614+
615+ expect ( manager . lastDriftToast ) . toBeNull ( )
616+ expect ( manager . lastInfoToast ) . toBeNull ( )
617+ } )
618+
619+ test ( 'does not show info toast when drift is detected (only drift toast)' , async ( ) => {
620+ const config = clonePluginConfig ( )
621+ config . currentMode = 'economy'
622+ config . showToastOnStartup = true
623+ manager . setConfig ( config )
624+
625+ manager . setOpencodeConfig ( {
626+ model : 'anthropic/claude-sonnet-4' , // Mismatch: drift
627+ agent : {
628+ build : { model : 'anthropic/claude-sonnet-4' } ,
629+ plan : { model : 'anthropic/claude-sonnet-4' } ,
630+ } ,
631+ } )
632+
633+ await manager . initialize ( )
634+
635+ expect ( manager . lastDriftToast ) . not . toBeNull ( )
636+ expect ( manager . lastInfoToast ) . toBeNull ( )
637+ } )
638+
549639 test ( 'does nothing when preset is not found' , async ( ) => {
550640 const config : ModeSwitcherConfig = {
551641 currentMode : 'nonexistent' ,
0 commit comments