ollama_chat 0.0.92 → 0.0.94

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 65c990826623b9e3d8548c69bf01b715dd9597e451a5a4b480e4e09d48249113
4
- data.tar.gz: bdf07bb49531d867d8be7b2cd8f2c5537867b9a2d297d939f123593952a77507
3
+ metadata.gz: 45c44a082f13dac46e85a681f8dcbda705075155d43f39b8a1b1ba37cf75db18
4
+ data.tar.gz: 7d45a03f43c1b916874e0d594ca5855bfb45c0883ee41c6e9dad355f73917fc6
5
5
  SHA512:
6
- metadata.gz: 2ee0222c25f838f0c2436e71b9d9d8aa630fe45c58f7dc592c850e3dbe6b85ec0461883b05d735aab74c664fe8516ef13adecd33c18b0fd5b8571feba6827e65
7
- data.tar.gz: a7ae3f192f4bead676495ee4053596fd5253e1394e5e2f1a5617f621d201e98d6dddd866c32b9d025a1b22cd3201fdf3be09a5399dab18c462c8bdc4d412b37f
6
+ metadata.gz: c7c48d1cfc04418d6d2d036be1807768bfc971415f87453671738d187ff7d24a392d06bbbba6845c2e65ad3cc4a6bf41396e83e8920f61d6eb1a34fee1c9b630
7
+ data.tar.gz: 2e4501051294b49ba0805970ee87934e8b817aeadcdf9326f06460c8a9d1e8cfecc050bff83c02c10f3519ff7207a303383febe91d487eda82cf82e1f6778e41
data/CHANGES.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-06-22 v0.0.94
4
+
5
+ ### Added
6
+
7
+ - Created a `LICENSE` file and updated the `README.md` to include a link to the
8
+ MIT license.
9
+ - Added comprehensive test coverage for tool calling in
10
+ `spec/ollama_chat/tool_calling_spec.rb`.
11
+
12
+ ### Changed
13
+
14
+ - Improved tool calling logic by utilizing the `tools_support` reader and
15
+ ensuring allowed paths are indexed by string keys via `.to_s`.
16
+ - Synchronized search feedback prompts across
17
+ `lib/ollama_chat/web_searching.rb`, `lib/ollama_chat/rag_handling.rb`, and
18
+ `lib/ollama_chat/state_selectors.rb` using the `%s` format specifier.
19
+ - Updated usage examples in `lib/ollama_chat/utils/chooser.rb` to include the
20
+ `%s` specifier.
21
+ - Updated prompt expectations in `spec/ollama_chat/state_selectors_spec.rb`.
22
+ - Added `LICENSE` and `spec/ollama_chat/tool_calling_spec.rb` to the gem
23
+ specification files.
24
+
25
+ ## 2026-06-21 v0.0.93
26
+
27
+ ### Added
28
+
29
+ - Integrated search feedback into interactive chooser prompts across several modules:
30
+ - `lib/ollama_chat/commands.rb` (added `%s` format specifier)
31
+ - `lib/ollama_chat/favourites_management.rb`
32
+ - `lib/ollama_chat/input_content.rb` (file import selector)
33
+ - `lib/ollama_chat/model_handling.rb` (model and profile selection)
34
+ - `lib/ollama_chat/personae_management.rb`
35
+ - `lib/ollama_chat/prompt_management.rb` (template selectors)
36
+ - `lib/ollama_chat/system_prompt_management.rb`
37
+ - `lib/ollama_chat/tool_calling.rb` (tool capability selection)
38
+ - `lib/ollama_chat/session_management.rb` (chat session selector)
39
+
40
+ ### Changed
41
+
42
+ - Updated `ollama-ruby` dependency to **1.22.0** in the `Rakefile` and
43
+ `ollama_chat.gemspec`.
44
+ - Synchronized expectations in `spec/ollama_chat/input_content_spec.rb` to
45
+ match updated prompt formats.
46
+
3
47
  ## 2026-06-19 v0.0.92
4
48
 
5
49
  ### New Features
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Florian Frank
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -273,4 +273,4 @@ The homepage of this app is located at
273
273
 
274
274
  ## License
275
275
 
276
- This software is licensed under the <i>MIT</i> license.
276
+ This software is licensed under the [MIT License](./LICENSE).
data/Rakefile CHANGED
@@ -39,7 +39,7 @@ GemHadar do
39
39
  )
40
40
 
41
41
  dependency 'excon', '~> 1.0'
42
- dependency 'ollama-ruby', '~> 1.21'
42
+ dependency 'ollama-ruby', '~> 1.22'
43
43
  dependency 'documentrix', '>= 0.6.0'
44
44
  dependency 'unix_socks', '>= 0.4'
45
45
  dependency 'rss', '~> 0.3'
@@ -164,7 +164,7 @@ module OllamaChat::Commands
164
164
  info_system_prompt
165
165
  when 'reset'
166
166
  if prompt = choose_system_prompt(
167
- prompt: 'Which system law needs to be restored to its origin? '
167
+ prompt: 'Which system law needs to be restored to its origin? %s'
168
168
  )
169
169
  then
170
170
  if reset_system_prompt_to_default(prompt.name)
@@ -437,7 +437,7 @@ module OllamaChat::Commands
437
437
  when 'reset'
438
438
  if prompt = choose_prompt(
439
439
  default: true,
440
- prompt: 'Which prompt needs to be restored to its origin? '
440
+ prompt: 'Which prompt needs to be restored to its origin? %s'
441
441
  )
442
442
  then
443
443
  if reset_prompt_to_default(prompt.name)
@@ -450,7 +450,7 @@ module OllamaChat::Commands
450
450
  prompt = suggest_prompts and next prompt
451
451
  when nil
452
452
  opts = go_command('e', opts)
453
- if prompt = choose_prompt(prompt: 'Which template shall guide the next response? ').full?(&:to_s)
453
+ if prompt = choose_prompt(prompt: 'Which template shall guide the next response? %s').full?(&:to_s)
454
454
  if opts[?e]
455
455
  prompt = edit_text(prompt)
456
456
  next prompt
@@ -51,7 +51,7 @@ module OllamaChat::FavouritesManagement
51
51
  return
52
52
  end
53
53
  to_select.unshift('[EXIT]')
54
- case chosen = choose_entry(to_select, prompt: 'Select an item to mark as favourite: ')
54
+ case chosen = choose_entry(to_select, prompt: 'Select an item to mark as favourite: %s')
55
55
  when '[EXIT]', nil
56
56
  STDOUT.puts "Cancelled."
57
57
  return
@@ -77,7 +77,7 @@ module OllamaChat::FavouritesManagement
77
77
  to_select = models::Favourite.where(context: type).map(&:name)
78
78
  to_select = all_things.select { to_select.member?(_1.value) }
79
79
  to_select = [ '[EXIT]' ] + to_select
80
- case chosen = choose_entry(to_select, prompt: 'Select a favourite to remove: ')
80
+ case chosen = choose_entry(to_select, prompt: 'Select a favourite to remove: %s')
81
81
  when '[EXIT]', nil
82
82
  STDOUT.puts "Cancelled."
83
83
  return
@@ -55,7 +55,7 @@ module OllamaChat::InputContent
55
55
  files = patterns.flat_map { Pathname.glob(_1) }
56
56
  files = files.reject { chosen&.member?(_1.expand_path) }.select { _1.file? }
57
57
  files.unshift('[EXIT]')
58
- case chosen_file = choose_entry(files, prompt: 'Select a file to import: ')
58
+ case chosen_file = choose_entry(files, prompt: 'Select a file to import: %s')
59
59
  when '[EXIT]', nil
60
60
  STDOUT.puts "Exiting chooser."
61
61
  return
@@ -163,7 +163,7 @@ module OllamaChat::ModelHandling
163
163
  def choose_profile_for_model(model_name)
164
164
  profiles = models::ModelOptions.where(model_name:).order(:profile).map(&:profile)
165
165
  profiles = [ '[EXIT]' ] + profiles
166
- case chosen = choose_entry(profiles, prompt: "Choose profile for #{bold{model_name}}: ")
166
+ case chosen = choose_entry(profiles, prompt: "Choose profile for #{bold{model_name}}: %s")
167
167
  when '[EXIT]', nil
168
168
  STDOUT.puts "Cancelled."
169
169
  return
@@ -366,7 +366,7 @@ module OllamaChat::ModelHandling
366
366
  elsif cli_model == ''
367
367
  choose_entry(
368
368
  models,
369
- prompt: "Which digital oracle shall we consult?"
369
+ prompt: "Which digital oracle shall we consult? %s"
370
370
  )&.value || current_model
371
371
  else
372
372
  cli_model || current_model
@@ -91,7 +91,7 @@ module OllamaChat::PersonaeManagement
91
91
  # @return [String, nil] The name of the persona that was set as default,
92
92
  # or nil if the selection was cancelled or no persona was chosen.
93
93
  def set_default_persona
94
- if persona = choose_persona(none: true, prompt: 'Who would you like to talk to today? ')
94
+ if persona = choose_persona(none: true, prompt: 'Who would you like to talk to today? %s')
95
95
  set_default_persona_name(persona)
96
96
  end
97
97
  end
@@ -214,7 +214,7 @@ module OllamaChat::PersonaeManagement
214
214
  # @return [String] A JSON object with deletion status on success,
215
215
  # or nil if persona was not selected or deletion was cancelled
216
216
  def delete_persona
217
- if persona = choose_persona(prompt: 'Which persona is no longer needed? ')
217
+ if persona = choose_persona(prompt: 'Which persona is no longer needed? %s')
218
218
  pathname = persona_name_to_pathname(persona)
219
219
  backup_pathname = persona_backup_pathname(persona)
220
220
  if pathname.exist?
@@ -245,7 +245,7 @@ module OllamaChat::PersonaeManagement
245
245
  #
246
246
  # @return [String, nil] persona name or nil if cancelled
247
247
  def edit_persona
248
- if persona = choose_persona(prompt: 'Which persona needs some polishing? ')
248
+ if persona = choose_persona(prompt: 'Which persona needs some polishing? %s')
249
249
  pathname = persona_name_to_pathname(persona)
250
250
  old_content = pathname.read
251
251
  if edit_file(pathname)
@@ -265,7 +265,7 @@ module OllamaChat::PersonaeManagement
265
265
  # @return [String, nil] the filesystem path of the selected persona,
266
266
  # or nil if the selection was cancelled.
267
267
  def select_persona_path
268
- persona = choose_persona(prompt: "Which persona's path do you need? ") or return
268
+ persona = choose_persona(prompt: "Which persona's path do you need? %s") or return
269
269
  path = persona_name_to_pathname(persona).to_s
270
270
  perform_copy_to_clipboard(text: path, edit: false)
271
271
  @prefill_prompt = path
@@ -279,7 +279,7 @@ module OllamaChat::PersonaeManagement
279
279
  # location using `File.write`. This ensures a safe copy is preserved before
280
280
  # any modifications are made to the original file.
281
281
  def backup_persona
282
- if persona = choose_persona(prompt: 'Which persona should be safely archived? ')
282
+ if persona = choose_persona(prompt: 'Which persona should be safely archived? %s')
283
283
  pathname = persona_name_to_pathname(persona)
284
284
  old_content = pathname.read
285
285
  backup_pathname = persona_backup_pathname(persona)
@@ -317,7 +317,7 @@ module OllamaChat::PersonaeManagement
317
317
  #
318
318
  # Shows the persona's profile using kramdown formatting with ansi parsing.
319
319
  def info_persona
320
- if persona = choose_persona(prompt: 'Who would you like to learn more about? ')
320
+ if persona = choose_persona(prompt: 'Who would you like to learn more about? %s')
321
321
  description = persona_description(persona) or return
322
322
  use_pager do |output|
323
323
  output.puts kramdown_ansi_parse(description)
@@ -378,7 +378,7 @@ module OllamaChat::PersonaeManagement
378
378
  # (default: 'Select a persona: ')
379
379
  # @return [String, Symbol, nil] The selected persona name, :none, or nil if
380
380
  # user exits
381
- def choose_persona(chosen: nil, none: false, prompt: 'Select a persona: ')
381
+ def choose_persona(chosen: nil, none: false, prompt: 'Select a persona: %s')
382
382
  personae_list = available_personae_names.
383
383
  reject { chosen&.member?(_1) }
384
384
  if personae_list.empty?
@@ -405,7 +405,7 @@ module OllamaChat::PersonaeManagement
405
405
  def load_personae
406
406
  chosen = Set[]
407
407
  choose_with_state do
408
- while persona = choose_persona(chosen: chosen, prompt: 'Who else should join the conversation? ')
408
+ while persona = choose_persona(chosen: chosen, prompt: 'Who else should join the conversation? %s')
409
409
  persona == :none and next
410
410
  chosen << persona
411
411
  end
@@ -534,7 +534,7 @@ module OllamaChat::PersonaeManagement
534
534
  # @return [self, nil] returns self on success, or nil if the operation was
535
535
  # cancelled during persona selection or name entry.
536
536
  def duplicate_persona
537
- persona = choose_persona(prompt: 'Which persona shall serve as the blueprint? ') or return
537
+ persona = choose_persona(prompt: 'Which persona shall serve as the blueprint? %s') or return
538
538
  pathname = persona_name_to_pathname(persona)
539
539
  new_persona_name = determine_valid_new_name_for_persona('to ducplicate as') or return
540
540
  new_pathname = persona_name_to_pathname(new_persona_name)
@@ -586,7 +586,7 @@ module OllamaChat::PersonaeManagement
586
586
  # @return [self, nil] returns self if the export was successful, or nil if
587
587
  # the process was cancelled during persona selection or filename entry.
588
588
  def export_persona
589
- persona = choose_persona(prompt: 'Which persona are you taking with you? ') or return
589
+ persona = choose_persona(prompt: 'Which persona are you taking with you? %s') or return
590
590
  pathname = persona_name_to_pathname(persona)
591
591
  content = pathname.read
592
592
  STDOUT.puts kramdown_ansi_parse(
@@ -30,7 +30,7 @@ module OllamaChat::PromptManagement
30
30
  #
31
31
  # @return [OllamaChat::Database::Models::Prompt, nil] the selected prompt
32
32
  # model, or nil if the user chooses '[EXIT]' or cancels the selection.
33
- def choose_prompt(default: nil, prompt: 'Select a prompt template: ')
33
+ def choose_prompt(default: nil, prompt: 'Select a prompt template: %s')
34
34
  prompts = all_prompts(default: default)
35
35
  prompts.unshift('[EXIT]')
36
36
  case chosen = choose_entry(prompts, prompt:)
@@ -46,7 +46,7 @@ module OllamaChat::PromptManagement
46
46
  #
47
47
  # @return [self, nil] the current context on success, or nil if cancelled
48
48
  def info_prompt
49
- if prompt = choose_prompt(prompt: 'Which blueprint would you like to inspect? ')
49
+ if prompt = choose_prompt(prompt: 'Which blueprint would you like to inspect? %s')
50
50
  use_pager do |output|
51
51
  output.puts kramdown_ansi_parse(<<~EOT)
52
52
  # Prompt #{prompt.name}
@@ -99,7 +99,7 @@ module OllamaChat::PromptManagement
99
99
  # Interactively selects an existing non-default prompt and deletes it after
100
100
  # confirmation.
101
101
  def choose_and_delete_prompt
102
- prompt = choose_prompt(default: false, prompt: 'Which template has outlived its usefulness? ') or return
102
+ prompt = choose_prompt(default: false, prompt: 'Which template has outlived its usefulness? %s') or return
103
103
  STDOUT.puts kramdown_ansi_parse(
104
104
  prompt.to_s + "\n---"
105
105
  )
@@ -115,7 +115,7 @@ module OllamaChat::PromptManagement
115
115
  #
116
116
  # @return [self, nil] the current context on success, or nil if cancelled
117
117
  def choose_and_edit_prompt
118
- prompt = choose_prompt(prompt: 'Which spell needs some fine-tuning? ') or return
118
+ prompt = choose_prompt(prompt: 'Which spell needs some fine-tuning? %s') or return
119
119
  prompt.metadata['content'] = edit_text(prompt.metadata['content'].to_s)
120
120
  prompt.save
121
121
  self
@@ -133,7 +133,7 @@ module OllamaChat::PromptManagement
133
133
  # @return [self, nil] the current context on success, or nil if the user
134
134
  # cancelled the operation or no prompt was selected.
135
135
  def duplicate_prompt
136
- prompt = choose_prompt(prompt: 'Which prompt shall be the basis for a new one? ') or return
136
+ prompt = choose_prompt(prompt: 'Which prompt shall be the basis for a new one? %s') or return
137
137
  STDOUT.puts kramdown_ansi_parse(
138
138
  prompt.to_s + "\n---"
139
139
  )
@@ -204,7 +204,7 @@ module OllamaChat::PromptManagement
204
204
  # @return [self, nil] returns self if the export was successful, or nil if
205
205
  # the process was cancelled during prompt selection or filename entry.
206
206
  def export_prompt
207
- prompt = choose_prompt(prompt: 'Which template are you exporting to disk? ') or return
207
+ prompt = choose_prompt(prompt: 'Which template are you exporting to disk? %s') or return
208
208
  STDOUT.puts kramdown_ansi_parse(
209
209
  prompt.to_s + "\n---"
210
210
  )
@@ -241,7 +241,7 @@ module OllamaChat::PromptManagement
241
241
  # was cancelled.
242
242
  def suggest_prompts
243
243
  # Let the user pick a prompt template (e.g., suggest_coding, suggest_roleplaying)
244
- instruction = choose_prompt(prompt: 'Which suggestion strategy shall we employ? ') or return
244
+ instruction = choose_prompt(prompt: 'Which suggestion strategy shall we employ? %s') or return
245
245
 
246
246
  # Build the context by gathering all current conversation messages
247
247
  history = prepare_conversation_history
@@ -44,7 +44,7 @@ module OllamaChat::RAGHandling
44
44
  tags = @documents.tags.to_a.unshift('[ALL]').unshift('[EXIT]')
45
45
  tag = choose_entry(
46
46
  tags,
47
- prompt: 'What obsolete records are to be excised from the annals? '
47
+ prompt: 'What obsolete records are to be excised from the annals? %s'
48
48
  )
49
49
  case tag
50
50
  when nil, '[EXIT]'
@@ -85,7 +85,7 @@ module OllamaChat::RAGHandling
85
85
  collections.unshift('[EXIT]').unshift('[NEW]')
86
86
  collection = choose_entry(
87
87
  collections,
88
- prompt: 'Which archive of knowledge shall we delve into?'
88
+ prompt: 'Which archive of knowledge shall we delve into? %s'
89
89
  ) || current_collection
90
90
  case collection&.to_s
91
91
  when '[NEW]'
@@ -506,7 +506,7 @@ module OllamaChat::SessionManagement
506
506
  else
507
507
  offer_new_session and sessions.unshift(SearchUI::Wrapper.new('[new]', display: '[NEW]'))
508
508
  sessions = sessions.unshift(SearchUI::Wrapper.new('[exit]', display: '[EXIT]'))
509
- value = choose_entry(sessions, prompt: 'Select a chat session: ')&.value
509
+ value = choose_entry(sessions, prompt: 'Select a chat session: %s')&.value
510
510
  if value == '[new]'
511
511
  return new_session
512
512
  end
@@ -92,7 +92,7 @@ module OllamaChat::StateSelectors
92
92
 
93
93
  chosen = choose_entry(
94
94
  states,
95
- prompt: 'Which operational paradigm should be engaged?'
95
+ prompt: 'Which operational paradigm should be engaged? %s'
96
96
  )
97
97
  case chosen
98
98
  when '[EXIT]', nil
@@ -87,7 +87,7 @@ module OllamaChat::SystemPromptManagement
87
87
  prompts.unshift('[MODEL DEFAULT]').unshift('[EXIT]')
88
88
  chosen = choose_entry(
89
89
  prompts,
90
- prompt: 'Which governing law shall we enact?'
90
+ prompt: 'Which governing law shall we enact? %s'
91
91
  )
92
92
  system_prompt_name =
93
93
  case chosen
@@ -112,7 +112,7 @@ module OllamaChat::SystemPromptManagement
112
112
  # (default: 'Select a system prompt: ')
113
113
  #
114
114
  # @return [Object, nil] the selected system prompt object, or nil if cancelled
115
- def choose_system_prompt(prompt: 'Select a system prompt: ')
115
+ def choose_system_prompt(prompt: 'Select a system prompt: %s')
116
116
  prompts = all_system_prompts
117
117
  prompts.unshift('[EXIT]')
118
118
  case chosen = choose_entry(prompts, prompt:)
@@ -128,7 +128,7 @@ module OllamaChat::SystemPromptManagement
128
128
  #
129
129
  # @return [self, nil] the current context on success, or nil if cancelled
130
130
  def info_system_prompt
131
- if system_prompt = choose_system_prompt(prompt: 'Which system law would you like to review? ')
131
+ if system_prompt = choose_system_prompt(prompt: 'Which system law would you like to review? %s')
132
132
  use_pager do |output|
133
133
  output.puts kramdown_ansi_parse(<<~EOT)
134
134
  # System Prompt #{system_prompt.name}
@@ -170,7 +170,7 @@ module OllamaChat::SystemPromptManagement
170
170
  # @return [self, nil] the current context on success, or nil if cancelled
171
171
  def choose_and_edit_system_prompt
172
172
  system_prompt = choose_system_prompt(
173
- prompt: 'Which system directive needs rewriting? '
173
+ prompt: 'Which system directive needs rewriting? %s'
174
174
  ) or return
175
175
  system_prompt.metadata['content'] = edit_text(system_prompt.metadata['content'].to_s)
176
176
  system_prompt.save
@@ -183,7 +183,7 @@ module OllamaChat::SystemPromptManagement
183
183
  #
184
184
  # @return [self, nil] the current context on success, or nil if cancelled
185
185
  def choose_and_delete_system_prompt
186
- system_prompt = choose_system_prompt(prompt: 'Which old rule is now obsolete? ') or return
186
+ system_prompt = choose_system_prompt(prompt: 'Which old rule is now obsolete? %s') or return
187
187
  STDOUT.puts kramdown_ansi_parse(
188
188
  system_prompt.to_s + "\n---"
189
189
  )
@@ -226,7 +226,7 @@ module OllamaChat::SystemPromptManagement
226
226
  # @return [self, nil] the current context on success, or nil if the user
227
227
  # cancelled the operation or no system prompt was selected.
228
228
  def duplicate_system_prompt
229
- system_prompt = choose_system_prompt(prompt: 'Which core logic shall be cloned? ') or return
229
+ system_prompt = choose_system_prompt(prompt: 'Which core logic shall be cloned? %s') or return
230
230
  STDOUT.puts kramdown_ansi_parse(
231
231
  system_prompt.to_s + "\n---"
232
232
  )
@@ -281,7 +281,7 @@ module OllamaChat::SystemPromptManagement
281
281
  # @return [self, nil] returns self if the export was successful, or nil if
282
282
  # the process was cancelled during system prompt selection or filename entry.
283
283
  def export_system_prompt
284
- prompt = choose_system_prompt(prompt: 'Which system prompt are you archiving to disk? ') or return
284
+ prompt = choose_system_prompt(prompt: 'Which system prompt are you archiving to disk? %s') or return
285
285
  STDOUT.puts kramdown_ansi_parse(
286
286
  prompt.to_s + "\n---"
287
287
  )
@@ -54,7 +54,7 @@ module OllamaChat::ToolCalling
54
54
  #
55
55
  # @return [ Hash ] a hash containing the registered tools
56
56
  def tools
57
- @tools_support.off? and return []
57
+ tools_support.off? and return []
58
58
  enabled_tools.filter_map { OllamaChat::Tools.registered[it]&.to_hash }
59
59
  end
60
60
 
@@ -130,7 +130,7 @@ module OllamaChat::ToolCalling
130
130
  select_tools = [ '[EXIT]' ] + select_tools
131
131
  chosen = choose_entry(
132
132
  select_tools,
133
- prompt: 'Which capabilities should be granted to the model?'
133
+ prompt: 'Which capabilities should be granted to the model? %s'
134
134
  )
135
135
  case chosen
136
136
  when '[EXIT]', nil
@@ -161,7 +161,7 @@ module OllamaChat::ToolCalling
161
161
  select_tools = [ '[EXIT]' ] + select_tools
162
162
  chosen = choose_entry(
163
163
  select_tools,
164
- prompt: 'Which capabilities should be granted to the model?'
164
+ prompt: 'Which capabilities should be granted to the model? %s'
165
165
  )
166
166
  case chosen
167
167
  when '[EXIT]', nil
@@ -186,7 +186,7 @@ module OllamaChat::ToolCalling
186
186
  select { |name, value| tool_enabled?(name) && value[:allowed].present? }.
187
187
  sort_by(&:first).
188
188
  each_with_object({}) do |(name, value), hash|
189
- hash[name] = value[:allowed].filter_map do
189
+ hash[name.to_s] = value[:allowed].filter_map do
190
190
  pathname = Pathname.new(_1).expand_path
191
191
  pathname.exist?.full? { pathname.to_path }
192
192
  end
@@ -12,7 +12,7 @@ require 'term/ansicolor'
12
12
  #
13
13
  # @example Using the chooser in an interactive menu
14
14
  # entries = ['apple', 'banana', 'cherry']
15
- # selected = choose_entry(entries, prompt: 'Choose a fruit:')
15
+ # selected = choose_entry(entries, prompt: 'Choose a fruit: %s')
16
16
  #
17
17
  # @example Returning immediately if only one entry exists
18
18
  # entries = ['single_option']
@@ -37,7 +37,7 @@ module OllamaChat::Utils::Chooser
37
37
  # @return [Object] the selected entry, or nil if no entry was chosen
38
38
  #
39
39
  # @example
40
- # choose_entry(['entry1', 'entry2'], prompt: 'Choose an option:')
40
+ # choose_entry(['entry1', 'entry2'], prompt: 'Choose an option: %s')
41
41
  def choose_entry(entries, prompt: 'Search? %s', return_immediately: false)
42
42
  if return_immediately && entries.size <= 1
43
43
  return entries.first
@@ -1,6 +1,6 @@
1
1
  module OllamaChat
2
2
  # OllamaChat version
3
- VERSION = '0.0.92'
3
+ VERSION = '0.0.94'
4
4
  VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
@@ -108,7 +108,10 @@ module OllamaChat::WebSearching
108
108
  choose_with_state do
109
109
  loop do
110
110
  links_options = links.to_a.unshift('[ALL]').unshift('[EXIT]')
111
- link = choose_entry(links_options, prompt: 'Clear? %s')
111
+ link = choose_entry(
112
+ links_options,
113
+ prompt: 'Which links of knowledge shall we sever? %s'
114
+ )
112
115
  case link
113
116
  when nil, '[EXIT]'
114
117
  STDOUT.puts "Exiting chooser."
data/ollama_chat.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: ollama_chat 0.0.92 ruby lib
2
+ # stub: ollama_chat 0.0.94 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "ollama_chat".freeze
6
- s.version = "0.0.92".freeze
6
+ s.version = "0.0.94".freeze
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
@@ -13,14 +13,14 @@ Gem::Specification.new do |s|
13
13
  s.email = "flori@ping.de".freeze
14
14
  s.executables = ["ollama_chat".freeze, "ollama_chat_send".freeze]
15
15
  s.extra_rdoc_files = ["README.md".freeze, "lib/ollama_chat.rb".freeze, "lib/ollama_chat/chat.rb".freeze, "lib/ollama_chat/clipboard.rb".freeze, "lib/ollama_chat/command_concern.rb".freeze, "lib/ollama_chat/commands.rb".freeze, "lib/ollama_chat/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/database.rb".freeze, "lib/ollama_chat/database/duplicatable.rb".freeze, "lib/ollama_chat/database/migrations.rb".freeze, "lib/ollama_chat/database/migrations/001_initial_schema.rb".freeze, "lib/ollama_chat/database/migrations/002_add_links_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/003_add_history_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/004_add_profile_to_model_options.rb".freeze, "lib/ollama_chat/database/models/favourite.rb".freeze, "lib/ollama_chat/database/models/model_options.rb".freeze, "lib/ollama_chat/database/models/prompt.rb".freeze, "lib/ollama_chat/database/models/session.rb".freeze, "lib/ollama_chat/database/session_locking.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/favourites_management.rb".freeze, "lib/ollama_chat/file_editing.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/history.rb".freeze, "lib/ollama_chat/http_handling.rb".freeze, "lib/ollama_chat/information.rb".freeze, "lib/ollama_chat/input_content.rb".freeze, "lib/ollama_chat/kramdown_ansi.rb".freeze, "lib/ollama_chat/links_set.rb".freeze, "lib/ollama_chat/location_handling.rb".freeze, "lib/ollama_chat/logging.rb".freeze, "lib/ollama_chat/message.rb".freeze, "lib/ollama_chat/message_editing.rb".freeze, "lib/ollama_chat/message_format.rb".freeze, "lib/ollama_chat/message_list.rb".freeze, "lib/ollama_chat/message_output.rb".freeze, "lib/ollama_chat/model_handling.rb".freeze, "lib/ollama_chat/oc.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/pager.rb".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/personae_management.rb".freeze, "lib/ollama_chat/prompt_handling.rb".freeze, "lib/ollama_chat/prompt_management.rb".freeze, "lib/ollama_chat/rag_handling.rb".freeze, "lib/ollama_chat/redis_cache.rb".freeze, "lib/ollama_chat/server_socket.rb".freeze, "lib/ollama_chat/session_management.rb".freeze, "lib/ollama_chat/source_fetching.rb".freeze, "lib/ollama_chat/state_selectors.rb".freeze, "lib/ollama_chat/switches.rb".freeze, "lib/ollama_chat/system_prompt_management.rb".freeze, "lib/ollama_chat/think_control.rb".freeze, "lib/ollama_chat/tool_calling.rb".freeze, "lib/ollama_chat/tools.rb".freeze, "lib/ollama_chat/tools/browse.rb".freeze, "lib/ollama_chat/tools/compute_bmi.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/copy_to_clipboard.rb".freeze, "lib/ollama_chat/tools/delete_file.rb".freeze, "lib/ollama_chat/tools/directory_structure.rb".freeze, "lib/ollama_chat/tools/eval_ruby.rb".freeze, "lib/ollama_chat/tools/execute_grep.rb".freeze, "lib/ollama_chat/tools/execute_ri.rb".freeze, "lib/ollama_chat/tools/file_context.rb".freeze, "lib/ollama_chat/tools/gem_path_lookup.rb".freeze, "lib/ollama_chat/tools/generate_image.rb".freeze, "lib/ollama_chat/tools/generate_password.rb".freeze, "lib/ollama_chat/tools/get_current_weather.rb".freeze, "lib/ollama_chat/tools/get_cve.rb".freeze, "lib/ollama_chat/tools/get_endoflife.rb".freeze, "lib/ollama_chat/tools/get_ghr.rb".freeze, "lib/ollama_chat/tools/get_jira_issue.rb".freeze, "lib/ollama_chat/tools/get_location.rb".freeze, "lib/ollama_chat/tools/get_rfc.rb".freeze, "lib/ollama_chat/tools/get_time.rb".freeze, "lib/ollama_chat/tools/get_url.rb".freeze, "lib/ollama_chat/tools/move_file.rb".freeze, "lib/ollama_chat/tools/open_file_in_editor.rb".freeze, "lib/ollama_chat/tools/paste_from_clipboard.rb".freeze, "lib/ollama_chat/tools/paste_into_editor.rb".freeze, "lib/ollama_chat/tools/patch_file.rb".freeze, "lib/ollama_chat/tools/read_file.rb".freeze, "lib/ollama_chat/tools/resolve_tag.rb".freeze, "lib/ollama_chat/tools/retrieve_document_snippets.rb".freeze, "lib/ollama_chat/tools/roll_dice.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_web.rb".freeze, "lib/ollama_chat/tools/write_file.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/analyze_directory.rb".freeze, "lib/ollama_chat/utils/backup.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/json_jsonl_io.rb".freeze, "lib/ollama_chat/utils/path_completer.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/png_character_extractor.rb".freeze, "lib/ollama_chat/utils/tag_resolver.rb".freeze, "lib/ollama_chat/utils/token_estimator.rb".freeze, "lib/ollama_chat/utils/value_formatter.rb".freeze, "lib/ollama_chat/version.rb".freeze, "lib/ollama_chat/vim.rb".freeze, "lib/ollama_chat/web_searching.rb".freeze]
16
- s.files = [".utilsrc".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_chat_send".freeze, "config/searxng/settings.yml".freeze, "config/sherlock.md".freeze, "docker-compose.yml".freeze, "lib/ollama_chat.rb".freeze, "lib/ollama_chat/chat.rb".freeze, "lib/ollama_chat/clipboard.rb".freeze, "lib/ollama_chat/command_concern.rb".freeze, "lib/ollama_chat/commands.rb".freeze, "lib/ollama_chat/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/database.rb".freeze, "lib/ollama_chat/database/duplicatable.rb".freeze, "lib/ollama_chat/database/migrations.rb".freeze, "lib/ollama_chat/database/migrations/001_initial_schema.rb".freeze, "lib/ollama_chat/database/migrations/002_add_links_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/003_add_history_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/004_add_profile_to_model_options.rb".freeze, "lib/ollama_chat/database/models/favourite.rb".freeze, "lib/ollama_chat/database/models/model_options.rb".freeze, "lib/ollama_chat/database/models/prompt.rb".freeze, "lib/ollama_chat/database/models/session.rb".freeze, "lib/ollama_chat/database/session_locking.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/favourites_management.rb".freeze, "lib/ollama_chat/file_editing.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/history.rb".freeze, "lib/ollama_chat/http_handling.rb".freeze, "lib/ollama_chat/information.rb".freeze, "lib/ollama_chat/input_content.rb".freeze, "lib/ollama_chat/kramdown_ansi.rb".freeze, "lib/ollama_chat/links_set.rb".freeze, "lib/ollama_chat/location_handling.rb".freeze, "lib/ollama_chat/logging.rb".freeze, "lib/ollama_chat/message.rb".freeze, "lib/ollama_chat/message_editing.rb".freeze, "lib/ollama_chat/message_format.rb".freeze, "lib/ollama_chat/message_list.rb".freeze, "lib/ollama_chat/message_output.rb".freeze, "lib/ollama_chat/model_handling.rb".freeze, "lib/ollama_chat/oc.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/ollama_chat_config/default_config.yml".freeze, "lib/ollama_chat/pager.rb".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/personae_management.rb".freeze, "lib/ollama_chat/prompt_handling.rb".freeze, "lib/ollama_chat/prompt_management.rb".freeze, "lib/ollama_chat/rag_handling.rb".freeze, "lib/ollama_chat/redis_cache.rb".freeze, "lib/ollama_chat/server_socket.rb".freeze, "lib/ollama_chat/session_management.rb".freeze, "lib/ollama_chat/source_fetching.rb".freeze, "lib/ollama_chat/state_selectors.rb".freeze, "lib/ollama_chat/switches.rb".freeze, "lib/ollama_chat/system_prompt_management.rb".freeze, "lib/ollama_chat/think_control.rb".freeze, "lib/ollama_chat/tool_calling.rb".freeze, "lib/ollama_chat/tools.rb".freeze, "lib/ollama_chat/tools/browse.rb".freeze, "lib/ollama_chat/tools/compute_bmi.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/copy_to_clipboard.rb".freeze, "lib/ollama_chat/tools/delete_file.rb".freeze, "lib/ollama_chat/tools/directory_structure.rb".freeze, "lib/ollama_chat/tools/eval_ruby.rb".freeze, "lib/ollama_chat/tools/execute_grep.rb".freeze, "lib/ollama_chat/tools/execute_ri.rb".freeze, "lib/ollama_chat/tools/file_context.rb".freeze, "lib/ollama_chat/tools/gem_path_lookup.rb".freeze, "lib/ollama_chat/tools/generate_image.rb".freeze, "lib/ollama_chat/tools/generate_password.rb".freeze, "lib/ollama_chat/tools/get_current_weather.rb".freeze, "lib/ollama_chat/tools/get_cve.rb".freeze, "lib/ollama_chat/tools/get_endoflife.rb".freeze, "lib/ollama_chat/tools/get_ghr.rb".freeze, "lib/ollama_chat/tools/get_jira_issue.rb".freeze, "lib/ollama_chat/tools/get_location.rb".freeze, "lib/ollama_chat/tools/get_rfc.rb".freeze, "lib/ollama_chat/tools/get_time.rb".freeze, "lib/ollama_chat/tools/get_url.rb".freeze, "lib/ollama_chat/tools/move_file.rb".freeze, "lib/ollama_chat/tools/open_file_in_editor.rb".freeze, "lib/ollama_chat/tools/paste_from_clipboard.rb".freeze, "lib/ollama_chat/tools/paste_into_editor.rb".freeze, "lib/ollama_chat/tools/patch_file.rb".freeze, "lib/ollama_chat/tools/read_file.rb".freeze, "lib/ollama_chat/tools/resolve_tag.rb".freeze, "lib/ollama_chat/tools/retrieve_document_snippets.rb".freeze, "lib/ollama_chat/tools/roll_dice.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_web.rb".freeze, "lib/ollama_chat/tools/write_file.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/analyze_directory.rb".freeze, "lib/ollama_chat/utils/backup.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/json_jsonl_io.rb".freeze, "lib/ollama_chat/utils/path_completer.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/png_character_extractor.rb".freeze, "lib/ollama_chat/utils/tag_resolver.rb".freeze, "lib/ollama_chat/utils/token_estimator.rb".freeze, "lib/ollama_chat/utils/value_formatter.rb".freeze, "lib/ollama_chat/version.rb".freeze, "lib/ollama_chat/vim.rb".freeze, "lib/ollama_chat/web_searching.rb".freeze, "ollama_chat.gemspec".freeze, "redis/redis.conf".freeze, "spec/assets/api_show.json".freeze, "spec/assets/api_tags.json".freeze, "spec/assets/api_version.json".freeze, "spec/assets/conversation.json".freeze, "spec/assets/conversation.jsonl".freeze, "spec/assets/deep/deeper/empty.txt".freeze, "spec/assets/deep/deeper/not-empty.txt".freeze, "spec/assets/deep/empty.txt".freeze, "spec/assets/duckduckgo.html".freeze, "spec/assets/example.atom".freeze, "spec/assets/example.csv".freeze, "spec/assets/example.html".freeze, "spec/assets/example.pdf".freeze, "spec/assets/example.ps".freeze, "spec/assets/example.rb".freeze, "spec/assets/example.rss".freeze, "spec/assets/example.xml".freeze, "spec/assets/example_with_quote.html".freeze, "spec/assets/fluffy.png".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/pirateweather.json".freeze, "spec/assets/prompt.txt".freeze, "spec/assets/searxng.json".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/database/models/favourite_spec.rb".freeze, "spec/ollama_chat/file_editing_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/history_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/input_content_spec.rb".freeze, "spec/ollama_chat/kramdown_ansi_spec.rb".freeze, "spec/ollama_chat/message_editing_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/message_output_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/state_selectors_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/compute_bmi_spec.rb".freeze, "spec/ollama_chat/tools/copy_to_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/delete_file_spec.rb".freeze, "spec/ollama_chat/tools/directory_structure_spec.rb".freeze, "spec/ollama_chat/tools/execute_grep_spec.rb".freeze, "spec/ollama_chat/tools/execute_ri_spec.rb".freeze, "spec/ollama_chat/tools/file_context_spec.rb".freeze, "spec/ollama_chat/tools/gem_path_lookup_spec.rb".freeze, "spec/ollama_chat/tools/generate_image_spec.rb".freeze, "spec/ollama_chat/tools/generate_password_spec.rb".freeze, "spec/ollama_chat/tools/get_current_weather_spec.rb".freeze, "spec/ollama_chat/tools/get_cve_spec.rb".freeze, "spec/ollama_chat/tools/get_endoflife_spec.rb".freeze, "spec/ollama_chat/tools/get_ghr_spec.rb".freeze, "spec/ollama_chat/tools/get_jira_issue_spec.rb".freeze, "spec/ollama_chat/tools/get_location_spec.rb".freeze, "spec/ollama_chat/tools/get_rfc_spec.rb".freeze, "spec/ollama_chat/tools/get_time_spec.rb".freeze, "spec/ollama_chat/tools/get_url_spec.rb".freeze, "spec/ollama_chat/tools/move_file_spec.rb".freeze, "spec/ollama_chat/tools/open_file_in_editor_spec.rb".freeze, "spec/ollama_chat/tools/paste_from_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/paste_into_editor_spec.rb".freeze, "spec/ollama_chat/tools/patch_file_spec.rb".freeze, "spec/ollama_chat/tools/read_file_spec.rb".freeze, "spec/ollama_chat/tools/resolve_tag_spec.rb".freeze, "spec/ollama_chat/tools/retrieve_document_snippets_spec.rb".freeze, "spec/ollama_chat/tools/roll_dice_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_web_spec.rb".freeze, "spec/ollama_chat/tools/write_file_spec.rb".freeze, "spec/ollama_chat/utils/analyze_directory_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/path_completer_spec.rb".freeze, "spec/ollama_chat/utils/png_character_extractor_spec.rb".freeze, "spec/ollama_chat/vim_spec.rb".freeze, "spec/ollama_chat/web_searching_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tmp/.keep".freeze]
16
+ s.files = [".utilsrc".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_chat_send".freeze, "config/searxng/settings.yml".freeze, "config/sherlock.md".freeze, "docker-compose.yml".freeze, "lib/ollama_chat.rb".freeze, "lib/ollama_chat/chat.rb".freeze, "lib/ollama_chat/clipboard.rb".freeze, "lib/ollama_chat/command_concern.rb".freeze, "lib/ollama_chat/commands.rb".freeze, "lib/ollama_chat/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/database.rb".freeze, "lib/ollama_chat/database/duplicatable.rb".freeze, "lib/ollama_chat/database/migrations.rb".freeze, "lib/ollama_chat/database/migrations/001_initial_schema.rb".freeze, "lib/ollama_chat/database/migrations/002_add_links_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/003_add_history_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/004_add_profile_to_model_options.rb".freeze, "lib/ollama_chat/database/models/favourite.rb".freeze, "lib/ollama_chat/database/models/model_options.rb".freeze, "lib/ollama_chat/database/models/prompt.rb".freeze, "lib/ollama_chat/database/models/session.rb".freeze, "lib/ollama_chat/database/session_locking.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.rb".freeze, "lib/ollama_chat/favourites_management.rb".freeze, "lib/ollama_chat/file_editing.rb".freeze, "lib/ollama_chat/follow_chat.rb".freeze, "lib/ollama_chat/history.rb".freeze, "lib/ollama_chat/http_handling.rb".freeze, "lib/ollama_chat/information.rb".freeze, "lib/ollama_chat/input_content.rb".freeze, "lib/ollama_chat/kramdown_ansi.rb".freeze, "lib/ollama_chat/links_set.rb".freeze, "lib/ollama_chat/location_handling.rb".freeze, "lib/ollama_chat/logging.rb".freeze, "lib/ollama_chat/message.rb".freeze, "lib/ollama_chat/message_editing.rb".freeze, "lib/ollama_chat/message_format.rb".freeze, "lib/ollama_chat/message_list.rb".freeze, "lib/ollama_chat/message_output.rb".freeze, "lib/ollama_chat/model_handling.rb".freeze, "lib/ollama_chat/oc.rb".freeze, "lib/ollama_chat/ollama_chat_config.rb".freeze, "lib/ollama_chat/ollama_chat_config/default_config.yml".freeze, "lib/ollama_chat/pager.rb".freeze, "lib/ollama_chat/parsing.rb".freeze, "lib/ollama_chat/personae_management.rb".freeze, "lib/ollama_chat/prompt_handling.rb".freeze, "lib/ollama_chat/prompt_management.rb".freeze, "lib/ollama_chat/rag_handling.rb".freeze, "lib/ollama_chat/redis_cache.rb".freeze, "lib/ollama_chat/server_socket.rb".freeze, "lib/ollama_chat/session_management.rb".freeze, "lib/ollama_chat/source_fetching.rb".freeze, "lib/ollama_chat/state_selectors.rb".freeze, "lib/ollama_chat/switches.rb".freeze, "lib/ollama_chat/system_prompt_management.rb".freeze, "lib/ollama_chat/think_control.rb".freeze, "lib/ollama_chat/tool_calling.rb".freeze, "lib/ollama_chat/tools.rb".freeze, "lib/ollama_chat/tools/browse.rb".freeze, "lib/ollama_chat/tools/compute_bmi.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/copy_to_clipboard.rb".freeze, "lib/ollama_chat/tools/delete_file.rb".freeze, "lib/ollama_chat/tools/directory_structure.rb".freeze, "lib/ollama_chat/tools/eval_ruby.rb".freeze, "lib/ollama_chat/tools/execute_grep.rb".freeze, "lib/ollama_chat/tools/execute_ri.rb".freeze, "lib/ollama_chat/tools/file_context.rb".freeze, "lib/ollama_chat/tools/gem_path_lookup.rb".freeze, "lib/ollama_chat/tools/generate_image.rb".freeze, "lib/ollama_chat/tools/generate_password.rb".freeze, "lib/ollama_chat/tools/get_current_weather.rb".freeze, "lib/ollama_chat/tools/get_cve.rb".freeze, "lib/ollama_chat/tools/get_endoflife.rb".freeze, "lib/ollama_chat/tools/get_ghr.rb".freeze, "lib/ollama_chat/tools/get_jira_issue.rb".freeze, "lib/ollama_chat/tools/get_location.rb".freeze, "lib/ollama_chat/tools/get_rfc.rb".freeze, "lib/ollama_chat/tools/get_time.rb".freeze, "lib/ollama_chat/tools/get_url.rb".freeze, "lib/ollama_chat/tools/move_file.rb".freeze, "lib/ollama_chat/tools/open_file_in_editor.rb".freeze, "lib/ollama_chat/tools/paste_from_clipboard.rb".freeze, "lib/ollama_chat/tools/paste_into_editor.rb".freeze, "lib/ollama_chat/tools/patch_file.rb".freeze, "lib/ollama_chat/tools/read_file.rb".freeze, "lib/ollama_chat/tools/resolve_tag.rb".freeze, "lib/ollama_chat/tools/retrieve_document_snippets.rb".freeze, "lib/ollama_chat/tools/roll_dice.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_web.rb".freeze, "lib/ollama_chat/tools/write_file.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/analyze_directory.rb".freeze, "lib/ollama_chat/utils/backup.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/json_jsonl_io.rb".freeze, "lib/ollama_chat/utils/path_completer.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/png_character_extractor.rb".freeze, "lib/ollama_chat/utils/tag_resolver.rb".freeze, "lib/ollama_chat/utils/token_estimator.rb".freeze, "lib/ollama_chat/utils/value_formatter.rb".freeze, "lib/ollama_chat/version.rb".freeze, "lib/ollama_chat/vim.rb".freeze, "lib/ollama_chat/web_searching.rb".freeze, "ollama_chat.gemspec".freeze, "redis/redis.conf".freeze, "spec/assets/api_show.json".freeze, "spec/assets/api_tags.json".freeze, "spec/assets/api_version.json".freeze, "spec/assets/conversation.json".freeze, "spec/assets/conversation.jsonl".freeze, "spec/assets/deep/deeper/empty.txt".freeze, "spec/assets/deep/deeper/not-empty.txt".freeze, "spec/assets/deep/empty.txt".freeze, "spec/assets/duckduckgo.html".freeze, "spec/assets/example.atom".freeze, "spec/assets/example.csv".freeze, "spec/assets/example.html".freeze, "spec/assets/example.pdf".freeze, "spec/assets/example.ps".freeze, "spec/assets/example.rb".freeze, "spec/assets/example.rss".freeze, "spec/assets/example.xml".freeze, "spec/assets/example_with_quote.html".freeze, "spec/assets/fluffy.png".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/pirateweather.json".freeze, "spec/assets/prompt.txt".freeze, "spec/assets/searxng.json".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/database/models/favourite_spec.rb".freeze, "spec/ollama_chat/file_editing_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/history_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/input_content_spec.rb".freeze, "spec/ollama_chat/kramdown_ansi_spec.rb".freeze, "spec/ollama_chat/message_editing_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/message_output_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/state_selectors_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/tool_calling_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/compute_bmi_spec.rb".freeze, "spec/ollama_chat/tools/copy_to_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/delete_file_spec.rb".freeze, "spec/ollama_chat/tools/directory_structure_spec.rb".freeze, "spec/ollama_chat/tools/execute_grep_spec.rb".freeze, "spec/ollama_chat/tools/execute_ri_spec.rb".freeze, "spec/ollama_chat/tools/file_context_spec.rb".freeze, "spec/ollama_chat/tools/gem_path_lookup_spec.rb".freeze, "spec/ollama_chat/tools/generate_image_spec.rb".freeze, "spec/ollama_chat/tools/generate_password_spec.rb".freeze, "spec/ollama_chat/tools/get_current_weather_spec.rb".freeze, "spec/ollama_chat/tools/get_cve_spec.rb".freeze, "spec/ollama_chat/tools/get_endoflife_spec.rb".freeze, "spec/ollama_chat/tools/get_ghr_spec.rb".freeze, "spec/ollama_chat/tools/get_jira_issue_spec.rb".freeze, "spec/ollama_chat/tools/get_location_spec.rb".freeze, "spec/ollama_chat/tools/get_rfc_spec.rb".freeze, "spec/ollama_chat/tools/get_time_spec.rb".freeze, "spec/ollama_chat/tools/get_url_spec.rb".freeze, "spec/ollama_chat/tools/move_file_spec.rb".freeze, "spec/ollama_chat/tools/open_file_in_editor_spec.rb".freeze, "spec/ollama_chat/tools/paste_from_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/paste_into_editor_spec.rb".freeze, "spec/ollama_chat/tools/patch_file_spec.rb".freeze, "spec/ollama_chat/tools/read_file_spec.rb".freeze, "spec/ollama_chat/tools/resolve_tag_spec.rb".freeze, "spec/ollama_chat/tools/retrieve_document_snippets_spec.rb".freeze, "spec/ollama_chat/tools/roll_dice_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_web_spec.rb".freeze, "spec/ollama_chat/tools/write_file_spec.rb".freeze, "spec/ollama_chat/utils/analyze_directory_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/path_completer_spec.rb".freeze, "spec/ollama_chat/utils/png_character_extractor_spec.rb".freeze, "spec/ollama_chat/vim_spec.rb".freeze, "spec/ollama_chat/web_searching_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tmp/.keep".freeze]
17
17
  s.homepage = "https://github.com/flori/ollama_chat".freeze
18
18
  s.licenses = ["MIT".freeze]
19
19
  s.rdoc_options = ["--title".freeze, "OllamaChat - A command-line interface (CLI) for interacting with an Ollama AI model.".freeze, "--main".freeze, "README.md".freeze]
20
20
  s.required_ruby_version = Gem::Requirement.new(">= 3.2".freeze)
21
21
  s.rubygems_version = "4.0.10".freeze
22
22
  s.summary = "A command-line interface (CLI) for interacting with an Ollama AI model.".freeze
23
- s.test_files = ["spec/assets/example.rb".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/database/models/favourite_spec.rb".freeze, "spec/ollama_chat/file_editing_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/history_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/input_content_spec.rb".freeze, "spec/ollama_chat/kramdown_ansi_spec.rb".freeze, "spec/ollama_chat/message_editing_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/message_output_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/state_selectors_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/compute_bmi_spec.rb".freeze, "spec/ollama_chat/tools/copy_to_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/delete_file_spec.rb".freeze, "spec/ollama_chat/tools/directory_structure_spec.rb".freeze, "spec/ollama_chat/tools/execute_grep_spec.rb".freeze, "spec/ollama_chat/tools/execute_ri_spec.rb".freeze, "spec/ollama_chat/tools/file_context_spec.rb".freeze, "spec/ollama_chat/tools/gem_path_lookup_spec.rb".freeze, "spec/ollama_chat/tools/generate_image_spec.rb".freeze, "spec/ollama_chat/tools/generate_password_spec.rb".freeze, "spec/ollama_chat/tools/get_current_weather_spec.rb".freeze, "spec/ollama_chat/tools/get_cve_spec.rb".freeze, "spec/ollama_chat/tools/get_endoflife_spec.rb".freeze, "spec/ollama_chat/tools/get_ghr_spec.rb".freeze, "spec/ollama_chat/tools/get_jira_issue_spec.rb".freeze, "spec/ollama_chat/tools/get_location_spec.rb".freeze, "spec/ollama_chat/tools/get_rfc_spec.rb".freeze, "spec/ollama_chat/tools/get_time_spec.rb".freeze, "spec/ollama_chat/tools/get_url_spec.rb".freeze, "spec/ollama_chat/tools/move_file_spec.rb".freeze, "spec/ollama_chat/tools/open_file_in_editor_spec.rb".freeze, "spec/ollama_chat/tools/paste_from_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/paste_into_editor_spec.rb".freeze, "spec/ollama_chat/tools/patch_file_spec.rb".freeze, "spec/ollama_chat/tools/read_file_spec.rb".freeze, "spec/ollama_chat/tools/resolve_tag_spec.rb".freeze, "spec/ollama_chat/tools/retrieve_document_snippets_spec.rb".freeze, "spec/ollama_chat/tools/roll_dice_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_web_spec.rb".freeze, "spec/ollama_chat/tools/write_file_spec.rb".freeze, "spec/ollama_chat/utils/analyze_directory_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/path_completer_spec.rb".freeze, "spec/ollama_chat/utils/png_character_extractor_spec.rb".freeze, "spec/ollama_chat/vim_spec.rb".freeze, "spec/ollama_chat/web_searching_spec.rb".freeze, "spec/spec_helper.rb".freeze]
23
+ s.test_files = ["spec/assets/example.rb".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/database/models/favourite_spec.rb".freeze, "spec/ollama_chat/file_editing_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/history_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/input_content_spec.rb".freeze, "spec/ollama_chat/kramdown_ansi_spec.rb".freeze, "spec/ollama_chat/message_editing_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/message_output_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/state_selectors_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/tool_calling_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/compute_bmi_spec.rb".freeze, "spec/ollama_chat/tools/copy_to_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/delete_file_spec.rb".freeze, "spec/ollama_chat/tools/directory_structure_spec.rb".freeze, "spec/ollama_chat/tools/execute_grep_spec.rb".freeze, "spec/ollama_chat/tools/execute_ri_spec.rb".freeze, "spec/ollama_chat/tools/file_context_spec.rb".freeze, "spec/ollama_chat/tools/gem_path_lookup_spec.rb".freeze, "spec/ollama_chat/tools/generate_image_spec.rb".freeze, "spec/ollama_chat/tools/generate_password_spec.rb".freeze, "spec/ollama_chat/tools/get_current_weather_spec.rb".freeze, "spec/ollama_chat/tools/get_cve_spec.rb".freeze, "spec/ollama_chat/tools/get_endoflife_spec.rb".freeze, "spec/ollama_chat/tools/get_ghr_spec.rb".freeze, "spec/ollama_chat/tools/get_jira_issue_spec.rb".freeze, "spec/ollama_chat/tools/get_location_spec.rb".freeze, "spec/ollama_chat/tools/get_rfc_spec.rb".freeze, "spec/ollama_chat/tools/get_time_spec.rb".freeze, "spec/ollama_chat/tools/get_url_spec.rb".freeze, "spec/ollama_chat/tools/move_file_spec.rb".freeze, "spec/ollama_chat/tools/open_file_in_editor_spec.rb".freeze, "spec/ollama_chat/tools/paste_from_clipboard_spec.rb".freeze, "spec/ollama_chat/tools/paste_into_editor_spec.rb".freeze, "spec/ollama_chat/tools/patch_file_spec.rb".freeze, "spec/ollama_chat/tools/read_file_spec.rb".freeze, "spec/ollama_chat/tools/resolve_tag_spec.rb".freeze, "spec/ollama_chat/tools/retrieve_document_snippets_spec.rb".freeze, "spec/ollama_chat/tools/roll_dice_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_web_spec.rb".freeze, "spec/ollama_chat/tools/write_file_spec.rb".freeze, "spec/ollama_chat/utils/analyze_directory_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/path_completer_spec.rb".freeze, "spec/ollama_chat/utils/png_character_extractor_spec.rb".freeze, "spec/ollama_chat/vim_spec.rb".freeze, "spec/ollama_chat/web_searching_spec.rb".freeze, "spec/spec_helper.rb".freeze]
24
24
 
25
25
  s.specification_version = 4
26
26
 
@@ -34,7 +34,7 @@ Gem::Specification.new do |s|
34
34
  s.add_development_dependency(%q<context_spook>.freeze, [">= 0".freeze])
35
35
  s.add_development_dependency(%q<utils>.freeze, [">= 0".freeze])
36
36
  s.add_runtime_dependency(%q<excon>.freeze, ["~> 1.0".freeze])
37
- s.add_runtime_dependency(%q<ollama-ruby>.freeze, ["~> 1.21".freeze])
37
+ s.add_runtime_dependency(%q<ollama-ruby>.freeze, ["~> 1.22".freeze])
38
38
  s.add_runtime_dependency(%q<documentrix>.freeze, [">= 0.6.0".freeze])
39
39
  s.add_runtime_dependency(%q<unix_socks>.freeze, [">= 0.4".freeze])
40
40
  s.add_runtime_dependency(%q<rss>.freeze, ["~> 0.3".freeze])
@@ -51,7 +51,7 @@ describe OllamaChat::InputContent do
51
51
  expect(chat).to receive(:choose_entry).
52
52
  with(
53
53
  files.unshift('[EXIT]'),
54
- prompt: 'Select a file to import: ',
54
+ prompt: 'Select a file to import: %s',
55
55
  ).and_return(files[1])
56
56
 
57
57
  result = chat.choose_filename('spec/assets/**/*.txt')
@@ -124,7 +124,7 @@ describe OllamaChat::StateSelectors::StateSelector do
124
124
  # Mock the chooser to return a specific choice
125
125
  expect(selector).to receive(:choose_entry).with(
126
126
  %w[ [EXIT] enabled disabled low high ],
127
- prompt: 'Which operational paradigm should be engaged?'
127
+ prompt: 'Which operational paradigm should be engaged? %s'
128
128
  ).and_return(double(value: 'low'))
129
129
 
130
130
  selector.choose
@@ -0,0 +1,202 @@
1
+ describe OllamaChat::ToolCalling do
2
+ let :chat do
3
+ OllamaChat::Chat.new(argv: chat_default_config).expose
4
+ end
5
+
6
+ connect_to_ollama_server
7
+
8
+ describe '#tool_configured?' do
9
+ it 'returns true if the tool is in the configuration' do
10
+ # Assuming a standard tool like 'read_file' is in default config
11
+ expect(chat.tool_configured?('read_file')).to be true
12
+ end
13
+
14
+ it 'returns false if the tool is not in the configuration' do
15
+ expect(chat.tool_configured?('non_existent_tool')).to be false
16
+ end
17
+ end
18
+
19
+ describe '#tool_function' do
20
+ it 'retrieves the configuration object for a valid tool' do
21
+ func = chat.tool_function('read_file')
22
+ expect(func).not_to be_nil
23
+ expect(func).to respond_to(:require_confirmation?)
24
+ end
25
+ end
26
+
27
+ describe '#tool_registered?' do
28
+ it 'returns true for tools registered in the global registry' do
29
+ expect(chat.tool_registered?('read_file')).to be true
30
+ end
31
+
32
+ it 'returns false for unregistered tools' do
33
+ expect(chat.tool_registered?('ghost_tool')).to be false
34
+ end
35
+ end
36
+
37
+ describe '#enabled_tools' do
38
+ it 'returns a list of tools that are both configured and enabled in the session' do
39
+ # Set up specific state in the session
40
+ chat.session.tools_default_enabled = { 'read_file' => true, 'write_file' => false }
41
+
42
+ enabled = chat.enabled_tools
43
+ expect(enabled).to include('read_file')
44
+ expect(enabled).not_to include('write_file')
45
+ end
46
+ end
47
+
48
+ describe '#tool_enabled?' do
49
+ it 'returns true if the tool is enabled' do
50
+ chat.session.tools_default_enabled['read_file'] = true
51
+ expect(chat.tool_enabled?('read_file')).to be true
52
+ end
53
+
54
+ it 'returns false if the tool is disabled' do
55
+ chat.session.tools_default_enabled['read_file'] = false
56
+ expect(chat.tool_enabled?('read_file')).to be false
57
+ end
58
+ end
59
+
60
+ describe '#tools' do
61
+ it 'returns a list of hashes for enabled and registered tools' do
62
+ expect(chat).to receive(:tools_support).and_return(double(off?: false))
63
+
64
+ # Setup: one tool is both, one is only enabled (unregistered)
65
+ chat.session.tools_default_enabled = { 'read_file' => true, 'ghost_tool' => true }
66
+
67
+ tools_list = chat.tools
68
+ expect(tools_list).to be_an(Array)
69
+ # Only 'read_file' should make the cut since 'ghost_tool' isn't registered
70
+ expect(tools_list.size).to eq(1)
71
+ expect(tools_list.first).to be_a(Hash)
72
+ end
73
+
74
+ it 'returns an empty array if tool support is disabled' do
75
+ # Mock the tools_support state to off
76
+ expect(chat).to receive(:tools_support).and_return(double(off?: true))
77
+ expect(chat.tools).to eq([])
78
+ end
79
+ end
80
+
81
+ describe '#default_enabled_tools' do
82
+ it 'returns configured tools that are marked as default and are registered' do
83
+ defaults = chat.default_enabled_tools
84
+ expect(defaults).to be_an(Array)
85
+ # Verify that every returned tool is actually registered
86
+ defaults.each { |t| expect(chat.tool_registered?(t)).to be true }
87
+ end
88
+ end
89
+
90
+ describe '#configured_tools' do
91
+ it 'returns a sorted list of all tools defined in the config' do
92
+ tools = chat.configured_tools
93
+ expect(tools).to be_an(Array)
94
+ expect(tools).to eq(tools.sort)
95
+ end
96
+ end
97
+
98
+ describe '#list_tools' do
99
+ it 'prints a formatted list of tools with their status' do
100
+ chat.session.tools_default_enabled = { 'read_file' => true, 'write_file' => false }
101
+
102
+ # We expect to see ✓ for read_file and ☐ for write_file
103
+ expect { chat.list_tools }.to output(/✓ .*read_file.*☐ .*write_file/m).to_stdout
104
+ end
105
+ end
106
+
107
+ describe '#enable_tool' do
108
+ it 'updates the session when a tool is selected from the menu' do
109
+ target_tool = chat.configured_tools.find { |t| !chat.session.tools_default_enabled[t] }
110
+ expect(target_tool).to be_present
111
+
112
+ # Mock choose_entry to return the target tool
113
+ expect(chat).to receive(:choose_entry).and_return(target_tool, '[EXIT]')
114
+
115
+ expect { chat.enable_tool }.to change {
116
+ chat.session.tools_default_enabled[target_tool]
117
+ }.from(false).to(true)
118
+ end
119
+
120
+ it 'warns the user if saving the session fails' do
121
+ target_tool = chat.configured_tools.find { |t| !chat.session.tools_default_enabled[t] }
122
+ expect(target_tool).to be_present
123
+
124
+ expect(chat).to receive(:choose_entry).and_return(target_tool, '[EXIT]')
125
+ expect(chat.session).to receive(:save).and_return(false)
126
+ expect(STDOUT).to receive(:puts).with(/Could not enable tool/)
127
+ expect(chat).to receive(:confirm?).and_return(true)
128
+ expect(STDOUT).to receive(:puts).with(/Exiting chooser./)
129
+ chat.enable_tool
130
+ end
131
+
132
+ it 'exits without and changes when [EXIT] is chosen' do
133
+ expect(chat).to receive(:choose_entry).and_return('[EXIT]')
134
+ initial_state = chat.session.tools_default_enabled.dup
135
+ chat.enable_tool
136
+ expect(chat.session.tools_default_enabled).to eq(initial_state)
137
+ end
138
+ end
139
+
140
+ describe '#disable_tool' do
141
+ it 'updates the session when a tool is deselected' do
142
+ target_tool = chat.configured_tools.first
143
+ chat.session.tools_default_enabled[target_tool] = true
144
+
145
+ expect(chat).to receive(:choose_entry).and_return(target_tool, '[EXIT]')
146
+
147
+ expect { chat.disable_tool }.to change {
148
+ chat.session.tools_default_enabled[target_tool]
149
+ }.from(true).to(false)
150
+ end
151
+
152
+ it 'warns the user if saving the session fails' do
153
+ target_tool = chat.configured_tools.find { |t| chat.session.tools_default_enabled[t] }
154
+ expect(target_tool).to be_present
155
+
156
+ chat.session.tools_default_enabled[target_tool] = true
157
+ expect(chat).to receive(:choose_entry).and_return(target_tool, '[EXIT]')
158
+ expect(chat.session).to receive(:save).and_return(false)
159
+ expect(STDOUT).to receive(:puts).with(/Could not disable tool/)
160
+ expect(chat).to receive(:confirm?).and_return(true)
161
+ expect(STDOUT).to receive(:puts).with(/Exiting chooser./)
162
+ chat.disable_tool
163
+ end
164
+ end
165
+
166
+ describe '#tool_paths_allowed' do
167
+ it 'returns a mapping of enabled tools to expanded existing paths' do
168
+ tool_name = chat.configured_tools.find { |t| chat.tool_function(t)[:allowed].present? }
169
+ expect(tool_name).to be_present
170
+ chat.session.tools_default_enabled[tool_name] = true
171
+ paths = chat.tool_paths_allowed
172
+ expect(paths).to have_key(tool_name)
173
+ expect(paths[tool_name]).to be_an(Array)
174
+ end
175
+ end
176
+
177
+ describe '#handle_tool_call_results?' do
178
+ it 'yields tool results to the provided block and then clears them' do
179
+ # Setup: inject tool results directly into the instance variable
180
+ chat.instance_variable_set(:@tool_call_results, {
181
+ 'read_file' => ['Content of file A', 'Content of file B']
182
+ })
183
+
184
+ processed = []
185
+ chat.send(:handle_tool_call_results?) do |index, tool, content|
186
+ processed << { idx: index, t: tool, c: content }
187
+ end
188
+
189
+ expect(processed).to eq([
190
+ { idx: 0, t: 'read_file', c: 'Content of file A' },
191
+ { idx: 1, t: 'read_file', c: 'Content of file B' }
192
+ ])
193
+ # Verify the buffer was cleared
194
+ expect(chat.instance_variable_get(:@tool_call_results)).to be_empty
195
+ end
196
+
197
+ it 'returns false if there are no results to process' do
198
+ chat.instance_variable_set(:@tool_call_results, {})
199
+ expect(chat.send(:handle_tool_call_results?) { }).to be false
200
+ end
201
+ end
202
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ollama_chat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.92
4
+ version: 0.0.94
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -155,14 +155,14 @@ dependencies:
155
155
  requirements:
156
156
  - - "~>"
157
157
  - !ruby/object:Gem::Version
158
- version: '1.21'
158
+ version: '1.22'
159
159
  type: :runtime
160
160
  prerelease: false
161
161
  version_requirements: !ruby/object:Gem::Requirement
162
162
  requirements:
163
163
  - - "~>"
164
164
  - !ruby/object:Gem::Version
165
- version: '1.21'
165
+ version: '1.22'
166
166
  - !ruby/object:Gem::Dependency
167
167
  name: documentrix
168
168
  requirement: !ruby/object:Gem::Requirement
@@ -574,6 +574,7 @@ files:
574
574
  - ".utilsrc"
575
575
  - CHANGES.md
576
576
  - Gemfile
577
+ - LICENSE
577
578
  - README.md
578
579
  - Rakefile
579
580
  - bin/ollama_chat
@@ -733,6 +734,7 @@ files:
733
734
  - spec/ollama_chat/state_selectors_spec.rb
734
735
  - spec/ollama_chat/switches_spec.rb
735
736
  - spec/ollama_chat/think_control_spec.rb
737
+ - spec/ollama_chat/tool_calling_spec.rb
736
738
  - spec/ollama_chat/tools/browse_spec.rb
737
739
  - spec/ollama_chat/tools/compute_bmi_spec.rb
738
740
  - spec/ollama_chat/tools/copy_to_clipboard_spec.rb
@@ -821,6 +823,7 @@ test_files:
821
823
  - spec/ollama_chat/state_selectors_spec.rb
822
824
  - spec/ollama_chat/switches_spec.rb
823
825
  - spec/ollama_chat/think_control_spec.rb
826
+ - spec/ollama_chat/tool_calling_spec.rb
824
827
  - spec/ollama_chat/tools/browse_spec.rb
825
828
  - spec/ollama_chat/tools/compute_bmi_spec.rb
826
829
  - spec/ollama_chat/tools/copy_to_clipboard_spec.rb