Class: OllamaChat::MessageList
- Inherits:
-
Object
- Object
- OllamaChat::MessageList
- Includes:
- MessageFormat, Pager, Utils::ValueFormatter, Term::ANSIColor
- Defined in:
- lib/ollama_chat/message_list.rb
Overview
A collection class for managing chat messages with support for system prompts, paged output, and conversation history.
This class provides functionality for storing, retrieving, and displaying chat messages in a structured manner. It handles system prompts separately from regular user and assistant messages, supports pagination for displaying conversations, and offers methods for manipulating message history including clearing, loading, saving, and dropping exchanges. The class integrates with Kramdown::ANSI for formatted output.
Instance Attribute Summary collapse
-
#messages ⇒ Object
readonly
The messages attribute reader returns the messages set for this object, initializing it lazily if needed.
-
#system ⇒ Object
readonly
The system attribute reader returns the system prompt for the chat session.
-
#system_name ⇒ Object
readonly
The system_name attribute reader returns the name of the current system prompt.
Instance Method Summary collapse
-
#<<(message) ⇒ OllamaChat::MessageList
The << operator appends a message to the list of messages and returns self.
-
#clean_messages(messages: @messages, what: %i[ tools images ])) ⇒ Array<OllamaChat::Message>
Returns a new list of messages with the content replaced by their stripped versions.
-
#clean_messages!(messages: @messages, what: %i[ tools images ])) ⇒ OllamaChat::MessageList
Cleans the messages in the list by replacing them with stripped versions.
-
#clear(all: false) ⇒ OllamaChat::MessageList
The clear method removes all non-system messages from the message list.
-
#clear_images ⇒ OllamaChat::MessageList
Removes all images from all messages in the current list.
-
#compact! ⇒ OllamaChat::Compaction::Result?
Compacts the message list by summarizing old groups and inserting a single summary tool message at the cut point.
-
#compacted_estimate_tokens ⇒ OllamaChat::TokenEstimator::Estimate
Estimates the token and byte size of the messages that will actually be sent to the LLM (i.e.
compacted_messages). -
#compacted_messages ⇒ Array<OllamaChat::Message>
Returns the messages that will actually be sent to the LLM.
-
#config ⇒ Object
private
The config method provides access to the chat configuration object.
-
#construct_message_from_hash(hash) ⇒ OllamaChat::Message
private
Constructs a message instance from a hash, ensuring that a 'content' key is present even if it is nil.
-
#drop(n) ⇒ Integer
Removes the last
nconversation exchanges from the message list. -
#each_group(role: %w[ user assistant ],, tool: false) {|Array<OllamaChat::Message>| ... } ⇒ Enumerator
Groups messages by their
group_uuid, yielding an array of messages belonging to the same conversational turn (User -> Assistant -> Tools). -
#each_message(role: %w[ user assistant ],, tool: false) {|message| ... } ⇒ Enumerator?
Iterates over messages in the conversation, yielding those matching the specified roles.
-
#find_cut_point(start:, keep_recent_tokens:) ⇒ Integer?
Finds the message index at which compaction should cut.
-
#find_last(content: false) {|Message| ... } ⇒ OllamaChat::Message?
Find the last message that satisfies the supplied block.
-
#find_summary ⇒ OllamaChat::Message?
Finds the most recent summary message in the list.
-
#full_estimate_tokens ⇒ OllamaChat::TokenEstimator::Estimate
Estimates the token and byte size of the full stored message list (i.e.
@messages), using per-messagetoken_estimate. -
#initialize(chat) ⇒ MessageList
constructor
The initialize method sets up the message list for an OllamaChat session.
-
#last ⇒ OllamaChat::Message
Returns the last message from the conversation.
-
#list_conversation(last = nil, think_loud: @chat.think_loud.on?) ⇒ OllamaChat::MessageList
Displays the most recent messages from the conversation history.
-
#load_conversation(filename) ⇒ OllamaChat::MessageList
The load_conversation method loads a conversation from a file and populates the message list.
-
#load_conversation_jsonl(filename) ⇒ Array<OllamaChat::Message>
private
Loads a conversation from a JSONL (JSON Lines) file.
-
#message_text_for(message, think_loud: @chat.think_loud.on?) ⇒ String
private
The message_text_for method generates formatted text representation of a message including its role, content, thinking annotations, and associated images.
-
#parse_message_from_json(string) ⇒ OllamaChat::Message
private
Parse a message from a JSON string.
-
#read_conversation_jsonl(input) ⇒ OllamaChat::MessageList
Loads conversation messages from a JSONL (JSON Lines) input stream.
-
#save_conversation(filename, messages: @messages) ⇒ OllamaChat::MessageList
The save_conversation method saves the current conversation to a file.
-
#save_conversation_jsonl(filename, messages: @messages) ⇒ OllamaChat::MessageList
private
Saves the conversation to a JSONL (JSON Lines) file.
-
#set_system_prompt(system_name) ⇒ OllamaChat::MessageList
Sets the system prompt for the chat session.
-
#show_last(n = nil, pager: true, think_loud: @chat.think_loud.on?) ⇒ OllamaChat::MessageList?
Displays the most recent messages that were not authored by the user.
-
#show_system_prompt ⇒ self, NilClass
The show_system_prompt method displays the system prompt configured for the chat session.
-
#size ⇒ Integer
Returns the number of messages stored in the message list.
-
#speak_last(n = nil) ⇒ OllamaChat::MessageList?
Speaks the most recent assistant messages aloud via the session's voice handler (TTS or Say).
-
#sync ⇒ OllOamaChat::MessageList
private
Synchronizes the message list state with the active chat session.
-
#to_ary ⇒ Array
The to_ary method converts the message list into an array of OllamaChat::Message objects.
-
#write_conversation_jsonl(output, messages: @messages) ⇒ OllamaChat::MessageList
Writes each message in the conversation to the output as a JSON line.
Methods included from Utils::ValueFormatter
Methods included from Pager
#determine_pager_command, #use_pager
Methods included from MessageFormat
#chat, #display_sender, #message_type, #role_color, #role_template, #sender_name_displayed, #talk_annotate, #think_annotate
Constructor Details
#initialize(chat) ⇒ MessageList
The initialize method sets up the message list for an OllamaChat session.
40 41 42 43 |
# File 'lib/ollama_chat/message_list.rb', line 40 def initialize(chat) @chat = chat @messages = [] end |
Instance Attribute Details
#messages ⇒ Object (readonly)
The messages attribute reader returns the messages set for this object, initializing it lazily if needed.
The messages set is memoized, meaning it will only be created once per object instance and subsequent calls will return the same OllamaChat::MessageList instance.
64 65 66 |
# File 'lib/ollama_chat/message_list.rb', line 64 def @messages end |
#system ⇒ Object (readonly)
The system attribute reader returns the system prompt for the chat session.
48 49 50 |
# File 'lib/ollama_chat/message_list.rb', line 48 def system @system end |
#system_name ⇒ Object (readonly)
The system_name attribute reader returns the name of the current system prompt.
53 54 55 |
# File 'lib/ollama_chat/message_list.rb', line 53 def system_name @system_name end |
Instance Method Details
#<<(message) ⇒ OllamaChat::MessageList
The << operator appends a message to the list of messages and returns self.
299 300 301 302 |
# File 'lib/ollama_chat/message_list.rb', line 299 def <<() @messages << sync end |
#clean_messages(messages: @messages, what: %i[ tools images ])) ⇒ Array<OllamaChat::Message>
Returns a new list of messages with the content replaced by their stripped versions. This is used to create a "clean" version of the conversation for saving or displaying without mutating the original message objects.
410 411 412 413 414 415 416 417 418 419 |
# File 'lib/ollama_chat/message_list.rb', line 410 def (messages: @messages, what: %i[ tools images ]) what = Array(what).map(&:to_sym) .map do || = .dup .content = '' if what.include?(:tools) && .tool? .images = nil if what.include?(:images) .thinking = nil if what.include?(:thinking) end end |
#clean_messages!(messages: @messages, what: %i[ tools images ])) ⇒ OllamaChat::MessageList
Cleans the messages in the list by replacing them with stripped versions. This is a destructive (mutating) operation.
427 428 429 430 |
# File 'lib/ollama_chat/message_list.rb', line 427 def (messages: @messages, what: %i[ tools images ]) @messages = (messages:, what:) self end |
#clear(all: false) ⇒ OllamaChat::MessageList
The clear method removes all non-system messages from the message list.
285 286 287 288 289 290 291 292 |
# File 'lib/ollama_chat/message_list.rb', line 285 def clear(all: false) if all @messages.clear else @messages.delete_if { _1.role != 'system' } end sync end |
#clear_images ⇒ OllamaChat::MessageList
Removes all images from all messages in the current list.
747 748 749 750 751 752 |
# File 'lib/ollama_chat/message_list.rb', line 747 def clear_images @messages.each do || .images = nil end sync end |
#compact! ⇒ OllamaChat::Compaction::Result?
Compacts the message list by summarizing old groups and inserting a single summary tool message at the cut point.
Resolves the keep-recent token budget from the current model's context
length, finds the cut point, summarizes all groups before it (passing
any existing summary as previous_summary for iterative re-compaction),
then inserts the new summary at the cut point. Old groups remain in
the list for retrieval via lookup_group; the LLM context builder
skips them on the next call.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/ollama_chat/message_list.rb', line 143 def compact! ctx = @chat.current_context_length budget = @chat.compact_ratio_tokens(:keep_recent, ctx) existing_summary = find_summary start = @messages.each_with_index.find do |m, i| m.role == 'tool' && m.tool_name == 'summary' and break i + 1 end start ||= 0 start = start.clamp(0..(@messages.size - 1)) # Cut among post-summary groups; the old summary is excluded # from the budget window by +start+. cut = find_cut_point(start:, keep_recent_tokens: budget) return nil if cut.nil? || cut <= 1 candidates = @messages[start...cut] .reject { |m| m.role == 'system' } .reject { |m| m.role == 'tool' && m.tool_name == 'summary' } return nil if candidates.empty? cand_es = OllamaChat::TokenEstimator::Crude.new( candidates.sum { |m| m.content.to_s.bytesize } ).perform context_before = @chat.context_usage_colored context_filled_before = @chat.context_filled @chat.log(:info, 'Compaction: starting', data: { context_length: ctx, budget: budget, cut_index: cut, candidates: candidates.size, candidate_bytes: cand_es.bytes_formatted, candidate_tokens: cand_es.tokens_formatted, previous_summary: existing_summary ? 'yes' : 'no', }) summary_text, all_tool_entries = @chat.summarize_for_compaction( messages: candidates, previous_summary: existing_summary, ) compact_es = OllamaChat::TokenEstimator.estimate(summary_text.bytesize) @chat.log(:info, 'Compaction: summary generated', data: { summary_bytes: compact_es.bytes_formatted, summary_tokens: compact_es.tokens_formatted, }) summary_msg = OllamaChat::Message.new( role: 'tool', tool_name: 'summary', content: summary_text, tool_calls: all_tool_entries, ).initialize_group_uuid # Remove old summary (if any) and adjust cut for the shift. if existing_summary idx = @messages.index(existing_summary) @messages.delete_at(idx) cut -= 1 if idx < cut end @messages.insert(cut, summary_msg) @chat.log(:info, 'Compaction: done', data: { total_messages: @messages.size, summary_at: cut, }) sync OllamaChat::Compaction::Result.new( context_before:, context_after: @chat.context_usage_colored, context_filled_before: , context_filled_after: @chat.context_filled, candidates: candidates.size, candidate_size: "#{cand_es.bytes_formatted} / " \ "#{cand_es.tokens_formatted}", summary_size: "#{compact_es.bytes_formatted} / " \ "#{compact_es.tokens_formatted}", stored_total: @chat.conversation_length, ) end |
#compacted_estimate_tokens ⇒ OllamaChat::TokenEstimator::Estimate
Estimates the token and byte size of the messages that will actually
be sent to the LLM (i.e. compacted_messages).
When no summary message exists this is identical to the full list. When a summary is present, the pre-summary groups are excluded.
Uses per-message token_estimate which counts only text content
(and thinking, unless think_strip is enabled), excluding images
and metadata scaffolding that would inflate a raw serialization.
257 258 259 260 261 262 263 |
# File 'lib/ollama_chat/message_list.rb', line 257 def compacted_estimate_tokens strip = @chat.think_strip.on? bytes = .sum { _1.token_estimate(strip_thinking: strip).bytes } OllamaChat::TokenEstimator.estimate(bytes) end |
#compacted_messages ⇒ Array<OllamaChat::Message>
Returns the messages that will actually be sent to the LLM.
If no summary message exists, returns all messages (identical to
to_ary). If a summary is present, returns only the system prompt,
the summary, and everything after it — groups before the summary
are invisible to the model but remain in the list for
lookup_group retrieval.
235 236 237 238 239 240 241 242 243 |
# File 'lib/ollama_chat/message_list.rb', line 235 def idx = @messages.rindex do |m| m.role == 'tool' && m.tool_name == 'summary' end return to_ary if idx.nil? system = @messages.take_while { |m| m.role == 'system' } system + [@messages[idx]] + @messages[(idx + 1)..] end |
#config ⇒ Object (private)
The config method provides access to the chat configuration object.
759 760 761 |
# File 'lib/ollama_chat/message_list.rb', line 759 def config @chat.config end |
#construct_message_from_hash(hash) ⇒ OllamaChat::Message (private)
Constructs a message instance from a hash, ensuring that a 'content' key is present even if it is nil.
827 828 829 |
# File 'lib/ollama_chat/message_list.rb', line 827 def (hash) OllamaChat::Message.from_hash(hash | { 'content' => nil }) end |
#drop(n) ⇒ Integer
This method automatically synchronizes the message list with the session store.
Removes the last n conversation exchanges from the message list.
An exchange is typically defined as a pair of user and assistant messages. This method iterates backwards through the history and removes messages until the requested number of exchanges have been dropped. It will stop if it encounters a system message.
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 |
# File 'lib/ollama_chat/message_list.rb', line 603 def drop(n) n = n.to_i.clamp(1, Float::INFINITY) i = 0 m = 0 current_group = nil @messages.reverse_each do || .role == 'system' and next if current_group.nil? current_group = .group_uuid i += 1 elsif .group_uuid == current_group i += 1 else current_group = .group_uuid m += 1 if m < n i += 1 else break end end end i > 0 && m == 0 and m = 1 i.times do @messages.last.role == 'system' and next @messages.pop end @chat.feedback("Dropped the last #{m} exchanges.", type: :info) m ensure sync end |
#each_group(role: %w[ user assistant ],, tool: false) {|Array<OllamaChat::Message>| ... } ⇒ Enumerator
Groups messages by their group_uuid, yielding an array of messages
belonging to the same conversational turn (User -> Assistant -> Tools).
585 586 587 588 |
# File 'lib/ollama_chat/message_list.rb', line 585 def each_group(role: %w[ user assistant ], tool: false, &block) block or return enum_for(__method__, role:, tool:) (role:, tool:).group_by(&:group_uuid).values.each(&block) end |
#each_message(role: %w[ user assistant ],, tool: false) {|message| ... } ⇒ Enumerator?
Iterates over messages in the conversation, yielding those matching the specified roles.
357 358 359 360 361 362 363 364 365 366 367 368 |
# File 'lib/ollama_chat/message_list.rb', line 357 def (role: %w[ user assistant ], tool: false, &block) block or return enum_for(__method__, role:, tool:) role = Array(role) @messages.each do || role.include?(.role) or next !tool && .tool? and next yield end nil end |
#find_cut_point(start:, keep_recent_tokens:) ⇒ Integer?
Finds the message index at which compaction should cut.
Walks non-system message groups (from start onward) backward from
the tail, accumulating per-group token estimates. Returns the index of
the first message in the group whose addition causes the running total
to meet or exceed keep_recent_tokens. Messages from start up to
that index are candidates for summarization; messages from that index
onward are preserved.
If every group together still fits under the budget, the index of the
first group at or after start is returned (signalling a no-op cut).
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/ollama_chat/message_list.rb', line 92 def find_cut_point(start:, keep_recent_tokens:) groups = [] @messages.each_with_index do |msg, i| next if msg.role == 'system' next if i < start tokens = msg.token_estimate( strip_thinking: @chat.think_strip.on? ).tokens uuid = msg.group_uuid if last = groups.last and last[:uuid] == uuid last[:tokens] += tokens else groups << { uuid:, start: i, tokens: } end end return nil if groups.empty? accumulated = 0 groups.reverse_each do |group| accumulated += group[:tokens] return group[:start] if accumulated >= keep_recent_tokens end groups.first[:start] end |
#find_last(content: false) {|Message| ... } ⇒ OllamaChat::Message?
The method iterates in reverse order (reverse_each) so that the
most recent matching message is returned. It also respects the
content flag to skip empty messages, which is handy when the
chat history contains empty messages e. g. when tool calling.
Find the last message that satisfies the supplied block.
338 339 340 341 342 343 |
# File 'lib/ollama_chat/message_list.rb', line 338 def find_last(content: false, &block) @messages.reverse_each.find { |m| content and !m.content.present? and next block.(m) } end |
#find_summary ⇒ OllamaChat::Message?
Finds the most recent summary message in the list.
Scans backward from the tail for a message with
role == 'tool' and tool_name == 'summary'.
124 125 126 127 128 |
# File 'lib/ollama_chat/message_list.rb', line 124 def find_summary .reverse_each.find do |m| m.role == 'tool' && m.tool_name == 'summary' end end |
#full_estimate_tokens ⇒ OllamaChat::TokenEstimator::Estimate
Estimates the token and byte size of the full stored message
list (i.e. @messages), using per-message token_estimate.
Unlike Session#estimate_tokens which measures raw JSONL bytes
(including base64 images and JSON scaffolding), this counts only
text content and thinking (unless think_strip is enabled).
274 275 276 277 278 279 280 |
# File 'lib/ollama_chat/message_list.rb', line 274 def full_estimate_tokens strip = @chat.think_strip.on? bytes = @messages.sum { _1.token_estimate(strip_thinking: strip).bytes } OllamaChat::TokenEstimator.estimate(bytes) end |
#last ⇒ OllamaChat::Message
Returns the last message from the conversation.
308 309 310 |
# File 'lib/ollama_chat/message_list.rb', line 308 def last @messages.last end |
#list_conversation(last = nil, think_loud: @chat.think_loud.on?) ⇒ OllamaChat::MessageList
Displays the most recent messages from the conversation history.
This method prints a specified number of trailing messages to the console using the pager for better readability. Tool messages are automatically excluded from the output. If no count is provided, the entire conversation is displayed.
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 |
# File 'lib/ollama_chat/message_list.rb', line 445 def list_conversation(last = nil, think_loud: @chat.think_loud.on?) = @messages.reject(&:tool?) last = (last || .size).clamp(0, .size) = [-last..-1].to_ary use_pager do |output| = (messages:) = .( output: STDERR, label: 'Message', total: .size, message: @chat., ) .each do || output.puts (, think_loud:) + end end self end |
#load_conversation(filename) ⇒ OllamaChat::MessageList
The load_conversation method loads a conversation from a file and populates the message list.
376 377 378 379 380 381 382 383 384 385 386 387 388 |
# File 'lib/ollama_chat/message_list.rb', line 376 def load_conversation(filename) filename = Pathname.new(filename). unless filename.exist? @chat.feedback("File #{filename.to_s.inspect} doesn't exist. " \ "Choose another filename.", type: :warn) return end @messages = OllamaChat::Utils::JSONJSONLIO.new(filename).read( jsonl_transform: method(:parse_message_from_json), json_transform: method(:construct_message_from_hash) ).to_a sync end |
#load_conversation_jsonl(filename) ⇒ Array<OllamaChat::Message> (private)
Loads a conversation from a JSONL (JSON Lines) file.
796 797 798 799 800 |
# File 'lib/ollama_chat/message_list.rb', line 796 def load_conversation_jsonl(filename) filename.each_line.map { (_1) } end |
#message_text_for(message, think_loud: @chat.think_loud.on?) ⇒ String (private)
The message_text_for method generates formatted text representation of a message including its role, content, thinking annotations, and associated images. It applies color coding to different message roles and uses markdown parsing when enabled. The method also handles special formatting for thinking annotations and image references within the message.
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 |
# File 'lib/ollama_chat/message_list.rb', line 775 def (, think_loud: @chat.think_loud.on?) thinking = if think_loud think_annotate(think_loud:) do .thinking.full? { @chat.markdown.on? ? @chat.kramdown_ansi_parse(_1) : _1 } end end content = .content.full? { @chat.markdown.on? ? @chat.kramdown_ansi_parse(_1) : _1 } = display_sender() if thinking += [ ?:, thinking, talk_annotate(think_loud:) { content } ].compact. map(&:chomp) * ?\n else += ":\n#{content}" end end |
#parse_message_from_json(string) ⇒ OllamaChat::Message (private)
Parse a message from a JSON string.
818 819 820 |
# File 'lib/ollama_chat/message_list.rb', line 818 def (string) (JSON.parse(string)) end |
#read_conversation_jsonl(input) ⇒ OllamaChat::MessageList
Loads conversation messages from a JSONL (JSON Lines) input stream. Each line in the input is expected to be a valid JSON representation of a message. The method parses each line and adds the resulting message to the current conversation.
736 737 738 739 740 741 742 |
# File 'lib/ollama_chat/message_list.rb', line 736 def read_conversation_jsonl(input) @messages = OllamaChat::Utils::JSONJSONLIO.new('as.jsonl').read_io( input:, jsonl_transform: method(:parse_message_from_json) ).to_a self end |
#save_conversation(filename, messages: @messages) ⇒ OllamaChat::MessageList
The save_conversation method saves the current conversation to a file.
397 398 399 400 |
# File 'lib/ollama_chat/message_list.rb', line 397 def save_conversation(filename, messages: @messages) OllamaChat::Utils::JSONJSONLIO.new(filename).write(collection: ) self end |
#save_conversation_jsonl(filename, messages: @messages) ⇒ OllamaChat::MessageList (private)
Saves the conversation to a JSONL (JSON Lines) file.
807 808 809 810 811 812 |
# File 'lib/ollama_chat/message_list.rb', line 807 def save_conversation_jsonl(filename, messages: @messages) filename.open(?w) do |output| write_conversation_jsonl(output, messages:) end self end |
#set_system_prompt(system_name) ⇒ OllamaChat::MessageList
This method:
- Removes all existing system prompts from the message list
- Adds the new system prompt to the beginning of the message list if provided
- Handles edge cases such as clearing prompts when
systemisnilorfalse
Sets the system prompt for the chat session.
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 |
# File 'lib/ollama_chat/message_list.rb', line 650 def set_system_prompt(system_name) @system_name = system_name if system_name == 'model_default' system = @chat.model_default_system_prompt.to_s else system = @chat.prompt(system_name, context: 'system').to_s end @messages.reject! { |msg| msg.role == 'system' } templates_values = { persona: @chat.default_persona_profile, persona_name: @chat.default_persona_name.full?, runtime_info: (@chat.static_runtime_information if @chat.runtime_info.on?), } if new_system_prompt = system.full? { _1.to_s.named_placeholders_interpolate(templates_values) } @system = new_system_prompt @messages.unshift( OllamaChat::Message.new(role: 'system', content: self.system).initialize_group_uuid ) else @system = nil end sync end |
#show_last(n = nil, pager: true, think_loud: @chat.think_loud.on?) ⇒ OllamaChat::MessageList?
Displays the most recent messages that were not authored by the user.
This is particularly useful for quickly reviewing the assistant's last responses without having to scroll through the user's own input. Output is routed through the pager.
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 |
# File 'lib/ollama_chat/message_list.rb', line 479 def show_last(n = nil, pager: true, think_loud: @chat.think_loud.on?) n ||= 1 = @messages.reject { || .role == 'user' } n = n.clamp(0...size) n <= 0 and return = (last.content if last&.role == 'user') outputter = -> output do = [-n..-1].to_a = .( output: STDERR, label: 'Message', total: .size, message: @chat., ) .each do || output.puts (, think_loud:) + end ensure if = Kramdown::ANSI::Width.truncate( .inspect, length: Tins::Terminal.columns * 0.9 ) msg = <<~EOT ⚠️ Last message is actually a #{bold{'user message'}}, see: #{} You might want to /drop it or /regenerate it. EOT output.puts msg end end if pager use_pager(&outputter) else outputter.(STDOUT) end self end |
#show_system_prompt ⇒ self, NilClass
The show_system_prompt method displays the system prompt configured for the chat session.
It retrieves the system prompt from the @system instance variable, parses it using Kramdown::ANSI, and removes any trailing newlines. If the resulting string is empty, the method returns immediately.
Otherwise, it prints a formatted message to the console, including the configured system prompt and its length in characters.
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 |
# File 'lib/ollama_chat/message_list.rb', line 685 def show_system_prompt current_system = system.to_s es = OllamaChat::TokenEstimator.estimate(current_system) system_prompt = @chat.kramdown_ansi_parse(current_system). gsub(/\n+\z/, '').full? if system_prompt.blank? if current_system.present? system_prompt = current_system else return end end use_pager do |output| output.puts <<~EOT Configured system prompt is: #{system_prompt} System prompt name: #{bold{system_name}} System prompt length: 👾#{es.bytes_formatted} 🧩#{es.tokens_formatted} EOT end self end |
#size ⇒ Integer
Returns the number of messages stored in the message list.
69 70 71 |
# File 'lib/ollama_chat/message_list.rb', line 69 def size @messages.size end |
#speak_last(n = nil) ⇒ OllamaChat::MessageList?
Speaks the most recent assistant messages aloud via the session's voice handler (TTS or Say).
Each message is printed to STDOUT (without thinking content) and
then spoken on a background thread. The method blocks until each
utterance finishes before moving to the next unless interrupted by entering
C-c. If the last message in the list is a user message, a warning is
shown and no audio is produced.
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 |
# File 'lib/ollama_chat/message_list.rb', line 537 def speak_last(n = nil) unless @chat.voice.on? @chat.feedback('Voice output is disabled.', type: :info) return end n ||= 1 = @messages.reject { || .role == 'user' } n = n.clamp(0...size) n <= 0 and return = (last.content if last&.role == 'user') if @chat.feedback('Last message is a user message!', type: :warn) return end = [-n..-1].to_a = .( output: STDERR, label: 'Message', total: .size, message: @chat., ) .each do || content = .content.full? or next STDOUT.puts (, think_loud: false) speaker = @chat.speak(content, background: true) begin speaker&.wait_for_speaker rescue Interrupt @chat.feedback('Skipping voice output.', type: :info) end ensure + end self end |
#sync ⇒ OllOamaChat::MessageList (private)
Synchronizes the message list state with the active chat session.
This method triggers the persistence of the current messages into the
database via the associated @chat instance, ensuring that any
recent mutations (like adding, clearing, or dropping messages) are
immediately captured in the persistent session store.
840 841 842 843 |
# File 'lib/ollama_chat/message_list.rb', line 840 def sync @chat. self end |
#to_ary ⇒ Array
The to_ary method converts the message list into an array of OllamaChat::Message objects.
714 715 716 |
# File 'lib/ollama_chat/message_list.rb', line 714 def to_ary @messages.dup end |
#write_conversation_jsonl(output, messages: @messages) ⇒ OllamaChat::MessageList
Writes each message in the conversation to the output as a JSON line.
724 725 726 727 |
# File 'lib/ollama_chat/message_list.rb', line 724 def write_conversation_jsonl(output, messages: @messages) OllamaChat::Utils::JSONJSONLIO.new('as.jsonl').write_io(output:, collection: ) self end |