@@ -200,8 +200,16 @@ const (
200200 promptListView
201201)
202202
203+ type focusedPanel int
204+
205+ const (
206+ mainPanelFocus focusedPanel = iota
207+ debugPanelFocus
208+ )
209+
203210type AppModel struct {
204211 state viewState
212+ focusedPanel focusedPanel
205213 ctx context.Context
206214 session * mcp.ClientSession
207215 toolList list.Model
@@ -314,6 +322,7 @@ func initialModel(ctx context.Context, session *mcp.ClientSession) *AppModel {
314322
315323 return & AppModel {
316324 state : toolSelectionView ,
325+ focusedPanel : mainPanelFocus ,
317326 ctx : ctx ,
318327 session : session ,
319328 toolList : toolList ,
@@ -365,9 +374,17 @@ func (m AppModel) Init() tea.Cmd {
365374
366375func (m * AppModel ) Update (msg tea.Msg ) (tea.Model , tea.Cmd ) {
367376 var cmd tea.Cmd
368- var cmds []tea.Cmd
369377
370378 switch msg := msg .(type ) {
379+ case tea.WindowSizeMsg :
380+ m .width = msg .Width
381+ m .height = msg .Height
382+ debugPanelWidth := m .width / 3
383+ m .debugViewport .Width = debugPanelWidth - 2
384+ m .debugViewport .Height = m .height - 2
385+ m .debugViewport , cmd = m .debugViewport .Update (msg )
386+ return m , cmd
387+
371388 case toolResult :
372389 if msg .err != nil {
373390 m .err = msg .err
@@ -378,6 +395,8 @@ func (m *AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
378395 }
379396 m .logf ("Result:\n ========\n %s" , msg .result )
380397 m .result = msg .result
398+ return m , nil
399+
381400 case resourceResult :
382401 if msg .err != nil {
383402 m .err = msg .err
@@ -386,13 +405,22 @@ func (m *AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
386405 if verbose {
387406 m .logf ("Resource result received" )
388407 }
389- m .logf ("Result:\n ========\n %s" , msg .result )
390408 m .resourceResult = msg .result
409+ return m , nil
410+
391411 case tea.KeyMsg :
392412 if verbose {
393413 m .logf ("Key pressed: %s" , msg .String ())
394414 }
415+ // Global key bindings that work regardless of focus
395416 switch msg .Type {
417+ case tea .KeyTab :
418+ if m .focusedPanel == mainPanelFocus {
419+ m .focusedPanel = debugPanelFocus
420+ } else {
421+ m .focusedPanel = mainPanelFocus
422+ }
423+ return m , nil
396424 case tea .KeyEsc :
397425 if m .state == resourceDetailView {
398426 m .state = resourceListView
@@ -403,54 +431,29 @@ func (m *AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
403431 case tea .KeyCtrlC :
404432 return m , tea .Quit
405433 }
434+ }
406435
407- switch m .state {
408- case toolSelectionView :
409- var model tea.Model
410- model , cmd = m .updateToolSelectionView (msg )
411- cmds = append (cmds , cmd )
412- m .debugViewport , cmd = m .debugViewport .Update (msg )
413- cmds = append (cmds , cmd )
414- return model , tea .Batch (cmds ... )
415- case resourceListView :
416- var model tea.Model
417- model , cmd = m .updateResourceListView (msg )
418- cmds = append (cmds , cmd )
419- m .debugViewport , cmd = m .debugViewport .Update (msg )
420- cmds = append (cmds , cmd )
421- return model , tea .Batch (cmds ... )
422- case promptListView :
423- var model tea.Model
424- model , cmd = m .updatePromptListView (msg )
425- cmds = append (cmds , cmd )
426- m .debugViewport , cmd = m .debugViewport .Update (msg )
427- cmds = append (cmds , cmd )
428- return model , tea .Batch (cmds ... )
429- case argumentInputView :
430- var model tea.Model
431- model , cmd = m .updateArgumentInputView (msg )
432- cmds = append (cmds , cmd )
433- m .debugViewport , cmd = m .debugViewport .Update (msg )
434- cmds = append (cmds , cmd )
435- return model , tea .Batch (cmds ... )
436- case resourceDetailView :
437- m .debugViewport , cmd = m .debugViewport .Update (msg )
438- cmds = append (cmds , cmd )
439- return m , tea .Batch (cmds ... )
440- }
441-
442- case tea.WindowSizeMsg :
443- m .width = msg .Width
444- m .height = msg .Height
445- debugWidth := m .width / 3
446- m .debugViewport .Width = debugWidth
447- m .debugViewport .Height = m .height - 2
436+ // Delegate message to the focused panel
437+ if m .focusedPanel == debugPanelFocus {
438+ m .debugViewport , cmd = m .debugViewport .Update (msg )
439+ return m , cmd
448440 }
449441
450- m .debugViewport , cmd = m .debugViewport .Update (msg )
451- cmds = append (cmds , cmd )
442+ // Main panel has focus, delegate to the active view
443+ switch m .state {
444+ case toolSelectionView :
445+ return m .updateToolSelectionView (msg )
446+ case resourceListView :
447+ return m .updateResourceListView (msg )
448+ case promptListView :
449+ return m .updatePromptListView (msg )
450+ case argumentInputView :
451+ return m .updateArgumentInputView (msg )
452+ case resourceDetailView :
453+ return m , nil
454+ }
452455
453- return m , tea . Batch ( cmds ... )
456+ return m , nil
454457}
455458
456459func (m * AppModel ) updateToolSelectionView (msg tea.Msg ) (tea.Model , tea.Cmd ) {
@@ -590,19 +593,19 @@ func (m AppModel) View() string {
590593 return fmt .Sprintf ("Error: %v\n \n Press ctrl+c to quit." , m .err )
591594 }
592595
593- mainWidth := m .width / 3
594- //debugWidth := m.width - mainWidth
596+ debugPanelWidth := m .width / 3
597+ mainPanelWidth := m .width - debugPanelWidth
595598
596599 var mainContent strings.Builder
597600 switch m .state {
598601 case toolSelectionView :
599- m .toolList .SetSize (mainWidth - 2 , m .height - 2 )
602+ m .toolList .SetSize (mainPanelWidth - 2 , m .height - 2 )
600603 mainContent .WriteString (m .toolList .View ())
601604 case resourceListView :
602- m .resourceList .SetSize (mainWidth - 2 , m .height - 2 )
605+ m .resourceList .SetSize (mainPanelWidth - 2 , m .height - 2 )
603606 mainContent .WriteString (m .resourceList .View ())
604607 case promptListView :
605- m .promptList .SetSize (mainWidth - 2 , m .height - 2 )
608+ m .promptList .SetSize (mainPanelWidth - 2 , m .height - 2 )
606609 mainContent .WriteString (m .promptList .View ())
607610 case resourceDetailView :
608611 var b strings.Builder
@@ -623,17 +626,24 @@ func (m AppModel) View() string {
623626 mainContent .WriteString (b .String ())
624627 }
625628
626- mainPanel := lipgloss .NewStyle ().
629+ mainPanelStyle := lipgloss .NewStyle ().
627630 Border (lipgloss .RoundedBorder ()).
628- Width (mainWidth ).
629- Height (m .height - 2 ).
630- Render (mainContent .String ())
631+ Width (mainPanelWidth - 2 ).
632+ Height (m .height - 2 )
631633
632- debugPanel := lipgloss .NewStyle ().
634+ debugPanelStyle := lipgloss .NewStyle ().
633635 Border (lipgloss .RoundedBorder ()).
634- Width (m .debugViewport .Width ).
635- Height (m .debugViewport .Height ).
636- Render (m .debugViewport .View ())
636+ Width (debugPanelWidth - 2 ).
637+ Height (m .debugViewport .Height )
638+
639+ if m .focusedPanel == mainPanelFocus {
640+ mainPanelStyle = mainPanelStyle .BorderForeground (lipgloss .Color ("228" )) // Yellow
641+ } else {
642+ debugPanelStyle = debugPanelStyle .BorderForeground (lipgloss .Color ("228" )) // Yellow
643+ }
644+
645+ mainPanel := mainPanelStyle .Render (mainContent .String ())
646+ debugPanel := debugPanelStyle .Render (m .debugViewport .View ())
637647
638648 return lipgloss .JoinHorizontal (lipgloss .Top , mainPanel , debugPanel )
639649}
@@ -782,7 +792,7 @@ func handleSession(ctx context.Context, session *mcp.ClientSession) error {
782792 defer f .Close ()
783793 }
784794 model := initialModel (ctx , session )
785- p := tea .NewProgram (model , tea .WithAltScreen ())
795+ p := tea .NewProgram (model , tea .WithAltScreen (), tea . WithMouseCellMotion () )
786796 finalModel , err := p .Run ()
787797 if err != nil {
788798 return fmt .Errorf ("error running program: %w" , err )
@@ -791,7 +801,6 @@ func handleSession(ctx context.Context, session *mcp.ClientSession) error {
791801 appModel , ok := finalModel .(* AppModel )
792802 if ! ok {
793803 return fmt .Errorf ("unexpected model type: %T" , finalModel )
794- }
795804
796805 return appModel .err
797806}
0 commit comments