ollama_chat 0.0.106 → 0.0.107

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: c735b80b131af33178cdbc883a31d6c0693371736cfc91366bcd0d9f42bf2ffb
4
- data.tar.gz: 18a1019995611afe96a0fad541aad75324834ce9ac1828392b956988f7c916ff
3
+ metadata.gz: e2686defd34fe5cf4e0f61c980480578f6b2589bc429d7b724ed4f3cb478d7b8
4
+ data.tar.gz: 8bd9136e0e6f3e202c93f8c4aec0a4b482a447bfd1e29163b0dff1973e64f2fa
5
5
  SHA512:
6
- metadata.gz: db82070f04d57c6679e0ec52474d26b1240b9cea164170258e34916a66097b3c6d3fac51e78a428372377fa956dc7732964387062f1c56d0f04906920e6a3e4e
7
- data.tar.gz: d049ed9ba805b0d2ff670ecc7c3427f5644373fab6a8bf877b0260edadabb777354d5d118fc40534801ea023a6f52b8467b705cfa126eb70115c9b420a1710ec
6
+ metadata.gz: 1a177889fb72f197a05895b60c7e73f1493a119fcc7832354772097f121d53b150ea500fdf50ae81bdeb05161f0a3121af204496d54a708a13c427096e126159
7
+ data.tar.gz: 55c0270902a86e39e1704d62a4478daf0d04526312d47eb35f560b3b95218045d6699dd428b874fa9059ce3af8585bed97a5c2bd662751ef05885baa452a9c6b
data/CHANGES.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-08-09 v0.0.107
4
+
5
+ ### Added
6
+
7
+ - New `-e` option to `ollama_chat_send` to open input content in the configured
8
+ editor before sending.
9
+ - New `-F` option to `ollama_chat_send` to specify file extension for syntax
10
+ highlighting in the editor.
11
+ - Confirmation prompts to `write_file` when overwriting existing files in
12
+ `overwrite` mode or creating new files in `append` mode.
13
+ - Support for pluggable voice handler architecture via a new `handler` key in
14
+ the `voice` configuration.
15
+
16
+ ### Changed
17
+
18
+ - Refactored voice handling to use a dynamic `voice_handler` method in
19
+ `OllamaChat::Chat` to resolve configured classes (e.g., `OllamaChat::Say`).
20
+ - Externalized the suggestion prompt template by adding
21
+ `context_template_suggest` to `default_config.yml` under `prompts`, replacing
22
+ hardcoded heredocs in `prompt_management.rb`.
23
+ - Updated `StateSelectors` to delegate voice list retrieval via
24
+ `voice_handler.ask_and_send(:voices)`.
25
+ - Updated `FollowChat` to instantiate the resolved voice handler dynamically.
26
+ - Refactored `OllamaChat::Say.voices` to extract logic from
27
+ `default_config.yml` ERB and remove RSpec-specific branching.
28
+ - Updated `spec/ollama_chat/commands_spec.rb` to use explicit `.jsonl`
29
+ extensions for `/conversation save` and `/conversation load` tests.
30
+
31
+ ### Fixed
32
+
33
+ - Reopened `STDIN` from `/dev/tty` during editing to prevent editor warnings.
34
+ - Ensured `save_conversation` and `load_conversation` expectations match the
35
+ new file naming convention.
36
+
37
+ ### Security & Error Handling
38
+
39
+ - Raised `OllamaChat::ToolFunctionArgumentError` when a user declines a file
40
+ operation confirmation.
41
+ - Added `.to_s` call on `prompt` results to correctly handle `Sequel::Model`
42
+ return types.
43
+
3
44
  ## 2026-08-06 v0.0.106
4
45
 
5
46
  ### Added
data/README.md CHANGED
@@ -344,6 +344,22 @@ functionality:
344
344
  $ echo "Hello world" | ollama_chat_send -d /tmp/my_working_dir -r
345
345
  ```
346
346
 
347
+ - **Edit Content (`-e`)**: Opens the input content in the configured editor
348
+ before sending. This is useful for refining the message or adding more
349
+ context.
350
+
351
+ ```bash
352
+ $ echo "Draft message..." | ollama_chat_send -e
353
+ ```
354
+
355
+ - **File Format (`-F`)**: When using edit mode, specify a file extension to
356
+ enable syntax highlighting in your editor (e.g., `rb` for Ruby, `md` for
357
+ Markdown).
358
+
359
+ ```bash
360
+ $ echo "def hello; end" | ollama_chat_send -e -F rb
361
+ ```
362
+
347
363
  - **Help (`-h` or `--help`)**: Displays usage information and available options.
348
364
 
349
365
  ```bash
data/bin/ollama_chat_send CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'ollama_chat'
4
+ include OllamaChat::FileEditing
4
5
  require 'tins/go'
5
6
  include Tins::GO
6
7
 
7
- opts = go 'f:d:rtph', ARGV
8
+ opts = go 'f:d:F:rteph', ARGV
8
9
 
9
10
  # Displays the usage information for the ollama_chat_send command.
10
11
  #
@@ -23,6 +24,8 @@ def usage(rc = 0)
23
24
  -p Send input with source parsing enabled (defaults to disabled)
24
25
  -f CONFIG file to read
25
26
  -d DIR the working directory to derive the socket file from
27
+ -e Edit content in editor before sending
28
+ -F FORMAT file extension for editor (e.g., rb, md)
26
29
  -h Show this help message
27
30
 
28
31
  Send data to a running Ollama Chat client via standard input.
@@ -38,8 +41,15 @@ begin
38
41
  else
39
42
  opts[?r] ? :socket_input_with_response : :socket_input
40
43
  end
44
+ content = STDIN.read
45
+ if opts[?e]
46
+ basename = %w[ text ]
47
+ basename << opts[?F]&.sub(/\A(?=[^.])/, ?.) || '.md'
48
+ STDIN.reopen('/dev/tty')
49
+ content = edit_text(content, basename:)
50
+ end
41
51
  response = OllamaChat::ServerSocket.send_to_server_socket(
42
- STDIN.read,
52
+ content,
43
53
  type:,
44
54
  config:,
45
55
  working_dir: opts[?d],
@@ -160,6 +160,21 @@ class OllamaChat::Chat
160
160
  # @return [OllamaChat::RedisCache, nil] the cache instance
161
161
  attr_reader :cache
162
162
 
163
+
164
+ # Returns the voice handler class based on the configuration.
165
+ #
166
+ # This method resolves the voice handler class specified in the config.
167
+ # If running within RSpec, it returns an empty array to avoid side effects.
168
+ #
169
+ # @return [Class, Array] the voice handler class or an empty array if in test mode
170
+ def voice_handler
171
+ defined?(RSpec) and return []
172
+ case config.voice.handler
173
+ when 'OllamaChat::Say'
174
+ OllamaChat::Say
175
+ end
176
+ end
177
+
163
178
  # The start method initializes the chat session by displaying information,
164
179
  # then prompts the user for input to begin interacting with the chat.
165
180
  def start
@@ -29,10 +29,14 @@ class OllamaChat::FollowChat
29
29
  super(output:)
30
30
  @chat = chat
31
31
  @output.sync = true
32
- @say = voice ? Handlers::Say.new(voice:) : NOP
33
32
  @messages = messages
34
33
  @group_uuid = group_uuid
35
34
  @sender = nil
35
+ @say = if voice && @chat.voice_handler.respond_to?(:new)
36
+ @chat.voice_handler.new(chat:, voice:)
37
+ else
38
+ NOP
39
+ end
36
40
  end
37
41
 
38
42
  attr_reader :chat
@@ -173,6 +173,12 @@ prompts:
173
173
  conversation. Output only the title and nothing else:
174
174
 
175
175
  %{content}
176
+ context_template_suggest: |
177
+ Conversation History:
178
+ %{history}
179
+
180
+ Create and output text following this instruction:
181
+ %{instruction}
176
182
  suggest:
177
183
  coding: |
178
184
  ## Context
@@ -343,9 +349,9 @@ prompts:
343
349
  %{runtime_info}
344
350
  assistant: You are a helpful assistant.
345
351
  voice:
352
+ handler: OllamaChat::Say
346
353
  enabled: false
347
354
  default: Samantha
348
- list: <%= defined?(RSpec) ? '[]' : `say -v '?' 2>/dev/null`.lines.map { |l| l.force_encoding('ASCII-8BIT'); l[/^(.+?)\s+[a-z]{2}_[a-zA-Z0-9]{2,}/, 1] }.uniq.sort.to_s %>
349
355
  roles:
350
356
  user: 👨 %{sender_name}
351
357
  assistant: 🤖 %{sender_name}
@@ -338,16 +338,11 @@ module OllamaChat::PromptManagement
338
338
 
339
339
  # Build the context by gathering all current conversation messages
340
340
  history = prepare_conversation_history
341
- full_prompt = <<~EOT
342
- Conversation History:
343
- #{history}
344
-
345
- Instruction:
346
- #{instruction}
347
- EOT
341
+ template = prompt('context_template_suggest', context: 'prompt').to_s
342
+ full_prompt = template % { history:, instruction: }
348
343
 
349
344
  # Execute a silent chat oneshot call (doesn't add to history)
350
- suggestions = generate(prompt: full_prompt).full? or return
345
+ suggestions = generate(prompt: full_prompt).full? or return
351
346
 
352
347
  # Pass the AI's suggestions through the editor for final refinement
353
348
  edit_text(suggestions)
@@ -0,0 +1,30 @@
1
+ # A handler that uses the system's say command to speak response content.
2
+ #
3
+ # This class extends Ollama::Handlers::Say to provide voice validation
4
+ # against the system's available voices. It ensures that only valid voices
5
+ # are used, falling back to nil if an invalid voice is specified.
6
+ #
7
+ # @example Using the Say handler
8
+ # OllamaChat::Say.new(chat: chat, voice: 'Samantha')
9
+ class OllamaChat::Say < Ollama::Handlers::Say
10
+ # Returns a list of available system voices.
11
+ #
12
+ # This method queries the system's `say` command to retrieve the list of
13
+ # available voices. If running within RSpec, it returns an empty array to
14
+ # avoid side effects during testing.
15
+ #
16
+ # @return [Array<String>] a sorted list of unique voice identifiers
17
+ def self.voices
18
+ `say -v '?' 2>/dev/null`.lines.map { |l| l[/^(.+?)\s+[a-z]{2}_[a-zA-Z0-9]{2,}/, 1] }.uniq.sort
19
+ end
20
+
21
+ # Initializes a new Say handler.
22
+ #
23
+ # @param chat [OllamaChat::Chat] the chat instance
24
+ # @param voice [String, nil] the voice to use (must be in the list of available voices)
25
+ def initialize(chat:, voice: nil)
26
+ voice && self.class.voices.member?(voice) or voice = nil
27
+ @chat = chat
28
+ super(voice:)
29
+ end
30
+ end
@@ -269,11 +269,12 @@ module OllamaChat::StateSelectors
269
269
  states: OllamaChat::ThinkControl::THINK_MODE_STATES,
270
270
  off: OllamaChat::ThinkControl::THINK_MODE_STATES[0, 1],
271
271
  )
272
+ list = voice_handler.ask_and_send(:voices) || []
272
273
  @voices = DatabaseStateSelector.new(
273
274
  chat: self,
274
275
  attribute: :current_voice,
275
276
  name: 'Voice',
276
- states: config.voice.list,
277
+ states: list,
277
278
  allow_empty: true
278
279
  )
279
280
  @context_format = DatabaseStateSelector.new(
@@ -76,6 +76,22 @@ class OllamaChat::Tools::WriteFile
76
76
 
77
77
  es = OllamaChat::TokenEstimator.estimate(args.content)
78
78
 
79
+ # Confirm overwrite if file already exists
80
+ if path.exist? && (args.mode == 'overwrite' || args.mode.nil?)
81
+ unless chat.confirm?(prompt: "File #{path.to_s.inspect} already exists. Overwrite? (y/N): ", yes: /\Ay/i)
82
+ raise OllamaChat::ToolFunctionArgumentError,
83
+ "Write rejected: File #{path.to_s.inspect} already exists and was not overwritten."
84
+ end
85
+ end
86
+
87
+ # Confirm creation if file doesn't exist in append mode
88
+ if !path.exist? && args.mode == 'append'
89
+ unless chat.confirm?(prompt: "File #{path.to_s.inspect} does not exist. Create it? (y/N): ", yes: /\Ay/i)
90
+ raise OllamaChat::ToolFunctionArgumentError,
91
+ "Write rejected: File #{path.to_s.inspect} does not exist and was not created."
92
+ end
93
+ end
94
+
79
95
  backup_path = nil
80
96
 
81
97
  content = args.content
@@ -1,6 +1,6 @@
1
1
  module OllamaChat
2
2
  # OllamaChat version
3
- VERSION = '0.0.106'
3
+ VERSION = '0.0.107'
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:
data/lib/ollama_chat.rb CHANGED
@@ -120,4 +120,5 @@ require 'ollama_chat/prompt_handling'
120
120
  require 'ollama_chat/system_prompt_management'
121
121
  require 'ollama_chat/prompt_management'
122
122
  require 'ollama_chat/token_estimator'
123
+ require 'ollama_chat/say'
123
124
  require 'ollama_chat/chat'
data/ollama_chat.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: ollama_chat 0.0.106 ruby lib
2
+ # stub: ollama_chat 0.0.107 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "ollama_chat".freeze
6
- s.version = "0.0.106".freeze
6
+ s.version = "0.0.107".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]
@@ -12,8 +12,8 @@ Gem::Specification.new do |s|
12
12
  s.description = "The app provides a command-line interface (CLI) to an Ollama AI model,\nallowing users to engage in text-based conversations and generate\nhuman-like responses. Users can import data from local files or web pages,\nwhich are then processed through three different modes: fully importing the\ncontent into the conversation context, summarizing the information for\nconcise reference, or storing it in an embedding vector database for later\nretrieval based on the conversation.\n".freeze
13
13
  s.email = "flori@ping.de".freeze
14
14
  s.executables = ["ollama_chat".freeze, "ollama_chat_send".freeze, "ollama_chat_log".freeze]
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/migrations/005_add_context_format_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/006_rename_system_prompt_context_to_system.rb".freeze, "lib/ollama_chat/database/migrations/007_add_collections_table.rb".freeze, "lib/ollama_chat/database/models/collection.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/token_estimator.rb".freeze, "lib/ollama_chat/token_estimator/crude.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/roll_dice.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_knowledge.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/log_viewer.rb".freeze, "lib/ollama_chat/utils/path_completer.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/png_metadata_extractor.rb".freeze, "lib/ollama_chat/utils/tag_resolver.rb".freeze, "lib/ollama_chat/utils/utf8_converter.rb".freeze, "lib/ollama_chat/utils/value_formatter.rb".freeze, "lib/ollama_chat/uuid_v7.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, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_chat_log".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/migrations/005_add_context_format_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/006_rename_system_prompt_context_to_system.rb".freeze, "lib/ollama_chat/database/migrations/007_add_collections_table.rb".freeze, "lib/ollama_chat/database/models/collection.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/token_estimator.rb".freeze, "lib/ollama_chat/token_estimator/crude.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/roll_dice.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_knowledge.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/log_viewer.rb".freeze, "lib/ollama_chat/utils/path_completer.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/png_metadata_extractor.rb".freeze, "lib/ollama_chat/utils/tag_resolver.rb".freeze, "lib/ollama_chat/utils/utf8_converter.rb".freeze, "lib/ollama_chat/utils/value_formatter.rb".freeze, "lib/ollama_chat/uuid_v7.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.epub".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/miyu.png".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/commands_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/session_management_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/token_estimator_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/roll_dice_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_knowledge_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/log_viewer_spec.rb".freeze, "spec/ollama_chat/utils/path_completer_spec.rb".freeze, "spec/ollama_chat/utils/png_metadata_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]
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/migrations/005_add_context_format_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/006_rename_system_prompt_context_to_system.rb".freeze, "lib/ollama_chat/database/migrations/007_add_collections_table.rb".freeze, "lib/ollama_chat/database/models/collection.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/say.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/token_estimator.rb".freeze, "lib/ollama_chat/token_estimator/crude.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/roll_dice.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_knowledge.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/log_viewer.rb".freeze, "lib/ollama_chat/utils/path_completer.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/png_metadata_extractor.rb".freeze, "lib/ollama_chat/utils/tag_resolver.rb".freeze, "lib/ollama_chat/utils/utf8_converter.rb".freeze, "lib/ollama_chat/utils/value_formatter.rb".freeze, "lib/ollama_chat/uuid_v7.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, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_chat_log".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/migrations/005_add_context_format_to_sessions.rb".freeze, "lib/ollama_chat/database/migrations/006_rename_system_prompt_context_to_system.rb".freeze, "lib/ollama_chat/database/migrations/007_add_collections_table.rb".freeze, "lib/ollama_chat/database/models/collection.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/say.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/token_estimator.rb".freeze, "lib/ollama_chat/token_estimator/crude.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/roll_dice.rb".freeze, "lib/ollama_chat/tools/run_tests.rb".freeze, "lib/ollama_chat/tools/search_knowledge.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/log_viewer.rb".freeze, "lib/ollama_chat/utils/path_completer.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/png_metadata_extractor.rb".freeze, "lib/ollama_chat/utils/tag_resolver.rb".freeze, "lib/ollama_chat/utils/utf8_converter.rb".freeze, "lib/ollama_chat/utils/value_formatter.rb".freeze, "lib/ollama_chat/uuid_v7.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.epub".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/miyu.png".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/commands_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/session_management_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/token_estimator_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/roll_dice_spec.rb".freeze, "spec/ollama_chat/tools/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_knowledge_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/log_viewer_spec.rb".freeze, "spec/ollama_chat/utils/path_completer_spec.rb".freeze, "spec/ollama_chat/utils/png_metadata_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]
@@ -475,13 +475,13 @@ describe OllamaChat::Commands, protect_env: true do
475
475
 
476
476
  describe 'conversation' do
477
477
  it 'returns :next when input is "/conversation save\\s+(.+)$"' do
478
- expect(chat).to receive(:save_conversation).with('./some_file', clean: false)
479
- expect(chat.handle_input("/conversation save ./some_file")).to eq :next
478
+ expect(chat).to receive(:save_conversation).with('./some_file.jsonl', clean: false)
479
+ expect(chat.handle_input("/conversation save ./some_file.jsonl")).to eq :next
480
480
  end
481
481
 
482
- it 'returns :next when input is "/conversation save -c ./some_file"' do
483
- expect(chat).to receive(:save_conversation).with('./some_file', clean: 1)
484
- expect(chat.handle_input("/conversation save -c ./some_file")).to eq :next
482
+ it 'returns :next when input is "/conversation save -c ./some_file.jsonl"' do
483
+ expect(chat).to receive(:save_conversation).with('./some_file.jsonl', clean: 1)
484
+ expect(chat.handle_input("/conversation save -c ./some_file.jsonl")).to eq :next
485
485
  end
486
486
 
487
487
  it 'returns :next when input is "/conversation save" without path' do
@@ -490,8 +490,8 @@ describe OllamaChat::Commands, protect_env: true do
490
490
  end
491
491
 
492
492
  it 'returns :next when input is "/conversation load\\s+(.+)$"' do
493
- expect(chat).to receive(:load_conversation).with('./some_file')
494
- expect(chat.handle_input("/conversation load ./some_file")).to eq :next
493
+ expect(chat).to receive(:load_conversation).with('./some_file.jsonl')
494
+ expect(chat.handle_input("/conversation load ./some_file.jsonl")).to eq :next
495
495
  end
496
496
 
497
497
  it 'returns :next when input is "/conversation load" without path' do
@@ -21,7 +21,7 @@ describe OllamaChat::Tools::WriteFile do
21
21
  "./tmp/test_write_file_#{Tins::Token.new(bits: 128)}.txt"
22
22
  end
23
23
 
24
- it 'can be executed successfully with overwrite mode' do
24
+ it 'can be executed successfully with overwrite mode on new file' do
25
25
  tool_call = double(
26
26
  'ToolCall',
27
27
  function: double(
@@ -51,7 +51,62 @@ describe OllamaChat::Tools::WriteFile do
51
51
  File.delete(test_write_file) if File.exist?(test_write_file)
52
52
  end
53
53
 
54
- it 'can be executed successfully with append mode' do
54
+ it 'can be executed successfully with overwrite mode on existing file with confirmation' do
55
+ # Pre-create the file
56
+ File.write(test_write_file, 'Old content')
57
+
58
+ expect(chat).to receive(:confirm?).and_return(true)
59
+
60
+ tool_call = double(
61
+ 'ToolCall',
62
+ function: double(
63
+ name: 'write_file',
64
+ arguments: double(
65
+ path: test_write_file,
66
+ content: 'New content',
67
+ mode: 'overwrite'
68
+ )
69
+ )
70
+ )
71
+
72
+ result = described_class.new.execute(tool_call, chat:)
73
+
74
+ json = json_object(result)
75
+ expect(json.success).to eq true
76
+ expect(File.read(test_write_file)).to eq 'New content'
77
+ ensure
78
+ File.delete(test_write_file) if File.exist?(test_write_file)
79
+ end
80
+
81
+ it 'rejects overwrite when user declines confirmation' do
82
+ # Pre-create the file
83
+ File.write(test_write_file, 'Old content')
84
+
85
+ expect(chat).to receive(:confirm?).and_return(false)
86
+
87
+ tool_call = double(
88
+ 'ToolCall',
89
+ function: double(
90
+ name: 'write_file',
91
+ arguments: double(
92
+ path: test_write_file,
93
+ content: 'New content',
94
+ mode: 'overwrite'
95
+ )
96
+ )
97
+ )
98
+
99
+ result = described_class.new.execute(tool_call, chat:)
100
+
101
+ json = json_object(result)
102
+ expect(json.error).to eq 'OllamaChat::ToolFunctionArgumentError'
103
+ expect(json.message).to include('Write rejected')
104
+ expect(File.read(test_write_file)).to eq 'Old content'
105
+ ensure
106
+ File.delete(test_write_file) if File.exist?(test_write_file)
107
+ end
108
+
109
+ it 'can be executed successfully with append mode on existing file' do
55
110
  # First write some initial content
56
111
  initial_content = 'Initial content\n'
57
112
  File.secure_write(test_write_file, initial_content)
@@ -87,6 +142,53 @@ describe OllamaChat::Tools::WriteFile do
87
142
  File.delete(test_write_file) if File.exist?(test_write_file)
88
143
  end
89
144
 
145
+ it 'can be executed successfully with append mode on new file with confirmation' do
146
+ expect(chat).to receive(:confirm?).and_return(true)
147
+
148
+ tool_call = double(
149
+ 'ToolCall',
150
+ function: double(
151
+ name: 'write_file',
152
+ arguments: double(
153
+ path: test_write_file,
154
+ content: 'First content\n',
155
+ mode: 'append'
156
+ )
157
+ )
158
+ )
159
+
160
+ result = described_class.new.execute(tool_call, chat:)
161
+
162
+ json = json_object(result)
163
+ expect(json.success).to eq true
164
+ expect(File.read(test_write_file)).to eq 'First content\n'
165
+ ensure
166
+ File.delete(test_write_file) if File.exist?(test_write_file)
167
+ end
168
+
169
+ it 'rejects append when user declines confirmation for new file' do
170
+ expect(chat).to receive(:confirm?).and_return(false)
171
+
172
+ tool_call = double(
173
+ 'ToolCall',
174
+ function: double(
175
+ name: 'write_file',
176
+ arguments: double(
177
+ path: test_write_file,
178
+ content: 'First content\n',
179
+ mode: 'append'
180
+ )
181
+ )
182
+ )
183
+
184
+ result = described_class.new.execute(tool_call, chat:)
185
+
186
+ json = json_object(result)
187
+ expect(json.error).to eq 'OllamaChat::ToolFunctionArgumentError'
188
+ expect(json.message).to include('Write rejected')
189
+ expect(File.exist?(test_write_file)).to be false
190
+ end
191
+
90
192
  it 'can handle execution errors gracefully when path is not allowed' do
91
193
  tool_call = double(
92
194
  'ToolCall',
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.106
4
+ version: 0.0.107
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -530,6 +530,7 @@ extra_rdoc_files:
530
530
  - lib/ollama_chat/prompt_management.rb
531
531
  - lib/ollama_chat/rag_handling.rb
532
532
  - lib/ollama_chat/redis_cache.rb
533
+ - lib/ollama_chat/say.rb
533
534
  - lib/ollama_chat/server_socket.rb
534
535
  - lib/ollama_chat/session_management.rb
535
536
  - lib/ollama_chat/source_fetching.rb
@@ -658,6 +659,7 @@ files:
658
659
  - lib/ollama_chat/prompt_management.rb
659
660
  - lib/ollama_chat/rag_handling.rb
660
661
  - lib/ollama_chat/redis_cache.rb
662
+ - lib/ollama_chat/say.rb
661
663
  - lib/ollama_chat/server_socket.rb
662
664
  - lib/ollama_chat/session_management.rb
663
665
  - lib/ollama_chat/source_fetching.rb