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] Scroll HUD"]).freeze
HUD_MIN_WIDTH =

HUD occupies 1/3 of screen width, clamped to a usable minimum.

24
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_STYLES =

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

{
  disconnected: {label: "πŸ”΄ Disconnected", color: "red"},
  connecting: {label: "🟑 Connecting", color: "yellow"},
  connected: {label: "🟑 Connecting", color: "yellow"},
  subscribed: {label: "🟒", color: "green"},
  reconnecting: {label: "🟑 Reconnecting", color: "yellow"}
}.freeze
TOKEN_MASK_VISIBLE =

Number of leading characters to show unmasked in the token input. Matches the β€œsk-ant-oat01-” prefix (13 chars) plus one character of the secret portion so the user can verify both the token type and start of key.

14
TOKEN_MASK_STARS =

Maximum stars to show in the masked portion of the token. Keeps the masked display compact regardless of actual token length.

4
14
44
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
TERMINAL_CHECK_INTERVAL =

How often the watchdog thread checks if the controlling terminal is alive.

See Also:

  • #terminal_watchdog_loop
0.5
CONTROLLING_TERMINAL =

Unix controlling terminal device path.

See Also:

  • #terminal_watchdog_loop
"/dev/tty"
WATCHDOG_SHUTDOWN_TIMEOUT =

Grace period for watchdog thread to exit before force-killing it.

1
HUD_SCROLL_STEP =

HUD scroll step sizes (lines per event).

1
HUD_MOUSE_SCROLL_STEP =
2

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



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/tui/app.rb', line 100

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_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.



85
86
87
# File 'lib/tui/app.rb', line 85

def command_mode
  @command_mode
end

#current_screenObject (readonly)

Returns the value of attribute current_screen.



85
86
87
# File 'lib/tui/app.rb', line 85

def current_screen
  @current_screen
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



90
91
92
# File 'lib/tui/app.rb', line 90

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



88
89
90
# File 'lib/tui/app.rb', line 88

def hud_visible
  @hud_visible
end

#perf_loggerTUI::PerformanceLogger (readonly)

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

Returns:



96
97
98
# File 'lib/tui/app.rb', line 96

def perf_logger
  @perf_logger
end

#session_picker_activeObject (readonly)

Returns the value of attribute session_picker_active.



85
86
87
# File 'lib/tui/app.rb', line 85

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



94
95
96
# File 'lib/tui/app.rb', line 94

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



92
93
94
# File 'lib/tui/app.rb', line 92

def token_setup_active
  @token_setup_active
end

#view_mode_picker_activeObject (readonly)

Returns the value of attribute view_mode_picker_active.



85
86
87
# File 'lib/tui/app.rb', line 85

def view_mode_picker_active
  @view_mode_picker_active
end

Instance Method Details

#runObject



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/tui/app.rb', line 131

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