ollama_chat 0.0.67 → 0.0.68

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: 3eb8ee4b480c19b26ba27b6d112da4038ed16615881425ba4f7142483d329a79
4
- data.tar.gz: 85a7d64b19b3e751d51d7ada7af2ff536e578f3425218394b0aa3efcd5301626
3
+ metadata.gz: 135734ab31efeba4bc0ba5a5268bb739269de2e30ed9bed5e92897e2bcf91007
4
+ data.tar.gz: 7b331fa27f44318d73524b532573a4e2a60d1d33a234400794ee30dfc9cb3210
5
5
  SHA512:
6
- metadata.gz: f374a3d58183068936222115a61e090ee3e45efd637401ffd97cebc147286b971025730d6393e95dc2b5eeb2e89cacc65d33a3dc76f6467fb23e1aedfe13fffd
7
- data.tar.gz: fefa35f2e685dab9c4f3e8b97487f4a4a072f3b2b982864ae423b8d4aaba29ea3e46dc4065dedb7db3908f3192c56c922f92e123163272ef186771b862b7ffc4
6
+ metadata.gz: 646671b9819e6f531e170edb969ce21d60bc7e32abbb1872eaa22da107895deaf0c5d46f816189d724a92a10e5cdcf21850e12ba80fa532e8e99d2f68265cfd7
7
+ data.tar.gz: b2f2a6e619d599d435025dfe715d7fab6af0d416356672a4c95721cff0bedb534868217281db916f9b26af3d1886e75c566d0695d712a341227fafd4b6e38ef4
data/CHANGES.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-02-19 v0.0.68
4
+
5
+ - Added JSON serialization for directory structure in `OllamaChat::Parsing`
6
+ using `generate_structure(file).to_json`
7
+ - Introduced `OllamaChat::HTTPError` exception with `status` attribute for
8
+ better error handling
9
+ - Enhanced `OllamaChat::Utils::Fetcher` to handle `reraise` option and raise
10
+ `HTTPError` on non-200 HTTP responses
11
+ - Added `require_confirmation: true` option for `open_file_in_editor` tool in
12
+ default configuration to provide additional safety check
13
+ - Updated `AssetHelpers.asset` in `spec/spec_helper.rb` to accept optional name
14
+ parameter
15
+ - Included `OllamaChat::Utils::AnalyzeDirectory` mixin in `OllamaChat::Parsing`
16
+ to simplify method calls
17
+ - Replaced fully-qualified
18
+ `OllamaChat::Utils::AnalyzeDirectory.generate_structure(file)` calls with
19
+ local `generate_structure(file)` after including the module
20
+ - Added specs to verify JSON output contains expected file names in
21
+ `spec/ollama_chat/parsing_spec.rb`
22
+ - Updated tools (`get_cve`, `get_endoflife`, `get_jira_issue`) to pass
23
+ `reraise: true` to Excon for improved error propagation
24
+
3
25
  ## 2026-02-18 v0.0.67
4
26
 
5
27
  - Added `max_depth` option to directory listing tool
@@ -139,6 +139,7 @@ tools:
139
139
  default: true
140
140
  open_file_in_editor:
141
141
  default: true
142
+ require_confirmation: true
142
143
  run_tests:
143
144
  require_confirmation: true
144
145
  default: true
@@ -12,6 +12,8 @@
12
12
  # chat.parse_source(pdf_io) # Extracts text from PDF files
13
13
  # chat.parse_source(csv_io) # Formats CSV data into readable strings
14
14
  module OllamaChat::Parsing
15
+ include OllamaChat::Utils::AnalyzeDirectory
16
+
15
17
  # The parse_source method processes different types of input sources and
16
18
  # converts them into a standardized text representation.
17
19
  #
@@ -221,7 +223,7 @@ module OllamaChat::Parsing
221
223
  contents = [ content ]
222
224
  content.scan(CONTENT_REGEXP).each { |url, tag, file_url, quoted_file, file|
223
225
  if file && File.directory?(file)
224
- contents << OllamaChat::Utils::AnalyzeDirectory.generate_structure(file)
226
+ contents << generate_structure(file).to_json
225
227
  next
226
228
  end
227
229
  check_exist = false
@@ -55,6 +55,7 @@ class OllamaChat::Tools::GetCVE
55
55
  'Accept' => 'application/json',
56
56
  },
57
57
  debug: OllamaChat::EnvConfig::OLLAMA::CHAT::DEBUG,
58
+ reraise: true,
58
59
  &valid_json?
59
60
  )
60
61
  rescue => e
@@ -60,6 +60,7 @@ class OllamaChat::Tools::GetEndoflife
60
60
  'User-Agent' => OllamaChat::Chat.user_agent
61
61
  },
62
62
  debug: OllamaChat::EnvConfig::OLLAMA::CHAT::DEBUG,
63
+ reraise: true,
63
64
  &valid_json?
64
65
  )
65
66
  rescue => e
@@ -76,6 +76,7 @@ class OllamaChat::Tools::GetJiraIssue
76
76
  url,
77
77
  user: env::USER,
78
78
  password: env::API_TOKEN,
79
+ reraise: true,
79
80
  &valid_json?
80
81
  )
81
82
  end
@@ -69,34 +69,75 @@ class OllamaChat::Utils::Fetcher
69
69
  # rescue RetryWithoutStreaming
70
70
  # # Handle retry with non-streaming method
71
71
  # end
72
- class RetryWithoutStreaming < StandardError; end
72
+ class RetryWithoutStreaming < OllamaChat::OllamaChatError; end
73
73
 
74
- # The get method retrieves content from a URL, using caching when available.
75
- # It processes the URL with optional headers and additional options,
76
- # then yields a temporary file containing the retrieved content.
77
- # If caching is enabled and content is found in the cache,
78
- # it returns the cached result instead of fetching again.
79
- # The method handles both cached and fresh fetches,
80
- # ensuring that cache is updated when new content is retrieved.
81
- #
82
- # @param url [ String ] the URL to fetch content from
83
- # @param headers [ Hash ] optional headers to include in the request
84
- # @param options [ Hash ] additional options for the fetch operation
85
- #
86
- # @yield [ tmp ]
87
- #
88
- # @return [ Object ] the result of the block execution
89
- # @return [ nil ] if no block is given or if the fetch fails
74
+ # Fetches the content located at +url+ and optionally caches it.
75
+ #
76
+ # This is a convenience wrapper around an instance of
77
+ # `OllamaChat::Utils::Fetcher`. It accepts the same options as the
78
+ # instance method, with the following additions:
79
+ #
80
+ # * `:cache` an object that responds to `get` and `put` (see
81
+ # `OllamaChat::Utils::CacheFetcher`). If a cached value exists,
82
+ # it is returned immediately and the network is not contacted.
83
+ # * `:reraise` if true, any exception raised during the fetch
84
+ # will be re‑raised after a failed temporary file has been yielded.
85
+ # The exception type `OllamaChat::HTTPError` is raised only when
86
+ # `:reraise` is true; otherwise the error is swallowed and the
87
+ # caller receives a failed `StringIO` via the block.
88
+ #
89
+ # The method streams the HTTP response into a temporary file (or a
90
+ # `StringIO` in the event of a failure). The temporary file is
91
+ # extended with `HeaderExtension`, so the block can inspect
92
+ # `tmp.content_type` and `tmp.ex`. After the block returns the
93
+ # temporary file is closed and discarded. If a cache is supplied
94
+ # and the response is not a `StringIO`, the temporary file is written
95
+ # back to the cache for future requests.
96
+ #
97
+ # @param url [String] the URL to fetch
98
+ # @param headers [Hash] optional HTTP headers to send with the request
99
+ # @param options [Hash] additional options
100
+ # * `:cache` – a cache object (see above)
101
+ # * `:reraise` – see description above
102
+ # * `:middlewares` – array of Excon middleware classes
103
+ # * `:http_options` – hash of options forwarded to the Excon client
104
+ #
105
+ # @yield [tmp] Gives the caller a `Tempfile` (or a `StringIO` in case of
106
+ # failure) that contains the fetched content. The yielded object
107
+ # is already extended with `HeaderExtension`, so the block can read
108
+ # `tmp.content_type` and `tmp.ex`.
109
+ #
110
+ # @return [Object] the value returned by the block. If no block is
111
+ # given, the method returns `nil`. If a cached value is returned,
112
+ # the cached object (typically a `StringIO`) is returned directly.
113
+ #
114
+ # @raise [OllamaChat::HTTPError] when the HTTP response status is not
115
+ # 200 **and** the `:reraise` option is true. The error is raised
116
+ # after the failed `StringIO` has been yielded to the caller.
117
+ # @raise [OllamaChat::OllamaChatError] (or subclasses) for other
118
+ # network or I/O errors. If `:reraise` is true, the original
119
+ # exception is re‑raised after yielding the failed `StringIO`.
120
+ #
121
+ # @example Fetch a URL with caching
122
+ # cache = RedisCache.new
123
+ # fetcher = OllamaChat::Utils::Fetcher
124
+ # fetcher.get('https://example.com/data.json', cache: cache) do |tmp|
125
+ # JSON.parse(tmp.read)
126
+ # end
127
+ #
128
+ # @see OllamaChat::Utils::CacheFetcher
129
+ # @see HeaderExtension
90
130
  def self.get(url, headers: {}, **options, &block)
91
131
  cache = options.delete(:cache) and
92
132
  cache = OllamaChat::Utils::CacheFetcher.new(cache)
133
+ reraise = options.delete(:reraise)
93
134
  cache and infobar.puts "Getting #{url.to_s.inspect} via cache…"
94
135
  if result = cache&.get(url, &block)
95
136
  content_type = result&.content_type || 'unknown'
96
137
  infobar.puts "…hit, found #{content_type} content in cache."
97
138
  return result
98
139
  else
99
- new(**options).send(:get, url, headers:) do |tmp|
140
+ new(**options).send(:get, url, headers:, reraise:) do |tmp|
100
141
  result = block.(tmp)
101
142
  if cache && !tmp.is_a?(StringIO)
102
143
  tmp.rewind
@@ -185,19 +226,67 @@ class OllamaChat::Utils::Fetcher
185
226
  @http_options = http_options
186
227
  end
187
228
 
188
- # Makes an HTTP GET request to the specified URL with optional headers and
189
- # processing block.
229
+ # Fetches the content located at +url+.
190
230
  #
191
- # This method handles both streaming and non-streaming HTTP requests, using
192
- # Excon for the actual HTTP communication. The response body is written to a
193
- # temporary file which is then decorated with additional behavior before
194
- # being passed to the provided block.
231
+ # The method first checks an optional cache (passed via the `:cache` option).
232
+ # If a cached response is found, it is returned immediately. Otherwise the
233
+ # URL is fetched over HTTP using Excon. Two modes are supported:
234
+ #
235
+ # * **Streaming** – the response body is streamed directly into a temporary
236
+ # file. Progress is reported via `infobar`. If the first request
237
+ # fails with a non‑200 status or the streaming mode is not supported,
238
+ # the method falls back to a non‑streaming request.
239
+ # * **Non‑streaming** – the entire body is read into memory before
240
+ # being written to the temporary file.
241
+ #
242
+ # The temporary file is yielded to the caller. The file is extended
243
+ # with `HeaderExtension`, so the block can inspect `content_type` and
244
+ # `ex` (cache‑expiry in seconds). After the block returns, the
245
+ # temporary file is closed and discarded.
246
+ #
247
+ # If a cache is supplied and the response is not a `StringIO`, the
248
+ # temporary file is written back to the cache for future requests.
249
+ #
250
+ # @param url [String] the URL to fetch
251
+ # @param headers [Hash] optional HTTP headers to send with the request
252
+ # @param options [Hash] additional options
253
+ # * `:cache` – an object that responds to `get` and `put` (see
254
+ # `OllamaChat::Utils::CacheFetcher`). When present, the method
255
+ # will attempt to read from the cache before making a network
256
+ # request.
257
+ # * `:reraise` – if true, any exception raised during the fetch
258
+ # will be re‑raised after a failed temporary file is yielded.
259
+ # * `:middlewares` – an array of Excon middleware classes to apply.
260
+ # * `:http_options` – hash of options forwarded to the Excon client.
261
+ #
262
+ # @yield [tmp] Gives the caller a `Tempfile` (or a `StringIO` in the
263
+ # unlikely event of a failure) that contains the fetched content.
264
+ # The yielded object is already extended with `HeaderExtension`,
265
+ # so the block can read `tmp.content_type` and `tmp.ex`.
266
+ #
267
+ # @return [Object] the value returned by the block. If no block is
268
+ # given, the method returns `nil`. If a cached value is returned,
269
+ # the cached object (typically a `StringIO`) is returned directly.
270
+ #
271
+ # @raise [OllamaChat::HTTPError] when the HTTP response status is not
272
+ # 200 **and** the `:reraise` option is true. The error is raised
273
+ # after the failed `StringIO` has been yielded to the caller.
274
+ # @raise [OllamaChat::OllamaChatError] (or subclasses) for other
275
+ # network or I/O errors. If `:reraise` is true, the original
276
+ # exception is re‑raised after yielding the failed `StringIO`.
277
+ #
278
+ # @example Fetch a URL with caching
279
+ # cache = RedisCache.new
280
+ # fetcher = OllamaChat::Utils::Fetcher
281
+ # fetcher.get('https://example.com/data.json', cache: cache) do |tmp|
282
+ # JSON.parse(tmp.read)
283
+ # end
195
284
  #
196
- # @param url [String] The URL to make the GET request to
197
- # @yield [Tempfile] The temporary file containing the response body, after
198
- # decoration
285
+ # @see OllamaChat::Utils::CacheFetcher
286
+ # @see HeaderExtension
199
287
  def get(url, **opts, &block)
200
288
  opts.delete(:response_block) and raise ArgumentError, 'response_block not allowed'
289
+ reraise ||= opts.delete(:reraise)
201
290
  middlewares = (self.middlewares | Array((opts.delete(:middlewares)))).uniq
202
291
  headers = opts.delete(:headers) || {}
203
292
  headers |= self.headers
@@ -213,8 +302,11 @@ class OllamaChat::Utils::Fetcher
213
302
  block.(tmp)
214
303
  else
215
304
  response = excon(url, headers:, middlewares:, **opts).request(method: :get)
216
- if response.status != 200
217
- raise "invalid response status code"
305
+ if status = response.status and status != 200
306
+ message = "request failed: %u %s" % [ status, response.reason_phrase ]
307
+ error = OllamaChat::HTTPError.new(message)
308
+ error.status = status
309
+ raise error
218
310
  end
219
311
  body = response.body
220
312
  tmp.print body
@@ -233,6 +325,7 @@ class OllamaChat::Utils::Fetcher
233
325
  STDERR.puts "#{e.backtrace * ?\n}"
234
326
  end
235
327
  yield HeaderExtension.failed
328
+ reraise and raise e
236
329
  end
237
330
 
238
331
  private
@@ -1,6 +1,6 @@
1
1
  module OllamaChat
2
2
  # OllamaChat version
3
- VERSION = '0.0.67'
3
+ VERSION = '0.0.68'
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
@@ -32,6 +32,13 @@ module OllamaChat
32
32
  # log or display the problematic location.
33
33
  class ConfigMissingError < OllamaChatError
34
34
  end
35
+
36
+ # Error raised when an HTTP request returns a non‑200 status code.
37
+ class HTTPError < OllamaChatError
38
+ # @!attribute [r] status
39
+ # @return [Integer] the HTTP status code that caused the error.
40
+ attr_accessor :status
41
+ end
35
42
  end
36
43
 
37
44
  require 'ollama'
data/ollama_chat.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: ollama_chat 0.0.67 ruby lib
2
+ # stub: ollama_chat 0.0.68 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "ollama_chat".freeze
6
- s.version = "0.0.67".freeze
6
+ s.version = "0.0.68".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]
@@ -279,5 +279,18 @@ describe OllamaChat::Parsing do
279
279
  EOT
280
280
  end
281
281
  end
282
+
283
+ it 'generates a readable directory‑structure string for directories' do
284
+ content, = chat.parse_content("look at #{asset}", [])
285
+ json_data = content.lines[2..-1].join('')
286
+ json = JSON(json_data)
287
+ expect(json.map { _1['name'] }.sort).to eq(
288
+ ["api_show.json", "api_tags.json", "api_version.json",
289
+ "conversation.json", "deep", "duckduckgo.html", "example.atom",
290
+ "example.csv", "example.html", "example.pdf", "example.ps",
291
+ "example.rb", "example.rss", "example.xml", "example_with_quote.html",
292
+ "kitten.jpg", "prompt.txt", "searxng.json"]
293
+ )
294
+ end
282
295
  end
283
296
  end
@@ -93,11 +93,24 @@ describe OllamaChat::Utils::Fetcher do
93
93
  with(headers: fetcher.headers).
94
94
  to_return(status: 500)
95
95
  expect(STDERR).to receive(:puts).with(/cannot.*get.*#{url}/i)
96
- fetcher.get(url) do |tmp|
96
+ fetcher.get(url) do |tmp|
97
+ expect(tmp).to be_a StringIO
98
+ expect(tmp.read).to eq ''
99
+ expect(tmp.content_type).to eq 'text/plain'
100
+ end
101
+ end
102
+
103
+ it 'can #get and finally fail with reraise' do
104
+ stub_request(:get, url).
105
+ with(headers: fetcher.headers).
106
+ to_return(status: 500)
107
+ expect {
108
+ fetcher.get(url, reraise: true) do |tmp|
97
109
  expect(tmp).to be_a StringIO
98
110
  expect(tmp.read).to eq ''
99
111
  expect(tmp.content_type).to eq 'text/plain'
100
112
  end
113
+ }.to raise_error OllamaChat::HTTPError, /request failed: 500/
101
114
  end
102
115
 
103
116
  it 'can redirect' do
data/spec/spec_helper.rb CHANGED
@@ -33,8 +33,8 @@ module AssetHelpers
33
33
  # @param name [String] the name of the asset file
34
34
  #
35
35
  # @return [String] the full path to the asset file
36
- def asset(name)
37
- File.join(__dir__, 'assets', name)
36
+ def asset(name = nil)
37
+ File.join(*[__dir__, 'assets', name ].compact)
38
38
  end
39
39
 
40
40
  # Reads and returns the content of an asset file from the assets directory.
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.67
4
+ version: 0.0.68
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank