ollama_chat 0.0.83 → 0.0.85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +46 -0
  3. data/README.md +4 -2
  4. data/Rakefile +1 -1
  5. data/lib/ollama_chat/chat.rb +18 -40
  6. data/lib/ollama_chat/config_handling.rb +3 -3
  7. data/lib/ollama_chat/conversation.rb +6 -3
  8. data/lib/ollama_chat/dialog.rb +50 -5
  9. data/lib/ollama_chat/follow_chat.rb +35 -14
  10. data/lib/ollama_chat/input_content.rb +9 -0
  11. data/lib/ollama_chat/message_output.rb +2 -2
  12. data/lib/ollama_chat/model_handling.rb +1 -1
  13. data/lib/ollama_chat/ollama_chat_config/default_config.yml +2 -0
  14. data/lib/ollama_chat/personae_management.rb +3 -3
  15. data/lib/ollama_chat/server_socket.rb +1 -1
  16. data/lib/ollama_chat/switches.rb +1 -1
  17. data/lib/ollama_chat/tools/browse.rb +11 -4
  18. data/lib/ollama_chat/tools/concern.rb +1 -0
  19. data/lib/ollama_chat/tools/copy_to_clipboard.rb +2 -2
  20. data/lib/ollama_chat/tools/open_file_in_editor.rb +7 -6
  21. data/lib/ollama_chat/tools/paste_from_clipboard.rb +3 -2
  22. data/lib/ollama_chat/tools/paste_into_editor.rb +1 -1
  23. data/lib/ollama_chat/tools/patch_file.rb +5 -3
  24. data/lib/ollama_chat/tools/resolve_tag.rb +8 -3
  25. data/lib/ollama_chat/tools/retrieve_document_snippets.rb +118 -0
  26. data/lib/ollama_chat/tools/search_web.rb +10 -3
  27. data/lib/ollama_chat/tools/write_file.rb +10 -3
  28. data/lib/ollama_chat/tools.rb +1 -0
  29. data/lib/ollama_chat/utils/value_formatter.rb +10 -0
  30. data/lib/ollama_chat/utils.rb +3 -2
  31. data/lib/ollama_chat/version.rb +1 -1
  32. data/ollama_chat.gemspec +6 -6
  33. data/spec/ollama_chat/chat_spec.rb +12 -4
  34. data/spec/ollama_chat/tools/browse_spec.rb +9 -3
  35. data/spec/ollama_chat/tools/open_file_in_editor_spec.rb +2 -0
  36. data/spec/ollama_chat/tools/paste_from_clipboard_spec.rb +3 -2
  37. data/spec/ollama_chat/tools/resolve_tag_spec.rb +1 -1
  38. data/spec/ollama_chat/tools/retrieve_document_snippets_spec.rb +66 -0
  39. data/spec/ollama_chat/tools/search_web_spec.rb +10 -6
  40. metadata +9 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8947d6cdb437ce85afb32cb689bad1b16de54c2afb35da9f0eac7b1f1fff19df
4
- data.tar.gz: 3a03448c69d3f8883e11d5de11e9f44c455a4a8e95e2d93593d945dc99a0be63
3
+ metadata.gz: 4a9e61c3d789441bb11ee79fe2ec63f219cc8d938845a7dc6fe9c8f6d012d5bb
4
+ data.tar.gz: f453e609568a6df073fbaf865860fa1c919419b728c309ae0e19e97dc09d6b52
5
5
  SHA512:
6
- metadata.gz: 02e28130adb2881c44ea053035b5b39eb43025bf0e761063e6442a031b8b8acd88fe588850438ff0ae3c9fcf039ca4cff32bcb5abae4bcca4a349852a217580b
7
- data.tar.gz: 1055061e111fff2384020505b467b60ab30facc7fbf5733856061adc6834401a5414ba28a6716452b5b5fe2bb8ec5a77d54fc81d2e3ed065f0b9568847ce326c
6
+ metadata.gz: 24fadb41107daee4f625bb3d80743c8323624da545e6386b07ef25da5be3974afa2b0759a8db86d44eea04c9b156b92400e6a348d6bd9aae3dd71791939533bd
7
+ data.tar.gz: 7c43765e2da1f09781b6a8b0af70ea562cdec22fbdb4c92ab7f4eca033fdd3b9f79a55cbe3d7c3e91684c771a29cca95c76f26c44b7871cf9e142c3d0ca12179
data/CHANGES.md CHANGED
@@ -1,5 +1,51 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-03-29 v0.0.85
4
+
5
+ - Added `list` and `rename` subcommands to the `/collection` command, allowing
6
+ users to display available collections and rename them via the
7
+ `rename_collection` method in `lib/ollama_chat/dialog.rb`.
8
+ - Enhanced the `/collection` command to be optional; running `/collection`
9
+ without arguments now displays collection statistics by invoking the
10
+ `collection_stats` method.
11
+ - Updated `README.md` to reflect new command options and adjusted help text for
12
+ the `/collection` command.
13
+ - Modified tests in `spec/ollama_chat/chat_spec.rb` to accommodate new command
14
+ options and collection handling.
15
+ - Adjusted `regexp` and `complete` configurations in `lib/ollama_chat/chat.rb`
16
+ for the `/collection` command.
17
+ - Updated the `documentrix` dependency from **0.0.4** to **0.1.0**.
18
+ - Introduced progress feedback in `lib/ollama_chat/input_content.rb` within the
19
+ `provide_file_set_content` method, displaying `count/total` for batch
20
+ processing or just `count` for interactive mode.
21
+ - Optimized persona loading logic to skip setting a default persona if the
22
+ conversation already contains messages, while retaining fallbacks from
23
+ command-line options for new conversations.
24
+ - Fixed the warning condition in `OllamaChat::FollowChat` by correcting the
25
+ success check in `lib/ollama_chat/follow_chat.rb`.
26
+
27
+ ## 2026-03-26 v0.0.84
28
+
29
+ - Added `OllamaChat::Utils::ValueFormatter` with helper `format_bytes` in
30
+ `lib/ollama_chat/utils/value_formatter.rb`.
31
+ - Added `require 'ollama_chat/utils/value_formatter'` where needed.
32
+ - Updated `write_file`, `patch_file`, `paste_from_clipboard` to use
33
+ `format_bytes` for byte‑size messages.
34
+ - Implemented new tool `RetrieveDocumentSnippets` in
35
+ `lib/ollama_chat/tools/retrieve_document_snippets.rb` and its spec
36
+ `spec/ollama_chat/tools/retrieve_document_snippets_spec.rb`.
37
+ - Updated `default_config.yml` to enable `retrieve_document_snippets` by
38
+ default.
39
+ - Rewrote tool payloads to include a `message` key for `browse`, `search_web`,
40
+ `paste_from_clipboard`, `resolve_tag`, and others.
41
+ - `browse` now returns `"Opened \"<url>\" in browser."` or a failure message.
42
+ - Refactored `confirm?` in `lib/ollama_chat/dialog.rb` to accept keyword `yes:`
43
+ for a confirmation regex and display a coloured emoji matching the response
44
+ or timeout/default.
45
+ - Updated all calls to `confirm?` to use `yes: /y/i` syntax.
46
+ - Updated `lib/ollama_chat/message_output.rb` to add `yes:` keyword to
47
+ `confirm?` calls and refine the emoji shown when a file already exists.
48
+
3
49
  ## 2026-03-24 v0.0.83
4
50
 
5
51
  - Added timeout support to `Dialog#confirm?`: introduced optional `timeout:`
data/README.md CHANGED
@@ -209,8 +209,10 @@ The following commands can be given inside the chat, if prefixed by a `/`:
209
209
  ├──────────────────┼────────────────────┼──────────────────┼──────────────────────────────────────────────────────────┤
210
210
  │ /load │ │ path │ load conversation messages │
211
211
  ├──────────────────┼────────────────────┼──────────────────┼──────────────────────────────────────────────────────────┤
212
- │ /collection │ change│ │ change (default) collection or clear
213
- │ │ clear│ │
212
+ │ /collection │ change │ │ display, clear (current), change, list, or rename
213
+ │ │ clear │ │ collection
214
+ │ │ list │ │ │
215
+ │ │ rename │ │ │
214
216
  ├──────────────────┼────────────────────┼──────────────────┼──────────────────────────────────────────────────────────┤
215
217
  │ /persona │ add │ │ manage and load/play personae for roleplay │
216
218
  │ │ delete │ │ │
data/Rakefile CHANGED
@@ -42,7 +42,7 @@ GemHadar do
42
42
 
43
43
  dependency 'excon', '~> 1.0'
44
44
  dependency 'ollama-ruby', '~> 1.21'
45
- dependency 'documentrix', '>= 0.0.4'
45
+ dependency 'documentrix', '>= 0.1.0'
46
46
  dependency 'unix_socks', '~> 0.3'
47
47
  dependency 'rss', '~> 0.3'
48
48
  dependency 'term-ansicolor', '~> 1.11'
@@ -61,6 +61,7 @@ class OllamaChat::Chat
61
61
  include OllamaChat::ToolCalling
62
62
  include OllamaChat::ConfigHandling
63
63
  include OllamaChat::PersonaeManagement
64
+ include OllamaChat::Utils::ValueFormatter
64
65
 
65
66
  # Initializes a new OllamaChat::Chat instance with the given command-line
66
67
  # arguments.
@@ -478,11 +479,12 @@ class OllamaChat::Chat
478
479
 
479
480
  command(
480
481
  name: :collection,
481
- regexp: %r(^/collection(?:\s+(clear|change))?$),
482
- complete: [ 'collection', %w[ clear change ] ],
483
- help: 'change (default) collection or clear'
482
+ regexp: %r(^/collection(?:\s+(clear|change|list|rename))?$),
483
+ complete: [ 'collection', %w[ clear change list rename ] ],
484
+ optional: true,
485
+ help: 'display, clear (current), change, list, or rename collection'
484
486
  ) do |subcommand|
485
- case subcommand || 'change'
487
+ case subcommand
486
488
  when 'clear'
487
489
  loop do
488
490
  tags = @documents.tags.add('[EXIT]').add('[ALL]')
@@ -492,7 +494,7 @@ class OllamaChat::Chat
492
494
  STDOUT.puts "Exiting chooser."
493
495
  break
494
496
  when '[ALL]'
495
- if confirm?(prompt: '🔔 Are you sure? (y/n) ') =~ /y/i
497
+ if confirm?(prompt: '🔔 Are you sure? (y/n) ', yes: /y/i)
496
498
  @documents.clear
497
499
  STDOUT.puts "Cleared collection #{bold{@documents.collection}}."
498
500
  break
@@ -508,6 +510,14 @@ class OllamaChat::Chat
508
510
  end
509
511
  when 'change'
510
512
  choose_collection(@documents.collection)
513
+ when 'list'
514
+ current_collection = @documents.collection
515
+ puts @documents.collections.
516
+ map { |c| current_collection == c ? bold { c } : c }
517
+ when 'rename'
518
+ rename_collection(@documents.collection)
519
+ when nil
520
+ collection_stats
511
521
  end
512
522
  :next
513
523
  end
@@ -537,7 +547,7 @@ class OllamaChat::Chat
537
547
  end
538
548
  when 'edit'
539
549
  if result = edit_persona and
540
- confirm?(prompt: '🔔 Load new persona profile? (y/n) ') =~ /y/i
550
+ confirm?(prompt: '🔔 Load new persona profile? (y/n) ', yes: /y/i)
541
551
  then
542
552
  result
543
553
  else
@@ -868,7 +878,7 @@ class OllamaChat::Chat
868
878
  STDOUT.puts "Exiting chooser."
869
879
  break
870
880
  when '[ALL]'
871
- if confirm?(prompt: '🔔 Are you sure? (y/n) ') =~ /y/i
881
+ if confirm?(prompt: '🔔 Are you sure? (y/n) ', yes: /y/i)
872
882
  links.clear
873
883
  STDOUT.puts "Cleared all links in list."
874
884
  break
@@ -916,7 +926,7 @@ class OllamaChat::Chat
916
926
  @documents.clear
917
927
  STDOUT.puts "Cleared all tags."
918
928
  when 'all'
919
- if confirm?(prompt: '🔔 Are you sure to clear messages and collection? (y/n) ') =~ /y/i
929
+ if confirm?(prompt: '🔔 Are you sure to clear messages and collection? (y/n) ', yes: /y/i)
920
930
  messages.clear
921
931
  @documents.clear
922
932
  links.clear
@@ -1000,27 +1010,6 @@ class OllamaChat::Chat
1000
1010
  [ content, Documentrix::Utils::Tags.new(valid_tag: /\A#*([\w\]\[]+)/) ]
1001
1011
  end
1002
1012
 
1003
- if embedding.on? && content
1004
- records = @documents.find_where(
1005
- content.downcase.first(config.embedding.model.context_length),
1006
- tags:,
1007
- prompt: config.embedding.model.prompt?,
1008
- text_size: config.embedding.found_texts_size?,
1009
- text_count: config.embedding.found_texts_count?,
1010
- )
1011
- unless records.empty?
1012
- content << ?\n << JSON(
1013
- prompt: "Consider these snippets generated from retrieval when formulating your response!",
1014
- ollama_chat_retrieval_snippets: records.map { |r|
1015
- {
1016
- text: r.text,
1017
- tags: r.tags_set.map { |t| { name: t.to_s(link: false), source: t.source }.compact }
1018
- }
1019
- },
1020
- )
1021
- end
1022
- end
1023
-
1024
1013
  runtime_info.on? && content and
1025
1014
  content << ?\n << {
1026
1015
  ollama_chat_runtime_information: runtime_information
@@ -1056,17 +1045,6 @@ class OllamaChat::Chat
1056
1045
  raise
1057
1046
  end
1058
1047
  end
1059
- if embedding.on? && !records.empty?
1060
- STDOUT.puts "", records.map { |record|
1061
- link = if record.source =~ %r(\Ahttps?://)
1062
- record.source
1063
- else
1064
- 'file://%s' % File.expand_path(record.source)
1065
- end
1066
- [ link, ?# + record.tags.first ]
1067
- }.uniq.map { |l, t| hyperlink(l, t) }.join(' ')
1068
- debug and jj messages.to_ary
1069
- end
1070
1048
 
1071
1049
  case type
1072
1050
  when :socket_input
@@ -58,7 +58,7 @@ module OllamaChat::ConfigHandling
58
58
  unless diff_tool = OC::DIFF_TOOL?
59
59
  exit 1
60
60
  end
61
- if confirm?(prompt: '🔔 Do you want to fix the config? (y/n) ') =~ /y/i
61
+ if confirm?(prompt: '🔔 Do you want to fix the config? (y/n) ', yes: /y/i)
62
62
  system Shellwords.join([
63
63
  diff_tool,
64
64
  @ollama_chat_config.filename,
@@ -84,7 +84,7 @@ module OllamaChat::ConfigHandling
84
84
  # `ollama_chat` if desired.
85
85
  def edit_config
86
86
  if result = edit_file(@ollama_chat_config.filename)
87
- if confirm?(prompt: "🔔 Do you want to restart #{progname}? (y/n) ") =~ /y/i
87
+ if confirm?(prompt: "🔔 Do you want to restart #{progname}? (y/n) ", yes: /y/i)
88
88
  save_conversation(OC::XDG_CACHE_HOME + 'backup.json')
89
89
  save_history
90
90
  exec($0, *ARGV)
@@ -101,7 +101,7 @@ module OllamaChat::ConfigHandling
101
101
  # @example Restarting the app after confirmation
102
102
  # config.reload_config # => restarts if user answers "y"
103
103
  def reload_config
104
- if confirm?(prompt: "🔔 Do you want to restart #{progname}? (y/n) ") =~ /y/i
104
+ if confirm?(prompt: "🔔 Do you want to restart #{progname}? (y/n) ", yes: /y/i)
105
105
  save_conversation(OC::XDG_CACHE_HOME + 'backup.json')
106
106
  save_history
107
107
  exec($0, *ARGV)
@@ -26,9 +26,12 @@ module OllamaChat::Conversation
26
26
  # @example Save conversation with explicit filename
27
27
  # chat.save_conversation('conversations/2023-10-15_my_session.json')
28
28
  def save_conversation(filename)
29
- File.exist?(filename) &&
30
- confirm?(prompt: "🔔 File #{filename.to_s.inspect} already exists, overwrite? (y/n) ") !~ /y/i and
31
- return
29
+ if File.exist?(filename)
30
+ confirm?(
31
+ prompt: "🔔 File #{filename.to_s.inspect} already exists, overwrite? (y/n) ",
32
+ yes: /y/i
33
+ ) or return
34
+ end
32
35
  if messages.save_conversation(filename)
33
36
  STDOUT.puts "Saved conversation to #{filename.to_s.inspect}."
34
37
  else
@@ -36,22 +36,46 @@ module OllamaChat::Dialog
36
36
  #
37
37
  # @return [Object] the character entered by the user, or the `default` value
38
38
  # if a timeout occurs
39
- def confirm?(prompt:, timeout: nil, default: nil)
39
+ def confirm?(prompt:, timeout: nil, default: nil, yes: nil)
40
40
  return default if timeout&.zero?
41
41
  if prompt.include?('%s')
42
42
  prompt = prompt % (timeout ? ('timeout in %us' % timeout) : 'no timeout')
43
43
  end
44
44
  print prompt
45
45
  system 'stty raw'
46
+ keypress = nil
46
47
  c = if timeout
47
- ready = IO.select([ STDIN ], nil, nil, timeout)
48
- ready ? STDIN.getc : nil
48
+ keypress = !!IO.select([ STDIN ], nil, nil, timeout)
49
+ keypress ? STDIN.getc : nil
49
50
  else
51
+ keypress = true
50
52
  STDIN.getc
51
53
  end
52
54
  system 'stty cooked'
53
- puts
54
- c || default
55
+ answer = c || default
56
+ case
57
+ when yes.nil?
58
+ if keypress
59
+ puts "⌨️ #{answer}"
60
+ else
61
+ puts "⌛️ #{answer}"
62
+ end
63
+ answer
64
+ when answer =~ yes
65
+ if keypress
66
+ puts "✅ #{answer}"
67
+ else
68
+ puts "☑️ #{answer}"
69
+ end
70
+ answer
71
+ else
72
+ if keypress
73
+ puts "🚫 #{answer}"
74
+ else
75
+ puts "⌛️ #{answer}"
76
+ end
77
+ nil
78
+ end
55
79
  end
56
80
 
57
81
  private
@@ -111,6 +135,27 @@ module OllamaChat::Dialog
111
135
  info
112
136
  end
113
137
 
138
+ # Rename an existing collection to a new, user‑supplied name.
139
+ #
140
+ # This helper prompts the user to provide a new name for the collection
141
+ # identified by <code>current_collection</code>. It then renames the current
142
+ # collection to have the new_name and switches to it.
143
+ #
144
+ # @param current_collection [Symbol] the current collection name
145
+ def rename_collection(current_collection)
146
+ prompt = 'Rename collection %s to: ' % current_collection
147
+ if new_collection = ask?(prompt:).full?(:to_sym)
148
+ begin
149
+ @documents.rename_collection(new_collection)
150
+ STDOUT.puts "Renamed current collection #{current_collection} to #{new_collection}."
151
+ rescue
152
+ STDERR.puts "Renaming to #{new_collection} failed, it already exists."
153
+ end
154
+ else
155
+ STDOUT.puts "Renaming cancelled."
156
+ end
157
+ end
158
+
114
159
  # The change_system_prompt method allows the user to select or enter a new
115
160
  # system prompt for the chat session.
116
161
  # It provides an interactive chooser when multiple prompts match the given
@@ -11,6 +11,7 @@ class OllamaChat::FollowChat
11
11
  include Ollama::Handlers::Concern
12
12
  include Term::ANSIColor
13
13
  include OllamaChat::MessageFormat
14
+ include OllamaChat::Utils::ValueFormatter
14
15
 
15
16
  # Initializes a new instance of OllamaChat::FollowChat.
16
17
  #
@@ -131,9 +132,10 @@ class OllamaChat::FollowChat
131
132
  if @chat.tool_function(name).require_confirmation?
132
133
  prompt = "🔔 I want to execute tool %s\n%s\nConfirm? (y/n) " % [
133
134
  bold { name },
134
- italic { function },
135
+ italic { function },
135
136
  ]
136
- if @chat.confirm?(prompt:) =~ /y/i
137
+ prompt.gsub!('%', '%%')
138
+ if @chat.confirm?(prompt:, yes: /y/i)
137
139
  confirmed = :explicit
138
140
  else
139
141
  confirmed = :denied
@@ -153,7 +155,7 @@ class OllamaChat::FollowChat
153
155
  resolve: 'You **MUST** ask the user for instructions on how to proceed!!!',
154
156
  )
155
157
  STDOUT.printf(
156
- "\n%s Execution of tool %s denied by user.\n", ?🚫, bold { name }
158
+ "\n%s Execution of tool %s denied by user.\n\n", ?🚫, bold { name }
157
159
  )
158
160
  @chat.log(:warn,"Execution of tool %s was denied by user!" % name)
159
161
  else
@@ -169,24 +171,43 @@ class OllamaChat::FollowChat
169
171
  @chat.log(:info, "Execution of tool %s was implicitly confirmed." % name)
170
172
  end
171
173
  end
172
- begin
173
- data = JSON.parse(result)
174
- @chat.log(:info, JSON.pretty_generate(data))
175
- rescue
176
- @chat.log(:info, result)
177
- end
174
+
178
175
  @chat.tool_call_results[name] = result
176
+
177
+ data = nil
178
+ message = begin
179
+ data = JSON.parse(result)
180
+ @chat.log(:info, JSON.pretty_generate(data))
181
+ data['message']
182
+ rescue
183
+ @chat.log(:info, result)
184
+ nil
185
+ end
186
+ warn =
187
+ begin
188
+ !!data.ask_and_send(:[], 'error') || data.ask_and_send(:[], 'success') == false
189
+ rescue
190
+ false
191
+ end
192
+
179
193
  tools_used[name] = {
180
- 'size' => Tins::Unit.format(result.to_s.size, unit: ?B, prefix: 1024, format: '%.1f %U'),
181
- 'duration' => Tins::Duration.new(Time.now - start).to_s,
194
+ message:,
195
+ warn: ,
196
+ size: format_bytes(result.to_s.size),
197
+ duration: Tins::Duration.new(Time.now - start).to_s,
182
198
  }
183
199
  end
184
200
 
185
201
  if tools_used.full?
186
202
  infobar.reset
187
203
  tools_used.each do |name, info|
188
- puts "🔧 Tool functions #{name} returned result:",
189
- info.to_yaml.sub(/\A---\s*\n/, '').gsub(/^/, ' '), ""
204
+ feedback_message = if info[:message]
205
+ "\n%s %s\n\n" % [ info[:warn] ? '⚠️' : '💡', info[:message] ]
206
+ end
207
+ puts <<~EOT.strip, ""
208
+ 🔧 Tool functions #{name} returned result (#{info[:size]} in #{info[:duration]}).
209
+ #{feedback_message}
210
+ EOT
190
211
  timeout = @chat.tool_function(name).result_display_timeout?
191
212
  @chat.confirm?(prompt: '⏎ Press any key to continue (%s). ', timeout:)
192
213
  end
@@ -304,7 +325,7 @@ class OllamaChat::FollowChat
304
325
  #
305
326
  # This method delegates to the messages object's show_last method, which
306
327
  # displays the most recent non-user message in the conversation history.
307
- # It is typically used to provide feedback to the user about the last
328
+ # It is typically used to provide message to the user about the last
308
329
  # response from the assistant.
309
330
  # @return [ nil, String ] the pager command or nil if no paging was
310
331
  # performed.
@@ -161,7 +161,16 @@ module OllamaChat::InputContent
161
161
  # @yield [filename] the block that processes each filename
162
162
  # @return [String] the concatenated result of the block applied to each file
163
163
  def provide_file_set_content(patterns, all: false, &block)
164
+ total = 0
165
+ all and file_set_each(patterns, all:) { total += 1 }
166
+ count = 0
164
167
  file_set_each(patterns, all:).each_with_object('') do |filename, result|
168
+ count += 1
169
+ if all
170
+ STDOUT.puts "Handling File (#{bold{count}}/#{bold{total}}):"
171
+ else
172
+ STDOUT.puts "Handling File (#{bold{count}}):"
173
+ end
165
174
  result << ("%s:\n\n%s\n\n" % [ filename, block.(filename) ])
166
175
  end.full?
167
176
  end
@@ -3,7 +3,7 @@
3
3
  # This module encapsulates methods for piping assistant responses to command
4
4
  # standard input and writing assistant responses to files. It handles the
5
5
  # mechanics of sending output to external processes or saving content to disk
6
- # while providing appropriate error handling and user feedback.
6
+ # while providing appropriate error handling and user message.
7
7
  #
8
8
  # @example Piping a response to a command
9
9
  # chat.pipe('cat > output.txt')
@@ -83,7 +83,7 @@ module OllamaChat::MessageOutput
83
83
  def attempt_to_write_file(filename, message)
84
84
  path = Pathname.new(filename.to_s).expand_path
85
85
  if !path.exist? ||
86
- confirm?(prompt: "🔔 File #{path.to_s.inspect} already exists, overwrite? (y/n) ") =~ /y/i
86
+ confirm?(prompt: "🔔 File #{path.to_s.inspect} already exists, overwrite? (y/n) ", yes: /y/i)
87
87
  then
88
88
  File.open(path, ?w) do |output|
89
89
  output.write(message.content)
@@ -95,7 +95,7 @@ module OllamaChat::ModelHandling
95
95
  # that combines the model name and formatted size
96
96
  private def model_with_size(model)
97
97
  formatted_size = Term::ANSIColor.bold {
98
- Tins::Unit.format(model.size, unit: ?B, prefix: 1024, format: '%.1f %U')
98
+ format_bytes(model.size)
99
99
  }
100
100
  SearchUI::Wrapper.new(model.name, display: "#{model.name} #{formatted_size}")
101
101
  end
@@ -264,3 +264,5 @@ tools:
264
264
  require_confirmation: true
265
265
  allowed:
266
266
  - './tmp'
267
+ retrieve_document_snippets:
268
+ default: true
@@ -40,7 +40,7 @@ module OllamaChat::PersonaeManagement
40
40
  # playing the persona file if it exists.
41
41
  def setup_persona_from_opts
42
42
  @default_persona and return
43
- @opts[?c] and return
43
+ @messages.size > 0 and return
44
44
  if persona = @opts[?p].full? { Pathname.new(_1) }
45
45
  if persona.extname == '.md'
46
46
  pathname = persona
@@ -173,9 +173,9 @@ module OllamaChat::PersonaeManagement
173
173
  STDOUT.puts "Deleting '#{bold{persona.sub_ext('')}}'..."
174
174
  STDOUT.puts "Backup will be saved to: #{backup_pathname}"
175
175
 
176
- if confirm?(prompt: "🔔 Are you sure? (y/n) ") =~ /y/i
176
+ if confirm?(prompt: "🔔 Are you sure? (y/n) ", yes: /y/i)
177
177
  FileUtils.mv pathname, backup_pathname
178
- STDOUT.puts "Persona #{bold{persona.sub_ext('')}} deleted successfully"
178
+ STDOUT.puts "Persona #{bold{persona.sub_ext('')}} deleted successfully"
179
179
  {
180
180
  success: true,
181
181
  persona: persona.sub_ext(''),
@@ -117,7 +117,7 @@ module OllamaChat::ServerSocket
117
117
  running using the same directory or that a previous process left a stale
118
118
  socket file.
119
119
  EOT
120
- if confirm?(prompt: '🔔 Do you want to remove the existing socket file and continue? (y/n) ') =~ /y/i
120
+ if confirm?(prompt: '🔔 Do you want to remove the existing socket file and continue? (y/n) ', yes: /y/i)
121
121
  FileUtils.rm_f socket_path
122
122
  retry
123
123
  else
@@ -51,7 +51,7 @@ module OllamaChat::Switches
51
51
  #
52
52
  # The Switch class provides a simple way to manage boolean configuration
53
53
  # options with methods to toggle, set, and query the current state. It
54
- # includes messaging capabilities to provide feedback when the state changes.
54
+ # includes messaging capabilities to provide message when the state changes.
55
55
  #
56
56
  # @example Creating and using a switch
57
57
  # switch = Switch.new(value: false, msg: { true => 'Enabled', false => 'Disabled' })
@@ -26,9 +26,9 @@ class OllamaChat::Tools::Browse
26
26
  function: Tool::Function.new(
27
27
  name:,
28
28
  description: <<~EOT,
29
- Launch external viewer – Opens an HTTP/HTTPS link (or local file) in
30
- the system’s web/browser app. Use when you want to hand off a page
31
- for human inspection; no return value is expected.
29
+ Launch external viewer – Opens an HTTP/HTTPS link (or local file
30
+ path) in the system’s web/browser app. Use when you want to hand off
31
+ a page for human inspection; no return value is expected.
32
32
  EOT
33
33
  parameters: Tool::Function::Parameters.new(
34
34
  type: 'object',
@@ -58,10 +58,17 @@ class OllamaChat::Tools::Browse
58
58
  def execute(tool_call, **opts)
59
59
  url = tool_call.function.arguments.url
60
60
  result = browse_url(url)
61
+
62
+ message = if result.success?
63
+ "Opened #{url.to_s.inspect} in browser."
64
+ else
65
+ "Could not open #{url.to_s.inspect} in browser."
66
+ end
67
+
61
68
  {
62
69
  success: result.success?,
63
70
  exitstatus: result.exitstatus,
64
- message: 'opening URL/file',
71
+ message: ,
65
72
  url: ,
66
73
  }.to_json
67
74
  rescue => e
@@ -6,6 +6,7 @@
6
6
  # functionality to integrate tools into the chat system's tool registry.
7
7
  module OllamaChat::Tools::Concern
8
8
  extend Tins::Concern
9
+ include OllamaChat::Utils::ValueFormatter
9
10
 
10
11
  included do
11
12
  include Ollama
@@ -56,8 +56,8 @@ class OllamaChat::Tools::CopyToClipboard
56
56
  "The provided text has been successfully copied to the system clipboard."
57
57
  end
58
58
  {
59
- success: true,
60
- message:,
59
+ success: true,
60
+ message: ,
61
61
  }.to_json
62
62
  rescue => e
63
63
  {
@@ -73,15 +73,16 @@ class OllamaChat::Tools::OpenFileInEditor
73
73
  end
74
74
 
75
75
  chat.vim.open_file(file_path, start_line, end_line)
76
- if end_line
77
- result_msg = "Opened #{file_path} and selected range #{start_line}-#{end_line}"
78
- else
79
- result_msg = "Opened #{file_path} at line #{start_line}"
80
- end
76
+ message =
77
+ if end_line
78
+ "Opened #{file_path.to_s.inspect} and selected range #{start_line}-#{end_line}"
79
+ else
80
+ "Opened #{file_path.to_s.inspect} at line #{start_line}"
81
+ end
81
82
 
82
83
  {
83
84
  success: true,
84
- message: result_msg,
85
+ message: ,
85
86
  path: file_path,
86
87
  start_line: start_line,
87
88
  end_line: end_line,
@@ -43,10 +43,11 @@ class OllamaChat::Tools::PasteFromClipboard
43
43
 
44
44
  # Use the chat instance's clipboard paste functionality
45
45
  content = chat.perform_paste_from_clipboard
46
+ message = "Pasted #{format_bytes(content.to_s.size)} of content."
46
47
 
47
48
  {
48
- success: true,
49
- message: "Content pasted from clipboard",
49
+ success: true,
50
+ message: ,
50
51
  content:
51
52
  }.to_json
52
53
  rescue => e
@@ -53,7 +53,7 @@ class OllamaChat::Tools::PasteIntoEditor
53
53
  end
54
54
 
55
55
  {
56
- success: true,
56
+ success: true,
57
57
  message: ,
58
58
  }.to_json
59
59
  rescue => e
@@ -68,9 +68,11 @@ class OllamaChat::Tools::PatchFile
68
68
  path = assert_valid_path(path, config.tools.functions.patch_file.allowed?, check_file: true)
69
69
 
70
70
  result = apply_patch(path, diff_content)
71
- message = result[:success] ?
72
- "Successfully applied patch to #{path.to_s.inspect}." :
73
- "Failed to apply patch to file #{path.to_s.inspect}."
71
+ message = if result[:success]
72
+ "Successfully applied patch to #{path.to_s.inspect}."
73
+ else
74
+ "Failed to apply patch to file #{path.to_s.inspect}."
75
+ end
74
76
  (result | {
75
77
  path: path.to_s,
76
78
  message: ,