ollama_chat 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.all_images.yml +17 -0
  3. data/.gitignore +9 -0
  4. data/Gemfile +5 -0
  5. data/README.md +159 -0
  6. data/Rakefile +58 -0
  7. data/VERSION +1 -0
  8. data/bin/ollama_chat +5 -0
  9. data/lib/ollama_chat/chat.rb +398 -0
  10. data/lib/ollama_chat/clipboard.rb +23 -0
  11. data/lib/ollama_chat/dialog.rb +94 -0
  12. data/lib/ollama_chat/document_cache.rb +16 -0
  13. data/lib/ollama_chat/follow_chat.rb +60 -0
  14. data/lib/ollama_chat/information.rb +113 -0
  15. data/lib/ollama_chat/message_list.rb +216 -0
  16. data/lib/ollama_chat/message_type.rb +5 -0
  17. data/lib/ollama_chat/model_handling.rb +29 -0
  18. data/lib/ollama_chat/ollama_chat_config.rb +103 -0
  19. data/lib/ollama_chat/parsing.rb +159 -0
  20. data/lib/ollama_chat/source_fetching.rb +173 -0
  21. data/lib/ollama_chat/switches.rb +119 -0
  22. data/lib/ollama_chat/utils/cache_fetcher.rb +38 -0
  23. data/lib/ollama_chat/utils/chooser.rb +53 -0
  24. data/lib/ollama_chat/utils/fetcher.rb +175 -0
  25. data/lib/ollama_chat/utils/file_argument.rb +34 -0
  26. data/lib/ollama_chat/utils.rb +7 -0
  27. data/lib/ollama_chat/version.rb +8 -0
  28. data/lib/ollama_chat.rb +20 -0
  29. data/ollama_chat.gemspec +50 -0
  30. data/spec/assets/api_show.json +63 -0
  31. data/spec/assets/api_tags.json +21 -0
  32. data/spec/assets/conversation.json +14 -0
  33. data/spec/assets/duckduckgo.html +757 -0
  34. data/spec/assets/example.atom +26 -0
  35. data/spec/assets/example.csv +5 -0
  36. data/spec/assets/example.html +10 -0
  37. data/spec/assets/example.pdf +139 -0
  38. data/spec/assets/example.ps +4 -0
  39. data/spec/assets/example.rb +1 -0
  40. data/spec/assets/example.rss +25 -0
  41. data/spec/assets/example.xml +7 -0
  42. data/spec/assets/kitten.jpg +0 -0
  43. data/spec/assets/prompt.txt +1 -0
  44. data/spec/ollama_chat/chat_spec.rb +105 -0
  45. data/spec/ollama_chat/clipboard_spec.rb +29 -0
  46. data/spec/ollama_chat/follow_chat_spec.rb +46 -0
  47. data/spec/ollama_chat/information_spec.rb +50 -0
  48. data/spec/ollama_chat/message_list_spec.rb +132 -0
  49. data/spec/ollama_chat/model_handling_spec.rb +35 -0
  50. data/spec/ollama_chat/parsing_spec.rb +240 -0
  51. data/spec/ollama_chat/source_fetching_spec.rb +54 -0
  52. data/spec/ollama_chat/switches_spec.rb +167 -0
  53. data/spec/ollama_chat/utils/cache_fetcher_spec.rb +43 -0
  54. data/spec/ollama_chat/utils/fetcher_spec.rb +137 -0
  55. data/spec/ollama_chat/utils/file_argument_spec.rb +17 -0
  56. data/spec/spec_helper.rb +46 -0
  57. data/tmp/.keep +0 -0
  58. metadata +476 -0
@@ -0,0 +1,240 @@
1
+ require 'spec_helper'
2
+ require 'pathname'
3
+
4
+ RSpec.describe OllamaChat::Parsing do
5
+ let :chat do
6
+ OllamaChat::Chat.new
7
+ end
8
+
9
+ before do
10
+ stub_request(:get, %r(/api/tags\z)).
11
+ to_return(status: 200, body: asset_json('api_tags.json'))
12
+ stub_request(:post, %r(/api/show\z)).
13
+ to_return(status: 200, body: asset_json('api_show.json'))
14
+ chat
15
+ end
16
+
17
+ describe '#parse_source' do
18
+ it 'can parse HTML' do
19
+ asset_io('example.html') do |io|
20
+ def io.content_type
21
+ 'text/html'
22
+ end
23
+ expect(chat.parse_source(io)).to eq(
24
+ "# My First Heading\n\nMy first paragraph.\n\n"
25
+ )
26
+ end
27
+ end
28
+
29
+ it 'can parse XML' do
30
+ asset_io('example.xml') do |io|
31
+ def io.content_type
32
+ 'text/xml'
33
+ end
34
+ expect(chat.parse_source(io)).to eq(asset_content('example.xml'))
35
+ end
36
+ end
37
+
38
+ it 'can parse CSV' do
39
+ asset_io('example.csv') do |io|
40
+ def io.content_type
41
+ 'text/csv'
42
+ end
43
+ expect(chat.parse_source(io)).to eq(<<EOT)
44
+ name: John Doe
45
+ age: 32
46
+ occupation: Software Engineer
47
+
48
+ name: Jane Smith
49
+ age: 28
50
+ occupation: Marketing Manager
51
+
52
+ name: Bob Johnson
53
+ age: 45
54
+ occupation: Retired
55
+
56
+ name: Alice Brown
57
+ age: 25
58
+ occupation: Student
59
+
60
+ EOT
61
+ end
62
+ end
63
+
64
+ it 'can parse RSS' do
65
+ asset_io('example.rss') do |io|
66
+ def io.content_type
67
+ 'application/rss+xml'
68
+ end
69
+ expect(chat.parse_source(io)).to start_with(<<~EOT)
70
+ # Example News Feed
71
+
72
+ ## [New Study Shows Benefits of Meditation](https://example.com/article/meditation-benefits)
73
+
74
+ EOT
75
+ end
76
+ end
77
+
78
+ it 'can parse RSS with content type XML' do
79
+ asset_io('example.rss') do |io|
80
+ def io.content_type
81
+ 'text/xml'
82
+ end
83
+ expect(chat.parse_source(io)).to start_with(<<~EOT)
84
+ # Example News Feed
85
+
86
+ ## [New Study Shows Benefits of Meditation](https://example.com/article/meditation-benefits)
87
+
88
+ EOT
89
+ end
90
+ end
91
+
92
+ it 'can parse Atom' do
93
+ asset_io('example.atom') do |io|
94
+ def io.content_type
95
+ 'application/atom+xml'
96
+ end
97
+ expect(chat.parse_source(io)).to start_with(<<~EOT)
98
+ # Example Feed
99
+
100
+ ## [New Study Shows Benefits of Meditation](https://example.com/article/meditation-benefits)
101
+
102
+ updated on 2024-01-01T12:00:00Z
103
+
104
+
105
+
106
+ ## [Local Business Opens New Location](https://example.com/article/local-business-new-location)
107
+
108
+ updated on 2024-01-02T10:00:00Z
109
+ EOT
110
+ end
111
+ end
112
+
113
+ it 'can parse Postscript' do
114
+ asset_io('example.ps') do |io|
115
+ def io.content_type
116
+ 'application/postscript'
117
+ end
118
+ expect(chat.parse_source(io)).to eq("Hello World!")
119
+ end
120
+ end
121
+
122
+ it 'can parse PDF' do
123
+ asset_io('example.pdf') do |io|
124
+ def io.content_type
125
+ 'application/pdf'
126
+ end
127
+ expect(chat.parse_source(io)).to eq("Hello World!")
128
+ end
129
+ end
130
+
131
+ it 'can parse other texts' do
132
+ asset_io('example.rb') do |io|
133
+ def io.content_type
134
+ 'application/x-ruby'
135
+ end
136
+ expect(chat.parse_source(io)).to eq(%{puts "Hello World!"\n})
137
+ end
138
+ end
139
+ end
140
+
141
+ describe '#parse_content' do
142
+ it 'can parse tags' do
143
+ content, tags = chat.parse_content("see #foobar …", [])
144
+ expect(content).to eq 'see #foobar …'
145
+ expect(tags).to include('foobar')
146
+ end
147
+
148
+ it 'can parse https URLs' do
149
+ stub_request(:get, "https://www.example.com/foo.html").
150
+ with(headers: { 'Host' => 'www.example.com' }).
151
+ to_return(
152
+ status: 200,
153
+ body: "",
154
+ headers: { 'Content-Type' => 'text/html' }
155
+ )
156
+ content, = chat.parse_content('https://www.example.com/foo.html', [])
157
+ expect(content).to include 'Imported "https://www.example.com/foo.html"'
158
+ end
159
+
160
+ it 'can parse file URLs' do
161
+ content, = chat.parse_content("see file://#{Dir.pwd}/spec/assets/example.html", [])
162
+ expect(content).to include(<<~EOT)
163
+ Imported "#{Pathname.pwd.join('spec/assets/example.html')}":
164
+
165
+ # My First Heading
166
+
167
+ My first paragraph.
168
+ EOT
169
+ end
170
+
171
+ it 'can parse file paths' do
172
+ content, = chat.parse_content("see #{Dir.pwd}/spec/assets/example.html", [])
173
+ expect(content).to include(<<~EOT)
174
+ Imported "#{Pathname.pwd.join('spec/assets/example.html')}":
175
+
176
+ # My First Heading
177
+
178
+ My first paragraph.
179
+ EOT
180
+ end
181
+
182
+ it 'can add images' do
183
+ images = []
184
+ expect(chat).to receive(:add_image).
185
+ with(images, kind_of(IO), %r(/spec/assets/kitten.jpg\z)).
186
+ and_call_original
187
+ chat.parse_content('./spec/assets/kitten.jpg', images)
188
+ expect(images.size).to eq 1
189
+ expect(images.first).to be_a Ollama::Image
190
+ end
191
+
192
+ context 'document_policy' do
193
+ it 'can be ignoring' do
194
+ chat.document_policy = 'ignoring'
195
+ c = "see #{Dir.pwd}/spec/assets/example.html"
196
+ content, = chat.parse_content(c, [])
197
+ expect(content).to eq(c)
198
+ end
199
+
200
+ it 'can be importing' do
201
+ chat.document_policy = 'importing'
202
+ c = "see #{Dir.pwd}/spec/assets/example.html"
203
+ content, = chat.parse_content(c, [])
204
+ expect(content).to include(<<~EOT)
205
+ Imported "#{Pathname.pwd.join('spec/assets/example.html')}":
206
+
207
+ # My First Heading
208
+
209
+ My first paragraph.
210
+ EOT
211
+ end
212
+
213
+ it 'can be embedding' do
214
+ chat.document_policy = 'embedding'
215
+ c = "see #{Dir.pwd}/spec/assets/example.html"
216
+ expect(chat).to receive(:embed_source).with(
217
+ kind_of(IO),
218
+ Pathname.pwd.join('spec/assets/example.html').to_s
219
+ )
220
+ content, = chat.parse_content(c, [])
221
+ end
222
+
223
+ it 'can be summarizing' do
224
+ chat.document_policy = 'summarizing'
225
+ c = "see #{Dir.pwd}/spec/assets/example.html"
226
+ content, = chat.parse_content(c, [])
227
+ expect(content).to start_with(<<~EOT)
228
+ see #{Pathname.pwd.join('spec/assets/example.html')}
229
+
230
+ Generate an abstract summary of the content in this document using
231
+ 100 words:
232
+
233
+ # My First Heading
234
+
235
+ My first paragraph.
236
+ EOT
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe OllamaChat::SourceFetching do
4
+ let :chat do
5
+ OllamaChat::Chat.new
6
+ end
7
+
8
+ before do
9
+ stub_request(:get, %r(/api/tags\z)).
10
+ to_return(status: 200, body: asset_json('api_tags.json'))
11
+ stub_request(:post, %r(/api/show\z)).
12
+ to_return(status: 200, body: asset_json('api_show.json'))
13
+ allow(chat).to receive(:location).and_return(double(on?: false))
14
+ end
15
+
16
+ it 'can import' do
17
+ expect(chat.import('./spec/assets/example.html')).to start_with(<<~EOT)
18
+ Imported "./spec/assets/example.html":
19
+
20
+ # My First Heading
21
+
22
+ My first paragraph.
23
+ EOT
24
+ end
25
+
26
+ it 'can summarize' do
27
+ expect(chat.summarize('./spec/assets/example.html')).to start_with(<<~EOT)
28
+ Generate an abstract summary of the content in this document using
29
+ 100 words:
30
+
31
+ # My First Heading
32
+
33
+ My first paragraph.
34
+ EOT
35
+ end
36
+
37
+ it 'can embed' do
38
+ expect(chat).to receive(:fetch_source).with(
39
+ './spec/assets/example.html'
40
+ )
41
+ expect(chat.embed('./spec/assets/example.html')).to eq(
42
+ 'This source was now embedded: ./spec/assets/example.html'
43
+ )
44
+ end
45
+
46
+ it 'can search web' do
47
+ stub_request(:get, "https://www.duckduckgo.com/html/?q=foo").
48
+ with(headers: { 'Host'=>'www.duckduckgo.com' }).
49
+ to_return(status: 200, body: asset_content('duckduckgo.html'), headers: {})
50
+ expect(chat.search_web('foo').first.to_s).to eq(
51
+ 'https://en.wikipedia.org/wiki/Foo_Fighters'
52
+ )
53
+ end
54
+ end
@@ -0,0 +1,167 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe OllamaChat::Switches do
4
+ describe OllamaChat::Switches::Switch do
5
+ let :switch do
6
+ described_class.new(
7
+ :test,
8
+ config: config,
9
+ msg: {
10
+ true => "Enabled.",
11
+ false => "Disabled.",
12
+ }
13
+ )
14
+ end
15
+
16
+ context 'default to false' do
17
+ let :config do
18
+ double(test?: false)
19
+ end
20
+
21
+
22
+ it 'can be switched on' do
23
+ expect {
24
+ switch.set(true)
25
+ }.to change {
26
+ switch.on? && !switch.off?
27
+ }.from(false).to(true)
28
+ end
29
+
30
+ it 'can be toggled on' do
31
+ expect(STDOUT).to receive(:puts).with('Enabled.')
32
+ expect {
33
+ switch.toggle
34
+ }.to change {
35
+ switch.on? && !switch.off?
36
+ }.from(false).to(true)
37
+ end
38
+ end
39
+
40
+ context 'default to false' do
41
+ let :config do
42
+ double(test?: true)
43
+ end
44
+
45
+ it 'can be switched on' do
46
+ expect {
47
+ switch.set(false)
48
+ }.to change {
49
+ switch.on? && !switch.off?
50
+ }.from(true).to(false)
51
+ end
52
+
53
+ it 'can be toggled off' do
54
+ expect(STDOUT).to receive(:puts).with('Disabled.')
55
+ expect {
56
+ switch.toggle
57
+ }.to change {
58
+ switch.on? && !switch.off?
59
+ }.from(true).to(false)
60
+ end
61
+ end
62
+ end
63
+
64
+ describe OllamaChat::Switches::CombinedSwitch do
65
+ describe 'off' do
66
+ let :config do
67
+ double(test1?: true, test2?: false)
68
+ end
69
+
70
+ let :switch1 do
71
+ OllamaChat::Switches::Switch.new(
72
+ :test1,
73
+ config: config,
74
+ msg: {
75
+ true => "Enabled.",
76
+ false => "Disabled.",
77
+ }
78
+ )
79
+ end
80
+
81
+ let :switch2 do
82
+ OllamaChat::Switches::Switch.new(
83
+ :test2,
84
+ config: config,
85
+ msg: {
86
+ true => "Enabled.",
87
+ false => "Disabled.",
88
+ }
89
+ )
90
+ end
91
+
92
+ let :switch do
93
+ described_class.new(
94
+ value: -> { switch1.on? && switch2.off? },
95
+ msg: {
96
+ true => "Enabled.",
97
+ false => "Disabled.",
98
+ }
99
+ )
100
+ end
101
+
102
+ it 'can be switched off 2' do
103
+ expect {
104
+ switch2.set(true)
105
+ }.to change {
106
+ switch.on? && !switch.off?
107
+ }.from(true).to(false)
108
+ end
109
+
110
+ it 'can be switched off 1' do
111
+ expect {
112
+ switch1.set(false)
113
+ }.to change {
114
+ switch.on? && !switch.off?
115
+ }.from(true).to(false)
116
+ end
117
+ end
118
+
119
+ describe 'on' do
120
+ let :config do
121
+ double(test1?: false, test2?: true)
122
+ end
123
+
124
+ let :switch1 do
125
+ OllamaChat::Switches::Switch.new(
126
+ :test1,
127
+ config: config,
128
+ msg: {
129
+ true => "Enabled.",
130
+ false => "Disabled.",
131
+ }
132
+ )
133
+ end
134
+
135
+ let :switch2 do
136
+ OllamaChat::Switches::Switch.new(
137
+ :test2,
138
+ config: config,
139
+ msg: {
140
+ true => "Enabled.",
141
+ false => "Disabled.",
142
+ }
143
+ )
144
+ end
145
+
146
+ let :switch do
147
+ described_class.new(
148
+ value: -> { switch1.on? && switch2.off? },
149
+ msg: {
150
+ true => "Enabled.",
151
+ false => "Disabled.",
152
+ }
153
+ )
154
+ end
155
+
156
+ it 'can be switched on' do
157
+ switch
158
+ expect {
159
+ switch1.set(true)
160
+ switch2.set(false)
161
+ }.to change {
162
+ switch.on? && !switch.off?
163
+ }.from(false).to(true)
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe OllamaChat::Utils::CacheFetcher do
4
+ let :url do
5
+ 'https://www.example.com/hello'
6
+ end
7
+
8
+ let :cache do
9
+ double('RedisCache')
10
+ end
11
+
12
+ let :fetcher do
13
+ described_class.new(cache).expose
14
+ end
15
+
16
+ it 'can be instantiated' do
17
+ expect(fetcher).to be_a described_class
18
+ end
19
+
20
+ it 'has #get' do
21
+ expect(cache).to receive(:[]).with('body-69ce405ab83f42dffa9fd22bbd47783f').and_return 'world'
22
+ expect(cache).to receive(:[]).with('content_type-69ce405ab83f42dffa9fd22bbd47783f').and_return 'text/plain'
23
+ yielded_io = nil
24
+ block = -> io { yielded_io = io }
25
+ fetcher.get(url, &block)
26
+ expect(yielded_io).to be_a StringIO
27
+ expect(yielded_io.read).to eq 'world'
28
+ end
29
+
30
+ it '#get needs block' do
31
+ expect { fetcher.get(url) }.to raise_error(ArgumentError)
32
+ end
33
+
34
+ it 'has #put' do
35
+ io = StringIO.new('world')
36
+ io.extend(OllamaChat::Utils::Fetcher::HeaderExtension)
37
+ io.content_type = MIME::Types['text/plain'].first
38
+ io.ex = 666
39
+ expect(cache).to receive(:set).with('body-69ce405ab83f42dffa9fd22bbd47783f', 'world', ex: 666)
40
+ expect(cache).to receive(:set).with('content_type-69ce405ab83f42dffa9fd22bbd47783f', 'text/plain', ex: 666)
41
+ fetcher.put(url, io)
42
+ end
43
+ end
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe OllamaChat::Utils::Fetcher do
4
+ let :url do
5
+ 'https://www.example.com/hello'
6
+ end
7
+
8
+ let :fetcher do
9
+ described_class.new.expose
10
+ end
11
+
12
+ it 'can be instantiated' do
13
+ expect(fetcher).to be_a described_class
14
+ end
15
+
16
+ it 'has .get' do
17
+ expect(described_class).to receive(:new).and_return double(get: true)
18
+ described_class.get(url)
19
+ end
20
+
21
+ it 'can #get with streaming' do
22
+ stub_request(:get, url).
23
+ with(headers: fetcher.headers).
24
+ to_return(
25
+ status: 200,
26
+ body: 'world',
27
+ headers: { 'Content-Type' => 'text/plain' },
28
+ )
29
+ fetcher.get(url) do |tmp|
30
+ expect(tmp).to be_a Tempfile
31
+ expect(tmp.read).to eq 'world'
32
+ expect(tmp.content_type).to eq 'text/plain'
33
+ end
34
+ end
35
+
36
+ it 'can #get without ssl peer verification' do
37
+ fetcher = described_class.new(
38
+ http_options: { ssl_verify_peer: false }
39
+ ).expose
40
+ stub_request(:get, url).
41
+ with(headers: fetcher.headers).
42
+ to_return(
43
+ status: 200,
44
+ body: 'world',
45
+ headers: { 'Content-Type' => 'text/plain' },
46
+ )
47
+ expect(Excon).to receive(:new).with(
48
+ url,
49
+ hash_including(ssl_verify_peer: false)
50
+ ).and_call_original
51
+ fetcher.get(url) do |tmp|
52
+ expect(tmp).to be_a Tempfile
53
+ expect(tmp.read).to eq 'world'
54
+ expect(tmp.content_type).to eq 'text/plain'
55
+ end
56
+ end
57
+
58
+ it 'can #get and fallback from streaming' do
59
+ stub_request(:get, url).
60
+ with(headers: fetcher.headers).
61
+ to_return(
62
+ { status: 501 },
63
+ {
64
+ status: 200,
65
+ body: 'world',
66
+ headers: { 'Content-Type' => 'text/plain' },
67
+ }
68
+ )
69
+ fetcher.get(url) do |tmp|
70
+ expect(tmp).to be_a Tempfile
71
+ expect(tmp.read).to eq 'world'
72
+ expect(tmp.content_type).to eq 'text/plain'
73
+ end
74
+ end
75
+
76
+ it 'can #get and finally fail' do
77
+ stub_request(:get, url).
78
+ with(headers: fetcher.headers).
79
+ to_return(status: 500)
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
+ end
87
+
88
+ it 'can redirect' do
89
+ expect(fetcher.middlewares).to include Excon::Middleware::RedirectFollower
90
+ end
91
+
92
+ it 'can .read' do
93
+ described_class.read(__FILE__) do |file|
94
+ expect(file).to be_a File
95
+ expect(file.read).to include 'can .read'
96
+ expect(file.content_type).to eq 'application/x-ruby'
97
+ end
98
+ end
99
+
100
+ it 'can .execute' do
101
+ described_class.execute('echo -n hello world') do |file|
102
+ expect(file).to be_a Tempfile
103
+ expect(file.read).to eq 'hello world'
104
+ expect(file.content_type).to eq 'text/plain'
105
+ end
106
+ end
107
+
108
+ it 'can .execute and fail' do
109
+ expect(IO).to receive(:popen).and_raise StandardError
110
+ expect(STDERR).to receive(:puts).with(/cannot.*execute.*foobar/i)
111
+ described_class.execute('foobar') do |file|
112
+ expect(file).to be_a StringIO
113
+ expect(file.read).to be_empty
114
+ expect(file.content_type).to eq 'text/plain'
115
+ end
116
+ end
117
+
118
+ describe '.normalize_url' do
119
+ it 'can handle umlauts' do
120
+ expect(described_class.normalize_url('https://foo.de/bär')).to eq(
121
+ 'https://foo.de/b%C3%A4r'
122
+ )
123
+ end
124
+
125
+ it 'can handle escaped umlauts' do
126
+ expect(described_class.normalize_url('https://foo.de/b%C3%A4r')).to eq(
127
+ 'https://foo.de/b%C3%A4r'
128
+ )
129
+ end
130
+
131
+ it 'can remove #anchors' do
132
+ expect(described_class.normalize_url('https://foo.de#bar')).to eq(
133
+ 'https://foo.de'
134
+ )
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe OllamaChat::Utils::FileArgument do
4
+ it 'it can return content' do
5
+ expect(described_class.get_file_argument('foo')).to eq 'foo'
6
+ end
7
+
8
+ it 'it can return content at path' do
9
+ expect(described_class.get_file_argument(asset('prompt.txt'))).to include\
10
+ 'test prompt'
11
+ end
12
+
13
+ it 'it can return default content' do
14
+ expect(described_class.get_file_argument('', default: 'foo')).to eq 'foo'
15
+ expect(described_class.get_file_argument(nil, default: 'foo')).to eq 'foo'
16
+ end
17
+ end
@@ -0,0 +1,46 @@
1
+ if ENV['START_SIMPLECOV'].to_i == 1
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter "#{File.basename(File.dirname(__FILE__))}/"
5
+ end
6
+ end
7
+ require 'rspec'
8
+ require 'tins/xt/expose'
9
+ begin
10
+ require 'debug'
11
+ rescue LoadError
12
+ end
13
+ require 'webmock/rspec'
14
+ WebMock.disable_net_connect!
15
+ require 'ollama_chat'
16
+
17
+ def asset(name)
18
+ File.join(__dir__, 'assets', name)
19
+ end
20
+
21
+ def asset_content(name)
22
+ File.read(File.join(__dir__, 'assets', name))
23
+ end
24
+
25
+ def asset_io(name, &block)
26
+ io = File.new(File.join(__dir__, 'assets', name))
27
+ if block
28
+ begin
29
+ block.call(io)
30
+ ensure
31
+ io.close
32
+ end
33
+ else
34
+ io
35
+ end
36
+ end
37
+
38
+ def asset_json(name)
39
+ JSON(JSON(File.read(asset(name))))
40
+ end
41
+
42
+ RSpec.configure do |config|
43
+ config.before(:suite) do
44
+ infobar.show = nil
45
+ end
46
+ end
data/tmp/.keep ADDED
File without changes