ollama-ruby 0.9.0 → 0.9.1
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 +4 -4
- data/CHANGES.md +16 -0
- data/bin/ollama_chat +138 -134
- data/lib/ollama/utils/fetcher.rb +8 -0
- data/lib/ollama/version.rb +1 -1
- data/ollama-ruby.gemspec +3 -3
- data/spec/ollama/utils/fetcher_spec.rb +27 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3976b4254bbedc3655a6a737000903217eff8b4b941971eb6ae4fda630ba40c3
|
4
|
+
data.tar.gz: 29187dded0f2748e8e684648ab374d027aaff18a6f85ede48df78dc34b705645
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69ad552c73c297d23db6a65681008c79329de3d4a02a07f28b027a94820f9505488870e4bce6b43c1ae6a6fb64c6107ce4cc3d28b307f07573987464e6eaed84
|
7
|
+
data.tar.gz: 79dd0a71d48726900ed7df4508f2031191f00f15b3713cc562aa29112c4942e72836c5d487c8883b173dc760d8e815461b66e3c4b0fbdccd1226e6019af2419a
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# Changes
|
2
2
|
|
3
|
+
## 2024-10-19 v0.9.1
|
4
|
+
|
5
|
+
* Fixing string interpolation in `import_source` method:
|
6
|
+
+ Changed result to use `#{}` instead of `%{}` for string interpolation
|
7
|
+
* Move `pull_model_unless_present` method:
|
8
|
+
+ Moved the method before other methods
|
9
|
+
* Moved Switch classes and `setup_switches` method into Switches module:
|
10
|
+
+ Moved the classes and method into a new module
|
11
|
+
* Utils::Fetcher: Normalize URL in fetcher utility:
|
12
|
+
+ Added `normalize_url` method to class Ollama::Utils::Fetcher
|
13
|
+
+ Normalizes URL by decoding URI components, removing anchors, and escaping special characters
|
14
|
+
+ `excon` method now calls `normalize_url` on the provided URL
|
15
|
+
+ Added specs for `normalize_url` in `fetcher_spec.rb`
|
16
|
+
* Remove Ollama top level Namespace b/c we include it from `ollama_chat`:
|
17
|
+
+ Removed the top-level namespace
|
18
|
+
|
3
19
|
## 2024-10-18 v0.9.0
|
4
20
|
|
5
21
|
* Add document policy chooser and modify embedding/importing/summarizing
|
data/bin/ollama_chat
CHANGED
@@ -108,7 +108,7 @@ class OllamaChatConfig
|
|
108
108
|
end
|
109
109
|
|
110
110
|
class FollowChat
|
111
|
-
include
|
111
|
+
include Handlers::Concern
|
112
112
|
include Term::ANSIColor
|
113
113
|
|
114
114
|
def initialize(messages:, markdown: false, voice: nil, output: $stdout)
|
@@ -164,114 +164,142 @@ class FollowChat
|
|
164
164
|
end
|
165
165
|
end
|
166
166
|
|
167
|
-
module
|
168
|
-
|
167
|
+
module Switches
|
168
|
+
module CheckSwitch
|
169
|
+
extend Tins::Concern
|
169
170
|
|
170
|
-
|
171
|
-
|
172
|
-
|
171
|
+
included do
|
172
|
+
alias_method :on?, :value
|
173
|
+
end
|
173
174
|
|
174
|
-
|
175
|
-
|
176
|
-
|
175
|
+
def off?
|
176
|
+
!on?
|
177
|
+
end
|
177
178
|
|
178
|
-
|
179
|
-
|
179
|
+
def show
|
180
|
+
puts @msg[value]
|
181
|
+
end
|
180
182
|
end
|
181
|
-
end
|
182
183
|
|
183
|
-
class Switch
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
184
|
+
class Switch
|
185
|
+
def initialize(name, msg:, config: $config)
|
186
|
+
@value = [ false, true ].include?(config) ? config : !!config.send("#{name}?")
|
187
|
+
@msg = msg
|
188
|
+
end
|
188
189
|
|
189
|
-
|
190
|
+
attr_reader :value
|
190
191
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
192
|
+
def set(value, show: false)
|
193
|
+
@value = !!value
|
194
|
+
show && self.show
|
195
|
+
end
|
196
|
+
|
197
|
+
def toggle(show: true)
|
198
|
+
@value = !@value
|
199
|
+
show && self.show
|
200
|
+
end
|
195
201
|
|
196
|
-
|
197
|
-
@value = !@value
|
198
|
-
show && self.show
|
202
|
+
include CheckSwitch
|
199
203
|
end
|
200
204
|
|
201
|
-
|
202
|
-
|
205
|
+
class CombinedSwitch
|
206
|
+
def initialize(value:, msg:)
|
207
|
+
@value = value
|
208
|
+
@msg = msg
|
209
|
+
end
|
203
210
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
@msg = msg
|
208
|
-
end
|
211
|
+
def value
|
212
|
+
@value.()
|
213
|
+
end
|
209
214
|
|
210
|
-
|
211
|
-
@value.()
|
215
|
+
include CheckSwitch
|
212
216
|
end
|
213
217
|
|
214
|
-
|
215
|
-
|
218
|
+
def setup_switches
|
219
|
+
$markdown = Switch.new(
|
220
|
+
:markdown,
|
221
|
+
msg: {
|
222
|
+
true => "Using #{italic{'ANSI'}} markdown to output content.",
|
223
|
+
false => "Using plaintext for outputting content.",
|
224
|
+
}
|
225
|
+
)
|
216
226
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
)
|
227
|
+
$stream = Switch.new(
|
228
|
+
:stream,
|
229
|
+
msg: {
|
230
|
+
true => "Streaming enabled.",
|
231
|
+
false => "Streaming disabled.",
|
232
|
+
}
|
233
|
+
)
|
225
234
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
235
|
+
$voice = Switch.new(
|
236
|
+
:stream,
|
237
|
+
msg: {
|
238
|
+
true => "Voice output enabled.",
|
239
|
+
false => "Voice output disabled.",
|
240
|
+
},
|
241
|
+
config: $config.voice
|
242
|
+
)
|
233
243
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
)
|
244
|
+
$embedding_enabled = Switch.new(
|
245
|
+
:embedding_enabled,
|
246
|
+
msg: {
|
247
|
+
true => "Embedding enabled.",
|
248
|
+
false => "Embedding disabled.",
|
249
|
+
}
|
250
|
+
)
|
242
251
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
252
|
+
$embedding_paused = Switch.new(
|
253
|
+
:embedding_paused,
|
254
|
+
msg: {
|
255
|
+
true => "Embedding paused.",
|
256
|
+
false => "Embedding resumed.",
|
257
|
+
}
|
258
|
+
)
|
250
259
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
260
|
+
$embedding = CombinedSwitch.new(
|
261
|
+
value: -> { $embedding_enabled.on? && $embedding_paused.off? },
|
262
|
+
msg: {
|
263
|
+
true => "Embedding is currently performed.",
|
264
|
+
false => "Embedding is currently not performed.",
|
265
|
+
}
|
266
|
+
)
|
258
267
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
268
|
+
$location = Switch.new(
|
269
|
+
:location,
|
270
|
+
msg: {
|
271
|
+
true => "Location and localtime enabled.",
|
272
|
+
false => "Location and localtime disabled.",
|
273
|
+
},
|
274
|
+
config: $config.location.enabled
|
275
|
+
)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
include Switches
|
266
279
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
280
|
+
def pull_model_unless_present(model, options, retried = false)
|
281
|
+
ollama.show(name: model) { |response|
|
282
|
+
puts "Model #{bold{model}} with architecture "\
|
283
|
+
"#{response.model_info['general.architecture']} found."
|
284
|
+
if system = response.system
|
285
|
+
puts "Configured model system prompt is:\n#{italic { system }}"
|
286
|
+
return system
|
287
|
+
else
|
288
|
+
return
|
289
|
+
end
|
290
|
+
}
|
291
|
+
rescue Errors::NotFoundError
|
292
|
+
puts "Model #{bold{model}} not found locally, attempting to pull it from remote now…"
|
293
|
+
ollama.pull(name: model)
|
294
|
+
if retried
|
295
|
+
exit 1
|
296
|
+
else
|
297
|
+
retried = true
|
298
|
+
retry
|
299
|
+
end
|
300
|
+
rescue Errors::Error => e
|
301
|
+
warn "Caught #{e.class} while pulling model: #{e} => Exiting."
|
302
|
+
exit 1
|
275
303
|
end
|
276
304
|
|
277
305
|
def search_web(query, n = nil)
|
@@ -282,7 +310,7 @@ def search_web(query, n = nil)
|
|
282
310
|
n < 1 and n = 1
|
283
311
|
query = URI.encode_uri_component(query)
|
284
312
|
url = "https://www.duckduckgo.com/html/?q=#{query}"
|
285
|
-
|
313
|
+
Utils::Fetcher.get(url, debug: $config.debug) do |tmp|
|
286
314
|
result = []
|
287
315
|
doc = Nokogiri::HTML(tmp)
|
288
316
|
doc.css('.results_links').each do |link|
|
@@ -303,38 +331,13 @@ def search_web(query, n = nil)
|
|
303
331
|
end
|
304
332
|
end
|
305
333
|
|
306
|
-
def pull_model_unless_present(model, options, retried = false)
|
307
|
-
ollama.show(name: model) { |response|
|
308
|
-
puts "Model #{bold{model}} with architecture "\
|
309
|
-
"#{response.model_info['general.architecture']} found."
|
310
|
-
if system = response.system
|
311
|
-
puts "Configured model system prompt is:\n#{italic { system }}"
|
312
|
-
return system
|
313
|
-
else
|
314
|
-
return
|
315
|
-
end
|
316
|
-
}
|
317
|
-
rescue Errors::NotFoundError
|
318
|
-
puts "Model #{bold{model}} not found locally, attempting to pull it from remote now…"
|
319
|
-
ollama.pull(name: model)
|
320
|
-
if retried
|
321
|
-
exit 1
|
322
|
-
else
|
323
|
-
retried = true
|
324
|
-
retry
|
325
|
-
end
|
326
|
-
rescue Errors::Error => e
|
327
|
-
warn "Caught #{e.class} while pulling model: #{e} => Exiting."
|
328
|
-
exit 1
|
329
|
-
end
|
330
|
-
|
331
334
|
def load_conversation(filename)
|
332
335
|
unless File.exist?(filename)
|
333
336
|
puts "File #{filename} doesn't exist. Choose another filename."
|
334
337
|
return
|
335
338
|
end
|
336
339
|
File.open(filename, 'r') do |output|
|
337
|
-
return JSON(output.read).map {
|
340
|
+
return JSON(output.read).map { Message.from_hash(_1) }
|
338
341
|
end
|
339
342
|
end
|
340
343
|
|
@@ -504,7 +507,7 @@ def fetch_source(source, &block)
|
|
504
507
|
source,
|
505
508
|
cache: $cache,
|
506
509
|
debug: $config.debug,
|
507
|
-
http_options: http_options(source)
|
510
|
+
http_options: http_options(Utils::Fetcher.normalize_url(source))
|
508
511
|
) do |tmp|
|
509
512
|
block.(tmp)
|
510
513
|
end
|
@@ -518,7 +521,7 @@ def fetch_source(source, &block)
|
|
518
521
|
raise "invalid source"
|
519
522
|
end
|
520
523
|
rescue => e
|
521
|
-
STDERR.puts "Cannot fetch source #{source.to_s.inspect}: #{e}\n#{e.backtrace * ?\n}"
|
524
|
+
STDERR.puts "Cannot fetch source #{source.to_s.inspect}: #{e.class} #{e}\n#{e.backtrace * ?\n}"
|
522
525
|
end
|
523
526
|
|
524
527
|
def add_image(images, source_io, source)
|
@@ -530,7 +533,8 @@ end
|
|
530
533
|
def import_source(source_io, source)
|
531
534
|
source = source.to_s
|
532
535
|
puts "Importing #{italic { source_io&.content_type }} document #{source.inspect} now."
|
533
|
-
|
536
|
+
source_content = parse_source(source_io)
|
537
|
+
"Imported #{source.inspect}:\n#{source_content}\n\n"
|
534
538
|
end
|
535
539
|
|
536
540
|
def import(source)
|
@@ -572,17 +576,17 @@ def embed_source(source_io, source, count: nil)
|
|
572
576
|
inputs = nil
|
573
577
|
case splitter_config.name
|
574
578
|
when 'Character'
|
575
|
-
splitter =
|
579
|
+
splitter = Documents::Splitters::Character.new(
|
576
580
|
chunk_size: splitter_config.chunk_size,
|
577
581
|
)
|
578
582
|
inputs = splitter.split(text)
|
579
583
|
when 'RecursiveCharacter'
|
580
|
-
splitter =
|
584
|
+
splitter = Documents::Splitters::RecursiveCharacter.new(
|
581
585
|
chunk_size: splitter_config.chunk_size,
|
582
586
|
)
|
583
587
|
inputs = splitter.split(text)
|
584
588
|
when 'Semantic'
|
585
|
-
splitter =
|
589
|
+
splitter = Documents::Splitters::Semantic.new(
|
586
590
|
ollama:, model: $config.embedding.model.name,
|
587
591
|
chunk_size: splitter_config.chunk_size,
|
588
592
|
)
|
@@ -597,7 +601,7 @@ def embed_source(source_io, source, count: nil)
|
|
597
601
|
inputs or return
|
598
602
|
source = source.to_s
|
599
603
|
if source.start_with?(?!)
|
600
|
-
source =
|
604
|
+
source = Utils::Width.truncate(
|
601
605
|
source[1..-1].gsub(/\W+/, ?_),
|
602
606
|
length: 10
|
603
607
|
)
|
@@ -662,7 +666,7 @@ end
|
|
662
666
|
def choose_model(cli_model, current_model)
|
663
667
|
models = ollama.tags.models.map(&:name).sort
|
664
668
|
model = if cli_model == ''
|
665
|
-
|
669
|
+
Utils::Chooser.choose(models) || current_model
|
666
670
|
else
|
667
671
|
cli_model || current_model
|
668
672
|
end
|
@@ -679,7 +683,7 @@ def choose_collection(current_collection)
|
|
679
683
|
collections = [ current_collection ] + $documents.collections
|
680
684
|
collections = collections.compact.map(&:to_s).uniq.sort
|
681
685
|
collections.unshift('[EXIT]').unshift('[NEW]')
|
682
|
-
collection =
|
686
|
+
collection = Utils::Chooser.choose(collections) || current_collection
|
683
687
|
case collection
|
684
688
|
when '[NEW]'
|
685
689
|
$documents.collection = ask?(prompt: "Enter name of the new collection: ")
|
@@ -703,7 +707,7 @@ def choose_document_policy
|
|
703
707
|
policies.first
|
704
708
|
end
|
705
709
|
policies.unshift('[EXIT]')
|
706
|
-
policy =
|
710
|
+
policy = Utils::Chooser.choose(policies)
|
707
711
|
case policy
|
708
712
|
when nil, '[EXIT]'
|
709
713
|
puts "Exiting chooser."
|
@@ -733,19 +737,19 @@ end
|
|
733
737
|
|
734
738
|
def configure_cache
|
735
739
|
if $opts[?M]
|
736
|
-
|
740
|
+
Documents::MemoryCache
|
737
741
|
else
|
738
742
|
Object.const_get($config.cache)
|
739
743
|
end
|
740
744
|
rescue => e
|
741
745
|
STDERR.puts "Caught #{e.class}: #{e} => Falling back to MemoryCache."
|
742
|
-
|
746
|
+
Documents::MemoryCache
|
743
747
|
end
|
744
748
|
|
745
749
|
def show_system_prompt
|
746
750
|
puts <<~EOT
|
747
751
|
Configured system prompt is:
|
748
|
-
#{
|
752
|
+
#{Utils::ANSIMarkdown.parse($system.to_s).gsub(/\n+\z/, '').full? || 'n/a'}
|
749
753
|
EOT
|
750
754
|
end
|
751
755
|
|
@@ -769,7 +773,7 @@ end
|
|
769
773
|
|
770
774
|
def change_system_prompt(messages, default)
|
771
775
|
prompts = $config.system_prompts.attribute_names.compact
|
772
|
-
chosen =
|
776
|
+
chosen = Utils::Chooser.choose(prompts)
|
773
777
|
system = if chosen
|
774
778
|
$config.system_prompts.send(chosen)
|
775
779
|
else
|
@@ -779,7 +783,7 @@ def change_system_prompt(messages, default)
|
|
779
783
|
end
|
780
784
|
|
781
785
|
def change_voice
|
782
|
-
chosen =
|
786
|
+
chosen = Utils::Chooser.choose($config.voice.list)
|
783
787
|
$current_voice = chosen.full? || $config.voice.default
|
784
788
|
end
|
785
789
|
|
@@ -872,7 +876,7 @@ def usage
|
|
872
876
|
end
|
873
877
|
|
874
878
|
def version
|
875
|
-
puts "%s %s" % [ File.basename($0),
|
879
|
+
puts "%s %s" % [ File.basename($0), VERSION ]
|
876
880
|
exit 0
|
877
881
|
end
|
878
882
|
|
@@ -907,7 +911,7 @@ else
|
|
907
911
|
if $opts[?s] == ??
|
908
912
|
change_system_prompt(messages, default)
|
909
913
|
else
|
910
|
-
system =
|
914
|
+
system = Utils::FileArgument.get_file_argument($opts[?s], default:)
|
911
915
|
system.present? and set_system_prompt(messages, system)
|
912
916
|
end
|
913
917
|
end
|
@@ -957,7 +961,7 @@ else
|
|
957
961
|
end
|
958
962
|
|
959
963
|
if redis_expiring_url = $config.redis.expiring.url?
|
960
|
-
$cache =
|
964
|
+
$cache = Documents::RedisCache.new(
|
961
965
|
prefix: 'Expiring-',
|
962
966
|
url: redis_expiring_url,
|
963
967
|
ex: $config.redis.expiring.ex,
|
@@ -1051,7 +1055,7 @@ loop do
|
|
1051
1055
|
when 'clear'
|
1052
1056
|
loop do
|
1053
1057
|
tags = $documents.tags.add('[EXIT]').add('[ALL]')
|
1054
|
-
tag =
|
1058
|
+
tag = Utils::Chooser.choose(tags, prompt: 'Clear? %s')
|
1055
1059
|
case tag
|
1056
1060
|
when nil, '[EXIT]'
|
1057
1061
|
puts "Exiting chooser."
|
data/lib/ollama/utils/fetcher.rb
CHANGED
@@ -38,6 +38,13 @@ class Ollama::Utils::Fetcher
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
def self.normalize_url(url)
|
42
|
+
url = url.to_s
|
43
|
+
url = URI.decode_uri_component(url)
|
44
|
+
url = url.sub(/#.*/, '')
|
45
|
+
URI::Parser.new.escape(url).to_s
|
46
|
+
end
|
47
|
+
|
41
48
|
def self.read(filename, &block)
|
42
49
|
if File.exist?(filename)
|
43
50
|
File.open(filename) do |file|
|
@@ -80,6 +87,7 @@ class Ollama::Utils::Fetcher
|
|
80
87
|
private
|
81
88
|
|
82
89
|
def excon(url, **options)
|
90
|
+
url = self.class.normalize_url(url)
|
83
91
|
Excon.new(url, options.merge(@http_options))
|
84
92
|
end
|
85
93
|
|
data/lib/ollama/version.rb
CHANGED
data/ollama-ruby.gemspec
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: ollama-ruby 0.9.
|
2
|
+
# stub: ollama-ruby 0.9.1 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "ollama-ruby".freeze
|
6
|
-
s.version = "0.9.
|
6
|
+
s.version = "0.9.1".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]
|
10
10
|
s.authors = ["Florian Frank".freeze]
|
11
|
-
s.date = "2024-10-
|
11
|
+
s.date = "2024-10-19"
|
12
12
|
s.description = "Library that allows interacting with the Ollama API".freeze
|
13
13
|
s.email = "flori@ping.de".freeze
|
14
14
|
s.executables = ["ollama_console".freeze, "ollama_chat".freeze, "ollama_update".freeze, "ollama_cli".freeze]
|
@@ -19,7 +19,7 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'can #get with streaming' do
|
22
|
-
stub_request(:get,
|
22
|
+
stub_request(:get, url).
|
23
23
|
with(headers: fetcher.headers).
|
24
24
|
to_return(
|
25
25
|
status: 200,
|
@@ -37,7 +37,7 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
37
37
|
fetcher = described_class.new(
|
38
38
|
http_options: { ssl_verify_peer: false }
|
39
39
|
).expose
|
40
|
-
stub_request(:get,
|
40
|
+
stub_request(:get, url).
|
41
41
|
with(headers: fetcher.headers).
|
42
42
|
to_return(
|
43
43
|
status: 200,
|
@@ -45,7 +45,7 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
45
45
|
headers: { 'Content-Type' => 'text/plain' },
|
46
46
|
)
|
47
47
|
expect(Excon).to receive(:new).with(
|
48
|
-
|
48
|
+
url,
|
49
49
|
hash_including(ssl_verify_peer: false)
|
50
50
|
).and_call_original
|
51
51
|
fetcher.get(url) do |tmp|
|
@@ -56,7 +56,7 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
56
56
|
end
|
57
57
|
|
58
58
|
it 'can #get and fallback from streaming' do
|
59
|
-
stub_request(:get,
|
59
|
+
stub_request(:get, url).
|
60
60
|
with(headers: fetcher.headers).
|
61
61
|
to_return(
|
62
62
|
{ status: 501 },
|
@@ -74,9 +74,10 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
74
74
|
end
|
75
75
|
|
76
76
|
it 'can #get and finally fail' do
|
77
|
-
stub_request(:get,
|
77
|
+
stub_request(:get, url).
|
78
78
|
with(headers: fetcher.headers).
|
79
79
|
to_return(status: 500)
|
80
|
+
expect(STDERR).to receive(:puts).with(/cannot.*get.*#{url}/i)
|
80
81
|
fetcher.get(url) do |tmp|
|
81
82
|
expect(tmp).to be_a StringIO
|
82
83
|
expect(tmp.read).to eq ''
|
@@ -106,10 +107,31 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
106
107
|
|
107
108
|
it 'can .execute and fail' do
|
108
109
|
expect(IO).to receive(:popen).and_raise StandardError
|
110
|
+
expect(STDERR).to receive(:puts).with(/cannot.*execute.*foobar/i)
|
109
111
|
described_class.execute('foobar') do |file|
|
110
112
|
expect(file).to be_a StringIO
|
111
113
|
expect(file.read).to be_empty
|
112
114
|
expect(file.content_type).to eq 'text/plain'
|
113
115
|
end
|
114
116
|
end
|
117
|
+
|
118
|
+
describe '.normalize_url' do
|
119
|
+
it 'can handle umlauts' do
|
120
|
+
expect(described_class.normalize_url('https://foo.de/bär')).to eq(
|
121
|
+
'https://foo.de/b%C3%A4r'
|
122
|
+
)
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'can handle escaped umlauts' do
|
126
|
+
expect(described_class.normalize_url('https://foo.de/b%C3%A4r')).to eq(
|
127
|
+
'https://foo.de/b%C3%A4r'
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'can remove #anchors' do
|
132
|
+
expect(described_class.normalize_url('https://foo.de#bar')).to eq(
|
133
|
+
'https://foo.de'
|
134
|
+
)
|
135
|
+
end
|
136
|
+
end
|
115
137
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ollama-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Frank
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-10-
|
11
|
+
date: 2024-10-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gem_hadar
|