ollama_chat 0.0.78 → 0.0.79

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: 8e531dd87a2f08ae4d6be00bdf3aef50e29c29405c37ddd439ffa4ad69cf4a22
4
- data.tar.gz: 2187cd9c3bd2ae6222ec705e0f0d8c8c143f83f51b282e36951b3ada0d8609d2
3
+ metadata.gz: 982588e8a14a4bb35aebd365a9dea99fb7c7b474f4d1293436fa97d1258eec79
4
+ data.tar.gz: 0a0410940246c4d9d260256e02373f002aeadba778a2097aefc97f190dc17e68
5
5
  SHA512:
6
- metadata.gz: aae64c9b513f65a31568ceb0b73a9ca8acfff96a82a5940ef18fbb568f41346ad3db1c9eb123d98cc969974c7709e840df21e985b7ef4077f948ea0e38db5ab1
7
- data.tar.gz: db40e853d4f39ad45677da690748b3f85b239cff3faf330acae44a4dc95961551d1f7c2b275e3aecd73c625372f9fc369de0a3decd17e55e1b7f6981772517c2
6
+ metadata.gz: f15c28d9980519078af9b27d5706edfa91df2c4c13ac235377dd97623c62a40c9b8014c06373f093ef473e5c9553e20a949fa4488afb7be06b94ebd006c2eb1c
7
+ data.tar.gz: 8bc4b5bd4880ab46ea227379ff4786681a7f7bef67d81df35628f5aea238c250f0842de5408fdb94056828c792080ce0ee0793a3a74e13d8a78c6d504b005f9d
data/CHANGES.md CHANGED
@@ -1,5 +1,59 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-03-13 v0.0.79
4
+
5
+ - Added `tmp/*` to Rakefile ignore list for cleaner builds.
6
+ - Updated gemspec: changed `s.rubygems_version` to **3.6.9**.
7
+ - Added `logging.rb` to `extra_rdoc_files` and `files` in gemspec.
8
+ - Adjusted gemspec file list to reflect new structure.
9
+ - Removed `Runtime Directory` (`-d`) explanation from `README.md`.
10
+ - Updated URL in `README.md`.
11
+ - Added explicit check that `args.path.full?` is true before calling
12
+ `assert_valid_path`, raising `ArgumentError` with message `'require path to
13
+ file to be patched'`.
14
+ - Updated path assignment to first validate presence, then assert validity
15
+ against `config.tools.functions.patch_file.allowed?`.
16
+ - Updated `OllamaChat::Tools::ExecuteGrep` to accept new options `before`,
17
+ `after`, and `context`.
18
+ - Added helper method `normalize_number` for optional integer arguments.
19
+ - Adjusted command template in `default_config.yml` to include `-B`, `-A`, and
20
+ `-C` flags based on provided values.
21
+ - Refactored logging: replaced `logger.error` / `logger.warn` calls with
22
+ `log(:error, …)` or `log(:warn, …)` across multiple files.
23
+ - Added optional `warn: true` flag to new helper so that critical errors also
24
+ trigger a user‑visible warning output while still being written to the log
25
+ file.
26
+ - Implemented `OllamaChat::Logging#log(severity, msg, warn:)` in `logging.rb`;
27
+ it formats exceptions with backtraces and forwards messages to the underlying
28
+ Ruby `Logger`.
29
+ - Updated `spec_helper.rb` by adding a global `config.before` hook that sets
30
+ temporary paths for `OC::OLLAMA::CHAT::HISTORY` and `LOGFILE` so all specs
31
+ run against isolated files.
32
+ - Added `tmp/*` to `.gitignore`.
33
+ - Created new module `OllamaChat::Logging` that lazily builds a Logger writing
34
+ to the file defined by `OC::OLLAMA::CHAT::LOGFILE` in XDG STATE.
35
+ - Required this logging module in `lib/ollama_chat.rb` and included it in
36
+ `class OllamaChat::Chat` so every chat instance has access to `logger`.
37
+ - Logged connection messages via `@chat.logger.info` before printing the
38
+ “Connecting …” line in `OllamaChat::Dialog#connect_message`.
39
+ - Centralized tool‑call error handling: log unconfigured, unregistered or
40
+ disabled tools with `@chat.logger.error`, and record each executed function
41
+ payload using `JSON.pretty_generate`.
42
+ - Introduced an explicit vs implicit confirmation flow (`:explicit`,
43
+ `:implicite`, `:denied`) in `OllamaChat::FollowChat#follow_chat` and log the
44
+ outcome accordingly.
45
+ - Switched chat history storage from XDG CACHE to XDG STATE by updating
46
+ `OC::OLLAMA::CHAT::HISTORY` path, adjusting file operations in
47
+ `lib/ollama_chat/history.rb`, and adding a new config entry for `LOGFILE`
48
+ under state home in `oc.rb`.
49
+ - Enhanced PatchFile tool: updated documentation to specify `unified diff
50
+ format` and `JSON response`.
51
+ - Added private method `digest` that returns `MD5` of a file path.
52
+ - Modified `apply_patch` to compute old digest, run patch command, compare
53
+ digests, set `success` flag accordingly.
54
+ - Improved error handling: now includes `success`, clearer messages, empty
55
+ result on failure.
56
+
3
57
  ## 2026-03-11 v0.0.78
4
58
 
5
59
  - Added new `patch_file` tool for applying unified diff patches to files with
data/README.md CHANGED
@@ -252,14 +252,6 @@ The `ollama_chat_send` command now supports additional parameters to enhance fun
252
252
  $ echo "Hello world" | ollama_chat_send -d /tmp/my_working_dir -r
253
253
  ```
254
254
 
255
- - **Runtime Directory (`-d`)**: Specifies the directory where the Unix socket
256
- file of `ollama_chat` was created, if you want to send to a specific
257
- `ollama_chat`.
258
-
259
- ```bash
260
- $ echo "Hello world" | ollama_chat_send -d /tmp/my_runtime_dir -r
261
- ```
262
-
263
255
  - **Help (`-h` or `--help`)**: Displays usage information and available options.
264
256
 
265
257
  ```bash
@@ -273,7 +265,7 @@ These parameters provide greater flexibility in how you interact with
273
265
 
274
266
  The homepage of this app is located at
275
267
 
276
- * https://github.com/flori/ollama\_chat
268
+ * https://github.com/flori/ollama_chat
277
269
 
278
270
  ## Author
279
271
 
data/Rakefile CHANGED
@@ -22,7 +22,7 @@ GemHadar do
22
22
  test_dir 'spec'
23
23
  ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', '.AppleDouble', '.bundle',
24
24
  '.yardoc', 'doc', 'tags', 'corpus', 'coverage', '/config/searxng/*',
25
- '.starscope.db', 'cscope.out', 'errors.lst'
25
+ '.starscope.db', 'cscope.out', 'errors.lst', 'tmp/*'
26
26
  package_ignore '.all_images.yml', '.tool-versions', '.gitignore', 'VERSION',
27
27
  '.rspec', '.github', '.contexts', '.envrc', '.yardopts'
28
28
 
@@ -33,6 +33,7 @@ require 'context_spook'
33
33
  class OllamaChat::Chat
34
34
  include Tins::GO
35
35
  include Term::ANSIColor
36
+ include OllamaChat::Logging
36
37
  include OllamaChat::DocumentCache
37
38
  include OllamaChat::Switches
38
39
  include OllamaChat::StateSelectors
@@ -264,7 +265,8 @@ class OllamaChat::Chat
264
265
  begin
265
266
  use_model
266
267
  rescue OllamaChatError::UnknownModelError => e
267
- STDERR.puts "Caught #{e.class}: #{e}"
268
+ msg = "Caught #{e.class}: #{e}"
269
+ log(:error, msg, warn: true)
268
270
  end
269
271
  :next
270
272
  when %r(^/system(?:\s+(show))?$)
@@ -761,7 +763,8 @@ class OllamaChat::Chat
761
763
  server_socket_message&.disconnect
762
764
  end
763
765
  rescue Ollama::Errors::TimeoutError
764
- STDOUT.puts "#{bold('Error')}: Currently lost connection to ollama server and cannot send command."
766
+ msg = "Currently lost connection to ollama server and cannot send command."
767
+ log(:warn, msg, warn: true)
765
768
  rescue Interrupt
766
769
  STDOUT.puts "Type /quit to quit."
767
770
  ensure
@@ -769,6 +772,7 @@ class OllamaChat::Chat
769
772
  end
770
773
  0
771
774
  rescue ComplexConfig::AttributeMissing, ComplexConfig::ConfigurationSyntaxError => e
775
+ log(:error, e)
772
776
  fix_config(e)
773
777
  ensure
774
778
  save_history
@@ -805,6 +809,7 @@ class OllamaChat::Chat
805
809
  if server_version.version < '0.9.0'.version
806
810
  raise 'require ollama API version 0.9.0 or higher'
807
811
  end
812
+ log(:info, "Connection to #{base_url} established.")
808
813
  @ollama
809
814
  end
810
815
 
@@ -98,7 +98,6 @@ module OllamaChat::Clipboard
98
98
  # handles any OllamaChat::OllamaChatError exceptions by printing the error
99
99
  # message to standard error and does not re-raise the exception.
100
100
  def copy_to_clipboard
101
-
102
101
  perform_copy_to_clipboard
103
102
  STDOUT.puts "The last response has been successfully copied to the system clipboard."
104
103
  true
@@ -30,7 +30,9 @@ module OllamaChat::Dialog
30
30
  # @param model [String] the model name to connect to
31
31
  # @param base_url [String] the base URL of the connection
32
32
  def connect_message(model, base_url)
33
- STDOUT.puts green { "Connecting to #{model}@#{base_url} now…" }
33
+ msg = "Connecting to #{model}@#{base_url} now…"
34
+ log(:info, msg)
35
+ STDOUT.puts green { msg }
34
36
  end
35
37
 
36
38
  # The choose_collection method presents a menu to select or create a document
@@ -43,7 +43,7 @@ module OllamaChat::DocumentCache
43
43
  document_cache_class
44
44
  end
45
45
  rescue => e
46
- STDERR.puts "Caught #{e.class}: #{e} => Falling back to MemoryCache."
46
+ log(:error, "Caught #{e.class}: #{e} => Falling back to MemoryCache.")
47
47
  Documentrix::Documents::MemoryCache
48
48
  end
49
49
  end
@@ -99,43 +99,46 @@ class OllamaChat::FollowChat
99
99
  response.message.tool_calls.each do |tool_call|
100
100
  name = tool_call.function.name
101
101
  unless @chat.tool_configured?(name)
102
- @chat.tool_call_results[name] =
103
- "Error: Unconfigured tool named %s ignored => Skip.\n" % name
102
+ msg = "Error: Unconfigured tool named %s ignored => Skip.\n" % name
103
+ @chat.tool_call_results[name] = msg
104
+ @chat.log(:error, msg)
104
105
  next
105
106
  end
106
107
  unless @chat.tool_registered?(name)
107
- @chat.tool_call_results[name] =
108
- "Error: Unregistered tool named %s ignored => Skip.\n" % name
108
+ msg = "Error: Unregistered tool named %s ignored => Skip.\n" % name
109
+ @chat.tool_call_results[name] = msg
110
+ @chat.log(:error, msg)
109
111
  next
110
112
  end
111
113
  unless @chat.tool_enabled?(name)
112
- @chat.tool_call_results[name] =
113
- "Error: Disabled tool named %s ignored => Skip.\n" % name
114
+ msg = "Error: Disabled tool named %s ignored => Skip.\n" % name
115
+ @chat.tool_call_results[name] = msg
116
+ @chat.log(:error, msg)
114
117
  next
115
118
  end
116
119
  STDOUT.puts
117
- confirmed = true
118
- args = JSON.pretty_generate(tool_call.function.arguments)
120
+ confirmed = :implicit
121
+ function = JSON.pretty_generate(tool_call.function)
122
+ @chat.log(:info, function)
119
123
  if @chat.tool_function(name).require_confirmation?
120
124
  prompt = "I want to execute tool %s\n%s\nConfirm? (y/n) " % [
121
125
  bold { name },
122
- italic { args },
126
+ italic { function },
123
127
  ]
124
- confirmed = @chat.ask?(prompt:) =~ /\Ay/i
128
+ if @chat.ask?(prompt:) =~ /\Ay/i
129
+ confirmed = :explicit
130
+ else
131
+ confirmed = :denied
132
+ end
125
133
  else
126
134
  STDOUT.puts "Executing tool %s\n%s" % [
127
135
  bold { name },
128
- italic { args },
136
+ italic { function },
129
137
  ]
130
138
  end
131
139
  result = nil
132
- if confirmed
133
- STDOUT.printf(
134
- "\n%s Execution of tool %s confirmed.\n\n", ?✅, bold { name }
135
- )
136
- result = OllamaChat::Tools.registered[name].
137
- execute(tool_call, chat: @chat, config: @chat.config)
138
- else
140
+ case confirmed
141
+ when :denied
139
142
  result = JSON(
140
143
  message: 'User denied confirmation!',
141
144
  resolve: 'You **MUST** ask the user for instructions on how to proceed!!!',
@@ -143,7 +146,25 @@ class OllamaChat::FollowChat
143
146
  STDOUT.printf(
144
147
  "\n%s Execution of tool %s denied by user.\n", ?🚫, bold { name }
145
148
  )
146
- sleep 1
149
+ @chat.log(:warn,"Execution of tool %s was denied by user!" % name)
150
+ else
151
+ symbol = confirmed == :implicit ? '☑️ ' : '✅'
152
+ STDOUT.printf(
153
+ "\n%s Execution of tool %s confirmed.\n\n", symbol, bold { name }
154
+ )
155
+ result = OllamaChat::Tools.registered[name].
156
+ execute(tool_call, chat: @chat, config: @chat.config)
157
+ if confirmed == :explicit
158
+ @chat.log(:info, "Execution of tool %s was explicitly confirmed." % name)
159
+ else
160
+ @chat.log(:info, "Execution of tool %s was implicitly confirmed." % name)
161
+ end
162
+ end
163
+ begin
164
+ data = JSON.parse(result)
165
+ @chat.log(:info, JSON.pretty_generate(data))
166
+ rescue
167
+ @chat.log(:info, result)
147
168
  end
148
169
  @chat.tool_call_results[name] = result
149
170
  end
@@ -17,20 +17,6 @@
17
17
  module OllamaChat::History
18
18
  private
19
19
 
20
- # The chat_history_filename method constructs and returns the full file path
21
- # for the chat history file.
22
- #
23
- # This method takes the configured chat history filename from the
24
- # configuration and expands it to an absolute path using File.expand_path.
25
- # This ensures that the returned path is fully qualified and can be used
26
- # reliably for reading from or writing to the chat history file.
27
- #
28
- # @return [String] the absolute file path to the chat history file as
29
- # specified in the configuration
30
- def chat_history_filename
31
- File.expand_path(OC::OLLAMA::CHAT::HISTORY)
32
- end
33
-
34
20
  # The init_chat_history method initializes the chat session by loading
35
21
  # previously saved command history from a file.
36
22
  #
@@ -40,15 +26,15 @@ module OllamaChat::History
40
26
  # loading process are caught and logged as warnings, but do not interrupt the
41
27
  # execution flow.
42
28
  def init_chat_history
43
- if File.exist?(chat_history_filename)
44
- File.open(chat_history_filename, ?r) do |history|
45
- history_data = JSON.load(history)
46
- Readline::HISTORY.clear
47
- Readline::HISTORY.push(*history_data)
48
- end
29
+ if OC::OLLAMA::CHAT::HISTORY.exist?
30
+ history = OC::OLLAMA::CHAT::HISTORY.read
31
+ history_data = JSON.load(history)
32
+ Readline::HISTORY.clear
33
+ Readline::HISTORY.push(*history_data)
49
34
  end
50
35
  rescue => e
51
- warn "Caught #{e.class} while loading #{chat_history_filename.inspect}: #{e}"
36
+ msg = "Caught #{e.class} while loading #{OC::OLLAMA::CHAT::HISTORY.inspect}: #{e}"
37
+ log(:error, msg, warn: true)
52
38
  end
53
39
 
54
40
  # The save_history method persists the current command history to a file.
@@ -57,9 +43,10 @@ module OllamaChat::History
57
43
  # writes it to the chat history filename. It handles potential errors during
58
44
  # the write operation by catching exceptions and issuing a warning message.
59
45
  def save_history
60
- File.secure_write(chat_history_filename, JSON.dump(Readline::HISTORY))
46
+ File.secure_write(OC::OLLAMA::CHAT::HISTORY, JSON.dump(Readline::HISTORY))
61
47
  rescue => e
62
- warn "Caught #{e.class} while saving #{chat_history_filename.inspect}: #{e}"
48
+ msg = "Caught #{e.class} while saving #{OC::OLLAMA::CHAT::HISTORY.inspect}: #{e}"
49
+ log(:error, msg, warn: true)
63
50
  end
64
51
 
65
52
  # The clear_history method clears the Readline history array and ensures that
@@ -0,0 +1,29 @@
1
+ # Provides a simple logging facility for the OllamaChat application. It offers
2
+ # methods to access a logger, determine the current log level, and write
3
+ # messages at various severity levels, including debug.
4
+ module OllamaChat::Logging
5
+ # The logger method returns the current Logger instance used by OllamaChat.
6
+ # If no Logger exists, it creates one pointing to the configured log file.
7
+ #
8
+ # @return [Logger] the active Logger instance
9
+ def logger
10
+ @logger and return @logger
11
+ OC::OLLAMA::CHAT::LOGFILE.dirname.mkpath
12
+ @logger = Logger.new(OC::OLLAMA::CHAT::LOGFILE)
13
+ end
14
+
15
+ # The log method records a message or exception at the specified severity
16
+ # level using the logger and optionally triggers a warning output
17
+ #
18
+ # @param severity [ Symbol ] the logging level to use
19
+ # @param msg [ String, Exception ] the message or exception to be logged
20
+ # @param warn [ TrueClass, FalseClass ] whether to also trigger a warning output
21
+ def log(severity, msg, warn: false)
22
+ if msg.is_a?(Exception)
23
+ msg = "Caught #{msg.class}: #{msg}\n#{Array(msg&.backtrace).join(?\n)}"
24
+ end
25
+ logger.send(severity, msg)
26
+ warn and self.warn(msg)
27
+ nil
28
+ end
29
+ end
@@ -17,17 +17,23 @@ module OC
17
17
  prefix ''
18
18
 
19
19
  XDG_CONFIG_HOME = set do
20
- description 'XDG Configuration directory path'
20
+ description 'XDG Configuration home directory path'
21
21
  default { '~/.config' }
22
22
  decode { Pathname.new(_1).join('ollama_chat').expand_path }
23
23
  end
24
24
 
25
25
  XDG_CACHE_HOME = set do
26
- description 'XDG Cache directory path'
26
+ description 'XDG Cache home directory path'
27
27
  default { '~/.cache' }
28
28
  decode { Pathname.new(_1).join('ollama_chat').expand_path }
29
29
  end
30
30
 
31
+ XDG_STATE_HOME = set do
32
+ description 'XDG State home directory path'
33
+ default { '~/.local' }
34
+ decode { Pathname.new(_1).join('state', 'ollama_chat').expand_path }
35
+ end
36
+
31
37
  PAGER = set do
32
38
  description 'Pager command to use in case terminal lines are exceeded by output'
33
39
 
@@ -133,7 +139,12 @@ module OC
133
139
 
134
140
  HISTORY = set do
135
141
  description 'File to save the chat history in'
136
- default XDG_CACHE_HOME + 'history.json'
142
+ default XDG_STATE_HOME + 'history.json'
143
+ end
144
+
145
+ LOGFILE = set do
146
+ description 'File to output log messages to'
147
+ default XDG_STATE_HOME + 'chat.log'
137
148
  end
138
149
 
139
150
  module TOOLS
@@ -185,7 +185,7 @@ tools:
185
185
  execute_grep:
186
186
  default: true
187
187
  cmd: |
188
- grep #{'-i' if ignore_case} -m #{max_results} -r #{pattern} #{path}
188
+ grep #{'-i' if ignore_case} -m #{max_results} -r #{before.full? { "-B %u " % it }}#{after.full? { "-A %u " % it }}#{context.full? { "-C %u " % it }}#{pattern} #{path}
189
189
  browse:
190
190
  default: true
191
191
  write_file:
@@ -42,7 +42,19 @@ class OllamaChat::Tools::ExecuteGrep
42
42
  ignore_case: Tool::Function::Parameters::Property.new(
43
43
  type: 'boolean',
44
44
  description: 'Matches ignore case if true, (default: false)'
45
- )
45
+ ),
46
+ before: Tool::Function::Parameters::Property.new(
47
+ type: 'integer',
48
+ description: 'Number of lines before match (optional)'
49
+ ),
50
+ after: Tool::Function::Parameters::Property.new(
51
+ type: 'integer',
52
+ description: 'Number of lines after match (optional)'
53
+ ),
54
+ context: Tool::Function::Parameters::Property.new(
55
+ type: 'integer',
56
+ description: 'Number of lines around match (optional)'
57
+ ),
46
58
  },
47
59
  required: %w[pattern]
48
60
  )
@@ -68,9 +80,12 @@ class OllamaChat::Tools::ExecuteGrep
68
80
  args = tool_call.function.arguments
69
81
  pattern = Shellwords.escape(args.pattern)
70
82
  path = Shellwords.escape(Pathname.new(args.path || '.').expand_path)
71
- max_results = args.max_results || 100
83
+ max_results = normalize_number(args.max_results) || 100
72
84
  ignore_case = args.ignore_case || false
73
- cmd = eval_template(config, pattern, path, max_results, ignore_case)
85
+ before = normalize_number(args.before)
86
+ after = normalize_number(args.after)
87
+ context = normalize_number(args.context)
88
+ cmd = eval_template(config, pattern, path, max_results, ignore_case, before, after, context)
74
89
  result = OllamaChat::Utils::Fetcher.execute(cmd, &:read)
75
90
  { cmd:, result: }.to_json
76
91
  rescue => e
@@ -79,6 +94,17 @@ class OllamaChat::Tools::ExecuteGrep
79
94
 
80
95
  private
81
96
 
97
+ # Normalizes a number by converting it to an integer and returning the value
98
+ # only if it is greater than or equal to one.
99
+ #
100
+ # @param n [ Integer ] the number to normalize
101
+ # @return [ Integer, nil ] the normalized integer, or nil if the input was
102
+ # less than one.
103
+ def normalize_number(n)
104
+ n = n.to_i
105
+ n unless n < 1
106
+ end
107
+
82
108
  # Evaluates a template string using the provided configuration and
83
109
  # parameters.
84
110
  #
@@ -89,7 +115,7 @@ class OllamaChat::Tools::ExecuteGrep
89
115
  # @param ignore_case [true, false] whether to ignore case when searching
90
116
  #
91
117
  # @return [String] the evaluated template string with substituted variables
92
- def eval_template(config, pattern, path, max_results, ignore_case)
118
+ def eval_template(config, pattern, path, max_results, ignore_case, before, after, context)
93
119
  eval('"%s"' % config.tools.functions.execute_grep.cmd.chomp)
94
120
  end
95
121
 
@@ -20,8 +20,10 @@ class OllamaChat::Tools::PatchFile
20
20
  function: Tool::Function.new(
21
21
  name:,
22
22
  description: <<~EOT,
23
- Patch applicator – Applies unified diff patches to existing files.
24
- Path must be allowed; no return value.
23
+ Patch applicator – Applies **unified diff format** patches given as
24
+ diff_content to existing files. Path of the patched file must be
25
+ given and be allowed, returns JSON with success or
26
+ failure result.
25
27
  EOT
26
28
  parameters: Tool::Function::Parameters.new(
27
29
  type: 'object',
@@ -60,41 +62,57 @@ class OllamaChat::Tools::PatchFile
60
62
  diff_content = args.diff_content.full? or
61
63
  raise ArgumentError, 'require diff_content to patch with'
62
64
 
63
- path = assert_valid_path(args.path, config.tools.functions.patch_file.allowed?)
65
+ path = args.path.full? or raise ArgumentError, 'require path to file to be patched'
66
+ path = assert_valid_path(path, config.tools.functions.patch_file.allowed?)
64
67
 
65
68
  path.exist? or
66
69
  raise Errno::ENOENT, 'file to patch does not exist %s' % path.to_s.inspect
67
70
 
68
71
  result = apply_patch(path, diff_content)
69
-
70
- {
71
- success: true,
72
+ message = result[:success] ?
73
+ "Successfully applied patch to #{path.to_s.inspect}." :
74
+ "Failed to apply patch to file #{path.to_s.inspect}."
75
+ (result | {
72
76
  path: path.to_s,
73
- message: "Successfully applied patch to #{path}",
74
- result: ,
75
- }.to_json
77
+ message: ,
78
+ }).to_json
76
79
  rescue => e
77
80
  {
78
81
  error: e.class,
79
- message: "Failed to apply patch to file: #{e.message}",
80
- result: ,
82
+ success: false,
83
+ message: "Failed to apply patch to file #{path.to_s.inspect}: #{e.message}",
84
+ result: '',
81
85
  }.to_json
82
86
  end
83
87
 
84
88
  private
85
89
 
90
+ # Computes the MD5 digest of the file located at the given path @param path [
91
+ # String ] the path to the file whose digest is computed
92
+ #
93
+ # @return [ Digest::MD5 ] the MD5 digest of the file
94
+ def digest(path)
95
+ Digest::MD5.file(path)
96
+ end
97
+
86
98
  # Apply the unified diff content to a target file.
87
99
  #
88
100
  # @param path [Pathname] The file path to patch
89
101
  # @param diff_content [String] Unified diff format string
90
102
  def apply_patch(path, diff_content)
91
- cmd = Shellwords.join([ OC::OLLAMA::CHAT::TOOLS::PATCH_TOOL, '-u', '-f', path ])
103
+ old_digest = digest(path)
104
+ cmd = Shellwords.join(
105
+ [ OC::OLLAMA::CHAT::TOOLS::PATCH_TOOL, '-u', '-f', path ]
106
+ )
92
107
  cmd << " 2>&1"
108
+ result = { result: '', success: false }
93
109
  IO.popen(cmd, 'r+') do |output|
94
110
  output.puts diff_content
95
111
  output.close_write
96
- return output.read
112
+ result[:result] = output.read
97
113
  end
114
+ result[:success] = $?.success? && digest(path) != old_digest
115
+ result
98
116
  end
99
117
 
100
118
  self
@@ -110,7 +110,7 @@ class OllamaChat::Utils::TagResolver
110
110
  obj.linenumber = linenumber
111
111
  results << obj
112
112
  rescue => e
113
- warn "Caught #{e.class}: #{e} for #{line}"
113
+ log(:error, e, warn: true)
114
114
  end
115
115
  results
116
116
  end
@@ -1,6 +1,6 @@
1
1
  module OllamaChat
2
2
  # OllamaChat version
3
- VERSION = '0.0.78'
3
+ VERSION = '0.0.79'
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:
@@ -1,10 +1,10 @@
1
1
  # A module that provides web search functionality for OllamaChat.
2
2
  #
3
3
  # The WebSearching module encapsulates the logic for performing web searches
4
- # using configured search engines. It handles query construction, location
5
- # information integration, and delegates to engine-specific implementations for
6
- # retrieving search results. The module supports multiple search engines
7
- # including SearxNG and DuckDuckGo, making it flexible for different deployment
4
+ # using configured search engines. It handles query construction information
5
+ # integration, and delegates to engine-specific implementations for retrieving
6
+ # search results. The module supports multiple search engines including SearxNG
7
+ # and DuckDuckGo, making it flexible for different deployment
8
8
  # scenarios and privacy preferences.
9
9
  #
10
10
  # @example Performing a web search
@@ -12,8 +12,7 @@
12
12
  module OllamaChat::WebSearching
13
13
  # The search_web method performs a web search using the configured search
14
14
  # engine.
15
- # It appends location information to the query if available and limits the
16
- # number of results.
15
+ # It limits the number of results.
17
16
  # The method delegates to engine-specific search methods based on the
18
17
  # configured search engine.
19
18
  #
@@ -23,7 +22,6 @@ module OllamaChat::WebSearching
23
22
  # @return [ Array<String>, nil ] an array of URLs from the search results or
24
23
  # nil if the search engine is not implemented
25
24
  def search_web(query, n = nil)
26
- l = location_description? and query += " #{l}"
27
25
  n = n.to_i.clamp(1..)
28
26
  query = URI.encode_uri_component(query)
29
27
  search_command = :"search_web_with_#{search_engine}"
data/lib/ollama_chat.rb CHANGED
@@ -84,4 +84,5 @@ require 'ollama_chat/tools'
84
84
  require 'ollama_chat/tool_calling'
85
85
  require 'ollama_chat/config_handling'
86
86
  require 'ollama_chat/personae_management'
87
+ require 'ollama_chat/logging'
87
88
  require 'ollama_chat/chat'
data/ollama_chat.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: ollama_chat 0.0.78 ruby lib
2
+ # stub: ollama_chat 0.0.79 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "ollama_chat".freeze
6
- s.version = "0.0.78".freeze
6
+ s.version = "0.0.79".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,13 +12,13 @@ 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]
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/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.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/information.rb".freeze, "lib/ollama_chat/input_content.rb".freeze, "lib/ollama_chat/kramdown_ansi.rb".freeze, "lib/ollama_chat/location_handling.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/redis_cache.rb".freeze, "lib/ollama_chat/server_socket.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/think_control.rb".freeze, "lib/ollama_chat/tool_calling.rb".freeze, "lib/ollama_chat/tools.rb".freeze, "lib/ollama_chat/tools/browse.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/copy_to_clipboard.rb".freeze, "lib/ollama_chat/tools/directory_structure.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_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_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/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/run_tests.rb".freeze, "lib/ollama_chat/tools/search_web.rb".freeze, "lib/ollama_chat/tools/write_file.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/analyze_directory.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/file_argument.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/tag_resolver.rb".freeze, "lib/ollama_chat/version.rb".freeze, "lib/ollama_chat/vim.rb".freeze, "lib/ollama_chat/web_searching.rb".freeze]
16
- s.files = [".utilsrc".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_chat_send".freeze, "config/searxng/settings.yml".freeze, "docker-compose.yml".freeze, "lib/ollama_chat.rb".freeze, "lib/ollama_chat/chat.rb".freeze, "lib/ollama_chat/clipboard.rb".freeze, "lib/ollama_chat/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.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/information.rb".freeze, "lib/ollama_chat/input_content.rb".freeze, "lib/ollama_chat/kramdown_ansi.rb".freeze, "lib/ollama_chat/location_handling.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/redis_cache.rb".freeze, "lib/ollama_chat/server_socket.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/think_control.rb".freeze, "lib/ollama_chat/tool_calling.rb".freeze, "lib/ollama_chat/tools.rb".freeze, "lib/ollama_chat/tools/browse.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/copy_to_clipboard.rb".freeze, "lib/ollama_chat/tools/directory_structure.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_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_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/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/run_tests.rb".freeze, "lib/ollama_chat/tools/search_web.rb".freeze, "lib/ollama_chat/tools/write_file.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/analyze_directory.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/file_argument.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/tag_resolver.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/deep/deeper/empty.txt".freeze, "spec/assets/deep/deeper/not-empty.txt".freeze, "spec/assets/deep/empty.txt".freeze, "spec/assets/duckduckgo.html".freeze, "spec/assets/example.atom".freeze, "spec/assets/example.csv".freeze, "spec/assets/example.html".freeze, "spec/assets/example.pdf".freeze, "spec/assets/example.ps".freeze, "spec/assets/example.rb".freeze, "spec/assets/example.rss".freeze, "spec/assets/example.xml".freeze, "spec/assets/example_with_quote.html".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/pirateweather.json".freeze, "spec/assets/prompt.txt".freeze, "spec/assets/searxng.json".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/input_content_spec.rb".freeze, "spec/ollama_chat/kramdown_ansi_spec.rb".freeze, "spec/ollama_chat/message_editing_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/message_output_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/state_selectors_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/copy_to_clipboard_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_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_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/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/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_web_spec.rb".freeze, "spec/ollama_chat/tools/write_file_spec.rb".freeze, "spec/ollama_chat/utils/analyze_directory_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/file_argument_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/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.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/information.rb".freeze, "lib/ollama_chat/input_content.rb".freeze, "lib/ollama_chat/kramdown_ansi.rb".freeze, "lib/ollama_chat/location_handling.rb".freeze, "lib/ollama_chat/logging.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/redis_cache.rb".freeze, "lib/ollama_chat/server_socket.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/think_control.rb".freeze, "lib/ollama_chat/tool_calling.rb".freeze, "lib/ollama_chat/tools.rb".freeze, "lib/ollama_chat/tools/browse.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/copy_to_clipboard.rb".freeze, "lib/ollama_chat/tools/directory_structure.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_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_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/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/run_tests.rb".freeze, "lib/ollama_chat/tools/search_web.rb".freeze, "lib/ollama_chat/tools/write_file.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/analyze_directory.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/file_argument.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/tag_resolver.rb".freeze, "lib/ollama_chat/version.rb".freeze, "lib/ollama_chat/vim.rb".freeze, "lib/ollama_chat/web_searching.rb".freeze]
16
+ s.files = [".utilsrc".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_chat_send".freeze, "config/searxng/settings.yml".freeze, "docker-compose.yml".freeze, "lib/ollama_chat.rb".freeze, "lib/ollama_chat/chat.rb".freeze, "lib/ollama_chat/clipboard.rb".freeze, "lib/ollama_chat/config_handling.rb".freeze, "lib/ollama_chat/conversation.rb".freeze, "lib/ollama_chat/dialog.rb".freeze, "lib/ollama_chat/document_cache.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/information.rb".freeze, "lib/ollama_chat/input_content.rb".freeze, "lib/ollama_chat/kramdown_ansi.rb".freeze, "lib/ollama_chat/location_handling.rb".freeze, "lib/ollama_chat/logging.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/redis_cache.rb".freeze, "lib/ollama_chat/server_socket.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/think_control.rb".freeze, "lib/ollama_chat/tool_calling.rb".freeze, "lib/ollama_chat/tools.rb".freeze, "lib/ollama_chat/tools/browse.rb".freeze, "lib/ollama_chat/tools/concern.rb".freeze, "lib/ollama_chat/tools/copy_to_clipboard.rb".freeze, "lib/ollama_chat/tools/directory_structure.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_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_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/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/run_tests.rb".freeze, "lib/ollama_chat/tools/search_web.rb".freeze, "lib/ollama_chat/tools/write_file.rb".freeze, "lib/ollama_chat/utils.rb".freeze, "lib/ollama_chat/utils/analyze_directory.rb".freeze, "lib/ollama_chat/utils/cache_fetcher.rb".freeze, "lib/ollama_chat/utils/chooser.rb".freeze, "lib/ollama_chat/utils/fetcher.rb".freeze, "lib/ollama_chat/utils/file_argument.rb".freeze, "lib/ollama_chat/utils/path_validator.rb".freeze, "lib/ollama_chat/utils/tag_resolver.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/deep/deeper/empty.txt".freeze, "spec/assets/deep/deeper/not-empty.txt".freeze, "spec/assets/deep/empty.txt".freeze, "spec/assets/duckduckgo.html".freeze, "spec/assets/example.atom".freeze, "spec/assets/example.csv".freeze, "spec/assets/example.html".freeze, "spec/assets/example.pdf".freeze, "spec/assets/example.ps".freeze, "spec/assets/example.rb".freeze, "spec/assets/example.rss".freeze, "spec/assets/example.xml".freeze, "spec/assets/example_with_quote.html".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/pirateweather.json".freeze, "spec/assets/prompt.txt".freeze, "spec/assets/searxng.json".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/input_content_spec.rb".freeze, "spec/ollama_chat/kramdown_ansi_spec.rb".freeze, "spec/ollama_chat/message_editing_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/message_output_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/state_selectors_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/copy_to_clipboard_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_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_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/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/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_web_spec.rb".freeze, "spec/ollama_chat/tools/write_file_spec.rb".freeze, "spec/ollama_chat/utils/analyze_directory_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/file_argument_spec.rb".freeze, "spec/ollama_chat/vim_spec.rb".freeze, "spec/ollama_chat/web_searching_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tmp/.keep".freeze]
17
17
  s.homepage = "https://github.com/flori/ollama_chat".freeze
18
18
  s.licenses = ["MIT".freeze]
19
19
  s.rdoc_options = ["--title".freeze, "OllamaChat - A command-line interface (CLI) for interacting with an Ollama AI model.".freeze, "--main".freeze, "README.md".freeze]
20
20
  s.required_ruby_version = Gem::Requirement.new(">= 3.2".freeze)
21
- s.rubygems_version = "4.0.3".freeze
21
+ s.rubygems_version = "3.6.9".freeze
22
22
  s.summary = "A command-line interface (CLI) for interacting with an Ollama AI model.".freeze
23
23
  s.test_files = ["spec/assets/example.rb".freeze, "spec/ollama_chat/chat_spec.rb".freeze, "spec/ollama_chat/clipboard_spec.rb".freeze, "spec/ollama_chat/follow_chat_spec.rb".freeze, "spec/ollama_chat/information_spec.rb".freeze, "spec/ollama_chat/input_content_spec.rb".freeze, "spec/ollama_chat/kramdown_ansi_spec.rb".freeze, "spec/ollama_chat/message_editing_spec.rb".freeze, "spec/ollama_chat/message_list_spec.rb".freeze, "spec/ollama_chat/message_output_spec.rb".freeze, "spec/ollama_chat/model_handling_spec.rb".freeze, "spec/ollama_chat/parsing_spec.rb".freeze, "spec/ollama_chat/redis_cache_spec.rb".freeze, "spec/ollama_chat/server_socket_spec.rb".freeze, "spec/ollama_chat/source_fetching_spec.rb".freeze, "spec/ollama_chat/state_selectors_spec.rb".freeze, "spec/ollama_chat/switches_spec.rb".freeze, "spec/ollama_chat/think_control_spec.rb".freeze, "spec/ollama_chat/tools/browse_spec.rb".freeze, "spec/ollama_chat/tools/copy_to_clipboard_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_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_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/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/run_tests_spec.rb".freeze, "spec/ollama_chat/tools/search_web_spec.rb".freeze, "spec/ollama_chat/tools/write_file_spec.rb".freeze, "spec/ollama_chat/utils/analyze_directory_spec.rb".freeze, "spec/ollama_chat/utils/cache_fetcher_spec.rb".freeze, "spec/ollama_chat/utils/fetcher_spec.rb".freeze, "spec/ollama_chat/utils/file_argument_spec.rb".freeze, "spec/ollama_chat/vim_spec.rb".freeze, "spec/ollama_chat/web_searching_spec.rb".freeze, "spec/spec_helper.rb".freeze]
24
24
 
@@ -235,23 +235,19 @@ describe OllamaChat::Chat, protect_env: true do
235
235
  describe 'chat history' do
236
236
  connect_to_ollama_server(instantiate: false)
237
237
 
238
- it 'derives chat_history_filename' do
239
- expect(chat.chat_history_filename).to_not be_nil
240
- end
241
-
242
238
  it 'can save chat history' do
243
239
  expect(File).to receive(:secure_write).with(
244
- chat.chat_history_filename,
245
- kind_of(String)
240
+ OC::OLLAMA::CHAT::HISTORY, kind_of(String)
246
241
  )
247
242
  chat.save_history
248
243
  end
249
244
 
250
245
  it 'can initialize chat history' do
251
- expect(File).to receive(:exist?).with(chat.chat_history_filename).
252
- and_return true
253
- expect(File).to receive(:open).with(chat.chat_history_filename, ?r)
254
- chat.init_chat_history
246
+ expect(OC::OLLAMA::CHAT::HISTORY).to receive(:exist?).and_return true
247
+ expect(OC::OLLAMA::CHAT::HISTORY).to receive(:read).and_return '{}'
248
+ expect_any_instance_of(described_class).to receive(:init_chat_history).
249
+ and_call_original
250
+ chat
255
251
  end
256
252
 
257
253
  it 'can clear history' do
@@ -26,7 +26,10 @@ describe OllamaChat::Tools::ExecuteGrep do
26
26
  pattern: 'Hello World',
27
27
  path: 'spec/assets',
28
28
  max_results: nil,
29
- ignore_case: nil
29
+ ignore_case: nil,
30
+ after: nil,
31
+ before: nil,
32
+ context: nil,
30
33
  )
31
34
  )
32
35
  )
@@ -55,7 +58,10 @@ describe OllamaChat::Tools::ExecuteGrep do
55
58
  pattern: 'class',
56
59
  path: 'spec/assets',
57
60
  max_results: 5,
58
- ignore_case: nil
61
+ ignore_case: nil,
62
+ after: nil,
63
+ before: nil,
64
+ context: nil,
59
65
  )
60
66
  )
61
67
  )
@@ -83,7 +89,10 @@ describe OllamaChat::Tools::ExecuteGrep do
83
89
  pattern: 'class',
84
90
  path: 'spec/assets',
85
91
  max_results: 5,
86
- ignore_case: true
92
+ ignore_case: true,
93
+ after: nil,
94
+ before: nil,
95
+ context: nil,
87
96
  )
88
97
  )
89
98
  )
@@ -103,7 +112,6 @@ describe OllamaChat::Tools::ExecuteGrep do
103
112
  expect(json.result).to match(/blub class blob/)
104
113
  end
105
114
 
106
-
107
115
  it 'can handle execution errors gracefully' do
108
116
  # Test with a non-existent pattern
109
117
  tool_call = double(
@@ -114,7 +122,10 @@ describe OllamaChat::Tools::ExecuteGrep do
114
122
  pattern: 'nonexistent_pattern',
115
123
  path: 'spec/assets',
116
124
  max_results: nil,
117
- ignore_case: nil
125
+ ignore_case: nil,
126
+ after: nil,
127
+ before: nil,
128
+ context: nil,
118
129
  )
119
130
  )
120
131
  )
@@ -142,7 +153,10 @@ describe OllamaChat::Tools::ExecuteGrep do
142
153
  pattern: 'test',
143
154
  path: '/nonexistent/path/that/does/not/exist',
144
155
  max_results: nil,
145
- ignore_case: nil
156
+ ignore_case: nil,
157
+ after: nil,
158
+ before: nil,
159
+ context: nil,
146
160
  )
147
161
  )
148
162
  )
@@ -168,7 +182,10 @@ describe OllamaChat::Tools::ExecuteGrep do
168
182
  pattern: 'test',
169
183
  path: '/nonexistent/path/that/does/not/exist',
170
184
  max_results: nil,
171
- ignore_case: nil
185
+ ignore_case: nil,
186
+ after: nil,
187
+ before: nil,
188
+ context: nil,
172
189
  )
173
190
  )
174
191
  )
@@ -193,7 +210,10 @@ describe OllamaChat::Tools::ExecuteGrep do
193
210
  pattern: 'Hello World!',
194
211
  path: 'spec/assets',
195
212
  max_results: nil,
196
- ignore_case: nil
213
+ ignore_case: nil,
214
+ after: nil,
215
+ before: nil,
216
+ context: nil,
197
217
  )
198
218
  )
199
219
  )
data/spec/spec_helper.rb CHANGED
@@ -192,6 +192,13 @@ RSpec.configure do |config|
192
192
  infobar.show = nil
193
193
  end
194
194
 
195
+ config.before do
196
+ const_conf_as(
197
+ 'OC::OLLAMA::CHAT::HISTORY' => Pathname.pwd.join('tmp', 'history.json'),
198
+ 'OC::OLLAMA::CHAT::LOGFILE' => Pathname.pwd.join('tmp', 'chat.log')
199
+ )
200
+ end
201
+
195
202
  config.around(&ProtectEnvVars.apply)
196
203
  config.include(ConstConf::ConstConfHelper)
197
204
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ollama_chat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.78
4
+ version: 0.0.79
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -464,6 +464,7 @@ extra_rdoc_files:
464
464
  - lib/ollama_chat/input_content.rb
465
465
  - lib/ollama_chat/kramdown_ansi.rb
466
466
  - lib/ollama_chat/location_handling.rb
467
+ - lib/ollama_chat/logging.rb
467
468
  - lib/ollama_chat/message_editing.rb
468
469
  - lib/ollama_chat/message_format.rb
469
470
  - lib/ollama_chat/message_list.rb
@@ -543,6 +544,7 @@ files:
543
544
  - lib/ollama_chat/input_content.rb
544
545
  - lib/ollama_chat/kramdown_ansi.rb
545
546
  - lib/ollama_chat/location_handling.rb
547
+ - lib/ollama_chat/logging.rb
546
548
  - lib/ollama_chat/message_editing.rb
547
549
  - lib/ollama_chat/message_format.rb
548
550
  - lib/ollama_chat/message_list.rb
@@ -694,7 +696,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
694
696
  - !ruby/object:Gem::Version
695
697
  version: '0'
696
698
  requirements: []
697
- rubygems_version: 4.0.3
699
+ rubygems_version: 3.6.9
698
700
  specification_version: 4
699
701
  summary: A command-line interface (CLI) for interacting with an Ollama AI model.
700
702
  test_files: