ollama_chat 0.0.98 → 0.0.100

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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +112 -0
  3. data/Rakefile +2 -2
  4. data/lib/ollama_chat/chat.rb +57 -18
  5. data/lib/ollama_chat/commands.rb +169 -216
  6. data/lib/ollama_chat/database/migrations/006_rename_system_prompt_context_to_system.rb +13 -0
  7. data/lib/ollama_chat/database/models/prompt.rb +14 -23
  8. data/lib/ollama_chat/dialog.rb +1 -1
  9. data/lib/ollama_chat/document_cache.rb +5 -1
  10. data/lib/ollama_chat/favourites_management.rb +2 -5
  11. data/lib/ollama_chat/follow_chat.rb +15 -14
  12. data/lib/ollama_chat/information.rb +17 -4
  13. data/lib/ollama_chat/logging.rb +24 -6
  14. data/lib/ollama_chat/message.rb +27 -6
  15. data/lib/ollama_chat/message_list.rb +32 -11
  16. data/lib/ollama_chat/model_handling.rb +51 -33
  17. data/lib/ollama_chat/ollama_chat_config/default_config.yml +318 -182
  18. data/lib/ollama_chat/parsing.rb +22 -6
  19. data/lib/ollama_chat/personae_management.rb +24 -11
  20. data/lib/ollama_chat/prompt_handling.rb +18 -56
  21. data/lib/ollama_chat/prompt_management.rb +89 -73
  22. data/lib/ollama_chat/session_management.rb +65 -14
  23. data/lib/ollama_chat/source_fetching.rb +2 -1
  24. data/lib/ollama_chat/system_prompt_management.rb +4 -246
  25. data/lib/ollama_chat/tools/browse.rb +4 -2
  26. data/lib/ollama_chat/tools/compute_bmi.rb +1 -0
  27. data/lib/ollama_chat/tools/copy_to_clipboard.rb +9 -17
  28. data/lib/ollama_chat/tools/delete_file.rb +3 -1
  29. data/lib/ollama_chat/tools/directory_structure.rb +5 -1
  30. data/lib/ollama_chat/tools/eval_ruby.rb +7 -2
  31. data/lib/ollama_chat/tools/execute_grep.rb +3 -1
  32. data/lib/ollama_chat/tools/execute_ri.rb +2 -0
  33. data/lib/ollama_chat/tools/file_context.rb +1 -0
  34. data/lib/ollama_chat/tools/gem_path_lookup.rb +8 -6
  35. data/lib/ollama_chat/tools/generate_image.rb +1 -0
  36. data/lib/ollama_chat/tools/generate_password.rb +13 -2
  37. data/lib/ollama_chat/tools/get_current_weather.rb +1 -0
  38. data/lib/ollama_chat/tools/get_cve.rb +1 -0
  39. data/lib/ollama_chat/tools/get_endoflife.rb +1 -0
  40. data/lib/ollama_chat/tools/get_ghr.rb +1 -0
  41. data/lib/ollama_chat/tools/get_jira_issue.rb +2 -0
  42. data/lib/ollama_chat/tools/get_location.rb +3 -0
  43. data/lib/ollama_chat/tools/get_rfc.rb +1 -0
  44. data/lib/ollama_chat/tools/get_time.rb +5 -1
  45. data/lib/ollama_chat/tools/get_url.rb +1 -0
  46. data/lib/ollama_chat/tools/move_file.rb +3 -1
  47. data/lib/ollama_chat/tools/open_file_in_editor.rb +4 -0
  48. data/lib/ollama_chat/tools/paste_from_clipboard.rb +1 -0
  49. data/lib/ollama_chat/tools/paste_into_editor.rb +7 -13
  50. data/lib/ollama_chat/tools/patch_file.rb +163 -39
  51. data/lib/ollama_chat/tools/read_file.rb +51 -39
  52. data/lib/ollama_chat/tools/resolve_tag.rb +3 -1
  53. data/lib/ollama_chat/tools/retrieve_document_snippets.rb +2 -1
  54. data/lib/ollama_chat/tools/roll_dice.rb +1 -0
  55. data/lib/ollama_chat/tools/run_tests.rb +3 -1
  56. data/lib/ollama_chat/tools/search_web.rb +1 -0
  57. data/lib/ollama_chat/tools/write_file.rb +3 -1
  58. data/lib/ollama_chat/utils/tag_resolver.rb +1 -1
  59. data/lib/ollama_chat/uuid_v7.rb +33 -0
  60. data/lib/ollama_chat/version.rb +1 -1
  61. data/lib/ollama_chat.rb +9 -0
  62. data/ollama_chat.gemspec +8 -8
  63. data/spec/assets/example.epub +0 -0
  64. data/spec/ollama_chat/chat_spec.rb +3 -3
  65. data/spec/ollama_chat/follow_chat_spec.rb +6 -2
  66. data/spec/ollama_chat/history_spec.rb +1 -1
  67. data/spec/ollama_chat/message_list_spec.rb +85 -29
  68. data/spec/ollama_chat/parsing_spec.rb +11 -2
  69. data/spec/ollama_chat/session_management_spec.rb +324 -0
  70. data/spec/ollama_chat/source_fetching_spec.rb +26 -0
  71. data/spec/ollama_chat/tools/copy_to_clipboard_spec.rb +13 -14
  72. data/spec/ollama_chat/tools/directory_structure_spec.rb +1 -1
  73. data/spec/ollama_chat/tools/execute_ri_spec.rb +4 -4
  74. data/spec/ollama_chat/tools/gem_path_lookup_spec.rb +8 -2
  75. data/spec/ollama_chat/tools/get_jira_issue_spec.rb +3 -3
  76. data/spec/ollama_chat/tools/get_url_spec.rb +7 -7
  77. data/spec/ollama_chat/tools/paste_into_editor_spec.rb +1 -35
  78. data/spec/ollama_chat/tools/patch_file_spec.rb +121 -87
  79. data/spec/ollama_chat/tools/read_file_spec.rb +76 -0
  80. data/spec/ollama_chat/tools/resolve_tag_spec.rb +2 -2
  81. data/spec/ollama_chat/tools/write_file_spec.rb +15 -11
  82. metadata +13 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3794355ad924879293253f68420d41eb6e5bc4e766d20fbb9292dea3f9905372
4
- data.tar.gz: 907e863402ec2bb4a225dc21a47751b69bf2f3b72e8776bd9eeba70f275a5f72
3
+ metadata.gz: 436406ccfaa267c8996e6986759b3f79773ad8b48127ed8b7f7bd749b8c82dd1
4
+ data.tar.gz: f2a66b87ebc221adf19e382568979f57baabfabef49929e123bbe0cc1932916d
5
5
  SHA512:
6
- metadata.gz: e8cfbc674eaa28164c9599686db526d70c7aeb1076ce9b2b6d160fb220f712c376a06df3dd41a55e327c26c965c8e06e049ade22dd886bd3c8555967e0658865
7
- data.tar.gz: 42da21a93f2295cd0cdbc01c8ad4bd2a12a93fb017c00e086336f46b2a358f29dea2b87a454298673c1d913404b1cf472682d1c7d56f3c82d961a0f40a8b63ed
6
+ metadata.gz: 576fc144f38595bec62043b30c170dc65a2bb891df41ab36bdd1b4bef2ad32dbe0b72b413d0e0f785604c0c0e3add5ca847e6da25144011518d67241b7fb8771
7
+ data.tar.gz: e3c808321e651a55bdf29326d41150700bcd2c8b28d4b2b407c49fdd6aff156e4e4d8555eafb1cf10c46589e44963714dafea95f667305c4173e788cd514da7f
data/CHANGES.md CHANGED
@@ -1,5 +1,117 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-07-23 v0.0.100
4
+
5
+ ### New Features
6
+
7
+ - **UUID v7 Integration**: Implemented a compatibility shim via
8
+ `OllamaChat::UUIDV7.generate` that utilizes native `SecureRandom.uuid_v7` for
9
+ Ruby **3.3**+ and a custom RFC 9562 compliant implementation for older
10
+ versions.
11
+ - **Document Parsing & Embeddings**:
12
+ - Added EPUB support using `pandoc` via the `epub_read` method and updated
13
+ `parse_source` to handle `application/epub+zip`.
14
+ - Enhanced retrieval precision by prepending source identifiers to document
15
+ chunks in `embed_source`.
16
+ - **Structured Logging**: Implemented a JSON formatter in `OllamaChat::Logging`
17
+ with a `data:` keyword argument for structured context, including separate
18
+ capture of backtraces and tool execution details.
19
+ - **Prompt Management Refactor**:
20
+ - Unified prompt API using a `context:` keyword argument across `prompt`,
21
+ `each_prompt`, `delete_prompt`, `store_prompt`, and `write_prompt`.
22
+ - Introduced dynamic context parameters (defaulting to `'prompt'`) and
23
+ restructured `default_config.yml` to nest prompts under `prompt:`,
24
+ `suggest:`, and `system:`.
25
+ - Promoted `/suggest` to a top-level command and simplified the `/system`
26
+ command.
27
+ - **Conversation Grouping**: Introduced `group_uuid` in `OllamaChat::Message`
28
+ to enable conversation grouping, including a `repair_group_uuids` method in
29
+ `OllamaChat::SessionManagement` for legacy data migration.
30
+ - **Tool Enhancements**:
31
+ - **`read_file`**: Added support for line numbering via the `line_numbers`
32
+ parameter and range extraction using `start_line` and `end_line`. Now
33
+ returns total `line_count` and file `mtime` in ISO8601 format.
34
+ - **`patch_file`**: Refactored to support coordinate-based patching via an
35
+ `edits` parameter for targeted line-range replacements, including overlap
36
+ detection and freshness checks using `mtime`.
37
+ - **`generate_password`**: Added `base64url` alphabet support and critical
38
+ security warnings to discourage the use of `eval_ruby` for secret
39
+ generation.
40
+
41
+ ### Improvements & Refactoring
42
+
43
+ - **CLI & UX**:
44
+ - Refactored command help strings with emoji prefixes and a more concise,
45
+ scannable multi-line format using heredocs.
46
+ - Added a welcome message upon startup displaying the version, connected
47
+ server version, and URL via `print_welcome`.
48
+ - Standardized the creation workflow for prompts and personae with a source
49
+ selection menu (`[CLIPBOARD]`, `[FILES]`, `[EMPTY/MANUAL]`).
50
+ - **Application Flow**:
51
+ - Implemented `OllamaChatQuitError` to handle graceful application
52
+ shutdowns via exception-based control flow.
53
+ - Added a `[QUIT-APP]` option to the session chooser after deletion.
54
+ - **Internal Logic**:
55
+ - Optimized `ps_read` by replacing manual read loops with `IO.copy_stream`.
56
+ - Centralized Ollama chat request logging through a new `call_ollama_chat`
57
+ wrapper.
58
+ - Refactored model option reconfiguration into a dedicated
59
+ `reconfigure_model_options` method in
60
+ `lib/ollama_chat/model_handling.rb`.
61
+ - Updated dependencies: `ollama-ruby` to **1.23** and `tins` to **1.54**.
62
+
63
+ ### Bug Fixes & Stability
64
+
65
+ - Added error logging (`chat.log(:error, e)`) to the `rescue` blocks of all 33
66
+ tool execution methods.
67
+ - Fixed a typo in the Ghostscript error message within `ps_read`.
68
+ - Added defensive handling for `JSON.load` results in `model_handling.rb` using
69
+ `.full? || {}` to prevent `nil` propagation.
70
+ - Removed implicit fallbacks to the last assistant response in
71
+ `copy_to_clipboard` and `paste_into_editor`, making `text` a required
72
+ parameter.
73
+
74
+ ## 2026-07-13 v0.0.99
75
+
76
+ ### Changed
77
+
78
+ - **Command Handling & UX**
79
+ - Updated regexes for `/system`, `/session`, `/prompt`, `/conversation`,
80
+ `/character`, `/input`, `/pipe`, and `/output` in
81
+ `lib/ollama_chat/commands.rb` to prevent positional arguments from
82
+ starting with a hyphen.
83
+ - Enhanced warning messages in `lib/ollama_chat/message_list.rb` to include
84
+ explicit suggestions for `/drop` and `/regenerate`.
85
+
86
+ - **LLM & Prompt Management**
87
+ - Updated the `generate` method in `lib/ollama_chat/chat.rb` to capture
88
+ output in `content` and implemented conditional logging ( `:warn` for
89
+ empty results, `:info` otherwise).
90
+ - Added `.full? or return` guard clauses to `edit_text('')` and
91
+ `generate(prompt: full_prompt)` within
92
+ `lib/ollama_chat/prompt_management.rb`.
93
+ - Overhauled the `suggest_coding` prompt in `default_config.yml` to adopt a
94
+ Senior Software Architect and Technical Auditor persona.
95
+ - Overhauled the `suggest_roleplaying` prompt in `default_config.yml` to
96
+ adopt a Narrative Consultant and Game Master's Assistant persona.
97
+
98
+ - **Tools**
99
+ - Modified `OllamaChat::Tools::CopyToClipboard` to make the `text`
100
+ parameter required.
101
+ - Updated `lib/ollama_chat/tools/copy_to_clipboard.rb` to raise
102
+ `OllamaChat::ToolFunctionArgumentError` if `text` is missing and
103
+ simplified the success message.
104
+
105
+ - **Refactoring & Internal Improvements**
106
+ - Adopted Ruby shorthand for keyword arguments in:
107
+ - `set_default_persona_name` and `load_personae`
108
+ (`lib/ollama_chat/personae_management.rb`).
109
+ - `choose_prompt` via the `default` parameter
110
+ (`lib/ollama_chat/prompt_management.rb`).
111
+ - `OllamaChat::Chat` instantiation using `argv` in specs.
112
+ - The `topic` parameter in `spec/ollama_chat/tools/execute_ri_spec.rb`.
113
+ - The `url` parameter in `spec/ollama_chat/tools/get_url_spec.rb`.
114
+
3
115
  ## 2026-07-09 v0.0.98
4
116
 
5
117
  ### Added
data/Rakefile CHANGED
@@ -39,7 +39,7 @@ GemHadar do
39
39
  )
40
40
 
41
41
  dependency 'excon', '~> 1.0'
42
- dependency 'ollama-ruby', '~> 1.22'
42
+ dependency 'ollama-ruby', '~> 1.23'
43
43
  dependency 'documentrix', '>= 0.6.0'
44
44
  dependency 'unix_socks', '>= 0.4'
45
45
  dependency 'rss', '~> 0.3'
@@ -49,7 +49,7 @@ GemHadar do
49
49
  dependency 'reverse_markdown', '~> 3.0'
50
50
  dependency 'kramdown-ansi', '~> 0.5'
51
51
  dependency 'complex_config', '~> 0.22', '>= 0.22.2'
52
- dependency 'tins', '~> 1.53'
52
+ dependency 'tins', '~> 1.55'
53
53
  dependency 'search_ui', '>= 0.2'
54
54
  dependency 'amatch', '~> 0.4'
55
55
  dependency 'pdf-reader', '~> 2.0'
@@ -116,6 +116,7 @@ class OllamaChat::Chat
116
116
  else
117
117
  messages.read_conversation_jsonl(session.messages.to_s)
118
118
  end
119
+ repair_group_uuids
119
120
  embedding_enabled.set(config.embedding.enabled && !@opts[?E])
120
121
  @documents = setup_documents
121
122
  @cache = setup_cache
@@ -124,7 +125,6 @@ class OllamaChat::Chat
124
125
  @tool_call_results = Hash.new { |h, name| h[name] = [] }
125
126
  setup_personae_directory
126
127
  @opts[?S] and init_server_socket
127
- info_session
128
128
  rescue ComplexConfig::AttributeMissing, ComplexConfig::ConfigurationSyntaxError => e
129
129
  fix_config(e)
130
130
  end
@@ -183,6 +183,7 @@ class OllamaChat::Chat
183
183
  setup_persona_from_session
184
184
  setup_system_prompt
185
185
 
186
+ print_welcome
186
187
  info_session
187
188
 
188
189
  STDOUT.puts "\nType /help to display the chat help."
@@ -255,7 +256,7 @@ class OllamaChat::Chat
255
256
  ),
256
257
  ]
257
258
 
258
- ollama.chat(
259
+ content = call_ollama_chat(
259
260
  model: @model,
260
261
  messages: ,
261
262
  options: model_options,
@@ -263,10 +264,35 @@ class OllamaChat::Chat
263
264
  think: false,
264
265
  tools:
265
266
  )&.message&.content.to_s
267
+
268
+ if content.empty?
269
+ log(:warn, "LLM generation returned empty content", data: { prompt: })
270
+ else
271
+ log(:info, "LLM generation successful", data: { prompt:, content: })
272
+ end
273
+
274
+ content
275
+ end
276
+
277
+ # Returns a human-readable string representation of the Chat object,
278
+ # including the class name and the base URL.
279
+ #
280
+ # @return [String] the inspected string
281
+ def inspect
282
+ "#<#{self.class}: #{base_url.to_s}>"
266
283
  end
267
284
 
268
285
  private
269
286
 
287
+ # Wrapper for ollama.chat to provide consistent logging of all arguments.
288
+ #
289
+ # @param opts [Hash] keyword arguments for the chat call
290
+ # @param block [Proc] optional handler block
291
+ def call_ollama_chat(**opts, &block)
292
+ log(:info, "Ollama chat request", data: { opts: })
293
+ ollama.chat(**opts, &block)
294
+ end
295
+
270
296
  # @return [Module] The module containing the database models.
271
297
  def models
272
298
  OllamaChat::Database::Models
@@ -314,6 +340,14 @@ class OllamaChat::Chat
314
340
  # @param prefill_prompt [String, nil] The text to prefill, or nil to clear it
315
341
  attr_writer :prefill_prompt
316
342
 
343
+ # Signals a graceful shutdown of the application.
344
+ #
345
+ # Raises {OllamaChat::OllamaChatQuitError} which is caught by the main
346
+ # interaction loop to terminate the session cleanly.
347
+ def quit_app
348
+ raise OllamaChat::OllamaChatQuitError
349
+ end
350
+
317
351
  # Handles user input commands and processes chat interactions.
318
352
  #
319
353
  # @param content [String] The input content to process
@@ -383,10 +417,11 @@ class OllamaChat::Chat
383
417
  def interact_with_user
384
418
  loop do
385
419
  content = nil
420
+ group_uuid = OllamaChat::UUIDV7.generate
386
421
  tools_were_called = false
387
422
  enable_content_parsing
388
- type = :terminal_input
389
- input_prompt = bold { color(172) { message_type(@images) + " user" } } + bold { "> " }
423
+ type = :terminal_input
424
+ input_prompt = bold { color(172) { message_type(@images) + " user" } } + bold { "> " }
390
425
  begin
391
426
  tools_were_called = handle_tool_call_results? { |index, tool_name, content|
392
427
  messages << OllamaChat::Message.new(
@@ -394,7 +429,8 @@ class OllamaChat::Chat
394
429
  sender_name: tool_name,
395
430
  tool_name: ,
396
431
  content: ,
397
- images: @images.dup
432
+ images: @images.dup,
433
+ group_uuid:
398
434
  )
399
435
  }
400
436
  tools_were_called and type = :tool_input
@@ -430,8 +466,6 @@ class OllamaChat::Chat
430
466
  next
431
467
  when :redo
432
468
  redo
433
- when :return
434
- return
435
469
  when String
436
470
  content = next_action
437
471
  end
@@ -444,6 +478,14 @@ class OllamaChat::Chat
444
478
 
445
479
  parse_content? and content = parse_content(content, @images)
446
480
 
481
+ messages << OllamaChat::Message.new(
482
+ role: 'user',
483
+ sender_name: user_name,
484
+ content: ,
485
+ images: @images.dup,
486
+ group_uuid:
487
+ )
488
+
447
489
  if runtime_info.on?
448
490
  tool_name = 'runtime_information'
449
491
  messages << OllamaChat::Message.new(
@@ -451,22 +493,17 @@ class OllamaChat::Chat
451
493
  tool_name: ,
452
494
  sender_name: tool_name,
453
495
  content: dynamic_runtime_information,
454
- images: @images.dup
496
+ images: @images.dup,
497
+ group_uuid:
455
498
  )
456
499
  end
457
-
458
- messages << OllamaChat::Message.new(
459
- role: 'user',
460
- sender_name: user_name,
461
- content: ,
462
- images: @images.dup
463
- )
464
500
  end
465
501
  @images.clear
466
502
  handler = OllamaChat::FollowChat.new(
467
503
  chat: self,
468
504
  messages:,
469
- voice: (voices.selected if voice.on?)
505
+ voice: (voices.selected if voice.on?),
506
+ group_uuid:
470
507
  )
471
508
  begin
472
509
  retried = false
@@ -479,7 +516,7 @@ class OllamaChat::Chat
479
516
  }
480
517
  end
481
518
  prepare_model(@model)
482
- ollama.chat(
519
+ call_ollama_chat(
483
520
  model: @model,
484
521
  messages: sent_messages,
485
522
  options: model_options,
@@ -520,6 +557,8 @@ class OllamaChat::Chat
520
557
  self.server_socket_message = nil
521
558
  end
522
559
  0
560
+ rescue OllamaChat::OllamaChatQuitError
561
+ STDOUT.puts "Goodbye."
523
562
  rescue ComplexConfig::AttributeMissing, ComplexConfig::ConfigurationSyntaxError => e
524
563
  log(:error, e)
525
564
  fix_config(e)
@@ -558,7 +597,7 @@ class OllamaChat::Chat
558
597
  if server_version.version < '0.9.0'.version
559
598
  raise 'require ollama API version 0.9.0 or higher'
560
599
  end
561
- log(:info, "Connection to #{base_url} established.")
600
+ log(:info, "Connection established", data: { base_url: })
562
601
  @ollama
563
602
  end
564
603