ollama_chat 0.0.74 → 0.0.76

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/.utilsrc +10 -0
  3. data/CHANGES.md +84 -0
  4. data/README.md +1 -0
  5. data/lib/ollama_chat/chat.rb +53 -15
  6. data/lib/ollama_chat/information.rb +11 -0
  7. data/lib/ollama_chat/location_handling.rb +8 -0
  8. data/lib/ollama_chat/message_list.rb +5 -33
  9. data/lib/ollama_chat/oc.rb +12 -0
  10. data/lib/ollama_chat/ollama_chat_config/default_config.yml +36 -7
  11. data/lib/ollama_chat/personae_management.rb +31 -12
  12. data/lib/ollama_chat/switches.rb +14 -0
  13. data/lib/ollama_chat/tool_calling.rb +13 -1
  14. data/lib/ollama_chat/tools/browse.rb +4 -4
  15. data/lib/ollama_chat/tools/copy_to_clipboard.rb +6 -5
  16. data/lib/ollama_chat/tools/directory_structure.rb +3 -2
  17. data/lib/ollama_chat/tools/execute_grep.rb +5 -1
  18. data/lib/ollama_chat/tools/execute_ri.rb +5 -1
  19. data/lib/ollama_chat/tools/file_context.rb +3 -4
  20. data/lib/ollama_chat/tools/gem_path_lookup.rb +15 -11
  21. data/lib/ollama_chat/tools/generate_password.rb +1 -1
  22. data/lib/ollama_chat/tools/get_current_weather.rb +5 -1
  23. data/lib/ollama_chat/tools/get_cve.rb +4 -1
  24. data/lib/ollama_chat/tools/get_endoflife.rb +7 -3
  25. data/lib/ollama_chat/tools/get_rfc.rb +5 -2
  26. data/lib/ollama_chat/tools/get_time.rb +4 -1
  27. data/lib/ollama_chat/tools/{import_url.rb → get_url.rb} +12 -13
  28. data/lib/ollama_chat/tools/insert_into_editor.rb +7 -7
  29. data/lib/ollama_chat/tools/open_file_in_editor.rb +11 -7
  30. data/lib/ollama_chat/tools/paste_from_clipboard.rb +7 -3
  31. data/lib/ollama_chat/tools/read_file.rb +5 -1
  32. data/lib/ollama_chat/tools/resolve_tag.rb +81 -0
  33. data/lib/ollama_chat/tools/run_tests.rb +34 -8
  34. data/lib/ollama_chat/tools/search_web.rb +6 -2
  35. data/lib/ollama_chat/tools/write_file.rb +4 -1
  36. data/lib/ollama_chat/tools.rb +3 -2
  37. data/lib/ollama_chat/utils/tag_resolver.rb +117 -0
  38. data/lib/ollama_chat/utils.rb +1 -0
  39. data/lib/ollama_chat/version.rb +1 -1
  40. data/lib/ollama_chat/web_searching.rb +1 -1
  41. data/ollama_chat.gemspec +5 -5
  42. data/spec/ollama_chat/chat_spec.rb +7 -1
  43. data/spec/ollama_chat/message_list_spec.rb +0 -29
  44. data/spec/ollama_chat/tools/{import_url_spec.rb → get_url_spec.rb} +9 -7
  45. data/spec/ollama_chat/tools/resolve_tag_spec.rb +86 -0
  46. data/spec/ollama_chat/tools/run_tests_spec.rb +5 -6
  47. metadata +11 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5cf8d81848dd2c573db23ac8182a092822bc273ba1d224307e756ab7e6741698
4
- data.tar.gz: ce5219be13b5293b477a89a9d1b187ec78dd06322b0e96275d7316f006d4828b
3
+ metadata.gz: c2fd2a7be9e054baac6b811b1a30fff33839905d39b4784d8aba2bbd6c5f3538
4
+ data.tar.gz: f1ff0f8a94cc8c55f43928a7e09153a92cfa4b8b0b890f1b52a7511c7fb18195
5
5
  SHA512:
6
- metadata.gz: a010b8f1cc2ce2eed10d873ec28b5c3c60af9f9f025af0d6db21c3103d7247cd433ea638b9ce78efb5659e5515ef8e15f7136e193c3470d5f87183f1939adc8e
7
- data.tar.gz: e2e0d34db7b81234f97e10e6e20e0747640ad15ac087c36c430c6d47540489414241c965a2759f31b3cf9bd9c6477c1d363793cb67f14c2769c03156f3ab2411
6
+ metadata.gz: fef0b8733d62c5769b4675f769a30cddec686806347b04325b7d0ec8d65c7e546e70d1829ebf423240c32683c07afd124770def3305556e395f174eb0a030c6e
7
+ data.tar.gz: e14e370d2391fa9d2e90b70831c389ff3edcd86b89f7cad55586125c12675bb65ab5b16eab14029f918c7478e54b7e31b1ede609110c64391b8a6376939620d4
data/.utilsrc CHANGED
@@ -33,15 +33,25 @@ code_indexer do
33
33
  verbose false
34
34
 
35
35
  gems = %w[
36
+ all_images
36
37
  amatch
37
38
  base64
38
39
  bigdecimal
39
40
  complex_config
41
+ const_conf
42
+ context_spook
43
+ csv
40
44
  date
41
45
  documentrix
42
46
  excon
47
+ fileutils
48
+ gem_hadar
49
+ infobar
50
+ irb
43
51
  json
52
+ kramdown
44
53
  kramdown-ansi
54
+ kramdown-parser-gfm
45
55
  mize
46
56
  more_math
47
57
  ollama-ruby
data/CHANGES.md CHANGED
@@ -1,5 +1,89 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-03-09 v0.0.76
4
+
5
+ - Added `client:` and `current_directory:` keys to `runtime_info_values` in
6
+ `chat.rb`.
7
+ - Implemented `#client` method returning `"progname **0.0.75**"` in
8
+ `information.rb`.
9
+ - Introduced helper `location_description?` in `location_handling.rb`.
10
+ - Simplified `MessageList#to_ary` to return a duplicate of the internal array,
11
+ removing automatic system prompt + location injection.
12
+ - Updated default config placeholders for `%{client}` and
13
+ `%{current_directory}` in `default_config.yml`.
14
+ - Adjusted web searching logic to use `location_description?` instead of
15
+ deprecated methods.
16
+ - Removed tests that expected location‑augmented system prompts from
17
+ `spec/ollama_chat/message_list_spec.rb`.
18
+ - Standardized JSON output formatting across tools: aligned JSON keys, added
19
+ spaces after commas, and added trailing commas in tool responses such as
20
+ `copy_to_clipboard`, `gem_path_lookup`, `generate_password`, `get_endoflife`,
21
+ `get_rfc`, `insert_into_editor`, `open_file_in_editor`,
22
+ `paste_from_clipboard`, and `search_web`.
23
+ - Added trailing commas to JSON objects for consistency and easier future
24
+ edits.
25
+ - Standardized error field formatting, ensuring each error block includes a
26
+ space after the colon and a trailing comma where appropriate.
27
+ - Added helper `disable_content_parsing` in `chat.rb` that sets `@parse_content
28
+ = false`.
29
+ - Refactored command handlers to call `disable_content_parsing` instead of
30
+ assigning directly to `@parse_content`.
31
+ - Updated persona setup logic so that a returned persona result triggers
32
+ `disable_content_parsing`; otherwise parsing is enabled with
33
+ `enable_command_completion`.
34
+ - Added explanatory comments around the new helper for clarity.
35
+ - Improved clean flow: captured return value of `clean` and set `@parse_content
36
+ = true` when a persona profile is returned.
37
+ - Replaced old flag `@persona_setup` with `@default_persona`; ensured it
38
+ defaults to `:none` in an `ensure` block after setup.
39
+ - Added new method `reload_default_persona` that prompts for confirmation
40
+ before reloading the default persona file if one exists.
41
+ - Modified `clean(what)` to return the result of `reload_default_persona`,
42
+ enabling the caller to react to a reload.
43
+ - Adjusted `/clear` command handling in the chat loop to use the returned value
44
+ from `clean` and only proceed when nothing is returned.
45
+ - Renamed local variable `runtime_info` to `runtime_info_values` in `chat.rb`
46
+ for clarity.
47
+ - Updated runtime info prompt interpolation to use `runtime_info_values`
48
+ instead of `runtime_info`.
49
+ - Updated `/.utilsrc` by adding gems to the `code_indexer` configuration:
50
+ `all_images`, `const_conf`, `context_spook`, `csv`, `fileutils`, `gem_hadar`,
51
+ `infobar`, `irb`, `kramdown`, and `kramdown-parser-gfm`.
52
+
53
+ ## 2026-03-08 v0.0.75
54
+
55
+ - Added runtime reporting of tool allowed paths by introducing
56
+ `tool_paths_allowed` method and including it in chat output, updating config
57
+ prompt, and normalizing tool name handling.
58
+ - Added new tool `OllamaChat::Tools::ResolveTag` with utility
59
+ `OllamaChat::Utils::TagResolver` to parse tag files; enabled in
60
+ `default_config.yml` and added corresponding tests.
61
+ - Introduced `runtime_info` switch in `OllamaChat::Switches`; added
62
+ `/runtime_info` command handling in `chat.rb`, runtime info block injection,
63
+ and display via `information.rb`; added `prompts/runtime_info` template and
64
+ `languages:` array; added `runtime_info.toggle`, `runtime_info.show`,
65
+ `runtime_info.on?`, `runtime_info.enabled` support.
66
+ - Updated `OllamaChat::Tools::DirectoryStructure` description to note it can
67
+ locate one or multiple files, referencing `max_depth`.
68
+ - Clarified usage of `browse`, `copy_to_clipboard`, `open_file_in_editor`,
69
+ `insert_into_editor` tools in documentation strings; fixed double‑negative
70
+ typo in `insert_into_editor.rb`.
71
+ - Renamed `import_url` tool to `get_url`: updated config key, tool
72
+ registration, class name `OllamaChat::Tools::GetURL`, spec file names, method
73
+ calls to `config.tools.functions.get_url.schemes?`, replaced all
74
+ `chat.import` with `OllamaChat::Utils::Fetcher.get`.
75
+ - Added path validation and error handling to `OllamaChat::Tools::RunTests`:
76
+ new private method `check_path(path)` prevents using `"./"` and validates
77
+ existence; wrapped execution in rescue block returning JSON with `error:` and
78
+ `message:`; updated function description accordingly.
79
+ - Refined and unified tool descriptions with consistent punctuation.
80
+ - Added explicit persona loading verification when editing: confirmation step
81
+ before applying edited personality configurations.
82
+ - Improved persona loading and prompt formatting: updated
83
+ `setup_persona_from_opts`, `info_persona`, `load_persona_file` to return
84
+ `[pathname, content]`, added newline in `play_persona_prompt`, adjusted
85
+ `play_persona` to handle new return value.
86
+
3
87
  ## 2026-03-06 v0.0.74
4
88
 
5
89
  - Added new tool `ExecuteRI` in `lib/ollama_chat/tools/execute_ri.rb` that
data/README.md CHANGED
@@ -158,6 +158,7 @@ The following commands can be given inside the chat, if prefixed by a `/`:
158
158
  /markdown toggle markdown output
159
159
  /stream toggle stream output
160
160
  /location toggle location submission
161
+ /runtime_info toggle runtime information in prompts
161
162
  /voice [change] toggle voice output or change the voice
162
163
  /last [n] show the last n / 1 system/assistant message
163
164
  /list [n] list the last n / all conversation exchanges
@@ -192,6 +192,15 @@ class OllamaChat::Chat
192
192
  @links ||= Set.new
193
193
  end
194
194
 
195
+ # The disable_content_parsing method turns off content parsing by setting
196
+ # @parse_content to false.
197
+ #
198
+ # This prevents automatic parsing of user input content during chat
199
+ # processing.
200
+ def disable_content_parsing
201
+ @parse_content = false
202
+ end
203
+
195
204
  # Handles user input commands and processes chat interactions.
196
205
  #
197
206
  # @param content [String] The input content to process
@@ -208,7 +217,7 @@ class OllamaChat::Chat
208
217
  copy_to_clipboard
209
218
  :next
210
219
  when %r(^/paste$)
211
- @parse_content = false
220
+ disable_content_parsing
212
221
  paste_from_clipboard
213
222
  when %r(^/markdown$)
214
223
  markdown.toggle
@@ -219,6 +228,9 @@ class OllamaChat::Chat
219
228
  when %r(^/location$)
220
229
  location.toggle
221
230
  :next
231
+ when %r(^/runtime_info$)
232
+ runtime_info.toggle
233
+ :next
222
234
  when %r(^/voice(?:\s+(change))?$)
223
235
  if $1 == 'change'
224
236
  change_voice
@@ -235,8 +247,12 @@ class OllamaChat::Chat
235
247
  messages.show_last(n)
236
248
  :next
237
249
  when %r(^/clear(?:\s+(messages|links|history|tags|all))?$)
238
- clean($1)
239
- :next
250
+ if result = clean($1)
251
+ disable_content_parsing
252
+ content = result
253
+ else
254
+ :next
255
+ end
240
256
  when %r(^/clobber$)
241
257
  clean('all')
242
258
  :next
@@ -272,7 +288,7 @@ class OllamaChat::Chat
272
288
  STDOUT.puts "Not enough messages in this conversation."
273
289
  return :redo
274
290
  end
275
- @parse_content = false
291
+ disable_content_parsing
276
292
  content
277
293
  when %r(^/collection(?:\s+(clear|change))?$)
278
294
  case $1 || 'change'
@@ -316,30 +332,30 @@ class OllamaChat::Chat
316
332
  think_loud.toggle
317
333
  :next
318
334
  when %r(^/import\s+(.+))
319
- @parse_content = false
335
+ disable_content_parsing
320
336
  import($1) or :next
321
337
  when %r(^/summarize\s+(?:(\d+)\s+)?(.+))
322
- @parse_content = false
338
+ disable_content_parsing
323
339
  summarize($2, words: $1) or :next
324
340
  when %r(^/embedding$)
325
341
  embedding_paused.toggle(show: false)
326
342
  embedding.show
327
343
  :next
328
344
  when %r(^/embed\s+(.+))
329
- @parse_content = false
345
+ disable_content_parsing
330
346
  embed($1) or :next
331
347
  when %r(^/web\s+(?:(\d+)\s+)?(.+))
332
- @parse_content = false
348
+ disable_content_parsing
333
349
  web($1, $2)
334
350
  when %r(^/input(?:\s+(.+))?$)
335
351
  arg = $1
336
352
  arg and patterns = arg.scan(/(\S+)/).flatten
337
- @parse_content = false
353
+ disable_content_parsing
338
354
  input(patterns) or :next
339
355
  when %r(^/context(?:\s+(.+))?$)
340
356
  arg = $1
341
357
  arg and patterns = arg.scan(/(\S+)/).flatten
342
- @parse_content = false
358
+ disable_content_parsing
343
359
  context_spook(patterns) or :next
344
360
  when %r(^/compose$)
345
361
  compose or :next
@@ -393,7 +409,7 @@ class OllamaChat::Chat
393
409
  end
394
410
  :next
395
411
  when %r(^/persona(?:\s+(add|delete|edit|file|info|list|load|play))?$)
396
- @parse_content = false
412
+ disable_content_parsing
397
413
  case $1
398
414
  when 'add'
399
415
  if result = add_persona
@@ -408,7 +424,9 @@ class OllamaChat::Chat
408
424
  :next
409
425
  end
410
426
  when 'edit'
411
- if result = edit_persona
427
+ if result = edit_persona and
428
+ ask?(prompt: 'Load new persona profile? (y/n) ') =~ /\Ay/i
429
+ then
412
430
  result
413
431
  else
414
432
  :next
@@ -448,7 +466,7 @@ class OllamaChat::Chat
448
466
  STDOUT.puts "Goodbye."
449
467
  :return
450
468
  when %r(^/help me$)
451
- @parse_content = false
469
+ disable_content_parsing
452
470
  config.prompts.help % { commands: display_chat_help_message }
453
471
  when %r(^/)
454
472
  display_chat_help
@@ -575,9 +593,11 @@ class OllamaChat::Chat
575
593
  # @param what [ String, nil ] the type of data to clear, defaults to
576
594
  # 'messages' if nil
577
595
  def clean(what)
596
+ persona_profile = nil
578
597
  case what
579
598
  when 'messages', nil
580
599
  messages.clear
600
+ persona_profile = reload_default_persona
581
601
  STDOUT.puts "Cleared messages."
582
602
  when 'links'
583
603
  links.clear
@@ -594,11 +614,13 @@ class OllamaChat::Chat
594
614
  @documents.clear
595
615
  links.clear
596
616
  clear_history
617
+ persona_profile = reload_default_persona
597
618
  STDOUT.puts "Cleared messages and collection #{bold{@documents.collection}}."
598
619
  else
599
620
  STDOUT.puts 'Cancelled.'
600
621
  end
601
622
  end
623
+ persona_profile
602
624
  end
603
625
 
604
626
  # The interact_with_user method manages the interactive loop for user input
@@ -616,7 +638,7 @@ class OllamaChat::Chat
616
638
  def interact_with_user
617
639
  loop do
618
640
  if persona_result = setup_persona_from_opts
619
- @parse_content = false
641
+ disable_content_parsing
620
642
  content = persona_result
621
643
  else
622
644
  @parse_content = true
@@ -624,7 +646,7 @@ class OllamaChat::Chat
624
646
  input_prompt = bold { color(172) { message_type(@images) + " user" } } + bold { "> " }
625
647
  begin
626
648
  if content = handle_tool_call_results?
627
- @parse_content = false
649
+ disable_content_parsing
628
650
  else
629
651
  content = enable_command_completion do
630
652
  if prefill_prompt = @prefill_prompt.full?
@@ -685,6 +707,22 @@ class OllamaChat::Chat
685
707
  end
686
708
  end
687
709
 
710
+ if runtime_info.on? && content
711
+ runtime_info_values = {
712
+ languages: config.languages * ', ',
713
+ location: location.on? ? location_description.inspect : 'n/a',
714
+ client: ,
715
+ current_directory: Pathname.pwd.expand_path.to_path.inspect,
716
+ terminal_rows: Tins::Terminal.rows,
717
+ terminal_cols: Tins::Terminal.cols,
718
+ time: Time.now.iso8601,
719
+ voice: voice.on? ? 'enabled' : 'disabled',
720
+ markdown: markdown.on? ? 'enabled' : 'disabled',
721
+ tool_paths_allowed: JSON(tool_paths_allowed),
722
+ }
723
+ content << config.prompts.runtime_info % runtime_info_values
724
+ end
725
+
688
726
  messages << Ollama::Message.new(role: 'user', content:, images: @images.dup)
689
727
  @images.clear
690
728
  handler = OllamaChat::FollowChat.new(
@@ -55,6 +55,15 @@ module OllamaChat::Information
55
55
  end
56
56
  end
57
57
 
58
+ # The client method returns the application name and its current version as a
59
+ # single string
60
+ #
61
+ # @return [ String ] the progname followed by the OllamaChat version
62
+ # separated by a space
63
+ def client
64
+ [ progname, OllamaChat::VERSION ] * ' '
65
+ end
66
+
58
67
  # The collection_stats method displays statistics about the current document
59
68
  # collection.
60
69
  #
@@ -103,6 +112,7 @@ module OllamaChat::Information
103
112
  think_mode.show
104
113
  think_loud.show
105
114
  location.show
115
+ runtime_info.show
106
116
  voice.show
107
117
  @voice.on? and @voices.show
108
118
  tools_support.show
@@ -124,6 +134,7 @@ module OllamaChat::Information
124
134
  /markdown toggle markdown output
125
135
  /stream toggle stream output
126
136
  /location toggle location submission
137
+ /runtime_info toggle runtime information in prompts
127
138
  /voice [change] toggle voice output or change the voice
128
139
  /last [n] show the last n / 1 system/assistant message
129
140
  /list [n] list the last n / all conversation exchanges
@@ -24,6 +24,14 @@ module OllamaChat::LocationHandling
24
24
  config.prompts.location % location_data
25
25
  end
26
26
 
27
+ # The location_description? method returns the location description string if
28
+ # the location setting is enabled; otherwise it returns nil.
29
+ #
30
+ # @return [String, nil]
31
+ def location_description?
32
+ location_description if location.on?
33
+ end
34
+
27
35
  # Generates a hash containing current location data.
28
36
  #
29
37
  # This method collects and returns structured location information including
@@ -1,14 +1,13 @@
1
1
  # A collection class for managing chat messages with support for system
2
2
  # prompts, paged output, and conversation history.
3
-
3
+ #
4
4
  # This class provides functionality for storing, retrieving, and displaying
5
5
  # chat messages in a structured manner. It handles system prompts separately
6
6
  # from regular user and assistant messages, supports pagination for displaying
7
7
  # conversations, and offers methods for manipulating message history including
8
8
  # clearing, loading, saving, and dropping exchanges. The class integrates with
9
- # Kramdown::ANSI for formatted output and supports location information in
10
- # system messages.
11
-
9
+ # Kramdown::ANSI for formatted output.
10
+ #
12
11
  # @example Creating a new message list
13
12
  # chat = OllamaChat::Chat.new
14
13
  # messages = OllamaChat::MessageList.new(chat)
@@ -285,39 +284,12 @@ class OllamaChat::MessageList
285
284
  end
286
285
 
287
286
  # The to_ary method converts the message list into an array of
288
- # Ollama::Message objects. If location support was enabled and the message
289
- # list contains a system message, the system messages is decorated with the
290
- # curent location, time, and unit preferences.
287
+ # Ollama::Message objects.
291
288
  #
292
289
  # @return [Array] An array of Ollama::Message objects representing the
293
290
  # messages in the list.
294
291
  def to_ary
295
- location = at_location.full?
296
- add_system = !!location
297
- result = @messages.map do |message|
298
- if message.role == 'system' && location
299
- add_system = false
300
- content = message.content + "\n\n#{location}"
301
- Ollama::Message.new(role: message.role, content:)
302
- else
303
- message
304
- end
305
- end
306
- if add_system
307
- prompt = @chat.config.system_prompts.assistant?
308
- content = [ prompt, location ].compact * "\n\n"
309
- message = Ollama::Message.new(role: 'system', content:)
310
- result.unshift message
311
- end
312
- result
313
- end
314
-
315
- # The at_location method returns the location/time/units information as a
316
- # string if location is enabled.
317
- #
318
- # @return [ String ] the location information
319
- def at_location
320
- @chat.location_description if @chat.location.on?
292
+ @messages.dup
321
293
  end
322
294
 
323
295
  private
@@ -150,6 +150,18 @@ module OC
150
150
  description 'Pirate Weather API key'
151
151
  end
152
152
 
153
+ CTAGS_TOOL = set do
154
+ description 'Tools ctags path'
155
+ default { `which ctags`.full?(:chomp) }
156
+ check { value.blank? || File.exist?(value) }
157
+ end
158
+
159
+ TAGS_FILE = set do
160
+ description 'Tag file location'
161
+ default './tags'
162
+ decode { Pathname.new(_1).expand_path }
163
+ end
164
+
153
165
  module JIRA
154
166
  description 'Jira tool configuration'
155
167
 
@@ -8,11 +8,15 @@ timeouts:
8
8
  connect_timeout: null
9
9
  read_timeout: 300
10
10
  write_timeout: 300
11
+ languages:
12
+ - en-US
11
13
  location:
12
14
  enabled: false
13
15
  name: Berlin
14
16
  decimal_degrees: [ 52.514127, 13.475211 ]
15
17
  units: SI (International System of Units) # or USCS (United States Customary System)
18
+ runtime_info:
19
+ enabled: true
16
20
  prompts:
17
21
  embed: "This source was now embedded: %{source}"
18
22
  summarize: |
@@ -31,14 +35,37 @@ prompts:
31
35
 
32
36
  %{results}
33
37
  location: You are at %{location_name}, %{location_decimal_degrees}, preferring %{units}
38
+ runtime_info: |
39
+
40
+ ---
41
+
42
+ **Runtime Information**
43
+
44
+ There is usually no reason to mention this information to the user unless
45
+ asked about it.
46
+
47
+ - Languages the user prefers: %{languages}.
48
+ - Location is %{location}.
49
+ - Current directory is %{current_directory}.
50
+ - Client is %{client}.
51
+ - Terminal has %{terminal_rows} rows.
52
+ - Terminal width is %{terminal_cols} columns. **Always** aim to stay within
53
+ 80%% of this width in your output of responses, especially when using
54
+ markdown tables.
55
+ - Current time is %{time}.
56
+ - Markdown output is %{markdown}. **Never** output markdown as your
57
+ responses if it is disabled.
58
+ - Voice output is %{voice}. Speak naturally and short if voice
59
+ output is enabled.
60
+ - These tools have access to these allowed paths: %{tool_paths_allowed}
34
61
  help: |
35
- Wait for the user to ask questions about the usage of chat commands. Just
36
- list the command names separated by spaces (no descriptions yet) and
37
- offer to answer any questions about any of them. Interactively help the
38
- user by answering questions about the following
39
- chat commands:
62
+ Wait for the user to ask questions about the usage of chat commands. Just
63
+ list the command names separated by spaces (no descriptions yet) and
64
+ offer to answer any questions about any of them. Interactively help the
65
+ user by answering questions about the following
66
+ chat commands:
40
67
 
41
- %{commands}
68
+ %{commands}
42
69
  persona: |
43
70
  # Persona
44
71
 
@@ -173,7 +200,7 @@ tools:
173
200
  default: true
174
201
  require_confirmation: true
175
202
  max_results: 25
176
- import_url:
203
+ get_url:
177
204
  default: true
178
205
  require_confirmation: true
179
206
  schemes:
@@ -203,3 +230,5 @@ tools:
203
230
  default: true
204
231
  execute_ri:
205
232
  default: true
233
+ resolve_tag:
234
+ default: true
@@ -35,9 +35,11 @@ module OllamaChat::PersonaeManagement
35
35
  FileUtils.mkdir_p personae_backup_directory
36
36
  end
37
37
 
38
+ # The setup_persona_from_opts method initializes persona setup by checking
39
+ # for a provided persona option, determining the appropriate file path, and
40
+ # playing the persona file if it exists.
38
41
  def setup_persona_from_opts
39
- @persona_setup and return
40
- @persona_setup = true
42
+ @default_persona and return
41
43
  if persona = @opts[?p].full? { Pathname.new(_1) }
42
44
  if persona.extname == '.md'
43
45
  pathname = persona
@@ -45,15 +47,28 @@ module OllamaChat::PersonaeManagement
45
47
  pathname = personae_directory + (persona.to_s + '.md')
46
48
  end
47
49
  if pathname.exist?
50
+ @default_persona = pathname
48
51
  play_persona_file pathname
49
52
  end
50
53
  end
54
+ ensure
55
+ @default_persona ||= :none
56
+ end
57
+
58
+ # Reloads the default persona file if one is set and not :none, prompting the
59
+ # user for confirmation before playing the persona file.
60
+ def reload_default_persona
61
+ !@default_persona || @default_persona == :none and return
62
+ prompt = "Reload default persona #{@default_persona.basename.sub_ext('')}? (y/n) "
63
+ if ask?(prompt:) =~ /\Ay/i
64
+ play_persona_file @default_persona
65
+ end
51
66
  end
52
67
 
53
68
  # Returns a sorted list of available persona file names.
54
69
  #
55
- # This method scans the personae directory for Markdown files and
56
- # returns their basenames sorted alphabetically.
70
+ # This method scans the personae directory for Markdown files and returns
71
+ # their basenames sorted alphabetically.
57
72
  #
58
73
  # @return [Array<String>] Sorted array of persona filenames without extension
59
74
  def available_personae
@@ -160,7 +175,7 @@ module OllamaChat::PersonaeManagement
160
175
  # Shows the persona's profile using kramdown formatting with ansi parsing.
161
176
  def info_persona
162
177
  if persona = choose_persona
163
- persona_profile = load_persona_file(persona)
178
+ _persona, persona_profile = load_persona_file(persona)
164
179
  use_pager do |output|
165
180
  output.puts kramdown_ansi_parse(<<~EOT)
166
181
  # Persona #{persona.sub_ext('')}
@@ -247,13 +262,17 @@ module OllamaChat::PersonaeManagement
247
262
  result.to_json
248
263
  end
249
264
 
250
- # Reads and returns the content of a persona file.
265
+ # Loads a persona file from disk.
251
266
  #
252
- # @param persona [String] The persona filename to read
253
- # @return [String] The content of the persona file
267
+ # @param persona [String] The basename of the persona (without extension)
268
+ #
269
+ # @return [Array<Pathname, String>] Returns the pathname and its content as a
270
+ # string
254
271
  def load_persona_file(persona)
255
272
  pathname = personae_directory + persona
256
- pathname.read if pathname.exist?
273
+ if pathname.exist?
274
+ return pathname, pathname.read
275
+ end
257
276
  end
258
277
 
259
278
  # Generates the roleplay prompt string for a persona.
@@ -265,7 +284,7 @@ module OllamaChat::PersonaeManagement
265
284
  # @return [String] Formatted roleplay prompt
266
285
  def play_persona_prompt(persona:, persona_profile:)
267
286
  persona_name = persona.basename.sub_ext('')
268
- "Roleplay as persona %{persona_name} loaded from %{persona}\n%{persona_profile}" % {
287
+ "Roleplay as persona %{persona_name} loaded from %{persona}\n\n%{persona_profile}" % {
269
288
  persona_name:, persona:, persona_profile:
270
289
  }
271
290
  end
@@ -275,8 +294,8 @@ module OllamaChat::PersonaeManagement
275
294
  # Uses the persona selection and loading methods to generate the
276
295
  # appropriate roleplay prompt.
277
296
  def play_persona(pathname: nil)
278
- persona = choose_persona or return
279
- persona_profile = load_persona_file(persona)
297
+ persona = choose_persona or return
298
+ persona, persona_profile = load_persona_file(persona)
280
299
  play_persona_prompt(persona:, persona_profile:)
281
300
  end
282
301
 
@@ -171,6 +171,13 @@ module OllamaChat::Switches
171
171
  # @return [ OllamaChat::Switches::Switch ] the location setting object
172
172
  attr_reader :location
173
173
 
174
+ # Provides access to the runtime_info switch controlling the visibility of
175
+ # runtime information in the chat
176
+ #
177
+ # @attr_reader [ Switches::Switch ] a Switch instance that manages runtime
178
+ # info visibility
179
+ attr_reader :runtime_info
180
+
174
181
  # Switch tools support on/off (off → skip all, on → honour per‑tool state)
175
182
  #
176
183
  # @return [OllamaChat::Switch] the tools_support setting object
@@ -250,6 +257,13 @@ module OllamaChat::Switches
250
257
  }
251
258
  )
252
259
 
260
+ @runtime_info = Switch.new(
261
+ value: config.runtime_info.enabled,
262
+ msg: {
263
+ true => "Runtime Information enabled.",
264
+ false => "Runtime Information disabled.",
265
+ }
266
+ )
253
267
  @tools_support = Switch.new(
254
268
  value: config.tools.enabled,
255
269
  msg: {
@@ -42,7 +42,7 @@ module OllamaChat::ToolCalling
42
42
  # @param [String] name the name of the tool
43
43
  # @return [true, false] true if the tool is enabled
44
44
  def tool_enabled?(name)
45
- enabled_tools.member?(name)
45
+ enabled_tools.member?(name.to_s)
46
46
  end
47
47
 
48
48
  # The tools reader returns the registered tools for the chat session.
@@ -153,6 +153,18 @@ module OllamaChat::ToolCalling
153
153
  end
154
154
  end
155
155
 
156
+ # The tool_paths_allowed method returns a hash mapping each enabled tool name
157
+ # to its list of allowed paths or patterns. @return [Hash] a hash where keys
158
+ # are tool names and values are the allowed path lists
159
+ def tool_paths_allowed
160
+ config.tools.functions.to_h.
161
+ select { |name, value| tool_enabled?(name) && value[:allowed].present? }.
162
+ sort_by(&:first).
163
+ each_with_object({}) { |(name, value), hash|
164
+ hash[name] = value[:allowed].map { Pathname.new(_1).expand_path.to_s }
165
+ }
166
+ end
167
+
156
168
  private
157
169
 
158
170
  # The handle_tool_call_results? method processes and returns results from