@@ -42,6 +42,7 @@ import (
4242 rhostorage "github.com/GrayCodeAI/rho/internal/storage"
4343 "github.com/GrayCodeAI/rho/internal/system/staleness"
4444 "github.com/GrayCodeAI/rho/internal/tool"
45+ "github.com/GrayCodeAI/rho/internal/tui"
4546 "github.com/GrayCodeAI/rho/internal/ui/icons"
4647)
4748
@@ -330,6 +331,9 @@ func newChatModelWithRegistry(ref *progRef, systemPrompt string, settings rhocon
330331 Enabled : true ,
331332 MaxAutoApprove : safety .AutonomySemi ,
332333 ConfirmFn : func (req engine.ApprovalRequest ) engine.ApprovalResponse {
334+ if sess .PermSvc () != nil && sess .PermSvc ().RuntimeState ().Autonomy == safety .AutonomyYOLO {
335+ return engine .ApprovalApprove
336+ }
333337 response := make (chan engine.ApprovalResponse , 1 )
334338 ref .Send (approvalAskMsg {req : req , response : response })
335339 select {
@@ -528,11 +532,11 @@ func (m *chatModel) refreshInputPlaceholder() {
528532 }
529533 switch work {
530534 case engine .WorkModePlan :
531- m .input .Placeholder = "Design architecture or draft plan... · / commands · ? help"
535+ m .input .Placeholder = "Design architecture or draft plan... · /select copy · ? help"
532536 case engine .WorkModeReview :
533- m .input .Placeholder = "Audit diffs, security, or PRs... · / commands · ? help"
537+ m .input .Placeholder = "Audit diffs, security, or PRs... · /select copy · ? help"
534538 default :
535- m .input .Placeholder = "Build, refactor, or run commands... · / commands · ? help"
539+ m .input .Placeholder = "Build, refactor, or run commands... · /select copy · ? help"
536540 }
537541}
538542
@@ -726,16 +730,24 @@ func runChat() error {
726730
727731 finalModel , err := p .Run ()
728732 writeTerminalMouse (disableMouseCSI )
733+ // Kitty graphics are not scoped to Bubble Tea's alternate screen. Remove
734+ // the optional welcome mascot before the farewell is written so shutdown
735+ // leaves only the final text message in the terminal.
736+ _ = tui .ClearGraphics (os .Stderr )
729737 if err != nil {
730738 return err
731739 }
732- fm , ok := finalModel .( chatModel )
733- if ! ok {
734- return fmt . Errorf ( "unexpected final model type: %T" , finalModel )
740+ fm , err := finalChatModel ( finalModel )
741+ if err != nil {
742+ return err
735743 }
736744 if fm .quitting {
737745 fm .saveSession ()
738- fmt .Print (formatQuitResumeMessage (fm .sessionID ))
746+ // Bubble Tea restores the previous screen before returning. Clear that
747+ // frame and any terminal-persistent mascot so shutdown has one clean,
748+ // predictable final state.
749+ fmt .Print ("\x1b [2J\x1b [H" )
750+ fmt .Println ("Thank you for using Rho!" )
739751 return nil
740752 }
741753 rhoC := ansiOrange
@@ -790,3 +802,18 @@ func runChat() error {
790802 }
791803 return nil
792804}
805+
806+ // finalChatModel normalizes Bubble Tea's shutdown model. Bubble Tea may return
807+ // either the value passed to NewProgram or its pointer after updates; both are
808+ // valid representations of the same chat state.
809+ func finalChatModel (model tea.Model ) (chatModel , error ) {
810+ switch m := model .(type ) {
811+ case chatModel :
812+ return m , nil
813+ case * chatModel :
814+ if m != nil {
815+ return * m , nil
816+ }
817+ }
818+ return chatModel {}, fmt .Errorf ("unexpected final model type: %T" , model )
819+ }
0 commit comments