ollama-ruby 0.9.3 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|