Class: RubyCoded::Chat::State
- Inherits:
-
Object
- Object
- RubyCoded::Chat::State
- Includes:
- ContextWindow, LoginFlow, MessageAssistant, MessageTokenTracking, Messages, ModelSelection, PlanTracking, Scrollable, TokenCost, ToolConfirmation
- Defined in:
- lib/ruby_coded/chat/state.rb,
lib/ruby_coded/chat/state/messages.rb,
lib/ruby_coded/chat/state/login_flow.rb,
lib/ruby_coded/chat/state/scrollable.rb,
lib/ruby_coded/chat/state/token_cost.rb,
lib/ruby_coded/chat/state/plan_tracking.rb,
lib/ruby_coded/chat/state/context_window.rb,
lib/ruby_coded/chat/state/model_selection.rb,
lib/ruby_coded/chat/state/login_flow_steps.rb,
lib/ruby_coded/chat/state/message_assistant.rb,
lib/ruby_coded/chat/state/tool_confirmation.rb,
lib/ruby_coded/chat/state/message_token_tracking.rb
Overview
This class is used to manage the state of the chat
Defined Under Namespace
Modules: ContextWindow, LoginFlow, LoginFlowSteps, MessageAssistant, MessageTokenTracking, Messages, ModelSelection, PlanTracking, Scrollable, TokenCost, ToolConfirmation
Constant Summary collapse
- MIN_RENDER_INTERVAL =
0.05
Constants included from TokenCost
TokenCost::CACHE_CREATION_INPUT_MULTIPLIER, TokenCost::UNPRICED_DEFAULTS
Constants included from MessageTokenTracking
MessageTokenTracking::TOKEN_KEYS
Constants included from Messages
Instance Attribute Summary collapse
-
#codex_mode ⇒ Object
Returns the value of attribute codex_mode.
-
#command_catalog ⇒ Object
readonly
Returns the value of attribute command_catalog.
-
#cursor_position ⇒ Object
readonly
Returns the value of attribute cursor_position.
-
#input_buffer ⇒ Object
readonly
Returns the value of attribute input_buffer.
-
#input_scroll_offset ⇒ Object
readonly
Returns the value of attribute input_scroll_offset.
-
#messages ⇒ Object
readonly
Returns the value of attribute messages.
-
#mode ⇒ Object
readonly
Returns the value of attribute mode.
-
#model ⇒ Object
Returns the value of attribute model.
-
#model_list ⇒ Object
readonly
Returns the value of attribute model_list.
-
#model_select_filter ⇒ Object
readonly
Returns the value of attribute model_select_filter.
-
#model_select_index ⇒ Object
readonly
Returns the value of attribute model_select_index.
-
#mutex ⇒ Object
readonly
Returns the value of attribute mutex.
-
#scroll_offset ⇒ Object
readonly
Returns the value of attribute scroll_offset.
-
#should_quit ⇒ Object
Returns the value of attribute should_quit.
-
#streaming ⇒ Object
Returns the value of attribute streaming.
-
#tui_suspend_reason ⇒ Object
readonly
Returns the value of attribute tui_suspend_reason.
Attributes included from LoginFlow
#login_auth_method, #login_error, #login_items, #login_key_buffer, #login_key_cursor, #login_oauth_result, #login_provider, #login_select_index, #login_step
Attributes included from PlanTracking
#clarification_custom_input, #clarification_index, #clarification_input_mode, #clarification_options, #clarification_question
Attributes included from ToolConfirmation
Attributes included from Messages
Instance Method Summary collapse
- #agentic_mode=(value) ⇒ Object
- #agentic_mode? ⇒ Boolean
- #append_to_input(text) ⇒ Object
- #clear_input! ⇒ Object
- #clear_tui_suspend! ⇒ Object
- #command_descriptions ⇒ Object
- #consume_input! ⇒ Object
- #delete_last_char ⇒ Object
- #dirty? ⇒ Boolean
-
#initialize(model:, command_catalog: nil) ⇒ State
constructor
A new instance of State.
- #mark_clean! ⇒ Object
- #mark_dirty! ⇒ Object
- #move_cursor_left ⇒ Object
- #move_cursor_right ⇒ Object
- #move_cursor_to_end ⇒ Object
- #move_cursor_to_start ⇒ Object
- #request_tui_suspend!(reason, **metadata) ⇒ Object
- #should_quit? ⇒ Boolean
- #streaming? ⇒ Boolean
- #tui_suspend_metadata ⇒ Object
- #tui_suspend_requested? ⇒ Boolean
-
#update_input_scroll_offset ⇒ Object
Updates the horizontal scroll offset of the input area so the cursor is always visible.
-
#update_input_visible_width(width) ⇒ Object
Called by the renderer so the state knows how many characters fit on screen (inner width minus the prompt prefix).
Methods included from LoginFlow
#append_to_login_key, #delete_last_login_key_char, #enter_login_flow!, #exit_login_flow!, #init_login_flow, #login_active?, #login_advance_to_api_key!, #login_advance_to_auth_method!, #login_advance_to_oauth!, #login_clear_oauth_result!, #login_provider_module, #login_select_down, #login_select_up, #login_selected_item, #login_set_error!, #login_set_oauth_result!
Methods included from ContextWindow
#current_model_context_window, #session_context_tokens_used, #session_context_usage_percentage
Methods included from TokenCost
#init_token_cost, #session_cost_breakdown, #total_session_cost
Methods included from PlanTracking
#activate_plan_mode!, #append_to_clarification_input, #clarification_down, #clarification_up, #clear_plan!, #current_plan, #deactivate_plan_mode!, #delete_last_clarification_char, #enter_plan_clarification!, #exit_plan_clarification!, #has_unsaved_plan?, #init_plan_tracking, #mark_plan_saved!, #plan_clarification?, #plan_mode_active?, #plan_saved?, #selected_clarification_option, #toggle_clarification_input_mode!, #update_current_plan!
Methods included from ToolConfirmation
#auto_approve_tools?, #awaiting_tool_confirmation?, #clear_tool_confirmation!, #disable_auto_approve!, #enable_auto_approve!, #init_tool_confirmation, #pending_tool_args, #pending_tool_name, #request_tool_confirmation!, #resolve_tool_confirmation!, #tool_confirmation_response, #tool_confirmation_response=
Methods included from Scrollable
#scroll_down, #scroll_to_bottom, #scroll_to_top, #scroll_up, #update_scroll_metrics
Methods included from MessageTokenTracking
#last_turn_context_tokens, #token_usage_by_model, #total_input_tokens, #total_output_tokens, #total_thinking_tokens, #update_last_message_tokens
Methods included from MessageAssistant
#ensure_last_is_assistant!, #fail_last_assistant, #last_assistant_empty?, #reset_last_assistant_content, #streaming_append
Methods included from Messages
#add_message, #append_to_last_message, #build_message, #clear_messages!, #init_messages, #messages_snapshot
Methods included from ModelSelection
#append_to_model_filter, #delete_last_filter_char, #enter_model_select!, #exit_model_select!, #filtered_model_list, #model_select?, #model_select_down, #model_select_show_all?, #model_select_up, #selected_model
Constructor Details
#initialize(model:, command_catalog: nil) ⇒ State
Returns a new instance of State.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/ruby_coded/chat/state.rb', line 36 def initialize(model:, command_catalog: nil) @model = model @command_catalog = command_catalog # String.new: literals like "" are frozen under frozen_string_literal @input_buffer = String.new @cursor_position = 0 @input_scroll_offset = 0 @messages = [] @streaming = false @should_quit = false @agentic_mode = false @codex_mode = false @mutex = Mutex.new @dirty = true @last_render_at = 0.0 @scroll_offset = 0 @total_lines = 0 @visible_height = 0 @mode = :chat @model_list = [] @model_select_index = 0 @model_select_filter = String.new @model_select_show_all = false init_tool_confirmation init_plan_tracking init_token_cost init_login_flow init_plugin_state end |
Instance Attribute Details
#codex_mode ⇒ Object
Returns the value of attribute codex_mode.
32 33 34 |
# File 'lib/ruby_coded/chat/state.rb', line 32 def codex_mode @codex_mode end |
#command_catalog ⇒ Object (readonly)
Returns the value of attribute command_catalog.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def command_catalog @command_catalog end |
#cursor_position ⇒ Object (readonly)
Returns the value of attribute cursor_position.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def cursor_position @cursor_position end |
#input_buffer ⇒ Object (readonly)
Returns the value of attribute input_buffer.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def input_buffer @input_buffer end |
#input_scroll_offset ⇒ Object (readonly)
Returns the value of attribute input_scroll_offset.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def input_scroll_offset @input_scroll_offset end |
#messages ⇒ Object (readonly)
Returns the value of attribute messages.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def @messages end |
#mode ⇒ Object (readonly)
Returns the value of attribute mode.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def mode @mode end |
#model ⇒ Object
Returns the value of attribute model.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def model @model end |
#model_list ⇒ Object (readonly)
Returns the value of attribute model_list.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def model_list @model_list end |
#model_select_filter ⇒ Object (readonly)
Returns the value of attribute model_select_filter.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def model_select_filter @model_select_filter end |
#model_select_index ⇒ Object (readonly)
Returns the value of attribute model_select_index.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def model_select_index @model_select_index end |
#mutex ⇒ Object (readonly)
Returns the value of attribute mutex.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def mutex @mutex end |
#scroll_offset ⇒ Object (readonly)
Returns the value of attribute scroll_offset.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def scroll_offset @scroll_offset end |
#should_quit ⇒ Object
Returns the value of attribute should_quit.
32 33 34 |
# File 'lib/ruby_coded/chat/state.rb', line 32 def should_quit @should_quit end |
#streaming ⇒ Object
Returns the value of attribute streaming.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def streaming @streaming end |
#tui_suspend_reason ⇒ Object (readonly)
Returns the value of attribute tui_suspend_reason.
29 30 31 |
# File 'lib/ruby_coded/chat/state.rb', line 29 def tui_suspend_reason @tui_suspend_reason end |
Instance Method Details
#agentic_mode=(value) ⇒ Object
87 88 89 90 |
# File 'lib/ruby_coded/chat/state.rb', line 87 def agentic_mode=(value) @agentic_mode = value mark_dirty! end |
#agentic_mode? ⇒ Boolean
83 84 85 |
# File 'lib/ruby_coded/chat/state.rb', line 83 def agentic_mode? @agentic_mode end |
#append_to_input(text) ⇒ Object
144 145 146 147 148 149 150 |
# File 'lib/ruby_coded/chat/state.rb', line 144 def append_to_input(text) @input_buffer.insert(@cursor_position, text) @cursor_position += text.length update_input_scroll_offset mark_dirty! reset_command_completion_index if respond_to?(:reset_command_completion_index, true) end |
#clear_input! ⇒ Object
194 195 196 197 198 199 |
# File 'lib/ruby_coded/chat/state.rb', line 194 def clear_input! @input_buffer.clear @cursor_position = 0 @input_scroll_offset = 0 mark_dirty! end |
#clear_tui_suspend! ⇒ Object
223 224 225 226 |
# File 'lib/ruby_coded/chat/state.rb', line 223 def clear_tui_suspend! @tui_suspend_reason = nil @tui_suspend_metadata = nil end |
#command_descriptions ⇒ Object
96 97 98 99 100 |
# File 'lib/ruby_coded/chat/state.rb', line 96 def command_descriptions return {} unless @command_catalog @command_catalog.command_descriptions end |
#consume_input! ⇒ Object
201 202 203 204 205 206 207 |
# File 'lib/ruby_coded/chat/state.rb', line 201 def consume_input! input = @input_buffer.dup @input_buffer.clear @cursor_position = 0 @input_scroll_offset = 0 input end |
#delete_last_char ⇒ Object
152 153 154 155 156 157 158 159 160 |
# File 'lib/ruby_coded/chat/state.rb', line 152 def delete_last_char return if @cursor_position <= 0 @input_buffer.slice!(@cursor_position - 1) @cursor_position -= 1 update_input_scroll_offset mark_dirty! reset_command_completion_index if respond_to?(:reset_command_completion_index, true) end |
#dirty? ⇒ Boolean
102 103 104 105 106 107 108 109 110 |
# File 'lib/ruby_coded/chat/state.rb', line 102 def dirty? @mutex.synchronize do return false unless @dirty return true unless @streaming now = Process.clock_gettime(Process::CLOCK_MONOTONIC) (now - @last_render_at) >= MIN_RENDER_INTERVAL end end |
#mark_clean! ⇒ Object
112 113 114 115 116 117 |
# File 'lib/ruby_coded/chat/state.rb', line 112 def mark_clean! @mutex.synchronize do @dirty = false @last_render_at = Process.clock_gettime(Process::CLOCK_MONOTONIC) end end |
#mark_dirty! ⇒ Object
119 120 121 |
# File 'lib/ruby_coded/chat/state.rb', line 119 def mark_dirty! @mutex.synchronize { @dirty = true } end |
#move_cursor_left ⇒ Object
162 163 164 165 166 167 168 |
# File 'lib/ruby_coded/chat/state.rb', line 162 def move_cursor_left return if @cursor_position <= 0 @cursor_position -= 1 update_input_scroll_offset mark_dirty! end |
#move_cursor_right ⇒ Object
170 171 172 173 174 175 176 |
# File 'lib/ruby_coded/chat/state.rb', line 170 def move_cursor_right return if @cursor_position >= @input_buffer.length @cursor_position += 1 update_input_scroll_offset mark_dirty! end |
#move_cursor_to_end ⇒ Object
186 187 188 189 190 191 192 |
# File 'lib/ruby_coded/chat/state.rb', line 186 def move_cursor_to_end return if @cursor_position == @input_buffer.length @cursor_position = @input_buffer.length update_input_scroll_offset mark_dirty! end |
#move_cursor_to_start ⇒ Object
178 179 180 181 182 183 184 |
# File 'lib/ruby_coded/chat/state.rb', line 178 def move_cursor_to_start return if @cursor_position == 0 @cursor_position = 0 update_input_scroll_offset mark_dirty! end |
#request_tui_suspend!(reason, **metadata) ⇒ Object
209 210 211 212 213 |
# File 'lib/ruby_coded/chat/state.rb', line 209 def request_tui_suspend!(reason, **) @tui_suspend_reason = reason @tui_suspend_metadata = mark_dirty! end |
#should_quit? ⇒ Boolean
92 93 94 |
# File 'lib/ruby_coded/chat/state.rb', line 92 def should_quit? @should_quit end |
#streaming? ⇒ Boolean
79 80 81 |
# File 'lib/ruby_coded/chat/state.rb', line 79 def streaming? @streaming end |
#tui_suspend_metadata ⇒ Object
219 220 221 |
# File 'lib/ruby_coded/chat/state.rb', line 219 def @tui_suspend_metadata || {} end |
#tui_suspend_requested? ⇒ Boolean
215 216 217 |
# File 'lib/ruby_coded/chat/state.rb', line 215 def tui_suspend_requested? !@tui_suspend_reason.nil? end |
#update_input_scroll_offset ⇒ Object
Updates the horizontal scroll offset of the input area so the cursor is always visible. Call this after every cursor / buffer change. visible_width is set by the renderer each frame via update_input_visible_width.
127 128 129 130 131 132 133 134 135 136 |
# File 'lib/ruby_coded/chat/state.rb', line 127 def update_input_scroll_offset visible = @input_visible_width || 0 return if visible <= 0 if @cursor_position < @input_scroll_offset @input_scroll_offset = @cursor_position elsif @cursor_position >= @input_scroll_offset + visible @input_scroll_offset = @cursor_position - visible + 1 end end |
#update_input_visible_width(width) ⇒ Object
Called by the renderer so the state knows how many characters fit on screen (inner width minus the prompt prefix).
140 141 142 |
# File 'lib/ruby_coded/chat/state.rb', line 140 def update_input_visible_width(width) @input_visible_width = width end |