Class: TUI::App

Inherits:
Object
  • Object
show all
Defined in:
lib/tui/app.rb

Constant Summary collapse

SCREENS =
%i[chat].freeze
COMMAND_KEYS =
{
  "a" => :anthropic_token,
  "h" => :toggle_hud,
  "n" => :new_session,
  "s" => :session_picker,
  "v" => :view_mode,
  "q" => :quit
}.freeze
(COMMAND_KEYS.map { |key, action| "[#{key}] #{action.to_s.tr("_", " ").capitalize}" } +
["[\u2191] Scroll chat", "[\u2193] Return to input", "[\u2192] Sub-agents / HUD"]).freeze
PICKER_PREFIX_WIDTH =

Picker entry prefix width: “[N]” (3) + marker (1) + space (1) = 5

5
VIEW_MODE_LABELS =

User-facing descriptions shown below each mode name in the view mode picker.

{
  "basic" => "Chat messages only",
  "verbose" => "Tools & timestamps",
  "debug" => "Full LLM context"
}.freeze
STATUS_LABELS =

Connection status emoji indicators for the info panel. Subscribed (normal state) shows only the emoji; other states add text.

{
  disconnected: "🔴 Disconnected",
  connecting: "🟡 Connecting",
  connected: "🟡 Connecting",
  subscribed: "🟢",
  reconnecting: "🟡 Reconnecting"
}.freeze
STATUS_COLORS =

Maps connection status to semantic theme color.

{
  disconnected: :theme_color_error,
  connecting: :theme_color_warning,
  connected: :theme_color_warning,
  subscribed: :theme_color_success,
  reconnecting: :theme_color_warning
}.freeze
PRINTABLE_CHAR =

Matches a single printable Unicode character (no control codes).

/\A[[:print:]]\z/
SHUTDOWN_SIGNALS =

Signals that trigger graceful shutdown when received from the OS.

%w[HUP TERM INT].freeze
CONTROLLING_TERMINAL =

Unix controlling terminal device path.

See Also:

  • #terminal_watchdog_loop
"/dev/tty"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cable_client:, debug: false) ⇒ App

Returns a new instance of App.

Parameters:

  • cable_client (TUI::CableClient)

    WebSocket client connected to the brain

  • debug (Boolean) (defaults to: false)

    enable performance logging to log/tui_performance.log



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/tui/app.rb', line 83

def initialize(cable_client:, debug: false)
  @cable_client = cable_client
  @perf_logger = PerformanceLogger.new(enabled: debug)
  @current_screen = :chat
  @command_mode = false
  @session_picker_active = false
  @session_picker_index = 0
  @session_picker_page = 0
  @session_picker_mode = :root
  @session_picker_parent_id = nil
  @hud_visible = true
  @hud_focused = false
  @hud_child_index = nil
  @hud_scroll_offset = 0
  @hud_max_scroll = 0
  @hud_visible_height = 0
  @hud_content_area = nil
  @view_mode_picker_active = false
  @view_mode_picker_index = 0
  @token_setup_active = false
  @token_input_buffer = InputBuffer.new
  @token_setup_error = nil
  @token_setup_warning = nil
  @token_setup_status = :idle
  @shutdown_requested = false
  @previous_signal_handlers = {}
  @watchdog_thread = nil
  @screens = {
    chat: Screens::Chat.new(cable_client: cable_client, perf_logger: @perf_logger)
  }
end

Instance Attribute Details

#command_modeObject (readonly)

Returns the value of attribute command_mode.



66
67
68
# File 'lib/tui/app.rb', line 66

def command_mode
  @command_mode
end

#current_screenObject (readonly)

Returns the value of attribute current_screen.



66
67
68
# File 'lib/tui/app.rb', line 66

def current_screen
  @current_screen
end

#hud_child_indexInteger? (readonly)

Returns index of selected child in HUD navigation, nil when inactive.

Returns:

  • (Integer, nil)

    index of selected child in HUD navigation, nil when inactive



73
74
75
# File 'lib/tui/app.rb', line 73

def hud_child_index
  @hud_child_index
end

#hud_focusedBoolean (readonly)

Returns true when the HUD pane has keyboard focus for scrolling.

Returns:

  • (Boolean)

    true when the HUD pane has keyboard focus for scrolling



71
72
73
# File 'lib/tui/app.rb', line 71

def hud_focused
  @hud_focused
end

#hud_visibleBoolean (readonly)

Returns true when the HUD info panel is visible.

Returns:

  • (Boolean)

    true when the HUD info panel is visible



69
70
71
# File 'lib/tui/app.rb', line 69

def hud_visible
  @hud_visible
end

#perf_loggerTUI::PerformanceLogger (readonly)

Returns frame timing logger (no-op when debug is off).

Returns:



79
80
81
# File 'lib/tui/app.rb', line 79

def perf_logger
  @perf_logger
end

#session_picker_activeObject (readonly)

Returns the value of attribute session_picker_active.



66
67
68
# File 'lib/tui/app.rb', line 66

def session_picker_active
  @session_picker_active
end

#shutdown_requestedBoolean (readonly)

Returns true when graceful shutdown has been requested via signal.

Returns:

  • (Boolean)

    true when graceful shutdown has been requested via signal



77
78
79
# File 'lib/tui/app.rb', line 77

def shutdown_requested
  @shutdown_requested
end

#token_setup_activeBoolean (readonly)

Returns true when the token setup popup overlay is visible.

Returns:

  • (Boolean)

    true when the token setup popup overlay is visible



75
76
77
# File 'lib/tui/app.rb', line 75

def token_setup_active
  @token_setup_active
end

#view_mode_picker_activeObject (readonly)

Returns the value of attribute view_mode_picker_active.



66
67
68
# File 'lib/tui/app.rb', line 66

def view_mode_picker_active
  @view_mode_picker_active
end

Instance Method Details

#runObject



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/tui/app.rb', line 115

def run
  install_signal_handlers
  start_terminal_watchdog
  RatatuiRuby.run do |tui|
    loop do
      break if @shutdown_requested

      tui.draw { |frame| render(frame, tui) }

      event = tui.poll_event(timeout: 0.1)
      break if @shutdown_requested
      next if event.nil? || event.none?
      break if handle_event(event) == :quit
    end
  end
ensure
  stop_terminal_watchdog
  restore_signal_handlers
  @cable_client.disconnect
end