ollama_chat 0.0.56 → 0.0.58

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +46 -0
  3. data/Rakefile +2 -1
  4. data/docker-compose.yml +1 -1
  5. data/lib/ollama_chat/chat.rb +47 -20
  6. data/lib/ollama_chat/clipboard.rb +8 -7
  7. data/lib/ollama_chat/conversation.rb +2 -2
  8. data/lib/ollama_chat/dialog.rb +2 -41
  9. data/lib/ollama_chat/document_cache.rb +8 -7
  10. data/lib/ollama_chat/env_config.rb +9 -0
  11. data/lib/ollama_chat/follow_chat.rb +8 -8
  12. data/lib/ollama_chat/history.rb +1 -1
  13. data/lib/ollama_chat/information.rb +5 -7
  14. data/lib/ollama_chat/kramdown_ansi.rb +2 -2
  15. data/lib/ollama_chat/message_list.rb +7 -5
  16. data/lib/ollama_chat/message_output.rb +8 -5
  17. data/lib/ollama_chat/model_handling.rb +2 -4
  18. data/lib/ollama_chat/ollama_chat_config/default_config.yml +3 -2
  19. data/lib/ollama_chat/ollama_chat_config.rb +2 -2
  20. data/lib/ollama_chat/parsing.rb +6 -5
  21. data/lib/ollama_chat/server_socket.rb +4 -4
  22. data/lib/ollama_chat/source_fetching.rb +8 -7
  23. data/lib/ollama_chat/state_selectors.rb +146 -0
  24. data/lib/ollama_chat/switches.rb +7 -9
  25. data/lib/ollama_chat/think_control.rb +11 -39
  26. data/lib/ollama_chat/utils/fetcher.rb +1 -1
  27. data/lib/ollama_chat/version.rb +1 -1
  28. data/lib/ollama_chat/web_searching.rb +3 -3
  29. data/lib/ollama_chat.rb +1 -0
  30. data/ollama_chat.gemspec +6 -5
  31. data/spec/ollama_chat/chat_spec.rb +5 -9
  32. data/spec/ollama_chat/clipboard_spec.rb +1 -1
  33. data/spec/ollama_chat/information_spec.rb +1 -1
  34. data/spec/ollama_chat/input_content_spec.rb +1 -1
  35. data/spec/ollama_chat/message_editing_spec.rb +1 -1
  36. data/spec/ollama_chat/message_output_spec.rb +1 -1
  37. data/spec/ollama_chat/model_handling_spec.rb +1 -1
  38. data/spec/ollama_chat/parsing_spec.rb +6 -6
  39. data/spec/ollama_chat/source_fetching_spec.rb +1 -3
  40. data/spec/ollama_chat/state_selectors_spec.rb +193 -0
  41. data/spec/ollama_chat/think_control_spec.rb +41 -101
  42. data/spec/ollama_chat/web_searching_spec.rb +1 -1
  43. data/spec/spec_helper.rb +6 -2
  44. metadata +19 -1
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe OllamaChat::MessageOutput do
4
4
  let :chat do
5
- OllamaChat::Chat.new
5
+ OllamaChat::Chat.new argv: chat_default_config
6
6
  end
7
7
 
8
8
  connect_to_ollama_server
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe OllamaChat::ModelHandling do
4
4
  let :chat do
5
- OllamaChat::Chat.new
5
+ OllamaChat::Chat.new argv: chat_default_config
6
6
  end
7
7
 
8
8
  connect_to_ollama_server
@@ -3,8 +3,8 @@ require 'pathname'
3
3
 
4
4
  describe OllamaChat::Parsing do
5
5
  let :chat do
6
- OllamaChat::Chat.new.tap do |chat|
7
- chat.document_policy = 'importing'
6
+ OllamaChat::Chat.new(argv: chat_default_config).tap do |chat|
7
+ chat.document_policy.selected = 'importing'
8
8
  end
9
9
  end
10
10
 
@@ -233,14 +233,14 @@ describe OllamaChat::Parsing do
233
233
 
234
234
  context 'document_policy' do
235
235
  it 'can be ignoring' do
236
- chat.document_policy = 'ignoring'
236
+ chat.document_policy.selected = 'ignoring'
237
237
  c = "see #{Dir.pwd}/spec/assets/example.html"
238
238
  content, = chat.parse_content(c, [])
239
239
  expect(content).to eq(c)
240
240
  end
241
241
 
242
242
  it 'can be importing' do
243
- chat.document_policy = 'importing'
243
+ chat.document_policy.selected = 'importing'
244
244
  c = "see #{Dir.pwd}/spec/assets/example.html"
245
245
  content, = chat.parse_content(c, [])
246
246
  expect(content).to include(<<~EOT)
@@ -253,7 +253,7 @@ describe OllamaChat::Parsing do
253
253
  end
254
254
 
255
255
  it 'can be embedding' do
256
- chat.document_policy = 'embedding'
256
+ chat.document_policy.selected = 'embedding'
257
257
  c = "see #{Dir.pwd}/spec/assets/example.html"
258
258
  expect(chat).to receive(:embed_source).with(
259
259
  kind_of(IO),
@@ -264,7 +264,7 @@ describe OllamaChat::Parsing do
264
264
  end
265
265
 
266
266
  it 'can be summarizing' do
267
- chat.document_policy = 'summarizing'
267
+ chat.document_policy.selected = 'summarizing'
268
268
  c = "see #{Dir.pwd}/spec/assets/example.html"
269
269
  content, = chat.parse_content(c, [])
270
270
  expect(content).to start_with(<<~EOT)
@@ -2,9 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe OllamaChat::SourceFetching do
4
4
  let :chat do
5
- OllamaChat::Chat.new(
6
- argv: %w[ -f lib/ollama_chat/ollama_chat_config/default_config.yml ]
7
- )
5
+ OllamaChat::Chat.new(argv: chat_default_config)
8
6
  end
9
7
 
10
8
  connect_to_ollama_server
@@ -0,0 +1,193 @@
1
+ require 'spec_helper'
2
+
3
+ describe OllamaChat::StateSelectors::StateSelector do
4
+ let(:name) { 'Test Selector' }
5
+ let(:states) { %w[ enabled disabled low high ] }
6
+ let(:default) { 'enabled' }
7
+ let(:off) { %w[ disabled ] }
8
+
9
+ let(:selector) do
10
+ described_class.new(
11
+ name: name,
12
+ states: states,
13
+ default: default,
14
+ off: off
15
+ )
16
+ end
17
+
18
+ describe '#initialize' do
19
+ it 'creates a new StateSelector with provided parameters' do
20
+ expect(selector).to be_a described_class
21
+ end
22
+
23
+ it 'sets the name correctly' do
24
+ expect(selector.instance_variable_get(:@name)).to eq name
25
+ end
26
+
27
+ it 'sets the states correctly' do
28
+ expect(selector.instance_variable_get(:@states)).to eq Set.new(states)
29
+ end
30
+
31
+ it 'sets the default state' do
32
+ expect(selector.instance_variable_get(:@default)).to eq default
33
+ end
34
+
35
+ it 'sets the off states correctly' do
36
+ expect(selector.instance_variable_get(:@off)).to eq off
37
+ end
38
+
39
+ it 'sets the selected state to default' do
40
+ expect(selector.selected).to eq default
41
+ end
42
+
43
+ context 'with empty states' do
44
+ it 'raises ArgumentError when states are empty' do
45
+ expect {
46
+ described_class.new(name: 'Test', states: [])
47
+ }.to raise_error(ArgumentError, 'states cannot be empty')
48
+ end
49
+ end
50
+
51
+ context 'with invalid default' do
52
+ it 'raises ArgumentError when default is not in states' do
53
+ expect {
54
+ described_class.new(name: 'Test', states: %w[ a b ], default: 'c')
55
+ }.to raise_error(ArgumentError, 'default has to be one of a, b.')
56
+ end
57
+ end
58
+ end
59
+
60
+ describe '#selected' do
61
+ it 'returns the currently selected state' do
62
+ expect(selector.selected).to eq default
63
+ end
64
+ end
65
+
66
+ describe '#selected=' do
67
+ it 'sets the selected state to a valid value' do
68
+ selector.selected = 'low'
69
+ expect(selector.selected).to eq 'low'
70
+ end
71
+
72
+ it 'raises ArgumentError when setting invalid state' do
73
+ expect {
74
+ selector.selected = 'invalid'
75
+ }.to raise_error(ArgumentError, 'value has to be one of enabled, disabled, low, high.')
76
+ end
77
+ end
78
+
79
+ describe '#allow_empty?' do
80
+ it 'returns false by default' do
81
+ expect(selector.allow_empty?).to be false
82
+ end
83
+
84
+ context 'when allow_empty is true' do
85
+ let(:selector) do
86
+ described_class.new(
87
+ name: name,
88
+ states: states,
89
+ default: nil,
90
+ allow_empty: true
91
+ )
92
+ end
93
+
94
+ it 'returns true when allow_empty is set' do
95
+ expect(selector.allow_empty?).to be true
96
+ end
97
+ end
98
+ end
99
+
100
+ describe '#off?' do
101
+ it 'returns true when selected state is in off set' do
102
+ selector.selected = 'disabled'
103
+ expect(selector.off?).to be true
104
+ end
105
+
106
+ it 'returns false when selected state is not in off set' do
107
+ selector.selected = 'enabled'
108
+ expect(selector.off?).to be false
109
+ end
110
+ end
111
+
112
+ describe '#on?' do
113
+ it 'returns true when selected state is not in off set' do
114
+ selector.selected = 'enabled'
115
+ expect(selector.on?).to be true
116
+ end
117
+
118
+ it 'returns false when selected state is in off set' do
119
+ selector.selected = 'disabled'
120
+ expect(selector.on?).to be false
121
+ end
122
+ end
123
+
124
+ describe '#choose' do
125
+ it 'allows user to select a state from available options' do
126
+ # Mock the chooser to return a specific choice
127
+ expect(OllamaChat::Utils::Chooser).to receive(:choose).with(
128
+ %w[ enabled disabled low high [EXIT] ]
129
+ ).and_return('low')
130
+
131
+ selector.choose
132
+ expect(selector.selected).to eq 'low'
133
+ end
134
+
135
+ it 'exits when user selects [EXIT]' do
136
+ expect(OllamaChat::Utils::Chooser).to receive(:choose).and_return('[EXIT]')
137
+
138
+ selector.choose
139
+ expect(selector.selected).to eq default
140
+ end
141
+
142
+ it 'exits when user cancels selection' do
143
+ expect(OllamaChat::Utils::Chooser).to receive(:choose).and_return(nil)
144
+
145
+ selector.choose
146
+ expect(selector.selected).to eq default
147
+ end
148
+ end
149
+
150
+ describe '#show' do
151
+ it 'outputs the current state to stdout' do
152
+ expect(STDOUT).to receive(:puts).with(/Test Selector is .*?enabled.*?\./)
153
+ selector.show
154
+ end
155
+ end
156
+
157
+ describe '#to_s' do
158
+ it 'returns the string representation of the selected state' do
159
+ expect(selector.to_s).to eq default
160
+ end
161
+
162
+ it 'returns the string representation after changing state' do
163
+ selector.selected = 'low'
164
+ expect(selector.to_s).to eq 'low'
165
+ end
166
+ end
167
+
168
+ describe 'with allow_empty true' do
169
+ let(:selector) do
170
+ described_class.new(
171
+ name: 'Empty Selector',
172
+ states: %w[ a b c ],
173
+ default: nil,
174
+ allow_empty: true
175
+ )
176
+ end
177
+
178
+ it 'allows setting nil as selected state' do
179
+ selector.selected = nil
180
+ expect(selector.selected).to eq ""
181
+ end
182
+
183
+ it 'allows empty state when allow_empty is true' do
184
+ expect(selector.allow_empty?).to be true
185
+ end
186
+
187
+ it 'raises no error when setting invalid state' do
188
+ expect {
189
+ selector.selected = 'invalid'
190
+ }.not_to raise_error
191
+ end
192
+ end
193
+ end
@@ -2,153 +2,93 @@ require 'spec_helper'
2
2
 
3
3
  describe OllamaChat::ThinkControl do
4
4
  let :chat do
5
- OllamaChat::Chat.new(
6
- argv: %w[ -f lib/ollama_chat/ollama_chat_config/default_config.yml ]
7
- )
5
+ OllamaChat::Chat.new(argv: chat_default_config)
8
6
  end
9
7
 
10
8
  connect_to_ollama_server
11
9
 
12
10
  describe '#think' do
13
- it 'returns the current think mode state' do
11
+ it 'returns false when the think mode selector is off' do
12
+ chat.think_mode.selected = 'disabled'
14
13
  expect(chat.think).to be false
15
- chat.instance_variable_set(:@think, true)
14
+ end
15
+
16
+ it 'returns true when the think mode selector is enabled' do
17
+ chat.think_mode.selected = 'enabled'
16
18
  expect(chat.think).to be true
17
- chat.instance_variable_set(:@think, false)
18
- expect(chat.think).to be false
19
- chat.instance_variable_set(:@think, 'low')
19
+ end
20
+
21
+ it 'returns the selected value when it is not “enabled”' do
22
+ chat.think_mode.selected = 'low'
20
23
  expect(chat.think).to eq 'low'
21
24
  end
22
25
  end
23
26
 
24
27
  describe '#think?' do
25
- it 'returns true when think mode is enabled (boolean true)' do
26
- chat.instance_variable_set(:@think, true)
28
+ it 'returns true when the think mode selector is on' do
29
+ chat.think_mode.selected = 'enabled'
27
30
  expect(chat.think?).to be true
28
31
  end
29
32
 
30
- it 'returns true when think mode is enabled (string value)' do
31
- chat.instance_variable_set(:@think, 'high')
33
+ it 'returns true when the think mode selector is on but the value is a string' do
34
+ chat.think_mode.selected = 'high'
32
35
  expect(chat.think?).to be true
33
36
  end
34
37
 
35
- it 'returns false when think mode is disabled (boolean false)' do
36
- chat.instance_variable_set(:@think, false)
37
- expect(chat.think?).to be false
38
- end
39
-
40
- it 'returns false when think mode is nil' do
41
- chat.instance_variable_set(:@think, nil)
38
+ it 'returns false when the think mode selector is off' do
39
+ chat.think_mode.selected = 'disabled'
42
40
  expect(chat.think?).to be false
43
41
  end
44
42
  end
45
43
 
46
44
  describe '#think_mode' do
47
- it 'returns "enabled" when think is true' do
48
- chat.instance_variable_set(:@think, true)
49
- expect(chat.think_mode).to eq 'enabled'
45
+ it 'exposes a StateSelector instance' do
46
+ expect(chat.think_mode).to be_a OllamaChat::StateSelectors::StateSelector
50
47
  end
51
48
 
52
- it 'returns the think value when it is a string' do
53
- chat.instance_variable_set(:@think, 'medium')
54
- expect(chat.think_mode).to eq 'medium'
55
- end
56
-
57
- it 'returns "disabled" when think is false' do
58
- chat.instance_variable_set(:@think, false)
59
- expect(chat.think_mode).to eq 'disabled'
60
- end
61
-
62
- it 'returns "disabled" when think is nil' do
63
- chat.instance_variable_set(:@think, nil)
64
- expect(chat.think_mode).to eq 'disabled'
65
- end
66
- end
67
-
68
- describe '#think_show' do
69
- it 'displays the current think mode status' do
70
- chat.instance_variable_set(:@think, true)
71
- expect(STDOUT).to receive(:puts).with(/Think mode is \e\[1menabled\e\[0m\./)
72
- chat.think_show
73
- end
74
-
75
- it 'displays the think mode level when set to string' do
76
- chat.instance_variable_set(:@think, 'high')
77
- expect(STDOUT).to receive(:puts).with(/Think mode is \e\[1mhigh\e\[0m\./)
78
- chat.think_show
79
- end
80
-
81
- it 'displays "disabled" when think is false' do
82
- chat.instance_variable_set(:@think, false)
83
- expect(STDOUT).to receive(:puts).with(/Think mode is \e\[1mdisabled\e\[0m\./)
84
- chat.think_show
85
- end
86
-
87
- it 'displays "disabled" when think is nil' do
88
- chat.instance_variable_set(:@think, nil)
89
- expect(STDOUT).to receive(:puts).with(/Think mode is \e\[1mdisabled\e\[0m\./)
90
- chat.think_show
49
+ it 'has the correct default selection (disabled)' do
50
+ expect(chat.think_mode.selected).to eq 'disabled'
91
51
  end
92
52
  end
93
53
 
94
54
  describe '#think_loud?' do
95
- it 'returns false when think is disabled' do
96
- chat.instance_variable_set(:@think, false)
55
+ it 'returns false when the think mode selector is off' do
56
+ chat.think_mode.selected = 'disabled'
97
57
  expect(chat.think_loud?).to be false
98
58
  end
99
59
 
100
- it 'returns false when think_loud is off' do
101
- chat.instance_variable_set(:@think, true)
60
+ it 'returns false when the think_loud switch is off' do
61
+ chat.think_mode.selected = 'enabled'
102
62
  allow(chat).to receive(:think_loud).and_return(double(on?: false))
103
63
  expect(chat.think_loud?).to be false
104
64
  end
105
65
 
106
- it 'returns true when both think and think_loud are enabled' do
107
- chat.instance_variable_set(:@think, true)
66
+ it 'returns true when both the think mode selector and think_loud switch are on' do
67
+ chat.think_mode.selected = 'enabled'
108
68
  allow(chat).to receive(:think_loud).and_return(double(on?: true))
109
69
  expect(chat.think_loud?).to be true
110
70
  end
111
71
  end
112
72
 
113
- describe '#choose_think_mode' do
114
- it 'can select "off" mode' do
115
- expect(OllamaChat::Utils::Chooser).to receive(:choose).and_return('off')
116
- chat.choose_think_mode
117
- expect(chat.think).to be false
73
+ describe '#think_mode.show' do
74
+ it 'prints the current think mode in bold' do
75
+ chat.think_mode.selected = 'high'
76
+ expect(STDOUT).to receive(:puts).with(/Think mode is \e\[1mhigh\e\[0m/)
77
+ chat.think_mode.show
118
78
  end
119
79
 
120
- it 'can select "on" mode' do
121
- expect(OllamaChat::Utils::Chooser).to receive(:choose).and_return('on')
122
- chat.choose_think_mode
123
- expect(chat.think).to be true
80
+ it 'prints “disabled” when the selector is off' do
81
+ chat.think_mode.selected = 'disabled'
82
+ expect(STDOUT).to receive(:puts).with(/Think mode is \e\[1mdisabled\e\[0m/)
83
+ chat.think_mode.show
124
84
  end
85
+ end
125
86
 
126
- it 'can select "low" mode' do
87
+ describe '#think_mode.choose' do
88
+ it 'updates the selector based on the user choice' do
127
89
  expect(OllamaChat::Utils::Chooser).to receive(:choose).and_return('low')
128
- chat.choose_think_mode
129
- expect(chat.think).to eq 'low'
130
- end
131
-
132
- it 'can select "medium" mode' do
133
- expect(OllamaChat::Utils::Chooser).to receive(:choose).and_return('medium')
134
- chat.choose_think_mode
135
- expect(chat.think).to eq 'medium'
136
- end
137
-
138
- it 'can select "high" mode' do
139
- expect(OllamaChat::Utils::Chooser).to receive(:choose).and_return('high')
140
- chat.choose_think_mode
141
- expect(chat.think).to eq 'high'
142
- end
143
-
144
- it 'can exit selection' do
145
- expect(OllamaChat::Utils::Chooser).to receive(:choose).and_return('[EXIT]')
146
- expect { chat.choose_think_mode }.not_to change { chat.think }
147
- end
148
-
149
- it 'can handle nil selection' do
150
- expect(OllamaChat::Utils::Chooser).to receive(:choose).and_return(nil)
151
- expect { chat.choose_think_mode }.not_to change { chat.think }
90
+ chat.think_mode.choose
91
+ expect(chat.think_mode.selected).to eq 'low'
152
92
  end
153
93
  end
154
94
  end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe OllamaChat::WebSearching do
4
4
  let :chat do
5
- OllamaChat::Chat.new
5
+ OllamaChat::Chat.new(argv: chat_default_config)
6
6
  end
7
7
 
8
8
  connect_to_ollama_server
data/spec/spec_helper.rb CHANGED
@@ -58,7 +58,7 @@ module AssetHelpers
58
58
  # @yield [ io ] yields the IO object for the asset file to the provided block
59
59
  #
60
60
  # @return [ File, nil ] returns the IO object for the asset file, or nil if a
61
- # block is provided and the block does not return a value
61
+ # block is provided and the block does not return a value
62
62
  def asset_io(name, &block)
63
63
  io = File.new(File.join(__dir__, 'assets', name))
64
64
  if block
@@ -86,6 +86,10 @@ module AssetHelpers
86
86
  end
87
87
  end
88
88
 
89
+ def chat_default_config(a = [])
90
+ a + %w[ -f lib/ollama_chat/ollama_chat_config/default_config.yml ]
91
+ end
92
+
89
93
  # A module that provides functionality for stubbing Ollama server responses.
90
94
  #
91
95
  # The StubOllamaServer module enables developers to simulate Ollama API
@@ -126,7 +130,7 @@ module ProtectEnvVars
126
130
  # during test execution.
127
131
  #
128
132
  # @return [Proc] a lambda that wraps test execution with environment variable
129
- # preservation
133
+ # preservation
130
134
  def self.apply
131
135
  -> example do
132
136
  if example.metadata[:protect_env]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ollama_chat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.56
4
+ version: 0.0.58
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -121,6 +121,20 @@ dependencies:
121
121
  - - ">="
122
122
  - !ruby/object:Gem::Version
123
123
  version: '0'
124
+ - !ruby/object:Gem::Dependency
125
+ name: utils
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
124
138
  - !ruby/object:Gem::Dependency
125
139
  name: excon
126
140
  requirement: !ruby/object:Gem::Requirement
@@ -430,6 +444,7 @@ extra_rdoc_files:
430
444
  - lib/ollama_chat/redis_cache.rb
431
445
  - lib/ollama_chat/server_socket.rb
432
446
  - lib/ollama_chat/source_fetching.rb
447
+ - lib/ollama_chat/state_selectors.rb
433
448
  - lib/ollama_chat/switches.rb
434
449
  - lib/ollama_chat/think_control.rb
435
450
  - lib/ollama_chat/utils.rb
@@ -473,6 +488,7 @@ files:
473
488
  - lib/ollama_chat/redis_cache.rb
474
489
  - lib/ollama_chat/server_socket.rb
475
490
  - lib/ollama_chat/source_fetching.rb
491
+ - lib/ollama_chat/state_selectors.rb
476
492
  - lib/ollama_chat/switches.rb
477
493
  - lib/ollama_chat/think_control.rb
478
494
  - lib/ollama_chat/utils.rb
@@ -516,6 +532,7 @@ files:
516
532
  - spec/ollama_chat/redis_cache_spec.rb
517
533
  - spec/ollama_chat/server_socket_spec.rb
518
534
  - spec/ollama_chat/source_fetching_spec.rb
535
+ - spec/ollama_chat/state_selectors_spec.rb
519
536
  - spec/ollama_chat/switches_spec.rb
520
537
  - spec/ollama_chat/think_control_spec.rb
521
538
  - spec/ollama_chat/utils/cache_fetcher_spec.rb
@@ -566,6 +583,7 @@ test_files:
566
583
  - spec/ollama_chat/redis_cache_spec.rb
567
584
  - spec/ollama_chat/server_socket_spec.rb
568
585
  - spec/ollama_chat/source_fetching_spec.rb
586
+ - spec/ollama_chat/state_selectors_spec.rb
569
587
  - spec/ollama_chat/switches_spec.rb
570
588
  - spec/ollama_chat/think_control_spec.rb
571
589
  - spec/ollama_chat/utils/cache_fetcher_spec.rb