ollama-ruby 0.9.3 → 0.11.0
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 +43 -0
- data/Rakefile +4 -4
- data/bin/ollama_chat +47 -38
- data/lib/ollama/documents/cache/common.rb +16 -1
- data/lib/ollama/documents.rb +7 -10
- data/lib/ollama/handlers/markdown.rb +2 -1
- data/lib/ollama/handlers/say.rb +42 -3
- data/lib/ollama/utils/colorize_texts.rb +4 -1
- data/lib/ollama/version.rb +1 -1
- data/lib/ollama.rb +0 -2
- data/ollama-ruby.gemspec +9 -9
- data/spec/ollama/handlers/say_spec.rb +73 -10
- data/spec/ollama/utils/fetcher_spec.rb +24 -24
- metadata +38 -40
- data/lib/ollama/utils/ansi_markdown.rb +0 -217
- data/lib/ollama/utils/width.rb +0 -39
- data/spec/ollama/utils/ansi_markdown_spec.rb +0 -15
- data/spec/ollama/utils/width_spec.rb +0 -82
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6611c14b779a919b256552774080305825b4e81cd5e43ae0303026aaaed7c13e
|
4
|
+
data.tar.gz: a34e71ef5b07cdd8a0cdf5dce9de7f7e9c3faca1829e4837c54ea243458b8f05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa38db4bdd42ebffe2ef9b5abf7f644e38821acc4fb9650b7e8646a9fab3350640224c4ba59e13d7f182becd2a84ac881fd0c5d136ca88782e1a7febec31c2fe
|
7
|
+
data.tar.gz: b14f2626d9f2c8e6e8bc6c3b3d8947d78b4400cf0dd8888cf9f818261ba3605fc9971c2c9015f976ec48f2004cb4b0ff5d922e2efe001b5b443f03728f14ce51
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,48 @@
|
|
1
1
|
# Changes
|
2
2
|
|
3
|
+
## 2024-11-20 v0.11.0
|
4
|
+
|
5
|
+
* Added `voice` and `interactive` reader attributes to the Say handler class.
|
6
|
+
* Refactored the `call` method in the Say handler to reopen the output stream
|
7
|
+
if it has been closed.
|
8
|
+
* Added the `open_output` method to open a new IO stream with synchronization
|
9
|
+
enabled.
|
10
|
+
* Added a test for the reopened output stream in the Say spec.
|
11
|
+
* Updated `initialize` method in `lib/ollama/handlers/say.rb` to add
|
12
|
+
`interactive` option and call new `command` method.
|
13
|
+
* Add private `command` method in lib/ollama/handlers/say.rb to generate
|
14
|
+
command for say utility based on voice and interactive options.
|
15
|
+
* Update specs in `spec/ollama/handlers/say_spec.rb` to test new behavior.
|
16
|
+
* Updated `FollowChat` class to correctly initialize markdown and voice
|
17
|
+
attributes
|
18
|
+
* Update `choose_document_policy` policy list in chat script to include
|
19
|
+
'ignoring'
|
20
|
+
* Updated `parse_content` method to handle 'ignoring' document policy.
|
21
|
+
|
22
|
+
## 2024-10-31 v0.10.0
|
23
|
+
|
24
|
+
* Improved URL and tag parsing in `parse_content`:
|
25
|
+
+ Added support for `file://` protocol to content scans.
|
26
|
+
+ Updated regex pattern to match local files starting with `~`, `.`, or `/`.
|
27
|
+
+ Remove # anchors for file URLs (and files)
|
28
|
+
* Improved parsing of content in ollama_chat:
|
29
|
+
+ Use `content.scan(%r((https?://\S+)|(#\S+)|(\S+\/\S+)))` to match URLs, tags and files.
|
30
|
+
+ For foo/bar file pathes prepend `./`foo/bar, for foo you have to enter ./foo still.
|
31
|
+
+ Added a check for file existence before fetching its content
|
32
|
+
* Move vector methods into cache implementations:
|
33
|
+
+ Update `documents.rb` to use `@cache.norm` and `@cache.cosine_similarity`
|
34
|
+
+ Remove unused code in `documents.rb` (including `Ollama::Utils::Math`)
|
35
|
+
+ Add `include Ollama::Utils::Math` in `cache/common.rb`
|
36
|
+
* Document existing collections, pre, and unpre methods:
|
37
|
+
+ Update module Ollama::Documents::Cache::Common to include documentation for existing methods
|
38
|
+
* Use kramdown-ansi gem for Markdown output in terminal:
|
39
|
+
+ Update `kramdown-ansi` to **0.0** in Gemfile and Rakefile
|
40
|
+
+ Remove `ollama/utils/width.rb` as it's no longer needed
|
41
|
+
+ Remove `spec/ollama/utils/width_spec.rb` and `spec/ollama/utils/ansi_markdown_spec.rb` as they're not used anymore
|
42
|
+
+ Update `ollama-ruby.gemspec` to reflect the new dependencies and remove unused files
|
43
|
+
* Updated print messages to include `.to_s.inspect` for accurate inspection of
|
44
|
+
source content in `ollama_chat`.
|
45
|
+
|
3
46
|
## 2024-10-21 v0.9.3
|
4
47
|
|
5
48
|
* Update dependencies and date:
|
data/Rakefile
CHANGED
@@ -14,7 +14,7 @@ GemHadar do
|
|
14
14
|
test_dir 'spec'
|
15
15
|
ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', '.AppleDouble', '.bundle',
|
16
16
|
'.yardoc', 'doc', 'tags', 'errors.lst', 'cscope.out', 'coverage', 'tmp',
|
17
|
-
'corpus'
|
17
|
+
'corpus', 'yard'
|
18
18
|
package_ignore '.all_images.yml', '.tool-versions', '.gitignore', 'VERSION',
|
19
19
|
'.rspec', *Dir.glob('.github/**/*', File::FNM_DOTMATCH)
|
20
20
|
readme 'README.md'
|
@@ -24,11 +24,9 @@ GemHadar do
|
|
24
24
|
|
25
25
|
required_ruby_version '~> 3.1'
|
26
26
|
|
27
|
-
dependency 'excon', '~> 0
|
27
|
+
dependency 'excon', '~> 1.0'
|
28
28
|
dependency 'infobar', '~> 0.8'
|
29
29
|
dependency 'term-ansicolor', '~> 1.11'
|
30
|
-
dependency 'kramdown-parser-gfm', '~> 1.1'
|
31
|
-
dependency 'terminal-table', '~> 3.0'
|
32
30
|
dependency 'redis', '~> 5.0'
|
33
31
|
dependency 'numo-narray', '~> 0.9'
|
34
32
|
dependency 'more_math', '~> 1.1'
|
@@ -42,6 +40,8 @@ GemHadar do
|
|
42
40
|
dependency 'json', '~> 2.0'
|
43
41
|
dependency 'xdg', '~> 7.0'
|
44
42
|
dependency 'tins', '~> 1.34'
|
43
|
+
dependency 'kramdown-ansi', '~> 0.0', '>= 0.0.1'
|
44
|
+
dependency 'ostruct', '~> 0.0'
|
45
45
|
development_dependency 'all_images', '~> 0.4'
|
46
46
|
development_dependency 'rspec', '~> 3.2'
|
47
47
|
development_dependency 'webmock'
|
data/bin/ollama_chat
CHANGED
@@ -114,10 +114,10 @@ class FollowChat
|
|
114
114
|
def initialize(messages:, markdown: false, voice: nil, output: $stdout)
|
115
115
|
super(output:)
|
116
116
|
@output.sync = true
|
117
|
-
@markdown
|
118
|
-
@say
|
119
|
-
@messages
|
120
|
-
@user
|
117
|
+
@markdown = markdown
|
118
|
+
@say = voice ? Handlers::Say.new(voice:) : NOP
|
119
|
+
@messages = messages
|
120
|
+
@user = nil
|
121
121
|
end
|
122
122
|
|
123
123
|
def call(response)
|
@@ -132,7 +132,7 @@ class FollowChat
|
|
132
132
|
content = response.message&.content
|
133
133
|
@messages.last.content << content
|
134
134
|
if @markdown and content = @messages.last.content.full?
|
135
|
-
markdown_content =
|
135
|
+
markdown_content = Kramdown::ANSI.parse(content)
|
136
136
|
@output.print clear_screen, move_home, @user, ?\n, markdown_content
|
137
137
|
else
|
138
138
|
@output.print content
|
@@ -159,7 +159,7 @@ class FollowChat
|
|
159
159
|
load_duration: Tins::Duration.new(response.load_duration / 1e9),
|
160
160
|
}.map { _1 * '=' } * ' '
|
161
161
|
'📊 ' + color(111) {
|
162
|
-
|
162
|
+
Kramdown::ANSI::Width.wrap(stats_text, percentage: 90).gsub(/(?<!\A)^/, ' ')
|
163
163
|
}
|
164
164
|
end
|
165
165
|
end
|
@@ -364,7 +364,7 @@ def list_conversation(messages, last = nil)
|
|
364
364
|
when 'system' then 213
|
365
365
|
else 210
|
366
366
|
end
|
367
|
-
content = m.content.full? { $markdown.on? ?
|
367
|
+
content = m.content.full? { $markdown.on? ? Kramdown::ANSI.parse(_1) : _1 }
|
368
368
|
message_text = message_type(m.images) + " "
|
369
369
|
message_text += bold { color(role_color) { m.role } }
|
370
370
|
message_text += ":\n#{content}"
|
@@ -539,8 +539,8 @@ end
|
|
539
539
|
|
540
540
|
def import_source(source_io, source)
|
541
541
|
source = source.to_s
|
542
|
-
puts "Importing #{italic { source_io&.content_type }} document #{source.inspect} now."
|
543
|
-
|
542
|
+
puts "Importing #{italic { source_io&.content_type }} document #{source.to_s.inspect} now."
|
543
|
+
source_content = parse_source(source_io)
|
544
544
|
"Imported #{source.inspect}:\n#{source_content}\n\n"
|
545
545
|
end
|
546
546
|
|
@@ -553,7 +553,7 @@ def import(source)
|
|
553
553
|
end
|
554
554
|
|
555
555
|
def summarize_source(source_io, source, words: nil)
|
556
|
-
puts "Summarizing #{italic { source_io&.content_type }} document #{source.inspect} now."
|
556
|
+
puts "Summarizing #{italic { source_io&.content_type }} document #{source.to_s.inspect} now."
|
557
557
|
words = words.to_i
|
558
558
|
words < 1 and words = 100
|
559
559
|
source_content = parse_source(source_io)
|
@@ -608,7 +608,7 @@ def embed_source(source_io, source, count: nil)
|
|
608
608
|
inputs or return
|
609
609
|
source = source.to_s
|
610
610
|
if source.start_with?(?!)
|
611
|
-
source =
|
611
|
+
source = Kramdown::ANSI::Width.truncate(
|
612
612
|
source[1..-1].gsub(/\W+/, ?_),
|
613
613
|
length: 10
|
614
614
|
)
|
@@ -638,31 +638,39 @@ def parse_content(content, images)
|
|
638
638
|
tags = Utils::Tags.new
|
639
639
|
|
640
640
|
contents = [ content ]
|
641
|
-
content.scan(%r((
|
642
|
-
case
|
643
|
-
when
|
644
|
-
tags.add(
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
641
|
+
content.scan(%r((https?://\S+)|(#\S+)|(?:file://)?(\S*\/\S+))).each do |url, tag, file|
|
642
|
+
case
|
643
|
+
when tag
|
644
|
+
tags.add(tag)
|
645
|
+
next
|
646
|
+
when file
|
647
|
+
file = file.sub(/#.*/, '')
|
648
|
+
file =~ %r(\A[~./]) or file.prepend('./')
|
649
|
+
File.exist?(file) or next
|
650
|
+
source = file
|
651
|
+
when url
|
652
|
+
source = url
|
653
|
+
end
|
654
|
+
fetch_source(source) do |source_io|
|
655
|
+
case source_io&.content_type&.media_type
|
656
|
+
when 'image'
|
657
|
+
add_image(images, source_io, source)
|
658
|
+
when 'text', 'application', nil
|
659
|
+
case $document_policy
|
660
|
+
when 'ignoring'
|
661
|
+
nil
|
662
|
+
when 'importing'
|
663
|
+
contents << import_source(source_io, source)
|
664
|
+
when 'embedding'
|
665
|
+
embed_source(source_io, source)
|
666
|
+
when 'summarizing'
|
667
|
+
contents << summarize_source(source_io, source)
|
665
668
|
end
|
669
|
+
else
|
670
|
+
STDERR.puts(
|
671
|
+
"Cannot fetch #{source.to_s.inspect} with content type "\
|
672
|
+
"#{source_io&.content_type.inspect}"
|
673
|
+
)
|
666
674
|
end
|
667
675
|
end
|
668
676
|
end
|
@@ -705,7 +713,7 @@ ensure
|
|
705
713
|
end
|
706
714
|
|
707
715
|
def choose_document_policy
|
708
|
-
policies = %w[ importing embedding summarizing ].sort
|
716
|
+
policies = %w[ importing embedding summarizing ignoring ].sort
|
709
717
|
current = if policies.index($document_policy)
|
710
718
|
$document_policy
|
711
719
|
elsif policies.index($config.document_policy)
|
@@ -755,7 +763,7 @@ end
|
|
755
763
|
def show_system_prompt
|
756
764
|
puts <<~EOT
|
757
765
|
Configured system prompt is:
|
758
|
-
#{
|
766
|
+
#{Kramdown::ANSI.parse($system.to_s).gsub(/\n+\z/, '').full? || 'n/a'}
|
759
767
|
EOT
|
760
768
|
end
|
761
769
|
|
@@ -1165,7 +1173,8 @@ loop do
|
|
1165
1173
|
end
|
1166
1174
|
|
1167
1175
|
if location = at_location.full?
|
1168
|
-
content += " [#{location} – do not comment on this
|
1176
|
+
content += " [#{location} – do not comment on this the time and location, "\
|
1177
|
+
"just consider it for eventual queries]"
|
1169
1178
|
end
|
1170
1179
|
|
1171
1180
|
messages << Message.new(role: 'user', content:, images: images.dup)
|
@@ -1,16 +1,31 @@
|
|
1
1
|
module Ollama::Documents::Cache::Common
|
2
|
-
|
2
|
+
include Ollama::Utils::Math
|
3
3
|
|
4
|
+
attr_writer :prefix # current prefix defined for the cache
|
5
|
+
|
6
|
+
# Returns an array of collection names that match the given prefix.
|
7
|
+
#
|
8
|
+
# @param prefix [String] a string to search for in collection names
|
9
|
+
# @return [Array<Symbol>] an array of matching collection names
|
4
10
|
def collections(prefix)
|
5
11
|
unique = Set.new
|
6
12
|
full_each { |key, _| unique << key[/\A#{prefix}(.*)-/, 1] }
|
7
13
|
unique.map(&:to_sym)
|
8
14
|
end
|
9
15
|
|
16
|
+
# Returns a string representing the given `key` prefixed with the defined
|
17
|
+
# prefix.
|
18
|
+
#
|
19
|
+
# @param key [String] the key to join with the prefix
|
20
|
+
# @return [String] the joined string of prefix and key
|
10
21
|
def pre(key)
|
11
22
|
[ @prefix, key ].join
|
12
23
|
end
|
13
24
|
|
25
|
+
# Returns a string with the prefix removed from the given `key`.
|
26
|
+
#
|
27
|
+
# @param key [String] the input string containing the prefix.
|
28
|
+
# @return [String] the input string without the prefix.
|
14
29
|
def unpre(key)
|
15
30
|
key.sub(/\A#@prefix/, '')
|
16
31
|
end
|
data/lib/ollama/documents.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'numo/narray'
|
2
2
|
require 'digest'
|
3
|
+
require 'kramdown/ansi'
|
3
4
|
|
4
5
|
class Ollama::Documents
|
5
6
|
end
|
@@ -14,8 +15,7 @@ require 'ollama/documents/splitters/character'
|
|
14
15
|
require 'ollama/documents/splitters/semantic'
|
15
16
|
|
16
17
|
class Ollama::Documents
|
17
|
-
include
|
18
|
-
include Ollama::Utils::Width
|
18
|
+
include Kramdown::ANSI::Width
|
19
19
|
|
20
20
|
class Record < JSON::GenericObject
|
21
21
|
def to_s
|
@@ -79,7 +79,7 @@ class Ollama::Documents
|
|
79
79
|
batches.each do |batch|
|
80
80
|
embeddings = fetch_embeddings(model:, options: @model_options, input: batch)
|
81
81
|
batch.zip(embeddings) do |text, embedding|
|
82
|
-
norm = norm(embedding)
|
82
|
+
norm = @cache.norm(embedding)
|
83
83
|
self[text] = Record[text:, embedding:, norm:, source:, tags: tags.to_a]
|
84
84
|
end
|
85
85
|
infobar.progress by: batch.size
|
@@ -125,7 +125,7 @@ class Ollama::Documents
|
|
125
125
|
|
126
126
|
def find(string, tags: nil, prompt: nil)
|
127
127
|
needle = convert_to_vector(string, prompt:)
|
128
|
-
needle_norm = norm(needle)
|
128
|
+
needle_norm = @cache.norm(needle)
|
129
129
|
records = @cache
|
130
130
|
if tags
|
131
131
|
tags = Ollama::Utils::Tags.new(tags).to_a
|
@@ -133,7 +133,7 @@ class Ollama::Documents
|
|
133
133
|
end
|
134
134
|
records = records.sort_by { |key, record|
|
135
135
|
record.key = key
|
136
|
-
record.similarity = cosine_similarity(
|
136
|
+
record.similarity = @cache.cosine_similarity(
|
137
137
|
a: needle,
|
138
138
|
b: record.embedding,
|
139
139
|
a_norm: needle_norm,
|
@@ -193,11 +193,8 @@ class Ollama::Documents
|
|
193
193
|
if prompt
|
194
194
|
input = prompt % input
|
195
195
|
end
|
196
|
-
|
197
|
-
|
198
|
-
else
|
199
|
-
super(input)
|
200
|
-
end
|
196
|
+
input.is_a?(String) and input = fetch_embeddings(model:, input:).first
|
197
|
+
@cache.convert_to_vector(input)
|
201
198
|
end
|
202
199
|
|
203
200
|
def fetch_embeddings(model:, input:, options: nil)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'term/ansicolor'
|
2
|
+
require 'kramdown/ansi'
|
2
3
|
|
3
4
|
class Ollama::Handlers::Markdown
|
4
5
|
include Ollama::Handlers::Concern
|
@@ -13,7 +14,7 @@ class Ollama::Handlers::Markdown
|
|
13
14
|
def call(response)
|
14
15
|
if content = response.response || response.message&.content
|
15
16
|
@content << content
|
16
|
-
markdown_content =
|
17
|
+
markdown_content = Kramdown::ANSI.parse(@content)
|
17
18
|
@output.print clear_screen, move_home, markdown_content
|
18
19
|
end
|
19
20
|
self
|
data/lib/ollama/handlers/say.rb
CHANGED
@@ -3,17 +3,56 @@ require 'shellwords'
|
|
3
3
|
class Ollama::Handlers::Say
|
4
4
|
include Ollama::Handlers::Concern
|
5
5
|
|
6
|
-
def initialize(output: nil, voice: 'Samantha')
|
7
|
-
|
6
|
+
def initialize(output: nil, voice: 'Samantha', interactive: nil)
|
7
|
+
@voice = voice
|
8
|
+
@interactive = interactive
|
8
9
|
super(output:)
|
9
|
-
|
10
|
+
unless output
|
11
|
+
@output = open_output
|
12
|
+
@output_pid = @output.pid
|
13
|
+
end
|
10
14
|
end
|
11
15
|
|
16
|
+
attr_reader :voice
|
17
|
+
|
18
|
+
attr_reader :interactive
|
19
|
+
|
12
20
|
def call(response)
|
21
|
+
if @output.closed?
|
22
|
+
wait_output_pid
|
23
|
+
@output = open_output
|
24
|
+
@output_pid = @output.pid
|
25
|
+
end
|
13
26
|
if content = response.response || response.message&.content
|
14
27
|
@output.print content
|
15
28
|
end
|
16
29
|
response.done and @output.close
|
17
30
|
self
|
18
31
|
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def open_output
|
36
|
+
io = IO.popen(Shellwords.join(command(voice:, interactive:)), 'w')
|
37
|
+
io.sync = true
|
38
|
+
io
|
39
|
+
end
|
40
|
+
|
41
|
+
def wait_output_pid
|
42
|
+
@output_pid or return
|
43
|
+
Process.wait(@output_pid, Process::WNOHANG | Process::WUNTRACED)
|
44
|
+
rescue Errno::ECHILD
|
45
|
+
end
|
46
|
+
|
47
|
+
def command(voice:, interactive:)
|
48
|
+
command = [ 'say' ]
|
49
|
+
voice and command.concat([ '-v', voice ])
|
50
|
+
case interactive
|
51
|
+
when true
|
52
|
+
command << '-i'
|
53
|
+
when String
|
54
|
+
command << '--interactive=%s' % interactive
|
55
|
+
end
|
56
|
+
command
|
57
|
+
end
|
19
58
|
end
|
@@ -1,7 +1,10 @@
|
|
1
|
+
require 'term/ansicolor'
|
2
|
+
require 'kramdown/ansi'
|
3
|
+
|
1
4
|
class Ollama::Utils::ColorizeTexts
|
2
5
|
include Math
|
3
6
|
include Term::ANSIColor
|
4
|
-
include
|
7
|
+
include Kramdown::ANSI::Width
|
5
8
|
|
6
9
|
# Initializes a new instance of Ollama::Utils::ColorizeTexts
|
7
10
|
#
|
data/lib/ollama/version.rb
CHANGED
data/lib/ollama.rb
CHANGED
data/ollama-ruby.gemspec
CHANGED
@@ -1,26 +1,26 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: ollama-ruby 0.
|
2
|
+
# stub: ollama-ruby 0.11.0 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "ollama-ruby".freeze
|
6
|
-
s.version = "0.
|
6
|
+
s.version = "0.11.0".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-
|
11
|
+
s.date = "2024-11-20"
|
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]
|
15
|
-
s.extra_rdoc_files = ["README.md".freeze, "lib/ollama.rb".freeze, "lib/ollama/client.rb".freeze, "lib/ollama/client/command.rb".freeze, "lib/ollama/client/doc.rb".freeze, "lib/ollama/commands/chat.rb".freeze, "lib/ollama/commands/copy.rb".freeze, "lib/ollama/commands/create.rb".freeze, "lib/ollama/commands/delete.rb".freeze, "lib/ollama/commands/embed.rb".freeze, "lib/ollama/commands/embeddings.rb".freeze, "lib/ollama/commands/generate.rb".freeze, "lib/ollama/commands/ps.rb".freeze, "lib/ollama/commands/pull.rb".freeze, "lib/ollama/commands/push.rb".freeze, "lib/ollama/commands/show.rb".freeze, "lib/ollama/commands/tags.rb".freeze, "lib/ollama/documents.rb".freeze, "lib/ollama/documents/cache/common.rb".freeze, "lib/ollama/documents/cache/memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_backed_memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_cache.rb".freeze, "lib/ollama/documents/splitters/character.rb".freeze, "lib/ollama/documents/splitters/semantic.rb".freeze, "lib/ollama/dto.rb".freeze, "lib/ollama/errors.rb".freeze, "lib/ollama/handlers.rb".freeze, "lib/ollama/handlers/collector.rb".freeze, "lib/ollama/handlers/concern.rb".freeze, "lib/ollama/handlers/dump_json.rb".freeze, "lib/ollama/handlers/dump_yaml.rb".freeze, "lib/ollama/handlers/markdown.rb".freeze, "lib/ollama/handlers/nop.rb".freeze, "lib/ollama/handlers/print.rb".freeze, "lib/ollama/handlers/progress.rb".freeze, "lib/ollama/handlers/say.rb".freeze, "lib/ollama/handlers/single.rb".freeze, "lib/ollama/image.rb".freeze, "lib/ollama/message.rb".freeze, "lib/ollama/options.rb".freeze, "lib/ollama/response.rb".freeze, "lib/ollama/tool.rb".freeze, "lib/ollama/tool/function.rb".freeze, "lib/ollama/tool/function/parameters.rb".freeze, "lib/ollama/tool/function/parameters/property.rb".freeze, "lib/ollama/utils/
|
16
|
-
s.files = [".envrc".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_cli".freeze, "bin/ollama_console".freeze, "bin/ollama_update".freeze, "config/redis.conf".freeze, "docker-compose.yml".freeze, "lib/ollama.rb".freeze, "lib/ollama/client.rb".freeze, "lib/ollama/client/command.rb".freeze, "lib/ollama/client/doc.rb".freeze, "lib/ollama/commands/chat.rb".freeze, "lib/ollama/commands/copy.rb".freeze, "lib/ollama/commands/create.rb".freeze, "lib/ollama/commands/delete.rb".freeze, "lib/ollama/commands/embed.rb".freeze, "lib/ollama/commands/embeddings.rb".freeze, "lib/ollama/commands/generate.rb".freeze, "lib/ollama/commands/ps.rb".freeze, "lib/ollama/commands/pull.rb".freeze, "lib/ollama/commands/push.rb".freeze, "lib/ollama/commands/show.rb".freeze, "lib/ollama/commands/tags.rb".freeze, "lib/ollama/documents.rb".freeze, "lib/ollama/documents/cache/common.rb".freeze, "lib/ollama/documents/cache/memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_backed_memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_cache.rb".freeze, "lib/ollama/documents/splitters/character.rb".freeze, "lib/ollama/documents/splitters/semantic.rb".freeze, "lib/ollama/dto.rb".freeze, "lib/ollama/errors.rb".freeze, "lib/ollama/handlers.rb".freeze, "lib/ollama/handlers/collector.rb".freeze, "lib/ollama/handlers/concern.rb".freeze, "lib/ollama/handlers/dump_json.rb".freeze, "lib/ollama/handlers/dump_yaml.rb".freeze, "lib/ollama/handlers/markdown.rb".freeze, "lib/ollama/handlers/nop.rb".freeze, "lib/ollama/handlers/print.rb".freeze, "lib/ollama/handlers/progress.rb".freeze, "lib/ollama/handlers/say.rb".freeze, "lib/ollama/handlers/single.rb".freeze, "lib/ollama/image.rb".freeze, "lib/ollama/message.rb".freeze, "lib/ollama/options.rb".freeze, "lib/ollama/response.rb".freeze, "lib/ollama/tool.rb".freeze, "lib/ollama/tool/function.rb".freeze, "lib/ollama/tool/function/parameters.rb".freeze, "lib/ollama/tool/function/parameters/property.rb".freeze, "lib/ollama/utils/
|
15
|
+
s.extra_rdoc_files = ["README.md".freeze, "lib/ollama.rb".freeze, "lib/ollama/client.rb".freeze, "lib/ollama/client/command.rb".freeze, "lib/ollama/client/doc.rb".freeze, "lib/ollama/commands/chat.rb".freeze, "lib/ollama/commands/copy.rb".freeze, "lib/ollama/commands/create.rb".freeze, "lib/ollama/commands/delete.rb".freeze, "lib/ollama/commands/embed.rb".freeze, "lib/ollama/commands/embeddings.rb".freeze, "lib/ollama/commands/generate.rb".freeze, "lib/ollama/commands/ps.rb".freeze, "lib/ollama/commands/pull.rb".freeze, "lib/ollama/commands/push.rb".freeze, "lib/ollama/commands/show.rb".freeze, "lib/ollama/commands/tags.rb".freeze, "lib/ollama/documents.rb".freeze, "lib/ollama/documents/cache/common.rb".freeze, "lib/ollama/documents/cache/memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_backed_memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_cache.rb".freeze, "lib/ollama/documents/splitters/character.rb".freeze, "lib/ollama/documents/splitters/semantic.rb".freeze, "lib/ollama/dto.rb".freeze, "lib/ollama/errors.rb".freeze, "lib/ollama/handlers.rb".freeze, "lib/ollama/handlers/collector.rb".freeze, "lib/ollama/handlers/concern.rb".freeze, "lib/ollama/handlers/dump_json.rb".freeze, "lib/ollama/handlers/dump_yaml.rb".freeze, "lib/ollama/handlers/markdown.rb".freeze, "lib/ollama/handlers/nop.rb".freeze, "lib/ollama/handlers/print.rb".freeze, "lib/ollama/handlers/progress.rb".freeze, "lib/ollama/handlers/say.rb".freeze, "lib/ollama/handlers/single.rb".freeze, "lib/ollama/image.rb".freeze, "lib/ollama/message.rb".freeze, "lib/ollama/options.rb".freeze, "lib/ollama/response.rb".freeze, "lib/ollama/tool.rb".freeze, "lib/ollama/tool/function.rb".freeze, "lib/ollama/tool/function/parameters.rb".freeze, "lib/ollama/tool/function/parameters/property.rb".freeze, "lib/ollama/utils/cache_fetcher.rb".freeze, "lib/ollama/utils/chooser.rb".freeze, "lib/ollama/utils/colorize_texts.rb".freeze, "lib/ollama/utils/fetcher.rb".freeze, "lib/ollama/utils/file_argument.rb".freeze, "lib/ollama/utils/math.rb".freeze, "lib/ollama/utils/tags.rb".freeze, "lib/ollama/version.rb".freeze]
|
16
|
+
s.files = [".envrc".freeze, "CHANGES.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/ollama_chat".freeze, "bin/ollama_cli".freeze, "bin/ollama_console".freeze, "bin/ollama_update".freeze, "config/redis.conf".freeze, "docker-compose.yml".freeze, "lib/ollama.rb".freeze, "lib/ollama/client.rb".freeze, "lib/ollama/client/command.rb".freeze, "lib/ollama/client/doc.rb".freeze, "lib/ollama/commands/chat.rb".freeze, "lib/ollama/commands/copy.rb".freeze, "lib/ollama/commands/create.rb".freeze, "lib/ollama/commands/delete.rb".freeze, "lib/ollama/commands/embed.rb".freeze, "lib/ollama/commands/embeddings.rb".freeze, "lib/ollama/commands/generate.rb".freeze, "lib/ollama/commands/ps.rb".freeze, "lib/ollama/commands/pull.rb".freeze, "lib/ollama/commands/push.rb".freeze, "lib/ollama/commands/show.rb".freeze, "lib/ollama/commands/tags.rb".freeze, "lib/ollama/documents.rb".freeze, "lib/ollama/documents/cache/common.rb".freeze, "lib/ollama/documents/cache/memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_backed_memory_cache.rb".freeze, "lib/ollama/documents/cache/redis_cache.rb".freeze, "lib/ollama/documents/splitters/character.rb".freeze, "lib/ollama/documents/splitters/semantic.rb".freeze, "lib/ollama/dto.rb".freeze, "lib/ollama/errors.rb".freeze, "lib/ollama/handlers.rb".freeze, "lib/ollama/handlers/collector.rb".freeze, "lib/ollama/handlers/concern.rb".freeze, "lib/ollama/handlers/dump_json.rb".freeze, "lib/ollama/handlers/dump_yaml.rb".freeze, "lib/ollama/handlers/markdown.rb".freeze, "lib/ollama/handlers/nop.rb".freeze, "lib/ollama/handlers/print.rb".freeze, "lib/ollama/handlers/progress.rb".freeze, "lib/ollama/handlers/say.rb".freeze, "lib/ollama/handlers/single.rb".freeze, "lib/ollama/image.rb".freeze, "lib/ollama/message.rb".freeze, "lib/ollama/options.rb".freeze, "lib/ollama/response.rb".freeze, "lib/ollama/tool.rb".freeze, "lib/ollama/tool/function.rb".freeze, "lib/ollama/tool/function/parameters.rb".freeze, "lib/ollama/tool/function/parameters/property.rb".freeze, "lib/ollama/utils/cache_fetcher.rb".freeze, "lib/ollama/utils/chooser.rb".freeze, "lib/ollama/utils/colorize_texts.rb".freeze, "lib/ollama/utils/fetcher.rb".freeze, "lib/ollama/utils/file_argument.rb".freeze, "lib/ollama/utils/math.rb".freeze, "lib/ollama/utils/tags.rb".freeze, "lib/ollama/version.rb".freeze, "ollama-ruby.gemspec".freeze, "spec/assets/embeddings.json".freeze, "spec/assets/kitten.jpg".freeze, "spec/assets/prompt.txt".freeze, "spec/ollama/client/doc_spec.rb".freeze, "spec/ollama/client_spec.rb".freeze, "spec/ollama/commands/chat_spec.rb".freeze, "spec/ollama/commands/copy_spec.rb".freeze, "spec/ollama/commands/create_spec.rb".freeze, "spec/ollama/commands/delete_spec.rb".freeze, "spec/ollama/commands/embed_spec.rb".freeze, "spec/ollama/commands/embeddings_spec.rb".freeze, "spec/ollama/commands/generate_spec.rb".freeze, "spec/ollama/commands/ps_spec.rb".freeze, "spec/ollama/commands/pull_spec.rb".freeze, "spec/ollama/commands/push_spec.rb".freeze, "spec/ollama/commands/show_spec.rb".freeze, "spec/ollama/commands/tags_spec.rb".freeze, "spec/ollama/documents/memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_backed_memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_cache_spec.rb".freeze, "spec/ollama/documents/splitters/character_spec.rb".freeze, "spec/ollama/documents/splitters/semantic_spec.rb".freeze, "spec/ollama/documents_spec.rb".freeze, "spec/ollama/handlers/collector_spec.rb".freeze, "spec/ollama/handlers/dump_json_spec.rb".freeze, "spec/ollama/handlers/dump_yaml_spec.rb".freeze, "spec/ollama/handlers/markdown_spec.rb".freeze, "spec/ollama/handlers/nop_spec.rb".freeze, "spec/ollama/handlers/print_spec.rb".freeze, "spec/ollama/handlers/progress_spec.rb".freeze, "spec/ollama/handlers/say_spec.rb".freeze, "spec/ollama/handlers/single_spec.rb".freeze, "spec/ollama/image_spec.rb".freeze, "spec/ollama/message_spec.rb".freeze, "spec/ollama/options_spec.rb".freeze, "spec/ollama/tool_spec.rb".freeze, "spec/ollama/utils/cache_fetcher_spec.rb".freeze, "spec/ollama/utils/colorize_texts_spec.rb".freeze, "spec/ollama/utils/fetcher_spec.rb".freeze, "spec/ollama/utils/file_argument_spec.rb".freeze, "spec/ollama/utils/tags_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tmp/.keep".freeze]
|
17
17
|
s.homepage = "https://github.com/flori/ollama-ruby".freeze
|
18
18
|
s.licenses = ["MIT".freeze]
|
19
19
|
s.rdoc_options = ["--title".freeze, "Ollama-ruby - Interacting with the Ollama API".freeze, "--main".freeze, "README.md".freeze]
|
20
20
|
s.required_ruby_version = Gem::Requirement.new("~> 3.1".freeze)
|
21
21
|
s.rubygems_version = "3.5.22".freeze
|
22
22
|
s.summary = "Interacting with the Ollama API".freeze
|
23
|
-
s.test_files = ["spec/ollama/client/doc_spec.rb".freeze, "spec/ollama/client_spec.rb".freeze, "spec/ollama/commands/chat_spec.rb".freeze, "spec/ollama/commands/copy_spec.rb".freeze, "spec/ollama/commands/create_spec.rb".freeze, "spec/ollama/commands/delete_spec.rb".freeze, "spec/ollama/commands/embed_spec.rb".freeze, "spec/ollama/commands/embeddings_spec.rb".freeze, "spec/ollama/commands/generate_spec.rb".freeze, "spec/ollama/commands/ps_spec.rb".freeze, "spec/ollama/commands/pull_spec.rb".freeze, "spec/ollama/commands/push_spec.rb".freeze, "spec/ollama/commands/show_spec.rb".freeze, "spec/ollama/commands/tags_spec.rb".freeze, "spec/ollama/documents/memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_backed_memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_cache_spec.rb".freeze, "spec/ollama/documents/splitters/character_spec.rb".freeze, "spec/ollama/documents/splitters/semantic_spec.rb".freeze, "spec/ollama/documents_spec.rb".freeze, "spec/ollama/handlers/collector_spec.rb".freeze, "spec/ollama/handlers/dump_json_spec.rb".freeze, "spec/ollama/handlers/dump_yaml_spec.rb".freeze, "spec/ollama/handlers/markdown_spec.rb".freeze, "spec/ollama/handlers/nop_spec.rb".freeze, "spec/ollama/handlers/print_spec.rb".freeze, "spec/ollama/handlers/progress_spec.rb".freeze, "spec/ollama/handlers/say_spec.rb".freeze, "spec/ollama/handlers/single_spec.rb".freeze, "spec/ollama/image_spec.rb".freeze, "spec/ollama/message_spec.rb".freeze, "spec/ollama/options_spec.rb".freeze, "spec/ollama/tool_spec.rb".freeze, "spec/ollama/utils/
|
23
|
+
s.test_files = ["spec/ollama/client/doc_spec.rb".freeze, "spec/ollama/client_spec.rb".freeze, "spec/ollama/commands/chat_spec.rb".freeze, "spec/ollama/commands/copy_spec.rb".freeze, "spec/ollama/commands/create_spec.rb".freeze, "spec/ollama/commands/delete_spec.rb".freeze, "spec/ollama/commands/embed_spec.rb".freeze, "spec/ollama/commands/embeddings_spec.rb".freeze, "spec/ollama/commands/generate_spec.rb".freeze, "spec/ollama/commands/ps_spec.rb".freeze, "spec/ollama/commands/pull_spec.rb".freeze, "spec/ollama/commands/push_spec.rb".freeze, "spec/ollama/commands/show_spec.rb".freeze, "spec/ollama/commands/tags_spec.rb".freeze, "spec/ollama/documents/memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_backed_memory_cache_spec.rb".freeze, "spec/ollama/documents/redis_cache_spec.rb".freeze, "spec/ollama/documents/splitters/character_spec.rb".freeze, "spec/ollama/documents/splitters/semantic_spec.rb".freeze, "spec/ollama/documents_spec.rb".freeze, "spec/ollama/handlers/collector_spec.rb".freeze, "spec/ollama/handlers/dump_json_spec.rb".freeze, "spec/ollama/handlers/dump_yaml_spec.rb".freeze, "spec/ollama/handlers/markdown_spec.rb".freeze, "spec/ollama/handlers/nop_spec.rb".freeze, "spec/ollama/handlers/print_spec.rb".freeze, "spec/ollama/handlers/progress_spec.rb".freeze, "spec/ollama/handlers/say_spec.rb".freeze, "spec/ollama/handlers/single_spec.rb".freeze, "spec/ollama/image_spec.rb".freeze, "spec/ollama/message_spec.rb".freeze, "spec/ollama/options_spec.rb".freeze, "spec/ollama/tool_spec.rb".freeze, "spec/ollama/utils/cache_fetcher_spec.rb".freeze, "spec/ollama/utils/colorize_texts_spec.rb".freeze, "spec/ollama/utils/fetcher_spec.rb".freeze, "spec/ollama/utils/file_argument_spec.rb".freeze, "spec/ollama/utils/tags_spec.rb".freeze, "spec/spec_helper.rb".freeze]
|
24
24
|
|
25
25
|
s.specification_version = 4
|
26
26
|
|
@@ -30,11 +30,9 @@ Gem::Specification.new do |s|
|
|
30
30
|
s.add_development_dependency(%q<webmock>.freeze, [">= 0".freeze])
|
31
31
|
s.add_development_dependency(%q<debug>.freeze, [">= 0".freeze])
|
32
32
|
s.add_development_dependency(%q<simplecov>.freeze, [">= 0".freeze])
|
33
|
-
s.add_runtime_dependency(%q<excon>.freeze, ["~> 0
|
33
|
+
s.add_runtime_dependency(%q<excon>.freeze, ["~> 1.0".freeze])
|
34
34
|
s.add_runtime_dependency(%q<infobar>.freeze, ["~> 0.8".freeze])
|
35
35
|
s.add_runtime_dependency(%q<term-ansicolor>.freeze, ["~> 1.11".freeze])
|
36
|
-
s.add_runtime_dependency(%q<kramdown-parser-gfm>.freeze, ["~> 1.1".freeze])
|
37
|
-
s.add_runtime_dependency(%q<terminal-table>.freeze, ["~> 3.0".freeze])
|
38
36
|
s.add_runtime_dependency(%q<redis>.freeze, ["~> 5.0".freeze])
|
39
37
|
s.add_runtime_dependency(%q<numo-narray>.freeze, ["~> 0.9".freeze])
|
40
38
|
s.add_runtime_dependency(%q<more_math>.freeze, ["~> 1.1".freeze])
|
@@ -48,4 +46,6 @@ Gem::Specification.new do |s|
|
|
48
46
|
s.add_runtime_dependency(%q<json>.freeze, ["~> 2.0".freeze])
|
49
47
|
s.add_runtime_dependency(%q<xdg>.freeze, ["~> 7.0".freeze])
|
50
48
|
s.add_runtime_dependency(%q<tins>.freeze, ["~> 1.34".freeze])
|
49
|
+
s.add_runtime_dependency(%q<kramdown-ansi>.freeze, ["~> 0.0".freeze, ">= 0.0.1".freeze])
|
50
|
+
s.add_runtime_dependency(%q<ostruct>.freeze, ["~> 0.0".freeze])
|
51
51
|
end
|
@@ -1,30 +1,93 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
RSpec.describe Ollama::Handlers::Say do
|
4
|
+
let :say do
|
5
|
+
described_class.new
|
6
|
+
end
|
7
|
+
|
4
8
|
it 'has .to_proc' do
|
5
9
|
expect_any_instance_of(described_class).to receive(:call).with(:foo)
|
6
10
|
described_class.call(:foo)
|
7
11
|
end
|
8
12
|
|
9
|
-
it 'can
|
10
|
-
|
13
|
+
it 'can be instantiated' do
|
14
|
+
expect(say).to be_a described_class
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'can be instantiated with a given voice' do
|
18
|
+
expect_any_instance_of(described_class).to receive(:command).
|
19
|
+
with(hash_including(voice: 'TheVoice')).and_return %w[ true ]
|
20
|
+
say = described_class.new(voice: 'TheVoice')
|
21
|
+
expect(say).to be_a described_class
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'command' do
|
25
|
+
it 'can be instantiated interactively' do
|
26
|
+
expect_any_instance_of(described_class).to receive(:command).
|
27
|
+
with(hash_including(interactive: true)).and_return %w[ true ]
|
28
|
+
say = described_class.new(interactive: true)
|
29
|
+
expect(say).to be_a described_class
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'can set the voice' do
|
33
|
+
expect(say.send(:command, voice: 'TheVoice', interactive: nil)).to eq(
|
34
|
+
%w[ say -v TheVoice ]
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'can be instantiated interactively with green' do
|
39
|
+
expect_any_instance_of(described_class).to receive(:command).
|
40
|
+
with(hash_including(interactive: 'green')).and_return %w[ true ]
|
41
|
+
say = described_class.new(interactive: 'green')
|
42
|
+
expect(say).to be_a described_class
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'can set interactive mode' do
|
46
|
+
expect(say.send(:command, voice: nil, interactive: true)).to eq(
|
47
|
+
%w[ say -i ]
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'can set interactive mode to green' do
|
52
|
+
expect(say.send(:command, voice: nil, interactive: 'green')).to eq(
|
53
|
+
%w[ say --interactive=green ]
|
54
|
+
)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'can say response' do
|
59
|
+
output = double('output', :sync= => true, closed?: false)
|
11
60
|
expect(output).to receive(:print).with('testing')
|
12
61
|
expect(output).to receive(:close)
|
13
|
-
|
62
|
+
say = described_class.new(output:)
|
14
63
|
response = double('response', response: 'testing', done: false)
|
15
|
-
|
64
|
+
say.call(response)
|
16
65
|
response = double('response', response: nil, message: nil, done: true)
|
17
|
-
|
66
|
+
say.call(response)
|
18
67
|
end
|
19
68
|
|
20
|
-
it 'can
|
21
|
-
output = double('output', :sync= => true)
|
69
|
+
it 'can say message content' do
|
70
|
+
output = double('output', :sync= => true, closed?: false)
|
22
71
|
expect(output).to receive(:print).with('testing')
|
23
72
|
expect(output).to receive(:close)
|
24
|
-
|
73
|
+
say = described_class.new(output:)
|
25
74
|
response = double('response', response: nil, message: double(content: 'testing'), done: false)
|
26
|
-
|
75
|
+
say.call(response)
|
76
|
+
response = double('response', response: nil, message: nil, done: true)
|
77
|
+
say.call(response)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'can reopen output if closed' do
|
81
|
+
output = double('output', :sync= => true, closed?: true)
|
82
|
+
reopened_output = double('output', :sync= => true, closed?: false, pid: 666)
|
83
|
+
expect(reopened_output).to receive(:print).with('testing')
|
84
|
+
expect(reopened_output).to receive(:close)
|
85
|
+
say = described_class.new(output:)
|
86
|
+
expect(say).to receive(:open_output).and_return(reopened_output)
|
87
|
+
response = double('response', response: 'testing', done: false)
|
88
|
+
say.call(response)
|
27
89
|
response = double('response', response: nil, message: nil, done: true)
|
28
|
-
|
90
|
+
say.call(response)
|
29
91
|
end
|
92
|
+
|
30
93
|
end
|
@@ -77,12 +77,12 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
77
77
|
stub_request(:get, url).
|
78
78
|
with(headers: fetcher.headers).
|
79
79
|
to_return(status: 500)
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
80
|
+
expect(STDERR).to receive(:puts).with(/cannot.*get.*#{url}/i)
|
81
|
+
fetcher.get(url) do |tmp|
|
82
|
+
expect(tmp).to be_a StringIO
|
83
|
+
expect(tmp.read).to eq ''
|
84
|
+
expect(tmp.content_type).to eq 'text/plain'
|
85
|
+
end
|
86
86
|
end
|
87
87
|
|
88
88
|
it 'can redirect' do
|
@@ -107,7 +107,7 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
107
107
|
|
108
108
|
it 'can .execute and fail' do
|
109
109
|
expect(IO).to receive(:popen).and_raise StandardError
|
110
|
-
|
110
|
+
expect(STDERR).to receive(:puts).with(/cannot.*execute.*foobar/i)
|
111
111
|
described_class.execute('foobar') do |file|
|
112
112
|
expect(file).to be_a StringIO
|
113
113
|
expect(file.read).to be_empty
|
@@ -115,23 +115,23 @@ RSpec.describe Ollama::Utils::Fetcher do
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
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
124
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
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
130
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
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
|
137
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.
|
4
|
+
version: 0.11.0
|
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-
|
11
|
+
date: 2024-11-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gem_hadar
|
@@ -100,14 +100,14 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0
|
103
|
+
version: '1.0'
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0
|
110
|
+
version: '1.0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: infobar
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,34 +136,6 @@ dependencies:
|
|
136
136
|
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '1.11'
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: kramdown-parser-gfm
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
142
|
-
requirements:
|
143
|
-
- - "~>"
|
144
|
-
- !ruby/object:Gem::Version
|
145
|
-
version: '1.1'
|
146
|
-
type: :runtime
|
147
|
-
prerelease: false
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
149
|
-
requirements:
|
150
|
-
- - "~>"
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: '1.1'
|
153
|
-
- !ruby/object:Gem::Dependency
|
154
|
-
name: terminal-table
|
155
|
-
requirement: !ruby/object:Gem::Requirement
|
156
|
-
requirements:
|
157
|
-
- - "~>"
|
158
|
-
- !ruby/object:Gem::Version
|
159
|
-
version: '3.0'
|
160
|
-
type: :runtime
|
161
|
-
prerelease: false
|
162
|
-
version_requirements: !ruby/object:Gem::Requirement
|
163
|
-
requirements:
|
164
|
-
- - "~>"
|
165
|
-
- !ruby/object:Gem::Version
|
166
|
-
version: '3.0'
|
167
139
|
- !ruby/object:Gem::Dependency
|
168
140
|
name: redis
|
169
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -352,6 +324,40 @@ dependencies:
|
|
352
324
|
- - "~>"
|
353
325
|
- !ruby/object:Gem::Version
|
354
326
|
version: '1.34'
|
327
|
+
- !ruby/object:Gem::Dependency
|
328
|
+
name: kramdown-ansi
|
329
|
+
requirement: !ruby/object:Gem::Requirement
|
330
|
+
requirements:
|
331
|
+
- - "~>"
|
332
|
+
- !ruby/object:Gem::Version
|
333
|
+
version: '0.0'
|
334
|
+
- - ">="
|
335
|
+
- !ruby/object:Gem::Version
|
336
|
+
version: 0.0.1
|
337
|
+
type: :runtime
|
338
|
+
prerelease: false
|
339
|
+
version_requirements: !ruby/object:Gem::Requirement
|
340
|
+
requirements:
|
341
|
+
- - "~>"
|
342
|
+
- !ruby/object:Gem::Version
|
343
|
+
version: '0.0'
|
344
|
+
- - ">="
|
345
|
+
- !ruby/object:Gem::Version
|
346
|
+
version: 0.0.1
|
347
|
+
- !ruby/object:Gem::Dependency
|
348
|
+
name: ostruct
|
349
|
+
requirement: !ruby/object:Gem::Requirement
|
350
|
+
requirements:
|
351
|
+
- - "~>"
|
352
|
+
- !ruby/object:Gem::Version
|
353
|
+
version: '0.0'
|
354
|
+
type: :runtime
|
355
|
+
prerelease: false
|
356
|
+
version_requirements: !ruby/object:Gem::Requirement
|
357
|
+
requirements:
|
358
|
+
- - "~>"
|
359
|
+
- !ruby/object:Gem::Version
|
360
|
+
version: '0.0'
|
355
361
|
description: Library that allows interacting with the Ollama API
|
356
362
|
email: flori@ping.de
|
357
363
|
executables:
|
@@ -406,7 +412,6 @@ extra_rdoc_files:
|
|
406
412
|
- lib/ollama/tool/function.rb
|
407
413
|
- lib/ollama/tool/function/parameters.rb
|
408
414
|
- lib/ollama/tool/function/parameters/property.rb
|
409
|
-
- lib/ollama/utils/ansi_markdown.rb
|
410
415
|
- lib/ollama/utils/cache_fetcher.rb
|
411
416
|
- lib/ollama/utils/chooser.rb
|
412
417
|
- lib/ollama/utils/colorize_texts.rb
|
@@ -414,7 +419,6 @@ extra_rdoc_files:
|
|
414
419
|
- lib/ollama/utils/file_argument.rb
|
415
420
|
- lib/ollama/utils/math.rb
|
416
421
|
- lib/ollama/utils/tags.rb
|
417
|
-
- lib/ollama/utils/width.rb
|
418
422
|
- lib/ollama/version.rb
|
419
423
|
files:
|
420
424
|
- ".envrc"
|
@@ -473,7 +477,6 @@ files:
|
|
473
477
|
- lib/ollama/tool/function.rb
|
474
478
|
- lib/ollama/tool/function/parameters.rb
|
475
479
|
- lib/ollama/tool/function/parameters/property.rb
|
476
|
-
- lib/ollama/utils/ansi_markdown.rb
|
477
480
|
- lib/ollama/utils/cache_fetcher.rb
|
478
481
|
- lib/ollama/utils/chooser.rb
|
479
482
|
- lib/ollama/utils/colorize_texts.rb
|
@@ -481,7 +484,6 @@ files:
|
|
481
484
|
- lib/ollama/utils/file_argument.rb
|
482
485
|
- lib/ollama/utils/math.rb
|
483
486
|
- lib/ollama/utils/tags.rb
|
484
|
-
- lib/ollama/utils/width.rb
|
485
487
|
- lib/ollama/version.rb
|
486
488
|
- ollama-ruby.gemspec
|
487
489
|
- spec/assets/embeddings.json
|
@@ -520,13 +522,11 @@ files:
|
|
520
522
|
- spec/ollama/message_spec.rb
|
521
523
|
- spec/ollama/options_spec.rb
|
522
524
|
- spec/ollama/tool_spec.rb
|
523
|
-
- spec/ollama/utils/ansi_markdown_spec.rb
|
524
525
|
- spec/ollama/utils/cache_fetcher_spec.rb
|
525
526
|
- spec/ollama/utils/colorize_texts_spec.rb
|
526
527
|
- spec/ollama/utils/fetcher_spec.rb
|
527
528
|
- spec/ollama/utils/file_argument_spec.rb
|
528
529
|
- spec/ollama/utils/tags_spec.rb
|
529
|
-
- spec/ollama/utils/width_spec.rb
|
530
530
|
- spec/spec_helper.rb
|
531
531
|
- tmp/.keep
|
532
532
|
homepage: https://github.com/flori/ollama-ruby
|
@@ -590,11 +590,9 @@ test_files:
|
|
590
590
|
- spec/ollama/message_spec.rb
|
591
591
|
- spec/ollama/options_spec.rb
|
592
592
|
- spec/ollama/tool_spec.rb
|
593
|
-
- spec/ollama/utils/ansi_markdown_spec.rb
|
594
593
|
- spec/ollama/utils/cache_fetcher_spec.rb
|
595
594
|
- spec/ollama/utils/colorize_texts_spec.rb
|
596
595
|
- spec/ollama/utils/fetcher_spec.rb
|
597
596
|
- spec/ollama/utils/file_argument_spec.rb
|
598
597
|
- spec/ollama/utils/tags_spec.rb
|
599
|
-
- spec/ollama/utils/width_spec.rb
|
600
598
|
- spec/spec_helper.rb
|
@@ -1,217 +0,0 @@
|
|
1
|
-
require 'kramdown'
|
2
|
-
require 'kramdown-parser-gfm'
|
3
|
-
require 'terminal-table'
|
4
|
-
|
5
|
-
class Ollama::Utils::ANSIMarkdown < Kramdown::Converter::Base
|
6
|
-
include Term::ANSIColor
|
7
|
-
include Ollama::Utils::Width
|
8
|
-
|
9
|
-
class ::Kramdown::Parser::Mygfm < ::Kramdown::Parser::GFM
|
10
|
-
def initialize(source, options)
|
11
|
-
options[:gfm_quirks] << :no_auto_typographic
|
12
|
-
super
|
13
|
-
@block_parsers -= %i[
|
14
|
-
definition_list block_html block_math
|
15
|
-
footnote_definition abbrev_definition
|
16
|
-
]
|
17
|
-
@span_parsers -= %i[ footnote_marker inline_math ]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.parse(source)
|
22
|
-
@doc = Kramdown::Document.new(
|
23
|
-
source, input: :mygfm, auto_ids: false, entity_output: :as_char
|
24
|
-
).to_ansi
|
25
|
-
end
|
26
|
-
|
27
|
-
def initialize(root, options)
|
28
|
-
super
|
29
|
-
end
|
30
|
-
|
31
|
-
def convert(el, opts = {})
|
32
|
-
send("convert_#{el.type}", el, opts)
|
33
|
-
end
|
34
|
-
|
35
|
-
def inner(el, opts, &block)
|
36
|
-
result = +''
|
37
|
-
options = opts.dup.merge(parent: el)
|
38
|
-
el.children.each_with_index do |inner_el, index|
|
39
|
-
options[:index] = index
|
40
|
-
options[:result] = result
|
41
|
-
begin
|
42
|
-
content = send("convert_#{inner_el.type}", inner_el, options)
|
43
|
-
result << (block&.(inner_el, index, content) || content)
|
44
|
-
rescue NameError => e
|
45
|
-
warning "Caught #{e.class} for #{inner_el.type}"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
result
|
49
|
-
end
|
50
|
-
|
51
|
-
def convert_root(el, opts)
|
52
|
-
inner(el, opts)
|
53
|
-
end
|
54
|
-
|
55
|
-
def convert_blank(_el, opts)
|
56
|
-
opts[:result] =~ /\n\n\Z|\A\Z/ ? "" : "\n"
|
57
|
-
end
|
58
|
-
|
59
|
-
def convert_text(el, _opts)
|
60
|
-
el.value
|
61
|
-
end
|
62
|
-
|
63
|
-
def convert_header(el, opts)
|
64
|
-
newline bold { underline { inner(el, opts) } }
|
65
|
-
end
|
66
|
-
|
67
|
-
def convert_p(el, opts)
|
68
|
-
length = width(percentage: 90) - opts[:list_indent].to_i
|
69
|
-
length < 0 and return ''
|
70
|
-
newline wrap(inner(el, opts), length:)
|
71
|
-
end
|
72
|
-
|
73
|
-
def convert_strong(el, opts)
|
74
|
-
bold { inner(el, opts) }
|
75
|
-
end
|
76
|
-
|
77
|
-
def convert_em(el, opts)
|
78
|
-
italic { inner(el, opts) }
|
79
|
-
end
|
80
|
-
|
81
|
-
def convert_a(el, opts)
|
82
|
-
url = el.attr['href']
|
83
|
-
hyperlink(url) { inner(el, opts) }
|
84
|
-
end
|
85
|
-
|
86
|
-
def convert_codespan(el, _opts)
|
87
|
-
blue { el.value }
|
88
|
-
end
|
89
|
-
|
90
|
-
def convert_codeblock(el, _opts)
|
91
|
-
blue { el.value }
|
92
|
-
end
|
93
|
-
|
94
|
-
def convert_blockquote(el, opts)
|
95
|
-
newline ?“ + inner(el, opts).sub(/\n+\z/, '') + ?”
|
96
|
-
end
|
97
|
-
|
98
|
-
def convert_hr(_el, _opts)
|
99
|
-
newline ?─ * width(percentage: 100)
|
100
|
-
end
|
101
|
-
|
102
|
-
def convert_img(el, _opts)
|
103
|
-
url = el.attr['src']
|
104
|
-
alt = el.attr['alt']
|
105
|
-
alt.strip.size == 0 and alt = url
|
106
|
-
alt = '🖼 ' + alt
|
107
|
-
hyperlink(url) { alt }
|
108
|
-
end
|
109
|
-
|
110
|
-
def convert_ul(el, opts)
|
111
|
-
list_indent = opts[:list_indent].to_i
|
112
|
-
inner(el, opts) { |_inner_el, index, content|
|
113
|
-
result = '· %s' % content
|
114
|
-
result = newline(result, count: index <= el.children.size - 1 ? 1 : 2)
|
115
|
-
result.gsub(/^/, ' ' * list_indent)
|
116
|
-
}
|
117
|
-
end
|
118
|
-
|
119
|
-
def convert_ol(el, opts)
|
120
|
-
list_indent = opts[:list_indent].to_i
|
121
|
-
inner(el, opts) { |_inner_el, index, content|
|
122
|
-
result = '%u. %s' % [ index + 1, content ]
|
123
|
-
result = newline(result, count: index <= el.children.size - 1 ? 1 : 2)
|
124
|
-
result.gsub(/^/, ' ' * list_indent)
|
125
|
-
}
|
126
|
-
end
|
127
|
-
|
128
|
-
def convert_li(el, opts)
|
129
|
-
opts = opts.dup
|
130
|
-
opts[:list_indent] = 2 + opts[:list_indent].to_i
|
131
|
-
newline inner(el, opts).sub(/\n+\Z/, '')
|
132
|
-
end
|
133
|
-
|
134
|
-
def convert_html_element(el, opts)
|
135
|
-
if el.value == 'i' || el.value == 'em'
|
136
|
-
italic { inner(el, opts) }
|
137
|
-
elsif el.value == 'b' || el.value == 'strong'
|
138
|
-
bold { inner(el, opts) }
|
139
|
-
else
|
140
|
-
''
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
def convert_table(el, opts)
|
145
|
-
table = Terminal::Table.new
|
146
|
-
table.style = {
|
147
|
-
all_separators: true,
|
148
|
-
border: :unicode_round,
|
149
|
-
}
|
150
|
-
opts[:table] = table
|
151
|
-
inner(el, opts)
|
152
|
-
el.options[:alignment].each_with_index do |a, i|
|
153
|
-
a == :default and next
|
154
|
-
opts[:table].align_column(i, a)
|
155
|
-
end
|
156
|
-
newline table.to_s
|
157
|
-
end
|
158
|
-
|
159
|
-
def convert_thead(el, opts)
|
160
|
-
rows = inner(el, opts)
|
161
|
-
rows = rows.split(/\s*\|\s*/)[1..].map(&:strip)
|
162
|
-
opts[:table].headings = rows
|
163
|
-
''
|
164
|
-
end
|
165
|
-
|
166
|
-
def convert_tbody(el, opts)
|
167
|
-
res = +''
|
168
|
-
res << inner(el, opts)
|
169
|
-
end
|
170
|
-
|
171
|
-
def convert_tfoot(el, opts)
|
172
|
-
''
|
173
|
-
end
|
174
|
-
|
175
|
-
def convert_tr(el, opts)
|
176
|
-
return '' if el.children.empty?
|
177
|
-
full_width = width(percentage: 90)
|
178
|
-
cols = el.children.map { |c| convert(c, opts).strip }
|
179
|
-
row_size = cols.sum(&:size)
|
180
|
-
return '' if row_size.zero?
|
181
|
-
opts[:table] << cols.map { |c|
|
182
|
-
length = (full_width * (c.size / row_size.to_f)).floor
|
183
|
-
wrap(c, length:)
|
184
|
-
}
|
185
|
-
''
|
186
|
-
end
|
187
|
-
|
188
|
-
def convert_td(el, opts)
|
189
|
-
inner(el, opts)
|
190
|
-
end
|
191
|
-
|
192
|
-
def convert_entity(el, _opts)
|
193
|
-
el.value.char
|
194
|
-
end
|
195
|
-
|
196
|
-
def convert_xml_comment(*)
|
197
|
-
''
|
198
|
-
end
|
199
|
-
|
200
|
-
def convert_xml_pi(*)
|
201
|
-
''
|
202
|
-
end
|
203
|
-
|
204
|
-
def convert_br(_el, opts)
|
205
|
-
''
|
206
|
-
end
|
207
|
-
|
208
|
-
def convert_smart_quote(el, _opts)
|
209
|
-
el.value.to_s =~ /[rl]dquo/ ? "\"" : "'"
|
210
|
-
end
|
211
|
-
|
212
|
-
def newline(text, count: 1)
|
213
|
-
text.gsub(/\n*\z/, ?\n * count)
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
Kramdown::Converter.const_set(:Ansi, Ollama::Utils::ANSIMarkdown)
|
data/lib/ollama/utils/width.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'tins/terminal'
|
2
|
-
|
3
|
-
module Ollama::Utils::Width
|
4
|
-
include Term::ANSIColor
|
5
|
-
extend Term::ANSIColor
|
6
|
-
|
7
|
-
module_function
|
8
|
-
|
9
|
-
def width(percentage: 100.0)
|
10
|
-
((Float(percentage) * Tins::Terminal.columns) / 100).floor
|
11
|
-
end
|
12
|
-
|
13
|
-
def wrap(text, percentage: nil, length: nil)
|
14
|
-
percentage.nil? ^ length.nil? or
|
15
|
-
raise ArgumentError, "either pass percentage or length argument"
|
16
|
-
percentage and length ||= width(percentage:)
|
17
|
-
text.gsub(/(?<!\n)\n(?!\n)/, ' ').lines.map do |line|
|
18
|
-
if length >= 1 && uncolor { line }.length > length
|
19
|
-
line.gsub(/(.{1,#{length}})(\s+|$)/, "\\1\n").strip
|
20
|
-
else
|
21
|
-
line.strip
|
22
|
-
end
|
23
|
-
end * ?\n
|
24
|
-
end
|
25
|
-
|
26
|
-
def truncate(text, percentage: nil, length: nil, ellipsis: ?…)
|
27
|
-
percentage.nil? ^ length.nil? or
|
28
|
-
raise ArgumentError, "either pass percentage or length argument"
|
29
|
-
percentage and length ||= width(percentage:)
|
30
|
-
ellipsis_length = ellipsis.size
|
31
|
-
if length < ellipsis_length
|
32
|
-
+''
|
33
|
-
elsif text.size >= length + ellipsis_length
|
34
|
-
text[0, length - ellipsis_length] + ellipsis
|
35
|
-
else
|
36
|
-
text
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Ollama::Utils::ANSIMarkdown do
|
4
|
-
let :source do
|
5
|
-
File.read(Pathname.new(__dir__) + '..' + '..' + '..' + 'README.md')
|
6
|
-
end
|
7
|
-
|
8
|
-
it 'can parse' do
|
9
|
-
File.open('tmp/README.ansi', ?w) do |output|
|
10
|
-
ansi = described_class.parse(source)
|
11
|
-
expect(ansi).to match("This is the end.")
|
12
|
-
output.puts ansi
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Ollama::Utils::Width do
|
4
|
-
before do
|
5
|
-
allow(Tins::Terminal).to receive(:columns).and_return 80
|
6
|
-
end
|
7
|
-
|
8
|
-
describe '.width' do
|
9
|
-
it 'defaults to 100%' do
|
10
|
-
expect(described_class.width).to eq 80
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'can be to 80%' do
|
14
|
-
expect(described_class.width(percentage: 80)).to eq 64
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
describe '.wrap' do
|
19
|
-
it 'can wrap with percentage' do
|
20
|
-
wrapped = described_class.wrap([ ?A * 10 ] * 10 * ' ', percentage: 80)
|
21
|
-
expect(wrapped).to eq(
|
22
|
-
"AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA\n"\
|
23
|
-
"AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA"
|
24
|
-
)
|
25
|
-
expect(wrapped.size).to eq 109
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'can wrap with length' do
|
29
|
-
wrapped = described_class.wrap([ ?A * 10 ] * 10 * ' ', length: 64)
|
30
|
-
expect(wrapped).to eq(
|
31
|
-
"AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA\n"\
|
32
|
-
"AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA"
|
33
|
-
)
|
34
|
-
expect(wrapped.size).to eq 109
|
35
|
-
end
|
36
|
-
|
37
|
-
it "doesn't wrap with length 0" do
|
38
|
-
wrapped = described_class.wrap([ ?A * 10 ] * 10 * ' ', length: 0)
|
39
|
-
expect(wrapped).to eq(
|
40
|
-
"AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA "\
|
41
|
-
"AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA"
|
42
|
-
)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
describe '.truncate' do
|
47
|
-
it 'can truncate with percentage' do
|
48
|
-
truncated = described_class.truncate([ ?A * 10 ] * 10 * ' ', percentage: 80)
|
49
|
-
expect(truncated).to eq(
|
50
|
-
"AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAA…"
|
51
|
-
)
|
52
|
-
expect(truncated.size).to eq 64
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'can truncate with length' do
|
56
|
-
truncated = described_class.truncate([ ?A * 10 ] * 10 * ' ', length: 64)
|
57
|
-
expect(truncated).to eq(
|
58
|
-
"AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAA…"
|
59
|
-
)
|
60
|
-
expect(truncated.size).to eq 64
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'cannot truncate if not necessary' do
|
64
|
-
text = [ ?A * 10 ] * 5 * ' '
|
65
|
-
truncated = described_class.truncate(text, length: 54)
|
66
|
-
expect(truncated).to eq text
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'can truncate with length 0' do
|
70
|
-
truncated = described_class.truncate([ ?A * 10 ] * 10 * ' ', length: 0)
|
71
|
-
expect(truncated).to be_empty
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'can truncate with ...' do
|
75
|
-
truncated = described_class.truncate([ ?A * 10 ] * 10 * ' ', length: 64, ellipsis: '...')
|
76
|
-
expect(truncated).to eq(
|
77
|
-
"AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAA..."
|
78
|
-
)
|
79
|
-
expect(truncated.size).to eq 64
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|